@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.
Files changed (87) hide show
  1. package/README.md +83 -21
  2. package/dist/apiContracts.cjs +17 -0
  3. package/dist/apiContracts.cjs.map +1 -0
  4. package/dist/apiContracts.d.mts +53 -0
  5. package/dist/apiContracts.d.mts.map +1 -0
  6. package/dist/apiContracts.mjs +13 -0
  7. package/dist/apiContracts.mjs.map +1 -0
  8. package/dist/extensions/pi.cjs +659 -1
  9. package/dist/extensions/pi.cjs.map +1 -1
  10. package/dist/extensions/pi.d.mts +5 -2
  11. package/dist/extensions/pi.d.mts.map +1 -0
  12. package/dist/extensions/pi.mjs +654 -1
  13. package/dist/extensions/pi.mjs.map +1 -1
  14. package/dist/extensions/server.cjs +369 -0
  15. package/dist/extensions/server.cjs.map +1 -0
  16. package/dist/extensions/server.d.mts +5 -0
  17. package/dist/extensions/server.d.mts.map +1 -0
  18. package/dist/extensions/server.mjs +364 -0
  19. package/dist/extensions/server.mjs.map +1 -0
  20. package/dist/extensions/web.mjs +331 -0
  21. package/dist/extensions/web.mjs.map +1 -0
  22. package/dist/index.cjs +0 -1
  23. package/dist/index.d.mts +2 -4
  24. package/dist/index.mjs +1 -1
  25. package/dist/loopLaunchers-Bciapxt0.d.mts +69 -0
  26. package/dist/loopLaunchers-Bciapxt0.d.mts.map +1 -0
  27. package/dist/loopLaunchers-BtcLH_xN.cjs +32 -0
  28. package/dist/loopLaunchers-BtcLH_xN.cjs.map +1 -0
  29. package/dist/loopLaunchers-cCniFbVA.mjs +15 -0
  30. package/dist/loopLaunchers-cCniFbVA.mjs.map +1 -0
  31. package/dist/loopLaunchers.cjs +5 -0
  32. package/dist/loopLaunchers.d.mts +2 -0
  33. package/dist/loopLaunchers.mjs +2 -0
  34. package/dist/loopView-BK4X_1UI.mjs +349 -0
  35. package/dist/loopView-BK4X_1UI.mjs.map +1 -0
  36. package/dist/loopView-C_OPuy8L.cjs +456 -0
  37. package/dist/loopView-C_OPuy8L.cjs.map +1 -0
  38. package/llms.txt +9 -0
  39. package/package.json +82 -14
  40. package/src/prompts/doompi-use-loop/SKILL.md +44 -0
  41. package/src/types/loopView.ts +73 -0
  42. package/dist/commands/loopCommand.cjs +0 -2
  43. package/dist/commands/loopCommand.cjs.map +0 -1
  44. package/dist/commands/loopCommand.mjs +0 -2
  45. package/dist/commands/loopCommand.mjs.map +0 -1
  46. package/dist/constants.cjs +0 -2
  47. package/dist/constants.cjs.map +0 -1
  48. package/dist/constants.mjs +0 -2
  49. package/dist/constants.mjs.map +0 -1
  50. package/dist/defaultLauncher.cjs +0 -2
  51. package/dist/defaultLauncher.cjs.map +0 -1
  52. package/dist/defaultLauncher.d.cts +0 -10
  53. package/dist/defaultLauncher.d.cts.map +0 -1
  54. package/dist/defaultLauncher.d.mts +0 -10
  55. package/dist/defaultLauncher.d.mts.map +0 -1
  56. package/dist/defaultLauncher.mjs +0 -2
  57. package/dist/defaultLauncher.mjs.map +0 -1
  58. package/dist/extension.cjs +0 -2
  59. package/dist/extension.cjs.map +0 -1
  60. package/dist/extension.d.cts +0 -6
  61. package/dist/extension.d.cts.map +0 -1
  62. package/dist/extension.d.mts +0 -6
  63. package/dist/extension.d.mts.map +0 -1
  64. package/dist/extension.mjs +0 -2
  65. package/dist/extension.mjs.map +0 -1
  66. package/dist/extensions/pi.d.cts +0 -2
  67. package/dist/index.d.cts +0 -4
  68. package/dist/launcher.cjs +0 -2
  69. package/dist/launcher.cjs.map +0 -1
  70. package/dist/launcher.d.cts +0 -47
  71. package/dist/launcher.d.cts.map +0 -1
  72. package/dist/launcher.d.mts +0 -47
  73. package/dist/launcher.d.mts.map +0 -1
  74. package/dist/launcher.mjs +0 -2
  75. package/dist/launcher.mjs.map +0 -1
  76. package/dist/leader.cjs +0 -2
  77. package/dist/leader.cjs.map +0 -1
  78. package/dist/leader.mjs +0 -2
  79. package/dist/leader.mjs.map +0 -1
  80. package/dist/tui/loopListOverlay.cjs +0 -2
  81. package/dist/tui/loopListOverlay.cjs.map +0 -1
  82. package/dist/tui/loopListOverlay.mjs +0 -2
  83. package/dist/tui/loopListOverlay.mjs.map +0 -1
  84. package/dist/tui/startLoopOverlay.cjs +0 -2
  85. package/dist/tui/startLoopOverlay.cjs.map +0 -1
  86. package/dist/tui/startLoopOverlay.mjs +0 -2
  87. 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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"}