@robota-sdk/agent-command 3.0.0-beta.73 → 3.0.0-beta.74
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/dist/node/index.cjs +34 -34
- package/dist/node/index.d.ts +40 -2
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +33 -33
- package/dist/node/index.js.map +1 -1
- package/package.json +9 -8
- package/src/agent/agent-command-module.ts +1 -2
- package/src/agent/agent-command-parser.ts +1 -1
- package/src/agent/agent-command.ts +2 -5
- package/src/background/background-command-module.ts +2 -6
- package/src/background/background-command.ts +2 -1
- package/src/compact/compact-command-module.ts +2 -6
- package/src/compact/compact-command.ts +2 -1
- package/src/context/__tests__/context-command-module.test.ts +2 -2
- package/src/context/context-command-module.ts +2 -6
- package/src/context/context-command.ts +1 -2
- package/src/default/default-command-modules.ts +2 -0
- package/src/exit/exit-command-module.ts +2 -3
- package/src/exit/exit-command.ts +2 -1
- package/src/help/__tests__/help-command.test.ts +2 -5
- package/src/help/help-command-module.ts +2 -6
- package/src/help/help-command.ts +2 -1
- package/src/index.ts +1 -0
- package/src/language/language-command-module.ts +2 -3
- package/src/language/language-command.ts +2 -1
- package/src/memory/memory-command-module.ts +2 -6
- package/src/memory/memory-command.ts +1 -2
- package/src/mode/__tests__/mode-command-module.test.ts +1 -1
- package/src/mode/mode-command-module.ts +2 -3
- package/src/mode/mode-command.ts +2 -1
- package/src/permissions/__tests__/permissions-command-module.test.ts +1 -1
- package/src/permissions/permissions-command-module.ts +2 -6
- package/src/permissions/permissions-command.ts +2 -1
- package/src/plugin/__tests__/plugin-command-module.test.ts +2 -5
- package/src/plugin/plugin-command-module.ts +2 -6
- package/src/plugin/plugin-command.ts +2 -5
- package/src/plugins/default-plugin-command-adapter.ts +2 -2
- package/src/provider/provider-command-execution.ts +1 -2
- package/src/provider/provider-command-module.ts +5 -3
- package/src/provider/provider-command-profile-lifecycle.ts +2 -5
- package/src/provider/provider-command-profile-operations.ts +2 -3
- package/src/provider/provider-command-profile.ts +1 -2
- package/src/provider/provider-command-setup.ts +7 -5
- package/src/provider/provider-startup.ts +14 -2
- package/src/reset/reset-command-module.ts +2 -6
- package/src/reset/reset-command.ts +2 -1
- package/src/rewind/rewind-command-module.ts +2 -6
- package/src/rewind/rewind-command.ts +1 -1
- package/src/schedule/__tests__/schedule-command.test.ts +107 -0
- package/src/schedule/index.ts +9 -0
- package/src/schedule/schedule-command-module.ts +102 -0
- package/src/schedule/schedule-command.ts +72 -0
- package/src/schedule/schedule-spec-parser.ts +66 -0
- package/src/session/session-command-module.ts +2 -3
- package/src/session/session-command.ts +2 -1
- package/src/settings/settings-command-module.ts +2 -6
- package/src/skills/skills-command-module.ts +2 -6
- package/src/skills/skills-command.ts +2 -5
- package/src/statusline/statusline-command-module.ts +2 -6
- package/src/statusline/statusline-command.ts +2 -2
- package/src/user-local/user-local-command-module.ts +2 -6
- package/src/user-local/user-local-command.ts +2 -1
- package/src/user-local/user-local-memory-command.ts +2 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ICommandHostContext
|
|
1
|
+
import type { ICommandHostContext } from '@robota-sdk/agent-framework';
|
|
2
|
+
import type { ICommandResult } from '@robota-sdk/agent-interface-transport';
|
|
2
3
|
|
|
3
4
|
export function executeResetCommand(_context: ICommandHostContext, _args: string): ICommandResult {
|
|
4
5
|
return {
|
|
@@ -6,12 +6,8 @@ import {
|
|
|
6
6
|
|
|
7
7
|
import { executeRewindCommand } from './rewind-command.js';
|
|
8
8
|
|
|
9
|
-
import type {
|
|
10
|
-
|
|
11
|
-
ICommandModule,
|
|
12
|
-
ICommandSource,
|
|
13
|
-
ISystemCommand,
|
|
14
|
-
} from '@robota-sdk/agent-framework';
|
|
9
|
+
import type { ICommandModule, ISystemCommand } from '@robota-sdk/agent-framework';
|
|
10
|
+
import type { ICommand, ICommandSource } from '@robota-sdk/agent-interface-transport';
|
|
15
11
|
|
|
16
12
|
export function createRewindCommandEntry(): ICommand {
|
|
17
13
|
return {
|
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
|
|
8
8
|
import type {
|
|
9
9
|
ICommandHostContext,
|
|
10
|
-
ICommandResult,
|
|
11
10
|
IEditCheckpointInspection,
|
|
12
11
|
IEditCheckpointRestoreResult,
|
|
13
12
|
IEditCheckpointSummary,
|
|
14
13
|
} from '@robota-sdk/agent-framework';
|
|
14
|
+
import type { ICommandResult } from '@robota-sdk/agent-interface-transport';
|
|
15
15
|
|
|
16
16
|
const SUBCOMMAND_INDEX = 0;
|
|
17
17
|
const CHECKPOINT_ID_INDEX = 1;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FLOW-005: `/schedule` + `/monitor` command surface.
|
|
3
|
+
* - parseScheduleSpec: relative delay → one-shot ISO; cron form; invalid input rejected.
|
|
4
|
+
* - executeScheduleCommand / executeMonitorCommand: build the wake request and spawn it.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
8
|
+
|
|
9
|
+
import { executeMonitorCommand, executeScheduleCommand } from '../schedule-command.js';
|
|
10
|
+
import { parseScheduleSpec } from '../schedule-spec-parser.js';
|
|
11
|
+
|
|
12
|
+
import type { IAgentJobHostContext } from '@robota-sdk/agent-framework';
|
|
13
|
+
|
|
14
|
+
function mockHost(): {
|
|
15
|
+
host: IAgentJobHostContext;
|
|
16
|
+
scheduled: ReturnType<typeof vi.fn>;
|
|
17
|
+
monitor: ReturnType<typeof vi.fn>;
|
|
18
|
+
} {
|
|
19
|
+
const scheduled = vi.fn().mockResolvedValue({ id: 'task_sched' });
|
|
20
|
+
const monitor = vi.fn().mockResolvedValue({ id: 'task_mon' });
|
|
21
|
+
const host = {
|
|
22
|
+
spawnScheduledWake: scheduled,
|
|
23
|
+
spawnMonitorWake: monitor,
|
|
24
|
+
} as unknown as IAgentJobHostContext;
|
|
25
|
+
return { host, scheduled, monitor };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
describe('parseScheduleSpec (FLOW-005)', () => {
|
|
29
|
+
it('parses a relative delay into a one-shot ISO timestamp', () => {
|
|
30
|
+
const result = parseScheduleSpec('in 5m summarize the logs', 0);
|
|
31
|
+
expect(result.ok).toBe(true);
|
|
32
|
+
if (!result.ok) return;
|
|
33
|
+
expect(result.spec.recurring).toBe(false);
|
|
34
|
+
expect(result.spec.cronExpression).toBe(new Date(5 * 60_000).toISOString());
|
|
35
|
+
expect(result.spec.instruction).toBe('summarize the logs');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('parses a quoted cron expression as recurring', () => {
|
|
39
|
+
const result = parseScheduleSpec('cron "0 9 * * *" run standup', 0);
|
|
40
|
+
expect(result.ok).toBe(true);
|
|
41
|
+
if (!result.ok) return;
|
|
42
|
+
expect(result.spec.recurring).toBe(true);
|
|
43
|
+
expect(result.spec.cronExpression).toBe('0 9 * * *');
|
|
44
|
+
expect(result.spec.instruction).toBe('run standup');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('rejects an invalid duration', () => {
|
|
48
|
+
expect(parseScheduleSpec('in 5x do X', 0).ok).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('rejects a missing instruction', () => {
|
|
52
|
+
expect(parseScheduleSpec('in 5m', 0).ok).toBe(false);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('rejects unrecognized input', () => {
|
|
56
|
+
expect(parseScheduleSpec('whenever you feel like it', 0).ok).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe('executeScheduleCommand (FLOW-005)', () => {
|
|
61
|
+
it('TC-01: relative delay spawns a one-shot scheduled wake', async () => {
|
|
62
|
+
const { host, scheduled } = mockHost();
|
|
63
|
+
const now = 1_000_000;
|
|
64
|
+
const result = await executeScheduleCommand(host, 'in 1m summarize', now);
|
|
65
|
+
|
|
66
|
+
expect(result.success).toBe(true);
|
|
67
|
+
expect(scheduled).toHaveBeenCalledTimes(1);
|
|
68
|
+
expect(scheduled).toHaveBeenCalledWith(
|
|
69
|
+
expect.objectContaining({
|
|
70
|
+
cronExpression: new Date(now + 60_000).toISOString(),
|
|
71
|
+
agentInstruction: 'summarize',
|
|
72
|
+
}),
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('TC-02: cron form spawns a recurring scheduled wake', async () => {
|
|
77
|
+
const { host, scheduled } = mockHost();
|
|
78
|
+
const result = await executeScheduleCommand(host, 'cron "0 9 * * *" standup', Date.now());
|
|
79
|
+
|
|
80
|
+
expect(result.success).toBe(true);
|
|
81
|
+
expect(scheduled).toHaveBeenCalledWith(
|
|
82
|
+
expect.objectContaining({ cronExpression: '0 9 * * *', agentInstruction: 'standup' }),
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('TC-03: invalid input is rejected without spawning', async () => {
|
|
87
|
+
const { host, scheduled } = mockHost();
|
|
88
|
+
const result = await executeScheduleCommand(host, 'garbage', Date.now());
|
|
89
|
+
|
|
90
|
+
expect(result.success).toBe(false);
|
|
91
|
+
expect(scheduled).not.toHaveBeenCalled();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('TC-04: monitor command spawns a process+match wake task', async () => {
|
|
95
|
+
const { host, monitor } = mockHost();
|
|
96
|
+
const result = await executeMonitorCommand(host, '"npm run dev" "ERROR" fix the failure');
|
|
97
|
+
|
|
98
|
+
expect(result.success).toBe(true);
|
|
99
|
+
expect(monitor).toHaveBeenCalledWith(
|
|
100
|
+
expect.objectContaining({
|
|
101
|
+
command: 'npm run dev',
|
|
102
|
+
matchPattern: 'ERROR',
|
|
103
|
+
agentInstruction: 'fix the failure',
|
|
104
|
+
}),
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export {
|
|
2
|
+
createScheduleCommandEntry,
|
|
3
|
+
createMonitorCommandEntry,
|
|
4
|
+
createScheduleCommandModule,
|
|
5
|
+
ScheduleCommandSource,
|
|
6
|
+
} from './schedule-command-module.js';
|
|
7
|
+
export { executeScheduleCommand, executeMonitorCommand } from './schedule-command.js';
|
|
8
|
+
export { parseScheduleSpec } from './schedule-spec-parser.js';
|
|
9
|
+
export type { IScheduleSpec, TScheduleParseResult } from './schedule-spec-parser.js';
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FLOW-005: the `/schedule` + `/monitor` command module — surfaces agent-wake scheduling
|
|
3
|
+
* and process monitoring to users (and the model as tools).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { executeMonitorCommand, executeScheduleCommand } from './schedule-command.js';
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
IAgentJobHostContext,
|
|
10
|
+
ICommandHostContext,
|
|
11
|
+
ICommandModule,
|
|
12
|
+
ISystemCommand,
|
|
13
|
+
} from '@robota-sdk/agent-framework';
|
|
14
|
+
import type {
|
|
15
|
+
ICommand,
|
|
16
|
+
ICommandResult,
|
|
17
|
+
ICommandSource,
|
|
18
|
+
} from '@robota-sdk/agent-interface-transport';
|
|
19
|
+
|
|
20
|
+
function getAgentHostContext(context: ICommandHostContext): IAgentJobHostContext {
|
|
21
|
+
const cap = context.getAgentJobCapability?.();
|
|
22
|
+
if (!cap) throw new Error('Scheduling requires an active agent runtime.');
|
|
23
|
+
return cap;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const SCHEDULE_DESCRIPTION =
|
|
27
|
+
'Schedule the agent to wake and run an instruction on a timer (one-shot or cron).';
|
|
28
|
+
const SCHEDULE_ARGUMENT_HINT = 'in <N><s|m|h|d> <instruction> | cron "<expr>" <instruction>';
|
|
29
|
+
const MONITOR_DESCRIPTION =
|
|
30
|
+
'Watch a process’s output and wake the agent when a line matches a pattern.';
|
|
31
|
+
const MONITOR_ARGUMENT_HINT = '"<command>" "<pattern>" <instruction>';
|
|
32
|
+
|
|
33
|
+
export function createScheduleCommandEntry(): ICommand {
|
|
34
|
+
return {
|
|
35
|
+
name: 'schedule',
|
|
36
|
+
displayName: 'Schedule Wake',
|
|
37
|
+
description: SCHEDULE_DESCRIPTION,
|
|
38
|
+
source: 'schedule',
|
|
39
|
+
argumentHint: SCHEDULE_ARGUMENT_HINT,
|
|
40
|
+
modelInvocable: true,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function createMonitorCommandEntry(): ICommand {
|
|
45
|
+
return {
|
|
46
|
+
name: 'monitor',
|
|
47
|
+
displayName: 'Monitor Process',
|
|
48
|
+
description: MONITOR_DESCRIPTION,
|
|
49
|
+
source: 'schedule',
|
|
50
|
+
argumentHint: MONITOR_ARGUMENT_HINT,
|
|
51
|
+
modelInvocable: true,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function createScheduleSystemCommand(): ISystemCommand {
|
|
56
|
+
const entry = createScheduleCommandEntry();
|
|
57
|
+
return {
|
|
58
|
+
name: entry.name,
|
|
59
|
+
displayName: entry.displayName,
|
|
60
|
+
description: entry.description,
|
|
61
|
+
requiresPermission: false,
|
|
62
|
+
userInvocable: true,
|
|
63
|
+
modelInvocable: true,
|
|
64
|
+
argumentHint: entry.argumentHint,
|
|
65
|
+
lifecycle: 'inline',
|
|
66
|
+
execute: (context, args): Promise<ICommandResult> =>
|
|
67
|
+
executeScheduleCommand(getAgentHostContext(context), args),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function createMonitorSystemCommand(): ISystemCommand {
|
|
72
|
+
const entry = createMonitorCommandEntry();
|
|
73
|
+
return {
|
|
74
|
+
name: entry.name,
|
|
75
|
+
displayName: entry.displayName,
|
|
76
|
+
description: entry.description,
|
|
77
|
+
requiresPermission: false,
|
|
78
|
+
userInvocable: true,
|
|
79
|
+
modelInvocable: true,
|
|
80
|
+
argumentHint: entry.argumentHint,
|
|
81
|
+
lifecycle: 'inline',
|
|
82
|
+
execute: (context, args): Promise<ICommandResult> =>
|
|
83
|
+
executeMonitorCommand(getAgentHostContext(context), args),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export class ScheduleCommandSource implements ICommandSource {
|
|
88
|
+
readonly name = 'schedule';
|
|
89
|
+
|
|
90
|
+
getCommands(): ICommand[] {
|
|
91
|
+
return [createScheduleCommandEntry(), createMonitorCommandEntry()];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function createScheduleCommandModule(): ICommandModule {
|
|
96
|
+
return {
|
|
97
|
+
name: 'agent-command-schedule',
|
|
98
|
+
commandSources: [new ScheduleCommandSource()],
|
|
99
|
+
systemCommands: [createScheduleSystemCommand(), createMonitorSystemCommand()],
|
|
100
|
+
sessionRequirements: ['agent-runtime'],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FLOW-005: `/schedule` and `/monitor` command executors — create agent-wake background tasks.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { parseScheduleSpec } from './schedule-spec-parser.js';
|
|
6
|
+
|
|
7
|
+
import type { IAgentJobHostContext } from '@robota-sdk/agent-framework';
|
|
8
|
+
import type { ICommandResult } from '@robota-sdk/agent-interface-transport';
|
|
9
|
+
|
|
10
|
+
const MAX_LABEL_LENGTH = 48;
|
|
11
|
+
|
|
12
|
+
function labelFor(prefix: string, instruction: string): string {
|
|
13
|
+
const snippet = instruction.slice(0, MAX_LABEL_LENGTH);
|
|
14
|
+
return `${prefix}: ${snippet}${instruction.length > MAX_LABEL_LENGTH ? '…' : ''}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function executeScheduleCommand(
|
|
18
|
+
host: IAgentJobHostContext,
|
|
19
|
+
args: string,
|
|
20
|
+
now: number = Date.now(),
|
|
21
|
+
): Promise<ICommandResult> {
|
|
22
|
+
const parsed = parseScheduleSpec(args, now);
|
|
23
|
+
if (!parsed.ok) return { message: parsed.error, success: false };
|
|
24
|
+
|
|
25
|
+
const { cronExpression, instruction, recurring } = parsed.spec;
|
|
26
|
+
const task = await host.spawnScheduledWake({
|
|
27
|
+
label: labelFor('Scheduled', instruction),
|
|
28
|
+
cronExpression,
|
|
29
|
+
agentInstruction: instruction,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const when = recurring ? `cron \`${cronExpression}\`` : `once at ${cronExpression}`;
|
|
33
|
+
return {
|
|
34
|
+
message: `Scheduled wake (${when}): "${instruction}" — task ${task.id}.`,
|
|
35
|
+
success: true,
|
|
36
|
+
data: { taskId: task.id, cronExpression, recurring },
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const MONITOR_USAGE = 'Usage: /monitor "<command>" "<pattern>" <instruction>';
|
|
41
|
+
|
|
42
|
+
/** Parse `"<command>" "<pattern>" <instruction>` (quotes may be single or double). */
|
|
43
|
+
function parseMonitorArgs(
|
|
44
|
+
args: string,
|
|
45
|
+
): { command: string; matchPattern: string; instruction: string } | null {
|
|
46
|
+
const match = /^["']([^"']+)["']\s+["']([^"']+)["']\s+(.+)$/.exec(args.trim());
|
|
47
|
+
if (!match) return null;
|
|
48
|
+
const instruction = match[3]!.trim();
|
|
49
|
+
if (instruction.length === 0) return null;
|
|
50
|
+
return { command: match[1]!, matchPattern: match[2]!, instruction };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function executeMonitorCommand(
|
|
54
|
+
host: IAgentJobHostContext,
|
|
55
|
+
args: string,
|
|
56
|
+
): Promise<ICommandResult> {
|
|
57
|
+
const parsed = parseMonitorArgs(args);
|
|
58
|
+
if (!parsed) return { message: MONITOR_USAGE, success: false };
|
|
59
|
+
|
|
60
|
+
const task = await host.spawnMonitorWake({
|
|
61
|
+
label: labelFor('Monitor', parsed.instruction),
|
|
62
|
+
command: parsed.command,
|
|
63
|
+
matchPattern: parsed.matchPattern,
|
|
64
|
+
agentInstruction: parsed.instruction,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
message: `Monitoring \`${parsed.command}\` for /${parsed.matchPattern}/ — task ${task.id}.`,
|
|
69
|
+
success: true,
|
|
70
|
+
data: { taskId: task.id, matchPattern: parsed.matchPattern },
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FLOW-005: parse the `<when>` portion of `/schedule` into a cron expression croner accepts.
|
|
3
|
+
*
|
|
4
|
+
* Two forms:
|
|
5
|
+
* in <N><unit> <instruction> — one-shot, fires once at now + duration (s|m|h|d)
|
|
6
|
+
* cron "<expr>" <instruction> — recurring, a standard cron expression
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export interface IScheduleSpec {
|
|
10
|
+
cronExpression: string;
|
|
11
|
+
instruction: string;
|
|
12
|
+
recurring: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type TScheduleParseResult = { ok: true; spec: IScheduleSpec } | { ok: false; error: string };
|
|
16
|
+
|
|
17
|
+
const DURATION_MS: Record<string, number> = {
|
|
18
|
+
s: 1_000,
|
|
19
|
+
m: 60_000,
|
|
20
|
+
h: 3_600_000,
|
|
21
|
+
d: 86_400_000,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const USAGE =
|
|
25
|
+
'Usage: /schedule in <N><s|m|h|d> <instruction> | /schedule cron "<expr>" <instruction>';
|
|
26
|
+
|
|
27
|
+
export function parseScheduleSpec(args: string, now: number): TScheduleParseResult {
|
|
28
|
+
const trimmed = args.trim();
|
|
29
|
+
if (trimmed.length === 0) return { ok: false, error: USAGE };
|
|
30
|
+
|
|
31
|
+
if (trimmed.startsWith('in ')) {
|
|
32
|
+
const rest = trimmed.slice(3).trim();
|
|
33
|
+
const spaceIdx = rest.indexOf(' ');
|
|
34
|
+
if (spaceIdx === -1) return { ok: false, error: `Missing instruction. ${USAGE}` };
|
|
35
|
+
const durationToken = rest.slice(0, spaceIdx);
|
|
36
|
+
const instruction = rest.slice(spaceIdx + 1).trim();
|
|
37
|
+
const match = /^(\d+)(s|m|h|d)$/.exec(durationToken);
|
|
38
|
+
if (!match) return { ok: false, error: `Invalid duration "${durationToken}". ${USAGE}` };
|
|
39
|
+
if (instruction.length === 0) return { ok: false, error: `Missing instruction. ${USAGE}` };
|
|
40
|
+
const ms = parseInt(match[1]!, 10) * DURATION_MS[match[2]!]!;
|
|
41
|
+
return {
|
|
42
|
+
ok: true,
|
|
43
|
+
spec: {
|
|
44
|
+
cronExpression: new Date(now + ms).toISOString(),
|
|
45
|
+
instruction,
|
|
46
|
+
recurring: false,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (trimmed.startsWith('cron ')) {
|
|
52
|
+
const rest = trimmed.slice(5).trim();
|
|
53
|
+
const quoted = /^["']([^"']+)["']\s+(.+)$/.exec(rest);
|
|
54
|
+
if (!quoted) {
|
|
55
|
+
return { ok: false, error: `cron form needs a quoted expression. ${USAGE}` };
|
|
56
|
+
}
|
|
57
|
+
const instruction = quoted[2]!.trim();
|
|
58
|
+
if (instruction.length === 0) return { ok: false, error: `Missing instruction. ${USAGE}` };
|
|
59
|
+
return {
|
|
60
|
+
ok: true,
|
|
61
|
+
spec: { cronExpression: quoted[1]!.trim(), instruction, recurring: true },
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return { ok: false, error: USAGE };
|
|
66
|
+
}
|
|
@@ -14,13 +14,12 @@ import {
|
|
|
14
14
|
executeValidateSessionCommand,
|
|
15
15
|
} from './session-command.js';
|
|
16
16
|
|
|
17
|
+
import type { ICommandModule, ISystemCommand } from '@robota-sdk/agent-framework';
|
|
17
18
|
import type {
|
|
18
19
|
ICommand,
|
|
19
20
|
ICommandInteractionHint,
|
|
20
|
-
ICommandModule,
|
|
21
21
|
ICommandSource,
|
|
22
|
-
|
|
23
|
-
} from '@robota-sdk/agent-framework';
|
|
22
|
+
} from '@robota-sdk/agent-interface-transport';
|
|
24
23
|
|
|
25
24
|
export function createClearCommandEntry(): ICommand {
|
|
26
25
|
return {
|
|
@@ -14,7 +14,8 @@ import {
|
|
|
14
14
|
|
|
15
15
|
import { calculateCost, formatTokens, formatUsd } from './model-pricing.js';
|
|
16
16
|
|
|
17
|
-
import type { ICommandHostContext
|
|
17
|
+
import type { ICommandHostContext } from '@robota-sdk/agent-framework';
|
|
18
|
+
import type { ICommandResult } from '@robota-sdk/agent-interface-transport';
|
|
18
19
|
|
|
19
20
|
export const CLEAR_COMMAND_MESSAGE = 'Conversation cleared.';
|
|
20
21
|
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
ICommandModule,
|
|
4
|
-
ICommandSource,
|
|
5
|
-
ISystemCommand,
|
|
6
|
-
} from '@robota-sdk/agent-framework';
|
|
1
|
+
import type { ICommandModule, ISystemCommand } from '@robota-sdk/agent-framework';
|
|
2
|
+
import type { ICommand, ICommandSource } from '@robota-sdk/agent-interface-transport';
|
|
7
3
|
|
|
8
4
|
export function createSettingsCommandEntry(): ICommand {
|
|
9
5
|
return {
|
|
@@ -2,12 +2,8 @@ import { SkillCommandSource } from '@robota-sdk/agent-framework';
|
|
|
2
2
|
|
|
3
3
|
import { executeSkillsCommand, SKILLS_COMMAND_DESCRIPTION } from './skills-command.js';
|
|
4
4
|
|
|
5
|
-
import type {
|
|
6
|
-
|
|
7
|
-
ICommandModule,
|
|
8
|
-
ICommandSource,
|
|
9
|
-
ISystemCommand,
|
|
10
|
-
} from '@robota-sdk/agent-framework';
|
|
5
|
+
import type { ICommandModule, ISystemCommand } from '@robota-sdk/agent-framework';
|
|
6
|
+
import type { ICommand, ICommandSource } from '@robota-sdk/agent-interface-transport';
|
|
11
7
|
|
|
12
8
|
export interface ISkillsCommandModuleOptions {
|
|
13
9
|
readonly cwd: string;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
ICommandResult,
|
|
4
|
-
ICommandSkillListEntry,
|
|
5
|
-
} from '@robota-sdk/agent-framework';
|
|
1
|
+
import type { ICommandHostContext, ICommandSkillListEntry } from '@robota-sdk/agent-framework';
|
|
2
|
+
import type { ICommandResult } from '@robota-sdk/agent-interface-transport';
|
|
6
3
|
|
|
7
4
|
export const SKILLS_COMMAND_DESCRIPTION =
|
|
8
5
|
'Skill command. Before following a matching registered skill from the system prompt Skills section, invoke the projected skills command tool with args "<skill-name> [args]". Without arguments, list registered skills. With a skill name, activate that skill. Slash syntax is a UI input/display concern; the SDK command identity is "skills".';
|
|
@@ -6,12 +6,8 @@ import {
|
|
|
6
6
|
|
|
7
7
|
import { executeStatusLineCommand } from './statusline-command.js';
|
|
8
8
|
|
|
9
|
-
import type {
|
|
10
|
-
|
|
11
|
-
ICommandModule,
|
|
12
|
-
ICommandSource,
|
|
13
|
-
ISystemCommand,
|
|
14
|
-
} from '@robota-sdk/agent-framework';
|
|
9
|
+
import type { ICommandModule, ISystemCommand } from '@robota-sdk/agent-framework';
|
|
10
|
+
import type { ICommand, ICommandSource } from '@robota-sdk/agent-interface-transport';
|
|
15
11
|
|
|
16
12
|
export function createStatusLineCommandEntry(): ICommand {
|
|
17
13
|
return {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { DEFAULT_STATUS_LINE_COMMAND_SETTINGS } from '@robota-sdk/agent-framework';
|
|
2
2
|
|
|
3
|
+
import type { ICommandHostContext } from '@robota-sdk/agent-framework';
|
|
3
4
|
import type {
|
|
4
|
-
ICommandHostContext,
|
|
5
5
|
ICommandResult,
|
|
6
6
|
TStatusLineCommandSettingsPatch,
|
|
7
|
-
} from '@robota-sdk/agent-
|
|
7
|
+
} from '@robota-sdk/agent-interface-transport';
|
|
8
8
|
|
|
9
9
|
interface IStatusLineCommandSuccessAction {
|
|
10
10
|
success: true;
|
|
@@ -4,12 +4,8 @@ import {
|
|
|
4
4
|
executeUserLocalCommand,
|
|
5
5
|
} from './user-local-command.js';
|
|
6
6
|
|
|
7
|
-
import type {
|
|
8
|
-
|
|
9
|
-
ICommandModule,
|
|
10
|
-
ICommandSource,
|
|
11
|
-
ISystemCommand,
|
|
12
|
-
} from '@robota-sdk/agent-framework';
|
|
7
|
+
import type { ICommandModule, ISystemCommand } from '@robota-sdk/agent-framework';
|
|
8
|
+
import type { ICommand, ICommandSource } from '@robota-sdk/agent-interface-transport';
|
|
13
9
|
|
|
14
10
|
export function createUserLocalCommandEntry(): ICommand {
|
|
15
11
|
return {
|
|
@@ -3,7 +3,8 @@ import { inspectUserLocalStorage } from '@robota-sdk/agent-framework';
|
|
|
3
3
|
import { USER_LOCAL_COMMAND_USAGE } from './user-local-command-constants.js';
|
|
4
4
|
import { executeMemoryCommand } from './user-local-memory-command.js';
|
|
5
5
|
|
|
6
|
-
import type { ICommandHostContext
|
|
6
|
+
import type { ICommandHostContext } from '@robota-sdk/agent-framework';
|
|
7
|
+
import type { ICommandResult } from '@robota-sdk/agent-interface-transport';
|
|
7
8
|
export {
|
|
8
9
|
USER_LOCAL_COMMAND_ARGUMENT_HINT,
|
|
9
10
|
USER_LOCAL_COMMAND_DESCRIPTION,
|
|
@@ -8,7 +8,8 @@ import {
|
|
|
8
8
|
|
|
9
9
|
import { USER_LOCAL_COMMAND_USAGE } from './user-local-command-constants.js';
|
|
10
10
|
|
|
11
|
-
import type {
|
|
11
|
+
import type { TUserLocalMemoryCategory } from '@robota-sdk/agent-framework';
|
|
12
|
+
import type { ICommandResult } from '@robota-sdk/agent-interface-transport';
|
|
12
13
|
|
|
13
14
|
export interface IUserLocalMemoryCommandArgs {
|
|
14
15
|
readonly action?: string;
|