@dreb/coding-agent 2.19.1 → 2.19.3
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 +2 -2
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +8 -5
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/thinking.d.ts +10 -0
- package/dist/core/thinking.d.ts.map +1 -0
- package/dist/core/thinking.js +14 -0
- package/dist/core/thinking.js.map +1 -0
- package/dist/core/tools/subagent.d.ts +3 -2
- package/dist/core/tools/subagent.d.ts.map +1 -1
- package/dist/core/tools/subagent.js +20 -10
- package/dist/core/tools/subagent.js.map +1 -1
- package/dist/core/tools/suggest-next.d.ts +2 -0
- package/dist/core/tools/suggest-next.d.ts.map +1 -1
- package/dist/core/tools/suggest-next.js +32 -12
- package/dist/core/tools/suggest-next.js.map +1 -1
- package/package.json +1 -1
|
@@ -4,14 +4,18 @@
|
|
|
4
4
|
* Allows the agent to suggest a command the user might want to run next.
|
|
5
5
|
* The suggestion is shown as ghost text in the editor prompt (Tab to accept).
|
|
6
6
|
*/
|
|
7
|
-
import { Text } from "@dreb/tui";
|
|
7
|
+
import { Container, Markdown, Text } from "@dreb/tui";
|
|
8
8
|
import { Type } from "@sinclair/typebox";
|
|
9
|
+
import { getMarkdownTheme } from "../../modes/interactive/theme/theme.js";
|
|
9
10
|
// ============================================================================
|
|
10
11
|
// Schema
|
|
11
12
|
const suggestNextSchema = Type.Object({
|
|
12
13
|
command: Type.String({
|
|
13
14
|
description: "The suggested command for the user to run next (e.g. /skill:mach6-push, /compact)",
|
|
14
15
|
}),
|
|
16
|
+
summary: Type.Optional(Type.String({
|
|
17
|
+
description: "Brief markdown summary of the work done this turn. Displayed to the user as the final message before the suggestion.",
|
|
18
|
+
})),
|
|
15
19
|
});
|
|
16
20
|
// ============================================================================
|
|
17
21
|
// Render helpers
|
|
@@ -19,14 +23,6 @@ function formatSuggestNextCall(args, theme) {
|
|
|
19
23
|
const cmd = args?.command ?? "";
|
|
20
24
|
return `${theme.fg("toolTitle", theme.bold("suggest_next"))} ${theme.fg("accent", cmd)}`;
|
|
21
25
|
}
|
|
22
|
-
function formatSuggestNextResult(result, theme) {
|
|
23
|
-
const details = result.details;
|
|
24
|
-
if (!details) {
|
|
25
|
-
const text = result.content?.[0];
|
|
26
|
-
return text?.type === "text" && text.text ? theme.fg("toolOutput", text.text) : "";
|
|
27
|
-
}
|
|
28
|
-
return theme.fg("toolOutput", `→ ${details.suggestion}`);
|
|
29
|
-
}
|
|
30
26
|
// ============================================================================
|
|
31
27
|
// Tool definition factory
|
|
32
28
|
export function createSuggestNextToolDefinition(onSuggest) {
|
|
@@ -41,8 +37,10 @@ export function createSuggestNextToolDefinition(onSuggest) {
|
|
|
41
37
|
"Use full command syntax: /skill:name args, /compact, etc.",
|
|
42
38
|
"Only suggest one command — pick the most likely next step",
|
|
43
39
|
"Don't suggest if the conversation is open-ended with no obvious next action",
|
|
40
|
+
"Include a brief summary of work done in the `summary` parameter — this is your last chance to communicate before the turn ends",
|
|
41
|
+
"Calling this tool ends your turn automatically — do not call wait afterwards",
|
|
44
42
|
],
|
|
45
|
-
async execute(_toolCallId, { command: rawCommand }, _signal, _onUpdate, _ctx) {
|
|
43
|
+
async execute(_toolCallId, { command: rawCommand, summary }, _signal, _onUpdate, _ctx) {
|
|
46
44
|
// Strip control characters (newlines, tabs, etc.) that would corrupt TUI rendering
|
|
47
45
|
const command = rawCommand?.replace(/[\x00-\x1f\x7f]/g, "").trim();
|
|
48
46
|
if (!command || !command.startsWith("/")) {
|
|
@@ -52,9 +50,16 @@ export function createSuggestNextToolDefinition(onSuggest) {
|
|
|
52
50
|
};
|
|
53
51
|
}
|
|
54
52
|
onSuggest(command);
|
|
53
|
+
// Convert literal \n sequences to actual newlines (LLMs emit these in XML tool calls),
|
|
54
|
+
// then strip control characters (preserve only newlines for markdown)
|
|
55
|
+
const sanitizedSummary = summary
|
|
56
|
+
?.replace(/\\n/g, "\n")
|
|
57
|
+
.replace(/[\x00-\x09\x0b-\x1f\x7f]/g, "")
|
|
58
|
+
.trim() || undefined;
|
|
55
59
|
return {
|
|
56
60
|
content: [{ type: "text", text: `Suggestion registered: ${command}` }],
|
|
57
|
-
details: { suggestion: command },
|
|
61
|
+
details: { suggestion: command, summary: sanitizedSummary },
|
|
62
|
+
endTurn: true,
|
|
58
63
|
};
|
|
59
64
|
},
|
|
60
65
|
renderCall(args, theme, context) {
|
|
@@ -63,8 +68,23 @@ export function createSuggestNextToolDefinition(onSuggest) {
|
|
|
63
68
|
return text;
|
|
64
69
|
},
|
|
65
70
|
renderResult(result, _options, theme, context) {
|
|
71
|
+
const details = result.details;
|
|
72
|
+
if (!details) {
|
|
73
|
+
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
74
|
+
const content = result.content?.[0];
|
|
75
|
+
const msg = content?.type === "text" && content.text ? content.text : "";
|
|
76
|
+
text.setText(theme.fg("toolOutput", msg));
|
|
77
|
+
return text;
|
|
78
|
+
}
|
|
79
|
+
if (details.summary) {
|
|
80
|
+
const container = context.lastComponent ?? new Container();
|
|
81
|
+
container.clear();
|
|
82
|
+
container.addChild(new Markdown(details.summary, 0, 0, getMarkdownTheme()));
|
|
83
|
+
container.addChild(new Text(theme.fg("toolOutput", `→ ${details.suggestion}`), 0, 0));
|
|
84
|
+
return container;
|
|
85
|
+
}
|
|
66
86
|
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
67
|
-
text.setText(
|
|
87
|
+
text.setText(theme.fg("toolOutput", `→ ${details.suggestion}`));
|
|
68
88
|
return text;
|
|
69
89
|
},
|
|
70
90
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suggest-next.js","sourceRoot":"","sources":["../../../src/core/tools/suggest-next.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"suggest-next.js","sourceRoot":"","sources":["../../../src/core/tools/suggest-next.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Suggest next command tool.\n *\n * Allows the agent to suggest a command the user might want to run next.\n * The suggestion is shown as ghost text in the editor prompt (Tab to accept).\n */\n\nimport { Container, Markdown, Text } from \"@dreb/tui\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { getMarkdownTheme } from \"../../modes/interactive/theme/theme.js\";\nimport type { ToolDefinition } from \"../extensions/types.js\";\n\n// ============================================================================\n// Types\n\nexport interface SuggestNextDetails {\n\tsuggestion: string;\n\tsummary?: string;\n}\n\nexport type SuggestNextCallback = (suggestion: string) => void;\n\n// ============================================================================\n// Schema\n\nconst suggestNextSchema = Type.Object({\n\tcommand: Type.String({\n\t\tdescription: \"The suggested command for the user to run next (e.g. /skill:mach6-push, /compact)\",\n\t}),\n\tsummary: Type.Optional(\n\t\tType.String({\n\t\t\tdescription:\n\t\t\t\t\"Brief markdown summary of the work done this turn. Displayed to the user as the final message before the suggestion.\",\n\t\t}),\n\t),\n});\n\nexport type SuggestNextInput = Static<typeof suggestNextSchema>;\n\n// ============================================================================\n// Render helpers\n\nfunction formatSuggestNextCall(args: { command?: string } | undefined, theme: any): string {\n\tconst cmd = args?.command ?? \"\";\n\treturn `${theme.fg(\"toolTitle\", theme.bold(\"suggest_next\"))} ${theme.fg(\"accent\", cmd)}`;\n}\n\n// ============================================================================\n// Tool definition factory\n\nexport function createSuggestNextToolDefinition(\n\tonSuggest: SuggestNextCallback,\n): ToolDefinition<typeof suggestNextSchema, SuggestNextDetails | undefined> {\n\treturn {\n\t\tname: \"suggest_next\",\n\t\tlabel: \"suggest_next\",\n\t\tdescription:\n\t\t\t\"Suggest a command for the user to run next. Shows as ghost text in the prompt that the user can Tab-accept.\",\n\n\t\tparameters: suggestNextSchema,\n\n\t\tpromptSnippet: \"Suggest a next command (shown as ghost text the user can Tab-accept)\",\n\n\t\tpromptGuidelines: [\n\t\t\t\"Call suggest_next at the end of your turn when there's a clear next action the user might want\",\n\t\t\t\"Use full command syntax: /skill:name args, /compact, etc.\",\n\t\t\t\"Only suggest one command — pick the most likely next step\",\n\t\t\t\"Don't suggest if the conversation is open-ended with no obvious next action\",\n\t\t\t\"Include a brief summary of work done in the `summary` parameter — this is your last chance to communicate before the turn ends\",\n\t\t\t\"Calling this tool ends your turn automatically — do not call wait afterwards\",\n\t\t],\n\n\t\tasync execute(_toolCallId, { command: rawCommand, summary }: SuggestNextInput, _signal?, _onUpdate?, _ctx?) {\n\t\t\t// Strip control characters (newlines, tabs, etc.) that would corrupt TUI rendering\n\t\t\tconst command = rawCommand?.replace(/[\\x00-\\x1f\\x7f]/g, \"\").trim();\n\t\t\tif (!command || !command.startsWith(\"/\")) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: \"Error: command must start with /\" }],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tonSuggest(command);\n\n\t\t\t// Convert literal \\n sequences to actual newlines (LLMs emit these in XML tool calls),\n\t\t\t// then strip control characters (preserve only newlines for markdown)\n\t\t\tconst sanitizedSummary =\n\t\t\t\tsummary\n\t\t\t\t\t?.replace(/\\\\n/g, \"\\n\")\n\t\t\t\t\t.replace(/[\\x00-\\x09\\x0b-\\x1f\\x7f]/g, \"\")\n\t\t\t\t\t.trim() || undefined;\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: `Suggestion registered: ${command}` }],\n\t\t\t\tdetails: { suggestion: command, summary: sanitizedSummary },\n\t\t\t\tendTurn: true,\n\t\t\t};\n\t\t},\n\n\t\trenderCall(args, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatSuggestNextCall(args, theme));\n\t\t\treturn text;\n\t\t},\n\n\t\trenderResult(result, _options, theme, context) {\n\t\t\tconst details = (result as any).details as SuggestNextDetails | undefined;\n\t\t\tif (!details) {\n\t\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\t\tconst content = result.content?.[0];\n\t\t\t\tconst msg = content?.type === \"text\" && content.text ? content.text : \"\";\n\t\t\t\ttext.setText(theme.fg(\"toolOutput\", msg));\n\t\t\t\treturn text;\n\t\t\t}\n\n\t\t\tif (details.summary) {\n\t\t\t\tconst container = (context.lastComponent as Container | undefined) ?? new Container();\n\t\t\t\tcontainer.clear();\n\t\t\t\tcontainer.addChild(new Markdown(details.summary, 0, 0, getMarkdownTheme()));\n\t\t\t\tcontainer.addChild(new Text(theme.fg(\"toolOutput\", `→ ${details.suggestion}`), 0, 0));\n\t\t\t\treturn container;\n\t\t\t}\n\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(theme.fg(\"toolOutput\", `→ ${details.suggestion}`));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n"]}
|