@pellux/goodvibes-agent 1.2.0 → 1.3.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 +159 -0
- package/dist/package/main.js +19016 -12684
- package/docs/README.md +3 -3
- package/docs/connected-host.md +2 -2
- package/docs/getting-started.md +11 -9
- package/docs/tools-and-commands.md +12 -10
- package/docs/voice-and-live-tts.md +2 -2
- package/package.json +1 -1
- package/release/release-notes.md +17 -5
- package/release/release-readiness.json +36 -36
- package/src/agent/competitive-feature-inventory.ts +42 -44
- package/src/agent/setup-wizard-artifact-receipts.ts +366 -0
- package/src/agent/setup-wizard.ts +245 -9
- package/src/input/agent-workspace-categories.ts +2 -2
- package/src/input/agent-workspace-onboarding-categories.ts +4 -4
- package/src/input/agent-workspace-settings.ts +52 -1
- package/src/input/agent-workspace-setup-snapshot.ts +20 -1
- package/src/input/agent-workspace-setup.ts +32 -5
- package/src/input/agent-workspace-snapshot.ts +23 -3
- package/src/input/agent-workspace.ts +5 -1
- package/src/input/setup-wizard-live-receipts.ts +76 -0
- package/src/renderer/agent-workspace-context-lines.ts +21 -6
- package/src/renderer/agent-workspace.ts +46 -10
- package/src/runtime/tool-permission-safety.ts +1 -1
- package/src/tools/agent-harness-agent-orchestration-policy.ts +75 -0
- package/src/tools/agent-harness-agent-orchestration.ts +216 -128
- package/src/tools/agent-harness-autonomy-live-records.ts +154 -0
- package/src/tools/agent-harness-autonomy-queue-types.ts +1 -1
- package/src/tools/agent-harness-autonomy-queue.ts +19 -8
- package/src/tools/agent-harness-autonomy-watcher-read-models.ts +509 -0
- package/src/tools/agent-harness-background-processes.ts +8 -4
- package/src/tools/agent-harness-browser-cockpit-route.ts +188 -34
- package/src/tools/agent-harness-browser-control.ts +12 -4
- package/src/tools/agent-harness-browser-pwa-read-models.ts +622 -0
- package/src/tools/agent-harness-device-live-read-models.ts +366 -0
- package/src/tools/agent-harness-execution-posture.ts +3 -0
- package/src/tools/agent-harness-interactive-runtime-records.ts +421 -0
- package/src/tools/agent-harness-local-model-benchmarks.ts +71 -1
- package/src/tools/agent-harness-local-model-endpoints.ts +469 -354
- package/src/tools/agent-harness-local-model-smoke.ts +277 -0
- package/src/tools/agent-harness-local-model-url.ts +78 -0
- package/src/tools/agent-harness-media-posture.ts +27 -12
- package/src/tools/agent-harness-memory-external-providers.ts +796 -0
- package/src/tools/agent-harness-memory-posture.ts +253 -137
- package/src/tools/agent-harness-memory-provider-certification.ts +219 -0
- package/src/tools/agent-harness-memory-refinement.ts +340 -0
- package/src/tools/agent-harness-mode-catalog.ts +4 -2
- package/src/tools/agent-harness-model-provider-health.ts +139 -42
- package/src/tools/agent-harness-model-readiness.ts +31 -5
- package/src/tools/agent-harness-model-routing-types.ts +61 -0
- package/src/tools/agent-harness-model-routing.ts +31 -6
- package/src/tools/agent-harness-pairing-posture.ts +30 -9
- package/src/tools/agent-harness-personal-ops-certification.ts +116 -0
- package/src/tools/agent-harness-personal-ops-lanes.ts +81 -15
- package/src/tools/agent-harness-personal-ops-operations.ts +225 -0
- package/src/tools/agent-harness-personal-ops-provider-records.ts +358 -0
- package/src/tools/agent-harness-personal-ops-provider-task-records.ts +321 -0
- package/src/tools/agent-harness-personal-ops-records.ts +176 -224
- package/src/tools/agent-harness-personal-ops-types.ts +19 -1
- package/src/tools/agent-harness-personal-ops.ts +18 -11
- package/src/tools/agent-harness-remote-read-models.ts +541 -0
- package/src/tools/agent-harness-research-briefing.ts +26 -7
- package/src/tools/agent-harness-research-live-read-models.ts +500 -0
- package/src/tools/agent-harness-research-runs.ts +15 -3
- package/src/tools/agent-harness-research-workflow.ts +92 -19
- package/src/tools/agent-harness-setup-model-helpers.ts +1 -0
- package/src/tools/agent-harness-setup-smoke.ts +26 -1
- package/src/tools/agent-harness-tool-schema.ts +23 -1
- package/src/tools/agent-harness-tool-types.ts +5 -0
- package/src/tools/agent-harness-tool.ts +9 -1
- package/src/tools/agent-harness-workspace-actions.ts +1 -1
- package/src/tools/agent-memory-tool.ts +40 -1
- package/src/tools/agent-model-compare-run.ts +13 -0
- package/src/tools/agent-research-runner.ts +367 -0
- package/src/tools/agent-research-tool.ts +7 -179
- package/src/tools/agent-route-planner-candidates-surfaces.ts +1 -1
- package/src/version.ts +1 -1
|
@@ -11,6 +11,12 @@ import {
|
|
|
11
11
|
type AgentResearchSourceRecord,
|
|
12
12
|
} from '../agent/research-source-registry.ts';
|
|
13
13
|
import { browserControlPosture } from './agent-harness-browser-control.ts';
|
|
14
|
+
import {
|
|
15
|
+
isCertifiedResearchLiveRecord,
|
|
16
|
+
researchLiveReadModelSnapshot,
|
|
17
|
+
type ResearchBrowserRunnerRecord,
|
|
18
|
+
type ResearchVisualReportRecord,
|
|
19
|
+
} from './agent-harness-research-live-read-models.ts';
|
|
14
20
|
import { previewHarnessText } from './agent-harness-text.ts';
|
|
15
21
|
|
|
16
22
|
interface AgentHarnessResearchWorkflowArgs {
|
|
@@ -91,6 +97,41 @@ function relatedSources(
|
|
|
91
97
|
));
|
|
92
98
|
}
|
|
93
99
|
|
|
100
|
+
function liveRunnerSearchText(record: ResearchBrowserRunnerRecord): string {
|
|
101
|
+
return [
|
|
102
|
+
record.id,
|
|
103
|
+
record.runId ?? '',
|
|
104
|
+
record.status,
|
|
105
|
+
record.phase ?? '',
|
|
106
|
+
record.question ?? '',
|
|
107
|
+
record.currentUrl ?? '',
|
|
108
|
+
record.reportDraftId ?? '',
|
|
109
|
+
record.reportArtifactId ?? '',
|
|
110
|
+
...record.sourceReceiptIds,
|
|
111
|
+
].join('\n').toLowerCase();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function matchingLiveRunners(
|
|
115
|
+
records: readonly ResearchBrowserRunnerRecord[],
|
|
116
|
+
run: AgentResearchRunRecord | null,
|
|
117
|
+
question: string,
|
|
118
|
+
): readonly ResearchBrowserRunnerRecord[] {
|
|
119
|
+
const normalized = question.toLowerCase();
|
|
120
|
+
return records.filter((record) => (
|
|
121
|
+
(!!run && record.runId === run.id)
|
|
122
|
+
|| (!!run?.reportArtifactId && record.reportArtifactId === run.reportArtifactId)
|
|
123
|
+
|| (!!normalized && liveRunnerSearchText(record).includes(normalized))
|
|
124
|
+
));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function matchingVisualReports(
|
|
128
|
+
records: readonly ResearchVisualReportRecord[],
|
|
129
|
+
run: AgentResearchRunRecord | null,
|
|
130
|
+
): readonly ResearchVisualReportRecord[] {
|
|
131
|
+
if (!run?.reportArtifactId) return records;
|
|
132
|
+
return records.filter((record) => record.reportArtifactId === run.reportArtifactId);
|
|
133
|
+
}
|
|
134
|
+
|
|
94
135
|
function runSummary(run: AgentResearchRunRecord, includeParameters: boolean): Record<string, unknown> {
|
|
95
136
|
return {
|
|
96
137
|
runId: run.id,
|
|
@@ -128,14 +169,21 @@ function sourceSummary(source: AgentResearchSourceRecord): Record<string, unknow
|
|
|
128
169
|
};
|
|
129
170
|
}
|
|
130
171
|
|
|
131
|
-
function browserRunnerContract(
|
|
172
|
+
function browserRunnerContract(
|
|
173
|
+
browser: ReturnType<typeof browserControlPosture>,
|
|
174
|
+
liveRecords: readonly ResearchBrowserRunnerRecord[],
|
|
175
|
+
): Record<string, unknown> {
|
|
176
|
+
const certified = liveRecords.filter(isCertifiedResearchLiveRecord);
|
|
132
177
|
return {
|
|
133
|
-
status: browser.configured ? 'ready-with-confirmation' : 'setup-contract-needed',
|
|
178
|
+
status: certified.length > 0 ? 'certified-live-runner' : browser.configured ? 'ready-with-confirmation' : 'setup-contract-needed',
|
|
134
179
|
userOutcome: 'Run browser-backed research only when live browser state, authenticated pages, or interactive source discovery are necessary.',
|
|
135
|
-
currentState:
|
|
180
|
+
currentState: certified.length > 0
|
|
181
|
+
? 'The SDK/daemon published certified browser-backed research run records with visible controls, source/page receipts, bounded logs, and exact inspect routes.'
|
|
182
|
+
: browser.configured
|
|
136
183
|
? 'A reviewed browser/desktop route is configured; use it only after the user accepts the browser-backed research scope.'
|
|
137
184
|
: 'No reviewed browser-backed research runner is configured, so public web_search/fetch stays the current safe route.',
|
|
138
185
|
requiredContracts: [
|
|
186
|
+
'Certified schema/version/publication/publisher/provenance/freshness-cursor/receipt metadata for every live browser-backed research run.',
|
|
139
187
|
'Trusted browser or desktop-control route with setup posture status ready.',
|
|
140
188
|
'Visible run id, phase/progress, current URL/task scope, checkpoint route, and pause/resume/cancel controls for every browser-backed research run.',
|
|
141
189
|
'Source-capture receipt for each accepted source with URL/title/publisher/summary/provenance.',
|
|
@@ -144,14 +192,17 @@ function browserRunnerContract(browser: ReturnType<typeof browserControlPosture>
|
|
|
144
192
|
'No credential or page-content leakage outside bounded redacted source summaries.',
|
|
145
193
|
],
|
|
146
194
|
setupRoutes: [
|
|
195
|
+
...certified.slice(0, 3).map((record) => record.modelRoute),
|
|
147
196
|
'computer action:"control" includeParameters:true',
|
|
148
197
|
'computer action:"setup" includeParameters:true',
|
|
149
198
|
browser.setupRoute,
|
|
150
199
|
...browser.fallbackRoutes,
|
|
151
200
|
],
|
|
152
|
-
recommendedRoute: browser.recommendedRoute,
|
|
201
|
+
recommendedRoute: certified[0]?.modelRoute ?? browser.recommendedRoute,
|
|
153
202
|
fallbackRoutes: browser.fallbackRoutes,
|
|
154
|
-
|
|
203
|
+
liveRecords: liveRecords.slice(0, 5),
|
|
204
|
+
certifiedLiveRecords: certified.slice(0, 5),
|
|
205
|
+
policy: 'Browser-backed research is not started by this workflow plan. Use certified live SDK/daemon records only as read-only evidence, and use returned confirmed routes before any browser/PWA, source-save, report-save, or Knowledge-ingest effect.',
|
|
155
206
|
};
|
|
156
207
|
}
|
|
157
208
|
|
|
@@ -160,12 +211,16 @@ function visualReportContract(options: {
|
|
|
160
211
|
readonly reportRoute: string;
|
|
161
212
|
readonly bundleRoute: string;
|
|
162
213
|
readonly question: string;
|
|
214
|
+
readonly liveRecords: readonly ResearchVisualReportRecord[];
|
|
163
215
|
}): Record<string, unknown> {
|
|
216
|
+
const certified = options.liveRecords.filter(isCertifiedResearchLiveRecord);
|
|
164
217
|
return {
|
|
165
|
-
status: options.reviewedSources > 0 ? 'visual-report-packet-ready' : 'waiting-for-reviewed-sources',
|
|
218
|
+
status: certified.length > 0 ? 'certified-live-renderer' : options.reviewedSources > 0 ? 'visual-report-packet-ready' : 'waiting-for-reviewed-sources',
|
|
166
219
|
userOutcome: 'Produce an inspectable research report with source-backed findings, citations, caveats, and handoff/export routes.',
|
|
167
|
-
currentRoute: options.reviewedSources > 0 ? options.reportRoute : options.bundleRoute,
|
|
168
|
-
currentState:
|
|
220
|
+
currentRoute: certified[0]?.modelRoute ?? (options.reviewedSources > 0 ? options.reportRoute : options.bundleRoute),
|
|
221
|
+
currentState: certified.length > 0
|
|
222
|
+
? 'The SDK/daemon published a certified browser/PWA visual report render over the same reviewed report artifact, with source-map and citation-coverage evidence.'
|
|
223
|
+
: options.reviewedSources > 0
|
|
169
224
|
? 'Agent can save a citation-covered markdown report artifact with a visual report packet now; browser/PWA rendering remains an optional view over the same artifact.'
|
|
170
225
|
: 'Review at least one source before saving a report or visual packet.',
|
|
171
226
|
requiredSections: [
|
|
@@ -184,12 +239,14 @@ function visualReportContract(options: {
|
|
|
184
239
|
'Every material claim maps to a reviewed source line or an explicit caveat.',
|
|
185
240
|
'The report artifact includes citation coverage metadata and repair hints.',
|
|
186
241
|
'The visual report packet is generated by research action:"report" visualReport:true over the same saved report/source artifacts, not a separate uncited answer.',
|
|
242
|
+
'Connected-host visual rendering counts only when the SDK/daemon publishes certified render route, source-map, citation coverage, section, publication, and receipt evidence.',
|
|
187
243
|
'Knowledge ingest remains a separate confirmed action after report review.',
|
|
188
244
|
],
|
|
189
245
|
routes: {
|
|
190
246
|
reviewedSourceBundle: options.bundleRoute,
|
|
191
247
|
saveVisualReport: options.reportRoute,
|
|
192
248
|
saveMarkdownReport: options.reportRoute,
|
|
249
|
+
...(certified[0] ? { openRenderedReport: certified[0].renderRoute } : {}),
|
|
193
250
|
reviewPacketWizard: 'agent_harness mode:"document_ops_lane" laneId:"review_packet_wizard"',
|
|
194
251
|
archiveArtifacts: 'agent_artifacts mode:"archive" artifactIds:["..."] destinationPath:"exports/research-report.zip" confirm:true explicitUserRequest:"..."',
|
|
195
252
|
},
|
|
@@ -199,6 +256,8 @@ function visualReportContract(options: {
|
|
|
199
256
|
'agent_harness mode:"document_ops_lane" laneId:"review_packet_wizard"',
|
|
200
257
|
'agent_artifacts mode:"archive" artifactIds:["..."] destinationPath:"exports/research-report.zip" confirm:true explicitUserRequest:"..."',
|
|
201
258
|
],
|
|
259
|
+
liveRecords: options.liveRecords.slice(0, 5),
|
|
260
|
+
certifiedRendererRecords: certified.slice(0, 5),
|
|
202
261
|
policy: `This contract is read-only planning for ${previewHarnessText(options.question, 96)}; saving reports, exports, packages, shares, or Knowledge ingest stay on separate confirmed routes.`,
|
|
203
262
|
};
|
|
204
263
|
}
|
|
@@ -216,6 +275,11 @@ export function researchWorkflowSummary(context: CommandContext, args: AgentHarn
|
|
|
216
275
|
const reviewedSources = matchedSources.filter((source) => source.status === 'reviewed' || source.status === 'used');
|
|
217
276
|
const candidateSources = matchedSources.filter((source) => source.status === 'candidate');
|
|
218
277
|
const browser = browserControlPosture(context);
|
|
278
|
+
const liveResearch = researchLiveReadModelSnapshot(context);
|
|
279
|
+
const liveRunnerRecords = matchingLiveRunners(liveResearch.browserRunnerRecords, run, question);
|
|
280
|
+
const certifiedRunnerRecords = liveRunnerRecords.filter(isCertifiedResearchLiveRecord);
|
|
281
|
+
const liveVisualRecords = matchingVisualReports(liveResearch.visualReportRecords, run);
|
|
282
|
+
const certifiedVisualRecords = liveVisualRecords.filter(isCertifiedResearchLiveRecord);
|
|
219
283
|
const status = !shellPaths
|
|
220
284
|
? 'unavailable'
|
|
221
285
|
: run?.status === 'completed'
|
|
@@ -251,20 +315,25 @@ export function researchWorkflowSummary(context: CommandContext, args: AgentHarn
|
|
|
251
315
|
candidateSources: candidateSources.slice(0, includeParameters ? 8 : 3).map(sourceSummary),
|
|
252
316
|
},
|
|
253
317
|
browserBackedResearch: {
|
|
254
|
-
status: browser.status,
|
|
255
|
-
configured: browser.configured,
|
|
256
|
-
recommendedRoute: browser.recommendedRoute,
|
|
318
|
+
status: certifiedRunnerRecords.length > 0 ? 'certified-live-runner' : browser.status,
|
|
319
|
+
configured: browser.configured || certifiedRunnerRecords.length > 0,
|
|
320
|
+
recommendedRoute: certifiedRunnerRecords[0]?.modelRoute ?? browser.recommendedRoute,
|
|
257
321
|
fallbackRoutes: browser.fallbackRoutes,
|
|
258
322
|
next: browser.configured
|
|
259
323
|
? 'Use reviewed browser/desktop tooling only when live browser state or authenticated pages are necessary.'
|
|
260
|
-
:
|
|
324
|
+
: certifiedRunnerRecords.length > 0
|
|
325
|
+
? 'Inspect the certified live research runner record, then use confirmed routes for follow-up source, report, or browser effects.'
|
|
326
|
+
: 'Use bounded public web_search/fetch routes now; inspect setup before browser-backed execution.',
|
|
327
|
+
liveRunnerRecords: liveRunnerRecords.slice(0, includeParameters ? 8 : 3),
|
|
328
|
+
certifiedLiveRunnerCount: certifiedRunnerRecords.length,
|
|
261
329
|
},
|
|
262
|
-
browserRunnerContract: browserRunnerContract(browser),
|
|
330
|
+
browserRunnerContract: browserRunnerContract(browser, liveRunnerRecords),
|
|
263
331
|
visualReportContract: visualReportContract({
|
|
264
332
|
reviewedSources: reviewedSources.length,
|
|
265
333
|
reportRoute,
|
|
266
334
|
bundleRoute,
|
|
267
335
|
question,
|
|
336
|
+
liveRecords: liveVisualRecords,
|
|
268
337
|
}),
|
|
269
338
|
workflow: [
|
|
270
339
|
{
|
|
@@ -276,11 +345,13 @@ export function researchWorkflowSummary(context: CommandContext, args: AgentHarn
|
|
|
276
345
|
},
|
|
277
346
|
{
|
|
278
347
|
id: 'collect-sources',
|
|
279
|
-
status: reviewedSources.length > 0 || candidateSources.length > 0 ? 'started' : 'needed',
|
|
280
|
-
next:
|
|
348
|
+
status: certifiedRunnerRecords.length > 0 ? 'ready' : reviewedSources.length > 0 || candidateSources.length > 0 ? 'started' : 'needed',
|
|
349
|
+
next: certifiedRunnerRecords.length > 0
|
|
350
|
+
? 'Use the certified live runner record to inspect source receipts, then review captured sources before report generation.'
|
|
351
|
+
: browser.configured
|
|
281
352
|
? 'Collect bounded sources, preferring primary/current sources, then capture each useful source in the queue.'
|
|
282
353
|
: 'Use web_search/fetch for public sources and capture each useful source in the queue.',
|
|
283
|
-
route: 'web_search query:"..." verbosity:"evidence" maxResults:10 evidenceTopN:3 or fetch urls:[...]',
|
|
354
|
+
route: certifiedRunnerRecords[0]?.modelRoute ?? 'web_search query:"..." verbosity:"evidence" maxResults:10 evidenceTopN:3 or fetch urls:[...]',
|
|
284
355
|
captureRoute: `research action:"add_source" question:${quote(question)} title:"..." url:"..." summary:"..." credibility:"unreviewed" tags:["research"] confirm:true explicitUserRequest:"..."`,
|
|
285
356
|
},
|
|
286
357
|
{
|
|
@@ -292,9 +363,9 @@ export function researchWorkflowSummary(context: CommandContext, args: AgentHarn
|
|
|
292
363
|
},
|
|
293
364
|
{
|
|
294
365
|
id: 'save-report',
|
|
295
|
-
status: reviewedSources.length > 0 ? 'ready' : 'waiting',
|
|
296
|
-
next: reviewedSources.length > 0 ? 'Use the reviewed-source bundle and save a citation-covered visual report packet artifact.' : 'Save the report only after reviewed or used sources exist.',
|
|
297
|
-
route: reviewedSources.length > 0 ? bundleRoute : `research action:"sources" query:${quote(sourceQuery)}
|
|
366
|
+
status: certifiedVisualRecords.length > 0 || reviewedSources.length > 0 ? 'ready' : 'waiting',
|
|
367
|
+
next: certifiedVisualRecords.length > 0 ? 'Inspect the certified browser/PWA report render, then export, archive, or promote only after review.' : reviewedSources.length > 0 ? 'Use the reviewed-source bundle and save a citation-covered visual report packet artifact.' : 'Save the report only after reviewed or used sources exist.',
|
|
368
|
+
route: certifiedVisualRecords[0]?.modelRoute ?? (reviewedSources.length > 0 ? bundleRoute : `research action:"sources" query:${quote(sourceQuery)}`),
|
|
298
369
|
reportRoute,
|
|
299
370
|
},
|
|
300
371
|
{
|
|
@@ -312,6 +383,8 @@ export function researchWorkflowSummary(context: CommandContext, args: AgentHarn
|
|
|
312
383
|
inspectSources: `research action:"sources" query:${quote(sourceQuery)}`,
|
|
313
384
|
bundleSources: bundleRoute,
|
|
314
385
|
saveReport: reportRoute,
|
|
386
|
+
...(certifiedRunnerRecords[0] ? { liveRunner: certifiedRunnerRecords[0].modelRoute } : {}),
|
|
387
|
+
...(certifiedVisualRecords[0] ? { liveVisualReport: certifiedVisualRecords[0].modelRoute } : {}),
|
|
315
388
|
...(run ? {
|
|
316
389
|
checkpointRun: `research action:"checkpoint" id:${quote(run.id)} phase:"reading" progress:${Math.max(run.progress, 25)} note:"..." sourceIds:["..."] confirm:true explicitUserRequest:"..."`,
|
|
317
390
|
completeRun: `research action:"complete" id:${quote(run.id)} reportArtifactId:"..." confirm:true explicitUserRequest:"..."`,
|
|
@@ -11,6 +11,7 @@ export function browserControlSignals(posture: BrowserControlPosture): readonly
|
|
|
11
11
|
`mcp:${server.name} ${server.connected ? 'connected' : 'disconnected'} ${server.readiness} role=${server.role} trust=${server.trustMode} schema=${server.schemaFreshness}`
|
|
12
12
|
)));
|
|
13
13
|
}
|
|
14
|
+
if (posture.certifiedRuntimeRecords.length > 0) signals.push(`certified runtime receipts: ${posture.certifiedRuntimeRecords.length}`);
|
|
14
15
|
if (signals.length === 0) signals.push('No browser, desktop, computer-use, screenshot, or screen-recording tool is configured.');
|
|
15
16
|
return signals;
|
|
16
17
|
}
|
|
@@ -2,8 +2,10 @@ import type { ArtifactDescriptor } from '@pellux/goodvibes-sdk/platform/artifact
|
|
|
2
2
|
import type { CommandContext } from '../input/command-registry.ts';
|
|
3
3
|
import { requireShellPaths } from '../input/commands/runtime-services.ts';
|
|
4
4
|
import { readOnboardingCompletionMarker } from '../runtime/onboarding/index.ts';
|
|
5
|
+
import { buildSetupWizardDurableReceipts } from '../agent/setup-wizard-artifact-receipts.ts';
|
|
6
|
+
import { mergeSetupWizardDurableReceipts, setupWizardLiveDurableReceipts } from '../input/setup-wizard-live-receipts.ts';
|
|
5
7
|
import { clearSetupWizardCheckpoint, readSetupWizardCheckpoint, saveSetupWizardCheckpoint } from '../agent/setup-wizard-checkpoint.ts';
|
|
6
|
-
import { DEFAULT_AGENT_SETUP_WIZARD_CLEAR_CHECKPOINT_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_INSPECT_CHECKPOINT_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_MARK_CHECKPOINT_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_RERUN_SMOKE_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_SAVE_SMOKE_ROUTE, buildAgentSetupWizard, emptyAgentSetupSmokeHistory, emptyAgentSetupWizardCheckpoint, type AgentSetupWizard, type AgentSetupWizardCheckpoint, type AgentSetupWizardSmokeHistory, type AgentSetupWizardSourceItem } from '../agent/setup-wizard.ts';
|
|
8
|
+
import { DEFAULT_AGENT_SETUP_WIZARD_CLEAR_CHECKPOINT_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_INSPECT_CHECKPOINT_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_MARK_CHECKPOINT_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_RERUN_SMOKE_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_SAVE_SMOKE_ROUTE, buildAgentSetupWizard, emptyAgentSetupSmokeHistory, emptyAgentSetupWizardCheckpoint, type AgentSetupWizard, type AgentSetupWizardCheckpoint, type AgentSetupWizardDurableReceipt, type AgentSetupWizardSmokeHistory, type AgentSetupWizardSourceItem } from '../agent/setup-wizard.ts';
|
|
7
9
|
import { previewHarnessText } from './agent-harness-text.ts';
|
|
8
10
|
import { readFieldMap, readString, safeIso, setupSmokeArtifactStore } from './agent-harness-setup-posture-utils.ts';
|
|
9
11
|
import { setupHandoffsForItem } from './agent-harness-setup-handoffs.ts';
|
|
@@ -273,6 +275,12 @@ export function setupSmokeEvidenceTrend(artifacts: readonly ArtifactDescriptor[]
|
|
|
273
275
|
return 'unchanged';
|
|
274
276
|
}
|
|
275
277
|
|
|
278
|
+
function artifactCreatedAtIso(artifact: ArtifactDescriptor): string | null {
|
|
279
|
+
const createdAt = artifact.createdAt;
|
|
280
|
+
if (typeof createdAt !== 'number' || !Number.isFinite(createdAt)) return null;
|
|
281
|
+
return new Date(createdAt).toISOString();
|
|
282
|
+
}
|
|
283
|
+
|
|
276
284
|
export function setupSmokeBlockedCheckFrequency(artifacts: readonly ArtifactDescriptor[]): readonly Record<string, unknown>[] {
|
|
277
285
|
const counts = new Map<string, number>();
|
|
278
286
|
for (const artifact of artifacts) {
|
|
@@ -343,6 +351,8 @@ export function setupSmokeEvidenceHistory(context: CommandContext): Record<strin
|
|
|
343
351
|
trend: setupSmokeEvidenceTrend(artifacts),
|
|
344
352
|
latestResult: readArtifactMetadataString(artifacts[0]!, 'result') || 'unknown',
|
|
345
353
|
previousResult: artifacts[1] ? readArtifactMetadataString(artifacts[1], 'result') || 'unknown' : null,
|
|
354
|
+
latestEvidenceId: artifacts[0]!.id,
|
|
355
|
+
latestEvidenceAt: artifactCreatedAtIso(artifacts[0]!),
|
|
346
356
|
resultCounts,
|
|
347
357
|
blockedCheckFrequency: setupSmokeBlockedCheckFrequency(artifacts),
|
|
348
358
|
recent: artifacts.slice(0, 5).map(describeSetupSmokeEvidenceArtifact),
|
|
@@ -373,6 +383,8 @@ export function setupWizardSmokeHistory(context: CommandContext): AgentSetupWiza
|
|
|
373
383
|
trend: setupSmokeEvidenceTrend(artifacts),
|
|
374
384
|
latestResult: readArtifactMetadataString(artifacts[0]!, 'result') || 'unknown',
|
|
375
385
|
previousResult: artifacts[1] ? readArtifactMetadataString(artifacts[1], 'result') || 'unknown' : null,
|
|
386
|
+
latestEvidenceId: artifacts[0]!.id,
|
|
387
|
+
latestEvidenceAt: artifactCreatedAtIso(artifacts[0]!),
|
|
376
388
|
resultCounts,
|
|
377
389
|
blockedCheckFrequency: setupSmokeBlockedCheckFrequency(artifacts).map((entry) => ({
|
|
378
390
|
checkId: readString(entry.checkId),
|
|
@@ -430,6 +442,17 @@ export function setupWizardCheckpoint(context: CommandContext): AgentSetupWizard
|
|
|
430
442
|
}
|
|
431
443
|
}
|
|
432
444
|
|
|
445
|
+
export function setupWizardDurableReceipts(context: CommandContext): readonly AgentSetupWizardDurableReceipt[] {
|
|
446
|
+
const artifactStore = setupSmokeArtifactStore(context);
|
|
447
|
+
const liveReceipts = setupWizardLiveDurableReceipts(context);
|
|
448
|
+
if (!artifactStore?.list) return liveReceipts;
|
|
449
|
+
try {
|
|
450
|
+
return mergeSetupWizardDurableReceipts(buildSetupWizardDurableReceipts(artifactStore.list(100)), liveReceipts);
|
|
451
|
+
} catch {
|
|
452
|
+
return liveReceipts;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
433
456
|
export function setupCompletionMarkerExists(context: CommandContext): boolean {
|
|
434
457
|
try {
|
|
435
458
|
return readOnboardingCompletionMarker(requireShellPaths(context), 'user').exists;
|
|
@@ -467,6 +490,8 @@ export function buildSetupWizard(plan: readonly SetupPlanItem[], context: Comman
|
|
|
467
490
|
smokeHistory: setupWizardSmokeHistory(context),
|
|
468
491
|
checkpoint: setupWizardCheckpoint(context),
|
|
469
492
|
closeoutCriticalStepIds: plan.filter((item) => item.blocksAutonomy).map((item) => item.id),
|
|
493
|
+
receiptRequiredStepIds: ['connected-host-readiness', 'connected-host-auth', 'install-smoke'],
|
|
494
|
+
durableReceipts: setupWizardDurableReceipts(context),
|
|
470
495
|
setupMarkerExists: markerItem?.status === 'ready' || setupCompletionMarkerExists(context),
|
|
471
496
|
repeatedBlockerAliases: SETUP_WIZARD_PLAN_BLOCKER_ALIASES,
|
|
472
497
|
});
|
|
@@ -13,7 +13,7 @@ export const AGENT_HARNESS_MODES = [
|
|
|
13
13
|
'execution_history', 'execution_history_item',
|
|
14
14
|
'file_recovery', 'run_file_recovery',
|
|
15
15
|
'personal_ops_briefing', 'personal_ops', 'personal_ops_queue', 'personal_ops_intake', 'personal_ops_lane', 'run_personal_ops_read',
|
|
16
|
-
'memory_posture', 'memory_provider',
|
|
16
|
+
'memory_posture', 'memory_provider', 'memory_refinement', 'run_memory_refinement',
|
|
17
17
|
'autonomy_intake', 'autonomy_queue', 'autonomy_queue_item',
|
|
18
18
|
'learning_curator', 'learning_candidate',
|
|
19
19
|
'research_briefing', 'research_workflow', 'research_runs', 'research_run',
|
|
@@ -242,6 +242,28 @@ export const AGENT_HARNESS_PARAMETER_PROPERTIES = {
|
|
|
242
242
|
type: 'string',
|
|
243
243
|
description: 'Selected Agent-local record id.',
|
|
244
244
|
},
|
|
245
|
+
knowledgeSpaceId: {
|
|
246
|
+
type: 'string',
|
|
247
|
+
description: 'Agent Knowledge space id for memory_refinement or run_memory_refinement.',
|
|
248
|
+
},
|
|
249
|
+
sourceIds: {
|
|
250
|
+
type: 'array',
|
|
251
|
+
items: { type: 'string' },
|
|
252
|
+
description: 'Agent Knowledge source ids for scoped semantic refinement.',
|
|
253
|
+
},
|
|
254
|
+
gapIds: {
|
|
255
|
+
type: 'array',
|
|
256
|
+
items: { type: 'string' },
|
|
257
|
+
description: 'Agent Knowledge semantic gap ids for scoped refinement.',
|
|
258
|
+
},
|
|
259
|
+
maxRunMs: {
|
|
260
|
+
type: 'number',
|
|
261
|
+
description: 'Maximum semantic refinement run budget in milliseconds.',
|
|
262
|
+
},
|
|
263
|
+
force: {
|
|
264
|
+
type: 'boolean',
|
|
265
|
+
description: 'Force semantic refinement reprocessing where supported.',
|
|
266
|
+
},
|
|
245
267
|
key: {
|
|
246
268
|
type: 'string',
|
|
247
269
|
description: 'Agent setting key.',
|
|
@@ -41,6 +41,11 @@ export interface AgentHarnessToolArgs {
|
|
|
41
41
|
readonly panelId?: unknown;
|
|
42
42
|
readonly actionId?: unknown;
|
|
43
43
|
readonly recordId?: unknown;
|
|
44
|
+
readonly knowledgeSpaceId?: unknown;
|
|
45
|
+
readonly sourceIds?: unknown;
|
|
46
|
+
readonly gapIds?: unknown;
|
|
47
|
+
readonly maxRunMs?: unknown;
|
|
48
|
+
readonly force?: unknown;
|
|
44
49
|
readonly fields?: unknown;
|
|
45
50
|
readonly combo?: unknown;
|
|
46
51
|
readonly combos?: unknown;
|
|
@@ -24,6 +24,7 @@ import { describeHarnessMcpServer, mcpServerCatalogStatus, mcpServerSummary } fr
|
|
|
24
24
|
import { describeHarnessModelRoute, modelRoutingCatalogStatus, modelRoutingSummary, runLocalModelServerSmoke } from './agent-harness-model-routing.ts';
|
|
25
25
|
import { describeHarnessModelTool, listHarnessModelTools } from './agent-harness-model-tool-catalog.ts';
|
|
26
26
|
import { describeMemoryProvider, memoryPostureCatalogStatus, memoryPostureSummary } from './agent-harness-memory-posture.ts';
|
|
27
|
+
import { memoryRefinementCatalogStatus, memoryRefinementSummary, runMemoryRefinement } from './agent-harness-memory-refinement.ts';
|
|
27
28
|
import { describeHarnessOperatorMethod, operatorMethodCatalogStatus, operatorMethodSummary } from './agent-harness-operator-methods.ts';
|
|
28
29
|
import { describePersonalOpsLane, personalOpsBriefingSummary, personalOpsCatalogStatus, personalOpsIntakeSummary, personalOpsQueueSummary, personalOpsSummary, runPersonalOpsRead } from './agent-harness-personal-ops.ts';
|
|
29
30
|
import { describeHarnessPairingRoute, pairingPostureCatalogStatus, pairingPostureSummary } from './agent-harness-pairing-posture.ts';
|
|
@@ -99,7 +100,7 @@ function detailedHarnessModelAccessGuide(): Record<string, string> {
|
|
|
99
100
|
executionHistory: 'Prefer execution action:"history|record" for activity cards and records; use returned verification, supervision, and recovery routes.',
|
|
100
101
|
fileRecovery: 'Prefer execution action:"recovery"; apply local file undo/redo snapshots with mode:"run_file_recovery" and confirmation.',
|
|
101
102
|
personalOps: 'Prefer personal_ops action:"briefing|status|queue|intake|lane|read"; lower-level modes personal_ops_briefing/personal_ops/personal_ops_queue/personal_ops_intake/personal_ops_lane/run_personal_ops_read remain available for harness inspection.',
|
|
102
|
-
memoryPosture: 'Prefer memory action:"status|provider|curator|candidate|list|search|get"; memory writes, vector rebuilds, and embedding-provider changes stay on confirmed existing routes.',
|
|
103
|
+
memoryPosture: 'Prefer memory action:"status|provider|refinement|run_refinement|curator|candidate|list|search|get"; run_refinement, memory writes, vector rebuilds, and embedding-provider changes stay on confirmed existing routes.',
|
|
103
104
|
autonomyQueue: 'Prefer autonomy action:"intake|queue|item" for ongoing work and visible autonomous work; lower-level autonomy_* modes remain available for detail. Effects stay confirmed on the owning route.',
|
|
104
105
|
learningCurator: 'Prefer memory action:"curator|candidate"; writes stay on reviewed Agent-local routes.',
|
|
105
106
|
researchWorkflow: 'Prefer research action:"briefing" for the current next-action queue, action:"plan" for deep-research route planning, action:"search" for bounded public source candidates, and action:"runner" for browser-runner readiness; lower-level mode:"research_workflow" sequences visible run, web/fetch or browser posture, source queue, report, and Knowledge promotion routes.',
|
|
@@ -176,6 +177,7 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
176
177
|
status: 'unavailable',
|
|
177
178
|
error: formatHarnessError(err),
|
|
178
179
|
}));
|
|
180
|
+
const memoryRefinement = memoryRefinementCatalogStatus(deps.commandContext);
|
|
179
181
|
const autonomyQueue = autonomyQueueCatalogStatus(deps.commandContext);
|
|
180
182
|
const learningCurator = learningCuratorCatalogStatus(deps.commandContext);
|
|
181
183
|
const researchBriefing = researchBriefingCatalogStatus(deps.commandContext);
|
|
@@ -232,6 +234,7 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
232
234
|
fileRecovery,
|
|
233
235
|
personalOps,
|
|
234
236
|
memoryPosture,
|
|
237
|
+
memoryRefinement,
|
|
235
238
|
autonomyQueue,
|
|
236
239
|
learningCurator,
|
|
237
240
|
researchBriefing,
|
|
@@ -483,6 +486,11 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
483
486
|
if (resolved.status === 'ambiguous') return error(`Ambiguous memory provider ${resolved.input}. Candidates: ${JSON.stringify(resolved.candidates)}`);
|
|
484
487
|
return error(resolved.usage);
|
|
485
488
|
}
|
|
489
|
+
if (args.mode === 'memory_refinement') return output(memoryRefinementSummary(deps.commandContext, args));
|
|
490
|
+
if (args.mode === 'run_memory_refinement') {
|
|
491
|
+
const confirmationError = requireConfirmedAction(args, 'Agent Knowledge semantic refinement');
|
|
492
|
+
return confirmationError ? error(confirmationError) : output(await runMemoryRefinement(deps.commandContext, args));
|
|
493
|
+
}
|
|
486
494
|
if (args.mode === 'autonomy_intake') return output(autonomyIntakeSummary(deps.commandContext, args));
|
|
487
495
|
if (args.mode === 'autonomy_queue') return output(autonomyQueueSummary(deps.commandContext, args));
|
|
488
496
|
if (args.mode === 'autonomy_queue_item') {
|
|
@@ -322,7 +322,7 @@ export function describeWorkspaceAction(
|
|
|
322
322
|
confirmation: 'required',
|
|
323
323
|
readinessRoute: 'agent_harness mode:"ui_surface" surfaceId:"connected-browser-cockpit" includeParameters:true',
|
|
324
324
|
fallback: 'Inspect host action:"service" endpointId:"web" or host action:"services" when the web cockpit is not enabled.',
|
|
325
|
-
note: 'Opens the connected-host browser/PWA cockpit through the configured web route; readiness inspection also reports workspace category coverage, mobile/PWA controls, and first-run receipt
|
|
325
|
+
note: 'Opens the connected-host browser/PWA cockpit through the configured web route; readiness inspection also reports certified workspace category coverage, mobile/PWA controls, and first-run receipt evidence without creating a separate Agent-hosted web app.',
|
|
326
326
|
},
|
|
327
327
|
} : {}),
|
|
328
328
|
...(action.kind === 'local-selection' || action.kind === 'local-operation' ? {
|
|
@@ -6,6 +6,8 @@ import { createAgentHarnessTool } from './agent-harness-tool.ts';
|
|
|
6
6
|
type AgentMemoryAction =
|
|
7
7
|
| 'status'
|
|
8
8
|
| 'provider'
|
|
9
|
+
| 'refinement'
|
|
10
|
+
| 'run_refinement'
|
|
9
11
|
| 'curator'
|
|
10
12
|
| 'candidate'
|
|
11
13
|
| 'list'
|
|
@@ -24,6 +26,9 @@ interface AgentMemoryToolArgs {
|
|
|
24
26
|
readonly recordId?: unknown;
|
|
25
27
|
readonly providerId?: unknown;
|
|
26
28
|
readonly candidateId?: unknown;
|
|
29
|
+
readonly knowledgeSpaceId?: unknown;
|
|
30
|
+
readonly sourceIds?: unknown;
|
|
31
|
+
readonly gapIds?: unknown;
|
|
27
32
|
readonly target?: unknown;
|
|
28
33
|
readonly query?: unknown;
|
|
29
34
|
readonly includeParameters?: unknown;
|
|
@@ -36,6 +41,8 @@ interface AgentMemoryToolArgs {
|
|
|
36
41
|
readonly confidence?: unknown;
|
|
37
42
|
readonly tags?: unknown;
|
|
38
43
|
readonly reason?: unknown;
|
|
44
|
+
readonly maxRunMs?: unknown;
|
|
45
|
+
readonly force?: unknown;
|
|
39
46
|
readonly confirm?: unknown;
|
|
40
47
|
readonly explicitUserRequest?: unknown;
|
|
41
48
|
}
|
|
@@ -61,6 +68,8 @@ function normalizeMemoryAction(value: unknown): AgentMemoryAction | null {
|
|
|
61
68
|
if (!action) return null;
|
|
62
69
|
if (action === 'status' || action === 'summary' || action === 'posture' || action === 'memory_posture' || action === 'recall' || action === 'providers') return 'status';
|
|
63
70
|
if (action === 'provider' || action === 'memory_provider' || action === 'embedding' || action === 'external' || action === 'external_provider') return 'provider';
|
|
71
|
+
if (action === 'refinement' || action === 'refinement_tasks' || action === 'semantic_refinement' || action === 'self_improvement' || action === 'semantic_self_improvement' || action === 'learning_loop') return 'refinement';
|
|
72
|
+
if (action === 'run_refinement' || action === 'refine' || action === 'run_semantic_refinement' || action === 'run_self_improvement' || action === 'self_improve') return 'run_refinement';
|
|
64
73
|
if (action === 'curator' || action === 'learning' || action === 'learning_curator' || action === 'queue' || action === 'review_queue' || action === 'plan') return 'curator';
|
|
65
74
|
if (action === 'candidate' || action === 'learning_candidate' || action === 'card' || action === 'inspect_candidate') return 'candidate';
|
|
66
75
|
if (action === 'list' || action === 'records' || action === 'memories') return 'list';
|
|
@@ -131,7 +140,7 @@ export function createAgentMemoryTool(deps: AgentMemoryToolDeps): Tool {
|
|
|
131
140
|
properties: {
|
|
132
141
|
action: {
|
|
133
142
|
type: 'string',
|
|
134
|
-
enum: ['status', 'provider', 'curator', 'candidate', 'list', 'search', 'get', 'create', 'update', 'review', 'stale', 'delete'],
|
|
143
|
+
enum: ['status', 'provider', 'refinement', 'run_refinement', 'curator', 'candidate', 'list', 'search', 'get', 'create', 'update', 'review', 'stale', 'delete'],
|
|
135
144
|
description: 'Read memory posture/providers/curator or operate records.',
|
|
136
145
|
},
|
|
137
146
|
mode: { type: 'string', description: 'Alias for action.' },
|
|
@@ -139,6 +148,9 @@ export function createAgentMemoryTool(deps: AgentMemoryToolDeps): Tool {
|
|
|
139
148
|
recordId: { type: 'string', description: 'Alias for id.' },
|
|
140
149
|
providerId: { type: 'string', description: 'Embedding or external-memory provider id.' },
|
|
141
150
|
candidateId: { type: 'string', description: 'Learning curator candidate id.' },
|
|
151
|
+
knowledgeSpaceId: { type: 'string', description: 'Agent Knowledge space id for semantic refinement.' },
|
|
152
|
+
sourceIds: { type: 'array', items: { type: 'string' }, description: 'Agent Knowledge source ids for scoped semantic refinement.' },
|
|
153
|
+
gapIds: { type: 'array', items: { type: 'string' }, description: 'Agent Knowledge semantic gap ids for scoped refinement.' },
|
|
142
154
|
target: { type: 'string', description: 'Lookup target or search text.' },
|
|
143
155
|
query: { type: 'string', description: 'Search text.' },
|
|
144
156
|
includeParameters: { type: 'boolean', description: 'Include provider setup contracts or candidate details.' },
|
|
@@ -151,6 +163,8 @@ export function createAgentMemoryTool(deps: AgentMemoryToolDeps): Tool {
|
|
|
151
163
|
confidence: { type: 'number', description: 'Review confidence, 0-100.' },
|
|
152
164
|
tags: { type: 'array', items: { type: 'string' }, description: 'Memory tags.' },
|
|
153
165
|
reason: { type: 'string', description: 'Reason for stale/delete decisions.' },
|
|
166
|
+
maxRunMs: { type: 'number', description: 'Maximum semantic refinement run budget in milliseconds.' },
|
|
167
|
+
force: { type: 'boolean', description: 'Force semantic refinement reprocessing where supported.' },
|
|
154
168
|
confirm: { type: 'boolean', description: 'Required for deletion and other confirmed memory effects.' },
|
|
155
169
|
explicitUserRequest: { type: 'string', description: 'User request authorizing confirmed memory effects.' },
|
|
156
170
|
},
|
|
@@ -180,6 +194,31 @@ export function createAgentMemoryTool(deps: AgentMemoryToolDeps): Tool {
|
|
|
180
194
|
includeParameters: args.includeParameters,
|
|
181
195
|
}));
|
|
182
196
|
}
|
|
197
|
+
if (action === 'refinement') {
|
|
198
|
+
return harnessTool.execute(compactArgs({
|
|
199
|
+
mode: 'memory_refinement',
|
|
200
|
+
target: args.target,
|
|
201
|
+
query: args.query,
|
|
202
|
+
knowledgeSpaceId: args.knowledgeSpaceId,
|
|
203
|
+
sourceIds: args.sourceIds,
|
|
204
|
+
gapIds: args.gapIds,
|
|
205
|
+
limit: args.limit,
|
|
206
|
+
includeParameters: args.includeParameters,
|
|
207
|
+
}));
|
|
208
|
+
}
|
|
209
|
+
if (action === 'run_refinement') {
|
|
210
|
+
return harnessTool.execute(compactArgs({
|
|
211
|
+
mode: 'run_memory_refinement',
|
|
212
|
+
knowledgeSpaceId: args.knowledgeSpaceId,
|
|
213
|
+
sourceIds: args.sourceIds,
|
|
214
|
+
gapIds: args.gapIds,
|
|
215
|
+
limit: args.limit,
|
|
216
|
+
maxRunMs: args.maxRunMs,
|
|
217
|
+
force: args.force,
|
|
218
|
+
confirm: args.confirm,
|
|
219
|
+
explicitUserRequest: args.explicitUserRequest,
|
|
220
|
+
}));
|
|
221
|
+
}
|
|
183
222
|
if (action === 'curator') {
|
|
184
223
|
return harnessTool.execute(compactArgs({
|
|
185
224
|
mode: 'learning_curator',
|
|
@@ -461,6 +461,18 @@ export function toArtifactCandidate(candidate: CompareCandidateResult): Record<s
|
|
|
461
461
|
};
|
|
462
462
|
}
|
|
463
463
|
|
|
464
|
+
export function toArtifactCandidateLatencyMetadata(candidate: CompareCandidateResult): Record<string, unknown> {
|
|
465
|
+
return {
|
|
466
|
+
blindId: candidate.blindId,
|
|
467
|
+
status: candidate.status,
|
|
468
|
+
latencyMs: candidate.latencyMs,
|
|
469
|
+
registryKey: candidate.model.registryKey,
|
|
470
|
+
providerId: candidate.model.providerId,
|
|
471
|
+
modelId: candidate.model.modelId,
|
|
472
|
+
displayName: candidate.model.displayName,
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
|
|
464
476
|
export function comparisonArtifactText(input: {
|
|
465
477
|
readonly comparison: StoredComparison;
|
|
466
478
|
readonly prompt: string;
|
|
@@ -580,6 +592,7 @@ export async function saveComparisonArtifact(input: {
|
|
|
580
592
|
...(input.comparison.documentId ? { documentId: input.comparison.documentId } : {}),
|
|
581
593
|
candidateCount: input.comparison.candidates.length,
|
|
582
594
|
completedCandidates: input.comparison.candidates.filter((candidate) => candidate.status === 'completed').length,
|
|
595
|
+
candidateLatencyEvidence: input.comparison.candidates.map(toArtifactCandidateLatencyMetadata),
|
|
583
596
|
...(input.benchmarkKind ? { benchmarkKind: input.benchmarkKind } : {}),
|
|
584
597
|
...(input.comparison.taskType ? { taskType: input.comparison.taskType } : {}),
|
|
585
598
|
revealStored: true,
|