agent-nuvira 3.3.13 → 3.3.14
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 +67 -1
- package/dist/agents/agents/planner.d.ts.map +1 -1
- package/dist/agents/agents/planner.js +9 -0
- package/dist/agents/agents/planner.js.map +1 -1
- package/dist/agents/orchestrator.d.ts +31 -0
- package/dist/agents/orchestrator.d.ts.map +1 -1
- package/dist/agents/orchestrator.js +74 -126
- package/dist/agents/orchestrator.js.map +1 -1
- package/dist/cli/chat.d.ts +89 -0
- package/dist/cli/chat.d.ts.map +1 -1
- package/dist/cli/chat.js +765 -33
- package/dist/cli/chat.js.map +1 -1
- package/dist/cli/cli-program.d.ts.map +1 -1
- package/dist/cli/cli-program.js +12 -0
- package/dist/cli/cli-program.js.map +1 -1
- package/dist/cli/config.d.ts +12 -0
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +86 -0
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/decisions.d.ts +28 -0
- package/dist/cli/decisions.d.ts.map +1 -0
- package/dist/cli/decisions.js +140 -0
- package/dist/cli/decisions.js.map +1 -0
- package/dist/cli/doctor.d.ts +6 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +46 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/failover-runner.d.ts.map +1 -1
- package/dist/cli/failover-runner.js +19 -1
- package/dist/cli/failover-runner.js.map +1 -1
- package/dist/cli/feedback.d.ts.map +1 -1
- package/dist/cli/feedback.js +5 -1
- package/dist/cli/feedback.js.map +1 -1
- package/dist/cli/hooks.d.ts +30 -0
- package/dist/cli/hooks.d.ts.map +1 -0
- package/dist/cli/hooks.js +224 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli/knowledge.d.ts +9 -1
- package/dist/cli/knowledge.d.ts.map +1 -1
- package/dist/cli/knowledge.js +93 -2
- package/dist/cli/knowledge.js.map +1 -1
- package/dist/cli/loop-executor.d.ts.map +1 -1
- package/dist/cli/loop-executor.js +47 -12
- package/dist/cli/loop-executor.js.map +1 -1
- package/dist/cli/model.d.ts +20 -0
- package/dist/cli/model.d.ts.map +1 -1
- package/dist/cli/model.js +294 -14
- package/dist/cli/model.js.map +1 -1
- package/dist/cli/rate.d.ts +78 -0
- package/dist/cli/rate.d.ts.map +1 -0
- package/dist/cli/rate.js +294 -0
- package/dist/cli/rate.js.map +1 -0
- package/dist/config/process-env.d.ts.map +1 -1
- package/dist/config/process-env.js +10 -0
- package/dist/config/process-env.js.map +1 -1
- package/dist/enterprise/vault.d.ts.map +1 -1
- package/dist/enterprise/vault.js +5 -21
- package/dist/enterprise/vault.js.map +1 -1
- package/dist/gateway/hook-contract.d.ts +33 -0
- package/dist/gateway/hook-contract.d.ts.map +1 -1
- package/dist/gateway/hook-contract.js +97 -0
- package/dist/gateway/hook-contract.js.map +1 -1
- package/dist/inference/gemini-adapter.d.ts.map +1 -1
- package/dist/inference/gemini-adapter.js +4 -0
- package/dist/inference/gemini-adapter.js.map +1 -1
- package/dist/inference/interface.d.ts +37 -0
- package/dist/inference/interface.d.ts.map +1 -1
- package/dist/inference/native-tools.d.ts +16 -1
- package/dist/inference/native-tools.d.ts.map +1 -1
- package/dist/inference/native-tools.js +34 -10
- package/dist/inference/native-tools.js.map +1 -1
- package/dist/inference/route-resolver.d.ts +30 -0
- package/dist/inference/route-resolver.d.ts.map +1 -1
- package/dist/inference/route-resolver.js +158 -1
- package/dist/inference/route-resolver.js.map +1 -1
- package/dist/inference/tools.d.ts +16 -1
- package/dist/inference/tools.d.ts.map +1 -1
- package/dist/inference/tools.js +51 -18
- package/dist/inference/tools.js.map +1 -1
- package/dist/learning/acceptance-model.d.ts +247 -0
- package/dist/learning/acceptance-model.d.ts.map +1 -0
- package/dist/learning/acceptance-model.js +708 -0
- package/dist/learning/acceptance-model.js.map +1 -0
- package/dist/learning/auto-router.d.ts +68 -24
- package/dist/learning/auto-router.d.ts.map +1 -1
- package/dist/learning/auto-router.js +301 -96
- package/dist/learning/auto-router.js.map +1 -1
- package/dist/learning/autonomy-policy.d.ts +12 -16
- package/dist/learning/autonomy-policy.d.ts.map +1 -1
- package/dist/learning/autonomy-policy.js +50 -48
- package/dist/learning/autonomy-policy.js.map +1 -1
- package/dist/learning/behavioural-labels.d.ts +86 -0
- package/dist/learning/behavioural-labels.d.ts.map +1 -0
- package/dist/learning/behavioural-labels.js +166 -0
- package/dist/learning/behavioural-labels.js.map +1 -0
- package/dist/learning/capability-evidence.d.ts +167 -0
- package/dist/learning/capability-evidence.d.ts.map +1 -0
- package/dist/learning/capability-evidence.js +210 -0
- package/dist/learning/capability-evidence.js.map +1 -0
- package/dist/learning/capability-readiness.d.ts +64 -0
- package/dist/learning/capability-readiness.d.ts.map +1 -0
- package/dist/learning/capability-readiness.js +74 -0
- package/dist/learning/capability-readiness.js.map +1 -0
- package/dist/learning/capability-types.d.ts +169 -0
- package/dist/learning/capability-types.d.ts.map +1 -0
- package/dist/learning/capability-types.js +20 -0
- package/dist/learning/capability-types.js.map +1 -0
- package/dist/learning/catalog-feed.d.ts +89 -0
- package/dist/learning/catalog-feed.d.ts.map +1 -0
- package/dist/learning/catalog-feed.js +211 -0
- package/dist/learning/catalog-feed.js.map +1 -0
- package/dist/learning/cli-intent-effects.d.ts +60 -0
- package/dist/learning/cli-intent-effects.d.ts.map +1 -0
- package/dist/learning/cli-intent-effects.js +153 -0
- package/dist/learning/cli-intent-effects.js.map +1 -0
- package/dist/learning/command-adaptation.d.ts +41 -0
- package/dist/learning/command-adaptation.d.ts.map +1 -0
- package/dist/learning/command-adaptation.js +122 -0
- package/dist/learning/command-adaptation.js.map +1 -0
- package/dist/learning/consent-picture.d.ts +42 -0
- package/dist/learning/consent-picture.d.ts.map +1 -0
- package/dist/learning/consent-picture.js +53 -0
- package/dist/learning/consent-picture.js.map +1 -0
- package/dist/learning/context-budget.d.ts +37 -6
- package/dist/learning/context-budget.d.ts.map +1 -1
- package/dist/learning/context-budget.js +38 -9
- package/dist/learning/context-budget.js.map +1 -1
- package/dist/learning/decision-log.d.ts +114 -0
- package/dist/learning/decision-log.d.ts.map +1 -0
- package/dist/learning/decision-log.js +296 -0
- package/dist/learning/decision-log.js.map +1 -0
- package/dist/learning/deliverable-class.d.ts.map +1 -1
- package/dist/learning/deliverable-class.js +19 -0
- package/dist/learning/deliverable-class.js.map +1 -1
- package/dist/learning/deliverable-corpus.d.ts +117 -0
- package/dist/learning/deliverable-corpus.d.ts.map +1 -0
- package/dist/learning/deliverable-corpus.js +176 -0
- package/dist/learning/deliverable-corpus.js.map +1 -0
- package/dist/learning/error-repair.d.ts +22 -1
- package/dist/learning/error-repair.d.ts.map +1 -1
- package/dist/learning/error-repair.js +37 -0
- package/dist/learning/error-repair.js.map +1 -1
- package/dist/learning/exhaustion-report.d.ts +136 -0
- package/dist/learning/exhaustion-report.d.ts.map +1 -0
- package/dist/learning/exhaustion-report.js +239 -0
- package/dist/learning/exhaustion-report.js.map +1 -0
- package/dist/learning/failure-bookkeeping.d.ts +16 -0
- package/dist/learning/failure-bookkeeping.d.ts.map +1 -1
- package/dist/learning/failure-bookkeeping.js +51 -5
- package/dist/learning/failure-bookkeeping.js.map +1 -1
- package/dist/learning/gate-friction.d.ts +39 -0
- package/dist/learning/gate-friction.d.ts.map +1 -0
- package/dist/learning/gate-friction.js +91 -0
- package/dist/learning/gate-friction.js.map +1 -0
- package/dist/learning/harness-narration.d.ts +34 -0
- package/dist/learning/harness-narration.d.ts.map +1 -0
- package/dist/learning/harness-narration.js +58 -0
- package/dist/learning/harness-narration.js.map +1 -0
- package/dist/learning/hub-skill-catalog.d.ts.map +1 -1
- package/dist/learning/hub-skill-catalog.js +1 -2
- package/dist/learning/hub-skill-catalog.js.map +1 -1
- package/dist/learning/hybrid-router.d.ts +65 -0
- package/dist/learning/hybrid-router.d.ts.map +1 -1
- package/dist/learning/hybrid-router.js +186 -0
- package/dist/learning/hybrid-router.js.map +1 -1
- package/dist/learning/knowledge-base.d.ts +229 -3
- package/dist/learning/knowledge-base.d.ts.map +1 -1
- package/dist/learning/knowledge-base.js +593 -24
- package/dist/learning/knowledge-base.js.map +1 -1
- package/dist/learning/knowledge-eval.d.ts +171 -0
- package/dist/learning/knowledge-eval.d.ts.map +1 -0
- package/dist/learning/knowledge-eval.js +196 -0
- package/dist/learning/knowledge-eval.js.map +1 -0
- package/dist/learning/knowledge-turn.d.ts +92 -0
- package/dist/learning/knowledge-turn.d.ts.map +1 -0
- package/dist/learning/knowledge-turn.js +190 -0
- package/dist/learning/knowledge-turn.js.map +1 -0
- package/dist/learning/learned-commands.d.ts +64 -0
- package/dist/learning/learned-commands.d.ts.map +1 -0
- package/dist/learning/learned-commands.js +108 -0
- package/dist/learning/learned-commands.js.map +1 -0
- package/dist/learning/lexical-search.d.ts +50 -0
- package/dist/learning/lexical-search.d.ts.map +1 -0
- package/dist/learning/lexical-search.js +111 -0
- package/dist/learning/lexical-search.js.map +1 -0
- package/dist/learning/machine-facts.d.ts +71 -0
- package/dist/learning/machine-facts.d.ts.map +1 -0
- package/dist/learning/machine-facts.js +164 -0
- package/dist/learning/machine-facts.js.map +1 -0
- package/dist/learning/markdown-outline.d.ts +73 -0
- package/dist/learning/markdown-outline.d.ts.map +1 -0
- package/dist/learning/markdown-outline.js +136 -0
- package/dist/learning/markdown-outline.js.map +1 -0
- package/dist/learning/model-first-router.d.ts +33 -1
- package/dist/learning/model-first-router.d.ts.map +1 -1
- package/dist/learning/model-first-router.js +123 -9
- package/dist/learning/model-first-router.js.map +1 -1
- package/dist/learning/model-identity.d.ts +80 -0
- package/dist/learning/model-identity.d.ts.map +1 -0
- package/dist/learning/model-identity.js +115 -0
- package/dist/learning/model-identity.js.map +1 -0
- package/dist/learning/model-registry.d.ts +141 -2
- package/dist/learning/model-registry.d.ts.map +1 -1
- package/dist/learning/model-registry.js +324 -38
- package/dist/learning/model-registry.js.map +1 -1
- package/dist/learning/model-scoring.d.ts.map +1 -1
- package/dist/learning/model-scoring.js +8 -1
- package/dist/learning/model-scoring.js.map +1 -1
- package/dist/learning/model-selection.d.ts.map +1 -1
- package/dist/learning/model-selection.js +41 -0
- package/dist/learning/model-selection.js.map +1 -1
- package/dist/learning/outcome-observation.d.ts +49 -0
- package/dist/learning/outcome-observation.d.ts.map +1 -0
- package/dist/learning/outcome-observation.js +95 -0
- package/dist/learning/outcome-observation.js.map +1 -0
- package/dist/learning/pair-entitlement.d.ts +184 -0
- package/dist/learning/pair-entitlement.d.ts.map +1 -0
- package/dist/learning/pair-entitlement.js +214 -0
- package/dist/learning/pair-entitlement.js.map +1 -0
- package/dist/learning/provider-fallback.d.ts +23 -1
- package/dist/learning/provider-fallback.d.ts.map +1 -1
- package/dist/learning/provider-fallback.js +24 -0
- package/dist/learning/provider-fallback.js.map +1 -1
- package/dist/learning/reasoning-trace.d.ts +65 -1
- package/dist/learning/reasoning-trace.d.ts.map +1 -1
- package/dist/learning/reasoning-trace.js +123 -1
- package/dist/learning/reasoning-trace.js.map +1 -1
- package/dist/learning/requirement-probe.d.ts +55 -0
- package/dist/learning/requirement-probe.d.ts.map +1 -0
- package/dist/learning/requirement-probe.js +77 -0
- package/dist/learning/requirement-probe.js.map +1 -0
- package/dist/learning/resilient-call.d.ts +20 -1
- package/dist/learning/resilient-call.d.ts.map +1 -1
- package/dist/learning/resilient-call.js +42 -4
- package/dist/learning/resilient-call.js.map +1 -1
- package/dist/learning/response-usability.d.ts +85 -0
- package/dist/learning/response-usability.d.ts.map +1 -0
- package/dist/learning/response-usability.js +135 -0
- package/dist/learning/response-usability.js.map +1 -0
- package/dist/learning/router-bandit.d.ts +132 -0
- package/dist/learning/router-bandit.d.ts.map +1 -1
- package/dist/learning/router-bandit.js +253 -0
- package/dist/learning/router-bandit.js.map +1 -1
- package/dist/learning/routing-history.d.ts +41 -2
- package/dist/learning/routing-history.d.ts.map +1 -1
- package/dist/learning/routing-history.js.map +1 -1
- package/dist/learning/run-trace.d.ts +21 -0
- package/dist/learning/run-trace.d.ts.map +1 -1
- package/dist/learning/run-trace.js +38 -0
- package/dist/learning/run-trace.js.map +1 -1
- package/dist/learning/session-grant.d.ts +75 -0
- package/dist/learning/session-grant.d.ts.map +1 -0
- package/dist/learning/session-grant.js +112 -0
- package/dist/learning/session-grant.js.map +1 -0
- package/dist/learning/task-model-continuity.d.ts +73 -0
- package/dist/learning/task-model-continuity.d.ts.map +1 -0
- package/dist/learning/task-model-continuity.js +87 -0
- package/dist/learning/task-model-continuity.js.map +1 -0
- package/dist/learning/turn-feedback.d.ts +93 -0
- package/dist/learning/turn-feedback.d.ts.map +1 -0
- package/dist/learning/turn-feedback.js +127 -0
- package/dist/learning/turn-feedback.js.map +1 -0
- package/dist/learning/turn-report.d.ts +104 -2
- package/dist/learning/turn-report.d.ts.map +1 -1
- package/dist/learning/turn-report.js +161 -6
- package/dist/learning/turn-report.js.map +1 -1
- package/dist/learning/verdict-routing.d.ts +51 -0
- package/dist/learning/verdict-routing.d.ts.map +1 -0
- package/dist/learning/verdict-routing.js +122 -0
- package/dist/learning/verdict-routing.js.map +1 -0
- package/dist/mcp/client.d.ts.map +1 -1
- package/dist/mcp/client.js +5 -0
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/manager.d.ts +10 -0
- package/dist/mcp/manager.d.ts.map +1 -1
- package/dist/mcp/manager.js +20 -0
- package/dist/mcp/manager.js.map +1 -1
- package/dist/mcp/mcp-discovery.d.ts +34 -0
- package/dist/mcp/mcp-discovery.d.ts.map +1 -0
- package/dist/mcp/mcp-discovery.js +71 -0
- package/dist/mcp/mcp-discovery.js.map +1 -0
- package/dist/mcp/mcp-schema-cache.d.ts +17 -0
- package/dist/mcp/mcp-schema-cache.d.ts.map +1 -1
- package/dist/mcp/mcp-schema-cache.js +47 -3
- package/dist/mcp/mcp-schema-cache.js.map +1 -1
- package/dist/mcp/types.d.ts +28 -0
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js.map +1 -1
- package/dist/tools/ask-user.d.ts.map +1 -1
- package/dist/tools/ask-user.js +4 -0
- package/dist/tools/ask-user.js.map +1 -1
- package/dist/tools/capability-registry.d.ts +150 -0
- package/dist/tools/capability-registry.d.ts.map +1 -0
- package/dist/tools/capability-registry.js +400 -0
- package/dist/tools/capability-registry.js.map +1 -0
- package/dist/tools/child-agent-runtime.d.ts.map +1 -1
- package/dist/tools/child-agent-runtime.js +19 -5
- package/dist/tools/child-agent-runtime.js.map +1 -1
- package/dist/tools/coding-tools.d.ts +17 -5
- package/dist/tools/coding-tools.d.ts.map +1 -1
- package/dist/tools/coding-tools.js +80 -11
- package/dist/tools/coding-tools.js.map +1 -1
- package/dist/tools/command-memo.d.ts +116 -0
- package/dist/tools/command-memo.d.ts.map +1 -0
- package/dist/tools/command-memo.js +202 -0
- package/dist/tools/command-memo.js.map +1 -0
- package/dist/tools/git-tool.d.ts.map +1 -1
- package/dist/tools/git-tool.js +13 -3
- package/dist/tools/git-tool.js.map +1 -1
- package/dist/tools/harness-directive.d.ts +42 -0
- package/dist/tools/harness-directive.d.ts.map +1 -0
- package/dist/tools/harness-directive.js +45 -0
- package/dist/tools/harness-directive.js.map +1 -0
- package/dist/tools/loop-skill-hint.d.ts +74 -174
- package/dist/tools/loop-skill-hint.d.ts.map +1 -1
- package/dist/tools/loop-skill-hint.js +110 -536
- package/dist/tools/loop-skill-hint.js.map +1 -1
- package/dist/tools/mcp-client-tool.d.ts +2 -0
- package/dist/tools/mcp-client-tool.d.ts.map +1 -1
- package/dist/tools/mcp-client-tool.js +3 -0
- package/dist/tools/mcp-client-tool.js.map +1 -1
- package/dist/tools/modality/shared.d.ts +1 -4
- package/dist/tools/modality/shared.d.ts.map +1 -1
- package/dist/tools/modality/shared.js +7 -22
- package/dist/tools/modality/shared.js.map +1 -1
- package/dist/tools/plan-store.d.ts +20 -2
- package/dist/tools/plan-store.d.ts.map +1 -1
- package/dist/tools/plan-store.js +51 -7
- package/dist/tools/plan-store.js.map +1 -1
- package/dist/tools/registry.d.ts +76 -3
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +486 -26
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/remediation-ladder.d.ts.map +1 -1
- package/dist/tools/remediation-ladder.js +8 -0
- package/dist/tools/remediation-ladder.js.map +1 -1
- package/dist/tools/run-cli.d.ts.map +1 -1
- package/dist/tools/run-cli.js +29 -4
- package/dist/tools/run-cli.js.map +1 -1
- package/dist/tools/run-terminal.d.ts +11 -0
- package/dist/tools/run-terminal.d.ts.map +1 -1
- package/dist/tools/run-terminal.js +265 -10
- package/dist/tools/run-terminal.js.map +1 -1
- package/dist/tools/tool-loop.d.ts +321 -13
- package/dist/tools/tool-loop.d.ts.map +1 -1
- package/dist/tools/tool-loop.js +867 -66
- package/dist/tools/tool-loop.js.map +1 -1
- package/dist/utils/atomic-store.d.ts +53 -0
- package/dist/utils/atomic-store.d.ts.map +1 -0
- package/dist/utils/atomic-store.js +178 -0
- package/dist/utils/atomic-store.js.map +1 -0
- package/dist/utils/binary-probe.d.ts +25 -0
- package/dist/utils/binary-probe.d.ts.map +1 -0
- package/dist/utils/binary-probe.js +48 -0
- package/dist/utils/binary-probe.js.map +1 -0
- package/dist/utils/workspace-path.d.ts +50 -0
- package/dist/utils/workspace-path.d.ts.map +1 -0
- package/dist/utils/workspace-path.js +86 -0
- package/dist/utils/workspace-path.js.map +1 -0
- package/dist/web-dashboard/chat-console.d.ts +24 -0
- package/dist/web-dashboard/chat-console.d.ts.map +1 -1
- package/dist/web-dashboard/chat-console.js +38 -0
- package/dist/web-dashboard/chat-console.js.map +1 -1
- package/dist/web-dashboard/project-context.d.ts +27 -2
- package/dist/web-dashboard/project-context.d.ts.map +1 -1
- package/dist/web-dashboard/project-context.js +32 -2
- package/dist/web-dashboard/project-context.js.map +1 -1
- package/dist/web-dashboard/server.d.ts +11 -0
- package/dist/web-dashboard/server.d.ts.map +1 -1
- package/dist/web-dashboard/server.js +362 -11
- package/dist/web-dashboard/server.js.map +1 -1
- package/dist/web-dashboard/src/types.d.ts +170 -1
- package/dist/web-dashboard/src/types.d.ts.map +1 -1
- package/dist/web-dashboard/workspace-guard.d.ts +11 -2
- package/dist/web-dashboard/workspace-guard.d.ts.map +1 -1
- package/dist/web-dashboard/workspace-guard.js +24 -12
- package/dist/web-dashboard/workspace-guard.js.map +1 -1
- package/dist/web-dashboard/workspace-resolution.d.ts +87 -0
- package/dist/web-dashboard/workspace-resolution.d.ts.map +1 -0
- package/dist/web-dashboard/workspace-resolution.js +105 -0
- package/dist/web-dashboard/workspace-resolution.js.map +1 -0
- package/package.json +1 -1
- package/src/web-dashboard/public/assets/index-zjbdJnO-.js +210 -0
- package/src/web-dashboard/public/assets/index-zjbdJnO-.js.map +1 -0
- package/src/web-dashboard/public/index.html +1 -1
- package/src/web-dashboard/public/assets/index-DhiuR4S2.js +0 -210
- package/src/web-dashboard/public/assets/index-DhiuR4S2.js.map +0 -1
|
@@ -25,6 +25,8 @@ import { loadEnv } from '../utils/env.js';
|
|
|
25
25
|
import { ConfigManager } from '../config/manager.js';
|
|
26
26
|
import { runAllChecks } from '../cli/doctor.js';
|
|
27
27
|
import { getAutoRouter } from '../learning/auto-router.js';
|
|
28
|
+
import { acceptanceSummary, collectLabelledTurns, serializeLabelledTurns, parseCorpusText, detectCorpusFormat, mergeImportedLabels, } from '../learning/acceptance-model.js';
|
|
29
|
+
import { readDecisions, recallDecisions, reviseDecision } from '../learning/decision-log.js';
|
|
28
30
|
import { withStrictModel } from '../inference/route-resolver.js';
|
|
29
31
|
import { readRecallHits } from '../context/session-recall.js';
|
|
30
32
|
import { getRouterPromotion } from '../learning/router-promotion.js';
|
|
@@ -2618,6 +2620,25 @@ function resolveDashboardCwd(configManager) {
|
|
|
2618
2620
|
return undefined;
|
|
2619
2621
|
}
|
|
2620
2622
|
}
|
|
2623
|
+
/**
|
|
2624
|
+
* The directory a decisions request targets: a directory the client named that
|
|
2625
|
+
* actually exists, else the configured workspace (`dashboard.cwd`), else the
|
|
2626
|
+
* process cwd. Never returns a path that is not a directory, so a read or a
|
|
2627
|
+
* revise can only ever touch a real project's own `.nuvira/` store.
|
|
2628
|
+
*/
|
|
2629
|
+
function resolveDecisionDir(requested) {
|
|
2630
|
+
const named = typeof requested === 'string' ? requested.trim() : '';
|
|
2631
|
+
if (named) {
|
|
2632
|
+
try {
|
|
2633
|
+
if (existsSync(named) && statSync(named).isDirectory())
|
|
2634
|
+
return resolve(named);
|
|
2635
|
+
}
|
|
2636
|
+
catch {
|
|
2637
|
+
// Unusable path — fall through to the configured default.
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
return resolveDashboardCwd() ?? process.cwd();
|
|
2641
|
+
}
|
|
2621
2642
|
function summarizeProvider(type, configManager) {
|
|
2622
2643
|
const c = (configManager.getAll().providers || {})[type];
|
|
2623
2644
|
const envVar = PROVIDER_ENV_VARS[type];
|
|
@@ -3120,7 +3141,9 @@ function handleRequest(req, res) {
|
|
|
3120
3141
|
writeJson(res, 200, {
|
|
3121
3142
|
ok: true,
|
|
3122
3143
|
file: m.hookDeclarationsFile(),
|
|
3123
|
-
hooks
|
|
3144
|
+
// Built-in starter hooks (disabled) are merged in for DISPLAY; the
|
|
3145
|
+
// runtime still evaluates only the in-force user set.
|
|
3146
|
+
hooks: m.listHookDeclarations(),
|
|
3124
3147
|
events: m.HOOK_EVENTS,
|
|
3125
3148
|
eventDescriptions: m.HOOK_EVENT_DESCRIPTIONS,
|
|
3126
3149
|
actionKinds: m.HOOK_ACTION_KINDS,
|
|
@@ -5141,6 +5164,149 @@ function handleRequest(req, res) {
|
|
|
5141
5164
|
res.end(JSON.stringify(readModelRegistryData()));
|
|
5142
5165
|
return;
|
|
5143
5166
|
}
|
|
5167
|
+
// GET /api/acceptance (Bundle 32) — the acceptance corpus at a glance: labelled
|
|
5168
|
+
// counts, class balance, the per-pair record, and whether the read-only fit has
|
|
5169
|
+
// enough to train. READ is open like the other model endpoints — it carries only
|
|
5170
|
+
// aggregate counts and a fit that nothing routes on. Always 200; an unavailable
|
|
5171
|
+
// store degrades to an empty summary rather than a spinner the UI never leaves.
|
|
5172
|
+
if (pathname === '/api/acceptance' && req.method === 'GET') {
|
|
5173
|
+
try {
|
|
5174
|
+
const s = acceptanceSummary();
|
|
5175
|
+
writeJson(res, 200, {
|
|
5176
|
+
labelled: s.labelled,
|
|
5177
|
+
accepted: s.accepted,
|
|
5178
|
+
rejected: s.rejected,
|
|
5179
|
+
bySource: s.bySource,
|
|
5180
|
+
byPair: s.byPair,
|
|
5181
|
+
fit: s.fit.ok
|
|
5182
|
+
? {
|
|
5183
|
+
ok: true,
|
|
5184
|
+
n: s.fit.model.n,
|
|
5185
|
+
positives: s.fit.model.positives,
|
|
5186
|
+
negatives: s.fit.model.negatives,
|
|
5187
|
+
featureNames: s.fit.model.featureNames,
|
|
5188
|
+
weights: s.fit.model.weights,
|
|
5189
|
+
bias: s.fit.model.bias,
|
|
5190
|
+
}
|
|
5191
|
+
: {
|
|
5192
|
+
ok: false,
|
|
5193
|
+
reason: s.fit.reason,
|
|
5194
|
+
n: s.fit.n,
|
|
5195
|
+
positives: s.fit.positives,
|
|
5196
|
+
negatives: s.fit.negatives,
|
|
5197
|
+
},
|
|
5198
|
+
});
|
|
5199
|
+
}
|
|
5200
|
+
catch {
|
|
5201
|
+
writeJson(res, 200, {
|
|
5202
|
+
labelled: 0,
|
|
5203
|
+
accepted: 0,
|
|
5204
|
+
rejected: 0,
|
|
5205
|
+
bySource: {},
|
|
5206
|
+
byPair: {},
|
|
5207
|
+
fit: { ok: false, reason: 'acceptance model unavailable', n: 0, positives: 0, negatives: 0 },
|
|
5208
|
+
});
|
|
5209
|
+
}
|
|
5210
|
+
return;
|
|
5211
|
+
}
|
|
5212
|
+
// GET /api/acceptance/export (Bundle 34) — the labelled corpus as a download, the
|
|
5213
|
+
// SAME rows `nuvira rate --export` writes, so the CLI and the dashboard ship an
|
|
5214
|
+
// identical file. `?format=csv` selects CSV; JSON is the default.
|
|
5215
|
+
if (pathname === '/api/acceptance/export' && req.method === 'GET') {
|
|
5216
|
+
try {
|
|
5217
|
+
const fmtParam = (new URL(req.url ?? '', 'http://localhost').searchParams.get('format') || '').toLowerCase();
|
|
5218
|
+
const fmt = fmtParam === 'csv' ? 'csv' : 'json';
|
|
5219
|
+
const text = serializeLabelledTurns(collectLabelledTurns(), fmt);
|
|
5220
|
+
res.writeHead(200, {
|
|
5221
|
+
'Content-Type': fmt === 'csv' ? 'text/csv; charset=utf-8' : 'application/json; charset=utf-8',
|
|
5222
|
+
'Content-Disposition': `attachment; filename="acceptance-corpus.${fmt}"`,
|
|
5223
|
+
});
|
|
5224
|
+
res.end(text);
|
|
5225
|
+
}
|
|
5226
|
+
catch {
|
|
5227
|
+
writeJson(res, 500, { error: 'Could not export the acceptance corpus' });
|
|
5228
|
+
}
|
|
5229
|
+
return;
|
|
5230
|
+
}
|
|
5231
|
+
// POST /api/acceptance/import { text, format? } (Bundle 34) — merge a corpus
|
|
5232
|
+
// collected elsewhere into the local store. The browser reads the file and posts
|
|
5233
|
+
// its TEXT, so the endpoint needs no multipart handling. Deduped by trace, so
|
|
5234
|
+
// re-importing is idempotent. Nothing routes on these labels.
|
|
5235
|
+
if (pathname === '/api/acceptance/import' && req.method === 'POST') {
|
|
5236
|
+
void (async () => {
|
|
5237
|
+
const body = await readJsonBody(req);
|
|
5238
|
+
const text = body && typeof body.text === 'string' ? body.text : '';
|
|
5239
|
+
if (!text.trim()) {
|
|
5240
|
+
writeJson(res, 400, { error: 'No corpus text supplied — POST { text, format? }' });
|
|
5241
|
+
return;
|
|
5242
|
+
}
|
|
5243
|
+
const fmt = body && (body.format === 'csv' || body.format === 'json')
|
|
5244
|
+
? body.format
|
|
5245
|
+
: detectCorpusFormat(undefined, text);
|
|
5246
|
+
const rows = parseCorpusText(text, fmt);
|
|
5247
|
+
if (rows.length === 0) {
|
|
5248
|
+
writeJson(res, 400, { error: 'No labelled turns found in the supplied corpus' });
|
|
5249
|
+
return;
|
|
5250
|
+
}
|
|
5251
|
+
const counts = mergeImportedLabels(rows);
|
|
5252
|
+
writeJson(res, 200, { ok: true, imported: rows.length, ...counts });
|
|
5253
|
+
})();
|
|
5254
|
+
return;
|
|
5255
|
+
}
|
|
5256
|
+
// ── The project's decision log (Bundle 36) ──────────────────────────────
|
|
5257
|
+
//
|
|
5258
|
+
// The decisions a project's turns asked the user to make (written by
|
|
5259
|
+
// `ask_user`). READ-ONLY apart from `revise`, which rewrites ONE record in the
|
|
5260
|
+
// project's own `.nuvira/` store. The dashboard is the same surface the CLI is
|
|
5261
|
+
// (`nuvira decisions`), reading the same files, so the two cannot disagree.
|
|
5262
|
+
//
|
|
5263
|
+
// GET /api/decisions?dir=<path>&for=<text>&limit=<n>
|
|
5264
|
+
// dir defaults to the configured workspace (`dashboard.cwd`), then the
|
|
5265
|
+
// process cwd — the SAME fallback the project picker uses.
|
|
5266
|
+
if (pathname === '/api/decisions' && req.method === 'GET') {
|
|
5267
|
+
const dir = resolveDecisionDir(url.searchParams.get('dir'));
|
|
5268
|
+
const forText = (url.searchParams.get('for') ?? '').trim();
|
|
5269
|
+
try {
|
|
5270
|
+
if (forText) {
|
|
5271
|
+
const limit = Math.max(1, Math.min(50, Number(url.searchParams.get('limit')) || 5));
|
|
5272
|
+
writeJson(res, 200, { ok: true, dir, relevant: true, decisions: recallDecisions(dir, forText, limit) });
|
|
5273
|
+
}
|
|
5274
|
+
else {
|
|
5275
|
+
writeJson(res, 200, { ok: true, dir, relevant: false, decisions: readDecisions(dir) });
|
|
5276
|
+
}
|
|
5277
|
+
}
|
|
5278
|
+
catch {
|
|
5279
|
+
// Best-effort: an unreadable store is an empty log, never a 500.
|
|
5280
|
+
writeJson(res, 200, { ok: true, dir, relevant: Boolean(forText), decisions: [] });
|
|
5281
|
+
}
|
|
5282
|
+
return;
|
|
5283
|
+
}
|
|
5284
|
+
// POST /api/decisions/revise { id, answer, note?, dir? } — change ONE decision,
|
|
5285
|
+
// keeping the previous answer in its history. Open, like the other turn/feedback
|
|
5286
|
+
// surfaces: it records a choice ABOUT this project rather than changing config.
|
|
5287
|
+
if (pathname === '/api/decisions/revise' && req.method === 'POST') {
|
|
5288
|
+
void (async () => {
|
|
5289
|
+
const body = await readJsonBody(req);
|
|
5290
|
+
const id = typeof body?.id === 'string' ? body.id.trim() : '';
|
|
5291
|
+
const answer = typeof body?.answer === 'string' ? body.answer.trim() : '';
|
|
5292
|
+
const note = typeof body?.note === 'string' && body.note.trim() ? body.note.trim() : undefined;
|
|
5293
|
+
if (!id || !answer) {
|
|
5294
|
+
writeJson(res, 400, { ok: false, error: 'Expected { id, answer }.' });
|
|
5295
|
+
return;
|
|
5296
|
+
}
|
|
5297
|
+
// The workspace the page is showing — a directory that EXISTS, else the
|
|
5298
|
+
// configured default. A revise only ever writes inside that directory's own
|
|
5299
|
+
// `.nuvira/` store.
|
|
5300
|
+
const dir = resolveDecisionDir(typeof body?.dir === 'string' ? body.dir : undefined);
|
|
5301
|
+
const revised = reviseDecision(dir, id, answer, note);
|
|
5302
|
+
if (!revised) {
|
|
5303
|
+
writeJson(res, 404, { ok: false, error: `No decision with id ${id} for this workspace.` });
|
|
5304
|
+
return;
|
|
5305
|
+
}
|
|
5306
|
+
writeJson(res, 200, { ok: true, decision: revised });
|
|
5307
|
+
})();
|
|
5308
|
+
return;
|
|
5309
|
+
}
|
|
5144
5310
|
// Model Discovery Timeline endpoint
|
|
5145
5311
|
if (pathname === '/api/model-timeline') {
|
|
5146
5312
|
try {
|
|
@@ -5288,6 +5454,32 @@ function handleRequest(req, res) {
|
|
|
5288
5454
|
res.end(JSON.stringify(readTracesData()));
|
|
5289
5455
|
return;
|
|
5290
5456
|
}
|
|
5457
|
+
// The USER's verdict on a turn — the one label a quality signal can be fit to.
|
|
5458
|
+
// POST /api/traces/:id/verdict { verdict: 'accepted' | 'rejected' }.
|
|
5459
|
+
//
|
|
5460
|
+
// Open, like the other turn surfaces: it records feedback ABOUT a turn rather
|
|
5461
|
+
// than changing configuration. It writes through the SAME module the CLI uses
|
|
5462
|
+
// (`learning/turn-feedback.ts`), so the two surfaces cannot drift into two
|
|
5463
|
+
// different notions of what a verdict means.
|
|
5464
|
+
if (pathname.startsWith('/api/traces/') && pathname.endsWith('/verdict') && req.method === 'POST') {
|
|
5465
|
+
void (async () => {
|
|
5466
|
+
const traceId = decodeURIComponent(pathname.slice('/api/traces/'.length, -'/verdict'.length));
|
|
5467
|
+
const body = await readJsonBody(req);
|
|
5468
|
+
const verdict = body?.verdict;
|
|
5469
|
+
if (verdict !== 'accepted' && verdict !== 'rejected') {
|
|
5470
|
+
writeJson(res, 400, { ok: false, error: "Expected { verdict: 'accepted' | 'rejected' }." });
|
|
5471
|
+
return;
|
|
5472
|
+
}
|
|
5473
|
+
const { rateTurn } = await import('../learning/turn-feedback.js');
|
|
5474
|
+
const result = rateTurn({ verdict, traceId, source: 'dashboard' });
|
|
5475
|
+
if (!result.ok) {
|
|
5476
|
+
writeJson(res, 404, { ok: false, error: result.error });
|
|
5477
|
+
return;
|
|
5478
|
+
}
|
|
5479
|
+
writeJson(res, 200, { ok: true, rated: result.rated });
|
|
5480
|
+
})();
|
|
5481
|
+
return;
|
|
5482
|
+
}
|
|
5291
5483
|
if (pathname.startsWith('/api/traces/')) {
|
|
5292
5484
|
const traceId = decodeURIComponent(pathname.slice('/api/traces/'.length));
|
|
5293
5485
|
const trace = readTraceDetail(traceId);
|
|
@@ -5300,6 +5492,117 @@ function handleRequest(req, res) {
|
|
|
5300
5492
|
res.end(JSON.stringify(trace));
|
|
5301
5493
|
return;
|
|
5302
5494
|
}
|
|
5495
|
+
// ── Bundle 37/39/40 — one picture of consent, and how much the harness spoke ──
|
|
5496
|
+
// Open like the other read paths: these expose policy and counts, never data.
|
|
5497
|
+
if (pathname === '/api/gates') {
|
|
5498
|
+
void (async () => {
|
|
5499
|
+
const { summarizeGateFriction } = await import('../learning/gate-friction.js');
|
|
5500
|
+
writeJson(res, 200, { ok: true, ...summarizeGateFriction(readTracesFile()) });
|
|
5501
|
+
})();
|
|
5502
|
+
return;
|
|
5503
|
+
}
|
|
5504
|
+
if (pathname === '/api/consent') {
|
|
5505
|
+
void (async () => {
|
|
5506
|
+
const { consentPicture } = await import('../learning/consent-picture.js');
|
|
5507
|
+
writeJson(res, 200, { ok: true, picture: consentPicture() });
|
|
5508
|
+
})();
|
|
5509
|
+
return;
|
|
5510
|
+
}
|
|
5511
|
+
// The live session grants (Bundle 37a). The console owns every session's plan
|
|
5512
|
+
// store, so it is the one place that can see them all.
|
|
5513
|
+
if (pathname === '/api/session-grants') {
|
|
5514
|
+
writeJson(res, 200, { ok: true, grants: chatConsole.listSessionGrants() });
|
|
5515
|
+
return;
|
|
5516
|
+
}
|
|
5517
|
+
// Ending a grant is the user asking to be asked again — it can only make the
|
|
5518
|
+
// agent MORE conservative, so it needs no further confirmation.
|
|
5519
|
+
if (pathname === '/api/session-grants/clear' && req.method === 'POST') {
|
|
5520
|
+
void (async () => {
|
|
5521
|
+
const body = await readJsonBody(req);
|
|
5522
|
+
const sessionId = typeof body?.sessionId === 'string' ? body.sessionId : '';
|
|
5523
|
+
if (!sessionId) {
|
|
5524
|
+
writeJson(res, 400, { ok: false, error: 'sessionId is required.' });
|
|
5525
|
+
return;
|
|
5526
|
+
}
|
|
5527
|
+
writeJson(res, 200, { ok: true, cleared: chatConsole.revokeSessionGrant(sessionId) });
|
|
5528
|
+
})();
|
|
5529
|
+
return;
|
|
5530
|
+
}
|
|
5531
|
+
// ── Capability readiness — what the agent can do on THIS machine ────────
|
|
5532
|
+
// Open like the other read paths: it exposes capability declarations and PATH
|
|
5533
|
+
// facts, never user data. The page pairs it with `/api/session-grants`, so the
|
|
5534
|
+
// grants shown and the grants ended are read and written through one source.
|
|
5535
|
+
if (pathname === '/api/capabilities' && req.method === 'GET') {
|
|
5536
|
+
void (async () => {
|
|
5537
|
+
const { capabilityReadiness } = await import('../learning/capability-readiness.js');
|
|
5538
|
+
const { listLearnedCommands } = await import('../learning/learned-commands.js');
|
|
5539
|
+
writeJson(res, 200, { ok: true, ...capabilityReadiness(), learnedCommands: listLearnedCommands() });
|
|
5540
|
+
})();
|
|
5541
|
+
return;
|
|
5542
|
+
}
|
|
5543
|
+
// Record (or replace) a per-OS command. A WRITE, so gated like the other
|
|
5544
|
+
// capability-changing surfaces. The store is keyed by (verb, os) and isolated
|
|
5545
|
+
// by $NUVIRA_CONFIG_DIR — the same store `tool_search record` writes.
|
|
5546
|
+
if (pathname === '/api/capabilities/commands' && req.method === 'POST') {
|
|
5547
|
+
void (async () => {
|
|
5548
|
+
const session = adminSessions.validate(bearerToken(req));
|
|
5549
|
+
if (!session) {
|
|
5550
|
+
writeJson(res, 401, { ok: false, error: 'Not authenticated — log in first.' });
|
|
5551
|
+
return;
|
|
5552
|
+
}
|
|
5553
|
+
if (!roleCan(session.role, 'routing.operate')) {
|
|
5554
|
+
writeJson(res, 403, {
|
|
5555
|
+
ok: false,
|
|
5556
|
+
error: `Access denied — role '${session.role}' cannot change capability commands (requires admin or operator).`,
|
|
5557
|
+
});
|
|
5558
|
+
return;
|
|
5559
|
+
}
|
|
5560
|
+
const body = await readJsonBody(req);
|
|
5561
|
+
const verb = typeof body?.verb === 'string' ? body.verb.trim() : '';
|
|
5562
|
+
const commandText = typeof body?.command === 'string' ? body.command.trim() : '';
|
|
5563
|
+
const note = typeof body?.note === 'string' ? body.note.trim() : '';
|
|
5564
|
+
if (!verb || !commandText) {
|
|
5565
|
+
writeJson(res, 400, { ok: false, error: 'A verb and a command are required.' });
|
|
5566
|
+
return;
|
|
5567
|
+
}
|
|
5568
|
+
const { recordLearnedCommand, listLearnedCommands } = await import('../learning/learned-commands.js');
|
|
5569
|
+
const { leadingBinary } = await import('../learning/command-adaptation.js');
|
|
5570
|
+
const bin = leadingBinary(commandText);
|
|
5571
|
+
const entry = recordLearnedCommand({
|
|
5572
|
+
verb,
|
|
5573
|
+
command: commandText,
|
|
5574
|
+
...(bin ? { binary: bin } : {}),
|
|
5575
|
+
...(note ? { note } : {}),
|
|
5576
|
+
});
|
|
5577
|
+
writeJson(res, 200, { ok: true, recorded: entry, commands: listLearnedCommands() });
|
|
5578
|
+
})();
|
|
5579
|
+
return;
|
|
5580
|
+
}
|
|
5581
|
+
if (pathname === '/api/capabilities/commands/forget' && req.method === 'POST') {
|
|
5582
|
+
void (async () => {
|
|
5583
|
+
const session = adminSessions.validate(bearerToken(req));
|
|
5584
|
+
if (!session) {
|
|
5585
|
+
writeJson(res, 401, { ok: false, error: 'Not authenticated — log in first.' });
|
|
5586
|
+
return;
|
|
5587
|
+
}
|
|
5588
|
+
if (!roleCan(session.role, 'routing.operate')) {
|
|
5589
|
+
writeJson(res, 403, {
|
|
5590
|
+
ok: false,
|
|
5591
|
+
error: `Access denied — role '${session.role}' cannot change capability commands (requires admin or operator).`,
|
|
5592
|
+
});
|
|
5593
|
+
return;
|
|
5594
|
+
}
|
|
5595
|
+
const body = await readJsonBody(req);
|
|
5596
|
+
const verb = typeof body?.verb === 'string' ? body.verb.trim() : '';
|
|
5597
|
+
if (!verb) {
|
|
5598
|
+
writeJson(res, 400, { ok: false, error: 'A verb is required.' });
|
|
5599
|
+
return;
|
|
5600
|
+
}
|
|
5601
|
+
const { forgetLearnedCommand, listLearnedCommands } = await import('../learning/learned-commands.js');
|
|
5602
|
+
writeJson(res, 200, { ok: true, forgotten: forgetLearnedCommand(verb), commands: listLearnedCommands() });
|
|
5603
|
+
})();
|
|
5604
|
+
return;
|
|
5605
|
+
}
|
|
5303
5606
|
if (pathname === '/api/routing') {
|
|
5304
5607
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
5305
5608
|
res.end(JSON.stringify(readRoutingInsights()));
|
|
@@ -6789,10 +7092,24 @@ function handleRequest(req, res) {
|
|
|
6789
7092
|
: undefined;
|
|
6790
7093
|
/**
|
|
6791
7094
|
* The workspace for this turn, in priority order: the folder the user
|
|
6792
|
-
* ATTACHED,
|
|
6793
|
-
*
|
|
7095
|
+
* ATTACHED, the one this CONVERSATION attached earlier, one the user NAMED
|
|
7096
|
+
* in their own message, then the operator-configured `dashboard.cwd` — and
|
|
7097
|
+
* otherwise NOTHING. See `resolveTurnWorkspace` (Cluster G); the rule lives
|
|
7098
|
+
* in that module so it can be tested without an HTTP server, and this call
|
|
7099
|
+
* site only carries it out.
|
|
6794
7100
|
*
|
|
6795
|
-
*
|
|
7101
|
+
* The two additions matter because both were reported failures:
|
|
7102
|
+
* - The SESSION's path is read back. The composer re-sends `projectPath`
|
|
7103
|
+
* from React state only, so a reload mid-conversation (or an attach whose
|
|
7104
|
+
* response the UI never got) left the server folder-less and answering
|
|
7105
|
+
* every turn with "I need a project folder" — the user's "agent keep
|
|
7106
|
+
* refusing even after i attach the folder".
|
|
7107
|
+
* - A folder TYPED IN THE MESSAGE is adopted. The guard already treated a
|
|
7108
|
+
* typed absolute path as specific enough not to ask about; it then
|
|
7109
|
+
* discarded it. "as user gives folder either path via chat … we can use
|
|
7110
|
+
* it" is that second half.
|
|
7111
|
+
*
|
|
7112
|
+
* "Nothing" remains the important case. The turn used to fall back to the
|
|
6796
7113
|
* dashboard server's own working directory, so a service started from the
|
|
6797
7114
|
* home folder answered "assess this project" by listing `~` and describing
|
|
6798
7115
|
* whatever unrelated checkout it found there — a confident answer about a
|
|
@@ -6800,17 +7117,35 @@ function handleRequest(req, res) {
|
|
|
6800
7117
|
* guard below turns that into a request for a folder.
|
|
6801
7118
|
*/
|
|
6802
7119
|
const configuredCwd = resolveDashboardCwd();
|
|
6803
|
-
const
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
7120
|
+
const { resolveTurnWorkspace, formatWorkspaceNoticeText } = await import('./workspace-resolution.js');
|
|
7121
|
+
const sessionProjectPath = chatConsole.get(sessionId)?.projectPath;
|
|
7122
|
+
const workspace = resolveTurnWorkspace({
|
|
7123
|
+
...(attachedPath ? { attachedPath } : {}),
|
|
7124
|
+
...(sessionProjectPath ? { sessionPath: sessionProjectPath } : {}),
|
|
7125
|
+
...(configuredCwd ? { configuredCwd } : {}),
|
|
7126
|
+
message,
|
|
7127
|
+
});
|
|
7128
|
+
if (workspace.path) {
|
|
7129
|
+
projectPath = workspace.path;
|
|
7130
|
+
const bundle = getProjectBundle(workspace.path);
|
|
7131
|
+
if (bundle) {
|
|
7132
|
+
projectContext = formatProjectText(bundle, {
|
|
7133
|
+
source: workspace.source,
|
|
7134
|
+
...(workspace.notice ? { notice: workspace.notice } : {}),
|
|
7135
|
+
});
|
|
7136
|
+
}
|
|
6809
7137
|
}
|
|
7138
|
+
/**
|
|
7139
|
+
* The warning the response carries when the turn is NOT in the user's own
|
|
7140
|
+
* folder, so the surface can say where the work went instead of the user
|
|
7141
|
+
* discovering it. Absent for the attached case — the user's own folder
|
|
7142
|
+
* needs no caption.
|
|
7143
|
+
*/
|
|
7144
|
+
const workspaceNotice = formatWorkspaceNoticeText(workspace);
|
|
6810
7145
|
// No workspace and no configured default: an ask that names a project, or
|
|
6811
7146
|
// that produces/consumes files, gets a folder request instead of an answer
|
|
6812
7147
|
// about the wrong tree. General chat is unaffected.
|
|
6813
|
-
if (!
|
|
7148
|
+
if (!workspace.path) {
|
|
6814
7149
|
const { needsProjectAttachment, projectAttachmentPrompt, projectAttachmentFollowups } = await import('./workspace-guard.js');
|
|
6815
7150
|
if (needsProjectAttachment(message)) {
|
|
6816
7151
|
writeJson(res, 200, {
|
|
@@ -6864,6 +7199,10 @@ function handleRequest(req, res) {
|
|
|
6864
7199
|
model,
|
|
6865
7200
|
projectContext,
|
|
6866
7201
|
projectPath,
|
|
7202
|
+
// Cluster G — carry the "no folder attached" state into the turn so a
|
|
7203
|
+
// write asks WHERE instead of landing in whatever directory the
|
|
7204
|
+
// dashboard process was started from (see `unscopedWriteRefusal`).
|
|
7205
|
+
...(workspace.unscoped ? { unscopedWorkspace: true } : {}),
|
|
6867
7206
|
attachments,
|
|
6868
7207
|
...(worktree === undefined ? {} : { worktree }),
|
|
6869
7208
|
...(keepWorktree === undefined ? {} : { keepWorktree }),
|
|
@@ -6936,6 +7275,18 @@ function handleRequest(req, res) {
|
|
|
6936
7275
|
provider: result.provider ?? null,
|
|
6937
7276
|
model: result.model ?? null,
|
|
6938
7277
|
...(routingNotice ? { routingNotice } : {}),
|
|
7278
|
+
// Cluster G — where this turn's workspace came from, when it was not the
|
|
7279
|
+
// folder the user attached: the session's earlier attachment, a folder
|
|
7280
|
+
// they named in the message, or the operator's default. The client shows
|
|
7281
|
+
// it so a file landing somewhere unexpected is explained, not discovered.
|
|
7282
|
+
...(workspaceNotice ? { workspaceNotice } : {}),
|
|
7283
|
+
// The resolved workspace itself, so the client can ATTACH it to the chat
|
|
7284
|
+
// and highlight it. A folder the user named in a message is a folder they
|
|
7285
|
+
// want to keep working in; leaving the composer's chip empty would ask
|
|
7286
|
+
// them for it again on the next turn.
|
|
7287
|
+
...(workspace.path && workspace.source !== 'attached'
|
|
7288
|
+
? { workspacePath: workspace.path, workspaceSource: workspace.source }
|
|
7289
|
+
: {}),
|
|
6939
7290
|
// WS1 — the findings this turn recorded, with the gate's verdicts, so
|
|
6940
7291
|
// a dashboard client reads the same wire form the CLI, the gateway and
|
|
6941
7292
|
// the subagent report (the GUI card is a rendering decision; the FACT
|