@caupulican/pi-adaptative 0.80.95 → 0.80.97
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/CHANGELOG.md +21 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +39 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/toolkit/reflex-interpreter.d.ts +28 -0
- package/dist/core/toolkit/reflex-interpreter.d.ts.map +1 -0
- package/dist/core/toolkit/reflex-interpreter.js +62 -0
- package/dist/core/toolkit/reflex-interpreter.js.map +1 -0
- package/dist/core/tools/run-toolkit-script.d.ts +8 -0
- package/dist/core/tools/run-toolkit-script.d.ts.map +1 -1
- package/dist/core/tools/run-toolkit-script.js +21 -3
- package/dist/core/tools/run-toolkit-script.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +7 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +147 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +12 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ToolkitScript } from "./script-registry.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Reflex interpreter (the BRAIN half of the user-ratified brain->muscle pipeline, statistically
|
|
4
|
+
* validated at 10/10 correct interpretations on the hard registry): a strict instruction
|
|
5
|
+
* interpreter that maps a fuzzy user request onto the toolkit registry. It NEVER executes
|
|
6
|
+
* anything — it only proposes `{script, args, danger, confidence}` for the deterministic
|
|
7
|
+
* executor path, which still enforces every safety rule (danger confirmation included).
|
|
8
|
+
*/
|
|
9
|
+
export declare const REFLEX_INTERPRETER_SYSTEM_PROMPT: string;
|
|
10
|
+
export interface ReflexPlan {
|
|
11
|
+
script: string;
|
|
12
|
+
args: string[];
|
|
13
|
+
danger: boolean;
|
|
14
|
+
confidence: number;
|
|
15
|
+
}
|
|
16
|
+
export declare const REFLEX_MIN_CONFIDENCE = 0.75;
|
|
17
|
+
export declare function buildReflexUserPrompt(request: string, scripts: readonly ToolkitScript[]): string;
|
|
18
|
+
export declare function parseReflexPlan(text: string): ReflexPlan | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Accept a plan only when it is confident AND names a real registry script ("none" and unknown
|
|
21
|
+
* names are honest refusals). The DANGER flag is never trusted from the plan — the registry's
|
|
22
|
+
* own flag governs confirmation, exactly as for a direct match.
|
|
23
|
+
*/
|
|
24
|
+
export declare function acceptReflexPlan(plan: ReflexPlan | undefined, scripts: readonly ToolkitScript[]): {
|
|
25
|
+
script: ToolkitScript;
|
|
26
|
+
args: string[];
|
|
27
|
+
} | undefined;
|
|
28
|
+
//# sourceMappingURL=reflex-interpreter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reflex-interpreter.d.ts","sourceRoot":"","sources":["../../../src/core/toolkit/reflex-interpreter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D;;;;;;GAMG;AAEH,eAAO,MAAM,gCAAgC,QAMjC,CAAC;AAEb,MAAM,WAAW,UAAU;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAE1C,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAKhG;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CA6BpE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC/B,IAAI,EAAE,UAAU,GAAG,SAAS,EAC5B,OAAO,EAAE,SAAS,aAAa,EAAE,GAC/B;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,SAAS,CAKvD","sourcesContent":["import type { ToolkitScript } from \"./script-registry.ts\";\n\n/**\n * Reflex interpreter (the BRAIN half of the user-ratified brain->muscle pipeline, statistically\n * validated at 10/10 correct interpretations on the hard registry): a strict instruction\n * interpreter that maps a fuzzy user request onto the toolkit registry. It NEVER executes\n * anything — it only proposes `{script, args, danger, confidence}` for the deterministic\n * executor path, which still enforces every safety rule (danger confirmation included).\n */\n\nexport const REFLEX_INTERPRETER_SYSTEM_PROMPT = [\n\t\"You are a strict instruction interpreter for a script executor. You NEVER execute anything.\",\n\t\"Given a user request and the script registry, output STRICT JSON only:\",\n\t'{\"script\":\"<exact registry name>\",\"args\":[\"...\"],\"danger\":true|false,\"confidence\":<0..1>}',\n\t\"Pick the single best script. Extract arguments exactly as the script expects. Mark danger from the registry.\",\n\t'If no script fits, output {\"script\":\"none\",\"args\":[],\"danger\":false,\"confidence\":0}.',\n].join(\"\\n\");\n\nexport interface ReflexPlan {\n\tscript: string;\n\targs: string[];\n\tdanger: boolean;\n\tconfidence: number;\n}\n\nexport const REFLEX_MIN_CONFIDENCE = 0.75;\n\nexport function buildReflexUserPrompt(request: string, scripts: readonly ToolkitScript[]): string {\n\tconst registry = scripts\n\t\t.map((script) => `${script.name}: ${script.description}${script.danger ? \" [DANGEROUS]\" : \"\"}`)\n\t\t.join(\"\\n\");\n\treturn `Registry:\\n${registry}\\n\\nRequest: ${request.slice(0, 2000)}`;\n}\n\nexport function parseReflexPlan(text: string): ReflexPlan | undefined {\n\tconst trimmed = text.trim();\n\t// Strip a leading think block some local models emit even with thinking off.\n\tconst thinkEnd = trimmed.indexOf(\"</think>\");\n\tconst body = thinkEnd >= 0 ? trimmed.slice(thinkEnd + 8) : trimmed;\n\tconst start = body.indexOf(\"{\");\n\tconst end = body.lastIndexOf(\"}\");\n\tif (start < 0 || end <= start) return undefined;\n\ttry {\n\t\tconst parsed = JSON.parse(body.slice(start, end + 1)) as {\n\t\t\tscript?: unknown;\n\t\t\targs?: unknown;\n\t\t\tdanger?: unknown;\n\t\t\tconfidence?: unknown;\n\t\t};\n\t\tif (typeof parsed.script !== \"string\" || parsed.script.length === 0) return undefined;\n\t\tconst confidence =\n\t\t\ttypeof parsed.confidence === \"number\" && Number.isFinite(parsed.confidence)\n\t\t\t\t? Math.max(0, Math.min(1, parsed.confidence))\n\t\t\t\t: 0;\n\t\treturn {\n\t\t\tscript: parsed.script,\n\t\t\targs: Array.isArray(parsed.args) ? parsed.args.filter((arg): arg is string => typeof arg === \"string\") : [],\n\t\t\tdanger: parsed.danger === true,\n\t\t\tconfidence,\n\t\t};\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Accept a plan only when it is confident AND names a real registry script (\"none\" and unknown\n * names are honest refusals). The DANGER flag is never trusted from the plan — the registry's\n * own flag governs confirmation, exactly as for a direct match.\n */\nexport function acceptReflexPlan(\n\tplan: ReflexPlan | undefined,\n\tscripts: readonly ToolkitScript[],\n): { script: ToolkitScript; args: string[] } | undefined {\n\tif (!plan || plan.confidence < REFLEX_MIN_CONFIDENCE) return undefined;\n\tconst script = scripts.find((entry) => entry.name === plan.script);\n\tif (!script) return undefined;\n\treturn { script, args: plan.args };\n}\n"]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reflex interpreter (the BRAIN half of the user-ratified brain->muscle pipeline, statistically
|
|
3
|
+
* validated at 10/10 correct interpretations on the hard registry): a strict instruction
|
|
4
|
+
* interpreter that maps a fuzzy user request onto the toolkit registry. It NEVER executes
|
|
5
|
+
* anything — it only proposes `{script, args, danger, confidence}` for the deterministic
|
|
6
|
+
* executor path, which still enforces every safety rule (danger confirmation included).
|
|
7
|
+
*/
|
|
8
|
+
export const REFLEX_INTERPRETER_SYSTEM_PROMPT = [
|
|
9
|
+
"You are a strict instruction interpreter for a script executor. You NEVER execute anything.",
|
|
10
|
+
"Given a user request and the script registry, output STRICT JSON only:",
|
|
11
|
+
'{"script":"<exact registry name>","args":["..."],"danger":true|false,"confidence":<0..1>}',
|
|
12
|
+
"Pick the single best script. Extract arguments exactly as the script expects. Mark danger from the registry.",
|
|
13
|
+
'If no script fits, output {"script":"none","args":[],"danger":false,"confidence":0}.',
|
|
14
|
+
].join("\n");
|
|
15
|
+
export const REFLEX_MIN_CONFIDENCE = 0.75;
|
|
16
|
+
export function buildReflexUserPrompt(request, scripts) {
|
|
17
|
+
const registry = scripts
|
|
18
|
+
.map((script) => `${script.name}: ${script.description}${script.danger ? " [DANGEROUS]" : ""}`)
|
|
19
|
+
.join("\n");
|
|
20
|
+
return `Registry:\n${registry}\n\nRequest: ${request.slice(0, 2000)}`;
|
|
21
|
+
}
|
|
22
|
+
export function parseReflexPlan(text) {
|
|
23
|
+
const trimmed = text.trim();
|
|
24
|
+
// Strip a leading think block some local models emit even with thinking off.
|
|
25
|
+
const thinkEnd = trimmed.indexOf("</think>");
|
|
26
|
+
const body = thinkEnd >= 0 ? trimmed.slice(thinkEnd + 8) : trimmed;
|
|
27
|
+
const start = body.indexOf("{");
|
|
28
|
+
const end = body.lastIndexOf("}");
|
|
29
|
+
if (start < 0 || end <= start)
|
|
30
|
+
return undefined;
|
|
31
|
+
try {
|
|
32
|
+
const parsed = JSON.parse(body.slice(start, end + 1));
|
|
33
|
+
if (typeof parsed.script !== "string" || parsed.script.length === 0)
|
|
34
|
+
return undefined;
|
|
35
|
+
const confidence = typeof parsed.confidence === "number" && Number.isFinite(parsed.confidence)
|
|
36
|
+
? Math.max(0, Math.min(1, parsed.confidence))
|
|
37
|
+
: 0;
|
|
38
|
+
return {
|
|
39
|
+
script: parsed.script,
|
|
40
|
+
args: Array.isArray(parsed.args) ? parsed.args.filter((arg) => typeof arg === "string") : [],
|
|
41
|
+
danger: parsed.danger === true,
|
|
42
|
+
confidence,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Accept a plan only when it is confident AND names a real registry script ("none" and unknown
|
|
51
|
+
* names are honest refusals). The DANGER flag is never trusted from the plan — the registry's
|
|
52
|
+
* own flag governs confirmation, exactly as for a direct match.
|
|
53
|
+
*/
|
|
54
|
+
export function acceptReflexPlan(plan, scripts) {
|
|
55
|
+
if (!plan || plan.confidence < REFLEX_MIN_CONFIDENCE)
|
|
56
|
+
return undefined;
|
|
57
|
+
const script = scripts.find((entry) => entry.name === plan.script);
|
|
58
|
+
if (!script)
|
|
59
|
+
return undefined;
|
|
60
|
+
return { script, args: plan.args };
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=reflex-interpreter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reflex-interpreter.js","sourceRoot":"","sources":["../../../src/core/toolkit/reflex-interpreter.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,gCAAgC,GAAG;IAC/C,6FAA6F;IAC7F,wEAAwE;IACxE,2FAA2F;IAC3F,8GAA8G;IAC9G,sFAAsF;CACtF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AASb,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAE1C,MAAM,UAAU,qBAAqB,CAAC,OAAe,EAAE,OAAiC,EAAU;IACjG,MAAM,QAAQ,GAAG,OAAO;SACtB,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;SAC9F,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,OAAO,cAAc,QAAQ,gBAAgB,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC;AAAA,CACtE;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAA0B;IACrE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,6EAA6E;IAC7E,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACnE,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,KAAK;QAAE,OAAO,SAAS,CAAC;IAChD,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAKnD,CAAC;QACF,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QACtF,MAAM,UAAU,GACf,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC;YAC1E,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;YAC7C,CAAC,CAAC,CAAC,CAAC;QACN,OAAO;YACN,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAiB,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;YAC3G,MAAM,EAAE,MAAM,CAAC,MAAM,KAAK,IAAI;YAC9B,UAAU;SACV,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AAAA,CACD;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC/B,IAA4B,EAC5B,OAAiC,EACuB;IACxD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,GAAG,qBAAqB;QAAE,OAAO,SAAS,CAAC;IACvE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC;IACnE,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;AAAA,CACnC","sourcesContent":["import type { ToolkitScript } from \"./script-registry.ts\";\n\n/**\n * Reflex interpreter (the BRAIN half of the user-ratified brain->muscle pipeline, statistically\n * validated at 10/10 correct interpretations on the hard registry): a strict instruction\n * interpreter that maps a fuzzy user request onto the toolkit registry. It NEVER executes\n * anything — it only proposes `{script, args, danger, confidence}` for the deterministic\n * executor path, which still enforces every safety rule (danger confirmation included).\n */\n\nexport const REFLEX_INTERPRETER_SYSTEM_PROMPT = [\n\t\"You are a strict instruction interpreter for a script executor. You NEVER execute anything.\",\n\t\"Given a user request and the script registry, output STRICT JSON only:\",\n\t'{\"script\":\"<exact registry name>\",\"args\":[\"...\"],\"danger\":true|false,\"confidence\":<0..1>}',\n\t\"Pick the single best script. Extract arguments exactly as the script expects. Mark danger from the registry.\",\n\t'If no script fits, output {\"script\":\"none\",\"args\":[],\"danger\":false,\"confidence\":0}.',\n].join(\"\\n\");\n\nexport interface ReflexPlan {\n\tscript: string;\n\targs: string[];\n\tdanger: boolean;\n\tconfidence: number;\n}\n\nexport const REFLEX_MIN_CONFIDENCE = 0.75;\n\nexport function buildReflexUserPrompt(request: string, scripts: readonly ToolkitScript[]): string {\n\tconst registry = scripts\n\t\t.map((script) => `${script.name}: ${script.description}${script.danger ? \" [DANGEROUS]\" : \"\"}`)\n\t\t.join(\"\\n\");\n\treturn `Registry:\\n${registry}\\n\\nRequest: ${request.slice(0, 2000)}`;\n}\n\nexport function parseReflexPlan(text: string): ReflexPlan | undefined {\n\tconst trimmed = text.trim();\n\t// Strip a leading think block some local models emit even with thinking off.\n\tconst thinkEnd = trimmed.indexOf(\"</think>\");\n\tconst body = thinkEnd >= 0 ? trimmed.slice(thinkEnd + 8) : trimmed;\n\tconst start = body.indexOf(\"{\");\n\tconst end = body.lastIndexOf(\"}\");\n\tif (start < 0 || end <= start) return undefined;\n\ttry {\n\t\tconst parsed = JSON.parse(body.slice(start, end + 1)) as {\n\t\t\tscript?: unknown;\n\t\t\targs?: unknown;\n\t\t\tdanger?: unknown;\n\t\t\tconfidence?: unknown;\n\t\t};\n\t\tif (typeof parsed.script !== \"string\" || parsed.script.length === 0) return undefined;\n\t\tconst confidence =\n\t\t\ttypeof parsed.confidence === \"number\" && Number.isFinite(parsed.confidence)\n\t\t\t\t? Math.max(0, Math.min(1, parsed.confidence))\n\t\t\t\t: 0;\n\t\treturn {\n\t\t\tscript: parsed.script,\n\t\t\targs: Array.isArray(parsed.args) ? parsed.args.filter((arg): arg is string => typeof arg === \"string\") : [],\n\t\t\tdanger: parsed.danger === true,\n\t\t\tconfidence,\n\t\t};\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Accept a plan only when it is confident AND names a real registry script (\"none\" and unknown\n * names are honest refusals). The DANGER flag is never trusted from the plan — the registry's\n * own flag governs confirmation, exactly as for a direct match.\n */\nexport function acceptReflexPlan(\n\tplan: ReflexPlan | undefined,\n\tscripts: readonly ToolkitScript[],\n): { script: ToolkitScript; args: string[] } | undefined {\n\tif (!plan || plan.confidence < REFLEX_MIN_CONFIDENCE) return undefined;\n\tconst script = scripts.find((entry) => entry.name === plan.script);\n\tif (!script) return undefined;\n\treturn { script, args: plan.args };\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type Static, Type } from "typebox";
|
|
2
2
|
import type { ToolDefinition } from "../extensions/types.ts";
|
|
3
|
+
import { type ReflexPlan } from "../toolkit/reflex-interpreter.ts";
|
|
3
4
|
import { type ToolkitScript } from "../toolkit/script-registry.ts";
|
|
4
5
|
import type { ScriptExecution } from "../toolkit/script-runner.ts";
|
|
5
6
|
declare const runToolkitScriptSchema: Type.TObject<{
|
|
@@ -18,6 +19,13 @@ export interface RunToolkitScriptDetails {
|
|
|
18
19
|
export interface RunToolkitScriptDependencies {
|
|
19
20
|
getScripts: () => ToolkitScript[];
|
|
20
21
|
execute: (script: ToolkitScript, args: readonly string[]) => Promise<ScriptExecution>;
|
|
22
|
+
/**
|
|
23
|
+
* Optional reflex interpreter (local brain): consulted ONLY when the deterministic Level-0
|
|
24
|
+
* matcher is ambiguous, to resolve fuzzy phrasing ("prepare db" vs "update db") into a
|
|
25
|
+
* registry pick. Its plan is advisory — the danger/confirm rules and structural execution
|
|
26
|
+
* contract apply identically to brain-selected scripts.
|
|
27
|
+
*/
|
|
28
|
+
interpret?: (request: string, scripts: readonly ToolkitScript[]) => Promise<ReflexPlan | undefined>;
|
|
21
29
|
}
|
|
22
30
|
export declare function createRunToolkitScriptToolDefinition(deps: RunToolkitScriptDependencies): ToolDefinition;
|
|
23
31
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-toolkit-script.d.ts","sourceRoot":"","sources":["../../../src/core/tools/run-toolkit-script.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,QAAA,MAAM,sBAAsB;;;;EAc3B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE1E,MAAM,WAAW,uBAAuB;IACvC,OAAO,EAAE,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,GAAG,uBAAuB,GAAG,gBAAgB,CAAC;IACxG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,4BAA4B;IAC5C,UAAU,EAAE,MAAM,aAAa,EAAE,CAAC;IAClC,OAAO,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"run-toolkit-script.d.ts","sourceRoot":"","sources":["../../../src/core/tools/run-toolkit-script.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,QAAA,MAAM,sBAAsB;;;;EAc3B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE1E,MAAM,WAAW,uBAAuB;IACvC,OAAO,EAAE,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,GAAG,uBAAuB,GAAG,gBAAgB,CAAC;IACxG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,4BAA4B;IAC5C,UAAU,EAAE,MAAM,aAAa,EAAE,CAAC;IAClC,OAAO,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IACtF;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,aAAa,EAAE,KAAK,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;CACpG;AAMD,wBAAgB,oCAAoC,CAAC,IAAI,EAAE,4BAA4B,GAAG,cAAc,CAmHvG","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport { acceptReflexPlan, type ReflexPlan } from \"../toolkit/reflex-interpreter.ts\";\nimport { matchToolkitScript, type ToolkitScript } from \"../toolkit/script-registry.ts\";\nimport type { ScriptExecution } from \"../toolkit/script-runner.ts\";\n\nconst runToolkitScriptSchema = Type.Object(\n\t{\n\t\tscript: Type.String({\n\t\t\tdescription:\n\t\t\t\t\"The toolkit script to run: its registered name, a taught alias, or a natural request (e.g. 'restore-db' or 'restore the database'). Ambiguous requests return a shortlist instead of executing.\",\n\t\t}),\n\t\targs: Type.Optional(Type.Array(Type.String(), { description: \"Arguments passed to the script as-is.\" })),\n\t\tconfirm: Type.Optional(\n\t\t\tType.Boolean({\n\t\t\t\tdescription: \"Required true to run a script flagged danger: scripts marked dangerous never run without it.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type RunToolkitScriptInput = Static<typeof runToolkitScriptSchema>;\n\nexport interface RunToolkitScriptDetails {\n\toutcome: \"executed\" | \"failed\" | \"ambiguous\" | \"not_found\" | \"confirmation_required\" | \"empty_registry\";\n\tscriptName?: string;\n\texitCode?: number | null;\n\tdurationMs?: number;\n\tshortlist?: string[];\n}\n\nexport interface RunToolkitScriptDependencies {\n\tgetScripts: () => ToolkitScript[];\n\texecute: (script: ToolkitScript, args: readonly string[]) => Promise<ScriptExecution>;\n\t/**\n\t * Optional reflex interpreter (local brain): consulted ONLY when the deterministic Level-0\n\t * matcher is ambiguous, to resolve fuzzy phrasing (\"prepare db\" vs \"update db\") into a\n\t * registry pick. Its plan is advisory — the danger/confirm rules and structural execution\n\t * contract apply identically to brain-selected scripts.\n\t */\n\tinterpret?: (request: string, scripts: readonly ToolkitScript[]) => Promise<ReflexPlan | undefined>;\n}\n\nfunction boundedOutput(text: string, maxChars = 4000): string {\n\treturn text.length <= maxChars ? text : `${text.slice(0, maxChars)}\\n… (truncated)`;\n}\n\nexport function createRunToolkitScriptToolDefinition(deps: RunToolkitScriptDependencies): ToolDefinition {\n\treturn {\n\t\tname: \"run_toolkit_script\",\n\t\tlabel: \"run_toolkit_script\",\n\t\tdescription:\n\t\t\t\"Run one of the user's registered toolkit scripts (daily-ops allowlist). Finding is a registry lookup — ambiguous requests return a shortlist to disambiguate, never a guess. The harness executes (uv/powershell/bash) and ALWAYS returns exit code, stdout, and stderr; failures are reported as errors — a failed script can never look like success.\",\n\t\tpromptSnippet: \"Run a registered toolkit script by name/alias; output and errors come back structurally.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Prefer the exact registered name; on a shortlist response, ask the user which one (or pick only when their request clearly names it).\",\n\t\t\t\"Scripts flagged dangerous require confirm: true — obtain explicit user confirmation first.\",\n\t\t\t\"Report the script's real output/exit code; never claim success when exitCode is non-zero.\",\n\t\t],\n\t\tparameters: runToolkitScriptSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\tinput: RunToolkitScriptInput,\n\t\t): Promise<{\n\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\tdetails: RunToolkitScriptDetails;\n\t\t\tisError?: boolean;\n\t\t}> {\n\t\t\tconst scripts = deps.getScripts();\n\t\t\tif (scripts.length === 0) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: \"run_toolkit_script: no scripts registered (settings.toolkit.scripts).\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { outcome: \"empty_registry\" },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst match = matchToolkitScript(input.script, scripts);\n\t\t\tif (match.kind === \"none\") {\n\t\t\t\tconst closest = match.closest.map((script) => `${script.name} — ${script.description}`).join(\"\\n\");\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: `script_not_found: nothing registered matches \"${input.script}\".${closest ? `\\nClosest:\\n${closest}` : \"\"}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { outcome: \"not_found\" },\n\t\t\t\t\tisError: true,\n\t\t\t\t};\n\t\t\t}\n\t\t\tlet interpreted: { script: ToolkitScript; args: string[]; confidence: number } | undefined;\n\t\t\tif (match.kind === \"ambiguous\" && deps.interpret) {\n\t\t\t\ttry {\n\t\t\t\t\tconst plan = await deps.interpret(input.script, scripts);\n\t\t\t\t\tconst accepted = acceptReflexPlan(plan, scripts);\n\t\t\t\t\tif (accepted && plan) {\n\t\t\t\t\t\tinterpreted = { ...accepted, confidence: plan.confidence };\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// interpreter is best-effort; ambiguity handling below stays authoritative\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (match.kind === \"ambiguous\" && !interpreted) {\n\t\t\t\tconst shortlist = match.shortlist.map((script) => `${script.name} — ${script.description}`);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: `Ambiguous request — did you mean:\\n${shortlist.join(\"\\n\")}\\nCall again with the exact name.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { outcome: \"ambiguous\", shortlist: match.shortlist.map((script) => script.name) },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst script = interpreted?.script ?? (match as { script: ToolkitScript }).script;\n\t\t\tif (script.danger && input.confirm !== true) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: `\"${script.name}\" is flagged DANGEROUS (${script.description}). It was NOT run. Confirm with the user, then call again with confirm: true.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { outcome: \"confirmation_required\", scriptName: script.name },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Explicit args from the caller win; a brain-extracted arg list fills in for fuzzy requests.\n\t\t\tconst execution = await deps.execute(script, input.args ?? interpreted?.args ?? []);\n\t\t\tconst failed = execution.exitCode !== 0 || execution.timedOut;\n\t\t\tconst header = failed\n\t\t\t\t? `FAILED: ${script.name} exited ${execution.timedOut ? \"by timeout\" : execution.exitCode} after ${execution.durationMs}ms`\n\t\t\t\t: `${script.name} succeeded in ${execution.durationMs}ms`;\n\t\t\tconst body = [\n\t\t\t\theader,\n\t\t\t\texecution.stdout.trim() ? `stdout:\\n${boundedOutput(execution.stdout.trim())}` : \"stdout: (empty)\",\n\t\t\t\texecution.stderr.trim() ? `stderr:\\n${boundedOutput(execution.stderr.trim())}` : \"\",\n\t\t\t]\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(\"\\n\");\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: body }],\n\t\t\t\tdetails: {\n\t\t\t\t\t...(interpreted\n\t\t\t\t\t\t? { interpreter: { script: interpreted.script.name, confidence: interpreted.confidence } }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\toutcome: failed ? \"failed\" : \"executed\",\n\t\t\t\t\tscriptName: script.name,\n\t\t\t\t\texitCode: execution.exitCode,\n\t\t\t\t\tdurationMs: execution.durationMs,\n\t\t\t\t},\n\t\t\t\t...(failed ? { isError: true } : {}),\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
|
+
import { acceptReflexPlan } from "../toolkit/reflex-interpreter.js";
|
|
2
3
|
import { matchToolkitScript } from "../toolkit/script-registry.js";
|
|
3
4
|
const runToolkitScriptSchema = Type.Object({
|
|
4
5
|
script: Type.String({
|
|
@@ -51,7 +52,20 @@ export function createRunToolkitScriptToolDefinition(deps) {
|
|
|
51
52
|
isError: true,
|
|
52
53
|
};
|
|
53
54
|
}
|
|
54
|
-
|
|
55
|
+
let interpreted;
|
|
56
|
+
if (match.kind === "ambiguous" && deps.interpret) {
|
|
57
|
+
try {
|
|
58
|
+
const plan = await deps.interpret(input.script, scripts);
|
|
59
|
+
const accepted = acceptReflexPlan(plan, scripts);
|
|
60
|
+
if (accepted && plan) {
|
|
61
|
+
interpreted = { ...accepted, confidence: plan.confidence };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// interpreter is best-effort; ambiguity handling below stays authoritative
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (match.kind === "ambiguous" && !interpreted) {
|
|
55
69
|
const shortlist = match.shortlist.map((script) => `${script.name} — ${script.description}`);
|
|
56
70
|
return {
|
|
57
71
|
content: [
|
|
@@ -63,7 +77,7 @@ export function createRunToolkitScriptToolDefinition(deps) {
|
|
|
63
77
|
details: { outcome: "ambiguous", shortlist: match.shortlist.map((script) => script.name) },
|
|
64
78
|
};
|
|
65
79
|
}
|
|
66
|
-
const script = match.script;
|
|
80
|
+
const script = interpreted?.script ?? match.script;
|
|
67
81
|
if (script.danger && input.confirm !== true) {
|
|
68
82
|
return {
|
|
69
83
|
content: [
|
|
@@ -75,7 +89,8 @@ export function createRunToolkitScriptToolDefinition(deps) {
|
|
|
75
89
|
details: { outcome: "confirmation_required", scriptName: script.name },
|
|
76
90
|
};
|
|
77
91
|
}
|
|
78
|
-
|
|
92
|
+
// Explicit args from the caller win; a brain-extracted arg list fills in for fuzzy requests.
|
|
93
|
+
const execution = await deps.execute(script, input.args ?? interpreted?.args ?? []);
|
|
79
94
|
const failed = execution.exitCode !== 0 || execution.timedOut;
|
|
80
95
|
const header = failed
|
|
81
96
|
? `FAILED: ${script.name} exited ${execution.timedOut ? "by timeout" : execution.exitCode} after ${execution.durationMs}ms`
|
|
@@ -90,6 +105,9 @@ export function createRunToolkitScriptToolDefinition(deps) {
|
|
|
90
105
|
return {
|
|
91
106
|
content: [{ type: "text", text: body }],
|
|
92
107
|
details: {
|
|
108
|
+
...(interpreted
|
|
109
|
+
? { interpreter: { script: interpreted.script.name, confidence: interpreted.confidence } }
|
|
110
|
+
: {}),
|
|
93
111
|
outcome: failed ? "failed" : "executed",
|
|
94
112
|
scriptName: script.name,
|
|
95
113
|
exitCode: execution.exitCode,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-toolkit-script.js","sourceRoot":"","sources":["../../../src/core/tools/run-toolkit-script.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport { matchToolkitScript, type ToolkitScript } from \"../toolkit/script-registry.ts\";\nimport type { ScriptExecution } from \"../toolkit/script-runner.ts\";\n\nconst runToolkitScriptSchema = Type.Object(\n\t{\n\t\tscript: Type.String({\n\t\t\tdescription:\n\t\t\t\t\"The toolkit script to run: its registered name, a taught alias, or a natural request (e.g. 'restore-db' or 'restore the database'). Ambiguous requests return a shortlist instead of executing.\",\n\t\t}),\n\t\targs: Type.Optional(Type.Array(Type.String(), { description: \"Arguments passed to the script as-is.\" })),\n\t\tconfirm: Type.Optional(\n\t\t\tType.Boolean({\n\t\t\t\tdescription: \"Required true to run a script flagged danger: scripts marked dangerous never run without it.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type RunToolkitScriptInput = Static<typeof runToolkitScriptSchema>;\n\nexport interface RunToolkitScriptDetails {\n\toutcome: \"executed\" | \"failed\" | \"ambiguous\" | \"not_found\" | \"confirmation_required\" | \"empty_registry\";\n\tscriptName?: string;\n\texitCode?: number | null;\n\tdurationMs?: number;\n\tshortlist?: string[];\n}\n\nexport interface RunToolkitScriptDependencies {\n\tgetScripts: () => ToolkitScript[];\n\texecute: (script: ToolkitScript, args: readonly string[]) => Promise<ScriptExecution>;\n}\n\nfunction boundedOutput(text: string, maxChars = 4000): string {\n\treturn text.length <= maxChars ? text : `${text.slice(0, maxChars)}\\n… (truncated)`;\n}\n\nexport function createRunToolkitScriptToolDefinition(deps: RunToolkitScriptDependencies): ToolDefinition {\n\treturn {\n\t\tname: \"run_toolkit_script\",\n\t\tlabel: \"run_toolkit_script\",\n\t\tdescription:\n\t\t\t\"Run one of the user's registered toolkit scripts (daily-ops allowlist). Finding is a registry lookup — ambiguous requests return a shortlist to disambiguate, never a guess. The harness executes (uv/powershell/bash) and ALWAYS returns exit code, stdout, and stderr; failures are reported as errors — a failed script can never look like success.\",\n\t\tpromptSnippet: \"Run a registered toolkit script by name/alias; output and errors come back structurally.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Prefer the exact registered name; on a shortlist response, ask the user which one (or pick only when their request clearly names it).\",\n\t\t\t\"Scripts flagged dangerous require confirm: true — obtain explicit user confirmation first.\",\n\t\t\t\"Report the script's real output/exit code; never claim success when exitCode is non-zero.\",\n\t\t],\n\t\tparameters: runToolkitScriptSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\tinput: RunToolkitScriptInput,\n\t\t): Promise<{\n\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\tdetails: RunToolkitScriptDetails;\n\t\t\tisError?: boolean;\n\t\t}> {\n\t\t\tconst scripts = deps.getScripts();\n\t\t\tif (scripts.length === 0) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: \"run_toolkit_script: no scripts registered (settings.toolkit.scripts).\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { outcome: \"empty_registry\" },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst match = matchToolkitScript(input.script, scripts);\n\t\t\tif (match.kind === \"none\") {\n\t\t\t\tconst closest = match.closest.map((script) => `${script.name} — ${script.description}`).join(\"\\n\");\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: `script_not_found: nothing registered matches \"${input.script}\".${closest ? `\\nClosest:\\n${closest}` : \"\"}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { outcome: \"not_found\" },\n\t\t\t\t\tisError: true,\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (match.kind === \"ambiguous\") {\n\t\t\t\tconst shortlist = match.shortlist.map((script) => `${script.name} — ${script.description}`);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: `Ambiguous request — did you mean:\\n${shortlist.join(\"\\n\")}\\nCall again with the exact name.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { outcome: \"ambiguous\", shortlist: match.shortlist.map((script) => script.name) },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst script = match.script;\n\t\t\tif (script.danger && input.confirm !== true) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: `\"${script.name}\" is flagged DANGEROUS (${script.description}). It was NOT run. Confirm with the user, then call again with confirm: true.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { outcome: \"confirmation_required\", scriptName: script.name },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst execution = await deps.execute(script, input.args ?? []);\n\t\t\tconst failed = execution.exitCode !== 0 || execution.timedOut;\n\t\t\tconst header = failed\n\t\t\t\t? `FAILED: ${script.name} exited ${execution.timedOut ? \"by timeout\" : execution.exitCode} after ${execution.durationMs}ms`\n\t\t\t\t: `${script.name} succeeded in ${execution.durationMs}ms`;\n\t\t\tconst body = [\n\t\t\t\theader,\n\t\t\t\texecution.stdout.trim() ? `stdout:\\n${boundedOutput(execution.stdout.trim())}` : \"stdout: (empty)\",\n\t\t\t\texecution.stderr.trim() ? `stderr:\\n${boundedOutput(execution.stderr.trim())}` : \"\",\n\t\t\t]\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(\"\\n\");\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: body }],\n\t\t\t\tdetails: {\n\t\t\t\t\toutcome: failed ? \"failed\" : \"executed\",\n\t\t\t\t\tscriptName: script.name,\n\t\t\t\t\texitCode: execution.exitCode,\n\t\t\t\t\tdurationMs: execution.durationMs,\n\t\t\t\t},\n\t\t\t\t...(failed ? { isError: true } : {}),\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"run-toolkit-script.js","sourceRoot":"","sources":["../../../src/core/tools/run-toolkit-script.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport { acceptReflexPlan, type ReflexPlan } from \"../toolkit/reflex-interpreter.ts\";\nimport { matchToolkitScript, type ToolkitScript } from \"../toolkit/script-registry.ts\";\nimport type { ScriptExecution } from \"../toolkit/script-runner.ts\";\n\nconst runToolkitScriptSchema = Type.Object(\n\t{\n\t\tscript: Type.String({\n\t\t\tdescription:\n\t\t\t\t\"The toolkit script to run: its registered name, a taught alias, or a natural request (e.g. 'restore-db' or 'restore the database'). Ambiguous requests return a shortlist instead of executing.\",\n\t\t}),\n\t\targs: Type.Optional(Type.Array(Type.String(), { description: \"Arguments passed to the script as-is.\" })),\n\t\tconfirm: Type.Optional(\n\t\t\tType.Boolean({\n\t\t\t\tdescription: \"Required true to run a script flagged danger: scripts marked dangerous never run without it.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type RunToolkitScriptInput = Static<typeof runToolkitScriptSchema>;\n\nexport interface RunToolkitScriptDetails {\n\toutcome: \"executed\" | \"failed\" | \"ambiguous\" | \"not_found\" | \"confirmation_required\" | \"empty_registry\";\n\tscriptName?: string;\n\texitCode?: number | null;\n\tdurationMs?: number;\n\tshortlist?: string[];\n}\n\nexport interface RunToolkitScriptDependencies {\n\tgetScripts: () => ToolkitScript[];\n\texecute: (script: ToolkitScript, args: readonly string[]) => Promise<ScriptExecution>;\n\t/**\n\t * Optional reflex interpreter (local brain): consulted ONLY when the deterministic Level-0\n\t * matcher is ambiguous, to resolve fuzzy phrasing (\"prepare db\" vs \"update db\") into a\n\t * registry pick. Its plan is advisory — the danger/confirm rules and structural execution\n\t * contract apply identically to brain-selected scripts.\n\t */\n\tinterpret?: (request: string, scripts: readonly ToolkitScript[]) => Promise<ReflexPlan | undefined>;\n}\n\nfunction boundedOutput(text: string, maxChars = 4000): string {\n\treturn text.length <= maxChars ? text : `${text.slice(0, maxChars)}\\n… (truncated)`;\n}\n\nexport function createRunToolkitScriptToolDefinition(deps: RunToolkitScriptDependencies): ToolDefinition {\n\treturn {\n\t\tname: \"run_toolkit_script\",\n\t\tlabel: \"run_toolkit_script\",\n\t\tdescription:\n\t\t\t\"Run one of the user's registered toolkit scripts (daily-ops allowlist). Finding is a registry lookup — ambiguous requests return a shortlist to disambiguate, never a guess. The harness executes (uv/powershell/bash) and ALWAYS returns exit code, stdout, and stderr; failures are reported as errors — a failed script can never look like success.\",\n\t\tpromptSnippet: \"Run a registered toolkit script by name/alias; output and errors come back structurally.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Prefer the exact registered name; on a shortlist response, ask the user which one (or pick only when their request clearly names it).\",\n\t\t\t\"Scripts flagged dangerous require confirm: true — obtain explicit user confirmation first.\",\n\t\t\t\"Report the script's real output/exit code; never claim success when exitCode is non-zero.\",\n\t\t],\n\t\tparameters: runToolkitScriptSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\tinput: RunToolkitScriptInput,\n\t\t): Promise<{\n\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\tdetails: RunToolkitScriptDetails;\n\t\t\tisError?: boolean;\n\t\t}> {\n\t\t\tconst scripts = deps.getScripts();\n\t\t\tif (scripts.length === 0) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: \"run_toolkit_script: no scripts registered (settings.toolkit.scripts).\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { outcome: \"empty_registry\" },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst match = matchToolkitScript(input.script, scripts);\n\t\t\tif (match.kind === \"none\") {\n\t\t\t\tconst closest = match.closest.map((script) => `${script.name} — ${script.description}`).join(\"\\n\");\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: `script_not_found: nothing registered matches \"${input.script}\".${closest ? `\\nClosest:\\n${closest}` : \"\"}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { outcome: \"not_found\" },\n\t\t\t\t\tisError: true,\n\t\t\t\t};\n\t\t\t}\n\t\t\tlet interpreted: { script: ToolkitScript; args: string[]; confidence: number } | undefined;\n\t\t\tif (match.kind === \"ambiguous\" && deps.interpret) {\n\t\t\t\ttry {\n\t\t\t\t\tconst plan = await deps.interpret(input.script, scripts);\n\t\t\t\t\tconst accepted = acceptReflexPlan(plan, scripts);\n\t\t\t\t\tif (accepted && plan) {\n\t\t\t\t\t\tinterpreted = { ...accepted, confidence: plan.confidence };\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// interpreter is best-effort; ambiguity handling below stays authoritative\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (match.kind === \"ambiguous\" && !interpreted) {\n\t\t\t\tconst shortlist = match.shortlist.map((script) => `${script.name} — ${script.description}`);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: `Ambiguous request — did you mean:\\n${shortlist.join(\"\\n\")}\\nCall again with the exact name.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { outcome: \"ambiguous\", shortlist: match.shortlist.map((script) => script.name) },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst script = interpreted?.script ?? (match as { script: ToolkitScript }).script;\n\t\t\tif (script.danger && input.confirm !== true) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\ttext: `\"${script.name}\" is flagged DANGEROUS (${script.description}). It was NOT run. Confirm with the user, then call again with confirm: true.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdetails: { outcome: \"confirmation_required\", scriptName: script.name },\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Explicit args from the caller win; a brain-extracted arg list fills in for fuzzy requests.\n\t\t\tconst execution = await deps.execute(script, input.args ?? interpreted?.args ?? []);\n\t\t\tconst failed = execution.exitCode !== 0 || execution.timedOut;\n\t\t\tconst header = failed\n\t\t\t\t? `FAILED: ${script.name} exited ${execution.timedOut ? \"by timeout\" : execution.exitCode} after ${execution.durationMs}ms`\n\t\t\t\t: `${script.name} succeeded in ${execution.durationMs}ms`;\n\t\t\tconst body = [\n\t\t\t\theader,\n\t\t\t\texecution.stdout.trim() ? `stdout:\\n${boundedOutput(execution.stdout.trim())}` : \"stdout: (empty)\",\n\t\t\t\texecution.stderr.trim() ? `stderr:\\n${boundedOutput(execution.stderr.trim())}` : \"\",\n\t\t\t]\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(\"\\n\");\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: body }],\n\t\t\t\tdetails: {\n\t\t\t\t\t...(interpreted\n\t\t\t\t\t\t? { interpreter: { script: interpreted.script.name, confidence: interpreted.confidence } }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\toutcome: failed ? \"failed\" : \"executed\",\n\t\t\t\t\tscriptName: script.name,\n\t\t\t\t\texitCode: execution.exitCode,\n\t\t\t\t\tdurationMs: execution.durationMs,\n\t\t\t\t},\n\t\t\t\t...(failed ? { isError: true } : {}),\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ThinkingLevel } from "@caupulican/pi-agent-core";
|
|
2
2
|
import type { Transport } from "@caupulican/pi-ai";
|
|
3
3
|
import { Container, type SelectItem, SelectList, SettingsList } from "@caupulican/pi-tui";
|
|
4
|
-
import type { AutoLearnSettings, AutonomySettings, ContextCurationSettings, ContextPromptEnforcementSettings, MemoryRetrievalSettings, ModelRouterSettings, ResearchLaneSettings, SelfModificationSettings, SettingsScope, WarningSettings, WorkerDelegationSettings } from "../../../core/settings-manager.ts";
|
|
4
|
+
import type { AutoLearnSettings, AutonomySettings, ContextCurationSettings, ContextPromptEnforcementSettings, LearningPolicySettings, MemoryRetrievalSettings, ModelCapabilitySettings, ModelRouterSettings, ResearchLaneSettings, SelfModificationSettings, SettingsScope, WarningSettings, WorkerDelegationSettings } from "../../../core/settings-manager.ts";
|
|
5
5
|
export interface SettingsConfig {
|
|
6
6
|
autoCompact: boolean;
|
|
7
7
|
showImages: boolean;
|
|
@@ -42,6 +42,10 @@ export interface SettingsConfig {
|
|
|
42
42
|
workerDelegation: WorkerDelegationSettings;
|
|
43
43
|
contextCuration: ContextCurationSettings;
|
|
44
44
|
contextCurationScope?: SettingsScope;
|
|
45
|
+
learningPolicy: LearningPolicySettings;
|
|
46
|
+
learningPolicyScope?: SettingsScope;
|
|
47
|
+
modelCapability: ModelCapabilitySettings;
|
|
48
|
+
modelCapabilityScope?: SettingsScope;
|
|
45
49
|
workerDelegationScope?: SettingsScope;
|
|
46
50
|
modelRouter: ModelRouterSettings;
|
|
47
51
|
modelRouterScope?: SettingsScope;
|
|
@@ -89,6 +93,8 @@ export interface SettingsCallbacks {
|
|
|
89
93
|
onResearchLaneChange: (settings: ResearchLaneSettings, scope: SettingsScope) => void;
|
|
90
94
|
onWorkerDelegationChange: (settings: WorkerDelegationSettings, scope: SettingsScope) => void;
|
|
91
95
|
onContextCurationChange: (settings: ContextCurationSettings, scope: SettingsScope) => void;
|
|
96
|
+
onLearningPolicyChange: (settings: LearningPolicySettings, scope: SettingsScope) => void;
|
|
97
|
+
onModelCapabilityChange: (settings: ModelCapabilitySettings, scope: SettingsScope) => void;
|
|
92
98
|
onModelRouterChange: (settings: ModelRouterSettings, scope: SettingsScope) => void;
|
|
93
99
|
onAutoLearnChange: (settings: AutoLearnSettings, scope: SettingsScope) => void;
|
|
94
100
|
onContextPolicyEnforcementChange: (settings: ContextPromptEnforcementSettings, scope: SettingsScope) => void;
|