praxis-agent 0.30.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/application/claude-project-purge.js +18 -5
- package/dist/application/project-memory.d.ts +141 -0
- package/dist/application/project-memory.js +607 -0
- package/dist/application/session-service.d.ts +24 -0
- package/dist/application/session-service.js +412 -44
- package/dist/application/subagent-service.js +6 -0
- package/dist/cli/interactive.d.ts +3 -1
- package/dist/cli/interactive.js +37 -4
- package/dist/cli/protocol.d.ts +1 -0
- package/dist/cli/protocol.js +24 -0
- package/dist/cli/tui/hook-settings.js +14 -1
- package/dist/cli/tui/memory-files.d.ts +2 -1
- package/dist/cli/tui/memory-files.js +30 -30
- package/dist/cli-runtime.d.ts +1 -0
- package/dist/cli-runtime.js +144 -24
- package/dist/compatibility/claude/context.d.ts +6 -1
- package/dist/compatibility/claude/context.js +16 -2
- package/dist/compatibility/claude/dynamic-context.js +2 -1
- package/dist/compatibility/claude/paths.js +2 -13
- package/dist/compatibility/claude/shared-resources.d.ts +4 -4
- package/dist/compatibility/claude/shared-resources.js +14 -35
- package/dist/core/context-budget.d.ts +9 -8
- package/dist/core/context-budget.js +16 -21
- package/dist/core/project-memory.d.ts +19 -0
- package/dist/core/project-memory.js +58 -0
- package/dist/core/runtime.d.ts +10 -1
- package/dist/core/runtime.js +47 -3
- package/dist/hooks/claude-file-change-watcher.d.ts +43 -0
- package/dist/hooks/claude-file-change-watcher.js +185 -0
- package/dist/hooks/claude-hook-tools.d.ts +2 -0
- package/dist/hooks/claude-hook-tools.js +45 -6
- package/dist/hooks/claude-hooks.d.ts +14 -2
- package/dist/hooks/claude-hooks.js +230 -5
- package/dist/hooks/claude-session-environment.d.ts +16 -0
- package/dist/hooks/claude-session-environment.js +112 -0
- package/dist/maintenance/doctor.js +29 -5
- package/dist/mcp/claude-mcp-management.js +2 -0
- package/dist/persistence/native-resources.d.ts +3 -1
- package/dist/persistence/native-resources.js +19 -6
- package/dist/platform/path-containment.d.ts +2 -0
- package/dist/platform/path-containment.js +7 -0
- package/dist/platform/project-identity.d.ts +6 -0
- package/dist/platform/project-identity.js +66 -0
- package/dist/platform/project-memory-paths.d.ts +13 -0
- package/dist/platform/project-memory-paths.js +28 -0
- package/dist/platform/project-path-key.d.ts +2 -0
- package/dist/platform/project-path-key.js +16 -0
- package/dist/providers/fallback-provider.js +3 -1
- package/dist/tools/claude-task-tools.d.ts +5 -0
- package/dist/tools/claude-task-tools.js +15 -1
- package/dist/tools/local-tools.d.ts +2 -0
- package/dist/tools/local-tools.js +11 -4
- package/package.json +1 -1
|
@@ -1318,6 +1318,11 @@ export class ClaudeSubagentExecutor {
|
|
|
1318
1318
|
hooks: scopedHooks,
|
|
1319
1319
|
session: hookSession,
|
|
1320
1320
|
recordOutcome: recordHookOutcome,
|
|
1321
|
+
...(this.options.eventSink
|
|
1322
|
+
? {
|
|
1323
|
+
warn: (message) => this.options.eventSink?.({ type: 'warning', message }),
|
|
1324
|
+
}
|
|
1325
|
+
: {}),
|
|
1321
1326
|
})
|
|
1322
1327
|
: agentTools;
|
|
1323
1328
|
const runtimePermissions = scopedHooks
|
|
@@ -1515,6 +1520,7 @@ export class ClaudeSubagentExecutor {
|
|
|
1515
1520
|
const configuredEffort = typeof customAgent?.effort === 'string' ? customAgent.effort : undefined;
|
|
1516
1521
|
const effectiveEffort = options.effort ?? configuredEffort;
|
|
1517
1522
|
const result = await runtime.run({
|
|
1523
|
+
sessionId: String(options.root.sessionId),
|
|
1518
1524
|
messages: await assembleMessages(),
|
|
1519
1525
|
collectMetrics: true,
|
|
1520
1526
|
reloadMessages: assembleMessages,
|
|
@@ -42,6 +42,7 @@ interface InteractiveSessionCommands {
|
|
|
42
42
|
rewindFiles?(sessionId: string, userMessageId: string): Promise<void>;
|
|
43
43
|
rewindPoints?(sessionId: string): Promise<RewindPoint[]>;
|
|
44
44
|
changeCwd?(sessionId: string | undefined, cwd: string): Promise<string>;
|
|
45
|
+
notify?(sessionId: string | undefined, message: string, notificationType: string, title?: string): void;
|
|
45
46
|
recordCdUsage?(sessionId: string): Promise<void>;
|
|
46
47
|
approveRecentlyDenied?(sessionId: string, display: string): Promise<void>;
|
|
47
48
|
retryRecentlyDenied?(sessionId: string, display: string, signal?: AbortSignal): Promise<SessionRunResult>;
|
|
@@ -189,11 +190,12 @@ interface InteractiveAppProps {
|
|
|
189
190
|
runtimeSettings?: PraxisRuntimeSettings;
|
|
190
191
|
runtimeSettingsTarget?: ConfigSettingsTarget;
|
|
191
192
|
notificationWriter?: TuiNotificationWriter;
|
|
193
|
+
notificationDelayMs?: number;
|
|
192
194
|
elicitationUrlOpener?: (url: string) => void | Promise<void>;
|
|
193
195
|
releaseNotesLoader?: (configRoot: string) => Promise<string>;
|
|
194
196
|
settingSources?: readonly ClaudeResourceScope[];
|
|
195
197
|
}
|
|
196
|
-
export declare function InteractiveApp({ dataPlane, configRoot: suppliedConfigRoot, statePath: suppliedStatePath, factory, initialSessions, initialPrompt, initialHistory, initialSessionColor, signal, onCancel, onTurnChange, onCleanup, onRendererChange, onBackground, axScreenReader, allowNewSession, resume, display, terminalWidth, slashCommands, agents, allowDangerouslySkipPermissions, additionalDirectories, diffLoader, doctorLoader, fileLoader, externalEditor, keybindingsConfigRoot, keybindingsFile, keybindingsLoader, keybindingsEditor, memoryFilesLoader, memoryEditor, memoryFolderOpener, suspendProcess, clipboardReader, clipboardWriter, sideQuestionClipboardWriter, exportWriter, permissionRuleStore, sandboxStore: suppliedSandboxStore, recentlyDeniedStore: suppliedRecentlyDeniedStore, terminalSetup: terminalSetupOverride, themeStore, initialThemeSettings, initialThemeLoadError, workspaceDirectoryResolver, workspaceDirectoryCompleter, runtimeSettings: suppliedRuntimeSettings, runtimeSettingsTarget, notificationWriter, elicitationUrlOpener, releaseNotesLoader, settingSources, }: InteractiveAppProps): import("react").JSX.Element;
|
|
198
|
+
export declare function InteractiveApp({ dataPlane, configRoot: suppliedConfigRoot, statePath: suppliedStatePath, factory, initialSessions, initialPrompt, initialHistory, initialSessionColor, signal, onCancel, onTurnChange, onCleanup, onRendererChange, onBackground, axScreenReader, allowNewSession, resume, display, terminalWidth, slashCommands, agents, allowDangerouslySkipPermissions, additionalDirectories, diffLoader, doctorLoader, fileLoader, externalEditor, keybindingsConfigRoot, keybindingsFile, keybindingsLoader, keybindingsEditor, memoryFilesLoader, memoryEditor, memoryFolderOpener, suspendProcess, clipboardReader, clipboardWriter, sideQuestionClipboardWriter, exportWriter, permissionRuleStore, sandboxStore: suppliedSandboxStore, recentlyDeniedStore: suppliedRecentlyDeniedStore, terminalSetup: terminalSetupOverride, themeStore, initialThemeSettings, initialThemeLoadError, workspaceDirectoryResolver, workspaceDirectoryCompleter, runtimeSettings: suppliedRuntimeSettings, runtimeSettingsTarget, notificationWriter, notificationDelayMs, elicitationUrlOpener, releaseNotesLoader, settingSources, }: InteractiveAppProps): import("react").JSX.Element;
|
|
197
199
|
export declare function runInteractive(options: {
|
|
198
200
|
dataPlane?: DataPlane;
|
|
199
201
|
configRoot?: string;
|
package/dist/cli/interactive.js
CHANGED
|
@@ -267,7 +267,7 @@ const HIDDEN_TUI_SLASH_COMMANDS = new Set([
|
|
|
267
267
|
'update',
|
|
268
268
|
'usage',
|
|
269
269
|
]);
|
|
270
|
-
export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: suppliedConfigRoot, statePath: suppliedStatePath, factory, initialSessions, initialPrompt, initialHistory = [], initialSessionColor, signal, onCancel, onTurnChange, onCleanup, onRendererChange, onBackground, axScreenReader = false, allowNewSession = true, resume, display = { version: 'dev', cwd: process.cwd() }, terminalWidth, slashCommands = EMPTY_SLASH_COMMANDS, agents = EMPTY_AGENTS, allowDangerouslySkipPermissions = false, additionalDirectories = [], diffLoader, doctorLoader, fileLoader, externalEditor = editTuiPrompt, keybindingsConfigRoot, keybindingsFile = ensureTuiKeybindingsFile, keybindingsLoader = loadTuiKeybindings, keybindingsEditor = openTuiEditorFile, memoryFilesLoader, memoryEditor = openTuiEditorFile, memoryFolderOpener = openTuiMemoryFolder, suspendProcess = suspendTuiProcess, clipboardReader = readTuiClipboard, clipboardWriter = writeTuiClipboard, sideQuestionClipboardWriter = writeTuiOsc52Clipboard, exportWriter = writeConversationExport, permissionRuleStore, sandboxStore: suppliedSandboxStore, recentlyDeniedStore: suppliedRecentlyDeniedStore, terminalSetup: terminalSetupOverride, themeStore, initialThemeSettings, initialThemeLoadError, workspaceDirectoryResolver = resolveTuiWorkspaceDirectory, workspaceDirectoryCompleter = completeTuiWorkspaceDirectory, runtimeSettings: suppliedRuntimeSettings, runtimeSettingsTarget, notificationWriter, elicitationUrlOpener = openTuiUrl, releaseNotesLoader = (configRoot) => loadClaudeReleaseNotes({ configRoot }), settingSources, }) {
|
|
270
|
+
export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: suppliedConfigRoot, statePath: suppliedStatePath, factory, initialSessions, initialPrompt, initialHistory = [], initialSessionColor, signal, onCancel, onTurnChange, onCleanup, onRendererChange, onBackground, axScreenReader = false, allowNewSession = true, resume, display = { version: 'dev', cwd: process.cwd() }, terminalWidth, slashCommands = EMPTY_SLASH_COMMANDS, agents = EMPTY_AGENTS, allowDangerouslySkipPermissions = false, additionalDirectories = [], diffLoader, doctorLoader, fileLoader, externalEditor = editTuiPrompt, keybindingsConfigRoot, keybindingsFile = ensureTuiKeybindingsFile, keybindingsLoader = loadTuiKeybindings, keybindingsEditor = openTuiEditorFile, memoryFilesLoader, memoryEditor = openTuiEditorFile, memoryFolderOpener = openTuiMemoryFolder, suspendProcess = suspendTuiProcess, clipboardReader = readTuiClipboard, clipboardWriter = writeTuiClipboard, sideQuestionClipboardWriter = writeTuiOsc52Clipboard, exportWriter = writeConversationExport, permissionRuleStore, sandboxStore: suppliedSandboxStore, recentlyDeniedStore: suppliedRecentlyDeniedStore, terminalSetup: terminalSetupOverride, themeStore, initialThemeSettings, initialThemeLoadError, workspaceDirectoryResolver = resolveTuiWorkspaceDirectory, workspaceDirectoryCompleter = completeTuiWorkspaceDirectory, runtimeSettings: suppliedRuntimeSettings, runtimeSettingsTarget, notificationWriter, notificationDelayMs = 6_000, elicitationUrlOpener = openTuiUrl, releaseNotesLoader = (configRoot) => loadClaudeReleaseNotes({ configRoot }), settingSources, }) {
|
|
271
271
|
const { exit, suspendTerminal, waitUntilRenderFlush } = useApp();
|
|
272
272
|
const width = useTerminalWidth(terminalWidth);
|
|
273
273
|
const rows = useTerminalRows();
|
|
@@ -449,6 +449,7 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
449
449
|
const [costUsd, setCostUsd] = useState();
|
|
450
450
|
const [contextWindowTokens, setContextWindowTokens] = useState(display.contextWindowTokens);
|
|
451
451
|
const [history, setHistory] = useState([...initialHistory]);
|
|
452
|
+
const activeAttemptThinkingItemsRef = useRef([]);
|
|
452
453
|
const [transcriptScrollOffset, setTranscriptScrollOffset] = useState(0);
|
|
453
454
|
// The pure TUI view model classifies the session identity (fresh/resumed/
|
|
454
455
|
// started) and projects the rendered transcript. Startup diagnostics are
|
|
@@ -1183,28 +1184,45 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
1183
1184
|
// Signatures authenticate a thinking block for provider replay; they are
|
|
1184
1185
|
// intentionally not part of the user-visible reasoning summary.
|
|
1185
1186
|
break;
|
|
1186
|
-
case 'thinking-stop':
|
|
1187
|
+
case 'thinking-stop': {
|
|
1187
1188
|
// append flushes pending thinking deltas before the retained boundary
|
|
1188
1189
|
// item, keeping streaming order correct; the effective thinking getter
|
|
1189
1190
|
// already includes any deltas not yet published.
|
|
1190
|
-
|
|
1191
|
+
const thinkingItem = {
|
|
1191
1192
|
kind: 'thinking',
|
|
1192
1193
|
text: event.block.type === 'thinking'
|
|
1193
1194
|
? redactSensitiveText(event.block.thinking, sensitiveValues)
|
|
1194
1195
|
: (streamingFrameRef.current?.thinking ?? ''),
|
|
1195
|
-
}
|
|
1196
|
+
};
|
|
1197
|
+
activeAttemptThinkingItemsRef.current.push(thinkingItem);
|
|
1198
|
+
append(thinkingItem);
|
|
1196
1199
|
streamingFrameRef.current?.resetThinking();
|
|
1197
1200
|
streamingFrameRef.current?.flush();
|
|
1198
1201
|
break;
|
|
1202
|
+
}
|
|
1199
1203
|
case 'user-message':
|
|
1200
1204
|
append({ kind: 'assistant', text: event.message });
|
|
1201
1205
|
break;
|
|
1202
1206
|
case 'state':
|
|
1207
|
+
if (event.state === 'awaiting-model') {
|
|
1208
|
+
activeAttemptThinkingItemsRef.current = [];
|
|
1209
|
+
}
|
|
1203
1210
|
setStatus(event.state);
|
|
1204
1211
|
break;
|
|
1205
1212
|
case 'usage':
|
|
1206
1213
|
setUsage(event.usage);
|
|
1207
1214
|
break;
|
|
1215
|
+
case 'model-attempt-discarded':
|
|
1216
|
+
streamingFrameRef.current?.resetText();
|
|
1217
|
+
streamingFrameRef.current?.resetThinking();
|
|
1218
|
+
streamingFrameRef.current?.flush();
|
|
1219
|
+
setUsage({ inputTokens: 0, outputTokens: 0 });
|
|
1220
|
+
if (activeAttemptThinkingItemsRef.current.length > 0) {
|
|
1221
|
+
const discarded = new Set(activeAttemptThinkingItemsRef.current);
|
|
1222
|
+
setHistory((current) => current.filter((item) => !discarded.has(item)));
|
|
1223
|
+
activeAttemptThinkingItemsRef.current = [];
|
|
1224
|
+
}
|
|
1225
|
+
break;
|
|
1208
1226
|
case 'tool-call':
|
|
1209
1227
|
if (['Edit', 'Write', 'NotebookEdit'].includes(event.call.name))
|
|
1210
1228
|
turnMutatedFilesRef.current = true;
|
|
@@ -1301,6 +1319,7 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
1301
1319
|
kind: 'notice',
|
|
1302
1320
|
text: `MCP elicitation completed · ${event.mcpServerName}`,
|
|
1303
1321
|
});
|
|
1322
|
+
serviceRef.current?.notify?.(sessionIdRef.current ?? undefined, `MCP elicitation completed · ${event.mcpServerName}`, 'elicitation_complete', 'Praxis');
|
|
1304
1323
|
if (elicitationUrlWaitingRef.current?.request.serverName ===
|
|
1305
1324
|
event.mcpServerName &&
|
|
1306
1325
|
elicitationUrlWaitingRef.current.request.elicitationId ===
|
|
@@ -1346,6 +1365,11 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
1346
1365
|
: null;
|
|
1347
1366
|
const editableRule = projected?.options.find((option) => option.editableRule)?.editableRule;
|
|
1348
1367
|
let settled = false;
|
|
1368
|
+
const notificationTimer = setTimeout(() => {
|
|
1369
|
+
if (settled)
|
|
1370
|
+
return;
|
|
1371
|
+
serviceRef.current?.notify?.(sessionIdRef.current ?? undefined, `Approval required for ${call.name}`, 'permission_prompt', 'Praxis');
|
|
1372
|
+
}, notificationDelayMs);
|
|
1349
1373
|
const pending = {
|
|
1350
1374
|
kind,
|
|
1351
1375
|
call,
|
|
@@ -1354,6 +1378,7 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
1354
1378
|
if (settled)
|
|
1355
1379
|
return;
|
|
1356
1380
|
settled = true;
|
|
1381
|
+
clearTimeout(notificationTimer);
|
|
1357
1382
|
if (permissionRef.current === pending)
|
|
1358
1383
|
permissionRef.current = null;
|
|
1359
1384
|
setPermission((current) => (current === pending ? null : current));
|
|
@@ -1370,12 +1395,20 @@ export function InteractiveApp({ dataPlane = resolveDataPlane(), configRoot: sup
|
|
|
1370
1395
|
const approveTool = (call, _originalCall, decision) => requestApproval(call, 'tool', decision);
|
|
1371
1396
|
const requestElicitation = (request) => new Promise((resolveResult) => {
|
|
1372
1397
|
let settled = false;
|
|
1398
|
+
const notificationTimer = setTimeout(() => {
|
|
1399
|
+
if (settled)
|
|
1400
|
+
return;
|
|
1401
|
+
serviceRef.current?.notify?.(sessionIdRef.current ?? undefined, 'Praxis needs your input', request.mode === 'url'
|
|
1402
|
+
? 'elicitation_url_dialog'
|
|
1403
|
+
: 'elicitation_dialog', 'Praxis');
|
|
1404
|
+
}, notificationDelayMs);
|
|
1373
1405
|
const pending = {
|
|
1374
1406
|
request,
|
|
1375
1407
|
resolve: (result, options) => {
|
|
1376
1408
|
if (settled)
|
|
1377
1409
|
return;
|
|
1378
1410
|
settled = true;
|
|
1411
|
+
clearTimeout(notificationTimer);
|
|
1379
1412
|
if (elicitationRef.current === pending)
|
|
1380
1413
|
elicitationRef.current = null;
|
|
1381
1414
|
if (!options?.keepUrlDialog) {
|
package/dist/cli/protocol.d.ts
CHANGED
package/dist/cli/protocol.js
CHANGED
|
@@ -1753,6 +1753,10 @@ export class StreamJsonOutput {
|
|
|
1753
1753
|
this.modelTurns = 0;
|
|
1754
1754
|
}
|
|
1755
1755
|
onEvent(event) {
|
|
1756
|
+
if (event.type === 'model-attempt-discarded') {
|
|
1757
|
+
this.discardTurn(event.reason);
|
|
1758
|
+
return;
|
|
1759
|
+
}
|
|
1756
1760
|
if (event.type === 'state') {
|
|
1757
1761
|
if (this.compacting && event.state !== 'compacting') {
|
|
1758
1762
|
this.compacting = false;
|
|
@@ -2109,6 +2113,26 @@ export class StreamJsonOutput {
|
|
|
2109
2113
|
if (!this.turnActive)
|
|
2110
2114
|
this.startTurn();
|
|
2111
2115
|
}
|
|
2116
|
+
discardTurn(reason) {
|
|
2117
|
+
this.write({
|
|
2118
|
+
type: 'system',
|
|
2119
|
+
subtype: 'model_attempt_discarded',
|
|
2120
|
+
reason,
|
|
2121
|
+
uuid: randomUUID(),
|
|
2122
|
+
session_id: this.sessionId,
|
|
2123
|
+
});
|
|
2124
|
+
this.turnText = '';
|
|
2125
|
+
this.turnThinking = [];
|
|
2126
|
+
this.turnCalls = [];
|
|
2127
|
+
this.turnUsage = emptyUsage();
|
|
2128
|
+
this.turnTerminalReason = undefined;
|
|
2129
|
+
this.turnActive = false;
|
|
2130
|
+
this.assistantFlushed = true;
|
|
2131
|
+
this.contentStarted = false;
|
|
2132
|
+
this.textContentIndex = undefined;
|
|
2133
|
+
this.activeThinkingIndex = undefined;
|
|
2134
|
+
this.nextContentIndex = 0;
|
|
2135
|
+
}
|
|
2112
2136
|
startTurn() {
|
|
2113
2137
|
if (this.turnActive)
|
|
2114
2138
|
this.finishTurn();
|
|
@@ -110,7 +110,20 @@ const TUI_HOOK_EVENT_DEFINITIONS = [
|
|
|
110
110
|
detail: [],
|
|
111
111
|
},
|
|
112
112
|
];
|
|
113
|
-
|
|
113
|
+
const OBSERVED_TUI_EVENTS_2_1_208 = new Set([
|
|
114
|
+
'PreToolUse',
|
|
115
|
+
'PostToolUse',
|
|
116
|
+
'PostToolUseFailure',
|
|
117
|
+
'UserPromptSubmit',
|
|
118
|
+
'SessionStart',
|
|
119
|
+
'Stop',
|
|
120
|
+
'SubagentStart',
|
|
121
|
+
'SubagentStop',
|
|
122
|
+
'SessionEnd',
|
|
123
|
+
'PermissionRequest',
|
|
124
|
+
]);
|
|
125
|
+
export const TUI_HOOK_EVENTS = TUI_HOOK_EVENT_DEFINITIONS.filter((definition) => OBSERVED_TUI_EVENTS_2_1_208.has(definition.name) &&
|
|
126
|
+
HOOK_EVENTS.includes(definition.name));
|
|
114
127
|
function isRecord(value) {
|
|
115
128
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
116
129
|
}
|
|
@@ -18,9 +18,10 @@ export interface LoadTuiMemoryFilesOptions {
|
|
|
18
18
|
cwd: string;
|
|
19
19
|
homeDirectory?: string;
|
|
20
20
|
dataPlane?: DataPlane;
|
|
21
|
+
environment?: Readonly<Record<string, string | undefined>>;
|
|
21
22
|
}
|
|
22
23
|
export declare function displayTuiMemoryPath(path: string, cwd: string, homeDirectory?: string): string;
|
|
23
|
-
export declare function loadTuiMemoryFiles({ configRoot, cwd, homeDirectory, dataPlane, }: LoadTuiMemoryFilesOptions): Promise<TuiMemoryFiles>;
|
|
24
|
+
export declare function loadTuiMemoryFiles({ configRoot, cwd, homeDirectory, dataPlane, environment, }: LoadTuiMemoryFilesOptions): Promise<TuiMemoryFiles>;
|
|
24
25
|
type TuiMemoryFolderLauncher = (command: string, args: readonly string[]) => Promise<void>;
|
|
25
26
|
export declare function openTuiMemoryFolder(path: string, launcher?: TuiMemoryFolderLauncher): Promise<void>;
|
|
26
27
|
export {};
|
|
@@ -2,9 +2,10 @@ import { spawn } from 'node:child_process';
|
|
|
2
2
|
import { mkdir, realpath } from 'node:fs/promises';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { basename, isAbsolute, relative, resolve } from 'node:path';
|
|
5
|
-
import { loadClaudeContextResources, loadClaudeSettings,
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { loadClaudeContextResources, loadClaudeSettings, } from '../../compatibility/claude/shared-resources.js';
|
|
6
|
+
import { resolveProjectMemoryPolicy } from '../../core/project-memory.js';
|
|
7
|
+
import { resolveProjectMemoryDirectory } from '../../platform/project-memory-paths.js';
|
|
8
|
+
import { loadNativeContextResources, loadNativeSettings, } from '../../persistence/native-resources.js';
|
|
8
9
|
function isWithin(root, path) {
|
|
9
10
|
const value = relative(root, path);
|
|
10
11
|
return value === '' || (!value.startsWith('..') && !isAbsolute(value));
|
|
@@ -41,40 +42,39 @@ function importedEntries(resource, instructions, cwd, homeDirectory, sourceDispl
|
|
|
41
42
|
imported: true,
|
|
42
43
|
}));
|
|
43
44
|
}
|
|
44
|
-
function
|
|
45
|
-
let enabled = true;
|
|
46
|
-
for (const resource of settings) {
|
|
47
|
-
if (typeof resource.value === 'object' &&
|
|
48
|
-
resource.value !== null &&
|
|
49
|
-
!Array.isArray(resource.value)) {
|
|
50
|
-
const value = resource.value
|
|
51
|
-
.autoMemoryEnabled;
|
|
52
|
-
if (typeof value === 'boolean')
|
|
53
|
-
enabled = value;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return enabled;
|
|
57
|
-
}
|
|
58
|
-
export async function loadTuiMemoryFiles({ configRoot, cwd, homeDirectory = homedir(), dataPlane = 'claude', }) {
|
|
45
|
+
export async function loadTuiMemoryFiles({ configRoot, cwd, homeDirectory = homedir(), dataPlane = 'claude', environment = process.env, }) {
|
|
59
46
|
const [canonicalCwd, canonicalHome] = await Promise.all([
|
|
60
47
|
realpath(cwd),
|
|
61
48
|
realpath(homeDirectory).catch(() => resolve(homeDirectory)),
|
|
62
49
|
]);
|
|
63
|
-
const
|
|
64
|
-
? await
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
50
|
+
const settings = dataPlane === 'native'
|
|
51
|
+
? await loadNativeSettings({ root: configRoot, cwd })
|
|
52
|
+
: await loadClaudeSettings({ configRoot, cwd });
|
|
53
|
+
const memoryPolicy = resolveProjectMemoryPolicy({
|
|
54
|
+
dataPlane,
|
|
55
|
+
settings,
|
|
56
|
+
environment,
|
|
57
|
+
});
|
|
58
|
+
const [context, autoMemoryDirectory] = await Promise.all([
|
|
59
|
+
dataPlane === 'native'
|
|
60
|
+
? loadNativeContextResources({
|
|
61
|
+
root: configRoot,
|
|
62
|
+
cwd,
|
|
63
|
+
environment,
|
|
64
|
+
includeProjectMemory: memoryPolicy.enabled,
|
|
65
|
+
})
|
|
66
|
+
: loadClaudeContextResources({
|
|
73
67
|
configRoot,
|
|
74
68
|
cwd,
|
|
75
69
|
homeDirectory,
|
|
70
|
+
includeProjectMemory: memoryPolicy.enabled,
|
|
76
71
|
}),
|
|
77
|
-
|
|
72
|
+
resolveProjectMemoryDirectory({
|
|
73
|
+
dataPlane,
|
|
74
|
+
configRoot,
|
|
75
|
+
cwd,
|
|
76
|
+
}),
|
|
77
|
+
]);
|
|
78
78
|
const instructionName = dataPlane === 'native' ? 'PRAXIS.md' : 'CLAUDE.md';
|
|
79
79
|
const userPath = resolve(configRoot, instructionName);
|
|
80
80
|
const projectResources = context.instructions.filter((resource) => resource.importedFrom === undefined &&
|
|
@@ -129,7 +129,7 @@ export async function loadTuiMemoryFiles({ configRoot, cwd, homeDirectory = home
|
|
|
129
129
|
});
|
|
130
130
|
entries.push(...importedEntries(resource, context.instructions, canonicalCwd, canonicalHome, displayPath));
|
|
131
131
|
}
|
|
132
|
-
const autoMemoryEnabled =
|
|
132
|
+
const autoMemoryEnabled = memoryPolicy.enabled;
|
|
133
133
|
if (autoMemoryEnabled) {
|
|
134
134
|
entries.push({
|
|
135
135
|
kind: 'folder',
|
package/dist/cli-runtime.d.ts
CHANGED
|
@@ -39,6 +39,7 @@ interface SessionCommands {
|
|
|
39
39
|
rewindFiles?(sessionId: string, userMessageId: string): Promise<void>;
|
|
40
40
|
rewindPoints?(sessionId: string): Promise<RewindPoint[]>;
|
|
41
41
|
changeCwd?(sessionId: string | undefined, cwd: string): Promise<string>;
|
|
42
|
+
notify?(sessionId: string | undefined, message: string, notificationType: string, title?: string): void;
|
|
42
43
|
recordCdUsage?(sessionId: string): Promise<void>;
|
|
43
44
|
approveRecentlyDenied?(sessionId: string, display: string): Promise<void>;
|
|
44
45
|
retryRecentlyDenied?(sessionId: string, display: string, signal?: AbortSignal): Promise<SessionRunResult>;
|
package/dist/cli-runtime.js
CHANGED
|
@@ -7,6 +7,9 @@ import { dirname, join, resolve } from 'node:path';
|
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
8
|
import { randomUUID } from 'node:crypto';
|
|
9
9
|
import { ClaudeSessionService, } from './application/session-service.js';
|
|
10
|
+
import { ProjectMemoryAgentExtractor, ProjectMemoryExtractionController, ProjectMemoryModelSelector, ProjectMemoryRecallController, } from './application/project-memory.js';
|
|
11
|
+
import { resolveProjectMemoryPolicy } from './core/project-memory.js';
|
|
12
|
+
import { resolveProjectMemoryDirectory, resolveProjectMemoryStatePath, } from './platform/project-memory-paths.js';
|
|
10
13
|
import { ClaudeCostStateStore } from './persistence/claude-cost-state-store.js';
|
|
11
14
|
import { agentColorMessage, parseAgentColorInput, } from './compatibility/claude/agent-color.js';
|
|
12
15
|
import { ClaudeConditionalRuleResolver, ClaudeContextAssembler, } from './compatibility/claude/context.js';
|
|
@@ -16,7 +19,7 @@ import { isClaudeSessionId, resolveClaudePaths, } from './compatibility/claude/p
|
|
|
16
19
|
import { resolveDataPlane, resolveDataPlaneRoot, resolveDataPlanePaths, } from './persistence/data-plane.js';
|
|
17
20
|
import { loadNativeContextResources, loadNativeSettings, loadNativeSharedResources, } from './persistence/native-resources.js';
|
|
18
21
|
import { migrateClaudeData } from './persistence/claude-migration.js';
|
|
19
|
-
import { loadClaudeContextResources, loadClaudeSettings, loadClaudeSharedResources, resolveClaudeProjectIdentity,
|
|
22
|
+
import { loadClaudeContextResources, loadClaudeSettings, loadClaudeSharedResources, resolveClaudeProjectIdentity, } from './compatibility/claude/shared-resources.js';
|
|
20
23
|
import { AgentRunCancelledError, } from './core/runtime.js';
|
|
21
24
|
import { persistTuiPermissionUpdates } from './cli/tui/permission-settings.js';
|
|
22
25
|
import { loadClaudeReleaseNotes } from './cli/tui/release-notes.js';
|
|
@@ -30,6 +33,7 @@ import { createClaudeModelAutoClassifier, defaultClaudeAutoModeConfig, loadClaud
|
|
|
30
33
|
import { ClaudeExtensionPermissionResolver, ClaudeExtensionToolRegistry, } from './extensions/claude-extension-tools.js';
|
|
31
34
|
import { ClaudeExtensionCatalog } from './extensions/claude-extensions.js';
|
|
32
35
|
import { ClaudeHookRunner } from './hooks/claude-hooks.js';
|
|
36
|
+
import { ClaudeSessionEnvironment } from './hooks/claude-session-environment.js';
|
|
33
37
|
import { ClaudeMcpToolRegistry, } from './mcp/claude-mcp-tools.js';
|
|
34
38
|
import { ClaudeMcpManagement, filterDisabledMcpResources, mcpScope, } from './mcp/claude-mcp-management.js';
|
|
35
39
|
import { authenticateMcpServer, ClaudeMcpOAuthStore, mcpOAuthServerIdentity, readMcpClientSecret, } from './mcp/claude-mcp-oauth.js';
|
|
@@ -1011,9 +1015,47 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
|
|
|
1011
1015
|
: toolProvider;
|
|
1012
1016
|
const automaticSettingSources = cli.safeMode || simpleMode ? [] : cli.settingSources;
|
|
1013
1017
|
const nativeSharedResourcesEnabled = !cli.safeMode && !simpleMode;
|
|
1018
|
+
const baseSettings = dataPlane === 'native'
|
|
1019
|
+
? nativeSharedResourcesEnabled
|
|
1020
|
+
? await loadNativeSettings({ root: configRoot, cwd })
|
|
1021
|
+
: []
|
|
1022
|
+
: await loadClaudeSettings({
|
|
1023
|
+
configRoot,
|
|
1024
|
+
cwd,
|
|
1025
|
+
...(automaticSettingSources === undefined
|
|
1026
|
+
? {}
|
|
1027
|
+
: { settingSources: automaticSettingSources }),
|
|
1028
|
+
});
|
|
1029
|
+
const pluginResources = await loadClaudePlugins({
|
|
1030
|
+
configRoot,
|
|
1031
|
+
dataPlane,
|
|
1032
|
+
cwd,
|
|
1033
|
+
pluginDirectories: cli.pluginDirectories,
|
|
1034
|
+
pluginUrls: cli.pluginUrls,
|
|
1035
|
+
strictPluginDirectories: cli.pluginDirectories.length + cli.pluginUrls.length > 0,
|
|
1036
|
+
loadInstalled: !cli.safeMode && !simpleMode,
|
|
1037
|
+
environment: runtimeEnvironment,
|
|
1038
|
+
});
|
|
1039
|
+
const projectMemoryPolicy = cli.safeMode || simpleMode
|
|
1040
|
+
? { enabled: false, extraction: false, recall: false }
|
|
1041
|
+
: resolveProjectMemoryPolicy({
|
|
1042
|
+
dataPlane,
|
|
1043
|
+
settings: [
|
|
1044
|
+
...baseSettings,
|
|
1045
|
+
...pluginResources.settings,
|
|
1046
|
+
...(cli.additionalSettings ? [cli.additionalSettings] : []),
|
|
1047
|
+
],
|
|
1048
|
+
environment: runtimeEnvironment,
|
|
1049
|
+
});
|
|
1050
|
+
const includeProjectMemory = projectMemoryPolicy.enabled && !projectMemoryPolicy.recall;
|
|
1014
1051
|
const loadedResources = dataPlane === 'native'
|
|
1015
1052
|
? nativeSharedResourcesEnabled
|
|
1016
|
-
? await loadNativeSharedResources({
|
|
1053
|
+
? await loadNativeSharedResources({
|
|
1054
|
+
root: configRoot,
|
|
1055
|
+
cwd,
|
|
1056
|
+
environment: runtimeEnvironment,
|
|
1057
|
+
includeProjectMemory,
|
|
1058
|
+
})
|
|
1017
1059
|
: {
|
|
1018
1060
|
instructions: [],
|
|
1019
1061
|
memory: [],
|
|
@@ -1027,20 +1069,11 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
|
|
|
1027
1069
|
configRoot,
|
|
1028
1070
|
cwd,
|
|
1029
1071
|
claudeStatePath,
|
|
1072
|
+
includeProjectMemory,
|
|
1030
1073
|
...(automaticSettingSources === undefined
|
|
1031
1074
|
? {}
|
|
1032
1075
|
: { settingSources: automaticSettingSources }),
|
|
1033
1076
|
});
|
|
1034
|
-
const pluginResources = await loadClaudePlugins({
|
|
1035
|
-
configRoot,
|
|
1036
|
-
dataPlane,
|
|
1037
|
-
cwd,
|
|
1038
|
-
pluginDirectories: cli.pluginDirectories,
|
|
1039
|
-
pluginUrls: cli.pluginUrls,
|
|
1040
|
-
strictPluginDirectories: cli.pluginDirectories.length + cli.pluginUrls.length > 0,
|
|
1041
|
-
loadInstalled: !cli.safeMode && !simpleMode,
|
|
1042
|
-
environment: runtimeEnvironment,
|
|
1043
|
-
});
|
|
1044
1077
|
const settings = [
|
|
1045
1078
|
...loadedResources.settings,
|
|
1046
1079
|
...pluginResources.settings,
|
|
@@ -1081,21 +1114,53 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
|
|
|
1081
1114
|
disableSlashCommands: cli.disableSlashCommands,
|
|
1082
1115
|
dataPlane,
|
|
1083
1116
|
});
|
|
1084
|
-
const memoryDirectory =
|
|
1117
|
+
const memoryDirectory = !projectMemoryPolicy.enabled
|
|
1085
1118
|
? undefined
|
|
1086
|
-
:
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
sessionId: randomUUID(),
|
|
1092
|
-
}).memoryRoot
|
|
1093
|
-
: await resolveClaudeProjectMemoryDirectory({ configRoot, cwd });
|
|
1119
|
+
: await resolveProjectMemoryDirectory({
|
|
1120
|
+
dataPlane,
|
|
1121
|
+
configRoot,
|
|
1122
|
+
cwd,
|
|
1123
|
+
});
|
|
1094
1124
|
if (memoryDirectory)
|
|
1095
1125
|
await mkdir(memoryDirectory, { recursive: true });
|
|
1126
|
+
const projectMemoryProviderFactory = providerForMainModel && model
|
|
1127
|
+
? () => providerForMainModel(model)
|
|
1128
|
+
: undefined;
|
|
1129
|
+
const projectMemoryRecall = projectMemoryPolicy.recall &&
|
|
1130
|
+
memoryDirectory &&
|
|
1131
|
+
projectMemoryProviderFactory
|
|
1132
|
+
? new ProjectMemoryRecallController({
|
|
1133
|
+
directory: memoryDirectory,
|
|
1134
|
+
selector: new ProjectMemoryModelSelector({
|
|
1135
|
+
directory: memoryDirectory,
|
|
1136
|
+
providerFactory: projectMemoryProviderFactory,
|
|
1137
|
+
}),
|
|
1138
|
+
})
|
|
1139
|
+
: undefined;
|
|
1140
|
+
const projectMemoryExtraction = projectMemoryPolicy.extraction &&
|
|
1141
|
+
memoryDirectory &&
|
|
1142
|
+
projectMemoryProviderFactory
|
|
1143
|
+
? new ProjectMemoryExtractionController({
|
|
1144
|
+
directory: memoryDirectory,
|
|
1145
|
+
cursorPath: resolveProjectMemoryStatePath({
|
|
1146
|
+
dataPlane,
|
|
1147
|
+
configRoot,
|
|
1148
|
+
memoryDirectory,
|
|
1149
|
+
}),
|
|
1150
|
+
extractor: new ProjectMemoryAgentExtractor({
|
|
1151
|
+
providerFactory: projectMemoryProviderFactory,
|
|
1152
|
+
}),
|
|
1153
|
+
onWarning: (message) => runtimeEventSink({ type: 'warning', message }),
|
|
1154
|
+
})
|
|
1155
|
+
: undefined;
|
|
1096
1156
|
const loadContextResources = (runtimeCwd = workspace.cwd()) => dataPlane === 'native'
|
|
1097
1157
|
? nativeSharedResourcesEnabled
|
|
1098
|
-
? loadNativeContextResources({
|
|
1158
|
+
? loadNativeContextResources({
|
|
1159
|
+
root: configRoot,
|
|
1160
|
+
cwd: runtimeCwd,
|
|
1161
|
+
environment: runtimeEnvironment,
|
|
1162
|
+
includeProjectMemory,
|
|
1163
|
+
})
|
|
1099
1164
|
: Promise.resolve({
|
|
1100
1165
|
instructions: [],
|
|
1101
1166
|
conditionalRules: [],
|
|
@@ -1104,6 +1169,7 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
|
|
|
1104
1169
|
: loadClaudeContextResources({
|
|
1105
1170
|
configRoot,
|
|
1106
1171
|
cwd: runtimeCwd,
|
|
1172
|
+
includeProjectMemory,
|
|
1107
1173
|
...(automaticSettingSources === undefined
|
|
1108
1174
|
? {}
|
|
1109
1175
|
: { settingSources: automaticSettingSources }),
|
|
@@ -1161,6 +1227,15 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
|
|
|
1161
1227
|
: {}),
|
|
1162
1228
|
}), extensions);
|
|
1163
1229
|
const permissions = permissionResolverForMode(cli.dangerouslySkipPermissions ? 'bypassPermissions' : cli.permissionMode);
|
|
1230
|
+
const hookSessionEnvironment = new ClaudeSessionEnvironment({
|
|
1231
|
+
stateRoot: resolveDataPlanePaths({
|
|
1232
|
+
dataPlane,
|
|
1233
|
+
root: configRoot,
|
|
1234
|
+
cwd,
|
|
1235
|
+
sessionId: '00000000-0000-4000-8000-000000000000',
|
|
1236
|
+
}).stateRoot,
|
|
1237
|
+
warn: (message) => runtimeEventSink({ type: 'warning', message }),
|
|
1238
|
+
});
|
|
1164
1239
|
const localTools = new LocalToolRegistry({
|
|
1165
1240
|
cwd,
|
|
1166
1241
|
cwdProvider: () => workspace.cwd(),
|
|
@@ -1172,6 +1247,7 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
|
|
|
1172
1247
|
homeDirectory: sandboxEnvironment.HOME ?? sandboxEnvironment.USERPROFILE ?? homedir(),
|
|
1173
1248
|
configRoot,
|
|
1174
1249
|
dataPlane,
|
|
1250
|
+
sessionEnvironment: (sessionId) => hookSessionEnvironment.environment(sessionId),
|
|
1175
1251
|
...(environment ? { environment } : {}),
|
|
1176
1252
|
});
|
|
1177
1253
|
const runtimeMcpResources = async (candidates) => {
|
|
@@ -1200,6 +1276,8 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
|
|
|
1200
1276
|
? await loadNativeSharedResources({
|
|
1201
1277
|
root: configRoot,
|
|
1202
1278
|
cwd: workspace.cwd(),
|
|
1279
|
+
environment: runtimeEnvironment,
|
|
1280
|
+
includeProjectMemory,
|
|
1203
1281
|
})
|
|
1204
1282
|
: {
|
|
1205
1283
|
instructions: [],
|
|
@@ -1214,6 +1292,7 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
|
|
|
1214
1292
|
configRoot,
|
|
1215
1293
|
cwd: workspace.cwd(),
|
|
1216
1294
|
claudeStatePath,
|
|
1295
|
+
includeProjectMemory,
|
|
1217
1296
|
...(automaticSettingSources === undefined
|
|
1218
1297
|
? {}
|
|
1219
1298
|
: { settingSources: automaticSettingSources }),
|
|
@@ -1369,6 +1448,7 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
|
|
|
1369
1448
|
settings,
|
|
1370
1449
|
cwd,
|
|
1371
1450
|
onEvent: (event) => runtimeEventSink({ type: 'hook', event }),
|
|
1451
|
+
sessionEnvironment: hookSessionEnvironment,
|
|
1372
1452
|
});
|
|
1373
1453
|
const interactiveTools = selectedInteractiveTools.length > 0 && askUser && approvePlan
|
|
1374
1454
|
? new ClaudeInteractiveToolManager({
|
|
@@ -1386,6 +1466,11 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
|
|
|
1386
1466
|
: undefined;
|
|
1387
1467
|
contextAssembler = new ClaudeContextAssembler({
|
|
1388
1468
|
loadResources: loadContextResources,
|
|
1469
|
+
onInstructionsLoaded: async (instructions, context) => {
|
|
1470
|
+
if (!context.lifecycleId)
|
|
1471
|
+
return;
|
|
1472
|
+
await service.instructionsLoaded(context.lifecycleId, instructions, context.reason);
|
|
1473
|
+
},
|
|
1389
1474
|
loadDynamicContext: (runtimeCwd = workspace.cwd()) => loadClaudeDynamicContext({
|
|
1390
1475
|
cwd: runtimeCwd,
|
|
1391
1476
|
...(memoryDirectory ? { memoryDirectory } : {}),
|
|
@@ -1467,6 +1552,9 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
|
|
|
1467
1552
|
...(interactiveTools ? { interactiveTools } : {}),
|
|
1468
1553
|
...(hooks ? { hooks } : {}),
|
|
1469
1554
|
...(selectedMainAgent ? { agent: selectedMainAgent } : {}),
|
|
1555
|
+
...(memoryDirectory ? { projectMemoryDirectory: memoryDirectory } : {}),
|
|
1556
|
+
...(projectMemoryRecall ? { projectMemoryRecall } : {}),
|
|
1557
|
+
...(projectMemoryExtraction ? { projectMemoryExtraction } : {}),
|
|
1470
1558
|
contextAssembler,
|
|
1471
1559
|
conditionalRuleResolver: new ClaudeConditionalRuleResolver({
|
|
1472
1560
|
loadResources: loadContextResources,
|
|
@@ -1553,6 +1641,7 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
|
|
|
1553
1641
|
rewindFiles: (sessionId, userMessageId) => service.rewindFiles(sessionId, userMessageId),
|
|
1554
1642
|
rewindPoints: (sessionId) => service.rewindPoints(sessionId),
|
|
1555
1643
|
changeCwd: (sessionId, cwd) => service.changeCwd(sessionId, cwd),
|
|
1644
|
+
notify: (sessionId, message, notificationType, title) => service.notifyDetached(sessionId, message, notificationType, title),
|
|
1556
1645
|
recordCdUsage: (sessionId) => service.recordCdUsage(sessionId),
|
|
1557
1646
|
approveRecentlyDenied: (sessionId, display) => service.approveRecentlyDenied(sessionId, display),
|
|
1558
1647
|
retryRecentlyDenied: (sessionId, display, retrySignal) => service.retryRecentlyDenied(sessionId, display, retrySignal),
|
|
@@ -3544,9 +3633,40 @@ function eventSink(io, outputFormat, legacyJson = false) {
|
|
|
3544
3633
|
}
|
|
3545
3634
|
if (outputFormat !== 'text')
|
|
3546
3635
|
return () => undefined;
|
|
3636
|
+
let turnBuffered = false;
|
|
3637
|
+
let bufferedText = '';
|
|
3638
|
+
const flushBufferedText = () => {
|
|
3639
|
+
if (bufferedText.length > 0)
|
|
3640
|
+
io.stdout(bufferedText);
|
|
3641
|
+
bufferedText = '';
|
|
3642
|
+
};
|
|
3547
3643
|
return (event) => {
|
|
3548
|
-
if (event.type === '
|
|
3549
|
-
|
|
3644
|
+
if (event.type === 'state' && event.state === 'awaiting-model') {
|
|
3645
|
+
turnBuffered = true;
|
|
3646
|
+
bufferedText = '';
|
|
3647
|
+
}
|
|
3648
|
+
if (event.type === 'text-delta') {
|
|
3649
|
+
if (turnBuffered)
|
|
3650
|
+
bufferedText += event.delta;
|
|
3651
|
+
else
|
|
3652
|
+
io.stdout(event.delta);
|
|
3653
|
+
}
|
|
3654
|
+
if (event.type === 'model-attempt-discarded')
|
|
3655
|
+
bufferedText = '';
|
|
3656
|
+
if (event.type === 'terminal' &&
|
|
3657
|
+
event.reason !== 'prompt_too_long' &&
|
|
3658
|
+
turnBuffered) {
|
|
3659
|
+
flushBufferedText();
|
|
3660
|
+
turnBuffered = false;
|
|
3661
|
+
}
|
|
3662
|
+
if (event.type === 'state' && event.state === 'completed' && turnBuffered) {
|
|
3663
|
+
flushBufferedText();
|
|
3664
|
+
turnBuffered = false;
|
|
3665
|
+
}
|
|
3666
|
+
if (event.type === 'failed') {
|
|
3667
|
+
bufferedText = '';
|
|
3668
|
+
turnBuffered = false;
|
|
3669
|
+
}
|
|
3550
3670
|
if (event.type === 'user-message')
|
|
3551
3671
|
io.stdout(`\n${event.message}\n`);
|
|
3552
3672
|
if (event.type === 'warning') {
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import type { AssembledContext, ContextAssembler, ContextAssemblyOptions, ContextInvalidationOptions } from '../../core/context.js';
|
|
2
2
|
import { type ClaudeDynamicContextSections } from './dynamic-context.js';
|
|
3
|
-
import type { ClaudeContextResources, ClaudeConditionalRule } from './shared-resources.js';
|
|
3
|
+
import type { ClaudeContextResources, ClaudeConditionalRule, ClaudeTextResource } from './shared-resources.js';
|
|
4
4
|
export interface ClaudeContextAssemblerOptions {
|
|
5
5
|
loadResources(cwd?: string): Promise<ClaudeContextResources>;
|
|
6
|
+
onInstructionsLoaded?(resources: readonly ClaudeTextResource[], context: {
|
|
7
|
+
lifecycleId?: string;
|
|
8
|
+
cwd?: string;
|
|
9
|
+
reason: 'session_start' | 'compact' | 'resource_reload';
|
|
10
|
+
}): Promise<void>;
|
|
6
11
|
loadDynamicContext?(cwd?: string): Promise<ClaudeDynamicContextSections>;
|
|
7
12
|
loadMcpInstructions?(): Promise<readonly ClaudeMcpInstruction[]>;
|
|
8
13
|
loadSessionGuidance?(): Promise<string | undefined>;
|