muonroi-cli 1.7.2 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/packages/agent-harness-core/src/event-filter.js +1 -0
- package/dist/packages/agent-harness-core/src/event-redact.js +8 -0
- package/dist/packages/agent-harness-core/src/mcp-server.d.ts +16 -0
- package/dist/packages/agent-harness-core/src/mcp-server.js +88 -10
- package/dist/packages/agent-harness-core/src/protocol.d.ts +15 -0
- package/dist/packages/agent-harness-core/src/selector.js +2 -2
- package/dist/packages/agent-harness-core/src/transports/sidechannel.js +1 -1
- package/dist/packages/agent-harness-opentui/src/agent-mode.js +1 -1
- package/dist/packages/agent-harness-opentui/src/install.js +1 -1
- package/dist/src/__test-stubs__/vitest-setup.js +4 -0
- package/dist/src/agent-harness/__tests__/mock-model.spec.js +54 -0
- package/dist/src/agent-harness/mock-model.d.ts +1 -1
- package/dist/src/agent-harness/mock-model.js +143 -6
- package/dist/src/agent-harness/test-spawn.js +3 -1
- package/dist/src/chat/chat-keychain.js +9 -1
- package/dist/src/cli/cost-forensics.js +7 -4
- package/dist/src/cli/keys.d.ts +2 -2
- package/dist/src/cli/keys.js +107 -28
- package/dist/src/cli/usage-report.js +2 -2
- package/dist/src/council/__tests__/abort-threading.test.d.ts +1 -0
- package/dist/src/council/__tests__/abort-threading.test.js +193 -0
- package/dist/src/council/__tests__/clarification-prompt.test.js +21 -1
- package/dist/src/council/__tests__/council-turn-length-emit.test.d.ts +1 -0
- package/dist/src/council/__tests__/council-turn-length-emit.test.js +130 -0
- package/dist/src/council/__tests__/debate-round-budget.test.d.ts +1 -0
- package/dist/src/council/__tests__/debate-round-budget.test.js +45 -0
- package/dist/src/council/__tests__/evaluator-metrics.test.js +3 -0
- package/dist/src/council/__tests__/post-debate-recommendation.test.d.ts +1 -0
- package/dist/src/council/__tests__/post-debate-recommendation.test.js +58 -0
- package/dist/src/council/__tests__/research-tools.test.js +4 -0
- package/dist/src/council/__tests__/round-tools.test.js +6 -0
- package/dist/src/council/clarifier-question-cap.test.d.ts +12 -0
- package/dist/src/council/clarifier-question-cap.test.js +73 -0
- package/dist/src/council/clarifier.d.ts +29 -1
- package/dist/src/council/clarifier.js +64 -1
- package/dist/src/council/debate-planner.d.ts +2 -1
- package/dist/src/council/debate-planner.js +5 -3
- package/dist/src/council/debate.d.ts +9 -0
- package/dist/src/council/debate.js +88 -8
- package/dist/src/council/index.d.ts +46 -1
- package/dist/src/council/index.js +125 -19
- package/dist/src/council/llm.js +41 -13
- package/dist/src/council/prompts.js +36 -1
- package/dist/src/council/types.d.ts +14 -1
- package/dist/src/ee/__tests__/export-transcripts.test.js +1 -1
- package/dist/src/ee/bridge.d.ts +3 -1
- package/dist/src/ee/bridge.js +9 -3
- package/dist/src/ee/bridge.test.js +1 -2
- package/dist/src/ee/client.js +15 -2
- package/dist/src/ee/recall-ledger.d.ts +20 -0
- package/dist/src/ee/recall-ledger.js +40 -1
- package/dist/src/ee/search.d.ts +25 -0
- package/dist/src/ee/search.js +73 -0
- package/dist/src/ee/types.d.ts +15 -1
- package/dist/src/ee/who-am-i.d.ts +41 -0
- package/dist/src/ee/who-am-i.js +143 -0
- package/dist/src/ee/who-am-i.test.d.ts +1 -0
- package/dist/src/ee/who-am-i.test.js +101 -0
- package/dist/src/flow/compaction/index.d.ts +1 -0
- package/dist/src/flow/compaction/index.js +4 -0
- package/dist/src/generated/version.d.ts +1 -1
- package/dist/src/generated/version.js +1 -1
- package/dist/src/headless/council-answers.js +1 -0
- package/dist/src/headless/output.d.ts +30 -1
- package/dist/src/headless/output.js +180 -0
- package/dist/src/headless/output.test.js +61 -1
- package/dist/src/hooks/index.js +48 -2
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +59 -62
- package/dist/src/lsp/client-normalize.test.d.ts +12 -0
- package/dist/src/lsp/client-normalize.test.js +34 -0
- package/dist/src/lsp/client.d.ts +1 -0
- package/dist/src/lsp/client.js +10 -2
- package/dist/src/lsp/manager.d.ts +1 -1
- package/dist/src/lsp/manager.js +13 -5
- package/dist/src/lsp/manager.test.js +41 -2
- package/dist/src/lsp/runtime.d.ts +1 -1
- package/dist/src/lsp/runtime.js +2 -2
- package/dist/src/maintain/__tests__/gh-create-pr.test.js +7 -3
- package/dist/src/maintain/__tests__/pr-builder.test.js +7 -3
- package/dist/src/mcp/__tests__/client-pool.spec.js +3 -3
- package/dist/src/mcp/__tests__/ee-tools.test.js +42 -14
- package/dist/src/mcp/__tests__/forensics-tools.test.js +3 -3
- package/dist/src/mcp/__tests__/lsp-tools.test.js +4 -4
- package/dist/src/mcp/auto-setup.js +0 -8
- package/dist/src/mcp/client-pool.d.ts +1 -1
- package/dist/src/mcp/client-pool.js +25 -9
- package/dist/src/mcp/ee-tools.d.ts +10 -0
- package/dist/src/mcp/ee-tools.js +34 -0
- package/dist/src/mcp/self-verify-jobs.d.ts +1 -0
- package/dist/src/mcp/self-verify-jobs.js +1 -3
- package/dist/src/mcp/self-verify-runner.js +1 -1
- package/dist/src/models/catalog-gemini.test.js +12 -10
- package/dist/src/models/catalog.json +106 -38
- package/dist/src/orchestrator/__tests__/auto-commit.test.d.ts +1 -0
- package/dist/src/orchestrator/__tests__/auto-commit.test.js +142 -0
- package/dist/src/orchestrator/__tests__/batch-turn-runner.test.js +3 -0
- package/dist/src/orchestrator/__tests__/delegations.test.d.ts +1 -0
- package/dist/src/orchestrator/__tests__/delegations.test.js +96 -0
- package/dist/src/orchestrator/__tests__/message-processor.test.js +2 -0
- package/dist/src/orchestrator/__tests__/prompts.test.d.ts +1 -0
- package/dist/src/orchestrator/__tests__/prompts.test.js +88 -0
- package/dist/src/orchestrator/__tests__/stream-runner.test.js +29 -0
- package/dist/src/orchestrator/__tests__/sub-session-delegation.test.d.ts +1 -0
- package/dist/src/orchestrator/__tests__/sub-session-delegation.test.js +507 -0
- package/dist/src/orchestrator/agent.test.js +5 -2
- package/dist/src/orchestrator/auto-commit.d.ts +110 -0
- package/dist/src/orchestrator/auto-commit.js +366 -0
- package/dist/src/orchestrator/batch-turn-runner.d.ts +3 -2
- package/dist/src/orchestrator/batch-turn-runner.js +2 -1
- package/dist/src/orchestrator/compaction-proposer-prompt.d.ts +8 -0
- package/dist/src/orchestrator/compaction-proposer-prompt.js +43 -0
- package/dist/src/orchestrator/compaction.d.ts +22 -0
- package/dist/src/orchestrator/compaction.js +42 -0
- package/dist/src/orchestrator/delegations.d.ts +1 -0
- package/dist/src/orchestrator/delegations.js +41 -0
- package/dist/src/orchestrator/error-utils.js +27 -2
- package/dist/src/orchestrator/message-processor.d.ts +23 -5
- package/dist/src/orchestrator/message-processor.js +226 -2573
- package/dist/src/orchestrator/orchestrator.d.ts +11 -2
- package/dist/src/orchestrator/orchestrator.js +530 -43
- package/dist/src/orchestrator/pending-calls.js +2 -1
- package/dist/src/orchestrator/preprocessor.d.ts +13 -0
- package/dist/src/orchestrator/preprocessor.js +146 -0
- package/dist/src/orchestrator/prompts.d.ts +16 -0
- package/dist/src/orchestrator/prompts.js +130 -67
- package/dist/src/orchestrator/safety-askcard.d.ts +66 -0
- package/dist/src/orchestrator/safety-askcard.js +74 -0
- package/dist/src/orchestrator/sandbox.test.js +8 -5
- package/dist/src/orchestrator/scope-ceiling.js +1 -1
- package/dist/src/orchestrator/stall-watchdog.d.ts +47 -0
- package/dist/src/orchestrator/stall-watchdog.js +23 -0
- package/dist/src/orchestrator/stall-watchdog.test.js +36 -1
- package/dist/src/orchestrator/stream-runner.js +52 -30
- package/dist/src/orchestrator/sub-agent-cap.d.ts +2 -0
- package/dist/src/orchestrator/sub-agent-cap.js +12 -4
- package/dist/src/orchestrator/sub-agent-model-tier.js +1 -1
- package/dist/src/orchestrator/subagent-compactor.d.ts +21 -0
- package/dist/src/orchestrator/subagent-compactor.js +148 -24
- package/dist/src/orchestrator/subagent-compactor.spec.js +249 -1
- package/dist/src/orchestrator/text-tool-call-detector.d.ts +9 -5
- package/dist/src/orchestrator/text-tool-call-detector.js +16 -12
- package/dist/src/orchestrator/text-tool-call-detector.test.js +66 -8
- package/dist/src/orchestrator/tool-args-repair.js +1 -1
- package/dist/src/orchestrator/tool-engine.d.ts +153 -0
- package/dist/src/orchestrator/tool-engine.js +3138 -0
- package/dist/src/orchestrator/turn-runner-deps.d.ts +3 -0
- package/dist/src/pil/__tests__/discovery-types.test.js +15 -4
- package/dist/src/pil/__tests__/discovery.test.js +89 -145
- package/dist/src/pil/__tests__/dual-run.test.js +2 -0
- package/dist/src/pil/__tests__/layer1-intent-trace.test.js +3 -0
- package/dist/src/pil/__tests__/layer1-intent.test.js +3 -0
- package/dist/src/pil/__tests__/layer16-clarity.test.js +35 -32
- package/dist/src/pil/__tests__/layer18-acceptance.test.js +1 -78
- package/dist/src/pil/__tests__/layer2_5-ponytail.test.d.ts +1 -0
- package/dist/src/pil/__tests__/layer2_5-ponytail.test.js +53 -0
- package/dist/src/pil/__tests__/layer3-ee-injection.test.js +67 -4
- package/dist/src/pil/__tests__/layer3-injected-chunk.test.js +14 -2
- package/dist/src/pil/__tests__/layer4-gsd.test.js +30 -0
- package/dist/src/pil/__tests__/layer5-context.test.js +39 -1
- package/dist/src/pil/__tests__/layer6-output.test.js +30 -2
- package/dist/src/pil/__tests__/llm-classify.test.js +79 -1
- package/dist/src/pil/__tests__/orchestrator-integration.test.js +3 -1
- package/dist/src/pil/__tests__/pipeline.test.js +11 -8
- package/dist/src/pil/__tests__/response-tools.test.js +52 -0
- package/dist/src/pil/agent-operating-contract.d.ts +1 -1
- package/dist/src/pil/agent-operating-contract.js +5 -3
- package/dist/src/pil/agent-operating-contract.test.js +2 -2
- package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
- package/dist/src/pil/cheap-model-playbook.js +1 -1
- package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
- package/dist/src/pil/cheap-model-workbooks.js +1 -1
- package/dist/src/pil/config.d.ts +20 -0
- package/dist/src/pil/config.js +35 -0
- package/dist/src/pil/discovery-types.d.ts +32 -9
- package/dist/src/pil/discovery.d.ts +3 -3
- package/dist/src/pil/discovery.js +138 -244
- package/dist/src/pil/index.d.ts +1 -1
- package/dist/src/pil/index.js +1 -1
- package/dist/src/pil/layer1-intent.d.ts +9 -1
- package/dist/src/pil/layer1-intent.js +62 -7
- package/dist/src/pil/layer1-intent.test.js +112 -2
- package/dist/src/pil/layer15-context-scan.js +1 -1
- package/dist/src/pil/layer16-clarity.d.ts +21 -25
- package/dist/src/pil/layer16-clarity.js +52 -88
- package/dist/src/pil/layer18-acceptance.d.ts +13 -3
- package/dist/src/pil/layer18-acceptance.js +1 -75
- package/dist/src/pil/layer2-personality.js +7 -8
- package/dist/src/pil/layer2_5-ponytail.d.ts +2 -0
- package/dist/src/pil/layer2_5-ponytail.js +41 -0
- package/dist/src/pil/layer3-ee-injection.js +180 -14
- package/dist/src/pil/layer4-gsd.js +22 -8
- package/dist/src/pil/layer5-context.d.ts +1 -0
- package/dist/src/pil/layer5-context.js +26 -11
- package/dist/src/pil/layer6-output.js +23 -5
- package/dist/src/pil/llm-classify.d.ts +11 -0
- package/dist/src/pil/llm-classify.js +196 -3
- package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
- package/dist/src/pil/native-capabilities-workbook.js +4 -3
- package/dist/src/pil/pipeline.js +15 -1
- package/dist/src/pil/response-tools.d.ts +16 -0
- package/dist/src/pil/response-tools.js +41 -0
- package/dist/src/pil/schema.d.ts +8 -0
- package/dist/src/pil/schema.js +24 -3
- package/dist/src/pil/task-tier-map.js +7 -7
- package/dist/src/pil/types.d.ts +9 -3
- package/dist/src/product-loop/__tests__/discovery-interview.test.js +103 -1
- package/dist/src/product-loop/__tests__/gather-selectable-alts.test.js +34 -0
- package/dist/src/product-loop/__tests__/sprint-self-verify.test.js +12 -12
- package/dist/src/product-loop/discovery-interview.d.ts +20 -0
- package/dist/src/product-loop/discovery-interview.js +121 -7
- package/dist/src/product-loop/gather.js +19 -5
- package/dist/src/product-loop/loop-driver.js +2 -2
- package/dist/src/product-loop/sprint-self-verify.js +2 -2
- package/dist/src/providers/__tests__/reasoning-roundtrip.test.js +12 -0
- package/dist/src/providers/auth/__tests__/gemini-oauth.test.d.ts +1 -5
- package/dist/src/providers/auth/__tests__/gemini-oauth.test.js +1 -5
- package/dist/src/providers/auth/gcloud.d.ts +28 -0
- package/dist/src/providers/auth/gcloud.js +102 -0
- package/dist/src/providers/auth/gemini-oauth.d.ts +46 -19
- package/dist/src/providers/auth/gemini-oauth.js +292 -105
- package/dist/src/providers/auth/grok-oauth.d.ts +1 -1
- package/dist/src/providers/auth/grok-oauth.js +1 -1
- package/dist/src/providers/auth/registry.js +28 -6
- package/dist/src/providers/gemini.d.ts +1 -1
- package/dist/src/providers/gemini.js +10 -3
- package/dist/src/providers/keychain.d.ts +2 -2
- package/dist/src/providers/keychain.js +20 -2
- package/dist/src/providers/openai.js +5 -1
- package/dist/src/providers/runtime.d.ts +1 -1
- package/dist/src/providers/runtime.js +11 -2
- package/dist/src/providers/siliconflow-sse-repair.js +1 -1
- package/dist/src/providers/strategies/google.strategy.d.ts +9 -2
- package/dist/src/providers/strategies/google.strategy.js +159 -9
- package/dist/src/providers/strategies/thinking-mode.js +19 -6
- package/dist/src/providers/types.d.ts +1 -1
- package/dist/src/router/decide.test.js +40 -8
- package/dist/src/router/step-router.d.ts +20 -0
- package/dist/src/router/step-router.js +73 -0
- package/dist/src/self-qa/agentic-loop.js +30 -21
- package/dist/src/self-qa/orchestrator.js +5 -5
- package/dist/src/self-qa/scenario-planner.js +1 -1
- package/dist/src/self-qa/spec-emitter.js +4 -4
- package/dist/src/storage/__tests__/hierarchical-session.test.d.ts +1 -0
- package/dist/src/storage/__tests__/hierarchical-session.test.js +161 -0
- package/dist/src/storage/__tests__/sweep-stale-pending.test.js +2 -2
- package/dist/src/storage/index.d.ts +1 -1
- package/dist/src/storage/index.js +1 -1
- package/dist/src/storage/migrations.js +13 -1
- package/dist/src/storage/transcript-response-entry.test.js +18 -5
- package/dist/src/storage/transcript-view.js +7 -1
- package/dist/src/storage/transcript.d.ts +3 -0
- package/dist/src/storage/transcript.js +254 -73
- package/dist/src/storage/ui-interaction-log.d.ts +17 -0
- package/dist/src/storage/usage.js +22 -5
- package/dist/src/tools/__tests__/native-tools.test.js +6 -0
- package/dist/src/tools/bash.d.ts +36 -23
- package/dist/src/tools/bash.js +59 -301
- package/dist/src/tools/bash.test.js +2 -257
- package/dist/src/tools/file-tracker.d.ts +5 -0
- package/dist/src/tools/file-tracker.js +14 -0
- package/dist/src/tools/file.js +2 -0
- package/dist/src/tools/git-safety.d.ts +38 -1
- package/dist/src/tools/git-safety.js +94 -4
- package/dist/src/tools/git-safety.test.js +45 -1
- package/dist/src/tools/native-tools.d.ts +1 -1
- package/dist/src/tools/native-tools.js +66 -1
- package/dist/src/tools/registry-bash-empty-command.test.js +4 -3
- package/dist/src/tools/registry-git-safety.test.js +17 -6
- package/dist/src/tools/registry.d.ts +6 -0
- package/dist/src/tools/registry.js +215 -13
- package/dist/src/types/index.d.ts +8 -2
- package/dist/src/ui/app.d.ts +1 -0
- package/dist/src/ui/app.js +0 -0
- package/dist/src/ui/components/council-question-card.js +1 -0
- package/dist/src/ui/components/message-view.js +37 -3
- package/dist/src/ui/components/structured-response-view.js +7 -0
- package/dist/src/ui/components/task-list-panel.js +3 -12
- package/dist/src/ui/containers/chat-feed.d.ts +40 -0
- package/dist/src/ui/containers/chat-feed.js +66 -0
- package/dist/src/ui/containers/modals-layer.d.ts +87 -0
- package/dist/src/ui/containers/modals-layer.js +18 -0
- package/dist/src/ui/slash/__tests__/menu-parity.test.d.ts +1 -0
- package/dist/src/ui/slash/__tests__/menu-parity.test.js +1 -0
- package/dist/src/ui/slash/__tests__/ponytail.test.d.ts +1 -0
- package/dist/src/ui/slash/__tests__/ponytail.test.js +37 -0
- package/dist/src/ui/slash/expand.js +14 -1
- package/dist/src/ui/slash/export.js +16 -1
- package/dist/src/ui/slash/menu-items.js +1 -0
- package/dist/src/ui/slash/ponytail.d.ts +2 -0
- package/dist/src/ui/slash/ponytail.js +19 -0
- package/dist/src/ui/status-bar/store.js +0 -1
- package/dist/src/ui/status-bar/store.test.js +2 -2
- package/dist/src/ui/use-app-logic.d.ts +26 -0
- package/dist/src/ui/use-app-logic.js +0 -0
- package/dist/src/ui/utils/relaunch.js +1 -1
- package/dist/src/ui/utils/text.d.ts +11 -0
- package/dist/src/ui/utils/text.js +21 -1
- package/dist/src/ui/utils/text.test.js +25 -1
- package/dist/src/ui/utils/tools.js +3 -1
- package/dist/src/usage/cost-log.js +2 -2
- package/dist/src/usage/estimator.d.ts +14 -0
- package/dist/src/usage/estimator.js +22 -0
- package/dist/src/utils/__tests__/compaction-caps.test.d.ts +21 -0
- package/dist/src/utils/__tests__/compaction-caps.test.js +187 -0
- package/dist/src/utils/__tests__/llm-deadline-abort.test.d.ts +1 -0
- package/dist/src/utils/__tests__/llm-deadline-abort.test.js +33 -0
- package/dist/src/utils/__tests__/llm-deadline.test.js +16 -4
- package/dist/src/utils/__tests__/logger.test.d.ts +1 -0
- package/dist/src/utils/__tests__/logger.test.js +115 -0
- package/dist/src/utils/__tests__/settings-agent-first.test.d.ts +1 -0
- package/dist/src/utils/__tests__/settings-agent-first.test.js +48 -0
- package/dist/src/utils/install-manager.d.ts +1 -0
- package/dist/src/utils/install-manager.js +76 -7
- package/dist/src/utils/install-manager.test.js +43 -1
- package/dist/src/utils/llm-deadline.d.ts +9 -1
- package/dist/src/utils/llm-deadline.js +31 -2
- package/dist/src/utils/logger.d.ts +28 -0
- package/dist/src/utils/logger.js +171 -0
- package/dist/src/utils/permission-mode.d.ts +33 -0
- package/dist/src/utils/permission-mode.js +164 -3
- package/dist/src/utils/permission-mode.test.js +92 -1
- package/dist/src/utils/settings.d.ts +36 -32
- package/dist/src/utils/settings.js +151 -123
- package/dist/src/utils/update-checker.test.js +5 -1
- package/package.json +1 -1
|
@@ -22,6 +22,8 @@ export interface RecallLedger {
|
|
|
22
22
|
record(entries: EERecallEntry[] | undefined, query: string): void;
|
|
23
23
|
/** Clear one id once it has been rated. Returns true if it was actually pending. */
|
|
24
24
|
clear(id: string): boolean;
|
|
25
|
+
/** Check if an id was ever cleared (fed back) in this session. Used by PIL Layer 3 to suppress re-injection. */
|
|
26
|
+
wasCleared(id: string): boolean;
|
|
25
27
|
/** Oldest-first list of still-unrated recalls. */
|
|
26
28
|
pending(): PendingRecall[];
|
|
27
29
|
pendingCount(): number;
|
|
@@ -30,3 +32,21 @@ export interface RecallLedger {
|
|
|
30
32
|
export declare function createRecallLedger(): RecallLedger;
|
|
31
33
|
/** Process-scoped singleton = the current MCP session's unrated-recall debt. */
|
|
32
34
|
export declare const sessionRecallLedger: RecallLedger;
|
|
35
|
+
/**
|
|
36
|
+
* Whether the recall-feedback ledger is active. Mirrors the gate env the external
|
|
37
|
+
* MCP ee.query already honours (EXPERIENCE_RECALL_FEEDBACK_GATE) so an operator
|
|
38
|
+
* can disable in-CLI ledger accounting with the same switch. In-CLI we only need
|
|
39
|
+
* on/off — never a hard refusal — so a turn is never blocked. Default on (soft).
|
|
40
|
+
*/
|
|
41
|
+
export declare function isRecallLedgerEnabled(): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Compact, token-bounded reminder of still-unrated surfaced/recalled handles, for
|
|
44
|
+
* injection next to the `[id]` handles the agent already saw. Names the actual
|
|
45
|
+
* `{id, collection}` pairs so an `ee_feedback(id, collection, verdict)` call is
|
|
46
|
+
* actionable — the legacy static nudge named no ids, so the model could not
|
|
47
|
+
* complete the rating even when willing. Capped so a long session can't bloat the
|
|
48
|
+
* prompt (token-thrift).
|
|
49
|
+
*/
|
|
50
|
+
export declare function formatPendingReminder(pending: PendingRecall[], opts?: {
|
|
51
|
+
max?: number;
|
|
52
|
+
}): string;
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
*/
|
|
13
13
|
export function createRecallLedger() {
|
|
14
14
|
const map = new Map();
|
|
15
|
+
// Tracks ids that have been fed back, so PIL Layer 3 can suppress re-injection.
|
|
16
|
+
const cleared = new Set();
|
|
15
17
|
return {
|
|
16
18
|
record(entries, query) {
|
|
17
19
|
if (!Array.isArray(entries))
|
|
@@ -34,7 +36,14 @@ export function createRecallLedger() {
|
|
|
34
36
|
}
|
|
35
37
|
},
|
|
36
38
|
clear(id) {
|
|
37
|
-
|
|
39
|
+
const nid = String(id ?? "").trim();
|
|
40
|
+
const deleted = map.delete(nid);
|
|
41
|
+
if (deleted)
|
|
42
|
+
cleared.add(nid);
|
|
43
|
+
return deleted;
|
|
44
|
+
},
|
|
45
|
+
wasCleared(id) {
|
|
46
|
+
return cleared.has(String(id ?? "").trim());
|
|
38
47
|
},
|
|
39
48
|
pending() {
|
|
40
49
|
return [...map.values()].sort((a, b) => a.ts - b.ts);
|
|
@@ -44,9 +53,39 @@ export function createRecallLedger() {
|
|
|
44
53
|
},
|
|
45
54
|
reset() {
|
|
46
55
|
map.clear();
|
|
56
|
+
cleared.clear();
|
|
47
57
|
},
|
|
48
58
|
};
|
|
49
59
|
}
|
|
50
60
|
/** Process-scoped singleton = the current MCP session's unrated-recall debt. */
|
|
51
61
|
export const sessionRecallLedger = createRecallLedger();
|
|
62
|
+
/**
|
|
63
|
+
* Whether the recall-feedback ledger is active. Mirrors the gate env the external
|
|
64
|
+
* MCP ee.query already honours (EXPERIENCE_RECALL_FEEDBACK_GATE) so an operator
|
|
65
|
+
* can disable in-CLI ledger accounting with the same switch. In-CLI we only need
|
|
66
|
+
* on/off — never a hard refusal — so a turn is never blocked. Default on (soft).
|
|
67
|
+
*/
|
|
68
|
+
export function isRecallLedgerEnabled() {
|
|
69
|
+
return (String(process.env.EXPERIENCE_RECALL_FEEDBACK_GATE ?? "soft")
|
|
70
|
+
.trim()
|
|
71
|
+
.toLowerCase() !== "off");
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Compact, token-bounded reminder of still-unrated surfaced/recalled handles, for
|
|
75
|
+
* injection next to the `[id]` handles the agent already saw. Names the actual
|
|
76
|
+
* `{id, collection}` pairs so an `ee_feedback(id, collection, verdict)` call is
|
|
77
|
+
* actionable — the legacy static nudge named no ids, so the model could not
|
|
78
|
+
* complete the rating even when willing. Capped so a long session can't bloat the
|
|
79
|
+
* prompt (token-thrift).
|
|
80
|
+
*/
|
|
81
|
+
export function formatPendingReminder(pending, opts = {}) {
|
|
82
|
+
if (pending.length === 0)
|
|
83
|
+
return "";
|
|
84
|
+
const max = Math.max(1, Math.min(opts.max ?? 5, 20));
|
|
85
|
+
const shown = pending.slice(0, max);
|
|
86
|
+
const lines = shown.map((p) => ` - [${p.id} ${p.collection ?? "?"}]`);
|
|
87
|
+
const more = pending.length > max ? `\n …and ${pending.length - max} more` : "";
|
|
88
|
+
return (`↳ ${pending.length} earlier EE hint(s) still unrated — rate the one(s) you acted on so the brain keeps what helped: ` +
|
|
89
|
+
`ee_feedback(id, collection, followed|ignored|noise).\n${lines.join("\n")}${more}`);
|
|
90
|
+
}
|
|
52
91
|
//# sourceMappingURL=recall-ledger.js.map
|
package/dist/src/ee/search.d.ts
CHANGED
|
@@ -92,6 +92,31 @@ export declare function feedbackEE(pointId: string, collection: string, verdict:
|
|
|
92
92
|
* compute unrated-recall debt as recalled ids minus fed-back ids. Best-effort.
|
|
93
93
|
*/
|
|
94
94
|
export declare function mirrorFeedbackLocally(pointId: string, collection: string, verdict: string, reason?: string | null, logPath?: string): Promise<void>;
|
|
95
|
+
export interface WriteExperienceResult {
|
|
96
|
+
ok: boolean;
|
|
97
|
+
id?: string;
|
|
98
|
+
error?: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Write a NEW experience/lesson into the brain mid-session so it is RECALLABLE.
|
|
102
|
+
* POSTs to /api/import-memory → storeImportedExperience → upsertEntry, which
|
|
103
|
+
* embeds the text AND writes the `text_bm25` sparse vector (+ a proper payload via
|
|
104
|
+
* buildStorePayload). That dense+sparse write is what makes the lesson reliably
|
|
105
|
+
* recallable via ee_query / passive injection (both the dense and lexical legs can
|
|
106
|
+
* match it). NB: /api/ingest-point writes DENSE-ONLY (no sparse) — its points are
|
|
107
|
+
* lexically invisible and only surface on a strong dense match, so they are NOT
|
|
108
|
+
* reliably recallable; do not use it for recall-critical writes.
|
|
109
|
+
*
|
|
110
|
+
* This is the missing "agent proactively records a mistake→fix lesson" arm of the
|
|
111
|
+
* recall loop: ee_query recalls, ee_feedback rates, ee_write creates. Mirrors
|
|
112
|
+
* feedbackEE's direct-fetch transport (cached baseUrl + bearer token); fails soft.
|
|
113
|
+
*/
|
|
114
|
+
export declare function writeExperienceEE(lesson: string, opts?: {
|
|
115
|
+
collection?: string;
|
|
116
|
+
title?: string;
|
|
117
|
+
projectSlug?: string;
|
|
118
|
+
confidence?: number;
|
|
119
|
+
}): Promise<WriteExperienceResult>;
|
|
95
120
|
/** Reachability probe for the EE server. */
|
|
96
121
|
export declare function healthEE(): Promise<{
|
|
97
122
|
ok: boolean;
|
package/dist/src/ee/search.js
CHANGED
|
@@ -211,6 +211,79 @@ export async function mirrorFeedbackLocally(pointId, collection, verdict, reason
|
|
|
211
211
|
logEeFailure("search.mirrorFeedbackLocally", classifyEeError(err), err);
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Write a NEW experience/lesson into the brain mid-session so it is RECALLABLE.
|
|
216
|
+
* POSTs to /api/import-memory → storeImportedExperience → upsertEntry, which
|
|
217
|
+
* embeds the text AND writes the `text_bm25` sparse vector (+ a proper payload via
|
|
218
|
+
* buildStorePayload). That dense+sparse write is what makes the lesson reliably
|
|
219
|
+
* recallable via ee_query / passive injection (both the dense and lexical legs can
|
|
220
|
+
* match it). NB: /api/ingest-point writes DENSE-ONLY (no sparse) — its points are
|
|
221
|
+
* lexically invisible and only surface on a strong dense match, so they are NOT
|
|
222
|
+
* reliably recallable; do not use it for recall-critical writes.
|
|
223
|
+
*
|
|
224
|
+
* This is the missing "agent proactively records a mistake→fix lesson" arm of the
|
|
225
|
+
* recall loop: ee_query recalls, ee_feedback rates, ee_write creates. Mirrors
|
|
226
|
+
* feedbackEE's direct-fetch transport (cached baseUrl + bearer token); fails soft.
|
|
227
|
+
*/
|
|
228
|
+
export async function writeExperienceEE(lesson, opts = {}) {
|
|
229
|
+
const { loadEEAuthToken, getCachedServerBaseUrl } = await import("./auth.js");
|
|
230
|
+
const { randomUUID } = await import("node:crypto");
|
|
231
|
+
const authToken = (await loadEEAuthToken()) ?? undefined;
|
|
232
|
+
const baseUrl = (getCachedServerBaseUrl() ?? "http://localhost:8082").replace(/\/+$/, "");
|
|
233
|
+
const collection = opts.collection ?? "experience-behavioral";
|
|
234
|
+
const id = randomUUID();
|
|
235
|
+
// storeImportedExperience embeds `${qa.trigger} ${qa.question} ${qa.solution}`,
|
|
236
|
+
// so put the lesson in solution (and the title in question) to anchor the vector.
|
|
237
|
+
const qa = {
|
|
238
|
+
trigger: "",
|
|
239
|
+
question: opts.title ?? "",
|
|
240
|
+
solution: lesson,
|
|
241
|
+
scope: opts.projectSlug ? { project_slug: opts.projectSlug } : {},
|
|
242
|
+
};
|
|
243
|
+
const body = {
|
|
244
|
+
experiences: [
|
|
245
|
+
{
|
|
246
|
+
id,
|
|
247
|
+
collection,
|
|
248
|
+
qa,
|
|
249
|
+
tier: 2,
|
|
250
|
+
confidence: opts.confidence ?? 0.65,
|
|
251
|
+
runtime: "muonroi-cli-agent",
|
|
252
|
+
},
|
|
253
|
+
],
|
|
254
|
+
};
|
|
255
|
+
const headers = { "Content-Type": "application/json" };
|
|
256
|
+
if (authToken)
|
|
257
|
+
headers.Authorization = `Bearer ${authToken}`;
|
|
258
|
+
try {
|
|
259
|
+
const res = await fetch(`${baseUrl}/api/import-memory`, {
|
|
260
|
+
method: "POST",
|
|
261
|
+
headers,
|
|
262
|
+
body: JSON.stringify(body),
|
|
263
|
+
});
|
|
264
|
+
const respText = await res.text();
|
|
265
|
+
let parsed = null;
|
|
266
|
+
try {
|
|
267
|
+
parsed = JSON.parse(respText);
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
/* non-JSON error body — fall through to status handling */
|
|
271
|
+
}
|
|
272
|
+
if (!res.ok) {
|
|
273
|
+
return { ok: false, error: parsed?.error || respText || `HTTP ${res.status}` };
|
|
274
|
+
}
|
|
275
|
+
const r0 = parsed?.results?.[0];
|
|
276
|
+
if (!parsed?.stored || r0?.ok !== true) {
|
|
277
|
+
return { ok: false, error: r0?.reason ?? "not_stored" };
|
|
278
|
+
}
|
|
279
|
+
return { ok: true, id };
|
|
280
|
+
}
|
|
281
|
+
catch (err) {
|
|
282
|
+
const { logEeFailure, classifyEeError } = await import("../utils/ee-logger.js");
|
|
283
|
+
logEeFailure("search.writeExperienceEE", classifyEeError(err), err);
|
|
284
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
285
|
+
}
|
|
286
|
+
}
|
|
214
287
|
/** Reachability probe for the EE server. */
|
|
215
288
|
export async function healthEE() {
|
|
216
289
|
const { createEEClient } = await import("./client.js");
|
package/dist/src/ee/types.d.ts
CHANGED
|
@@ -361,6 +361,20 @@ export interface EERecallOptions {
|
|
|
361
361
|
export interface EEUserResponse {
|
|
362
362
|
user: string;
|
|
363
363
|
}
|
|
364
|
+
export interface BrainProxyOptions {
|
|
365
|
+
/** Override the default system prompt sent to the LLM. */
|
|
366
|
+
systemPrompt?: string;
|
|
367
|
+
/** Request JSON-mode response_format (e.g. { type: "json_object" }). */
|
|
368
|
+
responseFormat?: {
|
|
369
|
+
type: string;
|
|
370
|
+
};
|
|
371
|
+
/** Override the LLM model id used for classification. */
|
|
372
|
+
model?: string;
|
|
373
|
+
/** Override max_tokens for the LLM response. */
|
|
374
|
+
maxTokens?: number;
|
|
375
|
+
/** Override the brain provider (siliconflow | ollama | openai | ...). */
|
|
376
|
+
provider?: string;
|
|
377
|
+
}
|
|
364
378
|
export interface EEClient {
|
|
365
379
|
health(): Promise<{
|
|
366
380
|
ok: boolean;
|
|
@@ -392,7 +406,7 @@ export interface EEClient {
|
|
|
392
406
|
/** Active recall via /api/recall (recallMode). Returns [id col] index + records a surface. */
|
|
393
407
|
recall(query: string, opts?: EERecallOptions): Promise<EERecallResponse | null>;
|
|
394
408
|
user(): Promise<EEUserResponse | null>;
|
|
395
|
-
brainProxy(prompt: string, timeoutMs?: number): Promise<string | null>;
|
|
409
|
+
brainProxy(prompt: string, timeoutMs?: number, options?: BrainProxyOptions): Promise<string | null>;
|
|
396
410
|
pilContext(prompt: string, options?: {
|
|
397
411
|
localeHint?: string;
|
|
398
412
|
projectCtx?: Record<string, unknown>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { OutputStyle } from "../pil/types.js";
|
|
2
|
+
export type PrivacyLevel = "minimal" | "standard" | "full";
|
|
3
|
+
export type WhoAmIDimName = "communication.question_style" | "communication.feedback_style" | "communication.brevity" | "personality.conflict_style" | "personality.risk_tolerance" | "personality.decision_speed" | "work_patterns.energy" | "work_patterns.multitasking" | "work_patterns.session_length" | "work_patterns.delegation_style";
|
|
4
|
+
export interface WhoAmIDim {
|
|
5
|
+
value: string;
|
|
6
|
+
confidence: number;
|
|
7
|
+
samples: number;
|
|
8
|
+
}
|
|
9
|
+
export interface WhoAmIProfile {
|
|
10
|
+
level: PrivacyLevel;
|
|
11
|
+
dims: Partial<Record<WhoAmIDimName, WhoAmIDim>>;
|
|
12
|
+
}
|
|
13
|
+
interface RawDim {
|
|
14
|
+
value: string | null;
|
|
15
|
+
confidence?: number;
|
|
16
|
+
sampleCount?: number;
|
|
17
|
+
samples?: number;
|
|
18
|
+
}
|
|
19
|
+
interface RawProfile {
|
|
20
|
+
dimensions?: Record<string, RawDim>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* PURE: project a raw EE profile to the privacy-gated dims for `level`, applying the
|
|
24
|
+
* positive name allowlist + value!=null commit gate + per-tier confidence floor.
|
|
25
|
+
*/
|
|
26
|
+
export declare function selectWhoAmIDims(raw: RawProfile | null | undefined, level: PrivacyLevel): WhoAmIProfile["dims"];
|
|
27
|
+
/**
|
|
28
|
+
* PURE: derive an output-style baseline from the profile. brevity is the primary
|
|
29
|
+
* signal; decision_speed is a weaker fallback. Returns null when no usable signal
|
|
30
|
+
* exists so the caller keeps its own per-turn default.
|
|
31
|
+
*/
|
|
32
|
+
export declare function outputStyleFromProfile(profile: WhoAmIProfile | null): OutputStyle | null;
|
|
33
|
+
/**
|
|
34
|
+
* Load + cache the privacy-gated profile for this process. The profile changes
|
|
35
|
+
* slowly (rebuilt by the EE Stop hook), so one read per process is enough.
|
|
36
|
+
* Returns null when EE is not installed, privacy is off, or nothing is committed.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getWhoAmIProfile(): WhoAmIProfile | null;
|
|
39
|
+
/** Clear the cache — test-only / after a known profile change. */
|
|
40
|
+
export declare function resetWhoAmICache(): void;
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// src/ee/who-am-i.ts
|
|
2
|
+
//
|
|
3
|
+
// "Who Am I" v4.0 profile provider for the PIL. The personality/work-style profile
|
|
4
|
+
// is DEVICE-LOCAL (~/.experience/profile.yaml) and never leaves the machine, so it
|
|
5
|
+
// cannot come from the EE HTTP API — we read it on-device, reusing the EE install's
|
|
6
|
+
// parser (profile-model.js loadProfile) + privacy gate (config.js getPrivacyLevel)
|
|
7
|
+
// via createRequire (the same in-process pattern as src/ee/bridge.ts).
|
|
8
|
+
//
|
|
9
|
+
// Privacy is enforced HERE at read time via a positive per-dimension-NAME allowlist
|
|
10
|
+
// (defense in depth): the EE writer keeps committed values regardless of privacyLevel,
|
|
11
|
+
// so a standard→minimal downgrade leaves stale Tang-2 values physically in the file —
|
|
12
|
+
// trusting the file would leak opted-out data. Mirrors experience-engine
|
|
13
|
+
// src/profile-render.js. Fail-open: any error / missing EE install returns null and the
|
|
14
|
+
// PIL keeps its own per-turn defaults.
|
|
15
|
+
import { createRequire } from "node:module";
|
|
16
|
+
import * as os from "node:os";
|
|
17
|
+
import * as path from "node:path";
|
|
18
|
+
import { classifyEeError, logEeFailure } from "../utils/ee-logger.js";
|
|
19
|
+
// Tang 1 (work patterns + activity-derived decision_speed — namespaced personality.*
|
|
20
|
+
// but its SOURCE is activity, so it belongs to the minimal tier; allowlist by NAME).
|
|
21
|
+
const TIER_MINIMAL = [
|
|
22
|
+
"work_patterns.energy",
|
|
23
|
+
"work_patterns.multitasking",
|
|
24
|
+
"work_patterns.session_length",
|
|
25
|
+
"personality.decision_speed",
|
|
26
|
+
];
|
|
27
|
+
// Tang 2 (decision + communication style) added at standard. `full` == standard today
|
|
28
|
+
// (no Tang-3 emotional dims exist); the allowlist guarantees emotional.* can never leak.
|
|
29
|
+
const TIER_STANDARD = [
|
|
30
|
+
...TIER_MINIMAL,
|
|
31
|
+
"communication.question_style",
|
|
32
|
+
"communication.feedback_style",
|
|
33
|
+
"communication.brevity",
|
|
34
|
+
"personality.conflict_style",
|
|
35
|
+
"personality.risk_tolerance",
|
|
36
|
+
// delegation_style is `work_patterns.*` by name but transcript-derived, so it commits
|
|
37
|
+
// only at standard+ (the EE writer skips the transcript at `minimal`). Standard-only.
|
|
38
|
+
"work_patterns.delegation_style",
|
|
39
|
+
];
|
|
40
|
+
const ALLOWLIST = {
|
|
41
|
+
minimal: TIER_MINIMAL,
|
|
42
|
+
standard: TIER_STANDARD,
|
|
43
|
+
full: TIER_STANDARD,
|
|
44
|
+
};
|
|
45
|
+
const WORK_DIMS = new Set(TIER_MINIMAL);
|
|
46
|
+
// Coarse work dims commit over 2-3-way splits (confidence ~0.45-0.6); the lower floor
|
|
47
|
+
// keeps the minimal tier usable. Mirrors experience-engine src/profile-render.js.
|
|
48
|
+
const WORK_MIN_CONFIDENCE = 0.45;
|
|
49
|
+
const MIN_CONFIDENCE = 0.6;
|
|
50
|
+
/**
|
|
51
|
+
* PURE: project a raw EE profile to the privacy-gated dims for `level`, applying the
|
|
52
|
+
* positive name allowlist + value!=null commit gate + per-tier confidence floor.
|
|
53
|
+
*/
|
|
54
|
+
export function selectWhoAmIDims(raw, level) {
|
|
55
|
+
const out = {};
|
|
56
|
+
const allow = ALLOWLIST[level];
|
|
57
|
+
if (!allow || !raw?.dimensions)
|
|
58
|
+
return out;
|
|
59
|
+
for (const name of allow) {
|
|
60
|
+
const d = raw.dimensions[name];
|
|
61
|
+
if (!d || d.value == null)
|
|
62
|
+
continue;
|
|
63
|
+
const confidence = Number(d.confidence) || 0;
|
|
64
|
+
const floor = WORK_DIMS.has(name) ? WORK_MIN_CONFIDENCE : MIN_CONFIDENCE;
|
|
65
|
+
if (confidence < floor)
|
|
66
|
+
continue;
|
|
67
|
+
out[name] = {
|
|
68
|
+
value: String(d.value),
|
|
69
|
+
confidence,
|
|
70
|
+
samples: Math.round(Number(d.sampleCount ?? d.samples) || 0),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* PURE: derive an output-style baseline from the profile. brevity is the primary
|
|
77
|
+
* signal; decision_speed is a weaker fallback. Returns null when no usable signal
|
|
78
|
+
* exists so the caller keeps its own per-turn default.
|
|
79
|
+
*/
|
|
80
|
+
export function outputStyleFromProfile(profile) {
|
|
81
|
+
if (!profile)
|
|
82
|
+
return null;
|
|
83
|
+
const brevity = profile.dims["communication.brevity"]?.value;
|
|
84
|
+
if (brevity === "concise")
|
|
85
|
+
return "concise";
|
|
86
|
+
if (brevity === "verbose")
|
|
87
|
+
return "detailed";
|
|
88
|
+
if (brevity === "moderate")
|
|
89
|
+
return "balanced";
|
|
90
|
+
const speed = profile.dims["personality.decision_speed"]?.value;
|
|
91
|
+
if (speed === "fast-intuitive")
|
|
92
|
+
return "concise";
|
|
93
|
+
if (speed === "deliberate")
|
|
94
|
+
return "detailed";
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
let _cache;
|
|
98
|
+
/**
|
|
99
|
+
* Load + cache the privacy-gated profile for this process. The profile changes
|
|
100
|
+
* slowly (rebuilt by the EE Stop hook), so one read per process is enough.
|
|
101
|
+
* Returns null when EE is not installed, privacy is off, or nothing is committed.
|
|
102
|
+
*/
|
|
103
|
+
export function getWhoAmIProfile() {
|
|
104
|
+
if (_cache !== undefined)
|
|
105
|
+
return _cache;
|
|
106
|
+
_cache = loadWhoAmIProfile();
|
|
107
|
+
return _cache;
|
|
108
|
+
}
|
|
109
|
+
/** Clear the cache — test-only / after a known profile change. */
|
|
110
|
+
export function resetWhoAmICache() {
|
|
111
|
+
_cache = undefined;
|
|
112
|
+
}
|
|
113
|
+
function loadWhoAmIProfile() {
|
|
114
|
+
try {
|
|
115
|
+
const req = createRequire(import.meta.url);
|
|
116
|
+
const srcDir = path.join(os.homedir(), ".experience", "src");
|
|
117
|
+
const config = req(path.join(srcDir, "config.js"));
|
|
118
|
+
const model = req(path.join(srcDir, "profile-model.js"));
|
|
119
|
+
if (typeof config.getPrivacyLevel !== "function" || typeof config.getProfilePath !== "function")
|
|
120
|
+
return null;
|
|
121
|
+
if (typeof model.loadProfile !== "function")
|
|
122
|
+
return null;
|
|
123
|
+
const level = String(config.getPrivacyLevel() ?? "off");
|
|
124
|
+
if (level !== "minimal" && level !== "standard" && level !== "full")
|
|
125
|
+
return null;
|
|
126
|
+
const raw = model.loadProfile(config.getProfilePath());
|
|
127
|
+
const dims = selectWhoAmIDims(raw, level);
|
|
128
|
+
if (Object.keys(dims).length === 0)
|
|
129
|
+
return null;
|
|
130
|
+
return { level, dims };
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
// EE not installed (module absent) is an expected feature-off condition, not a
|
|
134
|
+
// failure — stay quiet. Any other error (corrupt profile, throwing module) is a
|
|
135
|
+
// real fault: log it (No-Silent-Catch) and degrade.
|
|
136
|
+
const code = err?.code;
|
|
137
|
+
if (code !== "MODULE_NOT_FOUND" && code !== "ERR_MODULE_NOT_FOUND") {
|
|
138
|
+
logEeFailure("who-am-i.load", classifyEeError(err), err);
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=who-am-i.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import * as os from "node:os";
|
|
2
|
+
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
3
|
+
import { getWhoAmIProfile, outputStyleFromProfile, resetWhoAmICache, selectWhoAmIDims, } from "./who-am-i.js";
|
|
4
|
+
// Build a raw EE profile (the shape ~/.experience/src/profile-model.js loadProfile() returns).
|
|
5
|
+
function rawDim(value, confidence, sampleCount = 20) {
|
|
6
|
+
return { value, confidence, sampleCount, distribution: {}, evidence: null };
|
|
7
|
+
}
|
|
8
|
+
function rawProfile(dims) {
|
|
9
|
+
return { version: 1, updatedAt: null, dimensions: dims };
|
|
10
|
+
}
|
|
11
|
+
describe("selectWhoAmIDims — privacy allowlist + commit/confidence gates", () => {
|
|
12
|
+
const all = () => rawProfile({
|
|
13
|
+
"communication.question_style": rawDim("directive", 0.8),
|
|
14
|
+
"communication.feedback_style": rawDim("implicit", 0.75),
|
|
15
|
+
"communication.brevity": rawDim("concise", 0.83),
|
|
16
|
+
"personality.conflict_style": rawDim("direct-constructive", 0.7),
|
|
17
|
+
"personality.risk_tolerance": rawDim("experimental", 0.72),
|
|
18
|
+
"personality.decision_speed": rawDim("fast-intuitive", 0.7),
|
|
19
|
+
"work_patterns.energy": rawDim("night-owl", 0.6),
|
|
20
|
+
"work_patterns.multitasking": rawDim("sequential-deep", 0.65),
|
|
21
|
+
"work_patterns.session_length": rawDim("long", 0.55),
|
|
22
|
+
"work_patterns.delegation_style": rawDim("autonomous", 0.68),
|
|
23
|
+
});
|
|
24
|
+
test("minimal exposes only the 4 Tang-1 work dims", () => {
|
|
25
|
+
const dims = selectWhoAmIDims(all(), "minimal");
|
|
26
|
+
expect(Object.keys(dims).sort()).toEqual([
|
|
27
|
+
"personality.decision_speed",
|
|
28
|
+
"work_patterns.energy",
|
|
29
|
+
"work_patterns.multitasking",
|
|
30
|
+
"work_patterns.session_length",
|
|
31
|
+
].sort());
|
|
32
|
+
});
|
|
33
|
+
test("standard exposes all 10 committed dims", () => {
|
|
34
|
+
const dims = selectWhoAmIDims(all(), "standard");
|
|
35
|
+
expect(Object.keys(dims).length).toBe(10);
|
|
36
|
+
});
|
|
37
|
+
test("delegation_style is standard-only — stripped at minimal (transcript-derived, not Tang-1)", () => {
|
|
38
|
+
expect(selectWhoAmIDims(all(), "minimal")["work_patterns.delegation_style"]).toBeUndefined();
|
|
39
|
+
expect(selectWhoAmIDims(all(), "standard")["work_patterns.delegation_style"]).toBeDefined();
|
|
40
|
+
});
|
|
41
|
+
test("standard-built profile rendered at minimal strips Tang-2 dims (no stale leak)", () => {
|
|
42
|
+
const dims = selectWhoAmIDims(all(), "minimal");
|
|
43
|
+
expect(dims["communication.brevity"]).toBeUndefined();
|
|
44
|
+
expect(dims["personality.conflict_style"]).toBeUndefined();
|
|
45
|
+
});
|
|
46
|
+
test("pending (value=null) dims are skipped", () => {
|
|
47
|
+
const dims = selectWhoAmIDims(rawProfile({ "communication.brevity": rawDim(null, 0.9, 5) }), "standard");
|
|
48
|
+
expect(Object.keys(dims).length).toBe(0);
|
|
49
|
+
});
|
|
50
|
+
test("per-tier confidence floors: 0.55 Tang-2 drops at 0.6, 0.50 work survives at 0.45", () => {
|
|
51
|
+
const dims = selectWhoAmIDims(rawProfile({
|
|
52
|
+
"communication.brevity": rawDim("concise", 0.55),
|
|
53
|
+
"work_patterns.energy": rawDim("night-owl", 0.5),
|
|
54
|
+
}), "standard");
|
|
55
|
+
expect(dims["communication.brevity"]).toBeUndefined();
|
|
56
|
+
expect(dims["work_patterns.energy"]).toBeDefined();
|
|
57
|
+
});
|
|
58
|
+
test("Tang-3 emotional.* is never exposed (not in any allowlist)", () => {
|
|
59
|
+
const dims = selectWhoAmIDims(rawProfile({ "emotional.mood": rawDim("calm", 0.99) }), "full");
|
|
60
|
+
expect(Object.keys(dims).length).toBe(0);
|
|
61
|
+
});
|
|
62
|
+
test("decision_speed (personality.* but Tang-1) is allowed at minimal — namespace trap", () => {
|
|
63
|
+
const dims = selectWhoAmIDims(rawProfile({ "personality.decision_speed": rawDim("measured", 0.7) }), "minimal");
|
|
64
|
+
expect(dims["personality.decision_speed"]).toBeDefined();
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
describe("outputStyleFromProfile — brevity/decision_speed → OutputStyle", () => {
|
|
68
|
+
const p = (dims) => ({ level: "standard", dims });
|
|
69
|
+
test("brevity concise → concise, verbose → detailed, moderate → balanced", () => {
|
|
70
|
+
expect(outputStyleFromProfile(p({ "communication.brevity": { value: "concise", confidence: 0.8, samples: 20 } }))).toBe("concise");
|
|
71
|
+
expect(outputStyleFromProfile(p({ "communication.brevity": { value: "verbose", confidence: 0.8, samples: 20 } }))).toBe("detailed");
|
|
72
|
+
expect(outputStyleFromProfile(p({ "communication.brevity": { value: "moderate", confidence: 0.8, samples: 20 } }))).toBe("balanced");
|
|
73
|
+
});
|
|
74
|
+
test("no brevity → decision_speed fast-intuitive → concise; deliberate → detailed", () => {
|
|
75
|
+
expect(outputStyleFromProfile(p({ "personality.decision_speed": { value: "fast-intuitive", confidence: 0.7, samples: 20 } }))).toBe("concise");
|
|
76
|
+
expect(outputStyleFromProfile(p({ "personality.decision_speed": { value: "deliberate", confidence: 0.7, samples: 20 } }))).toBe("detailed");
|
|
77
|
+
});
|
|
78
|
+
test("null profile or no usable dim → null (caller keeps its own default)", () => {
|
|
79
|
+
expect(outputStyleFromProfile(null)).toBeNull();
|
|
80
|
+
expect(outputStyleFromProfile(p({ "personality.decision_speed": { value: "measured", confidence: 0.7, samples: 20 } }))).toBeNull();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe("getWhoAmIProfile — fail-open + cache", () => {
|
|
84
|
+
const origHome = process.env.HOME;
|
|
85
|
+
const origUser = process.env.USERPROFILE;
|
|
86
|
+
beforeEach(() => {
|
|
87
|
+
resetWhoAmICache();
|
|
88
|
+
});
|
|
89
|
+
afterEach(() => {
|
|
90
|
+
process.env.HOME = origHome;
|
|
91
|
+
process.env.USERPROFILE = origUser;
|
|
92
|
+
resetWhoAmICache();
|
|
93
|
+
});
|
|
94
|
+
test("returns null when no EE install is present (no ~/.experience modules)", () => {
|
|
95
|
+
const empty = os.tmpdir(); // no .experience/src here
|
|
96
|
+
process.env.HOME = empty;
|
|
97
|
+
process.env.USERPROFILE = empty;
|
|
98
|
+
expect(getWhoAmIProfile()).toBeNull();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
//# sourceMappingURL=who-am-i.test.js.map
|
|
@@ -49,6 +49,9 @@ export async function deliberateCompact(flowDir, messages, systemPrompt, tokenBu
|
|
|
49
49
|
const historyPath = path.join(historyDir, `${timestamp}.md`);
|
|
50
50
|
const fullSerialized = serializeConversation(messages);
|
|
51
51
|
await atomicWriteText(historyPath, fullSerialized);
|
|
52
|
+
// Save full JSON history next to the md file for exact expand/restore
|
|
53
|
+
const jsonPath = path.join(historyDir, `${timestamp}.json`);
|
|
54
|
+
await atomicWriteText(jsonPath, JSON.stringify(messages, null, 2));
|
|
52
55
|
// Token estimation before
|
|
53
56
|
const tokensBefore = estimateConversationTokens(systemPrompt, messages);
|
|
54
57
|
// Pass 2: Compress
|
|
@@ -58,6 +61,7 @@ export async function deliberateCompact(flowDir, messages, systemPrompt, tokenBu
|
|
|
58
61
|
tokensBeforeCompress: tokensBefore,
|
|
59
62
|
tokensAfterCompress: compressed.tokensAfter,
|
|
60
63
|
historyPath,
|
|
64
|
+
summary: compressed.summary,
|
|
61
65
|
};
|
|
62
66
|
}
|
|
63
67
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "1.
|
|
1
|
+
export declare const PACKAGE_VERSION = "1.8.1";
|
|
2
2
|
export declare const PACKAGE_DESCRIPTION = "BYOK AI coding agent with multi-model council debate, role-based routing, and auto-compact.";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// AUTO-GENERATED by scripts/sync-version.cjs. DO NOT EDIT BY HAND.
|
|
2
2
|
// Sourced from package.json at build time so it survives bun --compile bundling.
|
|
3
|
-
export const PACKAGE_VERSION = "1.
|
|
3
|
+
export const PACKAGE_VERSION = "1.8.1";
|
|
4
4
|
export const PACKAGE_DESCRIPTION = "BYOK AI coding agent with multi-model council debate, role-based routing, and auto-compact.";
|
|
5
5
|
//# sourceMappingURL=version.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ProcessMessageObserver } from "../orchestrator/agent-options.js";
|
|
2
|
-
import type { StreamChunk, ToolCall, ToolResult } from "../types/index.js";
|
|
2
|
+
import type { StreamChunk, StructuredResponse, ToolCall, ToolResult } from "../types/index.js";
|
|
3
3
|
export type HeadlessOutputFormat = "text" | "json";
|
|
4
4
|
export interface HeadlessWrites {
|
|
5
5
|
stdout?: string;
|
|
@@ -42,6 +42,13 @@ export type HeadlessJsonEvent = {
|
|
|
42
42
|
totalTokens?: number;
|
|
43
43
|
costUsdTicks?: number;
|
|
44
44
|
};
|
|
45
|
+
} | {
|
|
46
|
+
type: "structured_response";
|
|
47
|
+
sessionID?: string;
|
|
48
|
+
stepNumber: number;
|
|
49
|
+
timestamp: number;
|
|
50
|
+
taskType: string;
|
|
51
|
+
data: Record<string, unknown>;
|
|
45
52
|
} | {
|
|
46
53
|
type: "error";
|
|
47
54
|
sessionID?: string;
|
|
@@ -54,6 +61,28 @@ export declare function renderHeadlessPrelude(format: HeadlessOutputFormat, sess
|
|
|
54
61
|
* Headless text output only. JSON streaming uses {@link createHeadlessJsonlEmitter} + `Agent.processMessage` observer.
|
|
55
62
|
*/
|
|
56
63
|
export declare function renderHeadlessChunk(chunk: StreamChunk): HeadlessWrites;
|
|
64
|
+
/**
|
|
65
|
+
* Plain-text rendering of a respond_* terminal answer for headless `--format
|
|
66
|
+
* text`. Mirrors the per-taskType layout of {@link StructuredResponseView}
|
|
67
|
+
* (src/ui/components/structured-response-view.tsx) but emits flat text (no ANSI
|
|
68
|
+
* box-drawing) so the answer pipes cleanly. Falls back to the primary text
|
|
69
|
+
* field, then raw JSON, for taskTypes without a dedicated layout.
|
|
70
|
+
*/
|
|
71
|
+
export declare function formatStructuredResponseText(sr: StructuredResponse): string;
|
|
72
|
+
/**
|
|
73
|
+
* Stateful headless TEXT consumer. Streams tool/error progress to stderr (via
|
|
74
|
+
* {@link renderHeadlessChunk}) but BUFFERS assistant `content` so that a
|
|
75
|
+
* terminal `respond_*` answer ({@link StructuredResponse}) supersedes any
|
|
76
|
+
* preamble the model leaked before calling the response tool — otherwise the
|
|
77
|
+
* answer would print twice (once as raw leaked content, once formatted). For a
|
|
78
|
+
* normal chat turn with no structured answer, the buffered content is flushed
|
|
79
|
+
* verbatim at the end. Mirrors the buffer-and-supersede design of
|
|
80
|
+
* {@link createHeadlessJsonlEmitter}.
|
|
81
|
+
*/
|
|
82
|
+
export declare function createHeadlessTextEmitter(): {
|
|
83
|
+
consumeChunk(chunk: StreamChunk): HeadlessWrites;
|
|
84
|
+
flush(): HeadlessWrites;
|
|
85
|
+
};
|
|
57
86
|
/**
|
|
58
87
|
* Buffers assistant `content` per step and emits JSONL: step_start, text, tool_use, step_finish, error.
|
|
59
88
|
* Pair with `agent.processMessage(prompt, emitter.observer)` in headless JSON mode only.
|