@pellux/goodvibes-agent 0.1.117 → 1.0.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 +13 -4
- package/README.md +35 -14
- package/bin/goodvibes-agent.ts +16 -2
- package/dist/package/main.js +176073 -170980
- package/docs/README.md +11 -5
- package/docs/channels-remote-and-api.md +50 -0
- package/docs/connected-host.md +3 -3
- package/docs/getting-started.md +29 -15
- package/docs/knowledge-artifacts-and-multimodal.md +91 -0
- package/docs/project-planning.md +79 -0
- package/docs/providers-and-routing.md +46 -0
- package/docs/release-and-publishing.md +44 -9
- package/docs/tools-and-commands.md +123 -0
- package/docs/voice-and-live-tts.md +51 -0
- package/package.json +2 -5
- package/src/agent/channel-delivery.ts +201 -0
- package/src/agent/media-generation.ts +159 -0
- package/src/agent/memory-prompt.ts +0 -1
- package/src/agent/note-registry.ts +329 -0
- package/src/agent/operator-actions.ts +343 -0
- package/src/agent/persona-registry.ts +15 -14
- package/src/agent/record-labels.ts +107 -0
- package/src/agent/reminder-schedule-format.ts +33 -24
- package/src/agent/reminder-schedule.ts +26 -25
- package/src/agent/routine-registry.ts +13 -12
- package/src/agent/routine-schedule-args.ts +2 -1
- package/src/agent/routine-schedule-format.ts +77 -53
- package/src/agent/routine-schedule-promotion.ts +34 -32
- package/src/agent/routine-schedule-receipts.ts +28 -26
- package/src/agent/runtime-profile-starters.ts +2 -2
- package/src/agent/runtime-profile.ts +18 -17
- package/src/agent/skill-registry.ts +25 -24
- package/src/cli/agent-knowledge-args.ts +5 -1
- package/src/cli/agent-knowledge-command.ts +39 -33
- package/src/cli/agent-knowledge-format.ts +80 -67
- package/src/cli/agent-knowledge-methods.ts +1 -1
- package/src/cli/agent-knowledge-runtime.ts +32 -26
- package/src/cli/bundle-command.ts +13 -8
- package/src/cli/config-overrides.ts +37 -36
- package/src/cli/external-runtime.ts +10 -4
- package/src/cli/help.ts +29 -11
- package/src/cli/local-library-command.ts +134 -68
- package/src/cli/management-commands.ts +98 -62
- package/src/cli/management.ts +52 -26
- package/src/cli/memory-command.ts +66 -32
- package/src/cli/parser.ts +37 -24
- package/src/cli/profiles-command.ts +52 -35
- package/src/cli/provider-auth-routes.ts +2 -1
- package/src/cli/routines-command.ts +44 -36
- package/src/cli/service-posture.ts +6 -6
- package/src/cli/status.ts +46 -121
- package/src/core/conversation-message-snapshot.ts +131 -0
- package/src/input/agent-workspace-activation.ts +33 -7
- package/src/input/agent-workspace-basic-command-editor-submission.ts +7 -3
- package/src/input/agent-workspace-basic-command-editors.ts +30 -10
- package/src/input/agent-workspace-categories.ts +276 -64
- package/src/input/agent-workspace-channel-command-editor-submission.ts +34 -0
- package/src/input/agent-workspace-channel-command-editors.ts +23 -5
- package/src/input/agent-workspace-channels.ts +35 -2
- package/src/input/agent-workspace-command-editor.ts +18 -2
- package/src/input/agent-workspace-config-reader.ts +16 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +1 -1
- package/src/input/agent-workspace-editors.ts +140 -2
- package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
- package/src/input/agent-workspace-learned-behavior.ts +2 -2
- package/src/input/agent-workspace-library-command-editor-submission.ts +1 -1
- package/src/input/agent-workspace-library-command-editors.ts +2 -2
- package/src/input/agent-workspace-local-operations.ts +218 -0
- package/src/input/agent-workspace-local-selection.ts +75 -0
- package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
- package/src/input/agent-workspace-media-command-editors.ts +27 -0
- package/src/input/agent-workspace-memory-command-editors.ts +1 -1
- package/src/input/agent-workspace-memory-editor.ts +2 -2
- package/src/input/agent-workspace-navigation.ts +38 -2
- package/src/input/agent-workspace-notify-editor-submission.ts +16 -2
- package/src/input/agent-workspace-operations-command-editor-submission.ts +63 -1
- package/src/input/agent-workspace-operations-command-editors.ts +80 -3
- package/src/input/agent-workspace-panel-route.ts +43 -0
- package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
- package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
- package/src/input/agent-workspace-search.ts +169 -0
- package/src/input/agent-workspace-setup.ts +22 -11
- package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +6 -6
- package/src/input/agent-workspace-skill-bundle-command-editors.ts +10 -10
- package/src/input/agent-workspace-snapshot.ts +112 -13
- package/src/input/agent-workspace-task-command-editors.ts +4 -4
- package/src/input/agent-workspace-token.ts +18 -2
- package/src/input/agent-workspace-types.ts +92 -4
- package/src/input/agent-workspace-voice-media.ts +3 -6
- package/src/input/agent-workspace-web-research-editor.ts +104 -0
- package/src/input/agent-workspace.ts +136 -208
- package/src/input/command-registry.ts +4 -1
- package/src/input/commands/agent-runtime-profile-runtime.ts +45 -41
- package/src/input/commands/agent-skills-runtime.ts +83 -70
- package/src/input/commands/agent-workspace-runtime.ts +23 -7
- package/src/input/commands/brief-runtime.ts +25 -24
- package/src/input/commands/channels-runtime.ts +145 -31
- package/src/input/commands/delegation-runtime.ts +29 -23
- package/src/input/commands/experience-runtime.ts +6 -4
- package/src/input/commands/guidance-runtime.ts +4 -4
- package/src/input/commands/health-runtime.ts +140 -115
- package/src/input/commands/knowledge.ts +57 -56
- package/src/input/commands/local-provider-runtime.ts +36 -18
- package/src/input/commands/local-runtime.ts +138 -16
- package/src/input/commands/local-setup-review.ts +7 -7
- package/src/input/commands/mcp-runtime.ts +56 -35
- package/src/input/commands/notify-runtime.ts +38 -9
- package/src/input/commands/operator-actions-runtime.ts +138 -0
- package/src/input/commands/operator-runtime.ts +6 -17
- package/src/input/commands/personas-runtime.ts +45 -30
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +29 -29
- package/src/input/commands/provider-accounts-runtime.ts +60 -39
- package/src/input/commands/qrcode-runtime.ts +45 -6
- package/src/input/commands/recall-bundle.ts +11 -11
- package/src/input/commands/recall-capture.ts +13 -11
- package/src/input/commands/recall-query.ts +29 -21
- package/src/input/commands/recall-review.ts +2 -1
- package/src/input/commands/routines-runtime.ts +59 -43
- package/src/input/commands/schedule-runtime.ts +33 -20
- package/src/input/commands/security-runtime.ts +4 -4
- package/src/input/commands/session-content.ts +80 -78
- package/src/input/commands/session-workflow.ts +132 -93
- package/src/input/commands/session.ts +3 -174
- package/src/input/commands/shell-core.ts +32 -17
- package/src/input/commands/subscription-runtime.ts +53 -179
- package/src/input/commands/tasks-runtime.ts +20 -20
- package/src/input/commands/work-plan-runtime.ts +33 -8
- package/src/input/commands.ts +2 -2
- package/src/input/feed-context-factory.ts +2 -1
- package/src/input/file-picker.ts +3 -2
- package/src/input/handler-command-route.ts +4 -7
- package/src/input/handler-content-actions.ts +89 -1
- package/src/input/handler-feed-routes.ts +19 -12
- package/src/input/handler-feed.ts +6 -3
- package/src/input/handler-interactions.ts +7 -5
- package/src/input/handler-modal-stack.ts +3 -3
- package/src/input/handler-onboarding.ts +24 -80
- package/src/input/handler-shortcuts.ts +15 -4
- package/src/input/handler.ts +47 -17
- package/src/input/input-history.ts +5 -6
- package/src/input/keybindings.ts +22 -11
- package/src/input/onboarding/onboarding-wizard-apply.ts +13 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +147 -57
- package/src/input/onboarding/onboarding-wizard-steps.ts +46 -29
- package/src/input/onboarding/onboarding-wizard-types.ts +3 -1
- package/src/input/onboarding/onboarding-wizard.ts +68 -0
- package/src/input/profile-picker-modal.ts +31 -12
- package/src/input/session-picker-modal.ts +21 -4
- package/src/input/settings-modal-behavior.ts +0 -3
- package/src/input/settings-modal-subscriptions.ts +3 -3
- package/src/input/settings-modal-types.ts +2 -13
- package/src/input/settings-modal.ts +6 -52
- package/src/input/submission-intent.ts +0 -1
- package/src/input/submission-router.ts +3 -3
- package/src/main.ts +18 -8
- package/src/panels/approval-panel.ts +8 -8
- package/src/panels/automation-control-panel.ts +2 -2
- package/src/panels/base-panel.ts +1 -1
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +1 -10
- package/src/panels/builtin/session.ts +9 -9
- package/src/panels/builtin/shared.ts +2 -2
- package/src/panels/cost-tracker-panel.ts +1 -1
- package/src/panels/docs-panel.ts +5 -3
- package/src/panels/index.ts +0 -1
- package/src/panels/knowledge-panel.ts +6 -5
- package/src/panels/memory-panel.ts +7 -6
- package/src/panels/panel-list-panel.ts +36 -80
- package/src/panels/project-planning-panel.ts +18 -11
- package/src/panels/provider-account-snapshot.ts +51 -25
- package/src/panels/provider-accounts-panel.ts +33 -18
- package/src/panels/provider-health-domains.ts +45 -4
- package/src/panels/provider-health-panel.ts +5 -4
- package/src/panels/qr-panel.ts +1 -1
- package/src/panels/schedule-panel.ts +9 -17
- package/src/panels/security-panel.ts +8 -8
- package/src/panels/session-browser-panel.ts +10 -10
- package/src/panels/subscription-panel.ts +3 -3
- package/src/panels/system-messages-panel.ts +1 -1
- package/src/panels/tasks-panel.ts +20 -13
- package/src/panels/tool-inspector-panel.ts +19 -12
- package/src/panels/work-plan-panel.ts +5 -5
- package/src/planning/project-planning-coordinator.ts +1 -1
- package/src/provider-auth-route-display.ts +9 -0
- package/src/renderer/agent-workspace-style.ts +34 -0
- package/src/renderer/agent-workspace.ts +228 -52
- package/src/renderer/autocomplete-overlay.ts +25 -6
- package/src/renderer/bookmark-modal.ts +19 -4
- package/src/renderer/buffer.ts +4 -2
- package/src/renderer/context-inspector.ts +50 -13
- package/src/renderer/diff.ts +1 -1
- package/src/renderer/file-picker-overlay.ts +19 -6
- package/src/renderer/help-overlay.ts +106 -33
- package/src/renderer/history-search-overlay.ts +19 -4
- package/src/renderer/live-tail-modal.ts +27 -5
- package/src/renderer/mcp-workspace.ts +164 -50
- package/src/renderer/model-picker-overlay.ts +58 -2
- package/src/renderer/model-workspace.ts +104 -20
- package/src/renderer/process-modal.ts +27 -6
- package/src/renderer/profile-picker-modal.ts +20 -4
- package/src/renderer/search-overlay.ts +25 -5
- package/src/renderer/selection-modal-overlay.ts +46 -14
- package/src/renderer/session-picker-modal.ts +18 -1
- package/src/renderer/settings-modal-helpers.ts +2 -40
- package/src/renderer/settings-modal.ts +83 -50
- package/src/renderer/tool-call.ts +20 -11
- package/src/runtime/agent-runtime-events.ts +6 -6
- package/src/runtime/bootstrap-command-context.ts +7 -1
- package/src/runtime/bootstrap-command-parts.ts +9 -7
- package/src/runtime/bootstrap-core.ts +19 -1
- package/src/runtime/bootstrap-hook-bridge.ts +7 -18
- package/src/runtime/bootstrap-shell.ts +4 -4
- package/src/runtime/bootstrap.ts +31 -22
- package/src/runtime/connected-host-auth.ts +7 -2
- package/src/runtime/diagnostics/panels/index.ts +2 -2
- package/src/runtime/diagnostics/panels/policy.ts +7 -7
- package/src/runtime/index.ts +2 -1
- package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
- package/src/runtime/onboarding/apply.ts +80 -79
- package/src/runtime/onboarding/derivation.ts +5 -8
- package/src/runtime/onboarding/snapshot.ts +0 -15
- package/src/runtime/onboarding/types.ts +8 -19
- package/src/runtime/onboarding/verify.ts +32 -10
- package/src/runtime/operator-token-cleanup.ts +1 -1
- package/src/runtime/services.ts +91 -22
- package/src/runtime/store/selectors/index.ts +3 -3
- package/src/runtime/store/state.ts +1 -4
- package/src/runtime/surface-feature-flags.ts +41 -6
- package/src/runtime/ui-read-models.ts +3 -4
- package/src/runtime/ui-services.ts +6 -6
- package/src/shell/blocking-input.ts +2 -1
- package/src/shell/ui-openers.ts +3 -13
- package/src/tools/agent-analysis-registry-policy.ts +0 -1
- package/src/tools/agent-channel-send-tool.ts +133 -0
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
- package/src/tools/agent-knowledge-tool.ts +170 -0
- package/src/tools/agent-local-registry-tool.ts +269 -69
- package/src/tools/agent-media-generate-tool.ts +133 -0
- package/src/tools/agent-notify-tool.ts +143 -0
- package/src/tools/agent-operator-action-tool.ts +137 -0
- package/src/tools/agent-operator-briefing-tool.ts +217 -0
- package/src/tools/agent-reminder-schedule-tool.ts +237 -0
- package/src/tools/agent-tool-policy-guard.ts +8 -8
- package/src/tools/agent-work-plan-tool.ts +256 -0
- package/src/version.ts +1 -1
- package/src/input/commands/policy-dispatch.ts +0 -339
- package/src/input/commands/policy.ts +0 -13
- package/src/panels/panel-picker.ts +0 -105
- package/src/panels/policy-panel.ts +0 -308
- package/src/renderer/panel-picker-overlay.ts +0 -202
|
@@ -12,10 +12,14 @@ type KnowledgeAskInput = Parameters<KnowledgeService['ask']>[0];
|
|
|
12
12
|
type KnowledgeAskResult = Awaited<ReturnType<KnowledgeService['ask']>>;
|
|
13
13
|
type KnowledgeAskMode = NonNullable<KnowledgeAskInput['mode']>;
|
|
14
14
|
|
|
15
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
16
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
17
|
+
}
|
|
18
|
+
|
|
15
19
|
function requireAgentKnowledgeApi(context: CommandContext) {
|
|
16
20
|
const knowledgeApi = context.clients?.agentKnowledgeApi;
|
|
17
21
|
if (!knowledgeApi) {
|
|
18
|
-
context.print('[knowledge] Agent Knowledge API is not available in this runtime. Refusing to use default
|
|
22
|
+
context.print('[knowledge] Agent Knowledge API is not available in this runtime. Refusing to use default knowledge or non-Agent knowledge fallback.');
|
|
19
23
|
return null;
|
|
20
24
|
}
|
|
21
25
|
return knowledgeApi;
|
|
@@ -48,7 +52,7 @@ function findDisallowedKnowledgeScopeFlag(args: readonly string[]): string | nul
|
|
|
48
52
|
function printScopeFlagRejection(context: CommandContext, flag: string): void {
|
|
49
53
|
context.print([
|
|
50
54
|
`[knowledge] Agent Knowledge is isolated; ${flag} is not accepted.`,
|
|
51
|
-
'[knowledge] GoodVibes Agent must not use default
|
|
55
|
+
'[knowledge] GoodVibes Agent must not use default knowledge or non-Agent product spaces.',
|
|
52
56
|
'[knowledge] Use only /api/goodvibes-agent/knowledge/* Agent-owned routes.',
|
|
53
57
|
].join('\n'));
|
|
54
58
|
}
|
|
@@ -110,10 +114,7 @@ function readJsonObjectFlag(args: string[], name: string): Record<string, unknow
|
|
|
110
114
|
if (!value) return undefined;
|
|
111
115
|
try {
|
|
112
116
|
const parsed = JSON.parse(value) as unknown;
|
|
113
|
-
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
return parsed as Record<string, unknown>;
|
|
117
|
+
return isRecord(parsed) ? parsed : null;
|
|
117
118
|
} catch {
|
|
118
119
|
return null;
|
|
119
120
|
}
|
|
@@ -131,7 +132,7 @@ function requireAgentKnowledgeAsk(context: CommandContext): ((input: KnowledgeAs
|
|
|
131
132
|
const serviceAsk = context.extensions.agentKnowledgeService?.ask?.bind(context.extensions.agentKnowledgeService);
|
|
132
133
|
if (serviceAsk) return serviceAsk;
|
|
133
134
|
|
|
134
|
-
context.print('[knowledge] Agent Knowledge ask is not available in this runtime. Refusing to use default
|
|
135
|
+
context.print('[knowledge] Agent Knowledge ask is not available in this runtime. Refusing to use default knowledge or non-Agent knowledge fallback.');
|
|
135
136
|
return null;
|
|
136
137
|
}
|
|
137
138
|
|
|
@@ -144,7 +145,7 @@ function formatKnowledgeMap(result: KnowledgeMapResult): string {
|
|
|
144
145
|
'Agent Knowledge map',
|
|
145
146
|
` nodes: ${result.nodeCount}${result.totalNodeCount !== undefined && result.totalNodeCount !== result.nodeCount ? ` of ${result.totalNodeCount}` : ''}`,
|
|
146
147
|
` edges: ${result.edgeCount}${result.totalEdgeCount !== undefined && result.totalEdgeCount !== result.edgeCount ? ` of ${result.totalEdgeCount}` : ''}`,
|
|
147
|
-
' route
|
|
148
|
+
' route /api/goodvibes-agent/knowledge/map',
|
|
148
149
|
].join('\n');
|
|
149
150
|
}
|
|
150
151
|
|
|
@@ -152,7 +153,7 @@ function nodeLabel(node: { readonly kind?: string; readonly title?: string; read
|
|
|
152
153
|
const kind = cleanInline(node.kind) || 'node';
|
|
153
154
|
const title = cleanInline(node.title) || 'untitled';
|
|
154
155
|
const summary = cleanInline(node.summary);
|
|
155
|
-
const confidence = typeof node.confidence === 'number' ? `
|
|
156
|
+
const confidence = typeof node.confidence === 'number' ? ` confidence ${node.confidence}` : '';
|
|
156
157
|
return summary ? `[${kind}] ${title}${confidence} - ${summary}` : `[${kind}] ${title}${confidence}`;
|
|
157
158
|
}
|
|
158
159
|
|
|
@@ -179,7 +180,7 @@ function renderKnowledgeAskResult(result: KnowledgeAskResult): string {
|
|
|
179
180
|
`[knowledge] ${result.query}`,
|
|
180
181
|
answer.text,
|
|
181
182
|
'',
|
|
182
|
-
`mode
|
|
183
|
+
`mode ${answer.mode} confidence ${answer.confidence} synthesized ${answer.synthesized ? 'yes' : 'no'}`,
|
|
183
184
|
];
|
|
184
185
|
|
|
185
186
|
if (answer.sources.length > 0) {
|
|
@@ -208,7 +209,7 @@ function renderKnowledgeAskResult(result: KnowledgeAskResult): string {
|
|
|
208
209
|
export const knowledgeCommand: SlashCommand = {
|
|
209
210
|
name: 'knowledge',
|
|
210
211
|
aliases: ['know', 'kb'],
|
|
211
|
-
description: 'Agent Knowledge
|
|
212
|
+
description: 'Agent Knowledge: isolated Agent-owned sources, graph, review queue, and compact prompt packets.',
|
|
212
213
|
usage: '<subcommand> [args]',
|
|
213
214
|
argsHint: 'status|ask|ingest-url --yes|ingest-file --yes|import-bookmarks --yes|list|search|get|queue|review-issue --yes',
|
|
214
215
|
handler: async (args: string[], context: CommandContext): Promise<void> => {
|
|
@@ -330,9 +331,9 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
330
331
|
return;
|
|
331
332
|
}
|
|
332
333
|
const result = await knowledge.ingest.bookmarksFile({ path, sessionId: context.session.runtime.sessionId });
|
|
333
|
-
context.print(`[knowledge] Imported bookmarks
|
|
334
|
+
context.print(`[knowledge] Imported bookmarks ${result.imported} ok, ${result.failed} failed`);
|
|
334
335
|
if (result.errors.length > 0) {
|
|
335
|
-
for (const error of result.errors.slice(0, 10)) context.print(` error
|
|
336
|
+
for (const error of result.errors.slice(0, 10)) context.print(` error ${error}`);
|
|
336
337
|
}
|
|
337
338
|
break;
|
|
338
339
|
}
|
|
@@ -348,9 +349,9 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
348
349
|
return;
|
|
349
350
|
}
|
|
350
351
|
const result = await knowledge.ingest.urlsFile({ path, sessionId: context.session.runtime.sessionId });
|
|
351
|
-
context.print(`[knowledge] Imported URL list
|
|
352
|
+
context.print(`[knowledge] Imported URL list ${result.imported} ok, ${result.failed} failed`);
|
|
352
353
|
if (result.errors.length > 0) {
|
|
353
|
-
for (const error of result.errors.slice(0, 10)) context.print(` error
|
|
354
|
+
for (const error of result.errors.slice(0, 10)) context.print(` error ${error}`);
|
|
354
355
|
}
|
|
355
356
|
break;
|
|
356
357
|
}
|
|
@@ -371,9 +372,9 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
371
372
|
sessionId: context.session.runtime.sessionId,
|
|
372
373
|
});
|
|
373
374
|
context.print(`[knowledge] Imported browser knowledge: ${result.imported} ok, ${result.failed} failed`);
|
|
374
|
-
if (result.profiles.length > 0) context.print(` profiles
|
|
375
|
+
if (result.profiles.length > 0) context.print(` profiles ${result.profiles.length}`);
|
|
375
376
|
if (result.errors.length > 0) {
|
|
376
|
-
for (const error of result.errors.slice(0, 10)) context.print(` error
|
|
377
|
+
for (const error of result.errors.slice(0, 10)) context.print(` error ${error}`);
|
|
377
378
|
}
|
|
378
379
|
break;
|
|
379
380
|
}
|
|
@@ -405,7 +406,7 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
405
406
|
});
|
|
406
407
|
context.print(`[knowledge] Imported connector input: ${result.imported} ok, ${result.failed} failed`);
|
|
407
408
|
if (result.errors.length > 0) {
|
|
408
|
-
for (const error of result.errors.slice(0, 10)) context.print(` error
|
|
409
|
+
for (const error of result.errors.slice(0, 10)) context.print(` error ${error}`);
|
|
409
410
|
}
|
|
410
411
|
break;
|
|
411
412
|
}
|
|
@@ -419,7 +420,7 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
419
420
|
context.print('[knowledge] No nodes.');
|
|
420
421
|
return;
|
|
421
422
|
}
|
|
422
|
-
context.print(`[knowledge] ${nodes.length} node(s)
|
|
423
|
+
context.print(`[knowledge] ${nodes.length} node(s)`);
|
|
423
424
|
for (const node of nodes) {
|
|
424
425
|
context.print(` ${node.id} [${node.kind}] ${node.title}`);
|
|
425
426
|
if (node.summary) context.print(` ${node.summary}`);
|
|
@@ -432,7 +433,7 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
432
433
|
context.print('[knowledge] No issues.');
|
|
433
434
|
return;
|
|
434
435
|
}
|
|
435
|
-
context.print(`[knowledge] ${issues.length} issue(s)
|
|
436
|
+
context.print(`[knowledge] ${issues.length} issue(s)`);
|
|
436
437
|
for (const issue of issues) {
|
|
437
438
|
context.print(` ${issue.id} [${issue.severity}] ${issue.code}`);
|
|
438
439
|
context.print(` ${issue.message}`);
|
|
@@ -444,7 +445,7 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
444
445
|
context.print('[knowledge] No sources.');
|
|
445
446
|
return;
|
|
446
447
|
}
|
|
447
|
-
context.print(`[knowledge] ${sources.length} source(s)
|
|
448
|
+
context.print(`[knowledge] ${sources.length} source(s)`);
|
|
448
449
|
for (const source of sources) {
|
|
449
450
|
context.print(` ${source.id} [${source.sourceType}/${source.status}] ${source.title ?? source.canonicalUri ?? source.sourceUri ?? 'untitled'}`);
|
|
450
451
|
if (source.summary) context.print(` ${source.summary}`);
|
|
@@ -465,10 +466,10 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
465
466
|
context.print('[knowledge] No results.');
|
|
466
467
|
return;
|
|
467
468
|
}
|
|
468
|
-
context.print(`[knowledge] ${results.length} result(s)
|
|
469
|
+
context.print(`[knowledge] ${results.length} result(s)`);
|
|
469
470
|
for (const result of results) {
|
|
470
471
|
const title = result.source?.title ?? result.source?.canonicalUri ?? result.node?.title ?? result.id;
|
|
471
|
-
context.print(` ${result.id} [${result.kind}] score
|
|
472
|
+
context.print(` ${result.id} [${result.kind}] score ${result.score} ${title}`);
|
|
472
473
|
context.print(` ${result.reason}`);
|
|
473
474
|
}
|
|
474
475
|
break;
|
|
@@ -482,28 +483,28 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
482
483
|
}
|
|
483
484
|
const item = knowledge.graph.items.get(id);
|
|
484
485
|
if (!item) {
|
|
485
|
-
context.print(`[knowledge] Unknown item
|
|
486
|
+
context.print(`[knowledge] Unknown item ${id}`);
|
|
486
487
|
return;
|
|
487
488
|
}
|
|
488
489
|
if (item.source) {
|
|
489
490
|
context.print(`[knowledge] source ${item.source.id}`);
|
|
490
|
-
context.print(` title
|
|
491
|
-
context.print(` uri
|
|
492
|
-
context.print(` status
|
|
493
|
-
if (item.source.summary) context.print(` summary
|
|
491
|
+
context.print(` title ${item.source.title ?? 'untitled'}`);
|
|
492
|
+
context.print(` uri ${item.source.canonicalUri ?? item.source.sourceUri ?? 'n/a'}`);
|
|
493
|
+
context.print(` status ${item.source.status}`);
|
|
494
|
+
if (item.source.summary) context.print(` summary ${item.source.summary}`);
|
|
494
495
|
} else if (item.node) {
|
|
495
496
|
context.print(`[knowledge] node ${item.node.id}`);
|
|
496
|
-
context.print(`
|
|
497
|
-
context.print(` title
|
|
498
|
-
if (item.node.summary) context.print(` summary
|
|
497
|
+
context.print(` type ${item.node.kind}`);
|
|
498
|
+
context.print(` title ${item.node.title}`);
|
|
499
|
+
if (item.node.summary) context.print(` summary ${item.node.summary}`);
|
|
499
500
|
} else if (item.issue) {
|
|
500
501
|
context.print(`[knowledge] issue ${item.issue.id}`);
|
|
501
|
-
context.print(` severity
|
|
502
|
-
context.print(` code
|
|
503
|
-
context.print(` message
|
|
502
|
+
context.print(` severity ${item.issue.severity}`);
|
|
503
|
+
context.print(` code ${item.issue.code}`);
|
|
504
|
+
context.print(` message ${item.issue.message}`);
|
|
504
505
|
}
|
|
505
506
|
if (item.relatedEdges.length > 0) {
|
|
506
|
-
context.print(' relations
|
|
507
|
+
context.print(' relations');
|
|
507
508
|
for (const edge of item.relatedEdges.slice(0, 12)) {
|
|
508
509
|
context.print(` ${edge.fromKind}:${edge.fromId} -[${edge.relation}]-> ${edge.toKind}:${edge.toId}`);
|
|
509
510
|
}
|
|
@@ -528,7 +529,7 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
528
529
|
context.print('[knowledge] No lint issues.');
|
|
529
530
|
return;
|
|
530
531
|
}
|
|
531
|
-
context.print(`[knowledge] ${issues.length} lint issue(s)
|
|
532
|
+
context.print(`[knowledge] ${issues.length} lint issue(s)`);
|
|
532
533
|
for (const issue of issues) {
|
|
533
534
|
context.print(` ${issue.id} [${issue.severity}] ${issue.code}`);
|
|
534
535
|
context.print(` ${issue.message}`);
|
|
@@ -544,7 +545,7 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
544
545
|
context.print('Knowledge review queue is empty.');
|
|
545
546
|
return;
|
|
546
547
|
}
|
|
547
|
-
context.print(`[knowledge] Review queue (${issues.length})
|
|
548
|
+
context.print(`[knowledge] Review queue (${issues.length})`);
|
|
548
549
|
for (const issue of issues) {
|
|
549
550
|
context.print(` ${issue.id} [${issue.severity}] ${issue.code}`);
|
|
550
551
|
context.print(` ${issue.message}`);
|
|
@@ -578,11 +579,11 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
578
579
|
});
|
|
579
580
|
context.print([
|
|
580
581
|
`[knowledge] Reviewed issue ${result.issue.id}`,
|
|
581
|
-
` action
|
|
582
|
-
` status
|
|
583
|
-
...(result.node ? [` node
|
|
584
|
-
...(result.source ? [` source
|
|
585
|
-
...(result.appliedFacts ? [` applied facts
|
|
582
|
+
` action ${action}`,
|
|
583
|
+
` status ${result.issue.status}`,
|
|
584
|
+
...(result.node ? [` node ${result.node.id} ${result.node.title}`] : []),
|
|
585
|
+
...(result.source ? [` knowledge source ${result.source.id} ${result.source.title ?? result.source.canonicalUri ?? result.source.sourceUri ?? 'untitled'}`] : []),
|
|
586
|
+
...(result.appliedFacts ? [` applied facts ${Object.keys(result.appliedFacts).join(', ') || 'none'}`] : []),
|
|
586
587
|
].join('\n'));
|
|
587
588
|
} catch (error) {
|
|
588
589
|
context.print(`[knowledge] ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -598,9 +599,9 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
598
599
|
context.print('[knowledge] No consolidation candidates.');
|
|
599
600
|
return;
|
|
600
601
|
}
|
|
601
|
-
context.print(`[knowledge] Consolidation candidates (${candidates.length})
|
|
602
|
+
context.print(`[knowledge] Consolidation candidates (${candidates.length})`);
|
|
602
603
|
for (const candidate of candidates) {
|
|
603
|
-
context.print(` ${candidate.id} [${candidate.status}] score
|
|
604
|
+
context.print(` ${candidate.id} [${candidate.status}] score ${candidate.score} ${candidate.title}`);
|
|
604
605
|
context.print(` ${candidate.candidateType}`);
|
|
605
606
|
}
|
|
606
607
|
break;
|
|
@@ -615,7 +616,7 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
615
616
|
}
|
|
616
617
|
const report = await knowledge.connectors.doctor(second);
|
|
617
618
|
if (!report) {
|
|
618
|
-
context.print(`[knowledge] Connector doctor report unavailable
|
|
619
|
+
context.print(`[knowledge] Connector doctor report unavailable ${second}`);
|
|
619
620
|
return;
|
|
620
621
|
}
|
|
621
622
|
context.print([
|
|
@@ -630,14 +631,14 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
630
631
|
if (first) {
|
|
631
632
|
const connector = knowledge.connectors.get(first);
|
|
632
633
|
if (!connector) {
|
|
633
|
-
context.print(`[knowledge] Unknown connector
|
|
634
|
+
context.print(`[knowledge] Unknown connector ${first}`);
|
|
634
635
|
return;
|
|
635
636
|
}
|
|
636
637
|
context.print([
|
|
637
638
|
`[knowledge] Connector ${connector.id}`,
|
|
638
|
-
` name
|
|
639
|
-
`
|
|
640
|
-
` description
|
|
639
|
+
` name ${connector.displayName ?? connector.id}`,
|
|
640
|
+
` source type ${connector.sourceType}`,
|
|
641
|
+
` description ${connector.description}`,
|
|
641
642
|
` capabilities: ${connector.capabilities?.join(', ') || 'none'}`,
|
|
642
643
|
].join('\n'));
|
|
643
644
|
return;
|
|
@@ -647,7 +648,7 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
647
648
|
context.print('[knowledge] No connectors.');
|
|
648
649
|
return;
|
|
649
650
|
}
|
|
650
|
-
context.print(`[knowledge] Connectors (${connectors.length})
|
|
651
|
+
context.print(`[knowledge] Connectors (${connectors.length})`);
|
|
651
652
|
for (const connector of connectors) {
|
|
652
653
|
context.print(` ${connector.id} [${connector.sourceType}] ${connector.displayName ?? connector.id}`);
|
|
653
654
|
context.print(` ${connector.description}`);
|
|
@@ -663,7 +664,7 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
663
664
|
context.print('[knowledge] No consolidation reports.');
|
|
664
665
|
return;
|
|
665
666
|
}
|
|
666
|
-
context.print(`[knowledge] Consolidation reports (${reports.length})
|
|
667
|
+
context.print(`[knowledge] Consolidation reports (${reports.length})`);
|
|
667
668
|
for (const report of reports) {
|
|
668
669
|
context.print(` ${report.id} [${report.kind}] ${report.title}`);
|
|
669
670
|
context.print(` ${report.summary}`);
|
|
@@ -677,7 +678,7 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
677
678
|
context.print('[knowledge] No knowledge schedules.');
|
|
678
679
|
return;
|
|
679
680
|
}
|
|
680
|
-
context.print(`[knowledge] Managed schedules (${schedules.length})
|
|
681
|
+
context.print(`[knowledge] Managed schedules (${schedules.length})`);
|
|
681
682
|
for (const schedule of schedules) {
|
|
682
683
|
context.print(` ${schedule.id} [${schedule.enabled ? 'enabled' : 'disabled'}] ${schedule.jobId}`);
|
|
683
684
|
context.print(` ${schedule.label}`);
|
|
@@ -729,10 +730,10 @@ export const knowledgeCommand: SlashCommand = {
|
|
|
729
730
|
const result = await knowledge.status.reindex();
|
|
730
731
|
context.print([
|
|
731
732
|
'[knowledge] Reindex complete',
|
|
732
|
-
` sources
|
|
733
|
-
` nodes
|
|
734
|
-
` edges
|
|
735
|
-
` issues
|
|
733
|
+
` sources ${result.status.sourceCount}`,
|
|
734
|
+
` nodes ${result.status.nodeCount}`,
|
|
735
|
+
` edges ${result.status.edgeCount}`,
|
|
736
|
+
` issues ${result.status.issueCount}`,
|
|
736
737
|
].join('\n'));
|
|
737
738
|
break;
|
|
738
739
|
}
|
|
@@ -13,6 +13,14 @@ function isValidProviderName(name: string): boolean {
|
|
|
13
13
|
return /^[a-zA-Z0-9_-]+$/.test(name);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
function readDiscoveredModelIds(body: unknown): string[] {
|
|
17
|
+
if (!body || typeof body !== 'object' || !('data' in body) || !Array.isArray(body.data)) return [];
|
|
18
|
+
return body.data
|
|
19
|
+
.filter((model): model is { readonly id: unknown } => Boolean(model) && typeof model === 'object' && 'id' in model)
|
|
20
|
+
.map((model) => String(model.id))
|
|
21
|
+
.filter(Boolean);
|
|
22
|
+
}
|
|
23
|
+
|
|
16
24
|
export function registerLocalProviderRuntimeCommands(registry: CommandRegistry): void {
|
|
17
25
|
registry.register({
|
|
18
26
|
name: 'provider',
|
|
@@ -36,20 +44,26 @@ export function registerLocalProviderRuntimeCommands(registry: CommandRegistry):
|
|
|
36
44
|
return;
|
|
37
45
|
}
|
|
38
46
|
if (!isValidProviderName(name)) {
|
|
39
|
-
ctx.print(
|
|
47
|
+
ctx.print([
|
|
48
|
+
'Error',
|
|
49
|
+
' message Provider name must contain only letters, numbers, hyphens, and underscores.',
|
|
50
|
+
].join('\n'));
|
|
40
51
|
return;
|
|
41
52
|
}
|
|
42
53
|
let parsedUrl: URL;
|
|
43
54
|
try {
|
|
44
55
|
parsedUrl = new URL(baseURL);
|
|
45
56
|
} catch {
|
|
46
|
-
ctx.print(
|
|
57
|
+
ctx.print([
|
|
58
|
+
'Error',
|
|
59
|
+
` message ${baseURL} is not a valid URL. Example http://192.168.0.85:8001/v1`,
|
|
60
|
+
].join('\n'));
|
|
47
61
|
return;
|
|
48
62
|
}
|
|
49
63
|
const providersDir = shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, 'providers');
|
|
50
64
|
const providerFile = join(providersDir, `${name}.json`);
|
|
51
65
|
if (existsSync(providerFile)) {
|
|
52
|
-
ctx.print(`
|
|
66
|
+
ctx.print(`Provider ${name} already exists at ${providerFile}\nRemove it first with /provider remove ${name} --yes`);
|
|
53
67
|
return;
|
|
54
68
|
}
|
|
55
69
|
|
|
@@ -64,12 +78,7 @@ export function registerLocalProviderRuntimeCommands(registry: CommandRegistry):
|
|
|
64
78
|
clearTimeout(timeoutId);
|
|
65
79
|
if (res.ok) {
|
|
66
80
|
const body = await res.json() as unknown;
|
|
67
|
-
|
|
68
|
-
discoveredModelIds = ((body as { data: unknown[] }).data)
|
|
69
|
-
.filter((m): m is Record<string, unknown> => typeof m === 'object' && m !== null && 'id' in m)
|
|
70
|
-
.map((m) => String(m.id))
|
|
71
|
-
.filter(Boolean);
|
|
72
|
-
}
|
|
81
|
+
discoveredModelIds = readDiscoveredModelIds(body);
|
|
73
82
|
}
|
|
74
83
|
} catch {
|
|
75
84
|
ctx.print(`Could not reach ${baseURL}/models — creating provider with a minimal starter config.`);
|
|
@@ -111,10 +120,10 @@ export function registerLocalProviderRuntimeCommands(registry: CommandRegistry):
|
|
|
111
120
|
mkdirSync(providersDir, { recursive: true });
|
|
112
121
|
await writeFile(providerFile, JSON.stringify(config, null, 2), 'utf-8');
|
|
113
122
|
} catch (e) {
|
|
114
|
-
ctx.print(`Error writing provider file
|
|
123
|
+
ctx.print(`Error writing provider file ${summarizeError(e)}`);
|
|
115
124
|
return;
|
|
116
125
|
}
|
|
117
|
-
ctx.print(`Provider
|
|
126
|
+
ctx.print(`Provider ${name} added with ${models.length} model(s)\n${discoveredModelIds.length > 0 ? discoveredModelIds.map((id) => ` • ${id} (${(contextWindows[id] ?? 8192).toLocaleString()} ctx)`).join('\n') : ` • ${defaultModel} (starter entry)`}\nThe file watcher will auto-register it shortly.`);
|
|
118
127
|
return;
|
|
119
128
|
}
|
|
120
129
|
|
|
@@ -129,19 +138,22 @@ export function registerLocalProviderRuntimeCommands(registry: CommandRegistry):
|
|
|
129
138
|
return;
|
|
130
139
|
}
|
|
131
140
|
if (!isValidProviderName(name)) {
|
|
132
|
-
ctx.print(
|
|
141
|
+
ctx.print([
|
|
142
|
+
'Error',
|
|
143
|
+
' message Provider name must contain only letters, numbers, hyphens, and underscores.',
|
|
144
|
+
].join('\n'));
|
|
133
145
|
return;
|
|
134
146
|
}
|
|
135
147
|
const providerFile = shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, 'providers', `${name}.json`);
|
|
136
148
|
if (!existsSync(providerFile)) {
|
|
137
|
-
ctx.print(`
|
|
149
|
+
ctx.print(`No custom provider ${name} found at ${providerFile}`);
|
|
138
150
|
return;
|
|
139
151
|
}
|
|
140
152
|
try {
|
|
141
153
|
await unlink(providerFile);
|
|
142
|
-
ctx.print(`Provider
|
|
154
|
+
ctx.print(`Provider ${name} removed. The file watcher will deregister it shortly.`);
|
|
143
155
|
} catch (e) {
|
|
144
|
-
ctx.print(`Error removing provider file
|
|
156
|
+
ctx.print(`Error removing provider file ${summarizeError(e)}`);
|
|
145
157
|
}
|
|
146
158
|
return;
|
|
147
159
|
}
|
|
@@ -152,7 +164,7 @@ export function registerLocalProviderRuntimeCommands(registry: CommandRegistry):
|
|
|
152
164
|
return;
|
|
153
165
|
}
|
|
154
166
|
const providers = requireProviderApi(ctx).listProviderIds();
|
|
155
|
-
ctx.print(['Available providers
|
|
167
|
+
ctx.print(['Available providers', ...providers.map((provider) => ` ${provider === ctx.session.runtime.provider ? '▶' : ' '} ${provider}`)].join('\n'));
|
|
156
168
|
return;
|
|
157
169
|
}
|
|
158
170
|
|
|
@@ -165,7 +177,10 @@ export function registerLocalProviderRuntimeCommands(registry: CommandRegistry):
|
|
|
165
177
|
});
|
|
166
178
|
const match = selectable[0];
|
|
167
179
|
if (!match) {
|
|
168
|
-
ctx.print(
|
|
180
|
+
ctx.print([
|
|
181
|
+
`Unknown provider ${providerName}`,
|
|
182
|
+
`available providers ${providerApi.listProviderIds().join(', ')}`,
|
|
183
|
+
].join('\n'));
|
|
169
184
|
return;
|
|
170
185
|
}
|
|
171
186
|
try {
|
|
@@ -178,7 +193,10 @@ export function registerLocalProviderRuntimeCommands(registry: CommandRegistry):
|
|
|
178
193
|
ctx.platform.configManager.set('provider.model', selected.registryKey);
|
|
179
194
|
ctx.print(`Switched to provider: ${selected.providerId} (model: ${selected.modelId})`);
|
|
180
195
|
} catch (e) {
|
|
181
|
-
ctx.print(
|
|
196
|
+
ctx.print([
|
|
197
|
+
'Error',
|
|
198
|
+
` message ${summarizeError(e)}`,
|
|
199
|
+
].join('\n'));
|
|
182
200
|
}
|
|
183
201
|
},
|
|
184
202
|
});
|