@dreb/coding-agent 2.19.0 → 2.19.1
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 +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +3 -2
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +3 -2
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +6 -5
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/buddy/buddy-controller.d.ts.map +1 -1
- package/dist/core/buddy/buddy-controller.js +3 -2
- package/dist/core/buddy/buddy-controller.js.map +1 -1
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js +2 -1
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/logger.d.ts +29 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +54 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +3 -2
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +25 -2
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/stderr-guard.d.ts +37 -0
- package/dist/core/stderr-guard.d.ts.map +1 -0
- package/dist/core/stderr-guard.js +90 -0
- package/dist/core/stderr-guard.js.map +1 -0
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js +5 -4
- package/dist/core/timings.js.map +1 -1
- package/dist/core/tools/subagent.d.ts.map +1 -1
- package/dist/core/tools/subagent.js +18 -17
- package/dist/core/tools/subagent.js.map +1 -1
- package/dist/core/tools/terminal-render.d.ts.map +1 -1
- package/dist/core/tools/terminal-render.js +2 -1
- package/dist/core/tools/terminal-render.js.map +1 -1
- package/dist/core/tools/web-search-queue.d.ts.map +1 -1
- package/dist/core/tools/web-search-queue.js +2 -1
- package/dist/core/tools/web-search-queue.js.map +1 -1
- package/dist/core/tools/web.d.ts.map +1 -1
- package/dist/core/tools/web.js +6 -5
- package/dist/core/tools/web.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +25 -24
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +5 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +32 -2
- 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 +3 -2
- package/dist/modes/print-mode.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"print-mode.d.ts","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAoB,YAAY,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"print-mode.d.ts","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAoB,YAAY,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAI7D;;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,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAoGpG","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `dreb -p \"prompt\"` - text output\n * - `dreb --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { AssistantMessage, ImageContent } from \"@dreb/ai\";\nimport type { AgentSession } from \"../core/agent-session.js\";\nimport { log } from \"../core/logger.js\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.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(session: AgentSession, options: PrintModeOptions): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\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\t\t// Set up extensions for print mode (no UI)\n\t\tawait session.bindExtensions({\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.agent.waitForIdle(),\n\t\t\t\tnewSession: async (options) => {\n\t\t\t\t\tconst success = await session.newSession({ parentSession: options?.parentSession });\n\t\t\t\t\tif (success && options?.setup) {\n\t\t\t\t\t\tawait options.setup(session.sessionManager);\n\t\t\t\t\t}\n\t\t\t\t\treturn { cancelled: !success };\n\t\t\t\t},\n\t\t\t\tfork: async (entryId) => {\n\t\t\t\t\tconst result = await session.fork(entryId);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, options) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: options?.summarize,\n\t\t\t\t\t\tcustomInstructions: options?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: options?.replaceInstructions,\n\t\t\t\t\t\tlabel: options?.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) => {\n\t\t\t\t\tconst success = await session.switchSession(sessionPath);\n\t\t\t\t\treturn { cancelled: !success };\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\tlog.warn(`Extension error (${err.extensionPath}): ${err.error}`);\n\t\t\t},\n\t\t});\n\n\t\t// Always subscribe to enable session persistence via _handleAgentEvent\n\t\tsession.subscribe((event) => {\n\t\t\t// In JSON mode, output all events\n\t\t\tif (mode === \"json\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event)}\\n`);\n\t\t\t}\n\t\t});\n\n\t\t// Send initial message with attachments\n\t\tif (initialMessage) {\n\t\t\tawait session.prompt(initialMessage, { images: initialImages });\n\t\t}\n\n\t\t// Send remaining messages\n\t\tfor (const message of messages) {\n\t\t\tawait session.prompt(message);\n\t\t}\n\n\t\t// In text mode, output final response\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\n\t\t\t\t// Check for error/aborted\n\t\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\t\tlog.error(assistantMsg.errorMessage || `Request ${assistantMsg.stopReason}`);\n\t\t\t\t\texitCode = 1;\n\t\t\t\t} else {\n\t\t\t\t\t// Output text content\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} finally {\n\t\tconst extensionRunner = session.extensionRunner;\n\t\tif (extensionRunner?.hasHandlers(\"session_shutdown\")) {\n\t\t\tawait extensionRunner.emit({ type: \"session_shutdown\" });\n\t\t}\n\n\t\t// Ensure stdout is fully flushed before returning\n\t\t// This prevents race conditions where the process exits before all output is written\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
|
package/dist/modes/print-mode.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* - `dreb -p "prompt"` - text output
|
|
6
6
|
* - `dreb --mode json "prompt"` - JSON event stream
|
|
7
7
|
*/
|
|
8
|
+
import { log } from "../core/logger.js";
|
|
8
9
|
import { flushRawStdout, writeRawStdout } from "../core/output-guard.js";
|
|
9
10
|
/**
|
|
10
11
|
* Run in print (single-shot) mode.
|
|
@@ -53,7 +54,7 @@ export async function runPrintMode(session, options) {
|
|
|
53
54
|
},
|
|
54
55
|
},
|
|
55
56
|
onError: (err) => {
|
|
56
|
-
|
|
57
|
+
log.warn(`Extension error (${err.extensionPath}): ${err.error}`);
|
|
57
58
|
},
|
|
58
59
|
});
|
|
59
60
|
// Always subscribe to enable session persistence via _handleAgentEvent
|
|
@@ -79,7 +80,7 @@ export async function runPrintMode(session, options) {
|
|
|
79
80
|
const assistantMsg = lastMessage;
|
|
80
81
|
// Check for error/aborted
|
|
81
82
|
if (assistantMsg.stopReason === "error" || assistantMsg.stopReason === "aborted") {
|
|
82
|
-
|
|
83
|
+
log.error(assistantMsg.errorMessage || `Request ${assistantMsg.stopReason}`);
|
|
83
84
|
exitCode = 1;
|
|
84
85
|
}
|
|
85
86
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"print-mode.js","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAgBzE;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAqB,EAAE,OAAyB,EAAmB;IACrG,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,EAAE,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;IACvE,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,IAAI,CAAC;QACJ,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACrB,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;YAClD,IAAI,MAAM,EAAE,CAAC;gBACZ,cAAc,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC/C,CAAC;QACF,CAAC;QACD,2CAA2C;QAC3C,MAAM,OAAO,CAAC,cAAc,CAAC;YAC5B,qBAAqB,EAAE;gBACtB,WAAW,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE;gBAC9C,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC;oBAC9B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC;oBACpF,IAAI,OAAO,IAAI,OAAO,EAAE,KAAK,EAAE,CAAC;wBAC/B,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;oBAC7C,CAAC;oBACD,OAAO,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC;gBAAA,CAC/B;gBACD,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC;oBACxB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;gBAAA,CACvC;gBACD,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC;oBAC1C,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,QAAQ,EAAE;wBACnD,SAAS,EAAE,OAAO,EAAE,SAAS;wBAC7B,kBAAkB,EAAE,OAAO,EAAE,kBAAkB;wBAC/C,mBAAmB,EAAE,OAAO,EAAE,mBAAmB;wBACjD,KAAK,EAAE,OAAO,EAAE,KAAK;qBACrB,CAAC,CAAC;oBACH,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;gBAAA,CACvC;gBACD,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC;oBACrC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;oBACzD,OAAO,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC;gBAAA,CAC/B;gBACD,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC;oBACnB,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;gBAAA,CACvB;aACD;YACD,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC;gBACjB,
|
|
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 * - `dreb -p \"prompt\"` - text output\n * - `dreb --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { AssistantMessage, ImageContent } from \"@dreb/ai\";\nimport type { AgentSession } from \"../core/agent-session.js\";\nimport { log } from \"../core/logger.js\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.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(session: AgentSession, options: PrintModeOptions): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\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\t\t// Set up extensions for print mode (no UI)\n\t\tawait session.bindExtensions({\n\t\t\tcommandContextActions: {\n\t\t\t\twaitForIdle: () => session.agent.waitForIdle(),\n\t\t\t\tnewSession: async (options) => {\n\t\t\t\t\tconst success = await session.newSession({ parentSession: options?.parentSession });\n\t\t\t\t\tif (success && options?.setup) {\n\t\t\t\t\t\tawait options.setup(session.sessionManager);\n\t\t\t\t\t}\n\t\t\t\t\treturn { cancelled: !success };\n\t\t\t\t},\n\t\t\t\tfork: async (entryId) => {\n\t\t\t\t\tconst result = await session.fork(entryId);\n\t\t\t\t\treturn { cancelled: result.cancelled };\n\t\t\t\t},\n\t\t\t\tnavigateTree: async (targetId, options) => {\n\t\t\t\t\tconst result = await session.navigateTree(targetId, {\n\t\t\t\t\t\tsummarize: options?.summarize,\n\t\t\t\t\t\tcustomInstructions: options?.customInstructions,\n\t\t\t\t\t\treplaceInstructions: options?.replaceInstructions,\n\t\t\t\t\t\tlabel: options?.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) => {\n\t\t\t\t\tconst success = await session.switchSession(sessionPath);\n\t\t\t\t\treturn { cancelled: !success };\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\tlog.warn(`Extension error (${err.extensionPath}): ${err.error}`);\n\t\t\t},\n\t\t});\n\n\t\t// Always subscribe to enable session persistence via _handleAgentEvent\n\t\tsession.subscribe((event) => {\n\t\t\t// In JSON mode, output all events\n\t\t\tif (mode === \"json\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event)}\\n`);\n\t\t\t}\n\t\t});\n\n\t\t// Send initial message with attachments\n\t\tif (initialMessage) {\n\t\t\tawait session.prompt(initialMessage, { images: initialImages });\n\t\t}\n\n\t\t// Send remaining messages\n\t\tfor (const message of messages) {\n\t\t\tawait session.prompt(message);\n\t\t}\n\n\t\t// In text mode, output final response\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\n\t\t\t\t// Check for error/aborted\n\t\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\t\tlog.error(assistantMsg.errorMessage || `Request ${assistantMsg.stopReason}`);\n\t\t\t\t\texitCode = 1;\n\t\t\t\t} else {\n\t\t\t\t\t// Output text content\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} finally {\n\t\tconst extensionRunner = session.extensionRunner;\n\t\tif (extensionRunner?.hasHandlers(\"session_shutdown\")) {\n\t\t\tawait extensionRunner.emit({ type: \"session_shutdown\" });\n\t\t}\n\n\t\t// Ensure stdout is fully flushed before returning\n\t\t// This prevents race conditions where the process exits before all output is written\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
|