agent-nuvira 3.3.11 → 3.3.13
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 +32 -1
- package/dist/agents/agents/reasoner.d.ts.map +1 -1
- package/dist/agents/agents/reasoner.js +13 -0
- package/dist/agents/agents/reasoner.js.map +1 -1
- package/dist/agents/orchestrator.d.ts.map +1 -1
- package/dist/agents/orchestrator.js +56 -20
- package/dist/agents/orchestrator.js.map +1 -1
- package/dist/cli/chat.d.ts +36 -0
- package/dist/cli/chat.d.ts.map +1 -1
- package/dist/cli/chat.js +456 -43
- package/dist/cli/chat.js.map +1 -1
- package/dist/cli/cli-program.d.ts.map +1 -1
- package/dist/cli/cli-program.js +8 -0
- package/dist/cli/cli-program.js.map +1 -1
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +35 -4
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/execute.d.ts.map +1 -1
- package/dist/cli/execute.js +14 -0
- package/dist/cli/execute.js.map +1 -1
- package/dist/cli/knowledge.d.ts +23 -0
- package/dist/cli/knowledge.d.ts.map +1 -0
- package/dist/cli/knowledge.js +132 -0
- package/dist/cli/knowledge.js.map +1 -0
- package/dist/cli/loop-executor.d.ts.map +1 -1
- package/dist/cli/loop-executor.js +57 -13
- package/dist/cli/loop-executor.js.map +1 -1
- package/dist/cli/omniroute-control.d.ts +88 -0
- package/dist/cli/omniroute-control.d.ts.map +1 -0
- package/dist/cli/omniroute-control.js +179 -0
- package/dist/cli/omniroute-control.js.map +1 -0
- package/dist/cli/omniroute.d.ts +21 -0
- package/dist/cli/omniroute.d.ts.map +1 -0
- package/dist/cli/omniroute.js +67 -0
- package/dist/cli/omniroute.js.map +1 -0
- package/dist/cli/tool-install-prompt.d.ts +58 -0
- package/dist/cli/tool-install-prompt.d.ts.map +1 -1
- package/dist/cli/tool-install-prompt.js +137 -0
- package/dist/cli/tool-install-prompt.js.map +1 -1
- package/dist/cli/weak-model-prompt.d.ts +16 -7
- package/dist/cli/weak-model-prompt.d.ts.map +1 -1
- package/dist/cli/weak-model-prompt.js +24 -8
- package/dist/cli/weak-model-prompt.js.map +1 -1
- package/dist/config/types.d.ts +44 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/context/cache.d.ts +35 -1
- package/dist/context/cache.d.ts.map +1 -1
- package/dist/context/cache.js +31 -2
- package/dist/context/cache.js.map +1 -1
- package/dist/context/history.d.ts +21 -0
- package/dist/context/history.d.ts.map +1 -1
- package/dist/context/history.js +50 -0
- package/dist/context/history.js.map +1 -1
- package/dist/gateway/hook-contract.d.ts +173 -0
- package/dist/gateway/hook-contract.d.ts.map +1 -0
- package/dist/gateway/hook-contract.js +352 -0
- package/dist/gateway/hook-contract.js.map +1 -0
- package/dist/gateway/hooks.d.ts.map +1 -1
- package/dist/gateway/hooks.js +14 -0
- package/dist/gateway/hooks.js.map +1 -1
- package/dist/inference/interface.d.ts +17 -0
- package/dist/inference/interface.d.ts.map +1 -1
- package/dist/inference/model-catalog.d.ts +17 -0
- package/dist/inference/model-catalog.d.ts.map +1 -1
- package/dist/inference/model-catalog.js +42 -7
- package/dist/inference/model-catalog.js.map +1 -1
- package/dist/inference/model-id-validation.d.ts +57 -0
- package/dist/inference/model-id-validation.d.ts.map +1 -0
- package/dist/inference/model-id-validation.js +127 -0
- package/dist/inference/model-id-validation.js.map +1 -0
- package/dist/inference/openai-compat-adapter.d.ts.map +1 -1
- package/dist/inference/openai-compat-adapter.js +12 -1
- package/dist/inference/openai-compat-adapter.js.map +1 -1
- package/dist/inference/provider-catalog.d.ts +11 -0
- package/dist/inference/provider-catalog.d.ts.map +1 -1
- package/dist/inference/provider-catalog.js +80 -0
- package/dist/inference/provider-catalog.js.map +1 -1
- package/dist/inference/route-resolver.d.ts +2 -8
- package/dist/inference/route-resolver.d.ts.map +1 -1
- package/dist/inference/route-resolver.js +17 -0
- package/dist/inference/route-resolver.js.map +1 -1
- package/dist/inference/tool-call-utils.d.ts +4 -3
- package/dist/inference/tool-call-utils.d.ts.map +1 -1
- package/dist/inference/tool-call-utils.js +26 -12
- package/dist/inference/tool-call-utils.js.map +1 -1
- package/dist/inference/tools.d.ts +1 -0
- package/dist/inference/tools.d.ts.map +1 -1
- package/dist/inference/tools.js +20 -3
- package/dist/inference/tools.js.map +1 -1
- package/dist/learning/agentic-route-gate.d.ts +104 -0
- package/dist/learning/agentic-route-gate.d.ts.map +1 -0
- package/dist/learning/agentic-route-gate.js +125 -0
- package/dist/learning/agentic-route-gate.js.map +1 -0
- package/dist/learning/auto-router.d.ts +89 -0
- package/dist/learning/auto-router.d.ts.map +1 -1
- package/dist/learning/auto-router.js +188 -8
- package/dist/learning/auto-router.js.map +1 -1
- package/dist/learning/build-prerequisites.d.ts +68 -0
- package/dist/learning/build-prerequisites.d.ts.map +1 -0
- package/dist/learning/build-prerequisites.js +267 -0
- package/dist/learning/build-prerequisites.js.map +1 -0
- package/dist/learning/continuation-intent.d.ts +43 -0
- package/dist/learning/continuation-intent.d.ts.map +1 -0
- package/dist/learning/continuation-intent.js +82 -0
- package/dist/learning/continuation-intent.js.map +1 -0
- package/dist/learning/error-repair.d.ts +23 -1
- package/dist/learning/error-repair.d.ts.map +1 -1
- package/dist/learning/error-repair.js +58 -0
- package/dist/learning/error-repair.js.map +1 -1
- package/dist/learning/knowledge-base.d.ts +124 -0
- package/dist/learning/knowledge-base.d.ts.map +1 -0
- package/dist/learning/knowledge-base.js +337 -0
- package/dist/learning/knowledge-base.js.map +1 -0
- package/dist/learning/model-harness.d.ts +19 -0
- package/dist/learning/model-harness.d.ts.map +1 -1
- package/dist/learning/model-harness.js +27 -0
- package/dist/learning/model-harness.js.map +1 -1
- package/dist/learning/model-selection.d.ts +2 -1
- package/dist/learning/model-selection.d.ts.map +1 -1
- package/dist/learning/model-selection.js +35 -2
- package/dist/learning/model-selection.js.map +1 -1
- package/dist/learning/project-docs.d.ts +83 -0
- package/dist/learning/project-docs.d.ts.map +1 -0
- package/dist/learning/project-docs.js +132 -0
- package/dist/learning/project-docs.js.map +1 -0
- package/dist/learning/prompt-budget.d.ts +91 -0
- package/dist/learning/prompt-budget.d.ts.map +1 -0
- package/dist/learning/prompt-budget.js +99 -0
- package/dist/learning/prompt-budget.js.map +1 -0
- package/dist/learning/quota-ledger.d.ts +13 -0
- package/dist/learning/quota-ledger.d.ts.map +1 -1
- package/dist/learning/quota-ledger.js +28 -0
- package/dist/learning/quota-ledger.js.map +1 -1
- package/dist/learning/reasoning-trace.d.ts +55 -2
- package/dist/learning/reasoning-trace.d.ts.map +1 -1
- package/dist/learning/reasoning-trace.js +48 -0
- package/dist/learning/reasoning-trace.js.map +1 -1
- package/dist/learning/resilient-call.d.ts.map +1 -1
- package/dist/learning/resilient-call.js +16 -3
- package/dist/learning/resilient-call.js.map +1 -1
- package/dist/learning/routing-history.d.ts +13 -0
- package/dist/learning/routing-history.d.ts.map +1 -1
- package/dist/learning/routing-history.js.map +1 -1
- package/dist/learning/seeded-benchmark.d.ts +14 -0
- package/dist/learning/seeded-benchmark.d.ts.map +1 -1
- package/dist/learning/seeded-benchmark.js +43 -4
- package/dist/learning/seeded-benchmark.js.map +1 -1
- package/dist/learning/turn-report.d.ts +78 -0
- package/dist/learning/turn-report.d.ts.map +1 -0
- package/dist/learning/turn-report.js +140 -0
- package/dist/learning/turn-report.js.map +1 -0
- package/dist/security/secret-scan.d.ts +156 -0
- package/dist/security/secret-scan.d.ts.map +1 -0
- package/dist/security/secret-scan.js +525 -0
- package/dist/security/secret-scan.js.map +1 -0
- package/dist/tools/edit-verification.d.ts +2 -11
- package/dist/tools/edit-verification.d.ts.map +1 -1
- package/dist/tools/edit-verification.js +33 -1
- package/dist/tools/edit-verification.js.map +1 -1
- package/dist/tools/loop-skill-hint.d.ts +51 -0
- package/dist/tools/loop-skill-hint.d.ts.map +1 -1
- package/dist/tools/loop-skill-hint.js +87 -2
- package/dist/tools/loop-skill-hint.js.map +1 -1
- package/dist/tools/plan-store.d.ts +126 -3
- package/dist/tools/plan-store.d.ts.map +1 -1
- package/dist/tools/plan-store.js +290 -6
- package/dist/tools/plan-store.js.map +1 -1
- package/dist/tools/registry.d.ts +20 -1
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +165 -4
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/remediation-ladder.d.ts +91 -0
- package/dist/tools/remediation-ladder.d.ts.map +1 -0
- package/dist/tools/remediation-ladder.js +308 -0
- package/dist/tools/remediation-ladder.js.map +1 -0
- package/dist/tools/run-terminal.d.ts.map +1 -1
- package/dist/tools/run-terminal.js +60 -2
- package/dist/tools/run-terminal.js.map +1 -1
- package/dist/tools/skills-hub.d.ts +7 -0
- package/dist/tools/skills-hub.d.ts.map +1 -1
- package/dist/tools/skills-hub.js +11 -2
- package/dist/tools/skills-hub.js.map +1 -1
- package/dist/tools/step-artifact.d.ts +35 -0
- package/dist/tools/step-artifact.d.ts.map +1 -0
- package/dist/tools/step-artifact.js +154 -0
- package/dist/tools/step-artifact.js.map +1 -0
- package/dist/tools/tool-loop.d.ts +35 -0
- package/dist/tools/tool-loop.d.ts.map +1 -1
- package/dist/tools/tool-loop.js +284 -9
- package/dist/tools/tool-loop.js.map +1 -1
- package/dist/tools/toolsets.js +4 -4
- package/dist/tools/toolsets.js.map +1 -1
- package/dist/tools/worktree.d.ts +11 -2
- package/dist/tools/worktree.d.ts.map +1 -1
- package/dist/tools/worktree.js +11 -2
- package/dist/tools/worktree.js.map +1 -1
- package/dist/utils/effect-verification.js +1 -1
- package/dist/utils/effect-verification.js.map +1 -1
- package/dist/web-dashboard/chat-console.d.ts +21 -1
- package/dist/web-dashboard/chat-console.d.ts.map +1 -1
- package/dist/web-dashboard/chat-console.js +33 -5
- package/dist/web-dashboard/chat-console.js.map +1 -1
- package/dist/web-dashboard/server.d.ts +29 -0
- package/dist/web-dashboard/server.d.ts.map +1 -1
- package/dist/web-dashboard/server.js +410 -5
- package/dist/web-dashboard/server.js.map +1 -1
- package/dist/web-dashboard/src/types.d.ts +137 -0
- package/dist/web-dashboard/src/types.d.ts.map +1 -1
- package/dist/web-dashboard/workspace-guard.d.ts +7 -0
- package/dist/web-dashboard/workspace-guard.d.ts.map +1 -1
- package/dist/web-dashboard/workspace-guard.js +70 -0
- package/dist/web-dashboard/workspace-guard.js.map +1 -1
- package/package.json +4 -1
- package/src/web-dashboard/public/assets/index-DhiuR4S2.js +210 -0
- package/src/web-dashboard/public/assets/index-DhiuR4S2.js.map +1 -0
- package/src/web-dashboard/public/assets/index-tK8Y2qHB.css +1 -0
- package/src/web-dashboard/public/index.html +2 -2
- package/src/web-dashboard/public/assets/index-BdKf5Xw2.js +0 -207
- package/src/web-dashboard/public/assets/index-BdKf5Xw2.js.map +0 -1
- package/src/web-dashboard/public/assets/index-C9eBskc9.css +0 -1
package/dist/tools/registry.js
CHANGED
|
@@ -29,6 +29,7 @@ import { ACTION_BY_INTENT } from '../nlu/actions.js';
|
|
|
29
29
|
import { detectPermissionSeeking, IRREVERSIBLE_ACTION_RE } from '../learning/autonomy-policy.js';
|
|
30
30
|
import { createFindingTool } from './finding-tool.js';
|
|
31
31
|
import { recordArtifact } from './artifact-append.js';
|
|
32
|
+
import { checkStepArtifacts } from './step-artifact.js';
|
|
32
33
|
// ─── Tool definitions ───────────────────────────────────────────────────────
|
|
33
34
|
// ─── Shared auto-delivery helper ─────────────────────────────────────────
|
|
34
35
|
// Tools that produce artifact files (generate_image, speak, video_generate)
|
|
@@ -197,6 +198,10 @@ export const planTodoSchema = z.object({
|
|
|
197
198
|
.describe('Ordered steps (required for action=create)'),
|
|
198
199
|
id: z.string().optional().describe('The step id to update (required for action=update)'),
|
|
199
200
|
status: z.enum(['pending', 'running', 'done', 'blocked']).optional().describe('New status for the step (required for action=update)'),
|
|
201
|
+
note: z
|
|
202
|
+
.string()
|
|
203
|
+
.optional()
|
|
204
|
+
.describe('Optional plain-English note for this step, recorded with the update (e.g. "reproduced with a minimal test", "blocked on the missing API key"). Shown in the progress table and the completion summary.'),
|
|
200
205
|
});
|
|
201
206
|
/** H2 — delegate tool args: a focused subtask for a specialized sub-agent. */
|
|
202
207
|
const delegateSchema = z.object({
|
|
@@ -527,7 +532,13 @@ registerTool({
|
|
|
527
532
|
// Narrow on purpose — both conditions must hold, and any question naming an
|
|
528
533
|
// irreversible action (overwrite, delete, publish, deploy, send, pay…) is
|
|
529
534
|
// passed straight through, because that decision IS the user's.
|
|
530
|
-
|
|
535
|
+
// A confirmation the TOOL ITSELF demanded (run_terminal's "call ask_user")
|
|
536
|
+
// must not be swallowed by this gate — that is the deadlock fixed in
|
|
537
|
+
// ToolContext.pendingConfirmation. Consume the flag and fall through so the
|
|
538
|
+
// question reaches the user once.
|
|
539
|
+
const pending = ctx.pendingConfirmation;
|
|
540
|
+
if (!pending &&
|
|
541
|
+
(ctx.writesAuthorized?.authorized === true || Boolean(ctx.envelope)) &&
|
|
531
542
|
detectPermissionSeeking(question) &&
|
|
532
543
|
!IRREVERSIBLE_ACTION_RE.test(question)) {
|
|
533
544
|
const recommended = choices[0]?.label ?? '';
|
|
@@ -551,6 +562,9 @@ registerTool({
|
|
|
551
562
|
'high-impact and irreversible, and has no sensible default — re-call ask_user naming ' +
|
|
552
563
|
'that specific irreversible choice (e.g. whether to overwrite an existing file).');
|
|
553
564
|
}
|
|
565
|
+
// One confirmation refusal buys exactly ONE ask — clear it before rendering.
|
|
566
|
+
if (pending)
|
|
567
|
+
ctx.pendingConfirmation = undefined;
|
|
554
568
|
const render = ctx.askUser || (await import('./ask-user.js')).renderAskUser;
|
|
555
569
|
const answer = await render(question, choices, multi_select);
|
|
556
570
|
const picked = Array.isArray(answer.answer) ? answer.answer.join(', ') : answer.answer;
|
|
@@ -668,12 +682,12 @@ registerTool({
|
|
|
668
682
|
// cards show tool calls; this shows the plan itself).
|
|
669
683
|
registerTool({
|
|
670
684
|
name: 'plan_todo',
|
|
671
|
-
description: 'Declare and track a multi-step plan: create ordered steps with descriptions, then
|
|
685
|
+
description: 'Declare and track a multi-step plan as a live progress table: create ordered steps with descriptions, then update each step (running → done/blocked) as you work, ideally with a short note saying what happened. Use for any job with 2+ steps — the table persists across the whole conversation AND across sessions, so a later turn can reference "step N is done", and the plan closes out with an achieved summary. Call create once at the start, then update each step as it starts and again as it finishes.',
|
|
672
686
|
category: 'workflow',
|
|
673
687
|
inputSchema: planTodoSchema,
|
|
674
688
|
endsAgentStep: false,
|
|
675
689
|
run: async (args, ctx) => {
|
|
676
|
-
const { action, goal, steps, id, status } = planTodoSchema.parse(args);
|
|
690
|
+
const { action, goal, steps, id, status, note } = planTodoSchema.parse(args);
|
|
677
691
|
const { defaultPlanStore } = await import('./plan-store.js');
|
|
678
692
|
const store = ctx.planStore ?? defaultPlanStore();
|
|
679
693
|
if (action === 'create') {
|
|
@@ -683,7 +697,30 @@ registerTool({
|
|
|
683
697
|
store.create(goal, steps);
|
|
684
698
|
}
|
|
685
699
|
else if (id && status) {
|
|
686
|
-
|
|
700
|
+
// A1 — never accept an update that matched nothing. Silently returning
|
|
701
|
+
// the unchanged plan reads as success to the model (and as tracking to
|
|
702
|
+
// the user) while the counter stays frozen; observed live on the `cal`
|
|
703
|
+
// Android run, where the checklist sat at `1/7` across four successful
|
|
704
|
+
// steps. Resolve the reference first and, when it names no step, say so
|
|
705
|
+
// with the ids that DO exist so the model can re-send it and move on.
|
|
706
|
+
const resolved = store.resolveStepId ? store.resolveStepId(id) : id;
|
|
707
|
+
if (!resolved) {
|
|
708
|
+
const valid = (store.snapshot?.()?.steps ?? []).map((s) => s.id);
|
|
709
|
+
return `Error: plan_todo found no step "${id}" — valid step ids: ${valid.length > 0 ? valid.join(', ') : '(none — declare the plan with action "create" first)'}. Re-send this update with one of those ids.`;
|
|
710
|
+
}
|
|
711
|
+
// A6 — a step that NAMES an artifact is done only once that artifact
|
|
712
|
+
// exists. The plan can otherwise advance past undelivered work (the `cal`
|
|
713
|
+
// run kept going after its APK step never produced an APK). Checked
|
|
714
|
+
// against the workspace; a step with no file-like token is unaffected.
|
|
715
|
+
if (status === 'done' && ctx.cwd) {
|
|
716
|
+
const step = store.snapshot?.()?.steps.find((s) => s.id === resolved);
|
|
717
|
+
const { missing } = checkStepArtifacts(step?.description ?? '', ctx.cwd);
|
|
718
|
+
if (missing.length > 0) {
|
|
719
|
+
return (`Error: step "${resolved}" names artifact(s) that do not exist yet: ${missing.join(', ')}. ` +
|
|
720
|
+
`Create them in ${ctx.cwd}, then mark the step done — a step is not done while its artifact is missing.`);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
store.update(resolved, status, note);
|
|
687
724
|
}
|
|
688
725
|
else {
|
|
689
726
|
return 'Error: plan_todo update needs id + status (pending|running|done|blocked).';
|
|
@@ -1880,6 +1917,53 @@ registerTool({
|
|
|
1880
1917
|
return JSON.stringify(m.getSecurityScorer().score(filePath));
|
|
1881
1918
|
}),
|
|
1882
1919
|
});
|
|
1920
|
+
// Secret scan tool — LOCAL, dependency-free, on-demand.
|
|
1921
|
+
//
|
|
1922
|
+
// `security_score`/`ast_audit` scan ONE named file and report a score. This is
|
|
1923
|
+
// the other question an agent that writes and commits code actually has to
|
|
1924
|
+
// answer before it commits: "is anything secret-shaped anywhere in here?". It
|
|
1925
|
+
// walks the tree with bounded coverage, needs no `gitleaks`/`ggshield` binary
|
|
1926
|
+
// and no network, and reports masked values only — see src/security/secret-scan.ts.
|
|
1927
|
+
registerTool({
|
|
1928
|
+
name: 'secret_scan',
|
|
1929
|
+
description: 'Scan the workspace for secret-shaped strings (API keys, tokens, private keys, credentials in URLs) before committing or publishing. Fully local — no network and no external scanner binary — and every reported value is masked. Returns findings with path:line and severity, plus a summary. Set history:true to scan git HISTORY as well (every committed version of every file) — a key deleted in a later commit is STILL committed and must be rotated. A clean result means "nothing matched a known shape", NOT "no secrets": report it as a lint, never as a guarantee.',
|
|
1930
|
+
category: 'workflow',
|
|
1931
|
+
inputSchema: z.object({
|
|
1932
|
+
path: z.string().optional().describe('Directory to scan (relative to the workspace, or absolute). Default: the workspace root.'),
|
|
1933
|
+
subdir: z.string().optional().describe('Narrow the scan to one subtree, e.g. "src" or "docs".'),
|
|
1934
|
+
maxFiles: z.number().optional().describe('Cap on files visited (default 5000) — a huge repo does not hang the turn.'),
|
|
1935
|
+
history: z.boolean().optional().describe('Also scan git history (reachable blobs) for secrets ever committed. Default false. Use before publishing or when auditing an existing repo.'),
|
|
1936
|
+
maxBlobs: z.number().optional().describe('With history:true, cap on distinct historical blobs read (default 2000).'),
|
|
1937
|
+
}),
|
|
1938
|
+
endsAgentStep: false,
|
|
1939
|
+
run: async (args, ctx) => {
|
|
1940
|
+
const { join } = await import('node:path');
|
|
1941
|
+
const m = await import('../security/secret-scan.js');
|
|
1942
|
+
const { path: target, subdir, maxFiles, history, maxBlobs } = args;
|
|
1943
|
+
const cwd = ctx?.cwd ?? process.cwd();
|
|
1944
|
+
const root = target
|
|
1945
|
+
? (target.startsWith('/') || /^[A-Za-z]:[\\/]/.test(target) ? target : join(cwd, target))
|
|
1946
|
+
: cwd;
|
|
1947
|
+
if (history) {
|
|
1948
|
+
// History only: the tree scan runs first (fast, no git), then history is
|
|
1949
|
+
// appended as its own section so a reader can tell the two apart.
|
|
1950
|
+
const tree = m.scanDirectory(root, {
|
|
1951
|
+
...(subdir ? { subdir } : {}),
|
|
1952
|
+
...(maxFiles ? { maxFiles } : {}),
|
|
1953
|
+
});
|
|
1954
|
+
const hist = m.scanGitHistory(root, {
|
|
1955
|
+
...(subdir ? { subdir } : {}),
|
|
1956
|
+
...(maxBlobs ? { maxBlobs } : {}),
|
|
1957
|
+
});
|
|
1958
|
+
return [m.formatSecretScan(tree), '', '── git history ──', m.formatSecretHistoryScan(hist)].join('\n');
|
|
1959
|
+
}
|
|
1960
|
+
const result = m.scanDirectory(root, {
|
|
1961
|
+
...(subdir ? { subdir } : {}),
|
|
1962
|
+
...(maxFiles ? { maxFiles } : {}),
|
|
1963
|
+
});
|
|
1964
|
+
return m.formatSecretScan(result);
|
|
1965
|
+
},
|
|
1966
|
+
});
|
|
1883
1967
|
// ─── Batch 5: Infrastructure ──────────────────────────────────────────────
|
|
1884
1968
|
// Tool search tool — the tiered-exposure discovery surface. Two actions:
|
|
1885
1969
|
// - search (default): fuzzy-find tools by query (the pre-existing behavior).
|
|
@@ -2901,6 +2985,83 @@ registerTool({
|
|
|
2901
2985
|
return mgr.extract(filePath, { ocr: Boolean(ocr) }).then((r) => JSON.stringify(r));
|
|
2902
2986
|
}),
|
|
2903
2987
|
});
|
|
2988
|
+
// Knowledge — tag-scoped, vectorized retrieval over the user's own documents
|
|
2989
|
+
//
|
|
2990
|
+
// WHY A TOOL. The user's flow is "bring documents, tag them, ask questions scoped
|
|
2991
|
+
// to that tag." Retrieval must be something the AGENT can drive mid-task without
|
|
2992
|
+
// a CLI round-trip, and it must pay the read+embed cost ONCE per document rather
|
|
2993
|
+
// than re-reading the file into context every turn. This tool is that surface:
|
|
2994
|
+
// `add` ingests under a tag (documents are extracted, chunked, embedded once),
|
|
2995
|
+
// `query` returns the tag's top-k chunks with their source files so the model can
|
|
2996
|
+
// answer the data half from the user's data and the generic half from its own
|
|
2997
|
+
// knowledge / web-research.
|
|
2998
|
+
registerTool({
|
|
2999
|
+
name: 'knowledge',
|
|
3000
|
+
description: 'Answer questions from the USER\'S OWN tagged documents. `add` ingests files/folders under a tag '
|
|
3001
|
+
+ '(extract → chunk → embed, done once); `query` retrieves the tag\'s most relevant passages, labeled '
|
|
3002
|
+
+ 'with their source file, so the data part of an answer comes from the user\'s data and the general '
|
|
3003
|
+
+ 'part from model knowledge or web-research. Use this instead of re-reading a large document on every '
|
|
3004
|
+
+ 'turn. Actions: add | query | list | forget | stats. Tags are normalized (spaces/capitals/underscores '
|
|
3005
|
+
+ 'become lowercase-hyphen), e.g. "Dheeraj health report" → "dheeraj-health-report".',
|
|
3006
|
+
category: 'workflow',
|
|
3007
|
+
inputSchema: z.object({
|
|
3008
|
+
action: z.enum(['add', 'query', 'list', 'forget', 'stats']).describe('Action'),
|
|
3009
|
+
tag: z.string().optional().describe('Tag/hashtag scoping the data (e.g. "dheeraj-health-report")'),
|
|
3010
|
+
paths: z.array(z.string()).optional().describe('Files or folders to ingest (action: add)'),
|
|
3011
|
+
question: z.string().optional().describe('Question to answer from the tagged data (action: query)'),
|
|
3012
|
+
topK: z.number().optional().describe('Chunks to retrieve (action: query, default 6)'),
|
|
3013
|
+
}),
|
|
3014
|
+
endsAgentStep: false,
|
|
3015
|
+
run: (args) => import('../learning/knowledge-base.js').then(async (m) => {
|
|
3016
|
+
const { action, tag, paths, question, topK } = args;
|
|
3017
|
+
switch (action) {
|
|
3018
|
+
case 'add': {
|
|
3019
|
+
if (!tag)
|
|
3020
|
+
return 'tag is required for action: add';
|
|
3021
|
+
if (!paths || paths.length === 0)
|
|
3022
|
+
return 'paths is required for action: add';
|
|
3023
|
+
const result = await m.ingestKnowledge(tag, paths);
|
|
3024
|
+
const skipped = result.skipped.length
|
|
3025
|
+
? `\nSkipped: ${result.skipped.map((s) => `${s.path} (${s.reason})`).join('; ')}`
|
|
3026
|
+
: '';
|
|
3027
|
+
return `✅ Ingested ${result.files} document(s) / ${result.chunks} chunk(s) under tag '${result.tag}'.`
|
|
3028
|
+
+ `\nQuery it with action: query, tag: '${result.tag}'.${skipped}`;
|
|
3029
|
+
}
|
|
3030
|
+
case 'query': {
|
|
3031
|
+
if (!tag)
|
|
3032
|
+
return 'tag is required for action: query';
|
|
3033
|
+
if (!question)
|
|
3034
|
+
return 'question is required for action: query';
|
|
3035
|
+
const hits = await m.queryKnowledge(tag, question, { topK });
|
|
3036
|
+
return m.formatKnowledgeContext(tag, hits);
|
|
3037
|
+
}
|
|
3038
|
+
case 'list': {
|
|
3039
|
+
const tags = m.listKnowledgeTags();
|
|
3040
|
+
if (tags.length === 0)
|
|
3041
|
+
return 'No knowledge tags yet. Ingest documents with action: add.';
|
|
3042
|
+
return tags
|
|
3043
|
+
.map((t) => ` • ${t.tag} — ${t.chunkCount} chunk(s) across ${t.documents.length} document(s)`)
|
|
3044
|
+
.join('\n');
|
|
3045
|
+
}
|
|
3046
|
+
case 'forget': {
|
|
3047
|
+
if (!tag)
|
|
3048
|
+
return 'tag is required for action: forget';
|
|
3049
|
+
const removed = await m.forgetKnowledgeTag(tag);
|
|
3050
|
+
return removed ? `🗑️ Removed knowledge tag '${m.normalizeKnowledgeTag(tag)}'.` : `No knowledge tag '${tag}' found.`;
|
|
3051
|
+
}
|
|
3052
|
+
case 'stats': {
|
|
3053
|
+
if (!tag)
|
|
3054
|
+
return 'tag is required for action: stats';
|
|
3055
|
+
const entry = m.getKnowledgeTag(tag);
|
|
3056
|
+
if (!entry)
|
|
3057
|
+
return `No knowledge tag '${tag}' found.`;
|
|
3058
|
+
return JSON.stringify(entry);
|
|
3059
|
+
}
|
|
3060
|
+
default:
|
|
3061
|
+
return `Unknown action '${action}'`;
|
|
3062
|
+
}
|
|
3063
|
+
}),
|
|
3064
|
+
});
|
|
2904
3065
|
// Credential Files — Credential file management
|
|
2905
3066
|
registerTool({
|
|
2906
3067
|
name: 'credential_files',
|