@pellux/goodvibes-agent 0.1.117 → 1.0.1
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 +20 -4
- package/README.md +35 -14
- package/bin/goodvibes-agent.ts +16 -2
- package/dist/package/main.js +176093 -171065
- 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 +159 -73
- 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 +59 -39
- 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-knowledge-url-editor.ts +4 -11
- 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-local-library-args.ts +52 -0
- package/src/input/commands/agent-runtime-profile-runtime.ts +45 -41
- package/src/input/commands/agent-skills-runtime.ts +87 -99
- 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 +118 -50
- 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 +49 -59
- 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 +63 -72
- 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 +22 -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
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import type { Tool } from '@pellux/goodvibes-sdk/platform/types';
|
|
2
|
+
import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
|
|
3
|
+
import type { ShellPathService } from '@/runtime/index.ts';
|
|
4
|
+
import {
|
|
5
|
+
buildReminderSchedulePreview,
|
|
6
|
+
createReminderSchedule,
|
|
7
|
+
parseReminderScheduleArgs,
|
|
8
|
+
resolveReminderConnectedHostConnection,
|
|
9
|
+
type ReminderScheduleResult,
|
|
10
|
+
} from '../agent/reminder-schedule.ts';
|
|
11
|
+
import {
|
|
12
|
+
formatReminderScheduleFailure,
|
|
13
|
+
formatReminderSchedulePreview,
|
|
14
|
+
formatReminderScheduleSuccess,
|
|
15
|
+
} from '../agent/reminder-schedule-format.ts';
|
|
16
|
+
import type { AgentConnectedHostConfigReader } from '../agent/routine-schedule-promotion.ts';
|
|
17
|
+
|
|
18
|
+
type ReminderScheduleKind = 'at' | 'every' | 'cron';
|
|
19
|
+
|
|
20
|
+
export interface AgentReminderScheduleToolArgs {
|
|
21
|
+
readonly message?: unknown;
|
|
22
|
+
readonly scheduleKind?: unknown;
|
|
23
|
+
readonly scheduleValue?: unknown;
|
|
24
|
+
readonly timezone?: unknown;
|
|
25
|
+
readonly name?: unknown;
|
|
26
|
+
readonly provider?: unknown;
|
|
27
|
+
readonly model?: unknown;
|
|
28
|
+
readonly deliveryChannel?: unknown;
|
|
29
|
+
readonly deliveryRoute?: unknown;
|
|
30
|
+
readonly deliveryWebhook?: unknown;
|
|
31
|
+
readonly deliveryLink?: unknown;
|
|
32
|
+
readonly disabled?: unknown;
|
|
33
|
+
readonly confirm?: unknown;
|
|
34
|
+
readonly explicitUserRequest?: unknown;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const SCHEDULE_KINDS: readonly ReminderScheduleKind[] = ['at', 'every', 'cron'];
|
|
38
|
+
|
|
39
|
+
function isScheduleKind(value: unknown): value is ReminderScheduleKind {
|
|
40
|
+
return typeof value === 'string' && SCHEDULE_KINDS.includes(value as ReminderScheduleKind);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function readString(value: unknown): string {
|
|
44
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function readOptionalString(value: unknown): string | null {
|
|
48
|
+
const text = readString(value);
|
|
49
|
+
return text ? text : null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function readBoolean(value: unknown): boolean {
|
|
53
|
+
return value === true || value === 'true' || value === 'yes';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function addOptionalArg(args: string[], flag: string, value: unknown): void {
|
|
57
|
+
const text = readOptionalString(value);
|
|
58
|
+
if (!text) return;
|
|
59
|
+
args.push(flag, text);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function scheduleFlag(kind: ReminderScheduleKind): string {
|
|
63
|
+
if (kind === 'cron') return '--cron';
|
|
64
|
+
if (kind === 'every') return '--every';
|
|
65
|
+
return '--at';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function buildReminderScheduleArgs(rawArgs: AgentReminderScheduleToolArgs): readonly string[] {
|
|
69
|
+
const message = readOptionalString(rawArgs.message);
|
|
70
|
+
const scheduleValue = readOptionalString(rawArgs.scheduleValue);
|
|
71
|
+
if (!message) throw new Error('message is required.');
|
|
72
|
+
if (!isScheduleKind(rawArgs.scheduleKind)) throw new Error('scheduleKind must be one of: at, every, cron.');
|
|
73
|
+
if (!scheduleValue) throw new Error('scheduleValue is required.');
|
|
74
|
+
|
|
75
|
+
const args = [
|
|
76
|
+
scheduleFlag(rawArgs.scheduleKind),
|
|
77
|
+
scheduleValue,
|
|
78
|
+
'--message',
|
|
79
|
+
message,
|
|
80
|
+
];
|
|
81
|
+
addOptionalArg(args, '--timezone', rawArgs.timezone);
|
|
82
|
+
addOptionalArg(args, '--name', rawArgs.name);
|
|
83
|
+
addOptionalArg(args, '--provider', rawArgs.provider);
|
|
84
|
+
addOptionalArg(args, '--model', rawArgs.model);
|
|
85
|
+
addOptionalArg(args, '--delivery-channel', rawArgs.deliveryChannel);
|
|
86
|
+
addOptionalArg(args, '--delivery-route', rawArgs.deliveryRoute);
|
|
87
|
+
addOptionalArg(args, '--delivery-webhook', rawArgs.deliveryWebhook);
|
|
88
|
+
addOptionalArg(args, '--delivery-link', rawArgs.deliveryLink);
|
|
89
|
+
if (readBoolean(rawArgs.disabled)) args.push('--disabled');
|
|
90
|
+
if (readBoolean(rawArgs.confirm)) args.push('--yes');
|
|
91
|
+
return args;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function outputForResult(result: ReminderScheduleResult): { readonly success: boolean; readonly output?: string; readonly error?: string } {
|
|
95
|
+
if (result.ok) {
|
|
96
|
+
return {
|
|
97
|
+
success: true,
|
|
98
|
+
output: formatReminderScheduleSuccess(result),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
success: false,
|
|
103
|
+
error: formatReminderScheduleFailure(result),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function confirmationError(preview: ReturnType<typeof buildReminderSchedulePreview>): string {
|
|
108
|
+
return [
|
|
109
|
+
formatReminderSchedulePreview(preview),
|
|
110
|
+
'',
|
|
111
|
+
'Model tool confirmation required. Call this tool with confirm:true only when the user explicitly asked GoodVibes Agent to create this reminder or schedule.',
|
|
112
|
+
'Do not create reminders from vague suggestions, brainstorming, routine startup, or inferred follow-up work.',
|
|
113
|
+
].join('\n');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function createAgentReminderScheduleTool(
|
|
117
|
+
shellPaths: ShellPathService,
|
|
118
|
+
configManager: AgentConnectedHostConfigReader,
|
|
119
|
+
): Tool {
|
|
120
|
+
return {
|
|
121
|
+
definition: {
|
|
122
|
+
name: 'agent_reminder_schedule',
|
|
123
|
+
description: [
|
|
124
|
+
'Create one connected GoodVibes Agent reminder schedule from the main conversation.',
|
|
125
|
+
'Use only when the user explicitly asks to be reminded or asks Agent to schedule a reminder.',
|
|
126
|
+
'This calls the public schedules.create route on the connected GoodVibes host; it does not manage connected-host hosting, create a local scheduler, create separate Agent jobs, use delegated review, or write to default knowledge or non-Agent knowledge segments.',
|
|
127
|
+
'Set confirm:true only for an explicit user request. Otherwise return the preview/confirmation error.',
|
|
128
|
+
].join(' '),
|
|
129
|
+
parameters: {
|
|
130
|
+
type: 'object',
|
|
131
|
+
properties: {
|
|
132
|
+
message: {
|
|
133
|
+
type: 'string',
|
|
134
|
+
description: 'Reminder text to deliver when the schedule fires.',
|
|
135
|
+
},
|
|
136
|
+
scheduleKind: {
|
|
137
|
+
type: 'string',
|
|
138
|
+
enum: [...SCHEDULE_KINDS],
|
|
139
|
+
description: 'Schedule selector: at for one timestamp, every for an interval, cron for a cron expression.',
|
|
140
|
+
},
|
|
141
|
+
scheduleValue: {
|
|
142
|
+
type: 'string',
|
|
143
|
+
description: 'ISO timestamp, interval, or cron expression matching scheduleKind.',
|
|
144
|
+
},
|
|
145
|
+
timezone: {
|
|
146
|
+
type: 'string',
|
|
147
|
+
description: 'Optional IANA timezone for cron/at schedules.',
|
|
148
|
+
},
|
|
149
|
+
name: {
|
|
150
|
+
type: 'string',
|
|
151
|
+
description: 'Optional connected schedule display name.',
|
|
152
|
+
},
|
|
153
|
+
provider: {
|
|
154
|
+
type: 'string',
|
|
155
|
+
description: 'Optional provider row id for reminder execution.',
|
|
156
|
+
},
|
|
157
|
+
model: {
|
|
158
|
+
type: 'string',
|
|
159
|
+
description: 'Optional model id for reminder execution.',
|
|
160
|
+
},
|
|
161
|
+
deliveryChannel: {
|
|
162
|
+
type: 'string',
|
|
163
|
+
description: 'Optional delivery channel target: surfaceKind:routeId:label, for example slack:ops:Ops.',
|
|
164
|
+
},
|
|
165
|
+
deliveryRoute: {
|
|
166
|
+
type: 'string',
|
|
167
|
+
description: 'Optional connected route target: routeId:label.',
|
|
168
|
+
},
|
|
169
|
+
deliveryWebhook: {
|
|
170
|
+
type: 'string',
|
|
171
|
+
description: 'Optional http(s) webhook target.',
|
|
172
|
+
},
|
|
173
|
+
deliveryLink: {
|
|
174
|
+
type: 'string',
|
|
175
|
+
description: 'Optional link delivery target.',
|
|
176
|
+
},
|
|
177
|
+
disabled: {
|
|
178
|
+
type: 'boolean',
|
|
179
|
+
description: 'Create the schedule disabled.',
|
|
180
|
+
},
|
|
181
|
+
confirm: {
|
|
182
|
+
type: 'boolean',
|
|
183
|
+
description: 'Required true only when the user explicitly asked to create this reminder.',
|
|
184
|
+
},
|
|
185
|
+
explicitUserRequest: {
|
|
186
|
+
type: 'string',
|
|
187
|
+
description: 'Short quote or summary of the user request that authorized this reminder creation.',
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
required: ['message', 'scheduleKind', 'scheduleValue', 'confirm', 'explicitUserRequest'],
|
|
191
|
+
additionalProperties: false,
|
|
192
|
+
},
|
|
193
|
+
sideEffects: ['network', 'state'],
|
|
194
|
+
},
|
|
195
|
+
execute: async (rawArgs: unknown) => {
|
|
196
|
+
try {
|
|
197
|
+
const args = rawArgs as AgentReminderScheduleToolArgs;
|
|
198
|
+
const explicitUserRequest = readOptionalString(args.explicitUserRequest);
|
|
199
|
+
if (!explicitUserRequest) {
|
|
200
|
+
return {
|
|
201
|
+
success: false,
|
|
202
|
+
error: 'explicitUserRequest is required so reminder creation stays tied to a direct user request.',
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const parsed = parseReminderScheduleArgs(buildReminderScheduleArgs(args));
|
|
206
|
+
if (parsed.errors.length > 0) {
|
|
207
|
+
return {
|
|
208
|
+
success: false,
|
|
209
|
+
error: parsed.errors.join('\n'),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
const preview = buildReminderSchedulePreview(parsed);
|
|
213
|
+
if (!parsed.yes) {
|
|
214
|
+
return {
|
|
215
|
+
success: false,
|
|
216
|
+
error: confirmationError(preview),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
const connection = resolveReminderConnectedHostConnection(configManager, shellPaths.homeDirectory);
|
|
220
|
+
return outputForResult(await createReminderSchedule(connection, preview));
|
|
221
|
+
} catch (error) {
|
|
222
|
+
return {
|
|
223
|
+
success: false,
|
|
224
|
+
error: error instanceof Error ? error.message : String(error),
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export function registerAgentReminderScheduleTool(
|
|
232
|
+
registry: ToolRegistry,
|
|
233
|
+
shellPaths: ShellPathService,
|
|
234
|
+
configManager: AgentConnectedHostConfigReader,
|
|
235
|
+
): void {
|
|
236
|
+
registry.register(createAgentReminderScheduleTool(shellPaths, configManager));
|
|
237
|
+
}
|
|
@@ -122,13 +122,13 @@ const READ_ONLY_QUERY_TOOL_MODE_SET = new Set<string>(READ_ONLY_QUERY_TOOL_MODES
|
|
|
122
122
|
const READ_ONLY_CONTROL_TOOL_MODE_SET = new Set<string>(READ_ONLY_CONTROL_TOOL_MODES);
|
|
123
123
|
|
|
124
124
|
const LOCAL_AGENT_DENIAL = [
|
|
125
|
-
'GoodVibes Agent does not
|
|
125
|
+
'GoodVibes Agent does not create coding-role Agent jobs or run local delegated review chains.',
|
|
126
126
|
'Keep ordinary assistant work serial in the main conversation.',
|
|
127
127
|
'For explicit build/fix/review work, delegate one request to GoodVibes TUI through the public shared-session/build-delegation contract with the full original user ask.',
|
|
128
128
|
].join(' ');
|
|
129
129
|
|
|
130
130
|
const LOCAL_CODING_TOOL_DENIAL = [
|
|
131
|
-
'GoodVibes Agent does not perform direct local file mutation, local
|
|
131
|
+
'GoodVibes Agent does not perform direct local file mutation, local delegated review workflow execution, or local execution-isolation work from the main conversation.',
|
|
132
132
|
'For explicit build/fix/review/code execution work, delegate one request to GoodVibes TUI through the public shared-session/build-delegation contract with the full original user ask.',
|
|
133
133
|
'For durable Agent memory, skills, personas, routines, and knowledge, use the Agent-owned commands and isolated Agent Knowledge routes.',
|
|
134
134
|
].join(' ');
|
|
@@ -140,9 +140,9 @@ const BACKGROUND_EXEC_DENIAL = [
|
|
|
140
140
|
].join(' ');
|
|
141
141
|
|
|
142
142
|
const REMOTE_MUTATION_DENIAL = [
|
|
143
|
-
'GoodVibes Agent only inspects remote
|
|
143
|
+
'GoodVibes Agent only inspects remote build-host pools, contracts, artifacts, and review summaries from the main conversation.',
|
|
144
144
|
'Remote pool creation, assignment, unassignment, and artifact import are disabled here.',
|
|
145
|
-
'Use explicit GoodVibes TUI delegation
|
|
145
|
+
'Use explicit GoodVibes TUI delegation for build/fix/review execution changes.',
|
|
146
146
|
].join(' ');
|
|
147
147
|
|
|
148
148
|
const CHANNEL_ACTION_DENIAL = [
|
|
@@ -207,8 +207,8 @@ export function installAgentToolPolicyGuard(registry: ToolRegistry, options: Age
|
|
|
207
207
|
allowedModes: READ_ONLY_REMOTE_TOOL_MODES,
|
|
208
208
|
modeSet: READ_ONLY_REMOTE_TOOL_MODE_SET,
|
|
209
209
|
description: [
|
|
210
|
-
'Read-only remote
|
|
211
|
-
'Pool creation,
|
|
210
|
+
'Read-only remote build-host inspection for GoodVibes Agent.',
|
|
211
|
+
'Pool creation, host assignment, unassignment, and artifact import are disabled in the main conversation.',
|
|
212
212
|
].join(' '),
|
|
213
213
|
denial: REMOTE_MUTATION_DENIAL,
|
|
214
214
|
});
|
|
@@ -614,7 +614,7 @@ function isPresent(value: unknown): boolean {
|
|
|
614
614
|
function narrowAgentToolDefinitionForAgentPolicy(tool: Tool): void {
|
|
615
615
|
tool.definition.description = [
|
|
616
616
|
'Read-only local Agent inspection for GoodVibes Agent.',
|
|
617
|
-
'This product does not
|
|
617
|
+
'This product does not create separate Agent jobs or run local delegated review chains.',
|
|
618
618
|
'For build/fix/review work, delegate to GoodVibes TUI through the explicit build-delegation path instead.',
|
|
619
619
|
].join(' ');
|
|
620
620
|
tool.definition.sideEffects = [];
|
|
@@ -624,7 +624,7 @@ function narrowAgentToolDefinitionForAgentPolicy(tool: Tool): void {
|
|
|
624
624
|
const modeProperty = properties.mode;
|
|
625
625
|
if (!isRecord(modeProperty)) return;
|
|
626
626
|
modeProperty.enum = [...READ_ONLY_AGENT_TOOL_MODES];
|
|
627
|
-
modeProperty.description = 'Read-only Agent inspection mode.
|
|
627
|
+
modeProperty.description = 'Read-only Agent inspection mode. Separate Agent job creation, batch creation, cancel, message, wait, and plan modes are disabled in GoodVibes Agent.';
|
|
628
628
|
}
|
|
629
629
|
|
|
630
630
|
function narrowExecToolDefinitionForAgentPolicy(tool: Tool): void {
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import type { Tool } from '@pellux/goodvibes-sdk/platform/types';
|
|
2
|
+
import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
|
|
3
|
+
import {
|
|
4
|
+
WORK_PLAN_STATUSES,
|
|
5
|
+
type WorkPlanItem,
|
|
6
|
+
type WorkPlanItemStatus,
|
|
7
|
+
type WorkPlanStore,
|
|
8
|
+
} from '../work-plans/work-plan-store.ts';
|
|
9
|
+
|
|
10
|
+
export type AgentWorkPlanAction =
|
|
11
|
+
| 'list'
|
|
12
|
+
| 'get'
|
|
13
|
+
| 'create'
|
|
14
|
+
| 'update'
|
|
15
|
+
| 'set_status'
|
|
16
|
+
| 'remove'
|
|
17
|
+
| 'clear_completed';
|
|
18
|
+
|
|
19
|
+
export interface AgentWorkPlanToolArgs {
|
|
20
|
+
readonly action?: unknown;
|
|
21
|
+
readonly id?: unknown;
|
|
22
|
+
readonly title?: unknown;
|
|
23
|
+
readonly status?: unknown;
|
|
24
|
+
readonly owner?: unknown;
|
|
25
|
+
readonly source?: unknown;
|
|
26
|
+
readonly notes?: unknown;
|
|
27
|
+
readonly confirm?: unknown;
|
|
28
|
+
readonly explicitUserRequest?: unknown;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const ACTIONS: readonly AgentWorkPlanAction[] = [
|
|
32
|
+
'list',
|
|
33
|
+
'get',
|
|
34
|
+
'create',
|
|
35
|
+
'update',
|
|
36
|
+
'set_status',
|
|
37
|
+
'remove',
|
|
38
|
+
'clear_completed',
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
function isAction(value: unknown): value is AgentWorkPlanAction {
|
|
42
|
+
return typeof value === 'string' && ACTIONS.includes(value as AgentWorkPlanAction);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function isStatus(value: unknown): value is WorkPlanItemStatus {
|
|
46
|
+
return typeof value === 'string' && WORK_PLAN_STATUSES.includes(value as WorkPlanItemStatus);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function readString(value: unknown): string {
|
|
50
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function readBoolean(value: unknown): boolean {
|
|
54
|
+
return value === true || value === 'true' || value === 'yes';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function failure(error: string): { readonly success: false; readonly error: string } {
|
|
58
|
+
return { success: false, error };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function output(text: string): { readonly success: true; readonly output: string } {
|
|
62
|
+
return { success: true, output: text };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function requireId(args: AgentWorkPlanToolArgs): string {
|
|
66
|
+
const id = readString(args.id);
|
|
67
|
+
if (!id) throw new Error('id is required.');
|
|
68
|
+
return id;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function requireTitle(args: AgentWorkPlanToolArgs): string {
|
|
72
|
+
const title = readString(args.title);
|
|
73
|
+
if (!title) throw new Error('title is required.');
|
|
74
|
+
return title;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function readOptionalStatus(value: unknown): WorkPlanItemStatus | undefined {
|
|
78
|
+
if (value === undefined || value === null || readString(value) === '') return undefined;
|
|
79
|
+
if (!isStatus(value)) throw new Error(`Invalid status. Valid values ${WORK_PLAN_STATUSES.join(', ')}.`);
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function formatStatus(status: WorkPlanItemStatus): string {
|
|
84
|
+
return status.replace(/_/g, ' ');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function formatItem(item: WorkPlanItem): string {
|
|
88
|
+
const owner = item.owner ? ` owner ${item.owner}` : '';
|
|
89
|
+
const source = item.source ? ` source=${item.source}` : '';
|
|
90
|
+
const completed = item.completedAt ? ` completed ${new Date(item.completedAt).toISOString()}` : '';
|
|
91
|
+
return `${item.id} ${formatStatus(item.status)}${owner}${source}${completed} ${item.title}`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function formatItemDetail(item: WorkPlanItem): string {
|
|
95
|
+
return [
|
|
96
|
+
formatItem(item),
|
|
97
|
+
`created ${new Date(item.createdAt).toISOString()}`,
|
|
98
|
+
`updated ${new Date(item.updatedAt).toISOString()}`,
|
|
99
|
+
item.linked
|
|
100
|
+
? `linked ${Object.entries(item.linked).map(([key, value]) => `${key} ${String(value)}`).join(', ')}`
|
|
101
|
+
: 'linked (none)',
|
|
102
|
+
'',
|
|
103
|
+
item.notes || '(no notes)',
|
|
104
|
+
].join('\n');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function resolveItem(store: WorkPlanStore, idOrPrefix: string): WorkPlanItem {
|
|
108
|
+
const needle = idOrPrefix.trim();
|
|
109
|
+
if (!needle) throw new Error('id is required.');
|
|
110
|
+
const items = store.listItems();
|
|
111
|
+
const exact = items.find((item) => item.id === needle);
|
|
112
|
+
if (exact) return exact;
|
|
113
|
+
const matches = items.filter((item) => item.id.startsWith(needle));
|
|
114
|
+
if (matches.length === 1) return matches[0]!;
|
|
115
|
+
if (matches.length > 1) {
|
|
116
|
+
throw new Error(`Work plan item id "${needle}" is ambiguous. Matches ${matches.map((item) => item.id).join(', ')}`);
|
|
117
|
+
}
|
|
118
|
+
throw new Error(`Work plan item not found ${needle}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function listOutput(store: WorkPlanStore): string {
|
|
122
|
+
const plan = store.getActivePlan();
|
|
123
|
+
const counts = new Map<WorkPlanItemStatus, number>(WORK_PLAN_STATUSES.map((status) => [status, 0]));
|
|
124
|
+
for (const item of plan.items) counts.set(item.status, (counts.get(item.status) ?? 0) + 1);
|
|
125
|
+
const lines = [
|
|
126
|
+
'Agent local work plan',
|
|
127
|
+
` plan ${plan.id}`,
|
|
128
|
+
` project ${plan.projectRoot}`,
|
|
129
|
+
` items ${plan.items.length}; pending ${counts.get('pending') ?? 0}; active ${counts.get('in_progress') ?? 0}; blocked ${counts.get('blocked') ?? 0}; done ${counts.get('done') ?? 0}`,
|
|
130
|
+
];
|
|
131
|
+
if (plan.items.length === 0) {
|
|
132
|
+
lines.push('', 'No local work plan items.');
|
|
133
|
+
return lines.join('\n');
|
|
134
|
+
}
|
|
135
|
+
lines.push('', ...plan.items.slice(0, 20).map(formatItem));
|
|
136
|
+
if (plan.items.length > 20) lines.push(`${plan.items.length - 20} more item(s) omitted.`);
|
|
137
|
+
return lines.join('\n');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function requireDestructiveConfirmation(args: AgentWorkPlanToolArgs, action: string): string | null {
|
|
141
|
+
const explicitUserRequest = readString(args.explicitUserRequest);
|
|
142
|
+
if (!explicitUserRequest) return `explicitUserRequest is required before ${action}.`;
|
|
143
|
+
if (!readBoolean(args.confirm)) {
|
|
144
|
+
return [
|
|
145
|
+
`Agent work plan ${action} preview`,
|
|
146
|
+
' policy destructive local work-plan changes require confirm:true and an explicit user request',
|
|
147
|
+
` request ${explicitUserRequest}`,
|
|
148
|
+
].join('\n');
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function updatePatch(args: AgentWorkPlanToolArgs): Parameters<WorkPlanStore['updateItem']>[1] {
|
|
154
|
+
const status = readOptionalStatus(args.status);
|
|
155
|
+
return {
|
|
156
|
+
...(args.title !== undefined ? { title: requireTitle(args) } : {}),
|
|
157
|
+
...(status !== undefined ? { status } : {}),
|
|
158
|
+
...(args.owner !== undefined ? { owner: readString(args.owner) || null } : {}),
|
|
159
|
+
...(args.source !== undefined ? { source: readString(args.source) || null } : {}),
|
|
160
|
+
...(args.notes !== undefined ? { notes: readString(args.notes) || null } : {}),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function createAgentWorkPlanTool(store: WorkPlanStore): Tool {
|
|
165
|
+
return {
|
|
166
|
+
definition: {
|
|
167
|
+
name: 'agent_work_plan',
|
|
168
|
+
description: [
|
|
169
|
+
'Inspect and maintain the visible GoodVibes Agent local work plan from the main conversation.',
|
|
170
|
+
'Use this to track concrete tasks the assistant is doing or has agreed to do, so the work is visible in the Agent TUI workspace.',
|
|
171
|
+
'This uses only Agent-local persisted work-plan state; it does not call connected-host mutation routes, start background jobs, create separate Agent jobs, use delegated review, write default knowledge, or use non-Agent knowledge segments.',
|
|
172
|
+
'Create, update, and set_status are safe local state actions. remove and clear_completed require confirm:true plus explicitUserRequest.',
|
|
173
|
+
].join(' '),
|
|
174
|
+
parameters: {
|
|
175
|
+
type: 'object',
|
|
176
|
+
properties: {
|
|
177
|
+
action: { type: 'string', enum: [...ACTIONS] },
|
|
178
|
+
id: { type: 'string', description: 'Work plan item id or unique id prefix for get/update/set_status/remove.' },
|
|
179
|
+
title: { type: 'string', description: 'Work plan item title for create/update.' },
|
|
180
|
+
status: { type: 'string', enum: [...WORK_PLAN_STATUSES], description: 'Work plan item status.' },
|
|
181
|
+
owner: { type: 'string', description: 'Optional owner label.' },
|
|
182
|
+
source: { type: 'string', description: 'Optional source/provenance label.' },
|
|
183
|
+
notes: { type: 'string', description: 'Optional work-plan notes.' },
|
|
184
|
+
confirm: { type: 'boolean', description: 'Required true for remove and clear_completed.' },
|
|
185
|
+
explicitUserRequest: { type: 'string', description: 'Required for destructive remove and clear_completed actions.' },
|
|
186
|
+
},
|
|
187
|
+
required: ['action'],
|
|
188
|
+
additionalProperties: false,
|
|
189
|
+
},
|
|
190
|
+
sideEffects: ['state'],
|
|
191
|
+
},
|
|
192
|
+
execute: async (rawArgs: unknown) => {
|
|
193
|
+
try {
|
|
194
|
+
const args = rawArgs as AgentWorkPlanToolArgs;
|
|
195
|
+
if (!isAction(args.action)) return failure(`Unknown Agent work plan action. Valid values ${ACTIONS.join(', ')}.`);
|
|
196
|
+
if (args.action === 'list') return output(listOutput(store));
|
|
197
|
+
if (args.action === 'get') return output(formatItemDetail(resolveItem(store, requireId(args))));
|
|
198
|
+
if (args.action === 'create') {
|
|
199
|
+
const item = store.addItem(requireTitle(args), {
|
|
200
|
+
status: readOptionalStatus(args.status) ?? 'pending',
|
|
201
|
+
owner: readString(args.owner) || 'agent',
|
|
202
|
+
source: readString(args.source) || 'main-conversation',
|
|
203
|
+
notes: readString(args.notes) || undefined,
|
|
204
|
+
});
|
|
205
|
+
return output([
|
|
206
|
+
'Created Agent work plan item',
|
|
207
|
+
` id ${item.id}`,
|
|
208
|
+
` title ${item.title}`,
|
|
209
|
+
].join('\n'));
|
|
210
|
+
}
|
|
211
|
+
if (args.action === 'update') {
|
|
212
|
+
const item = store.updateItem(requireId(args), updatePatch(args));
|
|
213
|
+
return output([
|
|
214
|
+
'Updated Agent work plan item',
|
|
215
|
+
` id ${item.id}`,
|
|
216
|
+
` title ${item.title}`,
|
|
217
|
+
].join('\n'));
|
|
218
|
+
}
|
|
219
|
+
if (args.action === 'set_status') {
|
|
220
|
+
const status = readOptionalStatus(args.status);
|
|
221
|
+
if (!status) throw new Error('status is required.');
|
|
222
|
+
const item = store.setItemStatus(requireId(args), status);
|
|
223
|
+
return output([
|
|
224
|
+
'Set Agent work plan item status',
|
|
225
|
+
` id ${item.id}`,
|
|
226
|
+
` status ${formatStatus(item.status)}`,
|
|
227
|
+
` title ${item.title}`,
|
|
228
|
+
].join('\n'));
|
|
229
|
+
}
|
|
230
|
+
if (args.action === 'remove') {
|
|
231
|
+
const denied = requireDestructiveConfirmation(args, `remove ${readString(args.id) || '(missing id)'}`);
|
|
232
|
+
if (denied) return failure(denied);
|
|
233
|
+
const item = store.removeItem(requireId(args));
|
|
234
|
+
return output([
|
|
235
|
+
'Removed Agent work plan item',
|
|
236
|
+
` id ${item.id}`,
|
|
237
|
+
` title ${item.title}`,
|
|
238
|
+
].join('\n'));
|
|
239
|
+
}
|
|
240
|
+
const denied = requireDestructiveConfirmation(args, 'clear completed');
|
|
241
|
+
if (denied) return failure(denied);
|
|
242
|
+
const count = store.clearCompleted();
|
|
243
|
+
return output([
|
|
244
|
+
`Cleared ${count} completed/cancelled Agent work plan items`,
|
|
245
|
+
` count ${count}`,
|
|
246
|
+
].join('\n'));
|
|
247
|
+
} catch (error) {
|
|
248
|
+
return failure(error instanceof Error ? error.message : String(error));
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export function registerAgentWorkPlanTool(registry: ToolRegistry, store: WorkPlanStore): void {
|
|
255
|
+
registry.register(createAgentWorkPlanTool(store));
|
|
256
|
+
}
|
package/src/version.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { join } from 'node:path';
|
|
|
6
6
|
// The prebuild script updates the fallback value before compilation.
|
|
7
7
|
// Uses import.meta.dir (Bun) to locate package.json relative to this file,
|
|
8
8
|
// which is correct regardless of the process working directory.
|
|
9
|
-
let _version = '0.1
|
|
9
|
+
let _version = '1.0.1';
|
|
10
10
|
let _sdkVersion = '0.33.35';
|
|
11
11
|
try {
|
|
12
12
|
const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', 'package.json'), 'utf-8')) as {
|