opencode-routines 0.1.2 → 0.1.4
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/index.d.ts +0 -51
- package/dist/index.js +10 -8
- package/dist/tui.d.ts +1 -56
- package/dist/tui.js +88 -59
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -12,56 +12,5 @@
|
|
|
12
12
|
* - Environment variable injection (PATH for node/npx)
|
|
13
13
|
*/
|
|
14
14
|
import type { Plugin } from "@opencode-ai/plugin";
|
|
15
|
-
type OpencodeRunFormat = "default" | "json";
|
|
16
|
-
interface JobRunSpec {
|
|
17
|
-
prompt?: string;
|
|
18
|
-
command?: string;
|
|
19
|
-
arguments?: string;
|
|
20
|
-
files?: string[];
|
|
21
|
-
agent?: string;
|
|
22
|
-
model?: string;
|
|
23
|
-
variant?: string;
|
|
24
|
-
title?: string;
|
|
25
|
-
share?: boolean;
|
|
26
|
-
continue?: boolean;
|
|
27
|
-
session?: string;
|
|
28
|
-
runFormat?: OpencodeRunFormat;
|
|
29
|
-
attachUrl?: string;
|
|
30
|
-
port?: number;
|
|
31
|
-
}
|
|
32
|
-
type JobInvocation = {
|
|
33
|
-
command: string;
|
|
34
|
-
args: string[];
|
|
35
|
-
};
|
|
36
|
-
interface Job {
|
|
37
|
-
scopeId?: string;
|
|
38
|
-
slug: string;
|
|
39
|
-
name: string;
|
|
40
|
-
schedule: string;
|
|
41
|
-
prompt?: string;
|
|
42
|
-
attachUrl?: string;
|
|
43
|
-
run?: JobRunSpec;
|
|
44
|
-
invocation?: JobInvocation;
|
|
45
|
-
timeoutSeconds?: number;
|
|
46
|
-
source?: string;
|
|
47
|
-
workdir?: string;
|
|
48
|
-
createdAt: string;
|
|
49
|
-
updatedAt?: string;
|
|
50
|
-
lastRunAt?: string;
|
|
51
|
-
lastRunExitCode?: number;
|
|
52
|
-
lastRunError?: string;
|
|
53
|
-
lastRunSource?: "manual" | "scheduled";
|
|
54
|
-
lastRunStatus?: "running" | "success" | "failed";
|
|
55
|
-
}
|
|
56
|
-
type RoutinePromptClient = {
|
|
57
|
-
session?: {
|
|
58
|
-
prompt?: (input: unknown) => Promise<unknown>;
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
|
-
export declare function __testSubmitSessionPrompt(client: RoutinePromptClient, sessionID: string, prompt: string): Promise<void>;
|
|
62
|
-
export declare function __testBuildOpencodeArgs(job: Job): {
|
|
63
|
-
command: string;
|
|
64
|
-
args: string[];
|
|
65
|
-
};
|
|
66
15
|
export declare const SchedulerPlugin: Plugin;
|
|
67
16
|
export default SchedulerPlugin;
|
package/dist/index.js
CHANGED
|
@@ -12969,17 +12969,17 @@ function promptResultError(result) {
|
|
|
12969
12969
|
return;
|
|
12970
12970
|
return typeof error45 === "string" ? error45 : JSON.stringify(error45);
|
|
12971
12971
|
}
|
|
12972
|
-
async function
|
|
12972
|
+
async function testSubmitSessionPrompt(client, sessionID, prompt) {
|
|
12973
12973
|
await submitSessionPrompt(client, sessionID, prompt);
|
|
12974
12974
|
}
|
|
12975
12975
|
async function submitSessionPrompt(client, sessionID, prompt) {
|
|
12976
12976
|
const session = client.session;
|
|
12977
|
-
const send = session?.
|
|
12977
|
+
const send = session?.promptAsync;
|
|
12978
12978
|
if (!send)
|
|
12979
|
-
throw new Error("Current opencode client does not expose session.
|
|
12979
|
+
throw new Error("Current opencode client does not expose session.promptAsync");
|
|
12980
12980
|
const result = await send.call(session, {
|
|
12981
|
-
sessionID,
|
|
12982
|
-
parts: [{ type: "text", text: prompt }]
|
|
12981
|
+
path: { id: sessionID },
|
|
12982
|
+
body: { parts: [{ type: "text", text: prompt }] }
|
|
12983
12983
|
});
|
|
12984
12984
|
const error45 = promptResultError(result);
|
|
12985
12985
|
if (error45)
|
|
@@ -14182,7 +14182,7 @@ function buildOpencodeArgs(job) {
|
|
|
14182
14182
|
args.push(run.command ? run.arguments ?? "" : run.prompt ?? "");
|
|
14183
14183
|
return { command, args };
|
|
14184
14184
|
}
|
|
14185
|
-
function
|
|
14185
|
+
function testBuildOpencodeArgs(job) {
|
|
14186
14186
|
return buildOpencodeArgs(job);
|
|
14187
14187
|
}
|
|
14188
14188
|
function buildRunEnvironment() {
|
|
@@ -15386,10 +15386,12 @@ ${logs}`, { job, logPath, logs });
|
|
|
15386
15386
|
}
|
|
15387
15387
|
};
|
|
15388
15388
|
};
|
|
15389
|
+
SchedulerPlugin.__test = {
|
|
15390
|
+
buildOpencodeArgs: testBuildOpencodeArgs,
|
|
15391
|
+
submitSessionPrompt: testSubmitSessionPrompt
|
|
15392
|
+
};
|
|
15389
15393
|
var src_default = SchedulerPlugin;
|
|
15390
15394
|
export {
|
|
15391
15395
|
src_default as default,
|
|
15392
|
-
__testSubmitSessionPrompt,
|
|
15393
|
-
__testBuildOpencodeArgs,
|
|
15394
15396
|
SchedulerPlugin
|
|
15395
15397
|
};
|
package/dist/tui.d.ts
CHANGED
|
@@ -1,59 +1,4 @@
|
|
|
1
|
-
type
|
|
2
|
-
route: {
|
|
3
|
-
current: {
|
|
4
|
-
name: string;
|
|
5
|
-
params?: Record<string, any>;
|
|
6
|
-
};
|
|
7
|
-
navigate?: (name: string, params?: Record<string, unknown>) => void;
|
|
8
|
-
};
|
|
9
|
-
client: {
|
|
10
|
-
session: {
|
|
11
|
-
prompt: (input: any) => Promise<unknown>;
|
|
12
|
-
};
|
|
13
|
-
};
|
|
14
|
-
ui: {
|
|
15
|
-
dialog: {
|
|
16
|
-
replace: (render: () => any) => void;
|
|
17
|
-
clear: () => void;
|
|
18
|
-
};
|
|
19
|
-
DialogAlert: (props: {
|
|
20
|
-
title: string;
|
|
21
|
-
message: string;
|
|
22
|
-
}) => any;
|
|
23
|
-
DialogPrompt: (props: {
|
|
24
|
-
title: string;
|
|
25
|
-
placeholder?: string;
|
|
26
|
-
onConfirm?: (value: string) => void;
|
|
27
|
-
}) => any;
|
|
28
|
-
DialogSelect: (props: {
|
|
29
|
-
title: string;
|
|
30
|
-
options: Array<{
|
|
31
|
-
title: string;
|
|
32
|
-
value: string;
|
|
33
|
-
description?: string;
|
|
34
|
-
footer?: string;
|
|
35
|
-
}>;
|
|
36
|
-
onSelect?: (option: {
|
|
37
|
-
value: string;
|
|
38
|
-
}) => void;
|
|
39
|
-
}) => any;
|
|
40
|
-
toast: (input: {
|
|
41
|
-
variant?: "info" | "success" | "warning" | "error";
|
|
42
|
-
title?: string;
|
|
43
|
-
message: string;
|
|
44
|
-
}) => void;
|
|
45
|
-
};
|
|
46
|
-
lifecycle: {
|
|
47
|
-
onDispose: (fn: () => void) => void;
|
|
48
|
-
};
|
|
49
|
-
keymap: {
|
|
50
|
-
registerLayer: (input: {
|
|
51
|
-
commands: any[];
|
|
52
|
-
bindings?: any[];
|
|
53
|
-
}) => unknown;
|
|
54
|
-
};
|
|
55
|
-
};
|
|
56
|
-
type TuiPlugin = (api: TuiApi, options?: Record<string, unknown>, meta?: Record<string, unknown>) => Promise<void>;
|
|
1
|
+
import type { TuiPlugin } from "@opencode-ai/plugin/tui";
|
|
57
2
|
declare const _default: {
|
|
58
3
|
id: string;
|
|
59
4
|
tui: TuiPlugin;
|
package/dist/tui.js
CHANGED
|
@@ -54,11 +54,9 @@ function loopID() {
|
|
|
54
54
|
}
|
|
55
55
|
async function submitPrompt(api, loop) {
|
|
56
56
|
loop.fires += 1;
|
|
57
|
-
await api.client.session.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
parts: [{ type: "text", text: loop.prompt }]
|
|
61
|
-
}
|
|
57
|
+
await api.client.session.promptAsync({
|
|
58
|
+
sessionID: loop.sessionID,
|
|
59
|
+
parts: [{ type: "text", text: loop.prompt }]
|
|
62
60
|
});
|
|
63
61
|
}
|
|
64
62
|
function scheduleFixed(api, loop) {
|
|
@@ -113,11 +111,92 @@ function showLoops(api) {
|
|
|
113
111
|
}
|
|
114
112
|
}));
|
|
115
113
|
}
|
|
114
|
+
function openLoopPrompt(api) {
|
|
115
|
+
const sessionID = activeSessionID(api);
|
|
116
|
+
if (!sessionID) {
|
|
117
|
+
api.ui.toast({ variant: "warning", message: "Open a session before starting /loop." });
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
api.ui.dialog.replace(() => api.ui.DialogPrompt({
|
|
121
|
+
title: "Start loop",
|
|
122
|
+
placeholder: "5m /babysit-prs or /babysit-prs",
|
|
123
|
+
onConfirm: (value) => {
|
|
124
|
+
const parsed = parseLoop(value);
|
|
125
|
+
if (!parsed) {
|
|
126
|
+
api.ui.toast({ variant: "warning", message: "Usage: /loop 5m <prompt> or /loop <prompt>" });
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const loop = {
|
|
130
|
+
id: loopID(),
|
|
131
|
+
sessionID,
|
|
132
|
+
prompt: parsed.prompt,
|
|
133
|
+
mode: parsed.intervalSeconds === undefined ? "dynamic" : "fixed",
|
|
134
|
+
intervalSeconds: parsed.intervalSeconds,
|
|
135
|
+
createdAt: new Date().toISOString(),
|
|
136
|
+
fires: 0
|
|
137
|
+
};
|
|
138
|
+
loops.set(loop.id, loop);
|
|
139
|
+
if (loop.mode === "fixed")
|
|
140
|
+
scheduleFixed(api, loop);
|
|
141
|
+
else
|
|
142
|
+
submitPrompt(api, loop);
|
|
143
|
+
api.ui.toast({
|
|
144
|
+
variant: "success",
|
|
145
|
+
title: "Loop started",
|
|
146
|
+
message: loop.mode === "fixed" ? `${loop.id} every ${loop.intervalSeconds}s` : `${loop.id} dynamic mode; use ScheduleWakeup to continue`
|
|
147
|
+
});
|
|
148
|
+
api.ui.dialog.clear();
|
|
149
|
+
}
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
function showStandaloneSchedulesHelp(api) {
|
|
153
|
+
api.ui.dialog.replace(() => api.ui.DialogAlert({
|
|
154
|
+
title: "Standalone schedules",
|
|
155
|
+
message: "Use the ScheduleCreate tool (or natural language like 'create a standalone scheduled run...') to create durable OS-backed standalone sessions. The ambiguous /schedule command is intentionally not registered."
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
function legacyCommands(api) {
|
|
159
|
+
return [
|
|
160
|
+
{
|
|
161
|
+
title: "Start same-session loop",
|
|
162
|
+
value: "routines.loop",
|
|
163
|
+
description: "Start a same-session loop. Fixed: 5m <prompt>; dynamic: <prompt>.",
|
|
164
|
+
category: "Scheduler",
|
|
165
|
+
slash: { name: "loop" },
|
|
166
|
+
onSelect: () => openLoopPrompt(api)
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
title: "List active loops",
|
|
170
|
+
value: "routines.loops",
|
|
171
|
+
description: "List and stop active same-session loops.",
|
|
172
|
+
category: "Scheduler",
|
|
173
|
+
slash: { name: "loops" },
|
|
174
|
+
onSelect: () => showLoops(api)
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
title: "Stop a same-session loop",
|
|
178
|
+
value: "routines.stop-loop",
|
|
179
|
+
description: "List active loops and select one to stop.",
|
|
180
|
+
category: "Scheduler",
|
|
181
|
+
slash: { name: "stop-loop" },
|
|
182
|
+
onSelect: () => showLoops(api)
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
title: "Create standalone scheduled session",
|
|
186
|
+
value: "routines.schedule-standalone-session",
|
|
187
|
+
description: "Show help for durable OS-backed standalone schedules.",
|
|
188
|
+
category: "Scheduler",
|
|
189
|
+
slash: { name: "schedule-standalone-session" },
|
|
190
|
+
onSelect: () => showStandaloneSchedulesHelp(api)
|
|
191
|
+
}
|
|
192
|
+
];
|
|
193
|
+
}
|
|
116
194
|
var tui = async (api) => {
|
|
117
195
|
api.lifecycle.onDispose(() => {
|
|
118
196
|
for (const id of [...loops.keys()])
|
|
119
197
|
stopLoop(id);
|
|
120
198
|
});
|
|
199
|
+
api.command?.register(() => legacyCommands(api));
|
|
121
200
|
api.keymap.registerLayer({
|
|
122
201
|
commands: [
|
|
123
202
|
{
|
|
@@ -125,78 +204,28 @@ var tui = async (api) => {
|
|
|
125
204
|
title: "Start same-session loop",
|
|
126
205
|
category: "Scheduler",
|
|
127
206
|
namespace: "palette",
|
|
128
|
-
|
|
129
|
-
run() {
|
|
130
|
-
const sessionID = activeSessionID(api);
|
|
131
|
-
if (!sessionID) {
|
|
132
|
-
api.ui.toast({ variant: "warning", message: "Open a session before starting /loop." });
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
api.ui.dialog.replace(() => api.ui.DialogPrompt({
|
|
136
|
-
title: "Start loop",
|
|
137
|
-
placeholder: "5m /babysit-prs or /babysit-prs",
|
|
138
|
-
onConfirm: (value) => {
|
|
139
|
-
const parsed = parseLoop(value);
|
|
140
|
-
if (!parsed) {
|
|
141
|
-
api.ui.toast({ variant: "warning", message: "Usage: /loop 5m <prompt> or /loop <prompt>" });
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
const loop = {
|
|
145
|
-
id: loopID(),
|
|
146
|
-
sessionID,
|
|
147
|
-
prompt: parsed.prompt,
|
|
148
|
-
mode: parsed.intervalSeconds === undefined ? "dynamic" : "fixed",
|
|
149
|
-
intervalSeconds: parsed.intervalSeconds,
|
|
150
|
-
createdAt: new Date().toISOString(),
|
|
151
|
-
fires: 0
|
|
152
|
-
};
|
|
153
|
-
loops.set(loop.id, loop);
|
|
154
|
-
if (loop.mode === "fixed")
|
|
155
|
-
scheduleFixed(api, loop);
|
|
156
|
-
else
|
|
157
|
-
submitPrompt(api, loop);
|
|
158
|
-
api.ui.toast({
|
|
159
|
-
variant: "success",
|
|
160
|
-
title: "Loop started",
|
|
161
|
-
message: loop.mode === "fixed" ? `${loop.id} every ${loop.intervalSeconds}s` : `${loop.id} dynamic mode; use ScheduleWakeup to continue`
|
|
162
|
-
});
|
|
163
|
-
api.ui.dialog.clear();
|
|
164
|
-
}
|
|
165
|
-
}));
|
|
166
|
-
}
|
|
207
|
+
run: () => openLoopPrompt(api)
|
|
167
208
|
},
|
|
168
209
|
{
|
|
169
210
|
name: "routines.loops",
|
|
170
211
|
title: "List active loops",
|
|
171
212
|
category: "Scheduler",
|
|
172
213
|
namespace: "palette",
|
|
173
|
-
|
|
174
|
-
run() {
|
|
175
|
-
showLoops(api);
|
|
176
|
-
}
|
|
214
|
+
run: () => showLoops(api)
|
|
177
215
|
},
|
|
178
216
|
{
|
|
179
217
|
name: "routines.stop_loop",
|
|
180
218
|
title: "Stop a same-session loop",
|
|
181
219
|
category: "Scheduler",
|
|
182
220
|
namespace: "palette",
|
|
183
|
-
|
|
184
|
-
run() {
|
|
185
|
-
showLoops(api);
|
|
186
|
-
}
|
|
221
|
+
run: () => showLoops(api)
|
|
187
222
|
},
|
|
188
223
|
{
|
|
189
224
|
name: "routines.schedule_standalone_session",
|
|
190
225
|
title: "Create standalone scheduled session",
|
|
191
226
|
category: "Scheduler",
|
|
192
227
|
namespace: "palette",
|
|
193
|
-
|
|
194
|
-
run() {
|
|
195
|
-
api.ui.dialog.replace(() => api.ui.DialogAlert({
|
|
196
|
-
title: "Standalone schedules",
|
|
197
|
-
message: "Use the ScheduleCreate tool (or natural language like 'create a standalone scheduled run...') to create durable OS-backed standalone sessions. The ambiguous /schedule command is intentionally not registered."
|
|
198
|
-
}));
|
|
199
|
-
}
|
|
228
|
+
run: () => showStandaloneSchedulesHelp(api)
|
|
200
229
|
}
|
|
201
230
|
]
|
|
202
231
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-routines",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "OpenCode routines: same-session loops, cron prompts, and host-backed standalone scheduled agents",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -54,13 +54,13 @@
|
|
|
54
54
|
},
|
|
55
55
|
"homepage": "https://github.com/EmilioEsposito/opencode-routines#readme",
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@opencode-ai/plugin": "^1.
|
|
57
|
+
"@opencode-ai/plugin": "^1.17.3"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"bun-types": "latest",
|
|
61
61
|
"typescript": "^5.7.3"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
|
-
"@opencode-ai/plugin": ">=1.
|
|
64
|
+
"@opencode-ai/plugin": ">=1.17.3"
|
|
65
65
|
}
|
|
66
66
|
}
|