@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
|
@@ -3,6 +3,7 @@ export type AgentSetupWizardStatus = 'complete' | 'active' | 'blocked';
|
|
|
3
3
|
export type AgentSetupWizardStepStatus = 'done' | 'current' | 'pending' | 'blocked';
|
|
4
4
|
export type AgentSetupWizardCheckpointStatus = 'available' | 'none' | 'stale' | 'unavailable';
|
|
5
5
|
export type AgentSetupWizardCloseoutStatus = 'complete' | 'ready-to-finish' | 'needs-smoke-evidence' | 'blocked';
|
|
6
|
+
export type AgentSetupWizardReceiptSchemaStatus = 'certified' | 'legacy';
|
|
6
7
|
|
|
7
8
|
export interface AgentSetupWizardSourceItem {
|
|
8
9
|
readonly id: string;
|
|
@@ -25,6 +26,8 @@ export interface AgentSetupWizardSmokeHistory {
|
|
|
25
26
|
readonly trend: string;
|
|
26
27
|
readonly latestResult: string | null;
|
|
27
28
|
readonly previousResult: string | null;
|
|
29
|
+
readonly latestEvidenceId?: string | null;
|
|
30
|
+
readonly latestEvidenceAt?: string | null;
|
|
28
31
|
readonly resultCounts: Readonly<Record<string, number>>;
|
|
29
32
|
readonly blockedCheckFrequency: readonly AgentSetupWizardBlockedCheckFrequency[];
|
|
30
33
|
readonly inspectLatestRoute: string | null;
|
|
@@ -33,6 +36,26 @@ export interface AgentSetupWizardSmokeHistory {
|
|
|
33
36
|
readonly reason?: string;
|
|
34
37
|
}
|
|
35
38
|
|
|
39
|
+
export type AgentSetupWizardDurableReceiptStatus = 'ready' | 'blocked' | 'failed' | 'unknown';
|
|
40
|
+
|
|
41
|
+
export interface AgentSetupWizardDurableReceipt {
|
|
42
|
+
readonly stepId: string;
|
|
43
|
+
readonly stepLabel?: string;
|
|
44
|
+
readonly status: AgentSetupWizardDurableReceiptStatus;
|
|
45
|
+
readonly receiptId: string;
|
|
46
|
+
readonly recordedAt: string;
|
|
47
|
+
readonly summary: string;
|
|
48
|
+
readonly inspectRoute: string | null;
|
|
49
|
+
readonly source?: string;
|
|
50
|
+
readonly schemaStatus?: AgentSetupWizardReceiptSchemaStatus;
|
|
51
|
+
readonly schemaVersion?: string;
|
|
52
|
+
readonly provenance?: readonly string[];
|
|
53
|
+
readonly publicationGuarantee?: string;
|
|
54
|
+
readonly eventCursor?: string;
|
|
55
|
+
readonly eventSequence?: number;
|
|
56
|
+
readonly publisher?: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
36
59
|
export interface AgentSetupWizardRepeatedBlocker {
|
|
37
60
|
readonly setupItemId: string;
|
|
38
61
|
readonly checkId: string;
|
|
@@ -52,6 +75,36 @@ export interface AgentSetupWizardStep {
|
|
|
52
75
|
readonly backtrackRoute: string | null;
|
|
53
76
|
}
|
|
54
77
|
|
|
78
|
+
export type AgentSetupWizardStepHistoryKind = 'checkpoint' | 'setup-smoke' | 'durable-receipt';
|
|
79
|
+
|
|
80
|
+
export interface AgentSetupWizardStepHistoryEntry {
|
|
81
|
+
readonly id: string;
|
|
82
|
+
readonly stepId: string;
|
|
83
|
+
readonly stepLabel: string;
|
|
84
|
+
readonly kind: AgentSetupWizardStepHistoryKind;
|
|
85
|
+
readonly receiptId: string;
|
|
86
|
+
readonly recordedAt: string;
|
|
87
|
+
readonly summary: string;
|
|
88
|
+
readonly inspectRoute: string | null;
|
|
89
|
+
readonly source?: string;
|
|
90
|
+
readonly receiptStatus?: string;
|
|
91
|
+
readonly satisfiesReceipt?: boolean;
|
|
92
|
+
readonly schemaStatus?: AgentSetupWizardReceiptSchemaStatus;
|
|
93
|
+
readonly schemaVersion?: string;
|
|
94
|
+
readonly provenance?: readonly string[];
|
|
95
|
+
readonly publicationGuarantee?: string;
|
|
96
|
+
readonly eventCursor?: string;
|
|
97
|
+
readonly eventSequence?: number;
|
|
98
|
+
readonly publisher?: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface AgentSetupWizardReceiptGap {
|
|
102
|
+
readonly stepId: string;
|
|
103
|
+
readonly stepLabel: string;
|
|
104
|
+
readonly requiredReceipt: string;
|
|
105
|
+
readonly summary: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
55
108
|
export interface AgentSetupWizardCloseout {
|
|
56
109
|
readonly status: AgentSetupWizardCloseoutStatus;
|
|
57
110
|
readonly label: string;
|
|
@@ -107,6 +160,8 @@ export interface AgentSetupWizard {
|
|
|
107
160
|
readonly reviewRoute: string;
|
|
108
161
|
readonly repeatedBlocker: AgentSetupWizardRepeatedBlocker | null;
|
|
109
162
|
readonly smokeHistory: AgentSetupWizardSmokeHistory;
|
|
163
|
+
readonly stepHistory: readonly AgentSetupWizardStepHistoryEntry[];
|
|
164
|
+
readonly receiptGaps: readonly AgentSetupWizardReceiptGap[];
|
|
110
165
|
readonly closeout: AgentSetupWizardCloseout;
|
|
111
166
|
readonly checkpoint: AgentSetupWizardCheckpoint;
|
|
112
167
|
readonly steps: readonly AgentSetupWizardStep[];
|
|
@@ -120,6 +175,8 @@ export interface BuildAgentSetupWizardInput {
|
|
|
120
175
|
readonly setupMarkerExists?: boolean;
|
|
121
176
|
readonly finishRoute?: string;
|
|
122
177
|
readonly finishUserRoute?: string;
|
|
178
|
+
readonly receiptRequiredStepIds?: readonly string[];
|
|
179
|
+
readonly durableReceipts?: readonly AgentSetupWizardDurableReceipt[];
|
|
123
180
|
readonly repeatedBlockerAliases?: Readonly<Record<string, readonly string[]>>;
|
|
124
181
|
readonly reviewRoute?: string;
|
|
125
182
|
}
|
|
@@ -305,9 +362,168 @@ function buildStep(item: AgentSetupWizardSourceItem, currentId: string | null):
|
|
|
305
362
|
};
|
|
306
363
|
}
|
|
307
364
|
|
|
365
|
+
function validIso(value: string | null | undefined): string | null {
|
|
366
|
+
if (!value || Number.isNaN(Date.parse(value))) return null;
|
|
367
|
+
return new Date(value).toISOString();
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function setupReceiptKind(stepId: string): string {
|
|
371
|
+
if (stepId === 'runtime' || stepId === 'connected-host-readiness') return 'connected-host service status receipt';
|
|
372
|
+
if (stepId === 'connected-host-auth') return 'connected-host auth receipt';
|
|
373
|
+
if (stepId === 'install-smoke') return 'setup smoke evidence receipt';
|
|
374
|
+
if (stepId === 'browser-pwa') return 'connected-host browser/PWA first-run receipt';
|
|
375
|
+
return 'durable setup receipt';
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function setupStepAliases(stepId: string): readonly string[] {
|
|
379
|
+
if (stepId === 'runtime' || stepId === 'connected-host-readiness') return ['runtime', 'connected-host-readiness'];
|
|
380
|
+
return [stepId];
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function setupStepMatches(left: string, right: string): boolean {
|
|
384
|
+
const leftAliases = new Set(setupStepAliases(left));
|
|
385
|
+
return setupStepAliases(right).some((alias) => leftAliases.has(alias));
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function durableReceiptSatisfies(receipt: AgentSetupWizardDurableReceipt): boolean {
|
|
389
|
+
return receipt.status === 'ready' && Boolean(validIso(receipt.recordedAt)) && receipt.receiptId.trim().length > 0;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
export function setupStepHasSatisfyingReceipt(
|
|
393
|
+
receipts: readonly AgentSetupWizardDurableReceipt[],
|
|
394
|
+
stepId: string,
|
|
395
|
+
): boolean {
|
|
396
|
+
return receipts.some((receipt) => durableReceiptSatisfies(receipt) && setupStepMatches(stepId, receipt.stepId));
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function latestSatisfyingReceipt(
|
|
400
|
+
receipts: readonly AgentSetupWizardDurableReceipt[],
|
|
401
|
+
stepId: string,
|
|
402
|
+
): AgentSetupWizardDurableReceipt | null {
|
|
403
|
+
return receipts
|
|
404
|
+
.filter((receipt) => durableReceiptSatisfies(receipt) && setupStepMatches(stepId, receipt.stepId))
|
|
405
|
+
.sort((left, right) => Date.parse(right.recordedAt) - Date.parse(left.recordedAt) || left.receiptId.localeCompare(right.receiptId))[0] ?? null;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function applyDurableReceiptStatus(
|
|
409
|
+
items: readonly AgentSetupWizardSourceItem[],
|
|
410
|
+
receipts: readonly AgentSetupWizardDurableReceipt[],
|
|
411
|
+
): readonly AgentSetupWizardSourceItem[] {
|
|
412
|
+
if (receipts.length === 0) return items;
|
|
413
|
+
return items.map((item) => {
|
|
414
|
+
const receipt = latestSatisfyingReceipt(receipts, item.id);
|
|
415
|
+
if (!receipt) return item;
|
|
416
|
+
return {
|
|
417
|
+
...item,
|
|
418
|
+
status: 'ready',
|
|
419
|
+
detail: `${item.detail} Durable receipt ${receipt.receiptId}: ${receipt.summary}`,
|
|
420
|
+
};
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function buildStepHistory(input: {
|
|
425
|
+
readonly items: readonly AgentSetupWizardSourceItem[];
|
|
426
|
+
readonly smokeHistory: AgentSetupWizardSmokeHistory;
|
|
427
|
+
readonly checkpoint: AgentSetupWizardCheckpoint;
|
|
428
|
+
readonly durableReceipts: readonly AgentSetupWizardDurableReceipt[];
|
|
429
|
+
}): readonly AgentSetupWizardStepHistoryEntry[] {
|
|
430
|
+
const byId = new Map(input.items.map((item) => [item.id, item]));
|
|
431
|
+
const history: AgentSetupWizardStepHistoryEntry[] = [];
|
|
432
|
+
|
|
433
|
+
const checkpointAt = validIso(input.checkpoint.savedAt);
|
|
434
|
+
if (input.checkpoint.status === 'available' && input.checkpoint.currentStepId && checkpointAt) {
|
|
435
|
+
const item = byId.get(input.checkpoint.currentStepId);
|
|
436
|
+
const stepLabel = item?.label ?? input.checkpoint.currentStepLabel ?? input.checkpoint.currentStepId;
|
|
437
|
+
const receiptId = `setup-wizard-checkpoint:${input.checkpoint.currentStepId}:${checkpointAt}`;
|
|
438
|
+
history.push({
|
|
439
|
+
id: `setup-step-history:${input.checkpoint.currentStepId}:checkpoint:${checkpointAt}`,
|
|
440
|
+
stepId: input.checkpoint.currentStepId,
|
|
441
|
+
stepLabel,
|
|
442
|
+
kind: 'checkpoint',
|
|
443
|
+
receiptId,
|
|
444
|
+
recordedAt: checkpointAt,
|
|
445
|
+
summary: `Saved checkpoint for ${stepLabel}.`,
|
|
446
|
+
inspectRoute: input.checkpoint.inspectRoute,
|
|
447
|
+
source: input.checkpoint.source ?? undefined,
|
|
448
|
+
satisfiesReceipt: false,
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const smokeAt = validIso(input.smokeHistory.latestEvidenceAt);
|
|
453
|
+
if (input.smokeHistory.latestEvidenceId && smokeAt) {
|
|
454
|
+
const item = byId.get('install-smoke');
|
|
455
|
+
const result = input.smokeHistory.latestResult ?? 'unknown';
|
|
456
|
+
const ready = result === 'ready-for-user-run';
|
|
457
|
+
history.push({
|
|
458
|
+
id: `setup-step-history:install-smoke:setup-smoke:${input.smokeHistory.latestEvidenceId}`,
|
|
459
|
+
stepId: 'install-smoke',
|
|
460
|
+
stepLabel: item?.label ?? 'Install smoke',
|
|
461
|
+
kind: 'setup-smoke',
|
|
462
|
+
receiptId: input.smokeHistory.latestEvidenceId,
|
|
463
|
+
recordedAt: smokeAt,
|
|
464
|
+
summary: `Latest setup smoke evidence is ${result}.`,
|
|
465
|
+
inspectRoute: input.smokeHistory.inspectLatestRoute,
|
|
466
|
+
source: 'agent-setup-smoke-evidence',
|
|
467
|
+
receiptStatus: result,
|
|
468
|
+
satisfiesReceipt: ready,
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
for (const receipt of input.durableReceipts) {
|
|
473
|
+
const recordedAt = validIso(receipt.recordedAt);
|
|
474
|
+
if (!recordedAt || receipt.receiptId.trim().length === 0) continue;
|
|
475
|
+
const item = input.items.find((candidate) => setupStepMatches(candidate.id, receipt.stepId));
|
|
476
|
+
const stepLabel = receipt.stepLabel ?? item?.label ?? receipt.stepId;
|
|
477
|
+
history.push({
|
|
478
|
+
id: `setup-step-history:${receipt.stepId}:durable-receipt:${receipt.receiptId}`,
|
|
479
|
+
stepId: receipt.stepId,
|
|
480
|
+
stepLabel,
|
|
481
|
+
kind: 'durable-receipt',
|
|
482
|
+
receiptId: receipt.receiptId,
|
|
483
|
+
recordedAt,
|
|
484
|
+
summary: receipt.summary,
|
|
485
|
+
inspectRoute: receipt.inspectRoute,
|
|
486
|
+
source: receipt.source,
|
|
487
|
+
receiptStatus: receipt.status,
|
|
488
|
+
satisfiesReceipt: durableReceiptSatisfies(receipt),
|
|
489
|
+
schemaStatus: receipt.schemaStatus,
|
|
490
|
+
schemaVersion: receipt.schemaVersion,
|
|
491
|
+
provenance: receipt.provenance,
|
|
492
|
+
publicationGuarantee: receipt.publicationGuarantee,
|
|
493
|
+
eventCursor: receipt.eventCursor,
|
|
494
|
+
eventSequence: receipt.eventSequence,
|
|
495
|
+
publisher: receipt.publisher,
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
return history.sort((left, right) => Date.parse(right.recordedAt) - Date.parse(left.recordedAt) || left.id.localeCompare(right.id));
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
function buildReceiptGaps(input: {
|
|
503
|
+
readonly items: readonly AgentSetupWizardSourceItem[];
|
|
504
|
+
readonly stepHistory: readonly AgentSetupWizardStepHistoryEntry[];
|
|
505
|
+
readonly receiptRequiredStepIds: readonly string[];
|
|
506
|
+
}): readonly AgentSetupWizardReceiptGap[] {
|
|
507
|
+
return input.receiptRequiredStepIds
|
|
508
|
+
.filter((stepId) => !input.stepHistory.some((entry) => entry.satisfiesReceipt === true && setupStepMatches(stepId, entry.stepId)))
|
|
509
|
+
.map((stepId) => {
|
|
510
|
+
const item = input.items.find((candidate) => candidate.id === stepId);
|
|
511
|
+
const stepLabel = item?.label ?? stepId;
|
|
512
|
+
const requiredReceipt = setupReceiptKind(stepId);
|
|
513
|
+
return {
|
|
514
|
+
stepId,
|
|
515
|
+
stepLabel,
|
|
516
|
+
requiredReceipt,
|
|
517
|
+
summary: `${stepLabel} still needs a stable ${requiredReceipt} id and timestamp before release closeout can count it as durable setup evidence.`,
|
|
518
|
+
};
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
|
|
308
522
|
function buildCloseout(input: {
|
|
309
523
|
readonly items: readonly AgentSetupWizardSourceItem[];
|
|
310
524
|
readonly smokeHistory: AgentSetupWizardSmokeHistory;
|
|
525
|
+
readonly setupSmokeReceiptReady: boolean;
|
|
526
|
+
readonly stepHistory: readonly AgentSetupWizardStepHistoryEntry[];
|
|
311
527
|
readonly criticalStepIds: readonly string[];
|
|
312
528
|
readonly setupMarkerExists: boolean;
|
|
313
529
|
readonly reviewRoute: string;
|
|
@@ -318,14 +534,21 @@ function buildCloseout(input: {
|
|
|
318
534
|
const primaryBlocker = input.items.find((item) => (
|
|
319
535
|
critical.has(item.id) && item.status === 'blocked'
|
|
320
536
|
)) ?? null;
|
|
321
|
-
const smokeReady = input.
|
|
537
|
+
const smokeReady = input.setupSmokeReceiptReady
|
|
538
|
+
|| (input.smokeHistory.status === 'available' && input.smokeHistory.latestResult === 'ready-for-user-run');
|
|
322
539
|
const latestSmoke = input.smokeHistory.status === 'available'
|
|
323
540
|
? input.smokeHistory.latestResult ?? 'unknown'
|
|
324
|
-
: input.smokeHistory.status;
|
|
541
|
+
: input.setupSmokeReceiptReady ? 'durable receipt ready' : input.smokeHistory.status;
|
|
542
|
+
const satisfyingSetupReceipts = input.stepHistory.filter((entry) => entry.kind === 'durable-receipt' && entry.satisfiesReceipt === true);
|
|
543
|
+
const certifiedSetupReceipts = satisfyingSetupReceipts.filter((entry) => entry.schemaStatus === 'certified');
|
|
544
|
+
const eventStreamSetupReceipts = satisfyingSetupReceipts.filter((entry) => entry.eventCursor);
|
|
325
545
|
const evidence = [
|
|
326
546
|
`critical setup blockers: ${primaryBlocker ? `${primaryBlocker.label} (${primaryBlocker.status})` : 'none'}`,
|
|
327
547
|
`setup marker: ${input.setupMarkerExists ? 'present' : 'missing'}`,
|
|
328
548
|
`latest setup smoke: ${latestSmoke}`,
|
|
549
|
+
`setup smoke receipt: ${input.setupSmokeReceiptReady ? 'ready' : 'missing'}`,
|
|
550
|
+
`certified setup receipts: ${certifiedSetupReceipts.length}/${satisfyingSetupReceipts.length}`,
|
|
551
|
+
`setup receipt event streams: ${eventStreamSetupReceipts.length}`,
|
|
329
552
|
`setup smoke history: ${input.smokeHistory.status}; total ${input.smokeHistory.total}; trend ${input.smokeHistory.trend}`,
|
|
330
553
|
];
|
|
331
554
|
const policy = 'Setup closeout is advisory until a confirmed finish route writes the local onboarding marker. Optional setup recommendations do not block closeout, but unresolved critical blockers or missing ready setup smoke evidence do.';
|
|
@@ -401,14 +624,23 @@ function buildCloseout(input: {
|
|
|
401
624
|
export function buildAgentSetupWizard(input: BuildAgentSetupWizardInput): AgentSetupWizard {
|
|
402
625
|
const smokeHistory = input.smokeHistory ?? emptyAgentSetupSmokeHistory();
|
|
403
626
|
const inputCheckpoint = input.checkpoint ?? emptyAgentSetupWizardCheckpoint();
|
|
404
|
-
const
|
|
405
|
-
const
|
|
406
|
-
const
|
|
627
|
+
const durableReceipts = input.durableReceipts ?? [];
|
|
628
|
+
const items = applyDurableReceiptStatus(input.items, durableReceipts);
|
|
629
|
+
const repeated = itemFromRepeatedBlockers(items, smokeHistory, input.repeatedBlockerAliases ?? {});
|
|
630
|
+
const blocking = firstBlockingItem(items);
|
|
631
|
+
const rawCheckpointItem = itemFromCheckpoint(items, inputCheckpoint);
|
|
407
632
|
const checkpointItem = blocking && rawCheckpointItem?.id !== blocking.id ? null : rawCheckpointItem;
|
|
408
|
-
const checkpoint = buildCheckpoint(inputCheckpoint,
|
|
409
|
-
const current = repeated?.item ?? blocking ?? checkpointItem ?? firstAttentionItem(
|
|
633
|
+
const checkpoint = buildCheckpoint(inputCheckpoint, items, checkpointItem, blocking);
|
|
634
|
+
const current = repeated?.item ?? blocking ?? checkpointItem ?? firstAttentionItem(items);
|
|
410
635
|
const currentId = current?.id ?? null;
|
|
411
|
-
const steps =
|
|
636
|
+
const steps = items.map((item) => buildStep(item, currentId));
|
|
637
|
+
const stepHistory = buildStepHistory({ items, smokeHistory, checkpoint, durableReceipts });
|
|
638
|
+
const setupSmokeReceiptReady = stepHistory.some((entry) => entry.satisfiesReceipt === true && setupStepMatches('install-smoke', entry.stepId));
|
|
639
|
+
const receiptGaps = buildReceiptGaps({
|
|
640
|
+
items,
|
|
641
|
+
stepHistory,
|
|
642
|
+
receiptRequiredStepIds: input.receiptRequiredStepIds ?? [],
|
|
643
|
+
});
|
|
412
644
|
const completedSteps = steps.filter((step) => step.status === 'done').length;
|
|
413
645
|
const status: AgentSetupWizardStatus = completedSteps === steps.length
|
|
414
646
|
? 'complete'
|
|
@@ -432,9 +664,13 @@ export function buildAgentSetupWizard(input: BuildAgentSetupWizardInput): AgentS
|
|
|
432
664
|
reviewRoute: input.reviewRoute ?? DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE,
|
|
433
665
|
repeatedBlocker: repeated?.blocker ?? null,
|
|
434
666
|
smokeHistory,
|
|
667
|
+
stepHistory,
|
|
668
|
+
receiptGaps,
|
|
435
669
|
closeout: buildCloseout({
|
|
436
|
-
items
|
|
670
|
+
items,
|
|
437
671
|
smokeHistory,
|
|
672
|
+
setupSmokeReceiptReady,
|
|
673
|
+
stepHistory,
|
|
438
674
|
criticalStepIds: input.closeoutCriticalStepIds ?? [],
|
|
439
675
|
setupMarkerExists: input.setupMarkerExists === true,
|
|
440
676
|
reviewRoute: input.reviewRoute ?? DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE,
|
|
@@ -455,8 +455,8 @@ export const AGENT_WORKSPACE_CATEGORIES: readonly AgentWorkspaceCategory[] = [
|
|
|
455
455
|
detail: 'Voice, media, browser tools, and image-capable flows are first-class Agent tools. Connected-host administration stays outside Agent and side effects stay explicit.',
|
|
456
456
|
actions: [
|
|
457
457
|
{ id: 'voice-workflow-posture', label: 'Voice workflows', detail: 'Inspect push-to-talk, voice memo transcription, spoken responses, and wake-word readiness with device action:"voice".', kind: 'guidance', safety: 'read-only' },
|
|
458
|
-
{ id: 'device-capability-map', label: 'Device capability map', detail: 'Inspect pairing, mobile command routing, browser/PWA, notifications, browser/desktop control, and camera/location readiness with device action:"status" without claiming
|
|
459
|
-
{ id: 'browser-cockpit-readiness', label: 'Browser/PWA readiness', detail: 'Inspect the connected browser cockpit/PWA route, workspace category coverage, mobile controls, and first-run receipt
|
|
458
|
+
{ id: 'device-capability-map', label: 'Device capability map', detail: 'Inspect pairing, mobile command routing, browser/PWA, notifications, browser/desktop control, and certified camera/location readiness with device action:"status" without claiming uncertified contracts.', kind: 'guidance', safety: 'read-only' },
|
|
459
|
+
{ id: 'browser-cockpit-readiness', label: 'Browser/PWA readiness', detail: 'Inspect the connected browser cockpit/PWA route, certified workspace category coverage, mobile controls, and first-run receipt evidence with computer action:"browser" before opening a browser.', kind: 'guidance', safety: 'read-only' },
|
|
460
460
|
{ id: 'tts-config', label: 'Configure live TTS', detail: 'Open the settings workspace at the TTS group.', command: '/config tts', kind: 'command', safety: 'safe' },
|
|
461
461
|
{ id: 'tts-provider', label: 'Choose TTS provider', detail: 'Open provider/model routing for spoken responses through the settings flow.', command: '/config tts.provider', kind: 'command', safety: 'safe' },
|
|
462
462
|
{ id: 'voice-review', label: 'Voice review', detail: 'Inspect local voice posture before enabling spoken interaction.', command: '/voice review', kind: 'command', safety: 'read-only' },
|
|
@@ -103,10 +103,10 @@ export const AGENT_WORKSPACE_ONBOARDING_DETAIL_CATEGORIES: readonly AgentWorkspa
|
|
|
103
103
|
summary: 'Create/import memory, personas, skills, routines, notes, and Knowledge.',
|
|
104
104
|
detail: 'Use this page to seed the assistant with durable local context. These forms create Agent-owned records or ingest reviewed sources.',
|
|
105
105
|
actions: [
|
|
106
|
-
{ id: 'context-vibe-status', label: 'Inspect VIBE.md', detail: 'Show project/global VIBE.md personality files, blocked files, and init paths before relying on a custom assistant feel.',
|
|
107
|
-
{ id: 'context-project-files', label: 'Inspect project context', detail: 'List secret-scanned .hermes.md, HERMES.md, AGENTS.md, CLAUDE.md, SOUL.md, and Cursor context files with blocked/truncated status.',
|
|
108
|
-
{ id: 'context-project-file', label: 'Inspect one context file', detail: 'Inspect one loaded or blocked project context file by id, target, or query through the read-only context-file
|
|
109
|
-
{ id: 'context-prompt-context', label: 'Prompt context', detail: 'Inspect the applied prompt context order, selected memory/persona/skill/routine records, suppressed context, and approximate token budget.',
|
|
106
|
+
{ id: 'context-vibe-status', label: 'Inspect VIBE.md', detail: 'Show project/global VIBE.md personality files, blocked files, and init paths before relying on a custom assistant feel.', kind: 'guidance', safety: 'read-only' },
|
|
107
|
+
{ id: 'context-project-files', label: 'Inspect project context', detail: 'List secret-scanned .hermes.md, HERMES.md, AGENTS.md, CLAUDE.md, SOUL.md, and Cursor context files with blocked/truncated status.', kind: 'guidance', safety: 'read-only' },
|
|
108
|
+
{ id: 'context-project-file', label: 'Inspect one context file', detail: 'Inspect one loaded or blocked project context file by id, target, or query through the read-only context-file control.', kind: 'guidance', safety: 'read-only' },
|
|
109
|
+
{ id: 'context-prompt-context', label: 'Prompt context', detail: 'Inspect the applied prompt context order, selected memory/persona/skill/routine records, suppressed context, and approximate token budget.', kind: 'guidance', safety: 'read-only' },
|
|
110
110
|
{ id: 'context-profile-from-discovered', label: 'Profile from discovered files', detail: 'Create an isolated Agent profile from reviewed local persona, skill, and routine files.', editorKind: 'profile-from-discovered', kind: 'editor', safety: 'safe' },
|
|
111
111
|
{ id: 'context-persona-discovery', label: 'Import persona files', detail: 'Import discovered persona files into the Agent persona registry.', editorKind: 'persona-discovery-import', kind: 'editor', safety: 'safe' },
|
|
112
112
|
{ id: 'context-skill-discovery', label: 'Import skill files', detail: 'Import discovered skill files into the Agent skill registry.', editorKind: 'skill-discovery-import', kind: 'editor', safety: 'safe' },
|
|
@@ -173,10 +173,31 @@ function valuesMatch(left: unknown, right: unknown): boolean {
|
|
|
173
173
|
return JSON.stringify(left) === JSON.stringify(right);
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
+
function isSecretLikeSettingKey(key: string): boolean {
|
|
177
|
+
const normalized = key.replace(/([a-z0-9])([A-Z])/g, '$1.$2').toLowerCase();
|
|
178
|
+
if (normalized.endsWith('secret.policy')) return false;
|
|
179
|
+
return /(?:secret|token|password|api[-_.]?key|api\.key|signing)/i.test(normalized);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function compactSettingValue(key: string, value: unknown): string {
|
|
183
|
+
if (value === undefined || value === null) return '(unset)';
|
|
184
|
+
if (isSecretLikeSettingKey(key)) return value === '' ? '(empty)' : '(secret)';
|
|
185
|
+
if (typeof value === 'boolean') return value ? 'true' : 'false';
|
|
186
|
+
if (typeof value === 'number') return Number.isFinite(value) ? String(value) : '(invalid)';
|
|
187
|
+
if (typeof value === 'string') {
|
|
188
|
+
if (value.length === 0) return '(empty)';
|
|
189
|
+
if (value.startsWith('goodvibes://secrets/')) return '(secret)';
|
|
190
|
+
return value.length > 36 ? `${value.slice(0, 33)}...` : value;
|
|
191
|
+
}
|
|
192
|
+
if (Array.isArray(value)) return `[${value.length} item${value.length === 1 ? '' : 's'}]`;
|
|
193
|
+
if (isRecord(value)) return '{...}';
|
|
194
|
+
return String(value);
|
|
195
|
+
}
|
|
196
|
+
|
|
176
197
|
function redactImportValue(key: string, value: unknown): unknown {
|
|
177
198
|
if (typeof value !== 'string') return value;
|
|
178
199
|
if (!value) return value;
|
|
179
|
-
if (
|
|
200
|
+
if (isSecretLikeSettingKey(key)) {
|
|
180
201
|
return value.startsWith('goodvibes://secrets/') ? '<secret-ref>' : '<redacted>';
|
|
181
202
|
}
|
|
182
203
|
return value;
|
|
@@ -369,6 +390,36 @@ export function buildAgentWorkspaceSettingActionEffect(
|
|
|
369
390
|
};
|
|
370
391
|
}
|
|
371
392
|
|
|
393
|
+
export function buildAgentWorkspaceSettingActionPreview(
|
|
394
|
+
context: CommandContext | null,
|
|
395
|
+
action: AgentWorkspaceAction,
|
|
396
|
+
): string | null {
|
|
397
|
+
const settingKey = action.settingKey?.trim();
|
|
398
|
+
const configManager = context?.platform?.configManager;
|
|
399
|
+
if (!settingKey || !configManager) return null;
|
|
400
|
+
|
|
401
|
+
const setting = agentWorkspaceSettingSchema(context, settingKey);
|
|
402
|
+
const currentValue = configManager.get(settingKey as ConfigKey);
|
|
403
|
+
let proposedValue: unknown;
|
|
404
|
+
|
|
405
|
+
if (action.settingValueHint !== undefined) {
|
|
406
|
+
proposedValue = action.settingValueHint;
|
|
407
|
+
} else if (setting?.type === 'boolean') {
|
|
408
|
+
proposedValue = !Boolean(currentValue);
|
|
409
|
+
} else if (setting?.type === 'enum' && setting.enumValues && setting.enumValues.length > 0) {
|
|
410
|
+
const currentIndex = Math.max(0, setting.enumValues.indexOf(String(currentValue)));
|
|
411
|
+
proposedValue = setting.enumValues[(currentIndex + 1) % setting.enumValues.length]!;
|
|
412
|
+
} else if (setting?.type === 'number' || setting?.type === 'string') {
|
|
413
|
+
proposedValue = 'edit value';
|
|
414
|
+
} else if (typeof currentValue === 'boolean') {
|
|
415
|
+
proposedValue = !currentValue;
|
|
416
|
+
} else {
|
|
417
|
+
proposedValue = 'choose value';
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return `${settingKey}: ${compactSettingValue(settingKey, currentValue)} -> ${compactSettingValue(settingKey, proposedValue)}`;
|
|
421
|
+
}
|
|
422
|
+
|
|
372
423
|
export async function applyAgentWorkspaceSettingValue(
|
|
373
424
|
context: CommandContext | null,
|
|
374
425
|
setting: ConfigSetting,
|
|
@@ -2,7 +2,7 @@ import type { ArtifactDescriptor } from '@pellux/goodvibes-sdk/platform/artifact
|
|
|
2
2
|
import type { CommandContext } from './command-registry.ts';
|
|
3
3
|
import { readSetupWizardCheckpoint } from '../agent/setup-wizard-checkpoint.ts';
|
|
4
4
|
import { readOnboardingCompletionMarker } from '../runtime/onboarding/index.ts';
|
|
5
|
-
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_RERUN_SMOKE_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_SAVE_SMOKE_ROUTE, buildAgentSetupWizard, emptyAgentSetupSmokeHistory, emptyAgentSetupWizardCheckpoint, type AgentSetupWizard, type AgentSetupWizardBlockedCheckFrequency, type AgentSetupWizardCheckpoint, type AgentSetupWizardSmokeHistory, type AgentSetupWizardSourceItem } from '../agent/setup-wizard.ts';
|
|
5
|
+
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_RERUN_SMOKE_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_SAVE_SMOKE_ROUTE, buildAgentSetupWizard, emptyAgentSetupSmokeHistory, emptyAgentSetupWizardCheckpoint, type AgentSetupWizard, type AgentSetupWizardBlockedCheckFrequency, type AgentSetupWizardCheckpoint, type AgentSetupWizardDurableReceipt, type AgentSetupWizardSmokeHistory, type AgentSetupWizardSourceItem } from '../agent/setup-wizard.ts';
|
|
6
6
|
import type { AgentWorkspaceSetupChecklistItem } from './agent-workspace-setup.ts';
|
|
7
7
|
import { readArtifactMetadataString, readArtifactMetadataStringList } from './agent-workspace-artifact-metadata.ts';
|
|
8
8
|
|
|
@@ -30,6 +30,12 @@ function setupSmokeEvidenceTrend(artifacts: readonly ArtifactDescriptor[]): stri
|
|
|
30
30
|
return 'unchanged';
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
function artifactCreatedAtIso(artifact: ArtifactDescriptor): string | null {
|
|
34
|
+
const createdAt = artifact.createdAt;
|
|
35
|
+
if (typeof createdAt !== 'number' || !Number.isFinite(createdAt)) return null;
|
|
36
|
+
return new Date(createdAt).toISOString();
|
|
37
|
+
}
|
|
38
|
+
|
|
33
39
|
function setupSmokeBlockedCheckFrequency(artifacts: readonly ArtifactDescriptor[]): readonly AgentSetupWizardBlockedCheckFrequency[] {
|
|
34
40
|
const counts = new Map<string, number>();
|
|
35
41
|
for (const artifact of artifacts) {
|
|
@@ -67,6 +73,8 @@ export function buildSetupSmokeHistory(artifacts: readonly ArtifactDescriptor[],
|
|
|
67
73
|
trend: setupSmokeEvidenceTrend(setupSmokeArtifacts),
|
|
68
74
|
latestResult: readArtifactMetadataString(latest.metadata, 'result') || 'unknown',
|
|
69
75
|
previousResult: previous ? readArtifactMetadataString(previous.metadata, 'result') || 'unknown' : null,
|
|
76
|
+
latestEvidenceId: latest.id,
|
|
77
|
+
latestEvidenceAt: artifactCreatedAtIso(latest),
|
|
70
78
|
resultCounts,
|
|
71
79
|
blockedCheckFrequency: setupSmokeBlockedCheckFrequency(setupSmokeArtifacts),
|
|
72
80
|
inspectLatestRoute: `agent_artifacts show artifactId:"${latest.id}" includeContent:false`,
|
|
@@ -136,6 +144,7 @@ function setupChecklistModelRoute(item: AgentWorkspaceSetupChecklistItem): strin
|
|
|
136
144
|
if (item.id === 'memory') return 'memory action:"status"';
|
|
137
145
|
if (item.id === 'notes') return 'personal_ops action:"lane" laneId:"notes"';
|
|
138
146
|
if (item.id === 'channels') return 'channels action:"status"';
|
|
147
|
+
if (item.id === 'browser-pwa') return 'computer action:"browser" includeParameters:true';
|
|
139
148
|
if (item.id === 'voice-media') return 'device action:"voice"';
|
|
140
149
|
return `agent_harness mode:"setup_item" setupItemId:"${item.id}"`;
|
|
141
150
|
}
|
|
@@ -149,6 +158,7 @@ function setupChecklistActionId(item: AgentWorkspaceSetupChecklistItem): string
|
|
|
149
158
|
if (item.id === 'skills') return 'skill-search';
|
|
150
159
|
if (item.id === 'routines') return 'routine-search';
|
|
151
160
|
if (item.id === 'channels') return 'channel-show';
|
|
161
|
+
if (item.id === 'browser-pwa') return 'browser-cockpit-readiness';
|
|
152
162
|
if (item.id === 'voice-media') return 'voice-enable';
|
|
153
163
|
return item.id;
|
|
154
164
|
}
|
|
@@ -167,7 +177,9 @@ export function buildWorkspaceSetupWizard(
|
|
|
167
177
|
smokeHistory: AgentSetupWizardSmokeHistory,
|
|
168
178
|
checkpoint: AgentSetupWizardCheckpoint,
|
|
169
179
|
setupMarkerExists: boolean,
|
|
180
|
+
durableReceipts: readonly AgentSetupWizardDurableReceipt[] = [],
|
|
170
181
|
): AgentSetupWizard {
|
|
182
|
+
const browserPwaNeedsReceipt = checklist.some((item) => item.id === 'browser-pwa' && item.status !== 'ready');
|
|
171
183
|
const items: AgentSetupWizardSourceItem[] = checklist.map((item) => ({
|
|
172
184
|
id: item.id,
|
|
173
185
|
label: item.label,
|
|
@@ -182,6 +194,13 @@ export function buildWorkspaceSetupWizard(
|
|
|
182
194
|
smokeHistory,
|
|
183
195
|
checkpoint,
|
|
184
196
|
closeoutCriticalStepIds: ['runtime', 'connected-host-auth', 'provider-model'],
|
|
197
|
+
receiptRequiredStepIds: [
|
|
198
|
+
'runtime',
|
|
199
|
+
'connected-host-auth',
|
|
200
|
+
'install-smoke',
|
|
201
|
+
...(browserPwaNeedsReceipt ? ['browser-pwa'] : []),
|
|
202
|
+
],
|
|
203
|
+
durableReceipts,
|
|
185
204
|
setupMarkerExists,
|
|
186
205
|
repeatedBlockerAliases: SETUP_WIZARD_SNAPSHOT_BLOCKER_ALIASES,
|
|
187
206
|
});
|
|
@@ -18,6 +18,7 @@ export interface AgentWorkspaceSetupChecklistInput {
|
|
|
18
18
|
readonly connectedHostTokenReadable: boolean;
|
|
19
19
|
readonly connectedHostTokenPath: string;
|
|
20
20
|
readonly connectedHostTokenError?: string | null;
|
|
21
|
+
readonly connectedHostAuthReceiptReady?: boolean;
|
|
21
22
|
readonly activeSubscriptionCount: number;
|
|
22
23
|
readonly pendingSubscriptionCount: number;
|
|
23
24
|
readonly availableSubscriptionProviderCount: number;
|
|
@@ -41,6 +42,10 @@ export interface AgentWorkspaceSetupChecklistInput {
|
|
|
41
42
|
readonly readyChannelCount: number;
|
|
42
43
|
readonly voiceProviderCount: number;
|
|
43
44
|
readonly mediaProviderCount: number;
|
|
45
|
+
readonly installSmokeReceiptReady?: boolean;
|
|
46
|
+
readonly browserPwaEnabled: boolean;
|
|
47
|
+
readonly browserPwaPublicBaseUrl: string;
|
|
48
|
+
readonly browserPwaFirstRunReceiptStatus: 'published' | 'not-published';
|
|
44
49
|
readonly runtimeProfileCount: number;
|
|
45
50
|
readonly runtimeStarterTemplateCount: number;
|
|
46
51
|
}
|
|
@@ -58,14 +63,19 @@ function sampleNames(summary: AgentBehaviorDiscoverySummary): string {
|
|
|
58
63
|
export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChecklistInput): readonly AgentWorkspaceSetupChecklistItem[] {
|
|
59
64
|
const providerReady = input.provider !== 'unknown' && input.model !== 'unknown';
|
|
60
65
|
const tokenPathKnown = input.connectedHostTokenPath !== '(Agent home unavailable)';
|
|
61
|
-
const
|
|
66
|
+
const connectedHostAuthReceiptReady = input.connectedHostAuthReceiptReady === true;
|
|
67
|
+
const connectedHostAuthStatus: AgentWorkspaceSetupStatus = input.connectedHostTokenReadable || connectedHostAuthReceiptReady
|
|
62
68
|
? 'ready'
|
|
63
69
|
: tokenPathKnown
|
|
64
70
|
? 'blocked'
|
|
65
71
|
: 'recommended';
|
|
66
|
-
const
|
|
72
|
+
const installSmokePrerequisitesReady = providerReady && (input.connectedHostTokenReadable || connectedHostAuthReceiptReady);
|
|
73
|
+
const installSmokeReceiptReady = input.installSmokeReceiptReady === true;
|
|
67
74
|
const hasActivePersona = input.activePersonaName !== '(none)' && input.activePersonaName !== '(unavailable)';
|
|
68
75
|
const discoveredBehaviorCount = input.discoveredPersonas.count + input.discoveredSkills.count + input.discoveredRoutines.count;
|
|
76
|
+
const browserPwaUrl = input.browserPwaPublicBaseUrl.trim();
|
|
77
|
+
const browserPwaHasPublicUrl = browserPwaUrl.length > 0 && browserPwaUrl !== '(not configured)';
|
|
78
|
+
const browserPwaReceiptPublished = input.browserPwaFirstRunReceiptStatus === 'published';
|
|
69
79
|
return [
|
|
70
80
|
{
|
|
71
81
|
id: 'runtime',
|
|
@@ -78,7 +88,9 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
78
88
|
id: 'connected-host-auth',
|
|
79
89
|
label: 'Connected-host auth',
|
|
80
90
|
status: connectedHostAuthStatus,
|
|
81
|
-
detail:
|
|
91
|
+
detail: connectedHostAuthReceiptReady
|
|
92
|
+
? `Durable connected-host auth receipt is ready${input.connectedHostTokenReadable ? ` and Agent has a readable operator token at ${input.connectedHostTokenPath}` : ''}.`
|
|
93
|
+
: input.connectedHostTokenReadable
|
|
82
94
|
? `Agent has a readable connected-host operator token at ${input.connectedHostTokenPath}.`
|
|
83
95
|
: input.connectedHostTokenError
|
|
84
96
|
? `The connected-host operator token exists but cannot be read at ${input.connectedHostTokenPath}. Use the confirmed setup token provisioning route, then rerun auth review.`
|
|
@@ -99,8 +111,10 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
99
111
|
{
|
|
100
112
|
id: 'install-smoke',
|
|
101
113
|
label: 'Install smoke',
|
|
102
|
-
status:
|
|
103
|
-
detail:
|
|
114
|
+
status: installSmokeReceiptReady ? 'ready' : installSmokePrerequisitesReady ? 'recommended' : tokenPathKnown ? 'blocked' : 'recommended',
|
|
115
|
+
detail: installSmokeReceiptReady
|
|
116
|
+
? 'Durable setup smoke receipt is ready for release closeout; rerun smoke only after install, host, auth, or model changes.'
|
|
117
|
+
: installSmokePrerequisitesReady
|
|
104
118
|
? 'Run setup smoke after install or migration to prove package start, connected host, auth, model route, setup posture, and first assistant turn.'
|
|
105
119
|
: 'Resolve connected-host auth and provider/model setup before treating the first assistant turn as install-ready.',
|
|
106
120
|
command: 'Start -> Install smoke',
|
|
@@ -208,6 +222,19 @@ export function buildAgentWorkspaceSetupChecklist(input: AgentWorkspaceSetupChec
|
|
|
208
222
|
: 'Pair or review channels only when you want the assistant reachable outside this terminal.',
|
|
209
223
|
command: 'Channels',
|
|
210
224
|
},
|
|
225
|
+
{
|
|
226
|
+
id: 'browser-pwa',
|
|
227
|
+
label: 'Browser/PWA',
|
|
228
|
+
status: browserPwaReceiptPublished ? 'ready' : 'recommended',
|
|
229
|
+
detail: browserPwaReceiptPublished
|
|
230
|
+
? `Connected-host browser/PWA first-run receipt is published${browserPwaHasPublicUrl ? ` for ${browserPwaUrl}` : ''}.`
|
|
231
|
+
: input.browserPwaEnabled
|
|
232
|
+
? browserPwaHasPublicUrl
|
|
233
|
+
? `Browser cockpit is openable at ${browserPwaUrl}, but the connected-host browser/PWA first-run completion receipt is not published yet. Terminal Agent remains primary until that receipt exists.`
|
|
234
|
+
: 'Browser cockpit is enabled through the connected-host web endpoint, but the connected-host browser/PWA first-run completion receipt is not published yet.'
|
|
235
|
+
: 'Enable the connected-host web endpoint and publish the browser/PWA first-run completion receipt before treating browser access as setup-ready.',
|
|
236
|
+
command: 'Voice & Media -> Browser/PWA readiness',
|
|
237
|
+
},
|
|
211
238
|
{
|
|
212
239
|
id: 'voice-media',
|
|
213
240
|
label: 'Voice and media',
|