@pellux/goodvibes-agent 1.1.7 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +170 -0
- package/README.md +46 -30
- package/dist/package/{ast-grep-napi.linux-x64-gnu-mkk8xwww.node → ast-grep-napi.linux-x64-gnu-swtppvy9.node} +0 -0
- package/dist/package/{ast-grep-napi.linux-x64-musl-ryqtgdv6.node → ast-grep-napi.linux-x64-musl-ttfcdtap.node} +0 -0
- package/dist/package/main.js +132577 -91483
- package/docs/README.md +14 -7
- package/docs/channels-remote-and-api.md +8 -5
- package/docs/connected-host.md +14 -12
- package/docs/getting-started.md +56 -30
- package/docs/knowledge-artifacts-and-multimodal.md +7 -5
- package/docs/project-planning.md +2 -2
- package/docs/providers-and-routing.md +11 -3
- package/docs/tools-and-commands.md +114 -45
- package/docs/voice-and-live-tts.md +3 -1
- package/package.json +3 -2
- package/release/release-notes.md +130 -5
- package/release/release-readiness.json +120 -90
- package/src/agent/assistant-cockpit.ts +247 -0
- package/src/agent/autonomy-schedule-format.ts +96 -0
- package/src/agent/autonomy-schedule.ts +514 -0
- package/src/agent/channel-delivery-receipts.ts +292 -0
- package/src/agent/competitive-feature-inventory.ts +296 -0
- package/src/agent/document-registry-types.ts +106 -0
- package/src/agent/document-registry.ts +734 -0
- package/src/agent/harness-control.ts +2 -2
- package/src/agent/memory-prompt.ts +2 -2
- package/src/agent/operator-actions.ts +50 -6
- package/src/agent/persona-registry.ts +8 -0
- package/src/agent/project-context-files.ts +273 -0
- package/src/agent/prompt-context-receipts.ts +502 -0
- package/src/agent/reminder-schedule-format.ts +16 -2
- package/src/agent/research-run-registry.ts +582 -0
- package/src/agent/research-source-registry.ts +441 -0
- package/src/agent/routine-registry.ts +19 -3
- package/src/agent/routine-schedule-format.ts +27 -2
- package/src/agent/runtime-profile-starters.ts +7 -0
- package/src/agent/runtime-profile.ts +106 -4
- package/src/agent/schedule-edit-format.ts +129 -0
- package/src/agent/schedule-edit.ts +496 -0
- package/src/agent/schedule-next-routes.ts +42 -0
- package/src/agent/setup-wizard-checkpoint.ts +140 -0
- package/src/agent/setup-wizard.ts +447 -0
- package/src/agent/skill-registry-types.ts +102 -0
- package/src/agent/skill-registry.ts +81 -107
- package/src/agent/vibe-confirmation-routes.ts +62 -0
- package/src/agent/vibe-file.ts +285 -0
- package/src/cli/agent-knowledge-command.ts +45 -2
- package/src/cli/help.ts +3 -0
- package/src/cli/profiles-command.ts +25 -11
- package/src/config/agent-settings-policy.ts +1 -18
- package/src/input/agent-workspace-activation.ts +53 -0
- package/src/input/agent-workspace-artifact-browser-editor.ts +494 -0
- package/src/input/agent-workspace-artifact-metadata.ts +17 -0
- package/src/input/agent-workspace-basic-command-editors.ts +5 -1
- package/src/input/agent-workspace-categories.ts +153 -155
- package/src/input/agent-workspace-channel-triage.ts +481 -0
- package/src/input/agent-workspace-channels.ts +263 -0
- package/src/input/agent-workspace-command-editor.ts +152 -0
- package/src/input/agent-workspace-context-snapshot.ts +349 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +8 -0
- package/src/input/agent-workspace-document-editor.ts +502 -0
- package/src/input/agent-workspace-document-ops-editor.ts +523 -0
- package/src/input/agent-workspace-host-category.ts +1 -1
- package/src/input/agent-workspace-local-library-snapshot.ts +167 -0
- package/src/input/agent-workspace-model-compare-editor.ts +376 -0
- package/src/input/agent-workspace-model-compare-prompt-submission.ts +552 -0
- package/src/input/agent-workspace-model-compare-types.ts +82 -0
- package/src/input/agent-workspace-model-compare-utils.ts +35 -0
- package/src/input/agent-workspace-onboarding-categories.ts +141 -0
- package/src/input/agent-workspace-operations-command-editor-submission.ts +53 -0
- package/src/input/agent-workspace-operations-command-editors.ts +22 -0
- package/src/input/agent-workspace-research-report-editor.ts +212 -0
- package/src/input/agent-workspace-research-run-editor.ts +144 -0
- package/src/input/agent-workspace-research-source-editor.ts +167 -0
- package/src/input/agent-workspace-review-packet-snapshot.ts +593 -0
- package/src/input/agent-workspace-review-packet-utils.ts +265 -0
- package/src/input/agent-workspace-settings.ts +262 -30
- package/src/input/agent-workspace-setup-checkpoint-action.ts +127 -0
- package/src/input/agent-workspace-setup-snapshot.ts +198 -0
- package/src/input/agent-workspace-setup.ts +34 -1
- package/src/input/agent-workspace-snapshot.ts +162 -147
- package/src/input/agent-workspace-types.ts +287 -2
- package/src/input/agent-workspace.ts +18 -0
- package/src/input/command-registry.ts +9 -2
- package/src/input/commands/agent-runtime-profile-runtime.ts +28 -13
- package/src/input/commands/channels-runtime.ts +102 -114
- package/src/input/commands/delegation-runtime.ts +87 -24
- package/src/input/commands/knowledge-browser-flags.ts +12 -0
- package/src/input/commands/knowledge.ts +28 -14
- package/src/input/commands/operator-actions-runtime.ts +6 -3
- package/src/input/commands/schedule-runtime.ts +71 -14
- package/src/input/commands/session-content.ts +2 -2
- package/src/input/commands/shell-core.ts +2 -0
- package/src/input/commands/vibe-runtime.ts +140 -0
- package/src/input/commands.ts +2 -0
- package/src/input/connected-host-routes.ts +123 -0
- package/src/input/settings-modal-types.ts +14 -0
- package/src/main.ts +15 -15
- package/src/panels/qr-panel.ts +2 -2
- package/src/renderer/agent-workspace-context-lines.ts +686 -0
- package/src/renderer/agent-workspace.ts +30 -419
- package/src/renderer/settings-modal-helpers.ts +12 -0
- package/src/renderer/settings-modal.ts +12 -0
- package/src/runtime/bootstrap-command-context.ts +11 -1
- package/src/runtime/bootstrap-command-parts.ts +14 -3
- package/src/runtime/bootstrap-core.ts +39 -1
- package/src/runtime/bootstrap-shell.ts +6 -0
- package/src/runtime/bootstrap.ts +113 -30
- package/src/runtime/connected-host-auth.ts +3 -2
- package/src/runtime/execution-ledger.ts +231 -0
- package/src/runtime/services.ts +88 -10
- package/src/runtime/tool-permission-safety.ts +199 -5
- package/src/shell/session-continuity-hints.ts +39 -0
- package/src/tools/agent-artifacts-tool.ts +606 -0
- package/src/tools/agent-audit-tool.ts +155 -0
- package/src/tools/agent-autonomy-schedule-tool.ts +238 -0
- package/src/tools/agent-autonomy-tool.ts +140 -0
- package/src/tools/agent-channel-send-tool.ts +24 -2
- package/src/tools/agent-channels-tool.ts +140 -0
- package/src/tools/agent-computer-tool.ts +168 -0
- package/src/tools/agent-context-policy.ts +137 -7
- package/src/tools/agent-context-tool.ts +143 -0
- package/src/tools/agent-delegation-tool.ts +128 -0
- package/src/tools/agent-device-tool.ts +240 -0
- package/src/tools/agent-documents-tool.ts +684 -0
- package/src/tools/agent-execution-tool.ts +230 -0
- package/src/tools/agent-harness-agent-orchestration.ts +703 -0
- package/src/tools/agent-harness-autonomy-intake.ts +785 -0
- package/src/tools/agent-harness-autonomy-live-records.ts +588 -0
- package/src/tools/agent-harness-autonomy-queue-types.ts +88 -0
- package/src/tools/agent-harness-autonomy-queue.ts +560 -0
- package/src/tools/agent-harness-background-processes-types.ts +35 -0
- package/src/tools/agent-harness-background-processes.ts +794 -0
- package/src/tools/agent-harness-browser-cockpit-route.ts +219 -0
- package/src/tools/agent-harness-browser-control.ts +338 -0
- package/src/tools/agent-harness-channel-metadata.ts +168 -10
- package/src/tools/agent-harness-cli-command-policy.ts +110 -0
- package/src/tools/agent-harness-command-catalog.ts +4 -2
- package/src/tools/agent-harness-command-runner.ts +42 -0
- package/src/tools/agent-harness-connected-host-status.ts +7 -4
- package/src/tools/agent-harness-delegation-posture.ts +234 -19
- package/src/tools/agent-harness-document-ops-reviewer-readiness.ts +234 -0
- package/src/tools/agent-harness-document-ops-types.ts +72 -0
- package/src/tools/agent-harness-document-ops.ts +671 -0
- package/src/tools/agent-harness-execution-history.ts +489 -0
- package/src/tools/agent-harness-execution-posture.ts +382 -0
- package/src/tools/agent-harness-file-recovery.ts +135 -0
- package/src/tools/agent-harness-keybinding-metadata.ts +16 -12
- package/src/tools/agent-harness-learning-curator-common.ts +102 -0
- package/src/tools/agent-harness-learning-curator-consolidation.ts +295 -0
- package/src/tools/agent-harness-learning-curator-proposals.ts +606 -0
- package/src/tools/agent-harness-learning-curator-types.ts +151 -0
- package/src/tools/agent-harness-learning-curator.ts +417 -0
- package/src/tools/agent-harness-local-model-benchmarks.ts +199 -0
- package/src/tools/agent-harness-local-model-cookbook.ts +238 -0
- package/src/tools/agent-harness-local-model-endpoints.ts +673 -0
- package/src/tools/agent-harness-media-posture.ts +208 -2
- package/src/tools/agent-harness-memory-posture.ts +556 -0
- package/src/tools/agent-harness-metadata.ts +100 -168
- package/src/tools/agent-harness-mode-catalog.ts +84 -33
- package/src/tools/agent-harness-model-catalog.ts +162 -0
- package/src/tools/agent-harness-model-provider-health.ts +186 -0
- package/src/tools/agent-harness-model-readiness.ts +406 -0
- package/src/tools/agent-harness-model-routing-types.ts +266 -0
- package/src/tools/agent-harness-model-routing-utils.ts +30 -0
- package/src/tools/agent-harness-model-routing.ts +137 -190
- package/src/tools/agent-harness-operator-methods.ts +115 -133
- package/src/tools/agent-harness-pairing-posture.ts +431 -18
- package/src/tools/agent-harness-personal-ops-discovery.ts +533 -0
- package/src/tools/agent-harness-personal-ops-intake.ts +385 -0
- package/src/tools/agent-harness-personal-ops-lanes.ts +204 -0
- package/src/tools/agent-harness-personal-ops-records.ts +732 -0
- package/src/tools/agent-harness-personal-ops-runner.ts +637 -0
- package/src/tools/agent-harness-personal-ops-types.ts +222 -0
- package/src/tools/agent-harness-personal-ops.ts +606 -0
- package/src/tools/agent-harness-project-context.ts +144 -0
- package/src/tools/agent-harness-prompt-context.ts +589 -0
- package/src/tools/agent-harness-provider-account-metadata.ts +2 -2
- package/src/tools/agent-harness-release-evidence.ts +9 -7
- package/src/tools/agent-harness-release-readiness.ts +9 -7
- package/src/tools/agent-harness-research-briefing.ts +427 -0
- package/src/tools/agent-harness-research-queue.ts +250 -0
- package/src/tools/agent-harness-research-runs.ts +295 -0
- package/src/tools/agent-harness-research-workflow.ts +322 -0
- package/src/tools/agent-harness-security-posture.ts +2 -2
- package/src/tools/agent-harness-service-posture.ts +9 -9
- package/src/tools/agent-harness-session-metadata.ts +3 -3
- package/src/tools/agent-harness-setup-connected-host.ts +501 -0
- package/src/tools/agent-harness-setup-describe.ts +557 -0
- package/src/tools/agent-harness-setup-handoffs.ts +502 -0
- package/src/tools/agent-harness-setup-model-helpers.ts +101 -0
- package/src/tools/agent-harness-setup-plan.ts +253 -0
- package/src/tools/agent-harness-setup-posture-types.ts +218 -0
- package/src/tools/agent-harness-setup-posture-utils.ts +173 -0
- package/src/tools/agent-harness-setup-posture.ts +449 -221
- package/src/tools/agent-harness-setup-smoke.ts +508 -0
- package/src/tools/agent-harness-sudo-posture.ts +114 -0
- package/src/tools/agent-harness-tool-schema.ts +120 -7
- package/src/tools/agent-harness-tool-types.ts +78 -0
- package/src/tools/agent-harness-tool-utils.ts +43 -0
- package/src/tools/agent-harness-tool.ts +311 -370
- package/src/tools/agent-harness-ui-surface-metadata.ts +76 -69
- package/src/tools/agent-harness-ui-surface-types.ts +46 -0
- package/src/tools/agent-harness-vibe-health.ts +105 -0
- package/src/tools/agent-harness-workspace-action-runner.ts +149 -0
- package/src/tools/agent-harness-workspace-actions.ts +114 -8
- package/src/tools/agent-harness-workspace-editor-execution.ts +214 -0
- package/src/tools/agent-harness-workspace-editor-runner.ts +755 -0
- package/src/tools/agent-host-tool.ts +159 -0
- package/src/tools/agent-knowledge-ingest-tool.ts +34 -1
- package/src/tools/agent-learning-consolidation-core.ts +327 -0
- package/src/tools/agent-learning-consolidation-tool.ts +758 -0
- package/src/tools/agent-memory-tool.ts +214 -0
- package/src/tools/agent-model-compare-export.ts +315 -0
- package/src/tools/agent-model-compare-handoff.ts +592 -0
- package/src/tools/agent-model-compare-judgment.ts +633 -0
- package/src/tools/agent-model-compare-run.ts +722 -0
- package/src/tools/agent-model-compare-tool.ts +698 -0
- package/src/tools/agent-model-compare-types.ts +191 -0
- package/src/tools/agent-model-compare-utils.ts +93 -0
- package/src/tools/agent-models-tool.ts +208 -0
- package/src/tools/agent-operator-action-tool.ts +1 -1
- package/src/tools/agent-operator-method-tool.ts +643 -0
- package/src/tools/agent-personal-ops-tool.ts +197 -0
- package/src/tools/agent-policy-explanation.ts +415 -0
- package/src/tools/agent-research-report-tool.ts +608 -0
- package/src/tools/agent-research-runs-tool.ts +434 -0
- package/src/tools/agent-research-sources-tool.ts +443 -0
- package/src/tools/agent-research-tool.ts +687 -0
- package/src/tools/agent-review-packet-presets-core.ts +757 -0
- package/src/tools/agent-review-packet-presets-tool.ts +466 -0
- package/src/tools/agent-review-packet-share-tool.ts +305 -0
- package/src/tools/agent-route-planner-candidates-setup.ts +411 -0
- package/src/tools/agent-route-planner-candidates-surfaces.ts +432 -0
- package/src/tools/agent-route-planner-candidates-work.ts +251 -0
- package/src/tools/agent-route-planner-helpers.ts +667 -0
- package/src/tools/agent-route-planner.ts +185 -0
- package/src/tools/agent-route-tool.ts +105 -0
- package/src/tools/agent-schedule-edit-tool.ts +210 -0
- package/src/tools/agent-schedule-tool.ts +282 -0
- package/src/tools/agent-security-tool.ts +145 -0
- package/src/tools/agent-sessions-tool.ts +122 -0
- package/src/tools/agent-settings-import-tool.ts +104 -0
- package/src/tools/agent-settings-tool.ts +176 -0
- package/src/tools/agent-setup-tool.ts +226 -0
- package/src/tools/agent-support-tool.ts +122 -0
- package/src/tools/agent-terminal-process-tools.ts +167 -0
- package/src/tools/agent-tool-policy-guard-types.ts +77 -0
- package/src/tools/agent-tool-policy-guard.ts +106 -85
- package/src/tools/agent-vibe-tool.ts +297 -0
- package/src/tools/agent-work-plan-tool.ts +265 -6
- package/src/tools/agent-workspace-tool.ts +305 -0
- package/src/tools/artifact-archive.ts +169 -0
- package/src/tools/tool-definition-compaction.ts +36 -0
- package/src/version.ts +1 -1
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
import type { MemoryApi } from '@pellux/goodvibes-sdk/platform/knowledge';
|
|
2
|
+
import { getTierForContextWindow, getTierPromptSupplement } from '@pellux/goodvibes-sdk/platform/providers';
|
|
3
|
+
import type { MemoryRecord } from '@pellux/goodvibes-sdk/platform/state';
|
|
4
|
+
import { isPromptActiveMemory, MIN_PROMPT_MEMORY_CONFIDENCE } from '../agent/memory-prompt.ts';
|
|
5
|
+
import { AgentPersonaRegistry, buildActivePersonaPrompt } from '../agent/persona-registry.ts';
|
|
6
|
+
import { buildProjectContextPrompt, discoverProjectContextFiles } from '../agent/project-context-files.ts';
|
|
7
|
+
import { AgentRoutineRegistry, buildEnabledRoutinesPrompt, evaluateAgentRoutineReadiness } from '../agent/routine-registry.ts';
|
|
8
|
+
import { AgentSkillRegistry, buildEnabledSkillsPrompt, evaluateAgentSkillBundleReadiness, evaluateAgentSkillReadiness } from '../agent/skill-registry.ts';
|
|
9
|
+
import { buildVibePrompt, discoverVibeFiles } from '../agent/vibe-file.ts';
|
|
10
|
+
import type { PromptContextReceipt } from '../agent/prompt-context-receipts.ts';
|
|
11
|
+
import type { CommandContext } from '../input/command-registry.ts';
|
|
12
|
+
import { previewHarnessText } from './agent-harness-text.ts';
|
|
13
|
+
|
|
14
|
+
interface PromptContextArgs {
|
|
15
|
+
readonly includeParameters?: unknown;
|
|
16
|
+
readonly receiptId?: unknown;
|
|
17
|
+
readonly turnId?: unknown;
|
|
18
|
+
readonly outcomeStatus?: unknown;
|
|
19
|
+
readonly limit?: unknown;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type PromptContextSegmentStatus = 'active' | 'attention' | 'empty' | 'unavailable';
|
|
23
|
+
type PromptContextReceiptOutcomeFilter = 'completed' | 'error' | 'cancelled' | 'pending';
|
|
24
|
+
|
|
25
|
+
interface PromptContextSegment {
|
|
26
|
+
readonly id: string;
|
|
27
|
+
readonly label: string;
|
|
28
|
+
readonly status: PromptContextSegmentStatus;
|
|
29
|
+
readonly order: number;
|
|
30
|
+
readonly activeCount: number;
|
|
31
|
+
readonly suppressedCount: number;
|
|
32
|
+
readonly promptChars: number;
|
|
33
|
+
readonly approxTokens: number;
|
|
34
|
+
readonly route?: string;
|
|
35
|
+
readonly selected?: readonly Record<string, unknown>[];
|
|
36
|
+
readonly suppressed?: readonly Record<string, unknown>[];
|
|
37
|
+
readonly note?: string;
|
|
38
|
+
readonly preview?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type PromptMemoryApi = Pick<MemoryApi, 'getAll'>;
|
|
42
|
+
|
|
43
|
+
interface PromptModelInfo {
|
|
44
|
+
readonly model: unknown;
|
|
45
|
+
readonly label: string;
|
|
46
|
+
readonly contextWindow: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface CompactPromptContextReceipt {
|
|
50
|
+
readonly receiptId: string;
|
|
51
|
+
readonly turnId: string | null;
|
|
52
|
+
readonly source: string;
|
|
53
|
+
readonly createdAt: number;
|
|
54
|
+
readonly provider: string;
|
|
55
|
+
readonly model: string;
|
|
56
|
+
readonly contextWindow: number;
|
|
57
|
+
readonly turnOutcome?: {
|
|
58
|
+
readonly status: string;
|
|
59
|
+
readonly terminalEvent: string;
|
|
60
|
+
readonly stopReason: string;
|
|
61
|
+
readonly completedAt: number;
|
|
62
|
+
readonly detail?: string;
|
|
63
|
+
};
|
|
64
|
+
readonly promptHash?: string;
|
|
65
|
+
readonly promptChars?: number;
|
|
66
|
+
readonly approxPromptTokens?: number;
|
|
67
|
+
readonly activeRecords?: number;
|
|
68
|
+
readonly suppressedRecords?: number;
|
|
69
|
+
readonly segments?: readonly {
|
|
70
|
+
readonly id: string;
|
|
71
|
+
readonly status: string;
|
|
72
|
+
readonly activeCount: number;
|
|
73
|
+
readonly suppressedCount: number;
|
|
74
|
+
readonly promptChars: number;
|
|
75
|
+
readonly approxTokens: number;
|
|
76
|
+
}[];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function readPromptString(value: unknown): string {
|
|
80
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function readPromptLimit(value: unknown, fallback: number): number {
|
|
84
|
+
const parsed = typeof value === 'string' && value.trim() ? Number(value) : value;
|
|
85
|
+
if (typeof parsed !== 'number' || !Number.isFinite(parsed)) return fallback;
|
|
86
|
+
return Math.max(1, Math.min(50, Math.trunc(parsed)));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function readOutcomeStatus(value: unknown): PromptContextReceiptOutcomeFilter | null {
|
|
90
|
+
if (value === 'completed' || value === 'error' || value === 'cancelled' || value === 'pending') return value;
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function promptContextReceiptOutcomeStatus(receipt: PromptContextReceipt): PromptContextReceiptOutcomeFilter {
|
|
95
|
+
return receipt.turnOutcome?.status ?? 'pending';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function promptContextQuote(value: string): string {
|
|
99
|
+
return JSON.stringify(value);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function promptContextReceiptRoute(receiptId: string): string {
|
|
103
|
+
return `context action:"receipt" receiptId:${promptContextQuote(receiptId)} includeParameters:true`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function promptContextTurnRoute(turnId: string): string {
|
|
107
|
+
return `context action:"receipt" turnId:${promptContextQuote(turnId)} includeParameters:true`;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function promptContextOutcomeRoute(status: PromptContextReceiptOutcomeFilter): string {
|
|
111
|
+
return `context action:"receipts" outcomeStatus:${promptContextQuote(status)} includeParameters:true`;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function approxTokens(text: string): number {
|
|
115
|
+
return Math.ceil(text.length / 4);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function modelLabel(model: unknown): string {
|
|
119
|
+
if (typeof model === 'string' && model.trim()) return model.trim();
|
|
120
|
+
if (typeof model === 'object' && model !== null) {
|
|
121
|
+
const candidate = model as { readonly registryKey?: unknown; readonly id?: unknown; readonly modelId?: unknown };
|
|
122
|
+
for (const value of [candidate.registryKey, candidate.id, candidate.modelId]) {
|
|
123
|
+
if (typeof value === 'string' && value.trim()) return value.trim();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return 'unknown';
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function promptModelInfo(context: CommandContext): PromptModelInfo {
|
|
130
|
+
const registry = context.provider.providerRegistry as {
|
|
131
|
+
readonly getCurrentModel?: () => unknown;
|
|
132
|
+
readonly getContextWindowForModel?: (model: unknown) => number;
|
|
133
|
+
};
|
|
134
|
+
let model: unknown = context.session.runtime.model ?? 'unknown';
|
|
135
|
+
if (typeof registry.getCurrentModel === 'function') {
|
|
136
|
+
try {
|
|
137
|
+
model = registry.getCurrentModel();
|
|
138
|
+
} catch {
|
|
139
|
+
model = context.session.runtime.model ?? model;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
let contextWindow = 0;
|
|
143
|
+
if (typeof registry.getContextWindowForModel === 'function') {
|
|
144
|
+
const value = registry.getContextWindowForModel(model);
|
|
145
|
+
contextWindow = Number.isFinite(value) ? Math.max(0, Math.trunc(value)) : 0;
|
|
146
|
+
}
|
|
147
|
+
return { model, label: modelLabel(model), contextWindow };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function promptMemoryApi(value: unknown): PromptMemoryApi | undefined {
|
|
151
|
+
if (typeof value !== 'object' || value === null) return undefined;
|
|
152
|
+
const candidate = value as { readonly getAll?: unknown };
|
|
153
|
+
return typeof candidate.getAll === 'function' ? candidate as PromptMemoryApi : undefined;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function segment(
|
|
157
|
+
input: Omit<PromptContextSegment, 'approxTokens'> & { readonly promptText?: string | null },
|
|
158
|
+
includeParameters: boolean,
|
|
159
|
+
): PromptContextSegment {
|
|
160
|
+
const promptChars = input.promptText?.length ?? input.promptChars;
|
|
161
|
+
return {
|
|
162
|
+
id: input.id,
|
|
163
|
+
label: input.label,
|
|
164
|
+
status: input.status,
|
|
165
|
+
order: input.order,
|
|
166
|
+
activeCount: input.activeCount,
|
|
167
|
+
suppressedCount: input.suppressedCount,
|
|
168
|
+
promptChars,
|
|
169
|
+
approxTokens: approxTokens(input.promptText ?? ''),
|
|
170
|
+
...(input.route ? { route: input.route } : {}),
|
|
171
|
+
...(input.selected ? { selected: input.selected } : {}),
|
|
172
|
+
...(input.suppressed ? { suppressed: input.suppressed } : {}),
|
|
173
|
+
...(input.note ? { note: input.note } : {}),
|
|
174
|
+
...(includeParameters && input.promptText ? { preview: previewHarnessText(input.promptText, 360) } : {}),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function memorySort(left: MemoryRecord, right: MemoryRecord): number {
|
|
179
|
+
if (right.confidence !== left.confidence) return right.confidence - left.confidence;
|
|
180
|
+
return right.updatedAt - left.updatedAt;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function formatMemoryLine(record: MemoryRecord): string {
|
|
184
|
+
const tags = record.tags.length > 0 ? ` tags=${record.tags.join(',')}` : '';
|
|
185
|
+
const provenance = record.provenance.length > 0
|
|
186
|
+
? ` source=${record.provenance.slice(0, 2).map((entry) => `${entry.kind}:${entry.ref}`).join(',')}`
|
|
187
|
+
: '';
|
|
188
|
+
return `- [${record.scope}/${record.cls} ${record.confidence}%${tags}${provenance}] ${record.summary}`;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function promptMemoryRecords(memory: PromptMemoryApi | undefined): readonly MemoryRecord[] {
|
|
192
|
+
if (!memory) return [];
|
|
193
|
+
return memory.getAll().filter(isPromptActiveMemory).sort(memorySort).slice(0, 10);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function buildMemoryPromptFromRecords(records: readonly MemoryRecord[]): string {
|
|
197
|
+
return [
|
|
198
|
+
'## Reviewed GoodVibes Agent Memory',
|
|
199
|
+
`Use these local, reviewed, non-secret memory records with confidence >= ${MIN_PROMPT_MEMORY_CONFIDENCE}% to avoid asking repeat questions and to preserve durable user preferences, constraints, and operating facts.`,
|
|
200
|
+
...records.map(formatMemoryLine),
|
|
201
|
+
].join('\n');
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function memorySegment(memory: PromptMemoryApi | undefined, includeParameters: boolean): PromptContextSegment {
|
|
205
|
+
if (!memory) {
|
|
206
|
+
return segment({
|
|
207
|
+
id: 'memory',
|
|
208
|
+
label: 'Reviewed memory',
|
|
209
|
+
status: 'unavailable',
|
|
210
|
+
order: 4,
|
|
211
|
+
activeCount: 0,
|
|
212
|
+
suppressedCount: 0,
|
|
213
|
+
promptChars: 0,
|
|
214
|
+
route: 'memory action:"status"',
|
|
215
|
+
note: 'Agent-local memory API is unavailable in this runtime.',
|
|
216
|
+
}, includeParameters);
|
|
217
|
+
}
|
|
218
|
+
const all = memory.getAll();
|
|
219
|
+
const active = promptMemoryRecords(memory);
|
|
220
|
+
const activeIds = new Set(active.map((record) => record.id));
|
|
221
|
+
const suppressed = all.filter((record) => !activeIds.has(record.id));
|
|
222
|
+
const promptText = active.length > 0 ? buildMemoryPromptFromRecords(active) : '';
|
|
223
|
+
return segment({
|
|
224
|
+
id: 'memory',
|
|
225
|
+
label: 'Reviewed memory',
|
|
226
|
+
status: suppressed.length > 0 ? 'attention' : active.length > 0 ? 'active' : 'empty',
|
|
227
|
+
order: 4,
|
|
228
|
+
activeCount: active.length,
|
|
229
|
+
suppressedCount: suppressed.length,
|
|
230
|
+
promptChars: promptText.length,
|
|
231
|
+
promptText,
|
|
232
|
+
route: 'memory action:"status"',
|
|
233
|
+
selected: active.map((record) => ({
|
|
234
|
+
id: record.id,
|
|
235
|
+
scope: record.scope,
|
|
236
|
+
class: record.cls,
|
|
237
|
+
confidence: record.confidence,
|
|
238
|
+
inspectRoute: `agent_local_registry domain:"memory" action:"get" recordId:"${record.id}"`,
|
|
239
|
+
})),
|
|
240
|
+
suppressed: suppressed.slice(0, 12).map((record) => ({
|
|
241
|
+
id: record.id,
|
|
242
|
+
reviewState: record.reviewState,
|
|
243
|
+
confidence: record.confidence,
|
|
244
|
+
reason: record.reviewState !== 'reviewed'
|
|
245
|
+
? 'not reviewed'
|
|
246
|
+
: record.confidence < MIN_PROMPT_MEMORY_CONFIDENCE
|
|
247
|
+
? `confidence below ${MIN_PROMPT_MEMORY_CONFIDENCE}`
|
|
248
|
+
: 'outside prompt limit',
|
|
249
|
+
inspectRoute: `agent_local_registry domain:"memory" action:"get" recordId:"${record.id}"`,
|
|
250
|
+
})),
|
|
251
|
+
}, includeParameters);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function promptStatus(active: number, suppressed: number): PromptContextSegmentStatus {
|
|
255
|
+
if (suppressed > 0) return 'attention';
|
|
256
|
+
if (active > 0) return 'active';
|
|
257
|
+
return 'empty';
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function compactPromptContextReceipt(
|
|
261
|
+
receipt: PromptContextReceipt,
|
|
262
|
+
includeParameters: boolean,
|
|
263
|
+
): CompactPromptContextReceipt {
|
|
264
|
+
return {
|
|
265
|
+
receiptId: receipt.receiptId,
|
|
266
|
+
turnId: receipt.turnId,
|
|
267
|
+
source: receipt.source,
|
|
268
|
+
createdAt: receipt.createdAt,
|
|
269
|
+
provider: receipt.provider,
|
|
270
|
+
model: receipt.model,
|
|
271
|
+
contextWindow: receipt.contextWindow,
|
|
272
|
+
...(receipt.turnOutcome ? {
|
|
273
|
+
turnOutcome: {
|
|
274
|
+
status: receipt.turnOutcome.status,
|
|
275
|
+
terminalEvent: receipt.turnOutcome.terminalEvent,
|
|
276
|
+
stopReason: receipt.turnOutcome.stopReason,
|
|
277
|
+
completedAt: receipt.turnOutcome.completedAt,
|
|
278
|
+
...(receipt.turnOutcome.detail ? { detail: receipt.turnOutcome.detail } : {}),
|
|
279
|
+
},
|
|
280
|
+
} : {}),
|
|
281
|
+
...(includeParameters ? {
|
|
282
|
+
promptHash: receipt.promptHash,
|
|
283
|
+
promptChars: receipt.promptChars,
|
|
284
|
+
approxPromptTokens: receipt.approxPromptTokens,
|
|
285
|
+
activeRecords: receipt.activeRecords,
|
|
286
|
+
suppressedRecords: receipt.suppressedRecords,
|
|
287
|
+
segments: receipt.segments.map((segment) => ({
|
|
288
|
+
id: segment.id,
|
|
289
|
+
status: segment.status,
|
|
290
|
+
activeCount: segment.activeCount,
|
|
291
|
+
suppressedCount: segment.suppressedCount,
|
|
292
|
+
promptChars: segment.promptChars,
|
|
293
|
+
approxTokens: segment.approxTokens,
|
|
294
|
+
})),
|
|
295
|
+
} : {}),
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function promptContextReceiptSummary(context: CommandContext, args: PromptContextArgs, includeParameters: boolean): Record<string, unknown> {
|
|
300
|
+
const store = context.clients?.promptContextReceipts;
|
|
301
|
+
if (!store) {
|
|
302
|
+
return {
|
|
303
|
+
status: 'unavailable',
|
|
304
|
+
count: 0,
|
|
305
|
+
latestReceiptId: null,
|
|
306
|
+
latestTurnId: null,
|
|
307
|
+
latestCreatedAt: null,
|
|
308
|
+
note: 'Prompt-context receipt storage is unavailable in this runtime.',
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
const receiptId = readPromptString(args.receiptId);
|
|
312
|
+
const turnId = readPromptString(args.turnId);
|
|
313
|
+
const outcomeStatus = readOutcomeStatus(args.outcomeStatus);
|
|
314
|
+
const hasFilter = Boolean(receiptId || turnId || outcomeStatus);
|
|
315
|
+
const limit = readPromptLimit(args.limit, includeParameters ? 5 : 3);
|
|
316
|
+
const latest = store.latest();
|
|
317
|
+
const allReceipts = store.list(Math.max(store.count(), limit));
|
|
318
|
+
const baseReceipts = receiptId ? allReceipts.filter((receipt) => receipt.receiptId === receiptId) : allReceipts;
|
|
319
|
+
const matchingReceipts = baseReceipts.filter((receipt) => {
|
|
320
|
+
if (turnId && receipt.turnId !== turnId) return false;
|
|
321
|
+
if (outcomeStatus && promptContextReceiptOutcomeStatus(receipt) !== outcomeStatus) return false;
|
|
322
|
+
return true;
|
|
323
|
+
});
|
|
324
|
+
const recent = matchingReceipts.slice(0, limit);
|
|
325
|
+
const selected = hasFilter ? recent[0] ?? null : null;
|
|
326
|
+
const filters = {
|
|
327
|
+
...(receiptId ? { receiptId } : {}),
|
|
328
|
+
...(turnId ? { turnId } : {}),
|
|
329
|
+
...(outcomeStatus ? { outcomeStatus } : {}),
|
|
330
|
+
limit,
|
|
331
|
+
};
|
|
332
|
+
return {
|
|
333
|
+
status: latest ? hasFilter && recent.length === 0 ? 'not_found' : 'ready' : 'empty',
|
|
334
|
+
count: store.count(),
|
|
335
|
+
latestReceiptId: latest?.receiptId ?? null,
|
|
336
|
+
latestTurnId: latest?.turnId ?? null,
|
|
337
|
+
latestCreatedAt: latest?.createdAt ?? null,
|
|
338
|
+
inspectRoute: 'context action:"prompt" includeParameters:true',
|
|
339
|
+
matchingCount: matchingReceipts.length,
|
|
340
|
+
...(hasFilter ? { filters } : {}),
|
|
341
|
+
selected: selected ? compactPromptContextReceipt(selected, includeParameters) : null,
|
|
342
|
+
recent: recent.map((receipt) => compactPromptContextReceipt(receipt, includeParameters)),
|
|
343
|
+
routes: {
|
|
344
|
+
latestReceipt: latest ? promptContextReceiptRoute(latest.receiptId) : null,
|
|
345
|
+
filterCompleted: promptContextOutcomeRoute('completed'),
|
|
346
|
+
filterErrors: promptContextOutcomeRoute('error'),
|
|
347
|
+
filterCancelled: promptContextOutcomeRoute('cancelled'),
|
|
348
|
+
filterPending: promptContextOutcomeRoute('pending'),
|
|
349
|
+
...(latest?.turnId ? { latestTurn: promptContextTurnRoute(latest.turnId) } : {}),
|
|
350
|
+
...(selected ? { selectedReceipt: promptContextReceiptRoute(selected.receiptId) } : {}),
|
|
351
|
+
},
|
|
352
|
+
...(includeParameters ? { latest: latest ? compactPromptContextReceipt(latest, true) : null } : {}),
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function promptContextSegments(context: CommandContext, includeParameters: boolean): readonly PromptContextSegment[] {
|
|
357
|
+
const shellPaths = context.workspace.shellPaths;
|
|
358
|
+
const runtimePrompt = context.session.runtime.systemPrompt ?? '';
|
|
359
|
+
const { label: currentModel, contextWindow } = promptModelInfo(context);
|
|
360
|
+
const tier = getTierForContextWindow(contextWindow);
|
|
361
|
+
const tierPrompt = getTierPromptSupplement(tier);
|
|
362
|
+
if (!shellPaths) {
|
|
363
|
+
return [
|
|
364
|
+
segment({
|
|
365
|
+
id: 'base_system_prompt',
|
|
366
|
+
label: 'Base system prompt',
|
|
367
|
+
status: runtimePrompt ? 'active' : 'empty',
|
|
368
|
+
order: 1,
|
|
369
|
+
activeCount: runtimePrompt ? 1 : 0,
|
|
370
|
+
suppressedCount: 0,
|
|
371
|
+
promptChars: runtimePrompt.length,
|
|
372
|
+
promptText: runtimePrompt,
|
|
373
|
+
}, includeParameters),
|
|
374
|
+
segment({
|
|
375
|
+
id: 'agent_local_context',
|
|
376
|
+
label: 'Agent-local context',
|
|
377
|
+
status: 'unavailable',
|
|
378
|
+
order: 2,
|
|
379
|
+
activeCount: 0,
|
|
380
|
+
suppressedCount: 0,
|
|
381
|
+
promptChars: 0,
|
|
382
|
+
note: 'Agent shell paths are unavailable, so VIBE.md, project context, personas, skills, routines, and local registry files cannot be inspected.',
|
|
383
|
+
}, includeParameters),
|
|
384
|
+
];
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const vibe = discoverVibeFiles(shellPaths);
|
|
388
|
+
const vibePrompt = buildVibePrompt(shellPaths) ?? '';
|
|
389
|
+
const projectContext = discoverProjectContextFiles(shellPaths);
|
|
390
|
+
const projectContextPrompt = buildProjectContextPrompt(shellPaths) ?? '';
|
|
391
|
+
const personaSnapshot = AgentPersonaRegistry.fromShellPaths(shellPaths).snapshot();
|
|
392
|
+
const activePersona = personaSnapshot.activePersona;
|
|
393
|
+
const personaPrompt = buildActivePersonaPrompt(shellPaths) ?? '';
|
|
394
|
+
const routineSnapshot = AgentRoutineRegistry.fromShellPaths(shellPaths).snapshot();
|
|
395
|
+
const activeRoutines = routineSnapshot.enabledRoutines.filter((routine) => routine.reviewState === 'reviewed' && evaluateAgentRoutineReadiness(routine).ready);
|
|
396
|
+
const suppressedRoutines = routineSnapshot.enabledRoutines.filter((routine) => !activeRoutines.some((active) => active.id === routine.id));
|
|
397
|
+
const routinePrompt = buildEnabledRoutinesPrompt(shellPaths) ?? '';
|
|
398
|
+
const skillSnapshot = AgentSkillRegistry.fromShellPaths(shellPaths).snapshot();
|
|
399
|
+
const activeBundles = skillSnapshot.enabledBundles.filter((bundle) => {
|
|
400
|
+
if (bundle.reviewState !== 'reviewed') return false;
|
|
401
|
+
const readiness = evaluateAgentSkillBundleReadiness(bundle, skillSnapshot.skills);
|
|
402
|
+
return readiness.ready && readiness.includedSkills.every((skill) => skill.reviewState === 'reviewed');
|
|
403
|
+
});
|
|
404
|
+
const activeSkillIds = new Set([
|
|
405
|
+
...skillSnapshot.enabledSkills.map((skill) => skill.id),
|
|
406
|
+
...activeBundles.flatMap((bundle) => bundle.skillIds),
|
|
407
|
+
]);
|
|
408
|
+
const activeSkills = skillSnapshot.skills.filter((skill) => activeSkillIds.has(skill.id) && skill.reviewState === 'reviewed' && evaluateAgentSkillReadiness(skill).ready);
|
|
409
|
+
const candidateSkillIds = new Set([
|
|
410
|
+
...skillSnapshot.enabledSkills.map((skill) => skill.id),
|
|
411
|
+
...skillSnapshot.enabledBundles.flatMap((bundle) => bundle.skillIds),
|
|
412
|
+
]);
|
|
413
|
+
const suppressedSkills = skillSnapshot.skills.filter((skill) => candidateSkillIds.has(skill.id) && !activeSkills.some((active) => active.id === skill.id));
|
|
414
|
+
const suppressedBundles = skillSnapshot.enabledBundles.filter((bundle) => !activeBundles.some((active) => active.id === bundle.id));
|
|
415
|
+
const skillPrompt = buildEnabledSkillsPrompt(shellPaths) ?? '';
|
|
416
|
+
const memory = promptMemoryApi(context.clients?.agentKnowledgeApi?.memory);
|
|
417
|
+
|
|
418
|
+
return [
|
|
419
|
+
segment({
|
|
420
|
+
id: 'base_system_prompt',
|
|
421
|
+
label: 'Base system prompt',
|
|
422
|
+
status: runtimePrompt ? 'active' : 'empty',
|
|
423
|
+
order: 1,
|
|
424
|
+
activeCount: runtimePrompt ? 1 : 0,
|
|
425
|
+
suppressedCount: 0,
|
|
426
|
+
promptChars: runtimePrompt.length,
|
|
427
|
+
promptText: runtimePrompt,
|
|
428
|
+
note: 'Runtime-owned base instructions are applied before Agent-local context.',
|
|
429
|
+
}, includeParameters),
|
|
430
|
+
segment({
|
|
431
|
+
id: 'vibe',
|
|
432
|
+
label: 'VIBE.md personality',
|
|
433
|
+
status: promptStatus(vibe.files.length, vibe.blocked.length + vibe.files.filter((file) => file.truncated).length),
|
|
434
|
+
order: 2,
|
|
435
|
+
activeCount: vibe.files.length,
|
|
436
|
+
suppressedCount: vibe.blocked.length,
|
|
437
|
+
promptChars: vibePrompt.length,
|
|
438
|
+
promptText: vibePrompt,
|
|
439
|
+
route: 'vibe action:"status"',
|
|
440
|
+
selected: vibe.files.map((file) => ({ path: file.path, scope: file.scope, truncated: file.truncated })),
|
|
441
|
+
suppressed: vibe.blocked.map((file) => ({ path: file.path, scope: file.scope, reason: file.reason })),
|
|
442
|
+
}, includeParameters),
|
|
443
|
+
segment({
|
|
444
|
+
id: 'project_context',
|
|
445
|
+
label: 'Project context files',
|
|
446
|
+
status: promptStatus(projectContext.files.length, projectContext.blocked.length + projectContext.files.filter((file) => file.truncated).length),
|
|
447
|
+
order: 3,
|
|
448
|
+
activeCount: projectContext.files.length,
|
|
449
|
+
suppressedCount: projectContext.blocked.length,
|
|
450
|
+
promptChars: projectContextPrompt.length,
|
|
451
|
+
promptText: projectContextPrompt,
|
|
452
|
+
route: 'context action:"files"',
|
|
453
|
+
selected: projectContext.files.map((file) => ({
|
|
454
|
+
id: file.id,
|
|
455
|
+
source: file.source,
|
|
456
|
+
scope: file.scope,
|
|
457
|
+
truncated: file.truncated,
|
|
458
|
+
inspectRoute: `context action:"file" contextFileId:"${file.id}"`,
|
|
459
|
+
})),
|
|
460
|
+
suppressed: projectContext.blocked.map((file) => ({ id: file.id, source: file.source, reason: file.reason })),
|
|
461
|
+
}, includeParameters),
|
|
462
|
+
memorySegment(memory, includeParameters),
|
|
463
|
+
segment({
|
|
464
|
+
id: 'routines',
|
|
465
|
+
label: 'Reviewed setup-ready routines',
|
|
466
|
+
status: promptStatus(activeRoutines.length, suppressedRoutines.length),
|
|
467
|
+
order: 5,
|
|
468
|
+
activeCount: activeRoutines.length,
|
|
469
|
+
suppressedCount: suppressedRoutines.length,
|
|
470
|
+
promptChars: routinePrompt.length,
|
|
471
|
+
promptText: routinePrompt,
|
|
472
|
+
route: 'memory action:"curator" query:"routine"',
|
|
473
|
+
selected: activeRoutines.map((routine) => ({ id: routine.id, name: routine.name, inspectRoute: `agent_local_registry domain:"routine" action:"get" recordId:"${routine.id}"` })),
|
|
474
|
+
suppressed: suppressedRoutines.slice(0, 12).map((routine) => ({
|
|
475
|
+
id: routine.id,
|
|
476
|
+
reviewState: routine.reviewState,
|
|
477
|
+
missingRequirements: evaluateAgentRoutineReadiness(routine).missing.length,
|
|
478
|
+
})),
|
|
479
|
+
}, includeParameters),
|
|
480
|
+
segment({
|
|
481
|
+
id: 'skills',
|
|
482
|
+
label: 'Reviewed setup-ready skills and bundles',
|
|
483
|
+
status: promptStatus(activeSkills.length + activeBundles.length, suppressedSkills.length + suppressedBundles.length),
|
|
484
|
+
order: 6,
|
|
485
|
+
activeCount: activeSkills.length + activeBundles.length,
|
|
486
|
+
suppressedCount: suppressedSkills.length + suppressedBundles.length,
|
|
487
|
+
promptChars: skillPrompt.length,
|
|
488
|
+
promptText: skillPrompt,
|
|
489
|
+
route: 'memory action:"curator" query:"skill"',
|
|
490
|
+
selected: [
|
|
491
|
+
...activeBundles.map((bundle) => ({ id: bundle.id, domain: 'skill_bundle', name: bundle.name, inspectRoute: `agent_local_registry domain:"skill_bundle" action:"get" recordId:"${bundle.id}"` })),
|
|
492
|
+
...activeSkills.map((skill) => ({ id: skill.id, domain: 'skill', name: skill.name, inspectRoute: `agent_local_registry domain:"skill" action:"get" recordId:"${skill.id}"` })),
|
|
493
|
+
],
|
|
494
|
+
suppressed: [
|
|
495
|
+
...suppressedBundles.slice(0, 6).map((bundle) => ({ id: bundle.id, domain: 'skill_bundle', reviewState: bundle.reviewState })),
|
|
496
|
+
...suppressedSkills.slice(0, 12).map((skill) => ({
|
|
497
|
+
id: skill.id,
|
|
498
|
+
domain: 'skill',
|
|
499
|
+
reviewState: skill.reviewState,
|
|
500
|
+
missingRequirements: evaluateAgentSkillReadiness(skill).missing.length,
|
|
501
|
+
})),
|
|
502
|
+
],
|
|
503
|
+
}, includeParameters),
|
|
504
|
+
segment({
|
|
505
|
+
id: 'persona',
|
|
506
|
+
label: 'Active persona',
|
|
507
|
+
status: activePersona && activePersona.reviewState !== 'reviewed' ? 'attention' : activePersona ? 'active' : 'empty',
|
|
508
|
+
order: 7,
|
|
509
|
+
activeCount: activePersona?.reviewState === 'reviewed' ? 1 : 0,
|
|
510
|
+
suppressedCount: activePersona && activePersona.reviewState !== 'reviewed' ? 1 : 0,
|
|
511
|
+
promptChars: personaPrompt.length,
|
|
512
|
+
promptText: personaPrompt,
|
|
513
|
+
route: 'memory action:"curator" query:"persona"',
|
|
514
|
+
selected: activePersona?.reviewState === 'reviewed' ? [{ id: activePersona.id, name: activePersona.name, inspectRoute: `agent_local_registry domain:"persona" action:"get" recordId:"${activePersona.id}"` }] : [],
|
|
515
|
+
suppressed: activePersona && activePersona.reviewState !== 'reviewed' ? [{ id: activePersona.id, name: activePersona.name, reviewState: activePersona.reviewState }] : [],
|
|
516
|
+
}, includeParameters),
|
|
517
|
+
segment({
|
|
518
|
+
id: 'context_window_supplement',
|
|
519
|
+
label: 'Context-window supplement',
|
|
520
|
+
status: tierPrompt ? 'active' : 'empty',
|
|
521
|
+
order: 8,
|
|
522
|
+
activeCount: tierPrompt ? 1 : 0,
|
|
523
|
+
suppressedCount: 0,
|
|
524
|
+
promptChars: tierPrompt.length,
|
|
525
|
+
promptText: tierPrompt,
|
|
526
|
+
note: `Model ${currentModel} has context window ${contextWindow}; tier ${tier}.`,
|
|
527
|
+
}, includeParameters),
|
|
528
|
+
];
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
export function promptContextSummary(context: CommandContext, args: PromptContextArgs): Record<string, unknown> {
|
|
532
|
+
const includeParameters = args.includeParameters === true;
|
|
533
|
+
const segments = [...promptContextSegments(context, includeParameters)].sort((left, right) => left.order - right.order);
|
|
534
|
+
const activeRecords = segments.reduce((total, entry) => total + entry.activeCount, 0);
|
|
535
|
+
const suppressedRecords = segments.reduce((total, entry) => total + entry.suppressedCount, 0);
|
|
536
|
+
const promptChars = segments.reduce((total, entry) => total + entry.promptChars, 0);
|
|
537
|
+
const approxPromptTokens = segments.reduce((total, entry) => total + entry.approxTokens, 0);
|
|
538
|
+
const { label: currentModel, contextWindow } = promptModelInfo(context);
|
|
539
|
+
const status = segments.some((entry) => entry.status === 'unavailable')
|
|
540
|
+
? 'unavailable'
|
|
541
|
+
: suppressedRecords > 0 || segments.some((entry) => entry.status === 'attention')
|
|
542
|
+
? 'attention'
|
|
543
|
+
: activeRecords > 0
|
|
544
|
+
? 'ready'
|
|
545
|
+
: 'empty';
|
|
546
|
+
return {
|
|
547
|
+
status,
|
|
548
|
+
order: ['base_system_prompt', 'vibe', 'project_context', 'operator_policy', 'memory', 'routines', 'skills', 'persona', 'context_window_supplement'],
|
|
549
|
+
model: currentModel,
|
|
550
|
+
provider: context.session.runtime.provider,
|
|
551
|
+
contextWindow,
|
|
552
|
+
activeSegments: segments.filter((entry) => entry.status === 'active' || entry.status === 'attention').length,
|
|
553
|
+
activeRecords,
|
|
554
|
+
suppressedRecords,
|
|
555
|
+
promptChars,
|
|
556
|
+
approxPromptTokens,
|
|
557
|
+
budget: {
|
|
558
|
+
approxPromptTokens,
|
|
559
|
+
contextWindow,
|
|
560
|
+
percentOfWindow: contextWindow > 0 ? Math.round((approxPromptTokens / contextWindow) * 1000) / 10 : null,
|
|
561
|
+
},
|
|
562
|
+
receipts: promptContextReceiptSummary(context, args, includeParameters),
|
|
563
|
+
segments,
|
|
564
|
+
routes: {
|
|
565
|
+
promptPlan: 'memory action:"curator" includeParameters:true',
|
|
566
|
+
memoryPosture: 'memory action:"status"',
|
|
567
|
+
projectContext: 'context action:"files"',
|
|
568
|
+
vibeStatus: 'vibe action:"status"',
|
|
569
|
+
learningCurator: 'memory action:"curator"',
|
|
570
|
+
},
|
|
571
|
+
policy: 'Read-only prompt context inspection. It reports current prompt composition, selected records, suppressed review/setup work, and approximate token budget without creating memory, mutating behavior, or dumping raw secrets.',
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
export function promptContextCatalogStatus(context: CommandContext): Record<string, unknown> {
|
|
576
|
+
const summary = promptContextSummary(context, {});
|
|
577
|
+
const receipts = context.clients?.promptContextReceipts;
|
|
578
|
+
const latestReceipt = receipts?.latest() ?? null;
|
|
579
|
+
return {
|
|
580
|
+
modes: ['prompt_context'],
|
|
581
|
+
status: summary.status,
|
|
582
|
+
activeRecords: summary.activeRecords,
|
|
583
|
+
suppressedRecords: summary.suppressedRecords,
|
|
584
|
+
approxPromptTokens: summary.approxPromptTokens,
|
|
585
|
+
receiptCount: receipts?.count() ?? 0,
|
|
586
|
+
latestReceiptId: latestReceipt?.receiptId ?? null,
|
|
587
|
+
modelRoute: 'context action:"prompt" includeParameters:true',
|
|
588
|
+
};
|
|
589
|
+
}
|
|
@@ -189,7 +189,7 @@ export async function describeHarnessProviderAccount(
|
|
|
189
189
|
if (!lookup) {
|
|
190
190
|
return {
|
|
191
191
|
status: 'missing_lookup',
|
|
192
|
-
usage: 'provider_account requires providerId, target, or query.
|
|
192
|
+
usage: 'provider_account requires providerId, target, or query. Prefer models action:"providers" to inspect provider ids.',
|
|
193
193
|
};
|
|
194
194
|
}
|
|
195
195
|
const snapshot = await loadSnapshot(context);
|
|
@@ -211,6 +211,6 @@ export async function describeHarnessProviderAccount(
|
|
|
211
211
|
}
|
|
212
212
|
return {
|
|
213
213
|
status: 'missing_lookup',
|
|
214
|
-
usage: `Unknown provider account ${lookup.input}.
|
|
214
|
+
usage: `Unknown provider account ${lookup.input}. Prefer models action:"providers" to inspect provider ids.`,
|
|
215
215
|
};
|
|
216
216
|
}
|
|
@@ -122,8 +122,8 @@ function artifactSearchText(artifact: ReleaseEvidenceArtifact): string {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
function releaseEvidenceModelRoute(artifact?: ReleaseEvidenceArtifact): string {
|
|
125
|
-
if (artifact) return '
|
|
126
|
-
return '
|
|
125
|
+
if (artifact) return 'audit action:"artifact"';
|
|
126
|
+
return 'audit action:"evidence" or action:"artifact"';
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
function releaseEvidencePolicy(): Record<string, unknown> {
|
|
@@ -273,8 +273,9 @@ function summarizeLoadedArtifact(
|
|
|
273
273
|
summary,
|
|
274
274
|
policy: releaseEvidencePolicy(),
|
|
275
275
|
modelAccess: {
|
|
276
|
-
listArtifacts: '
|
|
277
|
-
inspectArtifact: `
|
|
276
|
+
listArtifacts: 'audit action:"evidence"',
|
|
277
|
+
inspectArtifact: `audit action:"artifact" artifactId:"${loaded.artifact.id}"`,
|
|
278
|
+
lowerLevelArtifact: `agent_harness mode:"release_evidence_artifact" artifactId:"${loaded.artifact.id}" includeParameters:true`,
|
|
278
279
|
includeContent: 'Pass includeParameters:true only when release audit requires artifact content.',
|
|
279
280
|
},
|
|
280
281
|
...(options.includeSource
|
|
@@ -323,10 +324,11 @@ export function releaseEvidenceSummary(args: ReleaseEvidenceArgs): Record<string
|
|
|
323
324
|
artifactsList: loaded.map((artifact) => summarizeLoadedArtifact(artifact, { includeSource: args.includeParameters === true })),
|
|
324
325
|
policy: releaseEvidencePolicy(),
|
|
325
326
|
modelAccess: {
|
|
326
|
-
listArtifacts: '
|
|
327
|
-
inspectArtifact: '
|
|
327
|
+
listArtifacts: 'audit action:"evidence"',
|
|
328
|
+
inspectArtifact: 'audit action:"artifact" with artifactId, target, or query',
|
|
329
|
+
lowerLevelArtifact: 'agent_harness mode:"release_evidence_artifact" artifactId:"..." includeParameters:true',
|
|
328
330
|
},
|
|
329
|
-
artifactLookup: 'Use
|
|
331
|
+
artifactLookup: 'Use audit action:"artifact" with artifactId, target, or query to inspect one release evidence artifact; lower-level agent_harness mode:"release_evidence_artifact" remains available.',
|
|
330
332
|
};
|
|
331
333
|
}
|
|
332
334
|
|