@pellux/goodvibes-agent 0.1.35 → 0.1.37
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 +8 -0
- package/README.md +5 -0
- package/docs/README.md +1 -1
- package/docs/getting-started.md +4 -1
- package/docs/operator-capability-benchmark.md +4 -3
- package/package.json +1 -1
- package/src/agent/routine-schedule-promotion.ts +434 -0
- package/src/agent/runtime-profile.ts +4 -0
- package/src/cli/completion.ts +1 -0
- package/src/cli/help.ts +17 -0
- package/src/cli/management.ts +6 -0
- package/src/cli/parser.ts +2 -0
- package/src/cli/routines-command.ts +185 -0
- package/src/cli/types.ts +1 -0
- package/src/input/agent-workspace.ts +20 -6
- package/src/input/commands/agent-runtime-profile-runtime.ts +223 -0
- package/src/input/commands/routines-runtime.ts +40 -2
- package/src/input/commands/schedule-runtime.ts +52 -8
- package/src/input/commands.ts +2 -0
- package/src/operator/capability-benchmark.ts +5 -5
- package/src/renderer/agent-workspace.ts +2 -1
- package/src/version.ts +1 -1
|
@@ -4,6 +4,18 @@ import {
|
|
|
4
4
|
} from '@pellux/goodvibes-sdk/platform/automation';
|
|
5
5
|
import type { AutomationJob } from '@pellux/goodvibes-sdk/platform/automation';
|
|
6
6
|
import type { AutomationScheduleDefinition } from '@pellux/goodvibes-sdk/platform/automation';
|
|
7
|
+
import { AgentRoutineRegistry } from '../../agent/routine-registry.ts';
|
|
8
|
+
import {
|
|
9
|
+
buildRoutineSchedulePreview,
|
|
10
|
+
formatRoutineScheduleFailure,
|
|
11
|
+
formatRoutineSchedulePreview,
|
|
12
|
+
formatRoutineScheduleSuccess,
|
|
13
|
+
parseRoutineSchedulePromotionArgs,
|
|
14
|
+
promoteRoutineToDaemonSchedule,
|
|
15
|
+
resolveAgentDaemonConnection,
|
|
16
|
+
} from '../../agent/routine-schedule-promotion.ts';
|
|
17
|
+
import type { CommandContext } from '../command-registry.ts';
|
|
18
|
+
import { requireShellPaths } from './runtime-services.ts';
|
|
7
19
|
|
|
8
20
|
function formatSchedule(schedule: AutomationScheduleDefinition): string {
|
|
9
21
|
switch (schedule.kind) {
|
|
@@ -31,35 +43,66 @@ function formatPrompt(job: AutomationJob): string {
|
|
|
31
43
|
|
|
32
44
|
function printReadOnlyScheduleBoundary(print: (text: string) => void, requestedAction: string): void {
|
|
33
45
|
print([
|
|
34
|
-
'GoodVibes Agent schedule commands are read-only in this runtime.',
|
|
46
|
+
'GoodVibes Agent local schedule commands are read-only in this runtime.',
|
|
35
47
|
` requested: ${requestedAction}`,
|
|
36
48
|
' policy: no local Agent automation jobs, scheduled spawns, or immediate automation runs',
|
|
37
49
|
' use: /schedule list',
|
|
38
|
-
'
|
|
50
|
+
' daemon route: use /schedule promote-routine <routine> --cron <expr> --yes to create an external daemon schedule explicitly',
|
|
39
51
|
].join('\n'));
|
|
40
52
|
}
|
|
41
53
|
|
|
54
|
+
async function promoteRoutineSchedule(args: readonly string[], ctx: CommandContext): Promise<void> {
|
|
55
|
+
const parsed = parseRoutineSchedulePromotionArgs(args);
|
|
56
|
+
if (parsed.errors.length > 0) {
|
|
57
|
+
ctx.print([
|
|
58
|
+
'Usage: /schedule promote-routine <routine-id> (--cron <expr>|--every <interval>|--at <iso-time>) [--timezone <tz>] [--name <schedule-name>] [--provider <id>] [--model <model>] [--disabled] --yes',
|
|
59
|
+
...parsed.errors.map((error) => ` ${error}`),
|
|
60
|
+
].join('\n'));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const shellPaths = requireShellPaths(ctx);
|
|
64
|
+
const routine = AgentRoutineRegistry.fromShellPaths(shellPaths).get(parsed.routineId ?? '');
|
|
65
|
+
if (!routine) {
|
|
66
|
+
ctx.print(`Unknown Agent routine: ${parsed.routineId ?? ''}`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const preview = buildRoutineSchedulePreview(routine, parsed);
|
|
70
|
+
if (!parsed.yes) {
|
|
71
|
+
ctx.print(formatRoutineSchedulePreview(preview));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const connection = resolveAgentDaemonConnection(ctx.platform.configManager, shellPaths.homeDirectory);
|
|
75
|
+
const result = await promoteRoutineToDaemonSchedule(connection, preview);
|
|
76
|
+
ctx.print(result.ok ? formatRoutineScheduleSuccess(result) : formatRoutineScheduleFailure(result));
|
|
77
|
+
}
|
|
78
|
+
|
|
42
79
|
export function registerScheduleRuntimeCommands(registry: CommandRegistry): void {
|
|
43
80
|
registry.register({
|
|
44
81
|
name: 'schedule',
|
|
45
82
|
aliases: ['sched'],
|
|
46
|
-
description: 'Inspect
|
|
47
|
-
usage: 'list',
|
|
48
|
-
argsHint: 'list',
|
|
83
|
+
description: 'Inspect schedules and explicitly promote local Agent routines to daemon schedules',
|
|
84
|
+
usage: 'list | promote-routine <routine-id> --cron <expr> --yes',
|
|
85
|
+
argsHint: 'list | promote-routine <routine-id> --cron <expr> --yes',
|
|
49
86
|
async handler(args, ctx) {
|
|
87
|
+
const sub = args[0];
|
|
88
|
+
|
|
89
|
+
if (sub === 'promote-routine' || sub === 'promote' || sub === 'create-routine-schedule') {
|
|
90
|
+
await promoteRoutineSchedule(args.slice(1), ctx);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
50
94
|
const manager = ctx.ops.automationManager;
|
|
51
95
|
if (!manager) {
|
|
52
96
|
ctx.print('Automation manager is not available in this runtime.');
|
|
53
97
|
return;
|
|
54
98
|
}
|
|
55
|
-
const sub = args[0];
|
|
56
99
|
|
|
57
100
|
if (!sub || sub === 'list') {
|
|
58
101
|
const jobs = manager.listJobs();
|
|
59
102
|
if (jobs.length === 0) {
|
|
60
103
|
ctx.print(
|
|
61
104
|
'No automation jobs.\n'
|
|
62
|
-
+ '
|
|
105
|
+
+ 'Local add/run/enable/disable/remove are blocked. Use /schedule promote-routine <routine> --cron <expr> --yes for an explicit external daemon schedule.'
|
|
63
106
|
);
|
|
64
107
|
return;
|
|
65
108
|
}
|
|
@@ -84,7 +127,8 @@ export function registerScheduleRuntimeCommands(registry: CommandRegistry): void
|
|
|
84
127
|
ctx.print(
|
|
85
128
|
'Usage:\n'
|
|
86
129
|
+ ' /schedule list\n'
|
|
87
|
-
+ '
|
|
130
|
+
+ ' /schedule promote-routine <routine-id> (--cron <expr>|--every <interval>|--at <iso-time>) --yes\n'
|
|
131
|
+
+ ' Local schedule mutations and runs remain blocked.'
|
|
88
132
|
);
|
|
89
133
|
},
|
|
90
134
|
});
|
package/src/input/commands.ts
CHANGED
|
@@ -53,6 +53,7 @@ import { registerTtsRuntimeCommands } from './commands/tts-runtime.ts';
|
|
|
53
53
|
import { registerCloudflareRuntimeCommands } from './commands/cloudflare-runtime.ts';
|
|
54
54
|
import { registerWorkPlanRuntimeCommands } from './commands/work-plan-runtime.ts';
|
|
55
55
|
import { registerAgentWorkspaceRuntimeCommands } from './commands/agent-workspace-runtime.ts';
|
|
56
|
+
import { registerAgentRuntimeProfileRuntimeCommands } from './commands/agent-runtime-profile-runtime.ts';
|
|
56
57
|
import { registerAgentExternalizedTuiCommands } from './commands/agent-externalized-tui.ts';
|
|
57
58
|
import { registerDelegationRuntimeCommands } from './commands/delegation-runtime.ts';
|
|
58
59
|
import { registerPersonasRuntimeCommands } from './commands/personas-runtime.ts';
|
|
@@ -67,6 +68,7 @@ import { registerCapabilitiesRuntimeCommands } from './commands/capabilities-run
|
|
|
67
68
|
export function registerBuiltinCommands(registry: CommandRegistry): void {
|
|
68
69
|
registerShellCoreCommands(registry);
|
|
69
70
|
registerAgentWorkspaceRuntimeCommands(registry);
|
|
71
|
+
registerAgentRuntimeProfileRuntimeCommands(registry);
|
|
70
72
|
registerCapabilitiesRuntimeCommands(registry);
|
|
71
73
|
registerPersonasRuntimeCommands(registry);
|
|
72
74
|
registerAgentSkillsRuntimeCommands(registry);
|
|
@@ -160,11 +160,11 @@ export const OPERATOR_CAPABILITY_BENCHMARKS: readonly OperatorCapabilityBenchmar
|
|
|
160
160
|
posture: 'ready',
|
|
161
161
|
competitors: ['hermes'],
|
|
162
162
|
competitorBaseline: 'Profiles run independent agents with isolated configs, sessions, skills, memory, cron jobs, and gateway state.',
|
|
163
|
-
goodvibesAgent: 'Supports GOODVIBES_AGENT_HOME and named --agent-profile homes for isolated Agent-local config, sessions, memory, personas, skills, routines, setup, and bundles; daemon remains shared/external by design. The Agent workspace exposes runtime profile posture, config profiles, profile sync, setup transfer shortcuts, starter profile templates, and local starter
|
|
164
|
-
configure: ['GOODVIBES_AGENT_HOME=<path> goodvibes-agent status', 'goodvibes-agent profiles create household --template household --yes', 'goodvibes-agent profiles templates export research ./starter.json --yes', '/agent → Profiles & Portability'],
|
|
165
|
-
use: ['goodvibes-agent --agent-profile household', '/profiles', '/profilesync list', '/setup transfer export <path> --yes'],
|
|
166
|
-
exceedsBy: ['Typed support bundles', 'explicit daemon boundary', 'no accidental cross-product knowledge fallback', 'profile isolation without hidden daemon lifecycle ownership', 'fullscreen profile and portability workflow discovery', 'curated local starter packs', 'editable starter templates'],
|
|
167
|
-
next: ['Add
|
|
163
|
+
goodvibesAgent: 'Supports GOODVIBES_AGENT_HOME and named --agent-profile homes for isolated Agent-local config, sessions, memory, personas, skills, routines, setup, and bundles; daemon remains shared/external by design. The Agent workspace exposes runtime profile posture, config profiles, profile sync, setup transfer shortcuts, starter profile templates, and local starter authoring.',
|
|
164
|
+
configure: ['GOODVIBES_AGENT_HOME=<path> goodvibes-agent status', 'goodvibes-agent profiles create household --template household --yes', 'goodvibes-agent profiles templates export research ./starter.json --yes', '/agent-profile guide', '/agent → Profiles & Portability'],
|
|
165
|
+
use: ['goodvibes-agent --agent-profile household', '/agent-profile templates', '/profiles', '/profilesync list', '/setup transfer export <path> --yes'],
|
|
166
|
+
exceedsBy: ['Typed support bundles', 'explicit daemon boundary', 'no accidental cross-product knowledge fallback', 'profile isolation without hidden daemon lifecycle ownership', 'fullscreen profile and portability workflow discovery', 'curated local starter packs', 'editable starter templates', 'TUI-guided starter authoring'],
|
|
167
|
+
next: ['Add visual starter-template editing inside the fullscreen Agent workspace.'],
|
|
168
168
|
},
|
|
169
169
|
{
|
|
170
170
|
id: 'security-approvals',
|
|
@@ -132,9 +132,10 @@ function snapshotLines(category: AgentWorkspaceCategory, snapshot: AgentWorkspac
|
|
|
132
132
|
{ text: `Active runtime profile: ${snapshot.activeRuntimeProfile}`, fg: PALETTE.info },
|
|
133
133
|
{ text: `Runtime profiles under this home: ${snapshot.runtimeProfileCount}`, fg: PALETTE.info },
|
|
134
134
|
{ text: `Runtime profile root: ${snapshot.runtimeProfileRoot}`, fg: PALETTE.muted },
|
|
135
|
+
{ text: `Starter templates: ${snapshot.runtimeStarterTemplateCount}; local custom: ${snapshot.localStarterTemplateCount}`, fg: PALETTE.info },
|
|
135
136
|
{ text: `Config profiles: ${snapshot.configProfileCount}`, fg: PALETTE.info },
|
|
136
137
|
{ text: 'Named runtime profiles isolate Agent-local config, sessions, memory, personas, skills, routines, setup, and bundles.', fg: PALETTE.good },
|
|
137
|
-
{ text: 'Starter
|
|
138
|
+
{ text: 'Starter authoring: browse, export, edit, import, and create Agent profiles from inside this workspace via /agent-profile.', fg: PALETTE.info },
|
|
138
139
|
{ text: 'The external daemon remains shared unless the daemon host is configured separately.', fg: PALETTE.warn },
|
|
139
140
|
{ text: 'Portable bundles require explicit export/import commands with real paths and --yes.', fg: PALETTE.muted },
|
|
140
141
|
);
|
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 = '0.1.37';
|
|
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 {
|