@leanandmean/coding-agent 0.74.1-scramjet.73 → 0.74.1-scramjet.74
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/README.md +4 -0
- package/dist/core/agent-session.d.ts +19 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +293 -68
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +5 -3
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +18 -5
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +9 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +123 -17
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +35 -16
- package/dist/modes/print-mode.js.map +1 -1
- package/docs/compaction.md +6 -0
- package/docs/custom-provider.md +3 -1
- package/docs/extensions.md +13 -1
- package/docs/sdk.md +27 -0
- package/docs/settings.md +2 -0
- package/docs/terminal-verification.md +8 -0
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"print-mode.d.ts","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"print-mode.d.ts","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAI5E;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,yEAAyE;IACzE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyJ/G","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `pi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { ImageContent } from \"@leanandmean/ai\";\nimport type { RunSettlement } from \"../core/agent-session.js\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.js\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.js\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.js\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet outcome: RunSettlement | undefined;\n\tlet session = runtimeHost.session;\n\tlet unsubscribe: (() => void) | undefined;\n\tlet disposed = false;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeRuntime = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tawait runtimeHost.dispose();\n\t};\n\n\tconst registerSignalHandlers = (): void => {\n\t\tconst signals: NodeJS.Signals[] = [\"SIGTERM\"];\n\t\tif (process.platform !== \"win32\") {\n\t\t\tsignals.push(\"SIGHUP\");\n\t\t}\n\n\t\tfor (const signal of signals) {\n\t\t\tconst handler = () => {\n\t\t\t\tkillTrackedDetachedChildren();\n\t\t\t\tvoid disposeRuntime().finally(() => {\n\t\t\t\t\tprocess.exit(signal === \"SIGHUP\" ? 129 : 143);\n\t\t\t\t});\n\t\t\t};\n\t\t\tprocess.on(signal, handler);\n\t\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t\t}\n\t};\n\n\tregisterSignalHandlers();\n\n\truntimeHost.setRebindSession(async () => {\n\t\tawait rebindSession();\n\t});\n\n\tconst rebindSession = async (): Promise<void> => {\n\t\tsession = runtimeHost.session;\n\t\tawait session.bindExtensions({\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.agent.waitForIdle(),\n\t\t\t\tnewSession: async (newSessionOptions) => runtimeHost.newSession(newSessionOptions),\n\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\tconst result = await runtimeHost.fork(entryId, forkOptions);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, navigateOptions) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: navigateOptions?.summarize,\n\t\t\t\t\t\tcustomInstructions: navigateOptions?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: navigateOptions?.replaceInstructions,\n\t\t\t\t\t\tlabel: navigateOptions?.label,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tswitchSession: async (sessionPath, switchOptions) => {\n\t\t\t\t\treturn runtimeHost.switchSession(sessionPath, switchOptions);\n\t\t\t\t},\n\t\t\t\treload: async () => {\n\t\t\t\t\tawait session.reload();\n\t\t\t\t},\n\t\t\t},\n\t\t\tonError: (err) => {\n\t\t\t\tconsole.error(`Extension error (${err.extensionPath}): ${err.error}`);\n\t\t\t},\n\t\t});\n\n\t\tunsubscribe?.();\n\t\tunsubscribe = session.subscribe((event) => {\n\t\t\tif (mode === \"json\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event)}\\n`);\n\t\t\t}\n\t\t});\n\t};\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = session.sessionManager.getHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tawait rebindSession();\n\n\t\t// SCRAMJET-DIVERGENCE: select the invocation's result, never mutable live history.\n\t\tconst prompt = async (text: string, images?: ImageContent[]) => {\n\t\t\toutcome = undefined;\n\t\t\tif (mode === \"json\") {\n\t\t\t\tawait session.prompt(text, { images });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet captured: Promise<RunSettlement> | undefined;\n\t\t\tawait session.prompt(text, {\n\t\t\t\timages,\n\t\t\t\tonRunSettlement(settlement) {\n\t\t\t\t\tcaptured = settlement;\n\t\t\t\t\tvoid settlement.catch(() => {});\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (captured) outcome = await captured;\n\t\t};\n\t\tif (initialMessage) {\n\t\t\tawait prompt(initialMessage, initialImages);\n\t\t}\n\n\t\tfor (const message of messages) {\n\t\t\tawait prompt(message);\n\t\t}\n\n\t\tif (mode === \"text\") {\n\t\t\tconst assistantMsg = outcome?.assistantMessage;\n\t\t\tif (outcome && outcome.status !== \"completed\") {\n\t\t\t\tconsole.error(\n\t\t\t\t\toutcome.status === \"cancelled\"\n\t\t\t\t\t\t? \"Execution cancelled. Review interrupted work before submitting a new prompt.\"\n\t\t\t\t\t\t: `Execution failed: ${outcome.errorMessage}. Review the failure before trying again.`,\n\t\t\t\t);\n\t\t\t\texitCode = 1;\n\t\t\t}\n\t\t\tif (assistantMsg) {\n\t\t\t\tif (outcome?.status === \"failed\") {\n\t\t\t\t\tconst snapshot = assistantMsg.diagnostics?.find(\n\t\t\t\t\t\t(diagnostic) => diagnostic.type === \"provider_failure_snapshot\",\n\t\t\t\t\t)?.details?.text;\n\t\t\t\t\tif (typeof snapshot === \"string\") console.error(`Error details (local):\\n${snapshot}`);\n\t\t\t\t} else if (outcome?.status === \"completed\") {\n\t\t\t\t\tfor (const content of assistantMsg.content) {\n\t\t\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\t\t\twriteRawStdout(`${content.text}\\n`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn exitCode;\n\t} catch (error: unknown) {\n\t\tconsole.error(\n\t\t\t`${error instanceof Error ? error.message : String(error)}. Review the failure before trying again.`,\n\t\t);\n\t\treturn 1;\n\t} finally {\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tawait disposeRuntime();\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
|
package/dist/modes/print-mode.js
CHANGED
|
@@ -14,6 +14,7 @@ import { killTrackedDetachedChildren } from "../utils/shell.js";
|
|
|
14
14
|
export async function runPrintMode(runtimeHost, options) {
|
|
15
15
|
const { mode, messages = [], initialMessage, initialImages } = options;
|
|
16
16
|
let exitCode = 0;
|
|
17
|
+
let outcome;
|
|
17
18
|
let session = runtimeHost.session;
|
|
18
19
|
let unsubscribe;
|
|
19
20
|
let disposed = false;
|
|
@@ -90,27 +91,45 @@ export async function runPrintMode(runtimeHost, options) {
|
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
93
|
await rebindSession();
|
|
94
|
+
// SCRAMJET-DIVERGENCE: select the invocation's result, never mutable live history.
|
|
95
|
+
const prompt = async (text, images) => {
|
|
96
|
+
outcome = undefined;
|
|
97
|
+
if (mode === "json") {
|
|
98
|
+
await session.prompt(text, { images });
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
let captured;
|
|
102
|
+
await session.prompt(text, {
|
|
103
|
+
images,
|
|
104
|
+
onRunSettlement(settlement) {
|
|
105
|
+
captured = settlement;
|
|
106
|
+
void settlement.catch(() => { });
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
if (captured)
|
|
110
|
+
outcome = await captured;
|
|
111
|
+
};
|
|
93
112
|
if (initialMessage) {
|
|
94
|
-
await
|
|
113
|
+
await prompt(initialMessage, initialImages);
|
|
95
114
|
}
|
|
96
115
|
for (const message of messages) {
|
|
97
|
-
await
|
|
116
|
+
await prompt(message);
|
|
98
117
|
}
|
|
99
118
|
if (mode === "text") {
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
119
|
+
const assistantMsg = outcome?.assistantMessage;
|
|
120
|
+
if (outcome && outcome.status !== "completed") {
|
|
121
|
+
console.error(outcome.status === "cancelled"
|
|
122
|
+
? "Execution cancelled. Review interrupted work before submitting a new prompt."
|
|
123
|
+
: `Execution failed: ${outcome.errorMessage}. Review the failure before trying again.`);
|
|
124
|
+
exitCode = 1;
|
|
125
|
+
}
|
|
126
|
+
if (assistantMsg) {
|
|
127
|
+
if (outcome?.status === "failed") {
|
|
128
|
+
const snapshot = assistantMsg.diagnostics?.find((diagnostic) => diagnostic.type === "provider_failure_snapshot")?.details?.text;
|
|
129
|
+
if (typeof snapshot === "string")
|
|
130
|
+
console.error(`Error details (local):\n${snapshot}`);
|
|
112
131
|
}
|
|
113
|
-
else {
|
|
132
|
+
else if (outcome?.status === "completed") {
|
|
114
133
|
for (const content of assistantMsg.content) {
|
|
115
134
|
if (content.type === "text") {
|
|
116
135
|
writeRawStdout(`${content.text}\n`);
|
|
@@ -122,7 +141,7 @@ export async function runPrintMode(runtimeHost, options) {
|
|
|
122
141
|
return exitCode;
|
|
123
142
|
}
|
|
124
143
|
catch (error) {
|
|
125
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
144
|
+
console.error(`${error instanceof Error ? error.message : String(error)}. Review the failure before trying again.`);
|
|
126
145
|
return 1;
|
|
127
146
|
}
|
|
128
147
|
finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"print-mode.js","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `pi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { AssistantMessage, ImageContent } from \"@leanandmean/ai\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.js\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.js\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.js\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet session = runtimeHost.session;\n\tlet unsubscribe: (() => void) | undefined;\n\tlet disposed = false;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeRuntime = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tawait runtimeHost.dispose();\n\t};\n\n\tconst registerSignalHandlers = (): void => {\n\t\tconst signals: NodeJS.Signals[] = [\"SIGTERM\"];\n\t\tif (process.platform !== \"win32\") {\n\t\t\tsignals.push(\"SIGHUP\");\n\t\t}\n\n\t\tfor (const signal of signals) {\n\t\t\tconst handler = () => {\n\t\t\t\tkillTrackedDetachedChildren();\n\t\t\t\tvoid disposeRuntime().finally(() => {\n\t\t\t\t\tprocess.exit(signal === \"SIGHUP\" ? 129 : 143);\n\t\t\t\t});\n\t\t\t};\n\t\t\tprocess.on(signal, handler);\n\t\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t\t}\n\t};\n\n\tregisterSignalHandlers();\n\n\truntimeHost.setRebindSession(async () => {\n\t\tawait rebindSession();\n\t});\n\n\tconst rebindSession = async (): Promise<void> => {\n\t\tsession = runtimeHost.session;\n\t\tawait session.bindExtensions({\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.agent.waitForIdle(),\n\t\t\t\tnewSession: async (newSessionOptions) => runtimeHost.newSession(newSessionOptions),\n\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\tconst result = await runtimeHost.fork(entryId, forkOptions);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, navigateOptions) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: navigateOptions?.summarize,\n\t\t\t\t\t\tcustomInstructions: navigateOptions?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: navigateOptions?.replaceInstructions,\n\t\t\t\t\t\tlabel: navigateOptions?.label,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tswitchSession: async (sessionPath, switchOptions) => {\n\t\t\t\t\treturn runtimeHost.switchSession(sessionPath, switchOptions);\n\t\t\t\t},\n\t\t\t\treload: async () => {\n\t\t\t\t\tawait session.reload();\n\t\t\t\t},\n\t\t\t},\n\t\t\tonError: (err) => {\n\t\t\t\tconsole.error(`Extension error (${err.extensionPath}): ${err.error}`);\n\t\t\t},\n\t\t});\n\n\t\tunsubscribe?.();\n\t\tunsubscribe = session.subscribe((event) => {\n\t\t\tif (mode === \"json\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event)}\\n`);\n\t\t\t}\n\t\t});\n\t};\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = session.sessionManager.getHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tawait rebindSession();\n\n\t\tif (initialMessage) {\n\t\t\tawait session.prompt(initialMessage, { images: initialImages });\n\t\t}\n\n\t\tfor (const message of messages) {\n\t\t\tawait session.prompt(message);\n\t\t}\n\n\t\tif (mode === \"text\") {\n\t\t\tconst state = session.state;\n\t\t\tconst lastMessage = state.messages[state.messages.length - 1];\n\n\t\t\tif (lastMessage?.role === \"assistant\") {\n\t\t\t\tconst assistantMsg = lastMessage as AssistantMessage;\n\t\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\t\tconsole.error(assistantMsg.errorMessage || `Request ${assistantMsg.stopReason}`);\n\t\t\t\t\tif (assistantMsg.stopReason === \"error\") {\n\t\t\t\t\t\tconst snapshot = assistantMsg.diagnostics?.find(\n\t\t\t\t\t\t\t(diagnostic) => diagnostic.type === \"provider_failure_snapshot\",\n\t\t\t\t\t\t)?.details?.text;\n\t\t\t\t\t\tif (typeof snapshot === \"string\") console.error(`Error details (local):\\n${snapshot}`);\n\t\t\t\t\t}\n\t\t\t\t\texitCode = 1;\n\t\t\t\t} else {\n\t\t\t\t\tfor (const content of assistantMsg.content) {\n\t\t\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\t\t\twriteRawStdout(`${content.text}\\n`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn exitCode;\n\t} catch (error: unknown) {\n\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\treturn 1;\n\t} finally {\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tawait disposeRuntime();\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"print-mode.js","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `pi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { ImageContent } from \"@leanandmean/ai\";\nimport type { RunSettlement } from \"../core/agent-session.js\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.js\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.js\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.js\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet outcome: RunSettlement | undefined;\n\tlet session = runtimeHost.session;\n\tlet unsubscribe: (() => void) | undefined;\n\tlet disposed = false;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeRuntime = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tawait runtimeHost.dispose();\n\t};\n\n\tconst registerSignalHandlers = (): void => {\n\t\tconst signals: NodeJS.Signals[] = [\"SIGTERM\"];\n\t\tif (process.platform !== \"win32\") {\n\t\t\tsignals.push(\"SIGHUP\");\n\t\t}\n\n\t\tfor (const signal of signals) {\n\t\t\tconst handler = () => {\n\t\t\t\tkillTrackedDetachedChildren();\n\t\t\t\tvoid disposeRuntime().finally(() => {\n\t\t\t\t\tprocess.exit(signal === \"SIGHUP\" ? 129 : 143);\n\t\t\t\t});\n\t\t\t};\n\t\t\tprocess.on(signal, handler);\n\t\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t\t}\n\t};\n\n\tregisterSignalHandlers();\n\n\truntimeHost.setRebindSession(async () => {\n\t\tawait rebindSession();\n\t});\n\n\tconst rebindSession = async (): Promise<void> => {\n\t\tsession = runtimeHost.session;\n\t\tawait session.bindExtensions({\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.agent.waitForIdle(),\n\t\t\t\tnewSession: async (newSessionOptions) => runtimeHost.newSession(newSessionOptions),\n\t\t\t\tfork: async (entryId, forkOptions) => {\n\t\t\t\t\tconst result = await runtimeHost.fork(entryId, forkOptions);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, navigateOptions) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: navigateOptions?.summarize,\n\t\t\t\t\t\tcustomInstructions: navigateOptions?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: navigateOptions?.replaceInstructions,\n\t\t\t\t\t\tlabel: navigateOptions?.label,\n\t\t\t\t\t});\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tswitchSession: async (sessionPath, switchOptions) => {\n\t\t\t\t\treturn runtimeHost.switchSession(sessionPath, switchOptions);\n\t\t\t\t},\n\t\t\t\treload: async () => {\n\t\t\t\t\tawait session.reload();\n\t\t\t\t},\n\t\t\t},\n\t\t\tonError: (err) => {\n\t\t\t\tconsole.error(`Extension error (${err.extensionPath}): ${err.error}`);\n\t\t\t},\n\t\t});\n\n\t\tunsubscribe?.();\n\t\tunsubscribe = session.subscribe((event) => {\n\t\t\tif (mode === \"json\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event)}\\n`);\n\t\t\t}\n\t\t});\n\t};\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = session.sessionManager.getHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tawait rebindSession();\n\n\t\t// SCRAMJET-DIVERGENCE: select the invocation's result, never mutable live history.\n\t\tconst prompt = async (text: string, images?: ImageContent[]) => {\n\t\t\toutcome = undefined;\n\t\t\tif (mode === \"json\") {\n\t\t\t\tawait session.prompt(text, { images });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet captured: Promise<RunSettlement> | undefined;\n\t\t\tawait session.prompt(text, {\n\t\t\t\timages,\n\t\t\t\tonRunSettlement(settlement) {\n\t\t\t\t\tcaptured = settlement;\n\t\t\t\t\tvoid settlement.catch(() => {});\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (captured) outcome = await captured;\n\t\t};\n\t\tif (initialMessage) {\n\t\t\tawait prompt(initialMessage, initialImages);\n\t\t}\n\n\t\tfor (const message of messages) {\n\t\t\tawait prompt(message);\n\t\t}\n\n\t\tif (mode === \"text\") {\n\t\t\tconst assistantMsg = outcome?.assistantMessage;\n\t\t\tif (outcome && outcome.status !== \"completed\") {\n\t\t\t\tconsole.error(\n\t\t\t\t\toutcome.status === \"cancelled\"\n\t\t\t\t\t\t? \"Execution cancelled. Review interrupted work before submitting a new prompt.\"\n\t\t\t\t\t\t: `Execution failed: ${outcome.errorMessage}. Review the failure before trying again.`,\n\t\t\t\t);\n\t\t\t\texitCode = 1;\n\t\t\t}\n\t\t\tif (assistantMsg) {\n\t\t\t\tif (outcome?.status === \"failed\") {\n\t\t\t\t\tconst snapshot = assistantMsg.diagnostics?.find(\n\t\t\t\t\t\t(diagnostic) => diagnostic.type === \"provider_failure_snapshot\",\n\t\t\t\t\t)?.details?.text;\n\t\t\t\t\tif (typeof snapshot === \"string\") console.error(`Error details (local):\\n${snapshot}`);\n\t\t\t\t} else if (outcome?.status === \"completed\") {\n\t\t\t\t\tfor (const content of assistantMsg.content) {\n\t\t\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\t\t\twriteRawStdout(`${content.text}\\n`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn exitCode;\n\t} catch (error: unknown) {\n\t\tconsole.error(\n\t\t\t`${error instanceof Error ? error.message : String(error)}. Review the failure before trying again.`,\n\t\t);\n\t\treturn 1;\n\t} finally {\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tawait disposeRuntime();\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
|
package/docs/compaction.md
CHANGED
|
@@ -44,6 +44,12 @@ A new user prompt independently checks threshold maintenance using trustworthy s
|
|
|
44
44
|
|
|
45
45
|
You can also trigger manually with `/compact [instructions]`, where optional instructions focus the summary.
|
|
46
46
|
|
|
47
|
+
### Originating recovery and automatic handoffs
|
|
48
|
+
|
|
49
|
+
A captured [run settlement](sdk.md#capturing-originating-run-settlement) remains pending through its settlement-triggered automatic compaction and any selected 100 ms overflow or queued-message continuation. The continuation waits for originating Agent execution to unwind and adopts the same obligation; it cannot restart after cancellation, disposal, or manual-compaction drain. New-prompt threshold maintenance is independent preflight and does not inherit a previous run's obligation.
|
|
50
|
+
|
|
51
|
+
Skipped optional maintenance may retain successful output. Skipped or failed required overflow recovery produces a failed disposition with actionable detail rather than claiming completion; cancellation produces a cancelled disposition after owned active work unwinds. Compaction persistence/reconstruction and continuation infrastructure failures reject the captured obligation. Existing threshold policy, one-attempt overflow cap, queue semantics, and manual admission remain unchanged. Neither retry records nor continuation ownership restore execution on resume.
|
|
52
|
+
|
|
47
53
|
### Manual admission and terminal drain
|
|
48
54
|
|
|
49
55
|
Manual compaction has one owner. It rejects while manual/automatic compaction or branch summarization is in progress, or while an idle-origin harness tool is still executing. Refusal leaves execution, abort signals, accounting, subscriptions, and context untouched. Await the conflicting operation's persisted settlement before deliberately retrying; requests are not queued.
|
package/docs/custom-provider.md
CHANGED
|
@@ -533,7 +533,9 @@ Built-in failure catches preserve an existing primary diagnosis, classify witnes
|
|
|
533
533
|
|
|
534
534
|
Callback failures must never be inferred from provider prose or persist original callback exception details. Message origin describes who produced the message, not which operation failed. Retain partial provider output and mark the callback failure separately.
|
|
535
535
|
|
|
536
|
-
|
|
536
|
+
Codex `type: "error"` events normalize witnessed top-level and nested error fields into one closed diagnosis before display formatting. An in-stream `status: 503` with `server_error` supports provider/server evidence, not an HTTP request rejection. Unknown and contradictory codes remain governed by the neutral evidence utility; arbitrary payloads and displayed prose do not authorize recovery.
|
|
537
|
+
|
|
538
|
+
Completeness coverage is route-qualified: shared Responses, started Codex WebSockets, Chat's existing finish-reason check, and started Anthropic streams detect missing terminals. A started Codex WebSocket close 1000 without accepted terminal completion emits stream `missing_terminal_event`: the cause remains unknown and its evidence is not transient, but session policy can retry that category within configured limits. Already-received WebSocket frames are decoded in arrival order before close adjudication; accepted terminals and semantic errors retain precedence, and cancellation remains immediate. Pre-start SSE fallback, abnormal-close transport evidence, and non-retryable policy-close exclusions remain separate. Additional mandatory markers for Google/Vertex, Mistral, Bedrock and startless Anthropic SSE were not established from installed SDK contracts and are not enforced. In particular, Google prompt-feedback blocking can occur without a candidate finish reason; parser acceptance alone does not establish valid backend completion. The installed Google SDK exposes bodyless generation failures as plain errors without a supported raw-response hook; Google/Vertex therefore retain an explicit unknown diagnosis rather than inferring body absence from the error message. Chat and Mistral classify body absence from their available response objects. Responses and default Chat/Anthropic clients distinguish local SDK preparation from dispatch at the invocation-local fetch boundary, not from observational SDK-attempt diagnostics or a generic `TypeError`.
|
|
537
539
|
|
|
538
540
|
### Context Overflow Errors
|
|
539
541
|
|
package/docs/extensions.md
CHANGED
|
@@ -539,7 +539,7 @@ Returning `systemPromptSection` contributes a section for the current turn witho
|
|
|
539
539
|
|
|
540
540
|
#### agent_start / agent_end
|
|
541
541
|
|
|
542
|
-
Fired
|
|
542
|
+
Fired for each Agent attempt, including automatic retry/compaction continuations. Attempt-level `agent_end` is not final recovery settlement; use the captured context capability described below for deferred completion observation.
|
|
543
543
|
|
|
544
544
|
```typescript
|
|
545
545
|
pi.on("agent_start", async (_event, ctx) => {});
|
|
@@ -985,6 +985,18 @@ pi.on("tool_result", async (event, ctx) => {
|
|
|
985
985
|
});
|
|
986
986
|
```
|
|
987
987
|
|
|
988
|
+
### ctx.getRunSettlement()
|
|
989
|
+
|
|
990
|
+
Optional `getRunSettlement(): Promise<RunSettlement> | undefined` captures the exact originating execution in queued Agent lifecycle/message/tool-execution events and its owned automatic `session_before_compact` / `session_compact` hooks. All attempts and owned maintenance share the same promise as SDK `PromptOptions.onRunSettlement`; a retained run A context never observes run B. Manual/unowned compaction, new-prompt preflight, harness-origin message events, and contexts without explicit run attribution return `undefined` (including command/input, provider hooks and separately constructed tool/shortcut contexts). `fromExtension` describes summary authorship, not ownership. See [SDK settlement outcomes](sdk.md#capturing-originating-run-settlement) and [automatic handoffs](compaction.md#originating-recovery-and-automatic-handoffs).
|
|
991
|
+
|
|
992
|
+
Capture during a hook, attach rejection handling immediately, return, and observe from an independent continuation. Awaiting its own completion inside an awaited gating hook deadlocks because classification/persistence needs that hook to return. Settlement is observation, not global quiescence, a lease, or permission to bypass admission. Revalidate context and application identity before subsequent guarded actions; stale runner contexts still throw. Missing capabilities in hand-built/unsupported contexts require an actionable pause, not a streaming-idle fallback.
|
|
993
|
+
|
|
994
|
+
### ctx.sendMessage(message, options?)
|
|
995
|
+
|
|
996
|
+
Optional async sender with the same message/options shapes as replacement-context `sendMessage()` and [pi.sendMessage()](#pisendmessagemessage-options). Session-bound runner contexts provide it; unsupported hand-built contexts may omit it. It delegates to the existing `AgentSession.sendCustomMessage` operation: streaming delivery and `nextTurn` resolve at queue acceptance; an immediate triggered turn waits for its run/retries; idle non-triggering delivery persists without starting a turn. `nextTurn` ignores `triggerTurn`. Asynchronous admission, launch and persistence failures reject; rejection does not prove artifact absence, so never blindly resend.
|
|
997
|
+
|
|
998
|
+
Do not await an immediate-turn send from an awaited gating hook whose return the turn needs. Return from that hook and await independently. The legacy `pi.sendMessage(): void` and its extension error channel remain unchanged; missing async sending must not silently fall back to void delivery.
|
|
999
|
+
|
|
988
1000
|
### ctx.isIdle() / ctx.abort() / ctx.hasPendingMessages()
|
|
989
1001
|
|
|
990
1002
|
Control flow helpers.
|
package/docs/sdk.md
CHANGED
|
@@ -200,6 +200,7 @@ interface PromptOptions {
|
|
|
200
200
|
streamingBehavior?: "steer" | "followUp";
|
|
201
201
|
source?: InputSource;
|
|
202
202
|
preflightResult?: (success: boolean) => void;
|
|
203
|
+
onRunSettlement?: (settlement: Promise<RunSettlement>) => void;
|
|
203
204
|
}
|
|
204
205
|
```
|
|
205
206
|
|
|
@@ -283,6 +284,8 @@ session.agent.state.tools = tools; // copies the top-level array
|
|
|
283
284
|
await session.agent.waitForIdle();
|
|
284
285
|
```
|
|
285
286
|
|
|
287
|
+
`session.agent.getRunExecution()` synchronously captures the active execution's `Promise<void>`, or returns `undefined` outside a run. It settles after runtime cleanup and rejects with any escaping `prompt()` / `continue()` failure, including final harness-drain failures. It preserves Agent's caught-error behavior and does not include Session recovery or persistence. `waitForIdle()` still resolves even when execution rejects. Capture in a listener and observe independently after the listener returns; awaiting the originating execution inside its own awaited listener deadlocks.
|
|
288
|
+
|
|
286
289
|
### Events
|
|
287
290
|
|
|
288
291
|
Subscribe to events to receive streaming output and lifecycle notifications.
|
|
@@ -465,6 +468,30 @@ AgentSession classifies the finalized persisted assistant snapshot. Built-in ada
|
|
|
465
468
|
|
|
466
469
|
Recognized incomplete responses can use the existing bounded agent retry loop; tools from a failed response do not execute. Provider/SDK retries remain a separate layer. See [settings.md](settings.md#retry) for numeric validation, zero semantics and Codex-only server-delay suppression, and [custom-provider.md](custom-provider.md#failure-evidence) for evidence precedence. Neither these attempt limits nor forwarding provider options guarantees a universal request-count or elapsed-time bound.
|
|
467
470
|
|
|
471
|
+
#### Capturing originating run settlement
|
|
472
|
+
|
|
473
|
+
`onRunSettlement` synchronously receives one stable promise after an immediate Agent run is reserved, before launch (including a delayed `agent_start`). It is not called for handled commands/input, explicit streaming queue acceptance, or rejected preflight. A command handler's separately launched custom turn is not adopted. New-prompt threshold maintenance is preflight, not part of an earlier run's capture.
|
|
474
|
+
|
|
475
|
+
The exported `RunSettlement` union has `status: "completed" | "failed" | "cancelled"`. Results retain the eligible finalized provider `assistantMessage` snapshot when available; failed results also carry `errorMessage`. Operational provider failure, exhausted/disabled retry, failed required overflow recovery, and cancellation resolve with their disposition. Persistence/infrastructure failure, disposal, capture-callback refusal, and launch without a start reject. Completion waits for terminal persistence/classification, originating execution unwind, bounded retries, and applicable automatic maintenance plus its selected continuation. Awaited public Agent-listener failures during execution unwind reject the uncancelled capture even after an earlier successful or retryable `agent_end`; cancellation retains its cancelled disposition. Retry backoff and unwind waiting run outside the Session event queue so caught-failure events can drain before continuation admission. Agent's existing caught-error behavior for `prompt()` is unchanged. It means execution recovered, not that the task or a Scramjet command completed.
|
|
476
|
+
|
|
477
|
+
```typescript
|
|
478
|
+
let captured: Promise<RunSettlement> | undefined;
|
|
479
|
+
await session.prompt("Continue the work", {
|
|
480
|
+
onRunSettlement(settlement) {
|
|
481
|
+
captured = settlement;
|
|
482
|
+
void settlement.catch((error) => console.error("Run settlement failed:", error));
|
|
483
|
+
},
|
|
484
|
+
});
|
|
485
|
+
if (captured) {
|
|
486
|
+
const outcome = await captured;
|
|
487
|
+
console.log(outcome.status);
|
|
488
|
+
}
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
Run-bound extension event contexts expose the exact same promise through optional `ctx.getRunSettlement()`, including matching owned automatic compaction hooks across retries/continuations. Manual/unowned maintenance and new-prompt preflight expose no originating capture; command/input handling and explicit queue acceptance do not borrow a previous run. A retained event context is bound to its original run, not a mutable latest-result lookup. Contexts from direct public `session.agent.prompt()` / `continue()` executions also wait for that execution's captured outcome and its queued classification before settling, rejecting escaping execution failures even when the idle wait resolves. Independently admitted harness work after that execution becomes idle does not delay its capture; those direct calls still bypass Session prompt preflight. Optional `ctx.sendMessage()` exposes existing asynchronous custom sending without changing void `pi.sendMessage`; see [context capabilities and deadlock cautions](extensions.md#ctxgetrunsettlement).
|
|
492
|
+
|
|
493
|
+
Import `RunSettlement` from `@leanandmean/coding-agent`. Attach rejection handling immediately and observe independently; the callback is notification, not an awaited consumer hook. Throwing from it rejects the reservation before launch and propagates through `prompt()`. Never await a run's own settlement from an awaited gating hook: classification needs that hook to return. Capture observes one originating run, not global idleness or an admission lease; retained captures never substitute later prompts or harness output. Revalidate session/context before subsequent guarded actions. `prompt()` remains `Promise<void>` with operational outcomes delivered separately rather than newly thrown provider failures.
|
|
494
|
+
|
|
468
495
|
### API Keys and OAuth
|
|
469
496
|
|
|
470
497
|
API key resolution priority (handled by AuthStorage):
|
package/docs/settings.md
CHANGED
|
@@ -119,6 +119,8 @@ Agent retries include validated missing-terminal Responses streams and accepted
|
|
|
119
119
|
|
|
120
120
|
Codex SSE honors `retry.provider.maxRetries` (default three) and rejects server-requested waits above `retry.provider.maxRetryDelayMs`, including after the final inner attempt. That rejection suppresses outer agent retries too. Set the delay cap to `0` to disable the policy cap; long representable waits remain cancellable, and unrepresentable waits fail without retry. Other SDKs do not necessarily implement this delay cap or these request controls; forwarding an option is not proof of enforcement.
|
|
121
121
|
|
|
122
|
+
The interactive countdown describes a recovery attempt, not final task completion. Escape cancels the originating recovery even between attempt completion and retry classification. Enter/Alt+Enter in non-streaming recovery retain your draft with a wait/cancel explanation; existing streaming and compaction queues stay explicit. Final cancellation/failure leaves the editor usable and tells you to review interrupted work before submitting again. Recovered execution is not a claim that the task completed. No additional retry setting or universal timeout is introduced.
|
|
123
|
+
|
|
122
124
|
Counts must be nonnegative safe integers; millisecond settings must be integers from 0 through 2,147,483,647. Invalid values generate scoped settings diagnostics and inherit a valid lower-priority value or the default without rewriting the file. Nested `retry.provider` leaves merge individually. Zero retries disables that layer's retries; zero base delay removes intentional backoff; timeout zero retains provider/SDK semantics and does not universally disable timeouts. Codex direct API callers receive a local validation failure for invalid retry options.
|
|
123
125
|
|
|
124
126
|
```json
|
|
@@ -16,6 +16,14 @@ The shared headless terminal feeds actual TUI writes into `@xterm/headless`; its
|
|
|
16
16
|
|
|
17
17
|
The native journey fixture is `packages/scramjet/tests/fixtures/interactive-viewport.mjs`. Hosted interaction and graphics drivers live in `.github/scripts/terminal-probe.py` and `.github/scripts/terminal-safety.py`; `.github/scripts/test-terminal-fixtures.py` exercises their evidence predicates. `.github/workflows/terminal-feasibility.yml` owns the hosted matrix. Build the runtime before running fixtures, because they load compiled packages. Windows desktop/clipboard execution through `.github/scripts/windows-terminal-probe.sh` requires separate explicit permission.
|
|
18
18
|
|
|
19
|
+
## Recovery input smoke — 2026-10-08
|
|
20
|
+
|
|
21
|
+
A separately authorized Windows Terminal 1.24.12741.0 / Windows build 22631 / WSL offline production InteractiveMode smoke ran against freshly built Stage 5 changes on the dirty working tree based on `08defe2b1e33b0505e9105d36858d241ac17aa60`. A disposable fixture used isolated in-memory settings, a synthetic provider, and the real terminal-indicator implementation; no paid calls, personal extensions, clipboard writes or terminal preference changes occurred.
|
|
22
|
+
|
|
23
|
+
Six targeted predicates passed: working title during retry backoff, native Enter draft retention, native Alt+Enter retention, Escape cancellation with an actionable outcome and waiting title, a subsequent successful prompt, and orderly exit. Screenshots confirmed the retained editor, retry countdown, attempt label, cancellation message and subsequent answer. Termios before/after matched; owned-window closure and pointer/focus restoration were verified. BEL timing is verified separately by deterministic indicator tests, not by this smoke (bell was disabled). The test window suppressed application title changes for safe identity-based ownership; emitted title values were recorded rather than asserting the visible window caption.
|
|
24
|
+
|
|
25
|
+
Reproduction: construct an isolated compiled InteractiveMode with one synthetic 503 attempt and ten-second backoff; use real desktop typing, Enter, Alt+Enter and Escape; submit deliberate new work and record input, editor, captured statuses, emitted titles and terminal restoration. Disposable probes reused the existing Windows driver's focus checks, screenshots and cleanup principles. Preliminary probes failed because the clean shell lacked Node on PATH and because fixture teardown ran inside stdin delivery; neither is acceptance evidence. The latter's test window was subsequently closed and the final probe deferred teardown beyond input delivery. The subsequent prompt retained the earlier draft alongside newly typed text; this was deliberately not a claim that Ctrl+A clears the editor. Linux/macOS/tmux, native audio/BEL, physical input devices and full-matrix acceptance were not rerun.
|
|
26
|
+
|
|
19
27
|
## Replacement right-click acceptance
|
|
20
28
|
|
|
21
29
|
The approved #608 / PR #610 scope replaces native Command+C interception with the existing application right-click interactions and removes the macOS shortcut/input Worker and its public capability. This intentionally supersedes the original native Command+C objective and acceptance criterion; it does not claim that objective was met by right-click. Right-click copies the last displayed application selection, or pastes into the eligible focused editor without submitting when there is no selection. Ctrl+C retains selected Copy versus ordinary editor/exit handling, and Command+V remains terminal paste. Command+C and terminal Copy menus remain terminal-owned, not application-selection Copy.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leanandmean/coding-agent",
|
|
3
|
-
"version": "0.74.1-scramjet.
|
|
3
|
+
"version": "0.74.1-scramjet.74",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
"test": "vitest --run --passWithNoTests"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@leanandmean/agent": "0.74.1-scramjet.
|
|
41
|
-
"@leanandmean/ai": "0.74.1-scramjet.
|
|
42
|
-
"@leanandmean/tui": "0.74.1-scramjet.
|
|
40
|
+
"@leanandmean/agent": "0.74.1-scramjet.53",
|
|
41
|
+
"@leanandmean/ai": "0.74.1-scramjet.49",
|
|
42
|
+
"@leanandmean/tui": "0.74.1-scramjet.46",
|
|
43
43
|
"@silvia-odwyer/photon-node": "^0.3.4",
|
|
44
44
|
"chalk": "^5.5.0",
|
|
45
45
|
"dictionary-en": "^4.0.0",
|