mirror of
http://10.0.2.1:3031/sauer/claude-code.git
synced 2026-06-30 21:46:58 +10:00
126 lines
18 KiB
TypeScript
126 lines
18 KiB
TypeScript
|
|
import { c as _c } from "react/compiler-runtime";
|
||
|
|
import chalk from 'chalk';
|
||
|
|
import figures from 'figures';
|
||
|
|
import React, { useEffect } from 'react';
|
||
|
|
import { getAdditionalDirectoriesForClaudeMd, setAdditionalDirectoriesForClaudeMd } from '../../bootstrap/state.js';
|
||
|
|
import type { LocalJSXCommandContext } from '../../commands.js';
|
||
|
|
import { MessageResponse } from '../../components/MessageResponse.js';
|
||
|
|
import { AddWorkspaceDirectory } from '../../components/permissions/rules/AddWorkspaceDirectory.js';
|
||
|
|
import { Box, Text } from '../../ink.js';
|
||
|
|
import type { LocalJSXCommandOnDone } from '../../types/command.js';
|
||
|
|
import { applyPermissionUpdate, persistPermissionUpdate } from '../../utils/permissions/PermissionUpdate.js';
|
||
|
|
import type { PermissionUpdateDestination } from '../../utils/permissions/PermissionUpdateSchema.js';
|
||
|
|
import { SandboxManager } from '../../utils/sandbox/sandbox-adapter.js';
|
||
|
|
import { addDirHelpMessage, validateDirectoryForWorkspace } from './validation.js';
|
||
|
|
function AddDirError(t0) {
|
||
|
|
const $ = _c(10);
|
||
|
|
const {
|
||
|
|
message,
|
||
|
|
args,
|
||
|
|
onDone
|
||
|
|
} = t0;
|
||
|
|
let t1;
|
||
|
|
let t2;
|
||
|
|
if ($[0] !== onDone) {
|
||
|
|
t1 = () => {
|
||
|
|
const timer = setTimeout(onDone, 0);
|
||
|
|
return () => clearTimeout(timer);
|
||
|
|
};
|
||
|
|
t2 = [onDone];
|
||
|
|
$[0] = onDone;
|
||
|
|
$[1] = t1;
|
||
|
|
$[2] = t2;
|
||
|
|
} else {
|
||
|
|
t1 = $[1];
|
||
|
|
t2 = $[2];
|
||
|
|
}
|
||
|
|
useEffect(t1, t2);
|
||
|
|
let t3;
|
||
|
|
if ($[3] !== args) {
|
||
|
|
t3 = <Text dimColor={true}>{figures.pointer} /add-dir {args}</Text>;
|
||
|
|
$[3] = args;
|
||
|
|
$[4] = t3;
|
||
|
|
} else {
|
||
|
|
t3 = $[4];
|
||
|
|
}
|
||
|
|
let t4;
|
||
|
|
if ($[5] !== message) {
|
||
|
|
t4 = <MessageResponse><Text>{message}</Text></MessageResponse>;
|
||
|
|
$[5] = message;
|
||
|
|
$[6] = t4;
|
||
|
|
} else {
|
||
|
|
t4 = $[6];
|
||
|
|
}
|
||
|
|
let t5;
|
||
|
|
if ($[7] !== t3 || $[8] !== t4) {
|
||
|
|
t5 = <Box flexDirection="column">{t3}{t4}</Box>;
|
||
|
|
$[7] = t3;
|
||
|
|
$[8] = t4;
|
||
|
|
$[9] = t5;
|
||
|
|
} else {
|
||
|
|
t5 = $[9];
|
||
|
|
}
|
||
|
|
return t5;
|
||
|
|
}
|
||
|
|
export async function call(onDone: LocalJSXCommandOnDone, context: LocalJSXCommandContext, args?: string): Promise<React.ReactNode> {
|
||
|
|
const directoryPath = (args ?? '').trim();
|
||
|
|
const appState = context.getAppState();
|
||
|
|
|
||
|
|
// Helper to handle adding a directory (shared by both with-path and no-path cases)
|
||
|
|
const handleAddDirectory = async (path: string, remember = false) => {
|
||
|
|
const destination: PermissionUpdateDestination = remember ? 'localSettings' : 'session';
|
||
|
|
const permissionUpdate = {
|
||
|
|
type: 'addDirectories' as const,
|
||
|
|
directories: [path],
|
||
|
|
destination
|
||
|
|
};
|
||
|
|
|
||
|
|
// Apply to session context
|
||
|
|
const latestAppState = context.getAppState();
|
||
|
|
const updatedContext = applyPermissionUpdate(latestAppState.toolPermissionContext, permissionUpdate);
|
||
|
|
context.setAppState(prev => ({
|
||
|
|
...prev,
|
||
|
|
toolPermissionContext: updatedContext
|
||
|
|
}));
|
||
|
|
|
||
|
|
// Update sandbox config so Bash commands can access the new directory.
|
||
|
|
// Bootstrap state is the source of truth for session-only dirs; persisted
|
||
|
|
// dirs are picked up via the settings subscription, but we refresh
|
||
|
|
// eagerly here to avoid a race when the user acts immediately.
|
||
|
|
const currentDirs = getAdditionalDirectoriesForClaudeMd();
|
||
|
|
if (!currentDirs.includes(path)) {
|
||
|
|
setAdditionalDirectoriesForClaudeMd([...currentDirs, path]);
|
||
|
|
}
|
||
|
|
SandboxManager.refreshConfig();
|
||
|
|
let message: string;
|
||
|
|
if (remember) {
|
||
|
|
try {
|
||
|
|
persistPermissionUpdate(permissionUpdate);
|
||
|
|
message = `Added ${chalk.bold(path)} as a working directory and saved to local settings`;
|
||
|
|
} catch (error) {
|
||
|
|
message = `Added ${chalk.bold(path)} as a working directory. Failed to save to local settings: ${error instanceof Error ? error.message : 'Unknown error'}`;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
message = `Added ${chalk.bold(path)} as a working directory for this session`;
|
||
|
|
}
|
||
|
|
const messageWithHint = `${message} ${chalk.dim('· /permissions to manage')}`;
|
||
|
|
onDone(messageWithHint);
|
||
|
|
};
|
||
|
|
|
||
|
|
// When no path is provided, show AddWorkspaceDirectory input form directly
|
||
|
|
// and return to REPL after confirmation
|
||
|
|
if (!directoryPath) {
|
||
|
|
return <AddWorkspaceDirectory permissionContext={appState.toolPermissionContext} onAddDirectory={handleAddDirectory} onCancel={() => {
|
||
|
|
onDone('Did not add a working directory.');
|
||
|
|
}} />;
|
||
|
|
}
|
||
|
|
const result = await validateDirectoryForWorkspace(directoryPath, appState.toolPermissionContext);
|
||
|
|
if (result.resultType !== 'success') {
|
||
|
|
const message = addDirHelpMessage(result);
|
||
|
|
return <AddDirError message={message} args={args ?? ''} onDone={() => onDone(message)} />;
|
||
|
|
}
|
||
|
|
return <AddWorkspaceDirectory directoryPath={result.absolutePath} permissionContext={appState.toolPermissionContext} onAddDirectory={handleAddDirectory} onCancel={() => {
|
||
|
|
onDone(`Did not add ${chalk.bold(result.absolutePath)} as a working directory.`);
|
||
|
|
}} />;
|
||
|
|
}
|
||
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjaGFsayIsImZpZ3VyZXMiLCJSZWFjdCIsInVzZUVmZmVjdCIsImdldEFkZGl0aW9uYWxEaXJlY3Rvcmllc0ZvckNsYXVkZU1kIiwic2V0QWRkaXRpb25hbERpcmVjdG9yaWVzRm9yQ2xhdWRlTWQiLCJMb2NhbEpTWENvbW1hbmRDb250ZXh0IiwiTWVzc2FnZVJlc3BvbnNlIiwiQWRkV29ya3NwYWNlRGlyZWN0b3J5IiwiQm94IiwiVGV4dCIsIkxvY2FsSlNYQ29tbWFuZE9uRG9uZSIsImFwcGx5UGVybWlzc2lvblVwZGF0ZSIsInBlcnNpc3RQZXJtaXNzaW9uVXBkYXRlIiwiUGVybWlzc2lvblVwZGF0ZURlc3RpbmF0aW9uIiwiU2FuZGJveE1hbmFnZXIiLCJhZGREaXJIZWxwTWVzc2FnZSIsInZhbGlkYXRlRGlyZWN0b3J5Rm9yV29ya3NwYWNlIiwiQWRkRGlyRXJyb3IiLCJ0MCIsIiQiLCJfYyIsIm1lc3NhZ2UiLCJhcmdzIiwib25Eb25lIiwidDEiLCJ0MiIsInRpbWVyIiwic2V0VGltZW91dCIsImNsZWFyVGltZW91dCIsInQzIiwicG9pbnRlciIsInQ0IiwidDUiLCJjYWxsIiwiY29udGV4dCIsIlByb21pc2UiLCJSZWFjdE5vZGUiLCJkaXJlY3RvcnlQYXRoIiwidHJpbSIsImFwcFN0YXRlIiwiZ2V0QXBwU3RhdGUiLCJoYW5kbGVBZGREaXJlY3RvcnkiLCJwYXRoIiwicmVtZW1iZXIiLCJkZXN0aW5hdGlvbiIsInBlcm1pc3Npb25VcGRhdGUiLCJ0eXBlIiwiY29uc3QiLCJkaXJlY3RvcmllcyIsImxhdGVzdEFwcFN0YXRlIiwidXBkYXRlZENvbnRleHQiLCJ0b29sUGVybWlzc2lvbkNvbnRleHQiLCJzZXRBcHBTdGF0ZSIsInByZXYiLCJjdXJyZW50RGlycyIsImluY2x1ZGVzIiwicmVmcmVzaENvbmZpZyIsImJvbGQiLCJlcnJvciIsIkVycm9yIiwibWVzc2FnZVdpdGhIaW50IiwiZGltIiwicmVzdWx0IiwicmVzdWx0VHlwZSIsImFic29sdXRlUGF0aCJdLCJzb3VyY2VzIjpbImFkZC1kaXIudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjaGFsayBmcm9tICdjaGFsaydcbmltcG9ydCBmaWd1cmVzIGZyb20gJ2ZpZ3VyZXMnXG5pbXBvcnQgUmVhY3QsIHsgdXNlRWZmZWN0IH0gZnJvbSAncmVhY3QnXG5pbXBvcnQge1xuICBnZXRBZGRpdGlvbmFsRGlyZWN0b3JpZXNGb3JDbGF1ZGVNZCxcbiAgc2V0QWRkaXRpb25hbERpcmVjdG9yaWVzRm9yQ2xhdWRlTWQsXG59IGZyb20gJy4uLy4uL2Jvb3RzdHJhcC9zdGF0ZS5qcydcbmltcG9ydCB0eXBlIHsgTG9jYWxKU1hDb21tYW5kQ29udGV4dCB9IGZyb20gJy4uLy4uL2NvbW1hbmRzLmpzJ1xuaW1wb3J0IHsgTWVzc2FnZVJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vY29tcG9uZW50cy9NZXNzYWdlUmVzcG9uc2UuanMnXG5pbXBvcnQgeyBBZGRXb3Jrc3BhY2VEaXJlY3RvcnkgfSBmcm9tICcuLi8uLi9jb21wb25lbnRzL3Blcm1pc3Npb25zL3J1bGVzL0FkZFdvcmtzcGFjZURpcmVjdG9yeS5qcydcbmltcG9ydCB7IEJveCwgVGV4dCB9IGZyb20gJy4uLy4uL2luay5qcydcbmltcG9ydCB0eXBlIHsgTG9jYWxKU1hDb21tYW5kT25Eb25lIH0gZnJvbSAnLi4vLi4vdHlwZXMvY29tbWFuZC5qcydcbmltcG9ydCB7XG4gIGFwcGx5UGVybWlzc2lvblVwZGF0ZSxcbiAgcGVyc2lzdFBlcm1pc3Npb25VcGRhdGUsXG59IGZyb20gJy4uLy4uL3V0aWxzL3Blcm1pc3Npb25zL1Blcm1pc3Npb25VcGRhdGUuanMnXG5pbXBvcnQgdHlwZSB7IFBlcm1pc3Npb25VcGRhdGVEZXN0aW5hdGlvbiB9IGZyb20gJy4uLy4uL3V0aWxzL3Blcm1pc3Npb25zL1Blcm1pc3Npb25VcGRhdGVTY2hlbWEuanMnXG5pbXBvcnQgeyBTYW5kYm94TWFuYWdlciB9IGZyb20gJy4uLy4uL3V0aWxzL3NhbmRib3gvc2FuZGJveC1hZGFwdGVyLmpzJ1xuaW1wb3J0IHtcbiAgYWRkRGlySGVscE1lc3NhZ2UsXG4gIHZhbGlkYXRlRGlyZWN0b3J5Rm9yV29ya3NwYWNlLFxufSBmcm9tICcuL3ZhbGlkYXRpb24uanMnXG5cbmZ1bmN0aW9uIEFkZERpckVycm9yKHtcbiAgbWVzc2FnZSxcbiAgYXJncyxcbiAgb25Eb25lLFxufToge1xuICBtZXNzYWdlOiBzdHJpbmdcbiAgYXJnczogc3RyaW5nXG4gIG9uRG9uZTogKCkgPT4gdm9pZFxufSk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgLy8gV2UgbmVlZCB0byBkZWZlciBjYWxsaW5nIG9uRG9uZSB0byBhdm9pZCB0aGUgXCJyZXR1cm4gbnVsbFwiIGJ1ZyB3aGVyZVxuICAgIC8vIHRoZSBjb21wb25lbnQgdW5tb3VudHMgYmVmb3JlIFJlYWN0IGNhbiByZW5kZXIgdGhlIGVycm9yIG1lc3NhZ2UuXG4gICAgLy8gVXNpbmcgc2V0VGltZW91dCBlbnN1cmVzIHRoZSBlcnJvciBkaXNwbGF5cyBiZWZvcmUgdGhlIGNvbW1hbmQgZXhpdHMuXG4gICAgY29uc3QgdGltZXIgPSBzZXRUaW1lb3V0KG9uRG9uZSwgMClcbiAgICByZXR1cm4gKCkgPT4gY2xlYXJUaW1lb3V0KHRpbWVyKVxuICB9LCBbb25Eb25lXSlcblxuICByZXR1cm4gKFxuICAgIDxCb3ggZmxleERpcmVjdGlvbj1cImNvbHVtblwiPlxuICAgICAgPFRleHQgZGltQ29sb3I+XG4gICAgICAgIHtmaWd1cmVzLnBvaW50ZXJ9IC9hZGQtZGlyIHthcmdzfVxuICAgICAgPC9UZXh0PlxuICAgICAgPE1lc3NhZ2VSZXNwb25zZT5cbiAgICAgICAgPFRleHQ+e21lc3NhZ2V9PC9UZXh0PlxuICAgICAgPC9NZXNzYWdlUmVzcG9uc2U+XG4gICAgPC9Cb3g+XG4gIClcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNhbGwoXG4gIG9uRG9uZTogTG9jYWxKU1hDb21tYW5kT25Eb25lLFxuICBjb250ZXh0OiBMb2NhbEpTWENvbW1hbmRDb250ZXh0LFxuICBhcmdzPzogc3RyaW5nLFxuKTogUHJvbWlzZTxSZWFjdC5SZWFjdE5vZGU+IHtcbiAgY29uc3QgZGlyZWN0b3J5UGF0aCA9IChhcmdzID8/ICcnKS50cmltKClcbiAgY29uc3QgYXBwU3RhdGUgPSBjb250ZXh0LmdldEFwcFN0YXRlKClcblxuICAvLyBIZWxwZXIgdG8gaGFuZGxlIGFkZGluZyBhIGRpcmVjdG9yeSAoc2hhcmVkIGJ5IGJvdGggd2l0aC1wYXRoIGFuZCBuby1wYXRoIGNhc2VzKVxuICBjb25zdCBoYW5kbGVBZGREaXJlY3RvcnkgPSBhc3luYyAocGF0aDogc3RyaW5nLCByZW1lbWJlciA9IGZ
|