@pellux/goodvibes-agent 1.1.6 → 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 +176 -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 +132662 -91399
- 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 +43 -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 +287 -0
- 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 +267 -10
- 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 +110 -89
- 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/tools/tool-execution-safety.ts +41 -0
- package/src/version.ts +1 -1
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import type { ArtifactDescriptor } from '@pellux/goodvibes-sdk/platform/artifacts';
|
|
3
|
+
import type { Tool } from '@pellux/goodvibes-sdk/platform/types';
|
|
4
|
+
import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
|
|
5
|
+
import { DEFAULT_LIST_LIMIT, MAX_FRESHNESS_ARTIFACT_SCAN, MAX_LIST_LIMIT, REVIEW_PACKET_PRESET_SCHEMA, auditPresetFreshness, buildPresetRecord, clamp, compactText, defaultPacketSummary, isPresetArtifact, packetFromMetadata, parseMode, parsePresetBody, presetCreateInput, readBoolean, readMetadataString, readNumber, readString, sourceArtifactId, type AgentReviewPacketPresetArtifactStore, type AgentReviewPacketPresetsToolArgs, type LoadedReviewPacketPreset, type ReviewPacketFreshnessAudit, type ReviewPacketPresetPacket, type ReviewPacketPresetRecord } from './agent-review-packet-presets-core.ts';
|
|
6
|
+
function formatPacketLines(packet: ReviewPacketPresetPacket): readonly string[] {
|
|
7
|
+
return [
|
|
8
|
+
` summary ${packet.summary}`,
|
|
9
|
+
packet.documentId ? ` document ${packet.documentId}${packet.documentTitle ? ` (${packet.documentTitle})` : ''}` : '',
|
|
10
|
+
packet.documentExportArtifactId ? ` documentExport ${packet.documentExportArtifactId}` : '',
|
|
11
|
+
packet.comparisonArtifactId ? ` comparison ${packet.comparisonArtifactId}` : '',
|
|
12
|
+
packet.judgmentArtifactId ? ` judgment ${packet.judgmentArtifactId}` : '',
|
|
13
|
+
packet.revealedJudgmentArtifactId ? ` revealedJudgment ${packet.revealedJudgmentArtifactId}` : '',
|
|
14
|
+
packet.routeDecisionArtifactId ? ` routeDecision ${packet.routeDecisionArtifactId}${packet.routeDecision ? ` (${packet.routeDecision})` : ''}` : '',
|
|
15
|
+
packet.handoffArtifactId ? ` handoff ${packet.handoffArtifactId}` : '',
|
|
16
|
+
packet.handoffArchiveArtifactId ? ` handoffArchive ${packet.handoffArchiveArtifactId}` : '',
|
|
17
|
+
` related ${packet.relatedArtifactIds.length > 0 ? packet.relatedArtifactIds.join(', ') : '(none)'}`,
|
|
18
|
+
].filter(Boolean);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function formatPresetPreview(record: ReviewPacketPresetRecord): string {
|
|
22
|
+
return [
|
|
23
|
+
'Agent review packet preset preview',
|
|
24
|
+
` name ${record.name}`,
|
|
25
|
+
` preset ${record.presetId}`,
|
|
26
|
+
...formatPacketLines(record.packet),
|
|
27
|
+
' policy save one local preset artifact only; documents, model routing, handoffs, and archives are unchanged',
|
|
28
|
+
].join('\n');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function formatSaveResult(descriptor: ArtifactDescriptor, record: ReviewPacketPresetRecord): string {
|
|
32
|
+
return [
|
|
33
|
+
'Review packet preset saved',
|
|
34
|
+
` artifact ${descriptor.id}`,
|
|
35
|
+
` preset ${record.presetId}`,
|
|
36
|
+
` name ${record.name}`,
|
|
37
|
+
...formatPacketLines(record.packet),
|
|
38
|
+
` inspect agent_review_packet_presets mode:"show" artifactId:"${descriptor.id}"`,
|
|
39
|
+
' list agent_review_packet_presets mode:"list"',
|
|
40
|
+
' policy local preset artifact only; documents, model routing, handoffs, and archives unchanged',
|
|
41
|
+
].join('\n');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function packetReferenceFingerprint(packet: ReviewPacketPresetPacket): string {
|
|
45
|
+
return JSON.stringify({
|
|
46
|
+
documentId: packet.documentId ?? '',
|
|
47
|
+
documentTitle: packet.documentTitle ?? '',
|
|
48
|
+
documentExportArtifactId: packet.documentExportArtifactId ?? '',
|
|
49
|
+
comparisonArtifactId: packet.comparisonArtifactId ?? '',
|
|
50
|
+
judgmentArtifactId: packet.judgmentArtifactId ?? '',
|
|
51
|
+
revealedJudgmentArtifactId: packet.revealedJudgmentArtifactId ?? '',
|
|
52
|
+
routeDecisionArtifactId: packet.routeDecisionArtifactId ?? '',
|
|
53
|
+
routeDecision: packet.routeDecision ?? '',
|
|
54
|
+
handoffArtifactId: packet.handoffArtifactId ?? '',
|
|
55
|
+
handoffArchiveArtifactId: packet.handoffArchiveArtifactId ?? '',
|
|
56
|
+
relatedArtifactIds: packet.relatedArtifactIds,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function hasRefreshableReplacements(audit: ReviewPacketFreshnessAudit): boolean {
|
|
61
|
+
return audit.missing.some((missing) => Boolean(missing.replacementId)) || audit.superseded.length > 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function unresolvedFreshnessCount(audit: ReviewPacketFreshnessAudit): number {
|
|
65
|
+
return audit.missing.filter((missing) => !missing.replacementId).length;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function updateSummaryReferences(summary: string, audit: ReviewPacketFreshnessAudit): string {
|
|
69
|
+
let updated = summary;
|
|
70
|
+
const replace = (from: string, to: string | undefined): void => {
|
|
71
|
+
if (!to || !from || from === to) return;
|
|
72
|
+
updated = updated.split(from).join(to);
|
|
73
|
+
};
|
|
74
|
+
for (const missing of audit.missing) replace(missing.id, missing.replacementId);
|
|
75
|
+
for (const superseded of audit.superseded) replace(superseded.id, superseded.replacementId);
|
|
76
|
+
return updated.trim();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function refreshedPacket(
|
|
80
|
+
original: ReviewPacketPresetPacket,
|
|
81
|
+
audit: ReviewPacketFreshnessAudit,
|
|
82
|
+
explicitSummary: string,
|
|
83
|
+
): ReviewPacketPresetPacket {
|
|
84
|
+
const recommended = audit.recommendedPacket;
|
|
85
|
+
const summary = explicitSummary
|
|
86
|
+
|| updateSummaryReferences(original.summary, audit)
|
|
87
|
+
|| defaultPacketSummary(recommended);
|
|
88
|
+
return { ...recommended, summary };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function buildRefreshRecord(input: {
|
|
92
|
+
readonly args: AgentReviewPacketPresetsToolArgs;
|
|
93
|
+
readonly loaded: LoadedReviewPacketPreset;
|
|
94
|
+
readonly audit: ReviewPacketFreshnessAudit;
|
|
95
|
+
readonly packet: ReviewPacketPresetPacket;
|
|
96
|
+
}): ReviewPacketPresetRecord {
|
|
97
|
+
const explicitUserRequest = readString(input.args.explicitUserRequest);
|
|
98
|
+
if (!explicitUserRequest) {
|
|
99
|
+
throw new Error('explicitUserRequest is required so refreshed packet presets stay tied to a direct user request.');
|
|
100
|
+
}
|
|
101
|
+
const oldName = input.loaded.body?.name
|
|
102
|
+
|| readMetadataString(input.loaded.descriptor.metadata, 'name')
|
|
103
|
+
|| input.loaded.descriptor.filename
|
|
104
|
+
|| input.loaded.descriptor.id;
|
|
105
|
+
const oldPresetId = input.loaded.body?.presetId || readMetadataString(input.loaded.descriptor.metadata, 'presetId');
|
|
106
|
+
const requestedName = readString(input.args.name);
|
|
107
|
+
return {
|
|
108
|
+
schema: REVIEW_PACKET_PRESET_SCHEMA,
|
|
109
|
+
schemaVersion: 1,
|
|
110
|
+
presetId: `packet_preset_${randomUUID()}`,
|
|
111
|
+
name: requestedName || `${oldName} refreshed`,
|
|
112
|
+
createdAt: new Date().toISOString(),
|
|
113
|
+
explicitUserRequest,
|
|
114
|
+
packet: refreshedPacket(input.packet, input.audit, readString(input.args.summary)),
|
|
115
|
+
refresh: {
|
|
116
|
+
sourceArtifactId: input.loaded.descriptor.id,
|
|
117
|
+
...(oldPresetId ? { sourcePresetId: oldPresetId } : {}),
|
|
118
|
+
missingCount: input.audit.missing.length,
|
|
119
|
+
supersededCount: input.audit.superseded.length,
|
|
120
|
+
unresolvedCount: unresolvedFreshnessCount(input.audit),
|
|
121
|
+
},
|
|
122
|
+
policy: {
|
|
123
|
+
effect: 'save-local-preset-artifact-only',
|
|
124
|
+
documentsChanged: false,
|
|
125
|
+
modelRouteChanged: false,
|
|
126
|
+
handoffArchiveCreated: false,
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function formatRefreshPreview(
|
|
132
|
+
source: LoadedReviewPacketPreset,
|
|
133
|
+
audit: ReviewPacketFreshnessAudit,
|
|
134
|
+
record: ReviewPacketPresetRecord,
|
|
135
|
+
): string {
|
|
136
|
+
return [
|
|
137
|
+
'Agent review packet preset refresh preview',
|
|
138
|
+
` refreshOf ${source.descriptor.id}`,
|
|
139
|
+
` name ${record.name}`,
|
|
140
|
+
...formatFreshnessLines(audit),
|
|
141
|
+
' refreshed packet',
|
|
142
|
+
...formatPacketLines(record.packet),
|
|
143
|
+
' policy save one new local preset artifact only; source preset, documents, model routing, handoffs, and archives are unchanged',
|
|
144
|
+
].join('\n');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function formatRefreshResult(
|
|
148
|
+
descriptor: ArtifactDescriptor,
|
|
149
|
+
source: LoadedReviewPacketPreset,
|
|
150
|
+
audit: ReviewPacketFreshnessAudit,
|
|
151
|
+
record: ReviewPacketPresetRecord,
|
|
152
|
+
): string {
|
|
153
|
+
return [
|
|
154
|
+
'Review packet preset refreshed',
|
|
155
|
+
` artifact ${descriptor.id}`,
|
|
156
|
+
` refreshedFrom ${source.descriptor.id}`,
|
|
157
|
+
` preset ${record.presetId}`,
|
|
158
|
+
` name ${record.name}`,
|
|
159
|
+
...formatPacketLines(record.packet),
|
|
160
|
+
` freshness repaired ${audit.missing.filter((missing) => Boolean(missing.replacementId)).length + audit.superseded.length}; unresolved ${unresolvedFreshnessCount(audit)}`,
|
|
161
|
+
` inspect agent_review_packet_presets mode:"show" artifactId:"${descriptor.id}"`,
|
|
162
|
+
' policy local preset artifact only; source preset, documents, model routing, handoffs, and archives unchanged',
|
|
163
|
+
].join('\n');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function formatAlreadyCurrent(source: LoadedReviewPacketPreset, audit: ReviewPacketFreshnessAudit): string {
|
|
167
|
+
return [
|
|
168
|
+
'Review packet preset already current',
|
|
169
|
+
` artifact ${source.descriptor.id}`,
|
|
170
|
+
` ${formatFreshnessSummary(audit)}`,
|
|
171
|
+
' no new preset artifact created',
|
|
172
|
+
' policy documents, model routing, handoffs, and archives unchanged',
|
|
173
|
+
].join('\n');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function formatFreshnessSummary(audit: ReviewPacketFreshnessAudit): string {
|
|
177
|
+
if (!audit.available) return 'freshness unchecked; artifact list unavailable';
|
|
178
|
+
if (audit.status === 'current') return `freshness current; checked ${audit.scannedArtifacts} artifact(s)`;
|
|
179
|
+
return `freshness needs-review; missing ${audit.missing.length}; newer ${audit.superseded.length}; checked ${audit.scannedArtifacts} artifact(s)`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function formatFreshnessLines(audit: ReviewPacketFreshnessAudit): readonly string[] {
|
|
183
|
+
if (!audit.available) return [' freshness unchecked; artifact list unavailable'];
|
|
184
|
+
const lines = [` ${formatFreshnessSummary(audit)}`];
|
|
185
|
+
for (const missing of audit.missing.slice(0, 8)) {
|
|
186
|
+
lines.push(
|
|
187
|
+
` missing ${missing.label} ${missing.id}${missing.replacementId ? `; recommended ${missing.replacementId} (${missing.reason ?? 'matching artifact'})` : ''}`,
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
for (const superseded of audit.superseded.slice(0, 8)) {
|
|
191
|
+
lines.push(` newer ${superseded.label} ${superseded.id} -> ${superseded.replacementId} (${superseded.reason})`);
|
|
192
|
+
}
|
|
193
|
+
const shownMissing = Math.min(audit.missing.length, 8);
|
|
194
|
+
const shownSuperseded = Math.min(audit.superseded.length, 8);
|
|
195
|
+
const hidden = Math.max(0, audit.missing.length + audit.superseded.length - shownMissing - shownSuperseded);
|
|
196
|
+
if (hidden > 0) lines.push(` freshness omitted ${hidden} additional issue(s)`);
|
|
197
|
+
if (audit.status === 'needs-review') {
|
|
198
|
+
lines.push(' policy inspect freshness before reuse; recommended routes below use newer ids when a safe replacement was found');
|
|
199
|
+
}
|
|
200
|
+
return lines;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function formatList(
|
|
204
|
+
artifacts: readonly ArtifactDescriptor[],
|
|
205
|
+
total: number,
|
|
206
|
+
allArtifacts: readonly ArtifactDescriptor[] | null,
|
|
207
|
+
store?: AgentReviewPacketPresetArtifactStore,
|
|
208
|
+
): string {
|
|
209
|
+
if (artifacts.length === 0) {
|
|
210
|
+
return [
|
|
211
|
+
'Saved review packet presets',
|
|
212
|
+
' none found',
|
|
213
|
+
' save agent_review_packet_presets mode:"save" name:"..." confirm:true explicitUserRequest:"..."',
|
|
214
|
+
].join('\n');
|
|
215
|
+
}
|
|
216
|
+
return [
|
|
217
|
+
'Saved review packet presets',
|
|
218
|
+
` shown ${artifacts.length}/${total}`,
|
|
219
|
+
...artifacts.flatMap((artifact) => {
|
|
220
|
+
const packet = packetFromMetadata(artifact);
|
|
221
|
+
const audit = auditPresetFreshness({ packet, descriptor: artifact, artifacts: allArtifacts, store });
|
|
222
|
+
const name = readMetadataString(artifact.metadata, 'name') || artifact.filename || artifact.id;
|
|
223
|
+
const source = sourceArtifactId(packet) || '(no source)';
|
|
224
|
+
return [
|
|
225
|
+
` - ${artifact.id}: ${name}`,
|
|
226
|
+
` summary ${compactText(packet.summary, 120)}`,
|
|
227
|
+
` document ${packet.documentId ?? '(none)'}; source ${source}; handoff ${packet.handoffArtifactId ?? '(none)'}; archive ${packet.handoffArchiveArtifactId ?? '(none)'}; related ${packet.relatedArtifactIds.length}`,
|
|
228
|
+
` ${formatFreshnessSummary(audit)}`,
|
|
229
|
+
audit.status === 'needs-review' && hasRefreshableReplacements(audit)
|
|
230
|
+
? ` refresh agent_review_packet_presets mode:"refresh" artifactId:"${artifact.id}" confirm:true explicitUserRequest:"..."`
|
|
231
|
+
: '',
|
|
232
|
+
` inspect agent_review_packet_presets mode:"show" artifactId:"${artifact.id}"`,
|
|
233
|
+
].filter(Boolean);
|
|
234
|
+
}),
|
|
235
|
+
].join('\n');
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function formatShow(loaded: LoadedReviewPacketPreset, audit: ReviewPacketFreshnessAudit): string {
|
|
239
|
+
const packet = loaded.body?.packet ?? packetFromMetadata(loaded.descriptor);
|
|
240
|
+
const routePacket = audit.recommendedPacket;
|
|
241
|
+
const name = loaded.body?.name || readMetadataString(loaded.descriptor.metadata, 'name') || loaded.descriptor.filename || loaded.descriptor.id;
|
|
242
|
+
const presetId = loaded.body?.presetId || readMetadataString(loaded.descriptor.metadata, 'presetId') || loaded.descriptor.id;
|
|
243
|
+
const sourceId = sourceArtifactId(routePacket);
|
|
244
|
+
const related = JSON.stringify(routePacket.relatedArtifactIds);
|
|
245
|
+
return [
|
|
246
|
+
'Saved review packet preset',
|
|
247
|
+
` artifact ${loaded.descriptor.id}`,
|
|
248
|
+
` preset ${presetId}`,
|
|
249
|
+
` name ${name}`,
|
|
250
|
+
...formatPacketLines(packet),
|
|
251
|
+
...formatFreshnessLines(audit),
|
|
252
|
+
loaded.body?.explicitUserRequest ? ` explicitUserRequest ${compactText(loaded.body.explicitUserRequest, 140)}` : '',
|
|
253
|
+
sourceId ? ` sideBySide agent_model_compare mode:"sideBySide" artifactId:"${sourceId}" relatedArtifactIds:${related}` : '',
|
|
254
|
+
sourceId ? ` handoff agent_model_compare mode:"handoff" artifactId:"${sourceId}" relatedArtifactIds:${related} confirm:true explicitUserRequest:"..."` : '',
|
|
255
|
+
routePacket.revealedJudgmentArtifactId ? ` routeDecision agent_model_compare mode:"routeDecision" artifactId:"${routePacket.revealedJudgmentArtifactId}" decision:"left-unchanged" confirm:true explicitUserRequest:"..."` : '',
|
|
256
|
+
routePacket.handoffArtifactId ? ` archive agent_model_compare mode:"handoffArchive" artifactId:"${routePacket.handoffArtifactId}" confirm:true explicitUserRequest:"..."` : '',
|
|
257
|
+
routePacket.handoffArchiveArtifactId ? ` inspectArchive agent_artifacts mode:"show" artifactId:"${routePacket.handoffArchiveArtifactId}"` : '',
|
|
258
|
+
audit.status === 'needs-review' && hasRefreshableReplacements(audit)
|
|
259
|
+
? ` refreshPreset agent_review_packet_presets mode:"refresh" artifactId:"${loaded.descriptor.id}" confirm:true explicitUserRequest:"..."`
|
|
260
|
+
: '',
|
|
261
|
+
' policy read-only inspection; reuse routes still require explicit confirmation where shown',
|
|
262
|
+
].filter(Boolean).join('\n');
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async function loadPresetArtifact(
|
|
266
|
+
store: AgentReviewPacketPresetArtifactStore,
|
|
267
|
+
artifactId: string,
|
|
268
|
+
): Promise<LoadedReviewPacketPreset | null> {
|
|
269
|
+
if (store.readContent) {
|
|
270
|
+
const { record, buffer } = await store.readContent(artifactId);
|
|
271
|
+
if (!isPresetArtifact(record)) return null;
|
|
272
|
+
return { descriptor: record, record, body: parsePresetBody(buffer) ?? undefined };
|
|
273
|
+
}
|
|
274
|
+
const descriptor = store.list?.(200).find((artifact) => artifact.id === artifactId) ?? null;
|
|
275
|
+
if (!descriptor || !isPresetArtifact(descriptor)) return null;
|
|
276
|
+
return { descriptor };
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export function createAgentReviewPacketPresetsTool(
|
|
280
|
+
artifactStore?: AgentReviewPacketPresetArtifactStore,
|
|
281
|
+
): Tool {
|
|
282
|
+
return {
|
|
283
|
+
definition: {
|
|
284
|
+
name: 'agent_review_packet_presets',
|
|
285
|
+
description: 'Save and refresh reusable Document Ops packet presets.',
|
|
286
|
+
parameters: {
|
|
287
|
+
type: 'object',
|
|
288
|
+
properties: {
|
|
289
|
+
mode: {
|
|
290
|
+
type: 'string',
|
|
291
|
+
enum: ['list', 'show', 'save', 'refresh'],
|
|
292
|
+
description: 'List, show, save, or refresh one review packet preset.',
|
|
293
|
+
},
|
|
294
|
+
artifactId: {
|
|
295
|
+
type: 'string',
|
|
296
|
+
description: 'Saved preset artifact id for show or refresh mode.',
|
|
297
|
+
},
|
|
298
|
+
name: {
|
|
299
|
+
type: 'string',
|
|
300
|
+
description: 'Human-friendly preset name for save or refresh mode.',
|
|
301
|
+
},
|
|
302
|
+
documentId: {
|
|
303
|
+
type: 'string',
|
|
304
|
+
description: 'Agent document draft id captured by the preset.',
|
|
305
|
+
},
|
|
306
|
+
documentTitle: {
|
|
307
|
+
type: 'string',
|
|
308
|
+
description: 'Optional document title captured by the preset.',
|
|
309
|
+
},
|
|
310
|
+
documentExportArtifactId: {
|
|
311
|
+
type: 'string',
|
|
312
|
+
description: 'Exported document evidence artifact id.',
|
|
313
|
+
},
|
|
314
|
+
comparisonArtifactId: {
|
|
315
|
+
type: 'string',
|
|
316
|
+
description: 'Saved blind comparison artifact id.',
|
|
317
|
+
},
|
|
318
|
+
judgmentArtifactId: {
|
|
319
|
+
type: 'string',
|
|
320
|
+
description: 'Saved comparison judgment artifact id.',
|
|
321
|
+
},
|
|
322
|
+
revealedJudgmentArtifactId: {
|
|
323
|
+
type: 'string',
|
|
324
|
+
description: 'Revealed judgment artifact id for route decisions.',
|
|
325
|
+
},
|
|
326
|
+
routeDecisionArtifactId: {
|
|
327
|
+
type: 'string',
|
|
328
|
+
description: 'Saved route-decision receipt artifact id.',
|
|
329
|
+
},
|
|
330
|
+
routeDecision: {
|
|
331
|
+
type: 'string',
|
|
332
|
+
description: 'Route decision label such as left-unchanged.',
|
|
333
|
+
},
|
|
334
|
+
handoffArtifactId: {
|
|
335
|
+
type: 'string',
|
|
336
|
+
description: 'Reviewer handoff artifact id.',
|
|
337
|
+
},
|
|
338
|
+
handoffArchiveArtifactId: {
|
|
339
|
+
type: 'string',
|
|
340
|
+
description: 'Final reviewer handoff ZIP artifact id.',
|
|
341
|
+
},
|
|
342
|
+
relatedArtifactIds: {
|
|
343
|
+
type: 'array',
|
|
344
|
+
items: { type: 'string' },
|
|
345
|
+
description: 'Related evidence artifact ids to reuse.',
|
|
346
|
+
},
|
|
347
|
+
summary: {
|
|
348
|
+
type: 'string',
|
|
349
|
+
description: 'Short preset summary.',
|
|
350
|
+
},
|
|
351
|
+
limit: {
|
|
352
|
+
type: 'number',
|
|
353
|
+
description: 'Maximum presets to list.',
|
|
354
|
+
},
|
|
355
|
+
confirm: {
|
|
356
|
+
type: 'boolean',
|
|
357
|
+
description: 'Required true for save or refresh mode.',
|
|
358
|
+
},
|
|
359
|
+
explicitUserRequest: {
|
|
360
|
+
type: 'string',
|
|
361
|
+
description: 'User request authorizing preset save or refresh.',
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
required: ['mode'],
|
|
365
|
+
additionalProperties: false,
|
|
366
|
+
},
|
|
367
|
+
sideEffects: ['state'],
|
|
368
|
+
concurrency: 'serial',
|
|
369
|
+
},
|
|
370
|
+
execute: async (rawArgs: Record<string, unknown>) => {
|
|
371
|
+
const args = rawArgs as AgentReviewPacketPresetsToolArgs;
|
|
372
|
+
try {
|
|
373
|
+
const mode = parseMode(args.mode);
|
|
374
|
+
if (mode === 'list') {
|
|
375
|
+
if (!artifactStore?.list) return failure('Review packet preset list is unavailable because this runtime cannot list artifacts.');
|
|
376
|
+
const limit = clamp(readNumber(args.limit, DEFAULT_LIST_LIMIT), 1, MAX_LIST_LIMIT);
|
|
377
|
+
const allArtifacts = artifactStore.list(Math.max(MAX_FRESHNESS_ARTIFACT_SCAN, limit * 4));
|
|
378
|
+
const source = allArtifacts.filter(isPresetArtifact);
|
|
379
|
+
const ordered = source.sort((left, right) => right.createdAt - left.createdAt || left.id.localeCompare(right.id));
|
|
380
|
+
return output(formatList(ordered.slice(0, limit), source.length, allArtifacts, artifactStore));
|
|
381
|
+
}
|
|
382
|
+
if (mode === 'show') {
|
|
383
|
+
const artifactId = readString(args.artifactId);
|
|
384
|
+
if (!artifactId) return failure('artifactId is required for mode:"show".');
|
|
385
|
+
if (!artifactStore?.readContent && !artifactStore?.list) return failure('Review packet preset show is unavailable because this runtime cannot read or list artifacts.');
|
|
386
|
+
const loaded = await loadPresetArtifact(artifactStore, artifactId);
|
|
387
|
+
if (!loaded) return failure(`Unknown review packet preset artifact ${artifactId}. Use agent_review_packet_presets mode:"list" first.`);
|
|
388
|
+
const allArtifacts = artifactStore.list?.(MAX_FRESHNESS_ARTIFACT_SCAN) ?? null;
|
|
389
|
+
const packet = loaded.body?.packet ?? packetFromMetadata(loaded.descriptor);
|
|
390
|
+
return output(formatShow(loaded, auditPresetFreshness({
|
|
391
|
+
packet,
|
|
392
|
+
descriptor: loaded.descriptor,
|
|
393
|
+
artifacts: allArtifacts,
|
|
394
|
+
store: artifactStore,
|
|
395
|
+
})));
|
|
396
|
+
}
|
|
397
|
+
if (mode === 'refresh') {
|
|
398
|
+
const artifactId = readString(args.artifactId);
|
|
399
|
+
if (!artifactId) return failure('artifactId is required for mode:"refresh".');
|
|
400
|
+
if (!artifactStore?.create) return failure('Review packet preset refresh is unavailable because this runtime did not provide an artifact store.');
|
|
401
|
+
if (!artifactStore.readContent && !artifactStore.list) return failure('Review packet preset refresh is unavailable because this runtime cannot read or list artifacts.');
|
|
402
|
+
if (!artifactStore.list) return failure('Review packet preset refresh is unavailable because this runtime cannot list artifacts for freshness checks.');
|
|
403
|
+
const loaded = await loadPresetArtifact(artifactStore, artifactId);
|
|
404
|
+
if (!loaded) return failure(`Unknown review packet preset artifact ${artifactId}. Use agent_review_packet_presets mode:"list" first.`);
|
|
405
|
+
const allArtifacts = artifactStore.list(MAX_FRESHNESS_ARTIFACT_SCAN);
|
|
406
|
+
const packet = loaded.body?.packet ?? packetFromMetadata(loaded.descriptor);
|
|
407
|
+
const audit = auditPresetFreshness({
|
|
408
|
+
packet,
|
|
409
|
+
descriptor: loaded.descriptor,
|
|
410
|
+
artifacts: allArtifacts,
|
|
411
|
+
store: artifactStore,
|
|
412
|
+
});
|
|
413
|
+
if (audit.status === 'current') return output(formatAlreadyCurrent(loaded, audit));
|
|
414
|
+
const record = buildRefreshRecord({ args, loaded, audit, packet });
|
|
415
|
+
if (
|
|
416
|
+
!hasRefreshableReplacements(audit)
|
|
417
|
+
|| packetReferenceFingerprint(packet) === packetReferenceFingerprint(record.packet)
|
|
418
|
+
) {
|
|
419
|
+
return failure([
|
|
420
|
+
'Review packet preset refresh could not find a safe replacement to save.',
|
|
421
|
+
...formatFreshnessLines(audit),
|
|
422
|
+
'Inspect the preset and repair missing evidence manually before saving a new preset.',
|
|
423
|
+
].join('\n'));
|
|
424
|
+
}
|
|
425
|
+
if (!readBoolean(args.confirm)) {
|
|
426
|
+
return failure([
|
|
427
|
+
formatRefreshPreview(loaded, audit, record),
|
|
428
|
+
'',
|
|
429
|
+
'Refresh confirmation required. Call this tool with confirm:true only when the user explicitly asked GoodVibes Agent to refresh this reviewer packet preset.',
|
|
430
|
+
].join('\n'));
|
|
431
|
+
}
|
|
432
|
+
const descriptor = await artifactStore.create(presetCreateInput(record));
|
|
433
|
+
return output(formatRefreshResult(descriptor, loaded, audit, record));
|
|
434
|
+
}
|
|
435
|
+
if (!artifactStore?.create) return failure('Review packet preset save is unavailable because this runtime did not provide an artifact store.');
|
|
436
|
+
const record = buildPresetRecord(args);
|
|
437
|
+
if (!readBoolean(args.confirm)) {
|
|
438
|
+
return failure([
|
|
439
|
+
formatPresetPreview(record),
|
|
440
|
+
'',
|
|
441
|
+
'Preset confirmation required. Call this tool with confirm:true only when the user explicitly asked GoodVibes Agent to save this reviewer packet preset.',
|
|
442
|
+
].join('\n'));
|
|
443
|
+
}
|
|
444
|
+
const descriptor = await artifactStore.create(presetCreateInput(record));
|
|
445
|
+
return output(formatSaveResult(descriptor, record));
|
|
446
|
+
} catch (error) {
|
|
447
|
+
return failure(error instanceof Error ? error.message : String(error));
|
|
448
|
+
}
|
|
449
|
+
},
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function output(text: string): { readonly success: true; readonly output: string } {
|
|
454
|
+
return { success: true, output: text };
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function failure(error: string): { readonly success: false; readonly error: string } {
|
|
458
|
+
return { success: false, error };
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
export function registerAgentReviewPacketPresetsTool(
|
|
462
|
+
registry: ToolRegistry,
|
|
463
|
+
artifactStore?: AgentReviewPacketPresetArtifactStore,
|
|
464
|
+
): void {
|
|
465
|
+
registry.register(createAgentReviewPacketPresetsTool(artifactStore));
|
|
466
|
+
}
|