@agimon-ai/doompi-loop 0.0.1-alpha.9 → 0.0.1-alpha.91
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/README.md +83 -21
- package/dist/apiContracts.cjs +17 -0
- package/dist/apiContracts.cjs.map +1 -0
- package/dist/apiContracts.d.mts +53 -0
- package/dist/apiContracts.d.mts.map +1 -0
- package/dist/apiContracts.mjs +13 -0
- package/dist/apiContracts.mjs.map +1 -0
- package/dist/extensions/pi.cjs +659 -1
- package/dist/extensions/pi.cjs.map +1 -1
- package/dist/extensions/pi.d.mts +5 -2
- package/dist/extensions/pi.d.mts.map +1 -0
- package/dist/extensions/pi.mjs +654 -1
- package/dist/extensions/pi.mjs.map +1 -1
- package/dist/extensions/server.cjs +369 -0
- package/dist/extensions/server.cjs.map +1 -0
- package/dist/extensions/server.d.mts +5 -0
- package/dist/extensions/server.d.mts.map +1 -0
- package/dist/extensions/server.mjs +364 -0
- package/dist/extensions/server.mjs.map +1 -0
- package/dist/extensions/web.mjs +331 -0
- package/dist/extensions/web.mjs.map +1 -0
- package/dist/index.cjs +0 -1
- package/dist/index.d.mts +2 -4
- package/dist/index.mjs +1 -1
- package/dist/loopLaunchers-Bciapxt0.d.mts +69 -0
- package/dist/loopLaunchers-Bciapxt0.d.mts.map +1 -0
- package/dist/loopLaunchers-BtcLH_xN.cjs +32 -0
- package/dist/loopLaunchers-BtcLH_xN.cjs.map +1 -0
- package/dist/loopLaunchers-cCniFbVA.mjs +15 -0
- package/dist/loopLaunchers-cCniFbVA.mjs.map +1 -0
- package/dist/loopLaunchers.cjs +5 -0
- package/dist/loopLaunchers.d.mts +2 -0
- package/dist/loopLaunchers.mjs +2 -0
- package/dist/loopView-BK4X_1UI.mjs +349 -0
- package/dist/loopView-BK4X_1UI.mjs.map +1 -0
- package/dist/loopView-C_OPuy8L.cjs +456 -0
- package/dist/loopView-C_OPuy8L.cjs.map +1 -0
- package/llms.txt +9 -0
- package/package.json +82 -14
- package/src/prompts/doompi-use-loop/SKILL.md +44 -0
- package/src/types/loopView.ts +73 -0
- package/dist/commands/loopCommand.cjs +0 -2
- package/dist/commands/loopCommand.cjs.map +0 -1
- package/dist/commands/loopCommand.mjs +0 -2
- package/dist/commands/loopCommand.mjs.map +0 -1
- package/dist/constants.cjs +0 -2
- package/dist/constants.cjs.map +0 -1
- package/dist/constants.mjs +0 -2
- package/dist/constants.mjs.map +0 -1
- package/dist/defaultLauncher.cjs +0 -2
- package/dist/defaultLauncher.cjs.map +0 -1
- package/dist/defaultLauncher.d.cts +0 -10
- package/dist/defaultLauncher.d.cts.map +0 -1
- package/dist/defaultLauncher.d.mts +0 -10
- package/dist/defaultLauncher.d.mts.map +0 -1
- package/dist/defaultLauncher.mjs +0 -2
- package/dist/defaultLauncher.mjs.map +0 -1
- package/dist/extension.cjs +0 -2
- package/dist/extension.cjs.map +0 -1
- package/dist/extension.d.cts +0 -6
- package/dist/extension.d.cts.map +0 -1
- package/dist/extension.d.mts +0 -6
- package/dist/extension.d.mts.map +0 -1
- package/dist/extension.mjs +0 -2
- package/dist/extension.mjs.map +0 -1
- package/dist/extensions/pi.d.cts +0 -2
- package/dist/index.d.cts +0 -4
- package/dist/launcher.cjs +0 -2
- package/dist/launcher.cjs.map +0 -1
- package/dist/launcher.d.cts +0 -47
- package/dist/launcher.d.cts.map +0 -1
- package/dist/launcher.d.mts +0 -47
- package/dist/launcher.d.mts.map +0 -1
- package/dist/launcher.mjs +0 -2
- package/dist/launcher.mjs.map +0 -1
- package/dist/leader.cjs +0 -2
- package/dist/leader.cjs.map +0 -1
- package/dist/leader.mjs +0 -2
- package/dist/leader.mjs.map +0 -1
- package/dist/tui/loopListOverlay.cjs +0 -2
- package/dist/tui/loopListOverlay.cjs.map +0 -1
- package/dist/tui/loopListOverlay.mjs +0 -2
- package/dist/tui/loopListOverlay.mjs.map +0 -1
- package/dist/tui/startLoopOverlay.cjs +0 -2
- package/dist/tui/startLoopOverlay.cjs.map +0 -1
- package/dist/tui/startLoopOverlay.mjs +0 -2
- package/dist/tui/startLoopOverlay.mjs.map +0 -1
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import { t as DOOM_LOOP_LAUNCHERS_SERVICE } from "../loopLaunchers-cCniFbVA.mjs";
|
|
2
|
+
import { _ as PACKAGE_SOURCE, a as CronLoopSchema, c as parseIntervalLoop, f as START_COMMAND_NAME, i as createDoomLoopLaunchersService, m as MODE_STATUS_ID, n as formatLoopStatusView, o as IntervalLoopSchema, r as createLoopTools, s as parseCronLoop, t as LOOP_VIEW_STATUS_KEY, u as LIST_COMMAND_NAME } from "../loopView-BK4X_1UI.mjs";
|
|
3
|
+
import { composeRootHooks, defineRoot, defineRoutedContribution, defineTool } from "@agimon-ai/doompi-core/extensionFile";
|
|
4
|
+
import { defineMinorMode, serverMinorModes } from "@agimon-ai/doompi-minor-mode";
|
|
5
|
+
import { Cron } from "croner";
|
|
6
|
+
import { defineServerPlugin, readPackageResource } from "@agimon-ai/doompi-core/serverFacet";
|
|
7
|
+
//#region src/services/serverRuntime/index.ts
|
|
8
|
+
async function prepareLoop(execution, request, cron) {
|
|
9
|
+
if (request.input !== void 0) return cron ? parseCronLoop(request.input) : parseIntervalLoop(request.input);
|
|
10
|
+
if (request.interactive === false) throw new Error("Loop configuration is required for agent launches.");
|
|
11
|
+
const input = await execution.client.request({
|
|
12
|
+
kind: "input",
|
|
13
|
+
title: "Loop prompt",
|
|
14
|
+
multiline: true
|
|
15
|
+
}, request.signal);
|
|
16
|
+
const prompt = typeof input === "string" ? input.trim() : "";
|
|
17
|
+
if (!prompt || request.signal.aborted) return void 0;
|
|
18
|
+
if (cron) {
|
|
19
|
+
const expression = await execution.client.request({
|
|
20
|
+
kind: "input",
|
|
21
|
+
title: "Cron expression (five fields)",
|
|
22
|
+
initialValue: "0 * * * *"
|
|
23
|
+
}, request.signal);
|
|
24
|
+
if (typeof expression !== "string" || request.signal.aborted) return void 0;
|
|
25
|
+
const timezone = await execution.client.request({
|
|
26
|
+
kind: "input",
|
|
27
|
+
title: "Loop timezone",
|
|
28
|
+
initialValue: "UTC"
|
|
29
|
+
}, request.signal);
|
|
30
|
+
if (typeof timezone !== "string" || request.signal.aborted) return void 0;
|
|
31
|
+
return parseCronLoop({
|
|
32
|
+
prompt,
|
|
33
|
+
cron: expression,
|
|
34
|
+
timezone: timezone.trim() || "UTC"
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const interval = await execution.client.request({
|
|
38
|
+
kind: "input",
|
|
39
|
+
title: "Loop interval in seconds",
|
|
40
|
+
initialValue: "300"
|
|
41
|
+
}, request.signal);
|
|
42
|
+
if (typeof interval !== "string" || request.signal.aborted) return void 0;
|
|
43
|
+
return parseIntervalLoop({
|
|
44
|
+
prompt,
|
|
45
|
+
intervalSeconds: Number(interval.trim() || "300")
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function createSessionState(host) {
|
|
49
|
+
const launchers = createDoomLoopLaunchersService({
|
|
50
|
+
generation: `${host.context.sessionId}:loop-launchers`,
|
|
51
|
+
createInstanceId: () => crypto.randomUUID(),
|
|
52
|
+
timestamp: () => (/* @__PURE__ */ new Date()).toISOString()
|
|
53
|
+
});
|
|
54
|
+
let disposed = false;
|
|
55
|
+
const modeSelected = () => !disposed && (host.context.selection.state?.["minor-mode"] ?? []).includes("loop.active");
|
|
56
|
+
const publishView = () => host.context.client.setStatus(LOOP_VIEW_STATUS_KEY, formatLoopStatusView(launchers.listInstances()));
|
|
57
|
+
const modeOwner = defineMinorMode({
|
|
58
|
+
descriptor: {
|
|
59
|
+
source: PACKAGE_SOURCE,
|
|
60
|
+
id: MODE_STATUS_ID,
|
|
61
|
+
label: "Loop",
|
|
62
|
+
description: "Give the agent tools to create, inspect, and stop session loops.",
|
|
63
|
+
order: 60,
|
|
64
|
+
actions: [{
|
|
65
|
+
id: "activate",
|
|
66
|
+
label: "Activate",
|
|
67
|
+
description: "Expose loop tools to the agent.",
|
|
68
|
+
contexts: ["headless"],
|
|
69
|
+
parameters: []
|
|
70
|
+
}, {
|
|
71
|
+
id: "deactivate",
|
|
72
|
+
label: "Deactivate",
|
|
73
|
+
description: "Hide agent loop tools. Existing loops and manual controls remain available.",
|
|
74
|
+
contexts: ["headless"],
|
|
75
|
+
parameters: []
|
|
76
|
+
}]
|
|
77
|
+
},
|
|
78
|
+
state: () => ({
|
|
79
|
+
activation: modeSelected() ? "active" : "inactive",
|
|
80
|
+
condition: "ready",
|
|
81
|
+
...modeSelected() ? {
|
|
82
|
+
detail: `${launchers.listInstances().length} loops`,
|
|
83
|
+
color: "accent"
|
|
84
|
+
} : {},
|
|
85
|
+
actions: [{
|
|
86
|
+
id: "activate",
|
|
87
|
+
enabled: !modeSelected(),
|
|
88
|
+
...modeSelected() ? { disabledReason: "Loop mode is already active." } : {}
|
|
89
|
+
}, {
|
|
90
|
+
id: "deactivate",
|
|
91
|
+
enabled: modeSelected(),
|
|
92
|
+
...modeSelected() ? {} : { disabledReason: "Loop mode is not active." }
|
|
93
|
+
}]
|
|
94
|
+
}),
|
|
95
|
+
async handleAction(_runtime, actionId, _arguments, { signal }) {
|
|
96
|
+
signal.throwIfAborted();
|
|
97
|
+
if (actionId !== "activate" && actionId !== "deactivate") throw new Error(`Unknown loop mode action: ${actionId}`);
|
|
98
|
+
const modes = (host.context.selection.state?.["minor-mode"] ?? []).filter((mode) => mode !== MODE_STATUS_ID);
|
|
99
|
+
await host.changeSelection({
|
|
100
|
+
axis: "state",
|
|
101
|
+
key: "minor-mode",
|
|
102
|
+
values: actionId === "activate" ? [...modes, MODE_STATUS_ID] : modes
|
|
103
|
+
});
|
|
104
|
+
modeOwner.publish();
|
|
105
|
+
return { message: actionId === "activate" ? "Loop tools activated." : "Loop tools deactivated. Existing loops are unchanged." };
|
|
106
|
+
}
|
|
107
|
+
}).createOwner(void 0);
|
|
108
|
+
const publish = () => {
|
|
109
|
+
if (disposed) return;
|
|
110
|
+
modeOwner.publish();
|
|
111
|
+
publishView();
|
|
112
|
+
};
|
|
113
|
+
const unsubscribe = launchers.subscribe(publish);
|
|
114
|
+
let submitting = false;
|
|
115
|
+
for (const cron of [false, true]) launchers.register({
|
|
116
|
+
id: cron ? "doompi.cron" : "doompi.default",
|
|
117
|
+
source: PACKAGE_SOURCE,
|
|
118
|
+
label: cron ? "Cron loop" : "Default loop",
|
|
119
|
+
description: cron ? "Run a prompt on a five-field cron schedule." : "Run a prompt in this session on an interval.",
|
|
120
|
+
inputSchema: { ...cron ? CronLoopSchema : IntervalLoopSchema },
|
|
121
|
+
async launch(request) {
|
|
122
|
+
const execution = host.context;
|
|
123
|
+
const prepared = await prepareLoop(execution, request, cron);
|
|
124
|
+
if (!prepared || request.signal.aborted) return void 0;
|
|
125
|
+
let stopped = false;
|
|
126
|
+
const tick = async () => {
|
|
127
|
+
if (stopped || request.signal.aborted || submitting) return;
|
|
128
|
+
submitting = true;
|
|
129
|
+
try {
|
|
130
|
+
const activity = await execution.session.activity();
|
|
131
|
+
if (stopped || request.signal.aborted || !activity.isIdle || activity.hasPendingMessages) return;
|
|
132
|
+
await execution.session.prompt(prepared.prompt);
|
|
133
|
+
} catch (error) {
|
|
134
|
+
await execution.client.notify({
|
|
135
|
+
body: `Loop pass failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
136
|
+
level: "warning"
|
|
137
|
+
});
|
|
138
|
+
} finally {
|
|
139
|
+
submitting = false;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
let stopTimer;
|
|
143
|
+
let detail;
|
|
144
|
+
if ("cron" in prepared) {
|
|
145
|
+
const job = new Cron(prepared.cron, {
|
|
146
|
+
timezone: prepared.timezone,
|
|
147
|
+
unref: true
|
|
148
|
+
}, tick);
|
|
149
|
+
if (job.nextRun() === null) {
|
|
150
|
+
job.stop();
|
|
151
|
+
throw new Error("Cron expression has no future run.");
|
|
152
|
+
}
|
|
153
|
+
stopTimer = () => {
|
|
154
|
+
job.stop();
|
|
155
|
+
};
|
|
156
|
+
detail = `${prepared.cron} (${prepared.timezone})`;
|
|
157
|
+
} else {
|
|
158
|
+
const timer = setInterval(() => {
|
|
159
|
+
tick();
|
|
160
|
+
}, prepared.intervalSeconds * 1e3);
|
|
161
|
+
timer.unref?.();
|
|
162
|
+
stopTimer = () => clearInterval(timer);
|
|
163
|
+
detail = `every ${prepared.intervalSeconds}s`;
|
|
164
|
+
tick();
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
instanceId: request.instanceId,
|
|
168
|
+
label: cron ? "Cron loop" : "Default loop",
|
|
169
|
+
detail,
|
|
170
|
+
stop() {
|
|
171
|
+
stopped = true;
|
|
172
|
+
stopTimer();
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
return {
|
|
178
|
+
loopTools: createLoopTools(() => launchers, () => {
|
|
179
|
+
if (!modeSelected()) throw new Error("Enable Loop minor mode before using agent loop tools.");
|
|
180
|
+
}).map((tool) => ({
|
|
181
|
+
...tool,
|
|
182
|
+
when: {
|
|
183
|
+
state: { "minor-mode": MODE_STATUS_ID },
|
|
184
|
+
attribution: {
|
|
185
|
+
kind: "minor",
|
|
186
|
+
mode: MODE_STATUS_ID
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
})),
|
|
190
|
+
services: [(context) => {
|
|
191
|
+
context.plugin((provider) => {
|
|
192
|
+
provider.provide(DOOM_LOOP_LAUNCHERS_SERVICE, launchers);
|
|
193
|
+
});
|
|
194
|
+
context.effect(() => host.subscribeSelection(publish));
|
|
195
|
+
}, serverMinorModes([modeOwner])],
|
|
196
|
+
resources: [{
|
|
197
|
+
when: {
|
|
198
|
+
state: { "minor-mode": MODE_STATUS_ID },
|
|
199
|
+
attribution: {
|
|
200
|
+
kind: "minor",
|
|
201
|
+
mode: MODE_STATUS_ID
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
name: "doompi-use-loop",
|
|
205
|
+
kind: "skill",
|
|
206
|
+
read: () => readPackageResource(import.meta.url, "src/prompts/doompi-use-loop/SKILL.md")
|
|
207
|
+
}],
|
|
208
|
+
activities: [{
|
|
209
|
+
name: "doompi-loop",
|
|
210
|
+
async start() {
|
|
211
|
+
publish();
|
|
212
|
+
return async () => {
|
|
213
|
+
await launchers.stopAll("Session loop activity stopped.");
|
|
214
|
+
publish();
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
}],
|
|
218
|
+
commands: [{
|
|
219
|
+
name: START_COMMAND_NAME,
|
|
220
|
+
description: "Start a registered loop manually.",
|
|
221
|
+
async execute(args, execution) {
|
|
222
|
+
const available = launchers.listLaunchers();
|
|
223
|
+
const selected = args.trim() || await execution.client.request({
|
|
224
|
+
kind: "select",
|
|
225
|
+
title: "Choose a loop launcher",
|
|
226
|
+
options: available.map((entry) => ({
|
|
227
|
+
label: entry.label,
|
|
228
|
+
value: entry.id
|
|
229
|
+
}))
|
|
230
|
+
});
|
|
231
|
+
if (typeof selected !== "string" || !selected) return;
|
|
232
|
+
const instance = await launchers.launch(selected);
|
|
233
|
+
await execution.client.notify({
|
|
234
|
+
body: instance ? `Loop '${instance.instanceId}' started.` : "Loop launch was cancelled.",
|
|
235
|
+
level: "info"
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}, {
|
|
239
|
+
name: LIST_COMMAND_NAME,
|
|
240
|
+
description: "List or stop session loops. Usage: /loops [stop instanceId].",
|
|
241
|
+
async execute(args, execution) {
|
|
242
|
+
const parts = args.trim().split(/\s+/u);
|
|
243
|
+
if (parts[0] === "stop" && parts.length === 2) {
|
|
244
|
+
const stopped = await launchers.stop(parts[1], "Stopped manually.");
|
|
245
|
+
await execution.client.notify({
|
|
246
|
+
body: stopped ? "Loop stopped." : "Loop instance was not active.",
|
|
247
|
+
level: "info"
|
|
248
|
+
});
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (args.trim()) throw new Error("Usage: /loops [stop instanceId]");
|
|
252
|
+
const instances = launchers.listInstances();
|
|
253
|
+
await execution.client.notify({
|
|
254
|
+
body: instances.length === 0 ? "No loops are active." : JSON.stringify(instances, null, 2),
|
|
255
|
+
level: "info"
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}],
|
|
259
|
+
hooks: [{
|
|
260
|
+
event: "session_start",
|
|
261
|
+
async handle() {
|
|
262
|
+
publish();
|
|
263
|
+
}
|
|
264
|
+
}, {
|
|
265
|
+
event: "session_shutdown",
|
|
266
|
+
async handle() {
|
|
267
|
+
await launchers.stopAll("Headless session shutdown.");
|
|
268
|
+
}
|
|
269
|
+
}],
|
|
270
|
+
onStart: publish,
|
|
271
|
+
async onDispose() {
|
|
272
|
+
if (disposed) return;
|
|
273
|
+
disposed = true;
|
|
274
|
+
unsubscribe();
|
|
275
|
+
await launchers.dispose("Headless loop facet disposed.");
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
//#endregion
|
|
280
|
+
//#region src/extensions/workspaces/sessions/(backend)/_lib/runtime.server.ts
|
|
281
|
+
var runtime_server_default = (({ agent }) => agent ? createSessionState(agent) : { loopTools: [] });
|
|
282
|
+
//#endregion
|
|
283
|
+
//#region src/extensions/workspaces/sessions/(backend)/root.server.ts
|
|
284
|
+
var root_server_default = defineRoot((context) => {
|
|
285
|
+
const value = runtime_server_default(context);
|
|
286
|
+
return {
|
|
287
|
+
value,
|
|
288
|
+
services: value.services,
|
|
289
|
+
activities: value.activities,
|
|
290
|
+
onStart: value.onStart,
|
|
291
|
+
onStop: value.onStop,
|
|
292
|
+
onDispose: value.onDispose
|
|
293
|
+
};
|
|
294
|
+
});
|
|
295
|
+
//#endregion
|
|
296
|
+
//#region src/extensions/workspaces/sessions/(backend)/command/loop.server.ts
|
|
297
|
+
var loop_server_default = defineRoutedContribution((context) => context.root.commands?.[0], { cardinality: "optional" });
|
|
298
|
+
//#endregion
|
|
299
|
+
//#region src/extensions/workspaces/sessions/(backend)/command/loops.server.ts
|
|
300
|
+
var loops_server_default = defineRoutedContribution((context) => context.root.commands?.[1], { cardinality: "optional" });
|
|
301
|
+
//#endregion
|
|
302
|
+
//#region src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.ts
|
|
303
|
+
var session_shutdown_server_default = defineRoutedContribution((context) => context.root.hooks?.find((hook) => hook.event === "session_shutdown"), { cardinality: "optional" });
|
|
304
|
+
//#endregion
|
|
305
|
+
//#region src/extensions/workspaces/sessions/(backend)/hook/session-start.server.ts
|
|
306
|
+
var session_start_server_default = defineRoutedContribution((context) => context.root.hooks?.find((hook) => hook.event === "session_start"), { cardinality: "optional" });
|
|
307
|
+
//#endregion
|
|
308
|
+
//#region src/extensions/workspaces/sessions/(backend)/resource/doompi-use-loop.server.ts
|
|
309
|
+
var doompi_use_loop_server_default = defineRoutedContribution((context) => context.root.resources?.[0], { cardinality: "optional" });
|
|
310
|
+
//#endregion
|
|
311
|
+
//#region src/extensions/workspaces/sessions/(backend)/tool/loop-list.server.ts
|
|
312
|
+
var loop_list_server_default = defineTool((context) => context.root.loopTools[0]);
|
|
313
|
+
//#endregion
|
|
314
|
+
//#region src/extensions/workspaces/sessions/(backend)/tool/loop-start.server.ts
|
|
315
|
+
var loop_start_server_default = defineTool((context) => context.root.loopTools[1]);
|
|
316
|
+
//#endregion
|
|
317
|
+
//#region src/extensions/workspaces/sessions/(backend)/tool/loop-stop.server.ts
|
|
318
|
+
var loop_stop_server_default = defineTool((context) => context.root.loopTools[2]);
|
|
319
|
+
//#endregion
|
|
320
|
+
//#region generated/server.ts
|
|
321
|
+
const at = (value, context) => typeof value === "function" ? value(context) : value;
|
|
322
|
+
/* v8 ignore next -- generated normalization branch */
|
|
323
|
+
const defined = (values) => values.filter((value) => value !== void 0);
|
|
324
|
+
const via = (identity, value) => value === void 0 ? void 0 : {
|
|
325
|
+
...identity,
|
|
326
|
+
...value
|
|
327
|
+
};
|
|
328
|
+
const facet = defineServerPlugin({
|
|
329
|
+
name: "@agimon-ai/doompi-loop",
|
|
330
|
+
session: async (context) => {
|
|
331
|
+
const scopeSession = await root_server_default(context);
|
|
332
|
+
const contextSession = {
|
|
333
|
+
...context,
|
|
334
|
+
root: scopeSession.value
|
|
335
|
+
};
|
|
336
|
+
return {
|
|
337
|
+
...composeRootHooks(scopeSession),
|
|
338
|
+
get commands() {
|
|
339
|
+
return defined([via({ name: "loop" }, at(loop_server_default, contextSession)), via({ name: "loops" }, at(loops_server_default, contextSession))]);
|
|
340
|
+
},
|
|
341
|
+
get hooks() {
|
|
342
|
+
return defined([via({ event: "session_shutdown" }, at(session_shutdown_server_default, contextSession)), via({ event: "session_start" }, at(session_start_server_default, contextSession))]);
|
|
343
|
+
},
|
|
344
|
+
get resources() {
|
|
345
|
+
return defined([at(doompi_use_loop_server_default, contextSession)]);
|
|
346
|
+
},
|
|
347
|
+
get tools() {
|
|
348
|
+
return [
|
|
349
|
+
via({ name: "loop_list" }, at(loop_list_server_default, contextSession)),
|
|
350
|
+
via({ name: "loop_start" }, at(loop_start_server_default, contextSession)),
|
|
351
|
+
via({ name: "loop_stop" }, at(loop_stop_server_default, contextSession))
|
|
352
|
+
];
|
|
353
|
+
},
|
|
354
|
+
services: [...scopeSession.services ?? []],
|
|
355
|
+
get activities() {
|
|
356
|
+
return [...scopeSession.activities ?? []];
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
//#endregion
|
|
362
|
+
export { facet as default, facet };
|
|
363
|
+
|
|
364
|
+
//# sourceMappingURL=server.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.mjs","names":["runtime","rootSession","commandLoop","commandLoops","hookSessionShutdown","hookSessionStart","resourceDoompiUseLoop","toolLoopList","toolLoopStart","toolLoopStop"],"sources":["../../src/services/serverRuntime/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/runtime.server.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/loop.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/loops.server.ts","../../src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.ts","../../src/extensions/workspaces/sessions/(backend)/hook/session-start.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/doompi-use-loop.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/loop-list.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/loop-start.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/loop-stop.server.ts","../../generated/server.ts"],"sourcesContent":["import type { DoomHeadlessExecutionContext, DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport { readPackageResource, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\nimport { defineMinorMode, serverMinorModes } from '@agimon-ai/doompi-minor-mode';\nimport { Cron } from 'croner';\n\nimport { LIST_COMMAND_NAME, START_COMMAND_NAME } from '../../constants/loop';\nimport { MODE_STATUS_ID, PACKAGE_SOURCE } from '../../constants/piLoop';\nimport { DOOM_LOOP_LAUNCHERS_SERVICE, type LoopLaunchRequest } from '../../schemas/loopLaunchers';\nimport { CronLoopSchema, IntervalLoopSchema, parseCronLoop, parseIntervalLoop } from '../../schemas/loopTools';\nimport { formatLoopStatusView, LOOP_VIEW_STATUS_KEY } from '../../types/loopView';\nimport { createDoomLoopLaunchersService } from '../loopLaunchers';\nimport { createLoopTools } from '../loopTools';\nimport type { LoopToolsRoot } from '../loopTools/type';\n\nexport type LoopServerState = DoomServerSessionPlugin & LoopToolsRoot;\n\nasync function prepareLoop(execution: DoomHeadlessExecutionContext, request: LoopLaunchRequest, cron: boolean) {\n if (request.input !== undefined) return cron ? parseCronLoop(request.input) : parseIntervalLoop(request.input);\n if (request.interactive === false) throw new Error('Loop configuration is required for agent launches.');\n const input = await execution.client.request(\n { kind: 'input', title: 'Loop prompt', multiline: true },\n request.signal,\n );\n const prompt = typeof input === 'string' ? input.trim() : '';\n if (!prompt || request.signal.aborted) return undefined;\n if (cron) {\n const expression = await execution.client.request(\n { kind: 'input', title: 'Cron expression (five fields)', initialValue: '0 * * * *' },\n request.signal,\n );\n if (typeof expression !== 'string' || request.signal.aborted) return undefined;\n const timezone = await execution.client.request(\n { kind: 'input', title: 'Loop timezone', initialValue: 'UTC' },\n request.signal,\n );\n if (typeof timezone !== 'string' || request.signal.aborted) return undefined;\n return parseCronLoop({ prompt, cron: expression, timezone: timezone.trim() || 'UTC' });\n }\n const interval = await execution.client.request(\n { kind: 'input', title: 'Loop interval in seconds', initialValue: '300' },\n request.signal,\n );\n if (typeof interval !== 'string' || request.signal.aborted) return undefined;\n return parseIntervalLoop({ prompt, intervalSeconds: Number(interval.trim() || '300') });\n}\n\nexport function createSessionState(host: DoomHeadlessHostService): LoopServerState {\n const launchers = createDoomLoopLaunchersService({\n generation: `${host.context.sessionId}:loop-launchers`,\n createInstanceId: () => crypto.randomUUID(),\n timestamp: () => new Date().toISOString(),\n });\n let disposed = false;\n const modeSelected = (): boolean =>\n !disposed && (host.context.selection.state?.['minor-mode'] ?? []).includes(MODE_STATUS_ID);\n const publishView = (): void =>\n host.context.client.setStatus(LOOP_VIEW_STATUS_KEY, formatLoopStatusView(launchers.listInstances()));\n const modeOwner = defineMinorMode({\n descriptor: {\n source: PACKAGE_SOURCE,\n id: MODE_STATUS_ID,\n label: 'Loop',\n description: 'Give the agent tools to create, inspect, and stop session loops.',\n order: 60,\n actions: [\n {\n id: 'activate',\n label: 'Activate',\n description: 'Expose loop tools to the agent.',\n contexts: ['headless'],\n parameters: [],\n },\n {\n id: 'deactivate',\n label: 'Deactivate',\n description: 'Hide agent loop tools. Existing loops and manual controls remain available.',\n contexts: ['headless'],\n parameters: [],\n },\n ],\n },\n state: () => ({\n activation: modeSelected() ? 'active' : 'inactive',\n condition: 'ready',\n ...(modeSelected() ? { detail: `${launchers.listInstances().length} loops`, color: 'accent' } : {}),\n actions: [\n {\n id: 'activate',\n enabled: !modeSelected(),\n ...(modeSelected() ? { disabledReason: 'Loop mode is already active.' } : {}),\n },\n {\n id: 'deactivate',\n enabled: modeSelected(),\n ...(modeSelected() ? {} : { disabledReason: 'Loop mode is not active.' }),\n },\n ],\n }),\n async handleAction(_runtime, actionId, _arguments, { signal }) {\n signal.throwIfAborted();\n if (actionId !== 'activate' && actionId !== 'deactivate')\n throw new Error(`Unknown loop mode action: ${actionId}`);\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== MODE_STATUS_ID);\n await host.changeSelection({\n axis: 'state',\n key: 'minor-mode',\n values: actionId === 'activate' ? [...modes, MODE_STATUS_ID] : modes,\n });\n modeOwner.publish();\n return {\n message:\n actionId === 'activate' ? 'Loop tools activated.' : 'Loop tools deactivated. Existing loops are unchanged.',\n };\n },\n }).createOwner(undefined);\n const publish = (): void => {\n if (disposed) return;\n modeOwner.publish();\n publishView();\n };\n const unsubscribe = launchers.subscribe(publish);\n let submitting = false;\n for (const cron of [false, true]) {\n launchers.register({\n id: cron ? 'doompi.cron' : 'doompi.default',\n source: PACKAGE_SOURCE,\n label: cron ? 'Cron loop' : 'Default loop',\n description: cron\n ? 'Run a prompt on a five-field cron schedule.'\n : 'Run a prompt in this session on an interval.',\n inputSchema: { ...(cron ? CronLoopSchema : IntervalLoopSchema) },\n async launch(request) {\n const execution = host.context;\n const prepared = await prepareLoop(execution, request, cron);\n if (!prepared || request.signal.aborted) return undefined;\n let stopped = false;\n const tick = async (): Promise<void> => {\n if (stopped || request.signal.aborted || submitting) return;\n submitting = true;\n try {\n const activity = await execution.session.activity();\n if (stopped || request.signal.aborted || !activity.isIdle || activity.hasPendingMessages) return;\n await execution.session.prompt(prepared.prompt);\n } catch (error) {\n await execution.client.notify({\n body: `Loop pass failed: ${error instanceof Error ? error.message : String(error)}`,\n level: 'warning',\n });\n } finally {\n submitting = false;\n }\n };\n let stopTimer: () => void;\n let detail: string;\n if ('cron' in prepared) {\n const job = new Cron(prepared.cron, { timezone: prepared.timezone, unref: true }, tick);\n if (job.nextRun() === null) {\n job.stop();\n throw new Error('Cron expression has no future run.');\n }\n stopTimer = () => {\n job.stop();\n };\n detail = `${prepared.cron} (${prepared.timezone})`;\n } else {\n const timer = setInterval(() => {\n void tick();\n }, prepared.intervalSeconds * 1000);\n timer.unref?.();\n stopTimer = () => clearInterval(timer);\n detail = `every ${prepared.intervalSeconds}s`;\n void tick();\n }\n return {\n instanceId: request.instanceId,\n label: cron ? 'Cron loop' : 'Default loop',\n detail,\n stop() {\n stopped = true;\n stopTimer();\n },\n };\n },\n });\n }\n const loopTools = createLoopTools(\n () => launchers,\n () => {\n if (!modeSelected()) throw new Error('Enable Loop minor mode before using agent loop tools.');\n },\n ).map((tool) => ({\n ...tool,\n when: { state: { 'minor-mode': MODE_STATUS_ID }, attribution: { kind: 'minor' as const, mode: MODE_STATUS_ID } },\n }));\n return {\n loopTools,\n services: [\n (context) => {\n context.plugin((provider) => {\n provider.provide(DOOM_LOOP_LAUNCHERS_SERVICE, launchers);\n });\n context.effect(() => host.subscribeSelection(publish));\n },\n serverMinorModes([modeOwner]),\n ],\n resources: [\n {\n when: { state: { 'minor-mode': MODE_STATUS_ID }, attribution: { kind: 'minor', mode: MODE_STATUS_ID } },\n name: 'doompi-use-loop',\n kind: 'skill',\n read: () => readPackageResource(import.meta.url, 'src/prompts/doompi-use-loop/SKILL.md'),\n },\n ],\n activities: [\n {\n name: 'doompi-loop',\n async start() {\n publish();\n return async () => {\n await launchers.stopAll('Session loop activity stopped.');\n publish();\n };\n },\n },\n ],\n commands: [\n {\n name: START_COMMAND_NAME,\n description: 'Start a registered loop manually.',\n async execute(args: string, execution: DoomHeadlessExecutionContext) {\n const available = launchers.listLaunchers();\n const selected =\n args.trim() ||\n (await execution.client.request({\n kind: 'select',\n title: 'Choose a loop launcher',\n options: available.map((entry) => ({ label: entry.label, value: entry.id })),\n }));\n if (typeof selected !== 'string' || !selected) return;\n const instance = await launchers.launch(selected);\n await execution.client.notify({\n body: instance ? `Loop '${instance.instanceId}' started.` : 'Loop launch was cancelled.',\n level: 'info',\n });\n },\n },\n {\n name: LIST_COMMAND_NAME,\n description: 'List or stop session loops. Usage: /loops [stop instanceId].',\n async execute(args: string, execution: DoomHeadlessExecutionContext) {\n const parts = args.trim().split(/\\s+/u);\n if (parts[0] === 'stop' && parts.length === 2) {\n const stopped = await launchers.stop(parts[1]!, 'Stopped manually.');\n await execution.client.notify({\n body: stopped ? 'Loop stopped.' : 'Loop instance was not active.',\n level: 'info',\n });\n return;\n }\n if (args.trim()) throw new Error('Usage: /loops [stop instanceId]');\n const instances = launchers.listInstances();\n await execution.client.notify({\n body: instances.length === 0 ? 'No loops are active.' : JSON.stringify(instances, null, 2),\n level: 'info',\n });\n },\n },\n ],\n hooks: [\n {\n event: 'session_start',\n async handle() {\n publish();\n },\n },\n {\n event: 'session_shutdown',\n async handle() {\n await launchers.stopAll('Headless session shutdown.');\n },\n },\n ],\n onStart: publish,\n async onDispose() {\n if (disposed) return;\n disposed = true;\n unsubscribe();\n await launchers.dispose('Headless loop facet disposed.');\n },\n };\n}\n","import type { DoomServerPluginDefinition } from '@agimon-ai/doompi-core/serverFacet';\n\nimport { createSessionState, type LoopServerState } from '../../../../../services/serverRuntime';\n\nexport default (({ agent }): LoopServerState =>\n agent ? createSessionState(agent) : { loopTools: [] }) satisfies NonNullable<DoomServerPluginDefinition['session']>;\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport runtime from './_lib/runtime.server';\n\nexport default defineRoot((context: DoomServerPluginContext) => {\n const value = runtime(context);\n return {\n value,\n services: value.services,\n activities: value.activities,\n onStart: value.onStart,\n onStop: value.onStop,\n onDispose: value.onDispose,\n };\n});\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext, DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\n\nexport default defineRoutedContribution(\n (context: WithRoot<DoomServerPluginContext, Partial<DoomServerSessionPlugin>>) => context.root.commands?.[0],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext, DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\n\nexport default defineRoutedContribution(\n (context: WithRoot<DoomServerPluginContext, Partial<DoomServerSessionPlugin>>) => context.root.commands?.[1],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext, DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\n\nexport default defineRoutedContribution(\n (context: WithRoot<DoomServerPluginContext, Partial<DoomServerSessionPlugin>>) =>\n context.root.hooks?.find((hook) => hook.event === 'session_shutdown'),\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext, DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\n\nexport default defineRoutedContribution(\n (context: WithRoot<DoomServerPluginContext, Partial<DoomServerSessionPlugin>>) =>\n context.root.hooks?.find((hook) => hook.event === 'session_start'),\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext, DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\n\nexport default defineRoutedContribution(\n (context: WithRoot<DoomServerPluginContext, Partial<DoomServerSessionPlugin>>) => context.root.resources?.[0],\n { cardinality: 'optional' },\n);\n","import { defineTool, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport type { LoopToolsRoot } from '../../../../../services/loopTools/type';\n\nexport default defineTool((context: WithRoot<unknown, LoopToolsRoot>) => context.root.loopTools[0]!);\n","import { defineTool, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport type { LoopToolsRoot } from '../../../../../services/loopTools/type';\n\nexport default defineTool((context: WithRoot<unknown, LoopToolsRoot>) => context.root.loopTools[1]!);\n","import { defineTool, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport type { LoopToolsRoot } from '../../../../../services/loopTools/type';\n\nexport default defineTool((context: WithRoot<unknown, LoopToolsRoot>) => context.root.loopTools[2]!);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport commandLoop from '../src/extensions/workspaces/sessions/(backend)/command/loop.server';\nimport commandLoops from '../src/extensions/workspaces/sessions/(backend)/command/loops.server';\nimport hookSessionShutdown from '../src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server';\nimport hookSessionStart from '../src/extensions/workspaces/sessions/(backend)/hook/session-start.server';\nimport resourceDoompiUseLoop from '../src/extensions/workspaces/sessions/(backend)/resource/doompi-use-loop.server';\nimport toolLoopList from '../src/extensions/workspaces/sessions/(backend)/tool/loop-list.server';\nimport toolLoopStart from '../src/extensions/workspaces/sessions/(backend)/tool/loop-start.server';\nimport toolLoopStop from '../src/extensions/workspaces/sessions/(backend)/tool/loop-stop.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\n/* v8 ignore next -- generated normalization branch */\nconst defined = <T>(values: readonly (T | undefined)[]): T[] =>\n values.filter((value): value is T => value !== undefined);\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-loop',\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get commands(): DoomServerSessionPlugin['commands'] { return defined([via({ name: 'loop' }, at(commandLoop, contextSession)), via({ name: 'loops' }, at(commandLoops, contextSession))]); },\n get hooks(): DoomServerSessionPlugin['hooks'] { return defined([via({ event: 'session_shutdown' }, at(hookSessionShutdown, contextSession)), via({ event: 'session_start' }, at(hookSessionStart, contextSession))]); },\n get resources(): DoomServerSessionPlugin['resources'] { return defined([at(resourceDoompiUseLoop, contextSession)]); },\n get tools(): DoomServerSessionPlugin['tools'] { return [via({ name: 'loop_list' }, at(toolLoopList, contextSession)), via({ name: 'loop_start' }, at(toolLoopStart, contextSession)), via({ name: 'loop_stop' }, at(toolLoopStop, contextSession))]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}
|