@agimon-ai/doompi-loop 0.0.1-alpha.7 → 0.0.1-alpha.71

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 (145) hide show
  1. package/README.md +83 -21
  2. package/dist/_virtual/_rolldown/runtime.cjs +1 -0
  3. package/dist/api-contracts.cjs +1 -0
  4. package/dist/api-contracts.d.cts +2 -0
  5. package/dist/api-contracts.d.mts +2 -0
  6. package/dist/api-contracts.mjs +1 -0
  7. package/dist/extensions/pi.cjs +1 -1
  8. package/dist/extensions/pi.cjs.map +1 -1
  9. package/dist/extensions/pi.d.cts +5 -2
  10. package/dist/extensions/pi.d.cts.map +1 -0
  11. package/dist/extensions/pi.d.mts +5 -2
  12. package/dist/extensions/pi.d.mts.map +1 -0
  13. package/dist/extensions/pi.mjs +1 -1
  14. package/dist/extensions/pi.mjs.map +1 -1
  15. package/dist/extensions/server.cjs +2 -0
  16. package/dist/extensions/server.cjs.map +1 -0
  17. package/dist/extensions/server.d.cts +5 -0
  18. package/dist/extensions/server.d.cts.map +1 -0
  19. package/dist/extensions/server.d.mts +5 -0
  20. package/dist/extensions/server.d.mts.map +1 -0
  21. package/dist/extensions/server.mjs +2 -0
  22. package/dist/extensions/server.mjs.map +1 -0
  23. package/dist/index.cjs +0 -1
  24. package/dist/index.d.cts +2 -4
  25. package/dist/index.d.mts +2 -4
  26. package/dist/index.mjs +1 -1
  27. package/dist/loopLaunchers.cjs +1 -0
  28. package/dist/loopLaunchers.d.cts +2 -0
  29. package/dist/loopLaunchers.d.mts +2 -0
  30. package/dist/loopLaunchers.mjs +1 -0
  31. package/dist/src/constants/loop.cjs +2 -0
  32. package/dist/src/constants/loop.cjs.map +1 -0
  33. package/dist/src/constants/loop.mjs +2 -0
  34. package/dist/src/constants/loop.mjs.map +1 -0
  35. package/dist/src/constants/piLoop.cjs +2 -0
  36. package/dist/src/constants/piLoop.cjs.map +1 -0
  37. package/dist/src/constants/piLoop.mjs +2 -0
  38. package/dist/src/constants/piLoop.mjs.map +1 -0
  39. package/dist/src/controllers/loopCommand.cjs +2 -0
  40. package/dist/src/controllers/loopCommand.cjs.map +1 -0
  41. package/dist/src/controllers/loopCommand.mjs +2 -0
  42. package/dist/src/controllers/loopCommand.mjs.map +1 -0
  43. package/dist/src/controllers/serverRuntime.cjs +2 -0
  44. package/dist/src/controllers/serverRuntime.cjs.map +1 -0
  45. package/dist/src/controllers/serverRuntime.mjs +2 -0
  46. package/dist/src/controllers/serverRuntime.mjs.map +1 -0
  47. package/dist/src/schemas/apiContracts.cjs +2 -0
  48. package/dist/src/schemas/apiContracts.cjs.map +1 -0
  49. package/dist/src/schemas/apiContracts.d.cts +53 -0
  50. package/dist/src/schemas/apiContracts.d.cts.map +1 -0
  51. package/dist/src/schemas/apiContracts.d.mts +53 -0
  52. package/dist/src/schemas/apiContracts.d.mts.map +1 -0
  53. package/dist/src/schemas/apiContracts.mjs +2 -0
  54. package/dist/src/schemas/apiContracts.mjs.map +1 -0
  55. package/dist/src/schemas/loopLaunchers.cjs +2 -0
  56. package/dist/src/schemas/loopLaunchers.cjs.map +1 -0
  57. package/dist/src/schemas/loopLaunchers.d.cts +60 -0
  58. package/dist/src/schemas/loopLaunchers.d.cts.map +1 -0
  59. package/dist/src/schemas/loopLaunchers.d.mts +60 -0
  60. package/dist/src/schemas/loopLaunchers.d.mts.map +1 -0
  61. package/dist/src/schemas/loopLaunchers.mjs +2 -0
  62. package/dist/src/schemas/loopLaunchers.mjs.map +1 -0
  63. package/dist/src/services/defaultLoopLauncher/index.cjs +2 -0
  64. package/dist/src/services/defaultLoopLauncher/index.cjs.map +1 -0
  65. package/dist/src/services/defaultLoopLauncher/index.mjs +2 -0
  66. package/dist/src/services/defaultLoopLauncher/index.mjs.map +1 -0
  67. package/dist/src/services/loopLaunchers/index.cjs +2 -0
  68. package/dist/src/services/loopLaunchers/index.cjs.map +1 -0
  69. package/dist/src/services/loopLaunchers/index.mjs +2 -0
  70. package/dist/src/services/loopLaunchers/index.mjs.map +1 -0
  71. package/dist/src/services/loopResource/index.cjs +2 -0
  72. package/dist/src/services/loopResource/index.cjs.map +1 -0
  73. package/dist/src/services/loopResource/index.mjs +2 -0
  74. package/dist/src/services/loopResource/index.mjs.map +1 -0
  75. package/dist/src/tui/leader.cjs +2 -0
  76. package/dist/src/tui/leader.cjs.map +1 -0
  77. package/dist/src/tui/leader.mjs +2 -0
  78. package/dist/src/tui/leader.mjs.map +1 -0
  79. package/dist/src/tui/loopListOverlay.cjs +2 -0
  80. package/dist/src/tui/loopListOverlay.cjs.map +1 -0
  81. package/dist/src/tui/loopListOverlay.mjs +2 -0
  82. package/dist/src/tui/loopListOverlay.mjs.map +1 -0
  83. package/dist/src/tui/loopRuntime.cjs +2 -0
  84. package/dist/src/tui/loopRuntime.cjs.map +1 -0
  85. package/dist/src/tui/loopRuntime.mjs +2 -0
  86. package/dist/src/tui/loopRuntime.mjs.map +1 -0
  87. package/dist/src/tui/startLoopOverlay.cjs +2 -0
  88. package/dist/src/tui/startLoopOverlay.cjs.map +1 -0
  89. package/dist/src/tui/startLoopOverlay.mjs +2 -0
  90. package/dist/src/tui/startLoopOverlay.mjs.map +1 -0
  91. package/dist/src/types/loopView.cjs +2 -0
  92. package/dist/src/types/loopView.cjs.map +1 -0
  93. package/dist/src/types/loopView.mjs +2 -0
  94. package/dist/src/types/loopView.mjs.map +1 -0
  95. package/llms.txt +9 -0
  96. package/package.json +80 -16
  97. package/src/extensions/web.ts +41 -0
  98. package/src/prompts/doompi-use-loop/SKILL.md +24 -0
  99. package/src/types/loopView.ts +73 -0
  100. package/src/web/components/LoopsActivitySection.tsx +94 -0
  101. package/src/web/tsconfig.json +23 -0
  102. package/dist/commands/loopCommand.cjs +0 -2
  103. package/dist/commands/loopCommand.cjs.map +0 -1
  104. package/dist/commands/loopCommand.mjs +0 -2
  105. package/dist/commands/loopCommand.mjs.map +0 -1
  106. package/dist/constants.cjs +0 -2
  107. package/dist/constants.cjs.map +0 -1
  108. package/dist/constants.mjs +0 -2
  109. package/dist/constants.mjs.map +0 -1
  110. package/dist/defaultLauncher.cjs +0 -2
  111. package/dist/defaultLauncher.cjs.map +0 -1
  112. package/dist/defaultLauncher.d.cts +0 -10
  113. package/dist/defaultLauncher.d.cts.map +0 -1
  114. package/dist/defaultLauncher.d.mts +0 -10
  115. package/dist/defaultLauncher.d.mts.map +0 -1
  116. package/dist/defaultLauncher.mjs +0 -2
  117. package/dist/defaultLauncher.mjs.map +0 -1
  118. package/dist/extension.cjs +0 -2
  119. package/dist/extension.cjs.map +0 -1
  120. package/dist/extension.d.cts +0 -6
  121. package/dist/extension.d.cts.map +0 -1
  122. package/dist/extension.d.mts +0 -6
  123. package/dist/extension.d.mts.map +0 -1
  124. package/dist/extension.mjs +0 -2
  125. package/dist/extension.mjs.map +0 -1
  126. package/dist/launcher.cjs +0 -2
  127. package/dist/launcher.cjs.map +0 -1
  128. package/dist/launcher.d.cts +0 -47
  129. package/dist/launcher.d.cts.map +0 -1
  130. package/dist/launcher.d.mts +0 -47
  131. package/dist/launcher.d.mts.map +0 -1
  132. package/dist/launcher.mjs +0 -2
  133. package/dist/launcher.mjs.map +0 -1
  134. package/dist/leader.cjs +0 -2
  135. package/dist/leader.cjs.map +0 -1
  136. package/dist/leader.mjs +0 -2
  137. package/dist/leader.mjs.map +0 -1
  138. package/dist/tui/loopListOverlay.cjs +0 -2
  139. package/dist/tui/loopListOverlay.cjs.map +0 -1
  140. package/dist/tui/loopListOverlay.mjs +0 -2
  141. package/dist/tui/loopListOverlay.mjs.map +0 -1
  142. package/dist/tui/startLoopOverlay.cjs +0 -2
  143. package/dist/tui/startLoopOverlay.cjs.map +0 -1
  144. package/dist/tui/startLoopOverlay.mjs +0 -2
  145. package/dist/tui/startLoopOverlay.mjs.map +0 -1
package/README.md CHANGED
@@ -1,42 +1,104 @@
1
1
  # @agimon-ai/doompi-loop
2
2
 
3
- Generic multi-loop controller for Doompi.
3
+ Send a prompt now, then repeat it at a bounded interval for the current session.
4
4
 
5
- Runs a prompt on a schedule. Loop is a minor mode: it toggles mid-session, stacks with
6
- the others, and reports itself on the shared `MODES` line.
5
+ Part of the [DoomPi distribution](https://www.npmjs.com/package/@agimon-ai/doompi).
7
6
 
8
- Part of [Doompi](https://www.npmjs.com/package/@agimon-ai/doompi), a coding agent that loads
9
- only the skills and tools you name. This package is composed by Doompi and is not usually
10
- installed on its own.
7
+ Several loops can coexist. Loop is a minor mode and remains active while at least one scheduled
8
+ prompt belongs to the current session.
9
+
10
+ > **Alpha:** launcher and scheduling contracts may change between releases.
11
+
12
+ ## Requirements
13
+
14
+ - Node.js 22.19.0 or newer
15
+ - Pi 0.85.0 and Pi TUI 0.85.0
11
16
 
12
17
  ## Install
13
18
 
19
+ The seeded `modes.yaml` selects Loop in `default.packages`. Keep it there or select it through a
20
+ layer; it is not fixed host infrastructure. For standalone Pi:
21
+
14
22
  ```bash
15
- npm install @agimon-ai/doompi-loop
23
+ pi install npm:@agimon-ai/doompi-loop
16
24
  ```
17
25
 
18
- ## How it loads
26
+ ## Start and manage loops
27
+
28
+ Use `/loop` to start a loop and `/loops` to inspect or stop active loops. In DoomPi, `SPC l s` opens
29
+ the start flow and `SPC l l` opens the list.
30
+
31
+ The default interval is 300 seconds. Accepted intervals range from 30 to 3600 seconds. A loop runs
32
+ its prompt once immediately, then schedules later passes.
33
+
34
+ If Pi is busy, a due pass waits for the shared agent to become idle. Multiple due signals can
35
+ coalesce rather than creating overlapping model turns. Stopping a loop prevents future passes but
36
+ does not rewind side effects from a pass already sent.
37
+
38
+ ## Lifecycle and cost
39
+
40
+ Loop state belongs to the session's `doom/loop-launchers` service; it is not a durable queue.
41
+ Replacing or shutting down the session aborts pending launches and stops active timers. Resuming a
42
+ transcript does not restart old loops.
19
43
 
20
- Doompi loads this unconditionally. It is core, not a layer, so it does not appear in
21
- `.doom/modes.yaml`: making it optional would only create broken configurations.
44
+ Every pass can start another model turn and repeat tool or external side effects. Choose
45
+ conservative intervals, make prompts idempotent where possible, and stop loops when the recurring
46
+ work is complete.
22
47
 
23
- Extension entry: `@agimon-ai/doompi-loop/extensions/pi`
48
+ ## Web extension slots
24
49
 
25
- ## Leader
50
+ The Loop Activity section declares `loop.registration` for start controls and `loop.items` for
51
+ session-scoped instance rows. Other web plugins may fill either slot; Loop owns the section shell and
52
+ renders all registered fills without requiring a feature-specific dependency.
26
53
 
27
- `SPC l s` starts a loop, `SPC l l` lists and stops them, once the extension is loaded.
54
+ ## Extension authors: cross-extension launchers
28
55
 
29
- The built-in **Default loop** asks for a prompt and an interval, runs one pass immediately,
30
- and repeats while the session is open. Other extensions can register domain-specific loop
31
- launchers alongside it.
56
+ Launcher definitions use the shared Cordis service. A consumer registers a launcher and returns its
57
+ cleanup callback. Cordis removes that launcher when either package or the session unloads, then
58
+ registers it again when the provider returns.
32
59
 
33
- ## Entry points
60
+ ```ts
61
+ import { DOOM_LOOP_LAUNCHERS_SERVICE, requireDoomLoopLaunchers } from '@agimon-ai/doompi-loop/loop-launchers';
62
+ import type { Context } from '@deepseek-ai/cordis';
34
63
 
35
- | Import |
36
- | -------------------------------------- |
37
- | `@agimon-ai/doompi-loop` |
38
- | `@agimon-ai/doompi-loop/extensions/pi` |
64
+ export function myLoopPlugin(ctx: Context): void {
65
+ ctx.inject([DOOM_LOOP_LAUNCHERS_SERVICE], (sessionContext) => {
66
+ const registration = requireDoomLoopLaunchers(sessionContext).register({
67
+ id: 'example.recurring-check',
68
+ source: '@example/doompi-recurring-check',
69
+ label: 'Recurring check',
70
+ async launch({ instanceId, signal }) {
71
+ signal.throwIfAborted();
72
+ // Start session work. The returned stop callback owns cleanup.
73
+ return { instanceId, stop: () => undefined };
74
+ },
75
+ });
76
+ return () => registration.dispose('Contributor unloaded.');
77
+ });
78
+ }
79
+ ```
80
+
81
+ Mount that plugin on the runner's shared Doom Cordis root. Loop owns the registry and default
82
+ launcher. Consumers depend only on
83
+ `@agimon-ai/doompi-loop/loop-launchers`; there is no process-global registry or
84
+ session-ID lookup API.
85
+
86
+ The package root exports the service contract
87
+ types. Normal Pi activation uses the discovered `extensions/pi` entry.
88
+
89
+ ## Development
90
+
91
+ ```bash
92
+ pnpm build
93
+ pnpm typecheck
94
+ pnpm test
95
+ pnpm lint
96
+ ```
97
+
98
+ Maintained by [Agimon](https://agimon.ai/about).
39
99
 
40
100
  ## License
41
101
 
42
102
  MIT
103
+
104
+ Pi and server entries live directly in `src/extensions/`. They declare commands, minor mode owners, and optional services. The helpers own registration and cleanup; `onDispose` clears UI state, while session service disposal stops pending launches and timers. Services live in named folders and public exports remain flat.
@@ -0,0 +1 @@
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));exports.__toESM=s;
@@ -0,0 +1 @@
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./src/schemas/apiContracts.cjs");exports.apiContracts=e.apiContracts,exports.default=e.apiContracts;
@@ -0,0 +1,2 @@
1
+ import { apiContracts } from "./src/schemas/apiContracts.cjs";
2
+ export { apiContracts, apiContracts as default };
@@ -0,0 +1,2 @@
1
+ import { apiContracts } from "./src/schemas/apiContracts.mjs";
2
+ export { apiContracts, apiContracts as default };
@@ -0,0 +1 @@
1
+ import{apiContracts as e}from"./src/schemas/apiContracts.mjs";export{e as apiContracts,e as default};
@@ -1,2 +1,2 @@
1
- var e=require("../extension.cjs").registerLoopExtension;module.exports=e;
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../src/constants/piLoop.cjs"),t=require("../src/controllers/loopCommand.cjs"),n=require("../src/tui/loopRuntime.cjs");let r=require("@agimon-ai/doompi-core/pi-extension"),i=require("@agimon-ai/doompi-minor-mode");const a=(0,r.definePiExtension)(e.PACKAGE_SOURCE,({pi:r})=>{let a=n.createLoopPiRuntime(r);return{services:[...a.services??[],(0,i.piMinorModes)(a.minorModes)],events:{agent_settled:a.onAgentSettled},commands:t.createLoopCommands(a.handlers),onDispose:()=>a.onDispose(),resources:[{source:e.PACKAGE_SOURCE,moduleUrl:require("url").pathToFileURL(__filename).href,skills:[{name:`doompi-use-loop`,description:`Use Doom Pi Loop to start, inspect, and stop session-scoped recurring prompts safely.`}]}]}});exports.default=a,exports.loopExtension=a;
2
2
  //# sourceMappingURL=pi.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"pi.cjs","names":["registerLoopExtension"],"sources":["../../src/extensions/pi.ts"],"sourcesContent":["import { registerLoopExtension } from '../extension.ts';\n\nexport default registerLoopExtension;\n"],"mappings":"AAEA,IAAA,4BAAeA,CAAAA,CAAAA"}
1
+ {"version":3,"file":"pi.cjs","names":["definePiExtension","PACKAGE_SOURCE","createLoopPiRuntime","piMinorModes","createLoopCommands"],"sources":["../../src/extensions/pi.ts"],"sourcesContent":["import { definePiExtension } from '@agimon-ai/doompi-core/pi-extension';\nimport { piMinorModes } from '@agimon-ai/doompi-minor-mode';\n\nimport { PACKAGE_SOURCE } from '../constants/piLoop';\nimport { createLoopCommands } from '../controllers/loopCommand';\nimport { createLoopPiRuntime } from '../tui/loopRuntime';\nexport const loopExtension = definePiExtension(PACKAGE_SOURCE, ({ pi }) => {\n const runtime = createLoopPiRuntime(pi);\n return {\n services: [...(runtime.services ?? []), piMinorModes(runtime.minorModes)],\n events: { agent_settled: runtime.onAgentSettled },\n commands: createLoopCommands(runtime.handlers),\n\n onDispose: () => runtime.onDispose(),\n resources: [\n {\n source: PACKAGE_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-use-loop',\n description: 'Use Doom Pi Loop to start, inspect, and stop session-scoped recurring prompts safely.',\n },\n ],\n },\n ],\n };\n});\nexport default loopExtension;\n"],"mappings":"qUAMA,MAAa,GAAA,EAAgBA,EAAAA,kBAAAA,CAAkBC,EAAAA,gBAAiB,CAAE,QAAS,CACzE,IAAM,EAAUC,EAAAA,oBAAoB,CAAE,EACtC,MAAO,CACL,SAAU,CAAC,GAAI,EAAQ,UAAY,CAAC,GAAA,EAAIC,EAAAA,aAAAA,CAAa,EAAQ,UAAU,CAAC,EACxE,OAAQ,CAAE,cAAe,EAAQ,cAAe,EAChD,SAAUC,EAAAA,mBAAmB,EAAQ,QAAQ,EAE7C,cAAiB,EAAQ,UAAU,EACnC,UAAW,CACT,CACE,OAAQH,EAAAA,eACR,UAAA,QAAA,KAAA,CAAA,CAAA,cAAA,UAAA,CAAA,CAAA,KACA,OAAQ,CACN,CACE,KAAM,kBACN,YAAa,uFACf,CACF,CACF,CACF,CACF,CACF,CAAC"}
@@ -1,2 +1,5 @@
1
- import { registerLoopExtension } from "../extension.cjs";
2
- export = registerLoopExtension;
1
+ //#region src/extensions/pi.d.ts
2
+ export declare const loopExtension: import("@agimon-ai/doompi-core/runtime-pi-extension").DefinedPiExtension<undefined>;
3
+ //#endregion
4
+ export { loopExtension as default };
5
+ //# sourceMappingURL=pi.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.d.cts","names":[],"sources":["../../src/extensions/pi.ts"],"mappings":";qBAMa,qEAAa"}
@@ -1,2 +1,5 @@
1
- import { registerLoopExtension } from "../extension.mjs";
2
- export { registerLoopExtension as default };
1
+ //#region src/extensions/pi.d.ts
2
+ export declare const loopExtension: import("@agimon-ai/doompi-core/runtime-pi-extension").DefinedPiExtension<undefined>;
3
+ //#endregion
4
+ export { loopExtension as default };
5
+ //# sourceMappingURL=pi.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.d.mts","names":[],"sources":["../../src/extensions/pi.ts"],"mappings":";qBAMa,qEAAa"}
@@ -1,2 +1,2 @@
1
- import{registerLoopExtension as e}from"../extension.mjs";var t=e;export{t as default};
1
+ import{PACKAGE_SOURCE as e}from"../src/constants/piLoop.mjs";import{createLoopCommands as t}from"../src/controllers/loopCommand.mjs";import{createLoopPiRuntime as n}from"../src/tui/loopRuntime.mjs";import{definePiExtension as r}from"@agimon-ai/doompi-core/pi-extension";import{piMinorModes as i}from"@agimon-ai/doompi-minor-mode";const a=r(e,({pi:r})=>{let a=n(r);return{services:[...a.services??[],i(a.minorModes)],events:{agent_settled:a.onAgentSettled},commands:t(a.handlers),onDispose:()=>a.onDispose(),resources:[{source:e,moduleUrl:import.meta.url,skills:[{name:`doompi-use-loop`,description:`Use Doom Pi Loop to start, inspect, and stop session-scoped recurring prompts safely.`}]}]}});export{a as default,a as loopExtension};
2
2
  //# sourceMappingURL=pi.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"pi.mjs","names":[],"sources":["../../src/extensions/pi.ts"],"sourcesContent":["import { registerLoopExtension } from '../extension.ts';\n\nexport default registerLoopExtension;\n"],"mappings":"yDAEA,IAAA,EAAe"}
1
+ {"version":3,"file":"pi.mjs","names":[],"sources":["../../src/extensions/pi.ts"],"sourcesContent":["import { definePiExtension } from '@agimon-ai/doompi-core/pi-extension';\nimport { piMinorModes } from '@agimon-ai/doompi-minor-mode';\n\nimport { PACKAGE_SOURCE } from '../constants/piLoop';\nimport { createLoopCommands } from '../controllers/loopCommand';\nimport { createLoopPiRuntime } from '../tui/loopRuntime';\nexport const loopExtension = definePiExtension(PACKAGE_SOURCE, ({ pi }) => {\n const runtime = createLoopPiRuntime(pi);\n return {\n services: [...(runtime.services ?? []), piMinorModes(runtime.minorModes)],\n events: { agent_settled: runtime.onAgentSettled },\n commands: createLoopCommands(runtime.handlers),\n\n onDispose: () => runtime.onDispose(),\n resources: [\n {\n source: PACKAGE_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-use-loop',\n description: 'Use Doom Pi Loop to start, inspect, and stop session-scoped recurring prompts safely.',\n },\n ],\n },\n ],\n };\n});\nexport default loopExtension;\n"],"mappings":"0UAMA,MAAa,EAAgB,EAAkB,GAAiB,CAAE,QAAS,CACzE,IAAM,EAAU,EAAoB,CAAE,EACtC,MAAO,CACL,SAAU,CAAC,GAAI,EAAQ,UAAY,CAAC,EAAI,EAAa,EAAQ,UAAU,CAAC,EACxE,OAAQ,CAAE,cAAe,EAAQ,cAAe,EAChD,SAAU,EAAmB,EAAQ,QAAQ,EAE7C,cAAiB,EAAQ,UAAU,EACnC,UAAW,CACT,CACE,OAAQ,EACR,UAAW,YAAY,IACvB,OAAQ,CACN,CACE,KAAM,kBACN,YAAa,uFACf,CACF,CACF,CACF,CACF,CACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../src/controllers/serverRuntime.cjs"),t=(0,require("@agimon-ai/doompi-core/server-facet").defineServerPlugin)({name:`@agimon-ai/doompi-loop`,session:({agent:t})=>t?e.createSessionState(t):{}});exports.default=t,exports.loopServerFacet=t;
2
+ //# sourceMappingURL=server.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.cjs","names":["defineServerPlugin","createSessionState"],"sources":["../../src/extensions/server.ts"],"sourcesContent":["import { defineServerPlugin } from '@agimon-ai/doompi-core/server-facet';\n\nimport { createSessionState } from '../controllers/serverRuntime';\nexport const loopServerFacet = defineServerPlugin({\n name: '@agimon-ai/doompi-loop',\n session: ({ agent }) => (agent ? createSessionState(agent) : {}),\n});\nexport default loopServerFacet;\n"],"mappings":"uJAGa,GAAA,+CAAkBA,CAAAA,CAAAA,mBAAAA,CAAmB,CAChD,KAAM,yBACN,SAAU,CAAE,WAAa,EAAQC,EAAAA,mBAAmB,CAAK,EAAI,CAAC,CAChE,CAAC"}
@@ -0,0 +1,5 @@
1
+ //#region src/extensions/server.d.ts
2
+ export declare const loopServerFacet: import("@agimon-ai/doompi-core/server-facet").DoomServerFacet;
3
+ //#endregion
4
+ export { loopServerFacet as default };
5
+ //# sourceMappingURL=server.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.cts","names":[],"sources":["../../src/extensions/server.ts"],"mappings":";qBAGa,+DAAe"}
@@ -0,0 +1,5 @@
1
+ //#region src/extensions/server.d.ts
2
+ export declare const loopServerFacet: import("@agimon-ai/doompi-core/server-facet").DoomServerFacet;
3
+ //#endregion
4
+ export { loopServerFacet as default };
5
+ //# sourceMappingURL=server.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.mts","names":[],"sources":["../../src/extensions/server.ts"],"mappings":";qBAGa,+DAAe"}
@@ -0,0 +1,2 @@
1
+ import{createSessionState as e}from"../src/controllers/serverRuntime.mjs";import{defineServerPlugin as t}from"@agimon-ai/doompi-core/server-facet";const n=t({name:`@agimon-ai/doompi-loop`,session:({agent:t})=>t?e(t):{}});export{n as default,n as loopServerFacet};
2
+ //# sourceMappingURL=server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.mjs","names":[],"sources":["../../src/extensions/server.ts"],"sourcesContent":["import { defineServerPlugin } from '@agimon-ai/doompi-core/server-facet';\n\nimport { createSessionState } from '../controllers/serverRuntime';\nexport const loopServerFacet = defineServerPlugin({\n name: '@agimon-ai/doompi-loop',\n session: ({ agent }) => (agent ? createSessionState(agent) : {}),\n});\nexport default loopServerFacet;\n"],"mappings":"mJAGA,MAAa,EAAkB,EAAmB,CAChD,KAAM,yBACN,SAAU,CAAE,WAAa,EAAQ,EAAmB,CAAK,EAAI,CAAC,CAChE,CAAC"}
package/dist/index.cjs CHANGED
@@ -1 +0,0 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./launcher.cjs"),t=require("./defaultLauncher.cjs"),n=require("./extension.cjs");exports.createDefaultLoopLauncher=t.createDefaultLoopLauncher,exports.createLoopLauncherClient=e.createLoopLauncherClient,exports.registerLoopExtension=n.registerLoopExtension,exports.registerLoopLauncher=e.registerLoopLauncher;
package/dist/index.d.cts CHANGED
@@ -1,4 +1,2 @@
1
- import { registerLoopExtension } from "./extension.cjs";
2
- import { LoopInstanceSnapshot, LoopLaunchRequest, LoopLauncherClient, LoopLauncherRegistration, LoopLauncherSummary, RegisterLoopLauncherOptions, StoppableLoop, createLoopLauncherClient, registerLoopLauncher } from "./launcher.cjs";
3
- import { DefaultLoopLauncher, createDefaultLoopLauncher } from "./defaultLauncher.cjs";
4
- export { type DefaultLoopLauncher, type LoopInstanceSnapshot, type LoopLaunchRequest, type LoopLauncherClient, type LoopLauncherRegistration, type LoopLauncherSummary, type RegisterLoopLauncherOptions, type StoppableLoop, createDefaultLoopLauncher, createLoopLauncherClient, registerLoopExtension, registerLoopLauncher };
1
+ import { DoomLoopLaunchersService, LoopInstanceSnapshot, LoopLaunchRequest, LoopLauncherDefinition, LoopLauncherRegistration, LoopLauncherSummary, StoppableLoop } from "./src/schemas/loopLaunchers.cjs";
2
+ export type { DoomLoopLaunchersService, LoopInstanceSnapshot, LoopLaunchRequest, LoopLauncherDefinition, LoopLauncherRegistration, LoopLauncherSummary, StoppableLoop };
package/dist/index.d.mts CHANGED
@@ -1,4 +1,2 @@
1
- import { registerLoopExtension } from "./extension.mjs";
2
- import { LoopInstanceSnapshot, LoopLaunchRequest, LoopLauncherClient, LoopLauncherRegistration, LoopLauncherSummary, RegisterLoopLauncherOptions, StoppableLoop, createLoopLauncherClient, registerLoopLauncher } from "./launcher.mjs";
3
- import { DefaultLoopLauncher, createDefaultLoopLauncher } from "./defaultLauncher.mjs";
4
- export { type DefaultLoopLauncher, type LoopInstanceSnapshot, type LoopLaunchRequest, type LoopLauncherClient, type LoopLauncherRegistration, type LoopLauncherSummary, type RegisterLoopLauncherOptions, type StoppableLoop, createDefaultLoopLauncher, createLoopLauncherClient, registerLoopExtension, registerLoopLauncher };
1
+ import { DoomLoopLaunchersService, LoopInstanceSnapshot, LoopLaunchRequest, LoopLauncherDefinition, LoopLauncherRegistration, LoopLauncherSummary, StoppableLoop } from "./src/schemas/loopLaunchers.mjs";
2
+ export type { DoomLoopLaunchersService, LoopInstanceSnapshot, LoopLaunchRequest, LoopLauncherDefinition, LoopLauncherRegistration, LoopLauncherSummary, StoppableLoop };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{createLoopLauncherClient as e,registerLoopLauncher as t}from"./launcher.mjs";import{createDefaultLoopLauncher as n}from"./defaultLauncher.mjs";import{registerLoopExtension as r}from"./extension.mjs";export{n as createDefaultLoopLauncher,e as createLoopLauncherClient,r as registerLoopExtension,t as registerLoopLauncher};
1
+ export{};
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./src/schemas/loopLaunchers.cjs");exports.DOOM_LOOP_LAUNCHERS_SERVICE=e.DOOM_LOOP_LAUNCHERS_SERVICE,exports.readDoomLoopLaunchers=e.readDoomLoopLaunchers,exports.requireDoomLoopLaunchers=e.requireDoomLoopLaunchers;
@@ -0,0 +1,2 @@
1
+ import { DOOM_LOOP_LAUNCHERS_SERVICE, DoomLoopLaunchersService, LoopInstanceSnapshot, LoopLaunchRequest, LoopLauncherDefinition, LoopLauncherRegistration, LoopLauncherSummary, StoppableLoop, readDoomLoopLaunchers, requireDoomLoopLaunchers } from "./src/schemas/loopLaunchers.cjs";
2
+ export { DOOM_LOOP_LAUNCHERS_SERVICE, type DoomLoopLaunchersService, type LoopInstanceSnapshot, type LoopLaunchRequest, type LoopLauncherDefinition, type LoopLauncherRegistration, type LoopLauncherSummary, type StoppableLoop, readDoomLoopLaunchers, requireDoomLoopLaunchers };
@@ -0,0 +1,2 @@
1
+ import { DOOM_LOOP_LAUNCHERS_SERVICE, DoomLoopLaunchersService, LoopInstanceSnapshot, LoopLaunchRequest, LoopLauncherDefinition, LoopLauncherRegistration, LoopLauncherSummary, StoppableLoop, readDoomLoopLaunchers, requireDoomLoopLaunchers } from "./src/schemas/loopLaunchers.mjs";
2
+ export { DOOM_LOOP_LAUNCHERS_SERVICE, type DoomLoopLaunchersService, type LoopInstanceSnapshot, type LoopLaunchRequest, type LoopLauncherDefinition, type LoopLauncherRegistration, type LoopLauncherSummary, type StoppableLoop, readDoomLoopLaunchers, requireDoomLoopLaunchers };
@@ -0,0 +1 @@
1
+ import{DOOM_LOOP_LAUNCHERS_SERVICE as e,readDoomLoopLaunchers as t,requireDoomLoopLaunchers as n}from"./src/schemas/loopLaunchers.mjs";export{e as DOOM_LOOP_LAUNCHERS_SERVICE,t as readDoomLoopLaunchers,n as requireDoomLoopLaunchers};
@@ -0,0 +1,2 @@
1
+ exports.LIST_COMMAND_DESCRIPTION=`List and stop active loops`,exports.LIST_COMMAND_NAME=`loops`,exports.START_COMMAND_DESCRIPTION=`Start a registered loop`,exports.START_COMMAND_NAME=`loop`;
2
+ //# sourceMappingURL=loop.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.cjs","names":[],"sources":["../../../src/constants/loop.ts"],"sourcesContent":["export const START_COMMAND_DESCRIPTION = 'Start a registered loop';\nexport const LIST_COMMAND_DESCRIPTION = 'List and stop active loops';\nexport const START_COMMAND_NAME = 'loop';\nexport const LIST_COMMAND_NAME = 'loops';\n"],"mappings":""}
@@ -0,0 +1,2 @@
1
+ const e=`Start a registered loop`,t=`List and stop active loops`,n=`loop`,r=`loops`;export{t as LIST_COMMAND_DESCRIPTION,r as LIST_COMMAND_NAME,e as START_COMMAND_DESCRIPTION,n as START_COMMAND_NAME};
2
+ //# sourceMappingURL=loop.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.mjs","names":[],"sources":["../../../src/constants/loop.ts"],"sourcesContent":["export const START_COMMAND_DESCRIPTION = 'Start a registered loop';\nexport const LIST_COMMAND_DESCRIPTION = 'List and stop active loops';\nexport const START_COMMAND_NAME = 'loop';\nexport const LIST_COMMAND_NAME = 'loops';\n"],"mappings":"AAAA,MAAa,EAA4B,0BAC5B,EAA2B,6BAC3B,EAAqB,OACrB,EAAoB"}
@@ -0,0 +1,2 @@
1
+ exports.ACTIVE_MODE_COLOR=`warning`,exports.MODE_STATUS_ID=`loop.active`,exports.NOTIFY_INFO_LEVEL=`info`,exports.NOTIFY_WARNING_LEVEL=`warning`,exports.PACKAGE_SOURCE=`@agimon-ai/doompi-loop`,exports.STATUS_KEY=`doom-loop`;
2
+ //# sourceMappingURL=piLoop.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"piLoop.cjs","names":[],"sources":["../../../src/constants/piLoop.ts"],"sourcesContent":["export const PACKAGE_SOURCE = '@agimon-ai/doompi-loop';\nexport const LOOPS_GROUP_ORDER = 60;\nexport const STATUS_KEY = 'doom-loop';\nexport const MODE_STATUS_ID = 'loop.active';\nexport const ACTIVE_MODE_COLOR = 'warning';\nexport const NOTIFY_INFO_LEVEL = 'info';\nexport const NOTIFY_WARNING_LEVEL = 'warning';\n"],"mappings":""}
@@ -0,0 +1,2 @@
1
+ const e=`@agimon-ai/doompi-loop`,t=`doom-loop`,n=`loop.active`,r=`warning`,i=`info`,a=`warning`;export{r as ACTIVE_MODE_COLOR,n as MODE_STATUS_ID,i as NOTIFY_INFO_LEVEL,a as NOTIFY_WARNING_LEVEL,e as PACKAGE_SOURCE,t as STATUS_KEY};
2
+ //# sourceMappingURL=piLoop.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"piLoop.mjs","names":[],"sources":["../../../src/constants/piLoop.ts"],"sourcesContent":["export const PACKAGE_SOURCE = '@agimon-ai/doompi-loop';\nexport const LOOPS_GROUP_ORDER = 60;\nexport const STATUS_KEY = 'doom-loop';\nexport const MODE_STATUS_ID = 'loop.active';\nexport const ACTIVE_MODE_COLOR = 'warning';\nexport const NOTIFY_INFO_LEVEL = 'info';\nexport const NOTIFY_WARNING_LEVEL = 'warning';\n"],"mappings":"AAAA,MAAa,EAAiB,yBAEjB,EAAa,YACb,EAAiB,cACjB,EAAoB,UACpB,EAAoB,OACpB,EAAuB"}
@@ -0,0 +1,2 @@
1
+ const e=require("../constants/loop.cjs");function t(t){return[[e.START_COMMAND_NAME,{description:e.START_COMMAND_DESCRIPTION,handler:async(e,n)=>t.start(n,e)}],[e.LIST_COMMAND_NAME,{description:e.LIST_COMMAND_DESCRIPTION,handler:async(e,n)=>t.list(n)}]]}exports.createLoopCommands=t;
2
+ //# sourceMappingURL=loopCommand.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopCommand.cjs","names":["START_COMMAND_NAME","START_COMMAND_DESCRIPTION","LIST_COMMAND_NAME","LIST_COMMAND_DESCRIPTION"],"sources":["../../../src/controllers/loopCommand.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\nimport { START_COMMAND_DESCRIPTION, LIST_COMMAND_DESCRIPTION } from '../constants/loop';\nimport { LIST_COMMAND_NAME, START_COMMAND_NAME } from '../constants/loop';\nimport type { LoopCommandHandlers } from '../types/loopCommand';\nexport function createLoopCommands(\n handlers: LoopCommandHandlers,\n): readonly (readonly [string, Parameters<ExtensionAPI['registerCommand']>[1]])[] {\n return [\n [\n START_COMMAND_NAME,\n {\n description: START_COMMAND_DESCRIPTION,\n handler: async (args, ctx) => handlers.start(ctx, args),\n },\n ],\n [\n LIST_COMMAND_NAME,\n {\n description: LIST_COMMAND_DESCRIPTION,\n handler: async (_args, ctx) => handlers.list(ctx),\n },\n ],\n ];\n}\n"],"mappings":"yCAKA,SAAgB,EACd,EACgF,CAChF,MAAO,CACL,CACEA,EAAAA,mBACA,CACE,YAAaC,EAAAA,0BACb,QAAS,MAAO,EAAM,IAAQ,EAAS,MAAM,EAAK,CAAI,CACxD,CACF,EACA,CACEC,EAAAA,kBACA,CACE,YAAaC,EAAAA,yBACb,QAAS,MAAO,EAAO,IAAQ,EAAS,KAAK,CAAG,CAClD,CACF,CACF,CACF"}
@@ -0,0 +1,2 @@
1
+ import{LIST_COMMAND_DESCRIPTION as e,LIST_COMMAND_NAME as t,START_COMMAND_DESCRIPTION as n,START_COMMAND_NAME as r}from"../constants/loop.mjs";function i(i){return[[r,{description:n,handler:async(e,t)=>i.start(t,e)}],[t,{description:e,handler:async(e,t)=>i.list(t)}]]}export{i as createLoopCommands};
2
+ //# sourceMappingURL=loopCommand.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopCommand.mjs","names":[],"sources":["../../../src/controllers/loopCommand.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\nimport { START_COMMAND_DESCRIPTION, LIST_COMMAND_DESCRIPTION } from '../constants/loop';\nimport { LIST_COMMAND_NAME, START_COMMAND_NAME } from '../constants/loop';\nimport type { LoopCommandHandlers } from '../types/loopCommand';\nexport function createLoopCommands(\n handlers: LoopCommandHandlers,\n): readonly (readonly [string, Parameters<ExtensionAPI['registerCommand']>[1]])[] {\n return [\n [\n START_COMMAND_NAME,\n {\n description: START_COMMAND_DESCRIPTION,\n handler: async (args, ctx) => handlers.start(ctx, args),\n },\n ],\n [\n LIST_COMMAND_NAME,\n {\n description: LIST_COMMAND_DESCRIPTION,\n handler: async (_args, ctx) => handlers.list(ctx),\n },\n ],\n ];\n}\n"],"mappings":"+IAKA,SAAgB,EACd,EACgF,CAChF,MAAO,CACL,CACE,EACA,CACE,YAAa,EACb,QAAS,MAAO,EAAM,IAAQ,EAAS,MAAM,EAAK,CAAI,CACxD,CACF,EACA,CACE,EACA,CACE,YAAa,EACb,QAAS,MAAO,EAAO,IAAQ,EAAS,KAAK,CAAG,CAClD,CACF,CACF,CACF"}
@@ -0,0 +1,2 @@
1
+ const e=require("../constants/loop.cjs"),t=require("../services/loopLaunchers/index.cjs"),n=require("../services/loopResource/index.cjs");let r=require("@agimon-ai/doompi-minor-mode");const i=`@agimon-ai/doompi-loop`,a=`loop.active`,o=3600;function s(e,t,n=`info`){return Promise.resolve(e.client.notify({body:t,level:n}))}function c(e,t){if(typeof e!=`string`||e.trim()===``)return t;let n=Number(e);if(!Number.isInteger(n)||n<30||n>o)throw Error(`Interval must be between 30 and ${o} seconds.`);return n}function l(o){let l,u,d,f,p=()=>(o.context.selection.state?.[`minor-mode`]??[]).includes(a),m=()=>{let e=l?.listLaunchers().length??0,t=(l?.listInstances().length??0)>0,n=e>0||!p();return{activation:t?`active`:`inactive`,condition:l?.listInstances().some(({state:e})=>e!==`running`)?`queued`:`ready`,...t?{detail:`${l?.listInstances().length} active`,color:`warning`}:{},actions:[{id:`start`,enabled:n,...n?{}:{disabledReason:`No loop launchers are registered.`}},{id:`stop`,enabled:t,...t?{}:{disabledReason:`No loops are active.`}}]}},h=()=>f?.publish();return f=(0,r.defineMinorMode)({descriptor:{source:i,id:a,label:`Loop`,description:`Session-scoped recurring prompt loops.`,order:60,actions:[{id:`start`,label:`Start`,description:`Start a loop with a registered launcher.`,contexts:[`headless`],parameters:[{name:`launcherId`,label:`Launcher`,kind:`string`,required:!0,minLength:1},{name:`instanceId`,label:`Instance ID`,kind:`string`,required:!1,minLength:1}]},{id:`stop`,label:`Stop`,description:`Stop one active loop instance.`,contexts:[`headless`],parameters:[{name:`instanceId`,label:`Instance ID`,kind:`string`,required:!0,minLength:1},{name:`reason`,label:`Reason`,kind:`string`,required:!1,minLength:1}]}]},state:m,async handleAction(e,t,n,{signal:r}){if(r.throwIfAborted(),t===`start`&&!l){let e=(o.context.selection.state?.[`minor-mode`]??[]).filter(e=>e!==a);await o.changeSelection({axis:`state`,key:`minor-mode`,values:[...e,a]})}if(!l)throw Error(`Loop activity is not active.`);if(t===`start`){let e=await l.launch(String(n.launcherId??``),n.instanceId?{instanceId:String(n.instanceId)}:{});return h(),{message:e?`Loop '${e.instanceId}' started.`:`Loop launch was cancelled.`}}if(t===`stop`){let e=await l.stop(String(n.instanceId??``),String(n.reason??`Stopped through minor_mode.`));if(e&&l.listInstances().length===0){let e=(o.context.selection.state?.[`minor-mode`]??[]).filter(e=>e!==a);await o.changeSelection({axis:`state`,key:`minor-mode`,values:e})}return h(),{message:e?`Loop stopped.`:`Loop instance was not active.`}}throw Error(`Unknown loop mode action: ${t}`)}}).createOwner(void 0),{services:[(0,r.serverMinorModes)([f])],resources:[{when:{state:{"minor-mode":a},attribution:{kind:`minor`,mode:a}},name:`doompi-use-loop`,kind:`skill`,read:()=>n.readLoopResource()}],activities:[{when:{state:{"minor-mode":a},attribution:{kind:`minor`,mode:a}},name:`doompi-loop`,start:async e=>{if(l!==void 0)return async()=>void 0;let n={generation:`${e.sessionId}:loop-launchers`,createInstanceId:()=>crypto.randomUUID(),timestamp:()=>new Date().toISOString()},r=t.createDoomLoopLaunchersService(n),a=r.register({id:`doompi.default`,source:i,label:`Default loop`,description:`Run a prompt in this session on an interval.`,async launch({instanceId:t,signal:n}){let r=await e.client.request({kind:`input`,title:`Loop prompt`,multiline:!0},n),i=typeof r==`string`?r.trim():``;if(!i||n.aborted)return;let a=c(await e.client.request({kind:`input`,title:`Loop interval in seconds`,initialValue:`300`},n),300),o=!1,l=()=>{o||n.aborted||e.session.prompt(i).catch(t=>{s(e,`Loop pass failed: ${t instanceof Error?t.message:String(t)}`,`warning`)})},u=setInterval(l,a*1e3);return u.unref?.(),l(),{instanceId:t,label:`Default loop`,detail:`every ${a}s`,stop(){o=!0,clearInterval(u)}}}});return l=r,u=a,d=r.subscribe(h),h(),async()=>{d?.(),d=void 0,await a.dispose(`Headless loop activity stopped.`),await r.dispose(`Headless loop activity stopped.`),l===r&&(l=void 0),u===a&&(u=void 0),h()}}}],commands:[{when:{state:{"minor-mode":a},attribution:{kind:`minor`,mode:a}},name:e.START_COMMAND_NAME,description:`Start a registered loop.`,async execute(e,t){if(!l)throw Error(`Loop activity is not active.`);let n=l.listLaunchers(),r=await t.client.request({kind:`select`,title:`Choose a loop launcher`,options:n.map(e=>({label:e.label,value:e.id}))}),i=e.trim()||(typeof r==`string`?r:``);if(!i)return;let a=await l.launch(i);h(),await s(t,a?`Loop '${a.instanceId}' started.`:`Loop launch was cancelled.`)}},{when:{state:{"minor-mode":a},attribution:{kind:`minor`,mode:a}},name:e.LIST_COMMAND_NAME,description:`List and stop active loops.`,async execute(e,t){if(!l)throw Error(`Loop activity is not active.`);let n=l.listInstances();await s(t,n.length===0?`No loops are active.`:JSON.stringify(n,null,2))}}],hooks:[{when:{state:{"minor-mode":a},attribution:{kind:`minor`,mode:a}},event:`session_shutdown`,async handle(){await l?.stopAll(`Headless session shutdown.`)}}],async onDispose(){await u?.dispose(`Headless loop facet disposed.`),await l?.dispose(`Headless loop facet disposed.`)}}}exports.createSessionState=l;
2
+ //# sourceMappingURL=serverRuntime.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverRuntime.cjs","names":["createDoomLoopLaunchersService","defineMinorMode","serverMinorModes","readLoopResource","START_COMMAND_NAME","LIST_COMMAND_NAME"],"sources":["../../../src/controllers/serverRuntime.ts"],"sourcesContent":["import { serverMinorModes } from '@agimon-ai/doompi-minor-mode';\nimport { defineMinorMode, type MinorModeOwner, type MinorModeState } from '@agimon-ai/doompi-minor-mode';\n\nimport { LIST_COMMAND_NAME, START_COMMAND_NAME } from '../constants/loop';\nimport type { DoomLoopLaunchersService, LoopLauncherRegistration, StoppableLoop } from '../schemas/loopLaunchers';\nimport { createDoomLoopLaunchersService, type LoopLaunchersDependencies } from '../services/loopLaunchers';\nimport { readLoopResource } from '../services/loopResource';\n\nconst SOURCE = '@agimon-ai/doompi-loop';\nconst MODE_ID = 'loop.active';\nconst DEFAULT_LAUNCHER_ID = 'doompi.default';\nconst DEFAULT_INTERVAL_SECONDS = 300;\nconst MIN_INTERVAL_SECONDS = 30;\nconst MAX_INTERVAL_SECONDS = 3600;\n\nfunction notify(\n context: {\n client: { notify(request: { body: string; level?: 'info' | 'warning' | 'error' }): void | Promise<void> };\n },\n body: string,\n level: 'info' | 'warning' | 'error' = 'info',\n): Promise<void> {\n return Promise.resolve(context.client.notify({ body, level }));\n}\n\nfunction numberInput(value: unknown, fallback: number): number {\n if (typeof value !== 'string' || value.trim() === '') return fallback;\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed < MIN_INTERVAL_SECONDS || parsed > MAX_INTERVAL_SECONDS) {\n throw new Error(`Interval must be between ${MIN_INTERVAL_SECONDS} and ${MAX_INTERVAL_SECONDS} seconds.`);\n }\n return parsed;\n}\n\nimport { type DoomHeadlessExecutionContext, type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport type { DoomServerSessionPlugin } from '@agimon-ai/doompi-core/server-facet';\nexport function createSessionState(host: DoomHeadlessHostService): DoomServerSessionPlugin {\n let launchers: DoomLoopLaunchersService | undefined;\n let defaultRegistration: LoopLauncherRegistration | undefined;\n let unsubscribe: (() => void) | undefined;\n let modeOwner: MinorModeOwner | undefined;\n const modeSelected = (): boolean => (host.context.selection.state?.['minor-mode'] ?? []).includes(MODE_ID);\n const modeState = (): MinorModeState => {\n const launcherCount = launchers?.listLaunchers().length ?? 0;\n const active = (launchers?.listInstances().length ?? 0) > 0;\n const canStart = launcherCount > 0 || !modeSelected();\n return {\n activation: active ? 'active' : 'inactive',\n condition: launchers?.listInstances().some(({ state }) => state !== 'running') ? 'queued' : 'ready',\n ...(active ? { detail: `${launchers?.listInstances().length} active`, color: 'warning' } : {}),\n actions: [\n {\n id: 'start',\n enabled: canStart,\n ...(canStart ? {} : { disabledReason: 'No loop launchers are registered.' }),\n },\n {\n id: 'stop',\n enabled: active,\n ...(active ? {} : { disabledReason: 'No loops are active.' }),\n },\n ],\n };\n };\n const publishMode = (): void => modeOwner?.publish();\n const startActivity = async (execution: typeof host.context): Promise<() => Promise<void>> => {\n if (launchers !== undefined) return async () => undefined;\n const dependencies: LoopLaunchersDependencies = {\n generation: `${execution.sessionId}:loop-launchers`,\n createInstanceId: () => crypto.randomUUID(),\n timestamp: () => new Date().toISOString(),\n };\n const service = createDoomLoopLaunchersService(dependencies);\n const registration = service.register({\n id: DEFAULT_LAUNCHER_ID,\n source: SOURCE,\n label: 'Default loop',\n description: 'Run a prompt in this session on an interval.',\n async launch({ instanceId, signal }): Promise<StoppableLoop | undefined> {\n const promptValue = await execution.client.request(\n { kind: 'input', title: 'Loop prompt', multiline: true },\n signal,\n );\n const prompt = typeof promptValue === 'string' ? promptValue.trim() : '';\n if (!prompt || signal.aborted) return undefined;\n const interval = numberInput(\n await execution.client.request(\n { kind: 'input', title: 'Loop interval in seconds', initialValue: String(DEFAULT_INTERVAL_SECONDS) },\n signal,\n ),\n DEFAULT_INTERVAL_SECONDS,\n );\n let stopped = false;\n const tick = (): void => {\n if (stopped || signal.aborted) return;\n void execution.session.prompt(prompt).catch((error) => {\n void notify(\n execution,\n `Loop pass failed: ${error instanceof Error ? error.message : String(error)}`,\n 'warning',\n );\n });\n };\n const timer = setInterval(tick, interval * 1000);\n timer.unref?.();\n tick();\n return {\n instanceId,\n label: 'Default loop',\n detail: `every ${interval}s`,\n stop() {\n stopped = true;\n clearInterval(timer);\n },\n };\n },\n });\n launchers = service;\n defaultRegistration = registration;\n unsubscribe = service.subscribe(publishMode);\n publishMode();\n return async () => {\n unsubscribe?.();\n unsubscribe = undefined;\n await registration.dispose('Headless loop activity stopped.');\n await service.dispose('Headless loop activity stopped.');\n if (launchers === service) launchers = undefined;\n if (defaultRegistration === registration) defaultRegistration = undefined;\n publishMode();\n };\n };\n modeOwner = defineMinorMode({\n descriptor: {\n source: SOURCE,\n id: MODE_ID,\n label: 'Loop',\n description: 'Session-scoped recurring prompt loops.',\n order: 60,\n actions: [\n {\n id: 'start',\n label: 'Start',\n description: 'Start a loop with a registered launcher.',\n contexts: ['headless'],\n parameters: [\n { name: 'launcherId', label: 'Launcher', kind: 'string', required: true, minLength: 1 },\n { name: 'instanceId', label: 'Instance ID', kind: 'string', required: false, minLength: 1 },\n ],\n },\n {\n id: 'stop',\n label: 'Stop',\n description: 'Stop one active loop instance.',\n contexts: ['headless'],\n parameters: [\n { name: 'instanceId', label: 'Instance ID', kind: 'string', required: true, minLength: 1 },\n { name: 'reason', label: 'Reason', kind: 'string', required: false, minLength: 1 },\n ],\n },\n ],\n },\n state: modeState,\n async handleAction(_runtime, actionId, argumentsValue, { signal }) {\n signal.throwIfAborted();\n if (actionId === 'start' && !launchers) {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== MODE_ID);\n await host.changeSelection({ axis: 'state', key: 'minor-mode', values: [...modes, MODE_ID] });\n }\n if (!launchers) throw new Error('Loop activity is not active.');\n if (actionId === 'start') {\n const instance = await launchers.launch(\n String(argumentsValue.launcherId ?? ''),\n argumentsValue.instanceId ? { instanceId: String(argumentsValue.instanceId) } : {},\n );\n publishMode();\n return { message: instance ? `Loop '${instance.instanceId}' started.` : 'Loop launch was cancelled.' };\n }\n if (actionId === 'stop') {\n const stopped = await launchers.stop(\n String(argumentsValue.instanceId ?? ''),\n String(argumentsValue.reason ?? 'Stopped through minor_mode.'),\n );\n if (stopped && launchers.listInstances().length === 0) {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== MODE_ID);\n await host.changeSelection({ axis: 'state', key: 'minor-mode', values: modes });\n }\n publishMode();\n return { message: stopped ? 'Loop stopped.' : 'Loop instance was not active.' };\n }\n throw new Error(`Unknown loop mode action: ${actionId}`);\n },\n }).createOwner(undefined);\n return {\n services: [serverMinorModes([modeOwner])],\n resources: [\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n name: 'doompi-use-loop',\n kind: 'skill',\n read: () => readLoopResource(),\n },\n ],\n activities: [\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n name: 'doompi-loop',\n start: startActivity,\n },\n ],\n commands: [\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n name: START_COMMAND_NAME,\n description: 'Start a registered loop.',\n async execute(args: string, execution: DoomHeadlessExecutionContext) {\n if (!launchers) throw new Error('Loop activity is not active.');\n const available = launchers.listLaunchers();\n const selected = 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 const launcherId = args.trim() || (typeof selected === 'string' ? selected : '');\n if (!launcherId) return;\n const instance = await launchers.launch(launcherId);\n publishMode();\n await notify(execution, instance ? `Loop '${instance.instanceId}' started.` : 'Loop launch was cancelled.');\n },\n },\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n name: LIST_COMMAND_NAME,\n description: 'List and stop active loops.',\n async execute(_args: string, execution: DoomHeadlessExecutionContext) {\n if (!launchers) throw new Error('Loop activity is not active.');\n const instances = launchers.listInstances();\n await notify(execution, instances.length === 0 ? 'No loops are active.' : JSON.stringify(instances, null, 2));\n },\n },\n ],\n hooks: [\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n event: 'session_shutdown',\n async handle() {\n await launchers?.stopAll('Headless session shutdown.');\n },\n },\n ],\n async onDispose() {\n await defaultRegistration?.dispose('Headless loop facet disposed.');\n await launchers?.dispose('Headless loop facet disposed.');\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{LIST_COMMAND_NAME as e,START_COMMAND_NAME as t}from"../constants/loop.mjs";import{createDoomLoopLaunchersService as n}from"../services/loopLaunchers/index.mjs";import{readLoopResource as r}from"../services/loopResource/index.mjs";import{defineMinorMode as i,serverMinorModes as a}from"@agimon-ai/doompi-minor-mode";const o=`@agimon-ai/doompi-loop`,s=`loop.active`,c=3600;function l(e,t,n=`info`){return Promise.resolve(e.client.notify({body:t,level:n}))}function u(e,t){if(typeof e!=`string`||e.trim()===``)return t;let n=Number(e);if(!Number.isInteger(n)||n<30||n>c)throw Error(`Interval must be between 30 and ${c} seconds.`);return n}function d(c){let d,f,p,m,h=()=>(c.context.selection.state?.[`minor-mode`]??[]).includes(s),g=()=>{let e=d?.listLaunchers().length??0,t=(d?.listInstances().length??0)>0,n=e>0||!h();return{activation:t?`active`:`inactive`,condition:d?.listInstances().some(({state:e})=>e!==`running`)?`queued`:`ready`,...t?{detail:`${d?.listInstances().length} active`,color:`warning`}:{},actions:[{id:`start`,enabled:n,...n?{}:{disabledReason:`No loop launchers are registered.`}},{id:`stop`,enabled:t,...t?{}:{disabledReason:`No loops are active.`}}]}},_=()=>m?.publish();return m=i({descriptor:{source:o,id:s,label:`Loop`,description:`Session-scoped recurring prompt loops.`,order:60,actions:[{id:`start`,label:`Start`,description:`Start a loop with a registered launcher.`,contexts:[`headless`],parameters:[{name:`launcherId`,label:`Launcher`,kind:`string`,required:!0,minLength:1},{name:`instanceId`,label:`Instance ID`,kind:`string`,required:!1,minLength:1}]},{id:`stop`,label:`Stop`,description:`Stop one active loop instance.`,contexts:[`headless`],parameters:[{name:`instanceId`,label:`Instance ID`,kind:`string`,required:!0,minLength:1},{name:`reason`,label:`Reason`,kind:`string`,required:!1,minLength:1}]}]},state:g,async handleAction(e,t,n,{signal:r}){if(r.throwIfAborted(),t===`start`&&!d){let e=(c.context.selection.state?.[`minor-mode`]??[]).filter(e=>e!==s);await c.changeSelection({axis:`state`,key:`minor-mode`,values:[...e,s]})}if(!d)throw Error(`Loop activity is not active.`);if(t===`start`){let e=await d.launch(String(n.launcherId??``),n.instanceId?{instanceId:String(n.instanceId)}:{});return _(),{message:e?`Loop '${e.instanceId}' started.`:`Loop launch was cancelled.`}}if(t===`stop`){let e=await d.stop(String(n.instanceId??``),String(n.reason??`Stopped through minor_mode.`));if(e&&d.listInstances().length===0){let e=(c.context.selection.state?.[`minor-mode`]??[]).filter(e=>e!==s);await c.changeSelection({axis:`state`,key:`minor-mode`,values:e})}return _(),{message:e?`Loop stopped.`:`Loop instance was not active.`}}throw Error(`Unknown loop mode action: ${t}`)}}).createOwner(void 0),{services:[a([m])],resources:[{when:{state:{"minor-mode":s},attribution:{kind:`minor`,mode:s}},name:`doompi-use-loop`,kind:`skill`,read:()=>r()}],activities:[{when:{state:{"minor-mode":s},attribution:{kind:`minor`,mode:s}},name:`doompi-loop`,start:async e=>{if(d!==void 0)return async()=>void 0;let t={generation:`${e.sessionId}:loop-launchers`,createInstanceId:()=>crypto.randomUUID(),timestamp:()=>new Date().toISOString()},r=n(t),i=r.register({id:`doompi.default`,source:o,label:`Default loop`,description:`Run a prompt in this session on an interval.`,async launch({instanceId:t,signal:n}){let r=await e.client.request({kind:`input`,title:`Loop prompt`,multiline:!0},n),i=typeof r==`string`?r.trim():``;if(!i||n.aborted)return;let a=u(await e.client.request({kind:`input`,title:`Loop interval in seconds`,initialValue:`300`},n),300),o=!1,s=()=>{o||n.aborted||e.session.prompt(i).catch(t=>{l(e,`Loop pass failed: ${t instanceof Error?t.message:String(t)}`,`warning`)})},c=setInterval(s,a*1e3);return c.unref?.(),s(),{instanceId:t,label:`Default loop`,detail:`every ${a}s`,stop(){o=!0,clearInterval(c)}}}});return d=r,f=i,p=r.subscribe(_),_(),async()=>{p?.(),p=void 0,await i.dispose(`Headless loop activity stopped.`),await r.dispose(`Headless loop activity stopped.`),d===r&&(d=void 0),f===i&&(f=void 0),_()}}}],commands:[{when:{state:{"minor-mode":s},attribution:{kind:`minor`,mode:s}},name:t,description:`Start a registered loop.`,async execute(e,t){if(!d)throw Error(`Loop activity is not active.`);let n=d.listLaunchers(),r=await t.client.request({kind:`select`,title:`Choose a loop launcher`,options:n.map(e=>({label:e.label,value:e.id}))}),i=e.trim()||(typeof r==`string`?r:``);if(!i)return;let a=await d.launch(i);_(),await l(t,a?`Loop '${a.instanceId}' started.`:`Loop launch was cancelled.`)}},{when:{state:{"minor-mode":s},attribution:{kind:`minor`,mode:s}},name:e,description:`List and stop active loops.`,async execute(e,t){if(!d)throw Error(`Loop activity is not active.`);let n=d.listInstances();await l(t,n.length===0?`No loops are active.`:JSON.stringify(n,null,2))}}],hooks:[{when:{state:{"minor-mode":s},attribution:{kind:`minor`,mode:s}},event:`session_shutdown`,async handle(){await d?.stopAll(`Headless session shutdown.`)}}],async onDispose(){await f?.dispose(`Headless loop facet disposed.`),await d?.dispose(`Headless loop facet disposed.`)}}}export{d as createSessionState};
2
+ //# sourceMappingURL=serverRuntime.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverRuntime.mjs","names":[],"sources":["../../../src/controllers/serverRuntime.ts"],"sourcesContent":["import { serverMinorModes } from '@agimon-ai/doompi-minor-mode';\nimport { defineMinorMode, type MinorModeOwner, type MinorModeState } from '@agimon-ai/doompi-minor-mode';\n\nimport { LIST_COMMAND_NAME, START_COMMAND_NAME } from '../constants/loop';\nimport type { DoomLoopLaunchersService, LoopLauncherRegistration, StoppableLoop } from '../schemas/loopLaunchers';\nimport { createDoomLoopLaunchersService, type LoopLaunchersDependencies } from '../services/loopLaunchers';\nimport { readLoopResource } from '../services/loopResource';\n\nconst SOURCE = '@agimon-ai/doompi-loop';\nconst MODE_ID = 'loop.active';\nconst DEFAULT_LAUNCHER_ID = 'doompi.default';\nconst DEFAULT_INTERVAL_SECONDS = 300;\nconst MIN_INTERVAL_SECONDS = 30;\nconst MAX_INTERVAL_SECONDS = 3600;\n\nfunction notify(\n context: {\n client: { notify(request: { body: string; level?: 'info' | 'warning' | 'error' }): void | Promise<void> };\n },\n body: string,\n level: 'info' | 'warning' | 'error' = 'info',\n): Promise<void> {\n return Promise.resolve(context.client.notify({ body, level }));\n}\n\nfunction numberInput(value: unknown, fallback: number): number {\n if (typeof value !== 'string' || value.trim() === '') return fallback;\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed < MIN_INTERVAL_SECONDS || parsed > MAX_INTERVAL_SECONDS) {\n throw new Error(`Interval must be between ${MIN_INTERVAL_SECONDS} and ${MAX_INTERVAL_SECONDS} seconds.`);\n }\n return parsed;\n}\n\nimport { type DoomHeadlessExecutionContext, type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport type { DoomServerSessionPlugin } from '@agimon-ai/doompi-core/server-facet';\nexport function createSessionState(host: DoomHeadlessHostService): DoomServerSessionPlugin {\n let launchers: DoomLoopLaunchersService | undefined;\n let defaultRegistration: LoopLauncherRegistration | undefined;\n let unsubscribe: (() => void) | undefined;\n let modeOwner: MinorModeOwner | undefined;\n const modeSelected = (): boolean => (host.context.selection.state?.['minor-mode'] ?? []).includes(MODE_ID);\n const modeState = (): MinorModeState => {\n const launcherCount = launchers?.listLaunchers().length ?? 0;\n const active = (launchers?.listInstances().length ?? 0) > 0;\n const canStart = launcherCount > 0 || !modeSelected();\n return {\n activation: active ? 'active' : 'inactive',\n condition: launchers?.listInstances().some(({ state }) => state !== 'running') ? 'queued' : 'ready',\n ...(active ? { detail: `${launchers?.listInstances().length} active`, color: 'warning' } : {}),\n actions: [\n {\n id: 'start',\n enabled: canStart,\n ...(canStart ? {} : { disabledReason: 'No loop launchers are registered.' }),\n },\n {\n id: 'stop',\n enabled: active,\n ...(active ? {} : { disabledReason: 'No loops are active.' }),\n },\n ],\n };\n };\n const publishMode = (): void => modeOwner?.publish();\n const startActivity = async (execution: typeof host.context): Promise<() => Promise<void>> => {\n if (launchers !== undefined) return async () => undefined;\n const dependencies: LoopLaunchersDependencies = {\n generation: `${execution.sessionId}:loop-launchers`,\n createInstanceId: () => crypto.randomUUID(),\n timestamp: () => new Date().toISOString(),\n };\n const service = createDoomLoopLaunchersService(dependencies);\n const registration = service.register({\n id: DEFAULT_LAUNCHER_ID,\n source: SOURCE,\n label: 'Default loop',\n description: 'Run a prompt in this session on an interval.',\n async launch({ instanceId, signal }): Promise<StoppableLoop | undefined> {\n const promptValue = await execution.client.request(\n { kind: 'input', title: 'Loop prompt', multiline: true },\n signal,\n );\n const prompt = typeof promptValue === 'string' ? promptValue.trim() : '';\n if (!prompt || signal.aborted) return undefined;\n const interval = numberInput(\n await execution.client.request(\n { kind: 'input', title: 'Loop interval in seconds', initialValue: String(DEFAULT_INTERVAL_SECONDS) },\n signal,\n ),\n DEFAULT_INTERVAL_SECONDS,\n );\n let stopped = false;\n const tick = (): void => {\n if (stopped || signal.aborted) return;\n void execution.session.prompt(prompt).catch((error) => {\n void notify(\n execution,\n `Loop pass failed: ${error instanceof Error ? error.message : String(error)}`,\n 'warning',\n );\n });\n };\n const timer = setInterval(tick, interval * 1000);\n timer.unref?.();\n tick();\n return {\n instanceId,\n label: 'Default loop',\n detail: `every ${interval}s`,\n stop() {\n stopped = true;\n clearInterval(timer);\n },\n };\n },\n });\n launchers = service;\n defaultRegistration = registration;\n unsubscribe = service.subscribe(publishMode);\n publishMode();\n return async () => {\n unsubscribe?.();\n unsubscribe = undefined;\n await registration.dispose('Headless loop activity stopped.');\n await service.dispose('Headless loop activity stopped.');\n if (launchers === service) launchers = undefined;\n if (defaultRegistration === registration) defaultRegistration = undefined;\n publishMode();\n };\n };\n modeOwner = defineMinorMode({\n descriptor: {\n source: SOURCE,\n id: MODE_ID,\n label: 'Loop',\n description: 'Session-scoped recurring prompt loops.',\n order: 60,\n actions: [\n {\n id: 'start',\n label: 'Start',\n description: 'Start a loop with a registered launcher.',\n contexts: ['headless'],\n parameters: [\n { name: 'launcherId', label: 'Launcher', kind: 'string', required: true, minLength: 1 },\n { name: 'instanceId', label: 'Instance ID', kind: 'string', required: false, minLength: 1 },\n ],\n },\n {\n id: 'stop',\n label: 'Stop',\n description: 'Stop one active loop instance.',\n contexts: ['headless'],\n parameters: [\n { name: 'instanceId', label: 'Instance ID', kind: 'string', required: true, minLength: 1 },\n { name: 'reason', label: 'Reason', kind: 'string', required: false, minLength: 1 },\n ],\n },\n ],\n },\n state: modeState,\n async handleAction(_runtime, actionId, argumentsValue, { signal }) {\n signal.throwIfAborted();\n if (actionId === 'start' && !launchers) {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== MODE_ID);\n await host.changeSelection({ axis: 'state', key: 'minor-mode', values: [...modes, MODE_ID] });\n }\n if (!launchers) throw new Error('Loop activity is not active.');\n if (actionId === 'start') {\n const instance = await launchers.launch(\n String(argumentsValue.launcherId ?? ''),\n argumentsValue.instanceId ? { instanceId: String(argumentsValue.instanceId) } : {},\n );\n publishMode();\n return { message: instance ? `Loop '${instance.instanceId}' started.` : 'Loop launch was cancelled.' };\n }\n if (actionId === 'stop') {\n const stopped = await launchers.stop(\n String(argumentsValue.instanceId ?? ''),\n String(argumentsValue.reason ?? 'Stopped through minor_mode.'),\n );\n if (stopped && launchers.listInstances().length === 0) {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== MODE_ID);\n await host.changeSelection({ axis: 'state', key: 'minor-mode', values: modes });\n }\n publishMode();\n return { message: stopped ? 'Loop stopped.' : 'Loop instance was not active.' };\n }\n throw new Error(`Unknown loop mode action: ${actionId}`);\n },\n }).createOwner(undefined);\n return {\n services: [serverMinorModes([modeOwner])],\n resources: [\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n name: 'doompi-use-loop',\n kind: 'skill',\n read: () => readLoopResource(),\n },\n ],\n activities: [\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n name: 'doompi-loop',\n start: startActivity,\n },\n ],\n commands: [\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n name: START_COMMAND_NAME,\n description: 'Start a registered loop.',\n async execute(args: string, execution: DoomHeadlessExecutionContext) {\n if (!launchers) throw new Error('Loop activity is not active.');\n const available = launchers.listLaunchers();\n const selected = 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 const launcherId = args.trim() || (typeof selected === 'string' ? selected : '');\n if (!launcherId) return;\n const instance = await launchers.launch(launcherId);\n publishMode();\n await notify(execution, instance ? `Loop '${instance.instanceId}' started.` : 'Loop launch was cancelled.');\n },\n },\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n name: LIST_COMMAND_NAME,\n description: 'List and stop active loops.',\n async execute(_args: string, execution: DoomHeadlessExecutionContext) {\n if (!launchers) throw new Error('Loop activity is not active.');\n const instances = launchers.listInstances();\n await notify(execution, instances.length === 0 ? 'No loops are active.' : JSON.stringify(instances, null, 2));\n },\n },\n ],\n hooks: [\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n event: 'session_shutdown',\n async handle() {\n await launchers?.stopAll('Headless session shutdown.');\n },\n },\n ],\n async onDispose() {\n await defaultRegistration?.dispose('Headless loop facet disposed.');\n await launchers?.dispose('Headless loop facet disposed.');\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const e=(0,require("@agimon-ai/doompi-core/api-contracts").defineApiContract)({version:1,http:[],sockets:[],dynamic:[]});exports.apiContracts=e,exports.default=e;
2
+ //# sourceMappingURL=apiContracts.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiContracts.cjs","names":["defineApiContract"],"sources":["../../../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract } from '@agimon-ai/doompi-core/api-contracts';\n\n/** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */\nexport const apiContracts = defineApiContract({ version: 1, http: [], sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":"AAGA,MAAa,GAAA,gDAAeA,CAAAA,CAAAA,kBAAAA,CAAkB,CAAE,QAAS,EAAG,KAAM,CAAC,EAAG,QAAS,CAAC,EAAG,QAAS,CAAC,CAAE,CAAC"}
@@ -0,0 +1,53 @@
1
+ //#region src/schemas/apiContracts.d.ts
2
+ /** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
3
+ export declare const apiContracts: {
4
+ version: 1;
5
+ protocols?: Record<string, string> | undefined;
6
+ schemas?: Record<string, boolean | object> | undefined;
7
+ http: {
8
+ id: string;
9
+ scope: "global" | "session" | "workspace";
10
+ basePath?: string | undefined;
11
+ path: string;
12
+ method: "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT";
13
+ description: string;
14
+ availability?: string | undefined;
15
+ authentication: "device" | "none" | "owner";
16
+ parameters?: {
17
+ name: string;
18
+ in: "header" | "path" | "query";
19
+ required: boolean;
20
+ schema: boolean | object;
21
+ }[] | undefined;
22
+ body?: {
23
+ contentType: string;
24
+ contentTypes?: string[] | undefined;
25
+ required: boolean;
26
+ schema: boolean | object;
27
+ } | undefined;
28
+ responses: Record<string, {
29
+ description: string;
30
+ contentType?: string | undefined;
31
+ schema?: boolean | object | undefined;
32
+ events?: Record<string, boolean | object> | undefined;
33
+ }>;
34
+ }[];
35
+ sockets: {
36
+ id: string;
37
+ scope: "global" | "session" | "workspace";
38
+ description: string;
39
+ availability?: string | undefined;
40
+ service: string;
41
+ member: string;
42
+ direction: "client-to-server" | "server-to-client";
43
+ kind: "channel" | "method" | "state";
44
+ input: boolean | object;
45
+ output?: boolean | object | undefined;
46
+ errors?: boolean | object | undefined;
47
+ }[];
48
+ dynamic: string[];
49
+ gaps?: string[] | undefined;
50
+ };
51
+ //#endregion
52
+ export { apiContracts as default };
53
+ //# sourceMappingURL=apiContracts.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiContracts.d.cts","names":[],"sources":["../../../src/schemas/apiContracts.ts"],"mappings":";;qBAGa"}
@@ -0,0 +1,53 @@
1
+ //#region src/schemas/apiContracts.d.ts
2
+ /** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
3
+ export declare const apiContracts: {
4
+ version: 1;
5
+ protocols?: Record<string, string> | undefined;
6
+ schemas?: Record<string, boolean | object> | undefined;
7
+ http: {
8
+ id: string;
9
+ scope: "global" | "session" | "workspace";
10
+ basePath?: string | undefined;
11
+ path: string;
12
+ method: "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT";
13
+ description: string;
14
+ availability?: string | undefined;
15
+ authentication: "device" | "none" | "owner";
16
+ parameters?: {
17
+ name: string;
18
+ in: "header" | "path" | "query";
19
+ required: boolean;
20
+ schema: boolean | object;
21
+ }[] | undefined;
22
+ body?: {
23
+ contentType: string;
24
+ contentTypes?: string[] | undefined;
25
+ required: boolean;
26
+ schema: boolean | object;
27
+ } | undefined;
28
+ responses: Record<string, {
29
+ description: string;
30
+ contentType?: string | undefined;
31
+ schema?: boolean | object | undefined;
32
+ events?: Record<string, boolean | object> | undefined;
33
+ }>;
34
+ }[];
35
+ sockets: {
36
+ id: string;
37
+ scope: "global" | "session" | "workspace";
38
+ description: string;
39
+ availability?: string | undefined;
40
+ service: string;
41
+ member: string;
42
+ direction: "client-to-server" | "server-to-client";
43
+ kind: "channel" | "method" | "state";
44
+ input: boolean | object;
45
+ output?: boolean | object | undefined;
46
+ errors?: boolean | object | undefined;
47
+ }[];
48
+ dynamic: string[];
49
+ gaps?: string[] | undefined;
50
+ };
51
+ //#endregion
52
+ export { apiContracts as default };
53
+ //# sourceMappingURL=apiContracts.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiContracts.d.mts","names":[],"sources":["../../../src/schemas/apiContracts.ts"],"mappings":";;qBAGa"}
@@ -0,0 +1,2 @@
1
+ import{defineApiContract as e}from"@agimon-ai/doompi-core/api-contracts";const t=e({version:1,http:[],sockets:[],dynamic:[]});export{t as apiContracts,t as default};
2
+ //# sourceMappingURL=apiContracts.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiContracts.mjs","names":[],"sources":["../../../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract } from '@agimon-ai/doompi-core/api-contracts';\n\n/** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */\nexport const apiContracts = defineApiContract({ version: 1, http: [], sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":"yEAGA,MAAa,EAAe,EAAkB,CAAE,QAAS,EAAG,KAAM,CAAC,EAAG,QAAS,CAAC,EAAG,QAAS,CAAC,CAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ const e=`doom/loop-launchers`;function t(t){return t.get(e)}function n(e){let n=t(e);if(!n)throw Error(`Doom loop launchers are unavailable. Load @agimon-ai/doompi-loop.`);return n}exports.DOOM_LOOP_LAUNCHERS_SERVICE=e,exports.readDoomLoopLaunchers=t,exports.requireDoomLoopLaunchers=n;
2
+ //# sourceMappingURL=loopLaunchers.cjs.map