@pellux/goodvibes-agent 1.5.5 → 1.5.6
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 +9 -0
- package/README.md +1 -1
- package/dist/package/main.js +94130 -79335
- package/docs/tools-and-commands.md +2 -1
- package/package.json +6 -3
- package/src/agent/autonomy-schedule-format.ts +1 -1
- package/src/agent/autonomy-schedule.ts +3 -3
- package/src/agent/calendar/calendar-oauth-service.ts +324 -0
- package/src/agent/calendar-subscription-registry.ts +497 -0
- package/src/agent/email/email-service.ts +57 -0
- package/src/agent/email/smtp-client.ts +30 -10
- package/src/agent/memory-prompt.ts +143 -12
- package/src/agent/operator-actions.ts +26 -22
- package/src/agent/prompt-context-receipts.ts +45 -18
- package/src/agent/reminder-schedule-format.ts +1 -1
- package/src/agent/reminder-schedule.ts +3 -3
- package/src/agent/routine-schedule-format.ts +2 -2
- package/src/agent/routine-schedule-promotion.ts +5 -5
- package/src/agent/routine-schedule-receipts.ts +2 -2
- package/src/agent/schedule-edit-format.ts +1 -1
- package/src/agent/schedule-edit.ts +5 -5
- package/src/agent/session-registration.ts +281 -0
- package/src/agent/vibe-file.ts +50 -0
- package/src/cli/local-library-command-shared.ts +146 -0
- package/src/cli/management.ts +2 -1
- package/src/cli/personas-command.ts +252 -0
- package/src/cli/resume-relaunch-notice.ts +151 -0
- package/src/cli/routines-command.ts +25 -2
- package/src/cli/service-posture.ts +3 -2
- package/src/cli/skill-bundle-command.ts +175 -0
- package/src/cli/skills-command.ts +309 -0
- package/src/cli/status.ts +43 -7
- package/src/cli/tui-startup.ts +24 -1
- package/src/config/agent-settings-policy.ts +0 -1
- package/src/config/secret-config.ts +4 -0
- package/src/core/conversation-rendering.ts +20 -11
- package/src/core/focus-tracker.ts +41 -0
- package/src/core/system-message-noise.ts +108 -0
- package/src/core/system-message-router.ts +54 -1
- package/src/core/thinking-overlay.ts +83 -0
- package/src/input/agent-workspace-access-command-editor-submission.ts +75 -108
- package/src/input/agent-workspace-access-command-editors.ts +108 -128
- package/src/input/agent-workspace-activation.ts +15 -0
- package/src/input/agent-workspace-basic-command-editor-submission.ts +292 -513
- package/src/input/agent-workspace-basic-command-editors.ts +433 -564
- package/src/input/agent-workspace-calendar-connect-editor.ts +116 -0
- package/src/input/agent-workspace-calendar-oauth-editor.ts +152 -0
- package/src/input/agent-workspace-calendar-subscribe-editor.ts +128 -0
- package/src/input/agent-workspace-categories.ts +7 -2
- package/src/input/agent-workspace-channel-command-editor-submission.ts +38 -52
- package/src/input/agent-workspace-channel-command-editors.ts +42 -46
- package/src/input/agent-workspace-command-editor-engine.ts +133 -0
- package/src/input/agent-workspace-command-editor.ts +4 -0
- package/src/input/agent-workspace-direct-editor-submission.ts +59 -0
- package/src/input/agent-workspace-email-connect-editor.ts +162 -0
- package/src/input/agent-workspace-knowledge-command-editor-submission.ts +52 -81
- package/src/input/agent-workspace-knowledge-command-editors.ts +71 -71
- package/src/input/agent-workspace-library-command-editor-submission.ts +10 -28
- package/src/input/agent-workspace-library-command-editors.ts +16 -2
- package/src/input/agent-workspace-live-counters.ts +55 -0
- package/src/input/agent-workspace-mcp-command-editor-submission.ts +60 -82
- package/src/input/agent-workspace-mcp-command-editors.ts +52 -0
- package/src/input/agent-workspace-media-command-editor-submission.ts +12 -39
- package/src/input/agent-workspace-media-command-editors.ts +10 -8
- package/src/input/agent-workspace-memory-command-editor-submission.ts +76 -151
- package/src/input/agent-workspace-memory-command-editors.ts +116 -141
- package/src/input/agent-workspace-operations-command-editor-submission.ts +131 -184
- package/src/input/agent-workspace-operations-command-editors.ts +150 -162
- package/src/input/agent-workspace-provider-command-editor-submission.ts +60 -106
- package/src/input/agent-workspace-provider-command-editors.ts +58 -68
- package/src/input/agent-workspace-search.ts +8 -1
- package/src/input/agent-workspace-session-command-editor-submission.ts +104 -132
- package/src/input/agent-workspace-session-command-editors.ts +160 -195
- package/src/input/agent-workspace-settings.ts +40 -1
- package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +55 -71
- package/src/input/agent-workspace-skill-bundle-command-editors.ts +65 -69
- package/src/input/agent-workspace-snapshot-builders.ts +431 -0
- package/src/input/agent-workspace-snapshot-config.ts +43 -0
- package/src/input/agent-workspace-snapshot.ts +198 -432
- package/src/input/agent-workspace-task-command-editor-submission.ts +34 -44
- package/src/input/agent-workspace-task-command-editors.ts +27 -28
- package/src/input/agent-workspace-types.ts +35 -1
- package/src/input/agent-workspace.ts +5 -14
- package/src/input/command-registry.ts +23 -1
- package/src/input/commands/calendar-connect-runtime.ts +226 -0
- package/src/input/commands/calendar-runtime.ts +110 -7
- package/src/input/commands/calendar-subscription-runtime.ts +225 -0
- package/src/input/commands/email-runtime.ts +100 -40
- package/src/input/commands/knowledge.ts +1 -1
- package/src/input/commands/network-scan-runtime.ts +75 -0
- package/src/input/commands/operator-actions-runtime.ts +9 -6
- package/src/input/commands/personas-runtime.ts +1 -1
- package/src/input/commands/schedule-runtime.ts +4 -4
- package/src/input/commands/session-content.ts +13 -1
- package/src/input/commands/session-workflow.ts +15 -20
- package/src/input/commands/session.ts +3 -1
- package/src/input/commands/shell-core.ts +20 -6
- package/src/input/commands.ts +2 -2
- package/src/input/delete-key-policy.ts +46 -0
- package/src/input/feed-context-factory.ts +10 -0
- package/src/input/handler-feed.ts +87 -0
- package/src/input/handler-modal-routes.ts +6 -1
- package/src/input/handler.ts +5 -0
- package/src/input/panel-paste-flood-guard.ts +94 -0
- package/src/input/settings-modal-types.ts +5 -3
- package/src/input/settings-modal.ts +21 -0
- package/src/main.ts +36 -36
- package/src/permissions/approval-posture.ts +141 -0
- package/src/renderer/agent-workspace-context-lines.ts +10 -2
- package/src/renderer/compositor.ts +27 -4
- package/src/renderer/diff.ts +61 -18
- package/src/renderer/fullscreen-primitives.ts +37 -18
- package/src/renderer/markdown.ts +20 -10
- package/src/renderer/modal-factory.ts +25 -15
- package/src/renderer/overlay-box.ts +23 -12
- package/src/renderer/process-indicator.ts +8 -3
- package/src/renderer/prompt-content-width.ts +16 -0
- package/src/renderer/settings-modal-helpers.ts +2 -0
- package/src/renderer/settings-modal.ts +2 -0
- package/src/renderer/startup-theme-probe.ts +35 -0
- package/src/renderer/status-glyphs.ts +11 -15
- package/src/renderer/system-message.ts +17 -2
- package/src/renderer/term-caps.ts +318 -0
- package/src/renderer/terminal-bg-probe.ts +373 -0
- package/src/renderer/terminal-escapes.ts +24 -0
- package/src/renderer/theme-mode-config.ts +87 -0
- package/src/renderer/theme.ts +241 -0
- package/src/renderer/thinking.ts +12 -3
- package/src/renderer/tool-call.ts +7 -3
- package/src/renderer/ui-factory.ts +92 -36
- package/src/renderer/ui-primitives.ts +33 -93
- package/src/runtime/bootstrap-core.ts +15 -0
- package/src/runtime/bootstrap-hook-bridge.ts +6 -0
- package/src/runtime/bootstrap-shell.ts +2 -0
- package/src/runtime/bootstrap.ts +68 -5
- package/src/runtime/calendar-boot-refresh.ts +105 -0
- package/src/runtime/lan-scan-consent.ts +253 -0
- package/src/runtime/services.ts +127 -2
- package/src/runtime/session-spine-rest-transport.ts +160 -0
- package/src/runtime/terminal-output-guard.ts +6 -1
- package/src/runtime/ui-services.ts +3 -0
- package/src/shell/agent-workspace-fullscreen.ts +5 -0
- package/src/shell/terminal-focus-mode.ts +120 -0
- package/src/shell/ui-openers.ts +13 -4
- package/src/tools/agent-harness-autonomy-intake.ts +5 -5
- package/src/tools/agent-harness-autonomy-queue.ts +1 -1
- package/src/tools/agent-harness-background-processes.ts +2 -1
- package/src/tools/agent-harness-metadata.ts +16 -8
- package/src/tools/agent-harness-operator-methods.ts +44 -8
- package/src/tools/agent-harness-personal-ops-discovery.ts +57 -10
- package/src/tools/agent-harness-personal-ops-lanes.ts +17 -5
- package/src/tools/agent-harness-personal-ops-operations.ts +7 -7
- package/src/tools/agent-harness-personal-ops-types.ts +6 -0
- package/src/tools/agent-harness-prompt-context.ts +26 -12
- package/src/tools/agent-harness-workspace-actions.ts +4 -0
- package/src/tools/agent-local-registry-args.ts +117 -0
- package/src/tools/agent-local-registry-memory.ts +227 -0
- package/src/tools/agent-local-registry-tool.ts +19 -237
- package/src/tools/agent-operator-briefing-tool.ts +2 -2
- package/src/tools/agent-operator-method-tool.ts +13 -0
- package/src/tools/agent-policy-explanation.ts +39 -4
- package/src/tools/agent-schedule-tool.ts +5 -5
- package/src/utils/terminal-width.ts +98 -1
- package/src/version.ts +1 -1
- package/src/cli/local-library-command.ts +0 -825
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { AgentWorkspaceEditorKind, AgentWorkspaceLocalEditor } from './agent-workspace-types.ts';
|
|
2
|
+
import type { AgentWorkspaceEditorSpec, AgentWorkspaceEditorSpecEntry } from './agent-workspace-command-editor-engine.ts';
|
|
3
|
+
import { createAgentWorkspaceEditorFromTable } from './agent-workspace-command-editor-engine.ts';
|
|
2
4
|
|
|
3
5
|
export type AgentWorkspaceSkillBundleCommandEditorKind = Extract<
|
|
4
6
|
AgentWorkspaceEditorKind,
|
|
@@ -23,81 +25,13 @@ export function isAgentWorkspaceSkillBundleCommandEditorKind(kind: AgentWorkspac
|
|
|
23
25
|
|| kind === 'skill-bundle-delete';
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
if (kind === 'skill-bundle-search') {
|
|
28
|
-
return {
|
|
29
|
-
kind,
|
|
30
|
-
mode: 'create',
|
|
31
|
-
title: 'Search Skill Bundles',
|
|
32
|
-
selectedFieldIndex: 0,
|
|
33
|
-
message: 'Search Agent-local skill bundles by name, description, or member skill.',
|
|
34
|
-
fields: [
|
|
35
|
-
{ id: 'query', label: 'Search query', value: '', required: false, multiline: false, hint: 'Optional text query. Blank lists every bundle.' },
|
|
36
|
-
],
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
if (kind === 'skill-bundle-show') {
|
|
40
|
-
return {
|
|
41
|
-
kind,
|
|
42
|
-
mode: 'create',
|
|
43
|
-
title: 'Show Skill Bundle',
|
|
44
|
-
selectedFieldIndex: 0,
|
|
45
|
-
message: 'Show one Agent-local skill bundle with readiness and member skills.',
|
|
46
|
-
fields: [
|
|
47
|
-
{ id: 'id', label: 'Bundle id', value: '', required: true, multiline: false, hint: 'Existing local skill bundle id.' },
|
|
48
|
-
],
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
if (kind === 'skill-bundle-update') {
|
|
52
|
-
return {
|
|
53
|
-
kind,
|
|
54
|
-
mode: 'update',
|
|
55
|
-
title: 'Update Skill Bundle',
|
|
56
|
-
selectedFieldIndex: 0,
|
|
57
|
-
message: 'Update one Agent-local skill bundle. Type yes on the final field to confirm.',
|
|
58
|
-
fields: [
|
|
59
|
-
{ id: 'id', label: 'Bundle id', value: '', required: true, multiline: false, hint: 'Existing local skill bundle id.' },
|
|
60
|
-
{ id: 'name', label: 'Name', value: '', required: false, multiline: false, hint: 'Optional replacement name.' },
|
|
61
|
-
{ id: 'description', label: 'Description', value: '', required: false, multiline: false, hint: 'Optional replacement one-line description.' },
|
|
62
|
-
{ id: 'skills', label: 'Skill ids', value: '', required: false, multiline: false, hint: 'Optional replacement comma-separated local skill ids.' },
|
|
63
|
-
{ id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /skills bundle update.' },
|
|
64
|
-
],
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
if (kind === 'skill-bundle-stale') {
|
|
68
|
-
return {
|
|
69
|
-
kind,
|
|
70
|
-
mode: 'update',
|
|
71
|
-
title: 'Mark Skill Bundle Stale',
|
|
72
|
-
selectedFieldIndex: 0,
|
|
73
|
-
message: 'Mark one Agent-local skill bundle stale with a review reason. Type yes on the final field to confirm.',
|
|
74
|
-
fields: [
|
|
75
|
-
{ id: 'id', label: 'Bundle id', value: '', required: true, multiline: false, hint: 'Existing local skill bundle id.' },
|
|
76
|
-
{ id: 'reason', label: 'Reason', value: '', required: true, multiline: true, hint: 'Why this bundle needs review. Ctrl-J inserts a new line.' },
|
|
77
|
-
{ id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /skills bundle stale.' },
|
|
78
|
-
],
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
if (kind === 'skill-bundle-delete') {
|
|
82
|
-
return {
|
|
83
|
-
kind,
|
|
84
|
-
mode: 'delete',
|
|
85
|
-
title: 'Delete Skill Bundle',
|
|
86
|
-
selectedFieldIndex: 0,
|
|
87
|
-
message: 'Delete one Agent-local skill bundle. This does not delete member skills. Type yes to confirm.',
|
|
88
|
-
fields: [
|
|
89
|
-
{ id: 'id', label: 'Bundle id', value: '', required: true, multiline: false, hint: 'Existing local skill bundle id.' },
|
|
90
|
-
{ id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /skills bundle delete with --yes.' },
|
|
91
|
-
],
|
|
92
|
-
};
|
|
93
|
-
}
|
|
28
|
+
function skillBundleEnableDisableReviewSpec(kind: AgentWorkspaceSkillBundleCommandEditorKind): AgentWorkspaceEditorSpec {
|
|
94
29
|
const verb = kind === 'skill-bundle-enable'
|
|
95
30
|
? 'Enable'
|
|
96
31
|
: kind === 'skill-bundle-disable'
|
|
97
32
|
? 'Disable'
|
|
98
33
|
: 'Review';
|
|
99
34
|
return {
|
|
100
|
-
kind,
|
|
101
35
|
mode: 'update',
|
|
102
36
|
title: `${verb} Skill Bundle`,
|
|
103
37
|
selectedFieldIndex: 0,
|
|
@@ -108,3 +42,65 @@ export function createAgentWorkspaceSkillBundleCommandEditor(kind: AgentWorkspac
|
|
|
108
42
|
],
|
|
109
43
|
};
|
|
110
44
|
}
|
|
45
|
+
|
|
46
|
+
const SKILL_BUNDLE_COMMAND_EDITOR_SPECS: Readonly<Record<AgentWorkspaceSkillBundleCommandEditorKind, AgentWorkspaceEditorSpecEntry<AgentWorkspaceSkillBundleCommandEditorKind>>> = {
|
|
47
|
+
'skill-bundle-search': {
|
|
48
|
+
mode: 'create',
|
|
49
|
+
title: 'Search Skill Bundles',
|
|
50
|
+
selectedFieldIndex: 0,
|
|
51
|
+
message: 'Search Agent-local skill bundles by name, description, or member skill.',
|
|
52
|
+
fields: [
|
|
53
|
+
{ id: 'query', label: 'Search query', value: '', required: false, multiline: false, hint: 'Optional text query. Blank lists every bundle.' },
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
'skill-bundle-show': {
|
|
57
|
+
mode: 'create',
|
|
58
|
+
title: 'Show Skill Bundle',
|
|
59
|
+
selectedFieldIndex: 0,
|
|
60
|
+
message: 'Show one Agent-local skill bundle with readiness and member skills.',
|
|
61
|
+
fields: [
|
|
62
|
+
{ id: 'id', label: 'Bundle id', value: '', required: true, multiline: false, hint: 'Existing local skill bundle id.' },
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
'skill-bundle-update': {
|
|
66
|
+
mode: 'update',
|
|
67
|
+
title: 'Update Skill Bundle',
|
|
68
|
+
selectedFieldIndex: 0,
|
|
69
|
+
message: 'Update one Agent-local skill bundle. Type yes on the final field to confirm.',
|
|
70
|
+
fields: [
|
|
71
|
+
{ id: 'id', label: 'Bundle id', value: '', required: true, multiline: false, hint: 'Existing local skill bundle id.' },
|
|
72
|
+
{ id: 'name', label: 'Name', value: '', required: false, multiline: false, hint: 'Optional replacement name.' },
|
|
73
|
+
{ id: 'description', label: 'Description', value: '', required: false, multiline: false, hint: 'Optional replacement one-line description.' },
|
|
74
|
+
{ id: 'skills', label: 'Skill ids', value: '', required: false, multiline: false, hint: 'Optional replacement comma-separated local skill ids.' },
|
|
75
|
+
{ id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /skills bundle update.' },
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
'skill-bundle-stale': {
|
|
79
|
+
mode: 'update',
|
|
80
|
+
title: 'Mark Skill Bundle Stale',
|
|
81
|
+
selectedFieldIndex: 0,
|
|
82
|
+
message: 'Mark one Agent-local skill bundle stale with a review reason. Type yes on the final field to confirm.',
|
|
83
|
+
fields: [
|
|
84
|
+
{ id: 'id', label: 'Bundle id', value: '', required: true, multiline: false, hint: 'Existing local skill bundle id.' },
|
|
85
|
+
{ id: 'reason', label: 'Reason', value: '', required: true, multiline: true, hint: 'Why this bundle needs review. Ctrl-J inserts a new line.' },
|
|
86
|
+
{ id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /skills bundle stale.' },
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
'skill-bundle-delete': {
|
|
90
|
+
mode: 'delete',
|
|
91
|
+
title: 'Delete Skill Bundle',
|
|
92
|
+
selectedFieldIndex: 0,
|
|
93
|
+
message: 'Delete one Agent-local skill bundle. This does not delete member skills. Type yes to confirm.',
|
|
94
|
+
fields: [
|
|
95
|
+
{ id: 'id', label: 'Bundle id', value: '', required: true, multiline: false, hint: 'Existing local skill bundle id.' },
|
|
96
|
+
{ id: 'confirm', label: 'Confirm', value: '', required: true, multiline: false, hint: 'Type yes to run /skills bundle delete with --yes.' },
|
|
97
|
+
],
|
|
98
|
+
},
|
|
99
|
+
'skill-bundle-enable': skillBundleEnableDisableReviewSpec,
|
|
100
|
+
'skill-bundle-disable': skillBundleEnableDisableReviewSpec,
|
|
101
|
+
'skill-bundle-review': skillBundleEnableDisableReviewSpec,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export function createAgentWorkspaceSkillBundleCommandEditor(kind: AgentWorkspaceSkillBundleCommandEditorKind): AgentWorkspaceLocalEditor {
|
|
105
|
+
return createAgentWorkspaceEditorFromTable(kind, SKILL_BUNDLE_COMMAND_EDITOR_SPECS);
|
|
106
|
+
}
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
// Sub-builders extracted out of the single ~516-line `buildAgentWorkspaceRuntimeSnapshot`
|
|
2
|
+
// function in agent-workspace-snapshot.ts (W4-H2, per the W4-H1 design ruling's
|
|
3
|
+
// giant-single-function-assembler verdict: "splitting into cohesive sub-builders...
|
|
4
|
+
// would reduce single-function size without changing behavior"). Each function here
|
|
5
|
+
// is the verbatim body of one of that function's local IIFEs or local variable blocks,
|
|
6
|
+
// moved unchanged so the top-level snapshot builder now composes named sub-builders
|
|
7
|
+
// instead of assembling everything inline. No behavior changes: same context reads,
|
|
8
|
+
// same try/catch fallbacks, same field shapes.
|
|
9
|
+
import { listAvailableSubscriptionProviders } from '@pellux/goodvibes-sdk/platform/config';
|
|
10
|
+
import type { CommandContext } from './command-registry.ts';
|
|
11
|
+
import { AgentNoteRegistry } from '../agent/note-registry.ts';
|
|
12
|
+
import { AgentPersonaRegistry } from '../agent/persona-registry.ts';
|
|
13
|
+
import { AgentResearchRunRegistry } from '../agent/research-run-registry.ts';
|
|
14
|
+
import { AgentResearchSourceRegistry } from '../agent/research-source-registry.ts';
|
|
15
|
+
import { AgentSkillRegistry } from '../agent/skill-registry.ts';
|
|
16
|
+
import { RoutineScheduleReceiptStore } from '../agent/routine-schedule-receipts.ts';
|
|
17
|
+
import {
|
|
18
|
+
getAgentRuntimeProfilesRoot,
|
|
19
|
+
listAgentRuntimeProfiles,
|
|
20
|
+
listAgentRuntimeProfileTemplates,
|
|
21
|
+
readAgentRuntimeProfileSelection,
|
|
22
|
+
} from '../agent/runtime-profile.ts';
|
|
23
|
+
import { GOODVIBES_AGENT_PAIRING_SURFACE } from '../config/surface.ts';
|
|
24
|
+
import { connectedHostOperatorTokenFingerprint, readConnectedHostOperatorToken, type ConnectedHostOperatorToken } from '../runtime/connected-host-auth.ts';
|
|
25
|
+
import { summarizePersonaItem, summarizeNoteItem, summarizeResearchRunItem, summarizeRoutineScheduleReceipt, summarizeSkillBundleItem, summarizeSkillItem } from './agent-workspace-local-library-snapshot.ts';
|
|
26
|
+
import { isReviewerHandoffArtifact, summarizeReviewerHandoffArtifact } from './agent-workspace-review-packet-utils.ts';
|
|
27
|
+
import { ensureEmailConfigDefaults, readEmailConfig, validateEmailConfig } from '../agent/email/email-service.ts';
|
|
28
|
+
import { CALENDAR_OAUTH_CLIENT_ID_KEYS, ensureCalendarConfigDefaults } from '../agent/calendar/calendar-oauth-service.ts';
|
|
29
|
+
import { readConfigBoolean, readConfigNumber, readConfigString } from './agent-workspace-snapshot-config.ts';
|
|
30
|
+
import type { AgentWorkspaceCalendarOAuthConfigStatus } from './agent-workspace-calendar-oauth-editor.ts';
|
|
31
|
+
import type { AgentWorkspaceEmailConnectStatus } from './agent-workspace-types.ts';
|
|
32
|
+
|
|
33
|
+
export function buildAgentWorkspaceCurrentModelSnapshot(context: CommandContext): ReturnType<NonNullable<NonNullable<CommandContext['provider']>['providerRegistry']>['getCurrentModel']> | null | undefined {
|
|
34
|
+
try {
|
|
35
|
+
return context.provider?.providerRegistry?.getCurrentModel?.();
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function buildAgentWorkspaceSessionMemoryCount(context: CommandContext): number {
|
|
42
|
+
try {
|
|
43
|
+
return context.session?.sessionMemoryStore?.list?.().length ?? 0;
|
|
44
|
+
} catch {
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function buildAgentWorkspacePersonaSnapshot(context: CommandContext) {
|
|
50
|
+
try {
|
|
51
|
+
const shellPaths = context.workspace?.shellPaths;
|
|
52
|
+
if (!shellPaths) return { count: 0, activeName: '(none)', items: [] };
|
|
53
|
+
const snapshot = AgentPersonaRegistry.fromShellPaths(shellPaths).snapshot();
|
|
54
|
+
return {
|
|
55
|
+
count: snapshot.personas.length,
|
|
56
|
+
activeName: snapshot.activePersona?.name ?? '(none)',
|
|
57
|
+
items: snapshot.personas.map((persona) => summarizePersonaItem(persona, snapshot.activePersonaId)),
|
|
58
|
+
};
|
|
59
|
+
} catch {
|
|
60
|
+
return { count: 0, activeName: '(unavailable)', items: [] };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function buildAgentWorkspaceNoteSnapshot(context: CommandContext) {
|
|
65
|
+
try {
|
|
66
|
+
const shellPaths = context.workspace?.shellPaths;
|
|
67
|
+
if (!shellPaths) return { count: 0, reviewQueueCount: 0, items: [] };
|
|
68
|
+
const snapshot = AgentNoteRegistry.fromShellPaths(shellPaths).snapshot();
|
|
69
|
+
return {
|
|
70
|
+
count: snapshot.notes.length,
|
|
71
|
+
reviewQueueCount: snapshot.reviewQueue.length,
|
|
72
|
+
items: snapshot.notes.map(summarizeNoteItem),
|
|
73
|
+
};
|
|
74
|
+
} catch {
|
|
75
|
+
return { count: 0, reviewQueueCount: 0, items: [] };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function buildAgentWorkspaceSkillSnapshot(context: CommandContext) {
|
|
80
|
+
try {
|
|
81
|
+
const shellPaths = context.workspace?.shellPaths;
|
|
82
|
+
if (!shellPaths) return { count: 0, enabled: 0, active: 0, bundleCount: 0, enabledBundleCount: 0, items: [], bundleItems: [] };
|
|
83
|
+
const snapshot = AgentSkillRegistry.fromShellPaths(shellPaths).snapshot();
|
|
84
|
+
return {
|
|
85
|
+
count: snapshot.skills.length,
|
|
86
|
+
enabled: snapshot.enabledSkills.length,
|
|
87
|
+
active: snapshot.activeSkills.length,
|
|
88
|
+
bundleCount: snapshot.bundles.length,
|
|
89
|
+
enabledBundleCount: snapshot.enabledBundles.length,
|
|
90
|
+
items: snapshot.skills.map(summarizeSkillItem),
|
|
91
|
+
bundleItems: snapshot.bundles.map((bundle) => summarizeSkillBundleItem(bundle, snapshot.skills)),
|
|
92
|
+
};
|
|
93
|
+
} catch {
|
|
94
|
+
return { count: 0, enabled: 0, active: 0, bundleCount: 0, enabledBundleCount: 0, items: [], bundleItems: [] };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function buildAgentWorkspaceRoutineScheduleReceiptsSnapshot(context: CommandContext) {
|
|
99
|
+
try {
|
|
100
|
+
const shellPaths = context.workspace?.shellPaths;
|
|
101
|
+
if (!shellPaths) return { count: 0, successful: 0, failed: 0, latest: null };
|
|
102
|
+
const receipts = RoutineScheduleReceiptStore.fromShellPaths(shellPaths).snapshot().receipts;
|
|
103
|
+
return {
|
|
104
|
+
count: receipts.length,
|
|
105
|
+
successful: receipts.filter((receipt) => receipt.status === 'created').length,
|
|
106
|
+
failed: receipts.filter((receipt) => receipt.status === 'failed').length,
|
|
107
|
+
latest: receipts[0] ? summarizeRoutineScheduleReceipt(receipts[0]) : null,
|
|
108
|
+
};
|
|
109
|
+
} catch {
|
|
110
|
+
return { count: 0, successful: 0, failed: 0, latest: null };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function buildAgentWorkspaceResearchSourceSnapshot(context: CommandContext) {
|
|
115
|
+
try {
|
|
116
|
+
const shellPaths = context.workspace?.shellPaths;
|
|
117
|
+
if (!shellPaths) return { count: 0, candidate: 0, reviewed: 0, rejected: 0, used: 0 };
|
|
118
|
+
const snapshot = AgentResearchSourceRegistry.fromShellPaths(shellPaths).snapshot();
|
|
119
|
+
return {
|
|
120
|
+
count: snapshot.sources.length,
|
|
121
|
+
candidate: snapshot.candidates.length,
|
|
122
|
+
reviewed: snapshot.reviewed.length,
|
|
123
|
+
rejected: snapshot.rejected.length,
|
|
124
|
+
used: snapshot.used.length,
|
|
125
|
+
};
|
|
126
|
+
} catch {
|
|
127
|
+
return { count: 0, candidate: 0, reviewed: 0, rejected: 0, used: 0 };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function buildAgentWorkspaceResearchRunSnapshot(context: CommandContext) {
|
|
132
|
+
try {
|
|
133
|
+
const shellPaths = context.workspace?.shellPaths;
|
|
134
|
+
if (!shellPaths) return { count: 0, planned: 0, running: 0, paused: 0, blocked: 0, terminal: 0, items: [] };
|
|
135
|
+
const snapshot = AgentResearchRunRegistry.fromShellPaths(shellPaths).snapshot();
|
|
136
|
+
const actionable = [
|
|
137
|
+
...snapshot.blocked,
|
|
138
|
+
...snapshot.running,
|
|
139
|
+
...snapshot.paused,
|
|
140
|
+
...snapshot.planned,
|
|
141
|
+
...snapshot.failed,
|
|
142
|
+
...snapshot.completed,
|
|
143
|
+
...snapshot.cancelled,
|
|
144
|
+
];
|
|
145
|
+
return {
|
|
146
|
+
count: snapshot.runs.length,
|
|
147
|
+
planned: snapshot.planned.length,
|
|
148
|
+
running: snapshot.running.length,
|
|
149
|
+
paused: snapshot.paused.length,
|
|
150
|
+
blocked: snapshot.blocked.length,
|
|
151
|
+
terminal: snapshot.cancelled.length + snapshot.completed.length + snapshot.failed.length,
|
|
152
|
+
items: actionable.slice(0, 8).map(summarizeResearchRunItem),
|
|
153
|
+
};
|
|
154
|
+
} catch {
|
|
155
|
+
return { count: 0, planned: 0, running: 0, paused: 0, blocked: 0, terminal: 0, items: [] };
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function buildAgentWorkspaceArtifactListSnapshot(context: CommandContext) {
|
|
160
|
+
try {
|
|
161
|
+
const list = context.platform?.artifactStore?.list;
|
|
162
|
+
return {
|
|
163
|
+
available: Boolean(list),
|
|
164
|
+
items: [...(list?.(100) ?? [])],
|
|
165
|
+
};
|
|
166
|
+
} catch {
|
|
167
|
+
return { available: false, items: [] };
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function buildAgentWorkspaceRecentReviewerHandoffsSnapshot(artifactItems: ReturnType<typeof buildAgentWorkspaceArtifactListSnapshot>['items']) {
|
|
172
|
+
try {
|
|
173
|
+
const handoffs = artifactItems
|
|
174
|
+
.filter(isReviewerHandoffArtifact)
|
|
175
|
+
.sort((left, right) => right.createdAt - left.createdAt);
|
|
176
|
+
return {
|
|
177
|
+
count: handoffs.length,
|
|
178
|
+
items: handoffs.slice(0, 6).map(summarizeReviewerHandoffArtifact),
|
|
179
|
+
};
|
|
180
|
+
} catch {
|
|
181
|
+
return { count: 0, items: [] };
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export function buildAgentWorkspaceRuntimeProfilesSnapshot(profileBaseHome: string) {
|
|
186
|
+
const runtimeProfiles = (() => {
|
|
187
|
+
try {
|
|
188
|
+
return listAgentRuntimeProfiles(profileBaseHome);
|
|
189
|
+
} catch {
|
|
190
|
+
return [];
|
|
191
|
+
}
|
|
192
|
+
})();
|
|
193
|
+
const runtimeStarterTemplates = (() => {
|
|
194
|
+
try {
|
|
195
|
+
return listAgentRuntimeProfileTemplates(profileBaseHome);
|
|
196
|
+
} catch {
|
|
197
|
+
return [];
|
|
198
|
+
}
|
|
199
|
+
})();
|
|
200
|
+
const selectedRuntimeProfile = (() => {
|
|
201
|
+
try {
|
|
202
|
+
return readAgentRuntimeProfileSelection(profileBaseHome);
|
|
203
|
+
} catch {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
})();
|
|
207
|
+
return { runtimeProfiles, runtimeStarterTemplates, selectedRuntimeProfile, runtimeProfileRoot: getAgentRuntimeProfilesRoot(profileBaseHome) };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function buildAgentWorkspaceVoiceMediaProvidersSnapshot(context: CommandContext) {
|
|
211
|
+
const voiceProviders = (() => {
|
|
212
|
+
try {
|
|
213
|
+
return context.platform?.voiceProviderRegistry?.list?.() ?? [];
|
|
214
|
+
} catch {
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
})();
|
|
218
|
+
const mediaProviders = (() => {
|
|
219
|
+
try {
|
|
220
|
+
return context.platform?.mediaProviderRegistry?.list?.() ?? [];
|
|
221
|
+
} catch {
|
|
222
|
+
return [];
|
|
223
|
+
}
|
|
224
|
+
})();
|
|
225
|
+
return { voiceProviders, mediaProviders };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export function buildAgentWorkspaceMcpServerSnapshot(context: CommandContext) {
|
|
229
|
+
try {
|
|
230
|
+
const servers = context.clients?.mcpApi?.listServerSecurity?.() ?? context.extensions?.mcpRegistry?.listServerSecurity?.() ?? [];
|
|
231
|
+
return {
|
|
232
|
+
serverCount: servers.length,
|
|
233
|
+
connectedCount: servers.filter((server) => server.connected).length,
|
|
234
|
+
quarantinedCount: servers.filter((server) => server.schemaFreshness === 'quarantined').length,
|
|
235
|
+
allowAllCount: servers.filter((server) => server.trustMode === 'allow-all').length,
|
|
236
|
+
};
|
|
237
|
+
} catch {
|
|
238
|
+
return {
|
|
239
|
+
serverCount: 0,
|
|
240
|
+
connectedCount: 0,
|
|
241
|
+
quarantinedCount: 0,
|
|
242
|
+
allowAllCount: 0,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function buildAgentWorkspaceCompanionAccessSnapshot(context: CommandContext, runtimeBaseUrl: string) {
|
|
248
|
+
const homeDirectory = context.workspace?.shellPaths?.homeDirectory ?? '';
|
|
249
|
+
const tokenRecord: ConnectedHostOperatorToken = homeDirectory.length > 0
|
|
250
|
+
? readConnectedHostOperatorToken(homeDirectory)
|
|
251
|
+
: { path: '(Agent home unavailable)', present: false, token: null };
|
|
252
|
+
const tokenFingerprint = tokenRecord.token ? connectedHostOperatorTokenFingerprint(tokenRecord.token) : null;
|
|
253
|
+
const pairingReady = Boolean(tokenRecord.token);
|
|
254
|
+
const nextStep = tokenRecord.error
|
|
255
|
+
? 'Repair the connected-host operator token file through the owning GoodVibes host, then rerun /pair.'
|
|
256
|
+
: pairingReady
|
|
257
|
+
? 'Use /pair to scan the QR code. Manual token display stays hidden unless /pair --show-token --yes is used.'
|
|
258
|
+
: 'Pair or provision connected-host access through the owning GoodVibes host, then rerun /pair.';
|
|
259
|
+
return {
|
|
260
|
+
surface: GOODVIBES_AGENT_PAIRING_SURFACE,
|
|
261
|
+
hostUrl: runtimeBaseUrl,
|
|
262
|
+
tokenPath: tokenRecord.path,
|
|
263
|
+
tokenPresent: tokenRecord.present,
|
|
264
|
+
tokenReadable: Boolean(tokenRecord.token),
|
|
265
|
+
tokenFingerprint,
|
|
266
|
+
tokenError: tokenRecord.error ?? null,
|
|
267
|
+
pairingReady,
|
|
268
|
+
qrCommand: '/pair',
|
|
269
|
+
manualTokenCommand: '/pair --show-token --yes',
|
|
270
|
+
nextStep,
|
|
271
|
+
} as const;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Honest email-connect status for the inbox connect wizard's entry state
|
|
276
|
+
* (W4-A5) — config validation only, no network I/O. Best-effort: never
|
|
277
|
+
* throws, returns null on any read failure.
|
|
278
|
+
*/
|
|
279
|
+
export function buildAgentWorkspaceEmailConnectStatus(context: CommandContext): AgentWorkspaceEmailConnectStatus | null {
|
|
280
|
+
try {
|
|
281
|
+
ensureEmailConfigDefaults(context.platform.configManager);
|
|
282
|
+
const cm = context.platform.configManager as unknown as { get: (key: string) => unknown };
|
|
283
|
+
const config = readEmailConfig((key) => cm.get(key));
|
|
284
|
+
const errors = validateEmailConfig(config);
|
|
285
|
+
return {
|
|
286
|
+
connected: errors.length === 0 && config.enabled,
|
|
287
|
+
username: config.username,
|
|
288
|
+
imapHost: config.imapHost,
|
|
289
|
+
errors,
|
|
290
|
+
};
|
|
291
|
+
} catch {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Honest calendar-OAuth build state per provider for the advanced connect
|
|
298
|
+
* cards (F1c) — config read only, no network I/O. "Configured" means a
|
|
299
|
+
* config-override client id has been stored (through this same card);
|
|
300
|
+
* "not configured" means the build still ships only the bundled SDK
|
|
301
|
+
* placeholder client id, the state in which a bare /calendar connect always
|
|
302
|
+
* fails at the config stage. Best-effort: never throws, returns null on any
|
|
303
|
+
* read failure.
|
|
304
|
+
*/
|
|
305
|
+
export function buildAgentWorkspaceCalendarOAuthConfigStatus(context: CommandContext): AgentWorkspaceCalendarOAuthConfigStatus | null {
|
|
306
|
+
try {
|
|
307
|
+
ensureCalendarConfigDefaults(context.platform.configManager);
|
|
308
|
+
const cm = context.platform.configManager as unknown as { get: (key: string) => unknown };
|
|
309
|
+
const hasClientId = (key: string): boolean => {
|
|
310
|
+
let value: unknown;
|
|
311
|
+
try {
|
|
312
|
+
value = cm.get(key);
|
|
313
|
+
} catch {
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
317
|
+
};
|
|
318
|
+
return {
|
|
319
|
+
google: hasClientId(CALENDAR_OAUTH_CLIENT_ID_KEYS.google),
|
|
320
|
+
microsoft: hasClientId(CALENDAR_OAUTH_CLIENT_ID_KEYS.microsoft),
|
|
321
|
+
};
|
|
322
|
+
} catch {
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export function buildAgentWorkspaceSubscriptionSnapshot(context: CommandContext) {
|
|
328
|
+
try {
|
|
329
|
+
const manager = context.platform?.subscriptionManager;
|
|
330
|
+
const services = context.platform?.serviceRegistry;
|
|
331
|
+
const active = manager?.list?.().length ?? 0;
|
|
332
|
+
const pending = manager?.listPending?.().length ?? 0;
|
|
333
|
+
const available = services ? listAvailableSubscriptionProviders(services.getAll()).length : 0;
|
|
334
|
+
return { active, pending, available };
|
|
335
|
+
} catch {
|
|
336
|
+
return { active: 0, pending: 0, available: 0 };
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export interface AgentWorkspaceConfigSettingsSnapshot {
|
|
341
|
+
readonly ttsProvider: string;
|
|
342
|
+
readonly ttsVoice: string;
|
|
343
|
+
readonly ttsLlmProvider: string;
|
|
344
|
+
readonly ttsLlmModel: string;
|
|
345
|
+
readonly embeddingProvider: string;
|
|
346
|
+
readonly reasoningEffort: string;
|
|
347
|
+
readonly helperEnabled: boolean;
|
|
348
|
+
readonly toolLlmEnabled: boolean;
|
|
349
|
+
readonly providerFailureHints: boolean;
|
|
350
|
+
readonly cacheEnabled: boolean;
|
|
351
|
+
readonly cacheStableTtl: string;
|
|
352
|
+
readonly cacheMonitorHitRate: boolean;
|
|
353
|
+
readonly cacheHitRateWarningThreshold: number;
|
|
354
|
+
readonly hitlMode: string;
|
|
355
|
+
readonly guidanceMode: string;
|
|
356
|
+
readonly saveHistory: boolean;
|
|
357
|
+
readonly autoApprove: boolean;
|
|
358
|
+
readonly autoCompactThreshold: number;
|
|
359
|
+
readonly staleContextWarnings: boolean;
|
|
360
|
+
readonly showThinking: boolean;
|
|
361
|
+
readonly showReasoningSummary: boolean;
|
|
362
|
+
readonly theme: string;
|
|
363
|
+
readonly stream: boolean;
|
|
364
|
+
readonly lineNumbers: string;
|
|
365
|
+
readonly operationalMessages: string;
|
|
366
|
+
readonly systemMessages: string;
|
|
367
|
+
readonly releaseChannel: string;
|
|
368
|
+
readonly permissionMode: string;
|
|
369
|
+
readonly toolAutoHeal: boolean;
|
|
370
|
+
readonly toolsDefaultTokenBudget: number;
|
|
371
|
+
readonly artifactMaxBytes: number;
|
|
372
|
+
readonly rawPromptTelemetry: boolean;
|
|
373
|
+
readonly automationEnabled: boolean;
|
|
374
|
+
readonly automationMaxConcurrentRuns: number;
|
|
375
|
+
readonly automationRunHistoryLimit: number;
|
|
376
|
+
readonly automationDefaultTimeoutMs: number;
|
|
377
|
+
readonly automationCatchUpWindowMinutes: number;
|
|
378
|
+
readonly automationFailureCooldownMs: number;
|
|
379
|
+
readonly automationDeleteAfterRun: boolean;
|
|
380
|
+
readonly browserPwaEnabled: boolean;
|
|
381
|
+
readonly browserPwaPublicBaseUrl: string;
|
|
382
|
+
readonly voiceSurfaceEnabled: boolean;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/** The flat sequence of config reads driving most of the runtime snapshot's settings fields. */
|
|
386
|
+
export function buildAgentWorkspaceConfigSettingsSnapshot(context: CommandContext): AgentWorkspaceConfigSettingsSnapshot {
|
|
387
|
+
return {
|
|
388
|
+
ttsProvider: readConfigString(context, 'tts.provider', '(provider default)'),
|
|
389
|
+
ttsVoice: readConfigString(context, 'tts.voice', '(voice default)'),
|
|
390
|
+
ttsLlmProvider: readConfigString(context, 'tts.llmProvider', ''),
|
|
391
|
+
ttsLlmModel: readConfigString(context, 'tts.llmModel', ''),
|
|
392
|
+
embeddingProvider: readConfigString(context, 'provider.embeddingProvider', '(provider default)'),
|
|
393
|
+
reasoningEffort: readConfigString(context, 'provider.reasoningEffort', '(default)'),
|
|
394
|
+
helperEnabled: readConfigBoolean(context, 'helper.enabled', false),
|
|
395
|
+
toolLlmEnabled: readConfigBoolean(context, 'tools.llmEnabled', false),
|
|
396
|
+
providerFailureHints: readConfigBoolean(context, 'behavior.suggestAlternativeOnProviderFail', false),
|
|
397
|
+
cacheEnabled: readConfigBoolean(context, 'cache.enabled', true),
|
|
398
|
+
cacheStableTtl: readConfigString(context, 'cache.stableTtl', '(default)'),
|
|
399
|
+
cacheMonitorHitRate: readConfigBoolean(context, 'cache.monitorHitRate', true),
|
|
400
|
+
cacheHitRateWarningThreshold: readConfigNumber(context, 'cache.hitRateWarningThreshold', 0.3),
|
|
401
|
+
hitlMode: readConfigString(context, 'behavior.hitlMode', '(default)'),
|
|
402
|
+
guidanceMode: readConfigString(context, 'behavior.guidanceMode', '(default)'),
|
|
403
|
+
saveHistory: readConfigBoolean(context, 'behavior.saveHistory', true),
|
|
404
|
+
autoApprove: readConfigBoolean(context, 'behavior.autoApprove', false),
|
|
405
|
+
autoCompactThreshold: readConfigNumber(context, 'behavior.autoCompactThreshold', 0),
|
|
406
|
+
staleContextWarnings: readConfigBoolean(context, 'behavior.staleContextWarnings', false),
|
|
407
|
+
showThinking: readConfigBoolean(context, 'display.showThinking', false),
|
|
408
|
+
showReasoningSummary: readConfigBoolean(context, 'display.showReasoningSummary', false),
|
|
409
|
+
theme: readConfigString(context, 'display.theme', '(default)'),
|
|
410
|
+
stream: readConfigBoolean(context, 'display.stream', true),
|
|
411
|
+
lineNumbers: readConfigString(context, 'display.lineNumbers', '(default)'),
|
|
412
|
+
operationalMessages: readConfigString(context, 'ui.operationalMessages', '(default)'),
|
|
413
|
+
systemMessages: readConfigString(context, 'ui.systemMessages', '(default)'),
|
|
414
|
+
releaseChannel: readConfigString(context, 'release.channel', '(default)'),
|
|
415
|
+
permissionMode: readConfigString(context, 'permissions.mode', '(default)'),
|
|
416
|
+
toolAutoHeal: readConfigBoolean(context, 'tools.autoHeal', false),
|
|
417
|
+
toolsDefaultTokenBudget: readConfigNumber(context, 'tools.defaultTokenBudget', 5000),
|
|
418
|
+
artifactMaxBytes: readConfigNumber(context, 'storage.artifacts.maxBytes', 512 * 1024 * 1024),
|
|
419
|
+
rawPromptTelemetry: readConfigBoolean(context, 'telemetry.includeRawPrompts', false),
|
|
420
|
+
automationEnabled: readConfigBoolean(context, 'automation.enabled', false),
|
|
421
|
+
automationMaxConcurrentRuns: readConfigNumber(context, 'automation.maxConcurrentRuns', 4),
|
|
422
|
+
automationRunHistoryLimit: readConfigNumber(context, 'automation.runHistoryLimit', 100),
|
|
423
|
+
automationDefaultTimeoutMs: readConfigNumber(context, 'automation.defaultTimeoutMs', 15 * 60 * 1000),
|
|
424
|
+
automationCatchUpWindowMinutes: readConfigNumber(context, 'automation.catchUpWindowMinutes', 30),
|
|
425
|
+
automationFailureCooldownMs: readConfigNumber(context, 'automation.failureCooldownMs', 5 * 60 * 1000),
|
|
426
|
+
automationDeleteAfterRun: readConfigBoolean(context, 'automation.deleteAfterRun', false),
|
|
427
|
+
browserPwaEnabled: readConfigBoolean(context, 'web.enabled', false),
|
|
428
|
+
browserPwaPublicBaseUrl: readConfigString(context, 'web.publicBaseUrl', '(not configured)'),
|
|
429
|
+
voiceSurfaceEnabled: readConfigBoolean(context, 'ui.voiceEnabled', false),
|
|
430
|
+
};
|
|
431
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Small config-read helpers shared by agent-workspace-snapshot.ts and
|
|
2
|
+
// agent-workspace-snapshot-builders.ts (W4-H2 split of the runtime-snapshot giant
|
|
3
|
+
// assembler). Each never throws: config reads fall back to the given default on any
|
|
4
|
+
// error, matching the original inline behavior exactly.
|
|
5
|
+
import type { CommandContext } from './command-registry.ts';
|
|
6
|
+
import { getAgentWorkspaceConfigReader } from './agent-workspace-config-reader.ts';
|
|
7
|
+
|
|
8
|
+
export function readConfigString(context: CommandContext, key: string, fallback: string): string {
|
|
9
|
+
try {
|
|
10
|
+
const configManager = getAgentWorkspaceConfigReader(context);
|
|
11
|
+
const value = configManager?.get(key);
|
|
12
|
+
return typeof value === 'string' && value.trim().length > 0 ? value.trim() : fallback;
|
|
13
|
+
} catch {
|
|
14
|
+
return fallback;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function readConfigNumber(context: CommandContext, key: string, fallback: number): number {
|
|
19
|
+
try {
|
|
20
|
+
const configManager = getAgentWorkspaceConfigReader(context);
|
|
21
|
+
const value = configManager?.get(key);
|
|
22
|
+
const numberValue = typeof value === 'number' ? value : Number(value);
|
|
23
|
+
return Number.isFinite(numberValue) ? numberValue : fallback;
|
|
24
|
+
} catch {
|
|
25
|
+
return fallback;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function readConfigBoolean(context: CommandContext, key: string, fallback: boolean): boolean {
|
|
30
|
+
try {
|
|
31
|
+
const configManager = getAgentWorkspaceConfigReader(context);
|
|
32
|
+
const value = configManager?.get(key);
|
|
33
|
+
if (typeof value === 'boolean') return value;
|
|
34
|
+
if (typeof value === 'string') {
|
|
35
|
+
const normalized = value.trim().toLowerCase();
|
|
36
|
+
if (normalized === 'true') return true;
|
|
37
|
+
if (normalized === 'false') return false;
|
|
38
|
+
}
|
|
39
|
+
return fallback;
|
|
40
|
+
} catch {
|
|
41
|
+
return fallback;
|
|
42
|
+
}
|
|
43
|
+
}
|