@agimon-ai/doompi-plan 0.0.1-alpha.6 → 0.0.1-alpha.65

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 (181) hide show
  1. package/README.md +95 -20
  2. package/dist/_virtual/_rolldown/runtime.cjs +1 -1
  3. package/dist/adapters/node/planPointer.cjs +2 -0
  4. package/dist/adapters/node/planPointer.cjs.map +1 -0
  5. package/dist/adapters/node/planPointer.mjs +2 -0
  6. package/dist/adapters/node/planPointer.mjs.map +1 -0
  7. package/dist/adapters/pi/extension.cjs +2 -0
  8. package/dist/adapters/pi/extension.cjs.map +1 -0
  9. package/dist/adapters/pi/extension.d.cts +8 -0
  10. package/dist/adapters/pi/extension.d.cts.map +1 -0
  11. package/dist/adapters/pi/extension.d.mts +8 -0
  12. package/dist/adapters/pi/extension.d.mts.map +1 -0
  13. package/dist/adapters/pi/extension.mjs +2 -0
  14. package/dist/adapters/pi/extension.mjs.map +1 -0
  15. package/dist/adapters/planApi.cjs +2 -0
  16. package/dist/adapters/planApi.cjs.map +1 -0
  17. package/dist/adapters/planApi.d.cts +14 -0
  18. package/dist/adapters/planApi.d.cts.map +1 -0
  19. package/dist/adapters/planApi.d.mts +14 -0
  20. package/dist/adapters/planApi.d.mts.map +1 -0
  21. package/dist/adapters/planApi.mjs +2 -0
  22. package/dist/adapters/planApi.mjs.map +1 -0
  23. package/dist/adapters/telemetry/logSinkTelemetry.cjs +2 -0
  24. package/dist/adapters/telemetry/logSinkTelemetry.cjs.map +1 -0
  25. package/dist/adapters/telemetry/logSinkTelemetry.d.cts +33 -0
  26. package/dist/adapters/telemetry/logSinkTelemetry.d.cts.map +1 -0
  27. package/dist/adapters/telemetry/logSinkTelemetry.d.mts +33 -0
  28. package/dist/adapters/telemetry/logSinkTelemetry.d.mts.map +1 -0
  29. package/dist/adapters/telemetry/logSinkTelemetry.mjs +2 -0
  30. package/dist/adapters/telemetry/logSinkTelemetry.mjs.map +1 -0
  31. package/dist/config.cjs +1 -2
  32. package/dist/config.d.cts +2 -14
  33. package/dist/config.d.mts +2 -14
  34. package/dist/config.mjs +1 -2
  35. package/dist/extensions/pi.cjs +1 -2
  36. package/dist/extensions/pi.d.cts +2 -2
  37. package/dist/extensions/pi.d.mts +2 -2
  38. package/dist/extensions/pi.mjs +1 -2
  39. package/dist/fableFlow.cjs +1 -3
  40. package/dist/fableFlow.d.cts +2 -66
  41. package/dist/fableFlow.d.mts +2 -66
  42. package/dist/fableFlow.mjs +1 -3
  43. package/dist/index.cjs +1 -1
  44. package/dist/index.d.cts +5 -5
  45. package/dist/index.d.mts +5 -5
  46. package/dist/index.mjs +1 -1
  47. package/dist/logSinkTelemetry.cjs +1 -2
  48. package/dist/logSinkTelemetry.d.cts +2 -24
  49. package/dist/logSinkTelemetry.d.mts +2 -24
  50. package/dist/logSinkTelemetry.mjs +1 -2
  51. package/dist/planConfig.cjs +1 -2
  52. package/dist/planConfig.d.cts +3 -0
  53. package/dist/planConfig.d.mts +3 -0
  54. package/dist/planConfig.mjs +1 -2
  55. package/dist/planMode.cjs +1 -6
  56. package/dist/planMode.d.cts +3 -75
  57. package/dist/planMode.d.mts +3 -75
  58. package/dist/planMode.mjs +1 -6
  59. package/dist/prompts.cjs +1 -3
  60. package/dist/prompts.d.cts +2 -24
  61. package/dist/prompts.d.mts +2 -24
  62. package/dist/prompts.mjs +1 -3
  63. package/dist/schemas/plan/config.cjs +2 -0
  64. package/dist/schemas/plan/config.cjs.map +1 -0
  65. package/dist/schemas/plan/config.d.cts +13 -0
  66. package/dist/schemas/plan/config.d.cts.map +1 -0
  67. package/dist/schemas/plan/config.d.mts +13 -0
  68. package/dist/schemas/plan/config.d.mts.map +1 -0
  69. package/dist/schemas/plan/config.mjs +2 -0
  70. package/dist/schemas/plan/config.mjs.map +1 -0
  71. package/dist/schemas/plan/planConfig.cjs +2 -0
  72. package/dist/schemas/plan/planConfig.cjs.map +1 -0
  73. package/dist/schemas/plan/planConfig.d.cts +23 -0
  74. package/dist/schemas/plan/planConfig.d.cts.map +1 -0
  75. package/dist/schemas/plan/planConfig.d.mts +23 -0
  76. package/dist/schemas/plan/planConfig.d.mts.map +1 -0
  77. package/dist/schemas/plan/planConfig.mjs +2 -0
  78. package/dist/schemas/plan/planConfig.mjs.map +1 -0
  79. package/dist/services/fableFlow.cjs +3 -0
  80. package/dist/services/fableFlow.cjs.map +1 -0
  81. package/dist/services/fableFlow.d.cts +67 -0
  82. package/dist/services/fableFlow.d.cts.map +1 -0
  83. package/dist/services/fableFlow.d.mts +67 -0
  84. package/dist/services/fableFlow.d.mts.map +1 -0
  85. package/dist/services/fableFlow.mjs +3 -0
  86. package/dist/services/fableFlow.mjs.map +1 -0
  87. package/dist/services/planMode.cjs +7 -0
  88. package/dist/services/planMode.cjs.map +1 -0
  89. package/dist/services/planMode.d.cts +82 -0
  90. package/dist/services/planMode.d.cts.map +1 -0
  91. package/dist/services/planMode.d.mts +82 -0
  92. package/dist/services/planMode.d.mts.map +1 -0
  93. package/dist/services/planMode.mjs +7 -0
  94. package/dist/services/planMode.mjs.map +1 -0
  95. package/dist/services/prompts.cjs +3 -0
  96. package/dist/services/prompts.cjs.map +1 -0
  97. package/dist/services/prompts.d.cts +23 -0
  98. package/dist/services/prompts.d.cts.map +1 -0
  99. package/dist/services/prompts.d.mts +23 -0
  100. package/dist/services/prompts.d.mts.map +1 -0
  101. package/dist/services/prompts.mjs +3 -0
  102. package/dist/services/prompts.mjs.map +1 -0
  103. package/dist/sessionApi.cjs +1 -0
  104. package/dist/sessionApi.d.cts +2 -0
  105. package/dist/sessionApi.d.mts +2 -0
  106. package/dist/sessionApi.mjs +1 -0
  107. package/dist/types/planApi.cjs +2 -0
  108. package/dist/types/planApi.cjs.map +1 -0
  109. package/dist/types/planApi.d.cts +17 -0
  110. package/dist/types/planApi.d.cts.map +1 -0
  111. package/dist/types/planApi.d.mts +17 -0
  112. package/dist/types/planApi.d.mts.map +1 -0
  113. package/dist/types/planApi.mjs +2 -0
  114. package/dist/types/planApi.mjs.map +1 -0
  115. package/dist/types/planPointer.d.cts +26 -0
  116. package/dist/types/planPointer.d.cts.map +1 -0
  117. package/dist/types/planPointer.d.mts +26 -0
  118. package/dist/types/planPointer.d.mts.map +1 -0
  119. package/dist/types/planSettings.cjs +2 -0
  120. package/dist/types/planSettings.cjs.map +1 -0
  121. package/dist/types/planSettings.d.cts +27 -0
  122. package/dist/types/planSettings.d.cts.map +1 -0
  123. package/dist/types/planSettings.d.mts +27 -0
  124. package/dist/types/planSettings.d.mts.map +1 -0
  125. package/dist/types/planSettings.mjs +2 -0
  126. package/dist/types/planSettings.mjs.map +1 -0
  127. package/llms.txt +9 -0
  128. package/package.json +111 -23
  129. package/src/exports/webClient.ts +1 -0
  130. package/src/prompts/doompi-use-plan/SKILL.md +25 -0
  131. package/src/types/planApi.ts +137 -0
  132. package/src/types/planSettings.ts +78 -0
  133. package/src/web/api/planApi.ts +81 -0
  134. package/src/web/components/PlanActivitySection.tsx +62 -0
  135. package/src/web/components/PlanPanel.tsx +200 -0
  136. package/src/web/components/PlanReviewPrompt.tsx +79 -0
  137. package/src/web/components/PlanToolMessage.tsx +42 -0
  138. package/src/web/index.ts +52 -0
  139. package/src/web/lib/planSettings.ts +30 -0
  140. package/src/web/lib/planToolRender.ts +242 -0
  141. package/src/web/tsconfig.json +23 -0
  142. package/dist/config.cjs.map +0 -1
  143. package/dist/config.d.cts.map +0 -1
  144. package/dist/config.d.mts.map +0 -1
  145. package/dist/config.mjs.map +0 -1
  146. package/dist/extension.cjs +0 -2
  147. package/dist/extension.cjs.map +0 -1
  148. package/dist/extension.d.cts +0 -8
  149. package/dist/extension.d.cts.map +0 -1
  150. package/dist/extension.d.mts +0 -8
  151. package/dist/extension.d.mts.map +0 -1
  152. package/dist/extension.mjs +0 -2
  153. package/dist/extension.mjs.map +0 -1
  154. package/dist/extensions/doom.cjs +0 -2
  155. package/dist/extensions/doom.cjs.map +0 -1
  156. package/dist/extensions/doom.d.cts +0 -8
  157. package/dist/extensions/doom.d.cts.map +0 -1
  158. package/dist/extensions/doom.d.mts +0 -8
  159. package/dist/extensions/doom.d.mts.map +0 -1
  160. package/dist/extensions/doom.mjs +0 -2
  161. package/dist/extensions/doom.mjs.map +0 -1
  162. package/dist/extensions/pi.cjs.map +0 -1
  163. package/dist/extensions/pi.mjs.map +0 -1
  164. package/dist/fableFlow.cjs.map +0 -1
  165. package/dist/fableFlow.d.cts.map +0 -1
  166. package/dist/fableFlow.d.mts.map +0 -1
  167. package/dist/fableFlow.mjs.map +0 -1
  168. package/dist/logSinkTelemetry.cjs.map +0 -1
  169. package/dist/logSinkTelemetry.d.cts.map +0 -1
  170. package/dist/logSinkTelemetry.d.mts.map +0 -1
  171. package/dist/logSinkTelemetry.mjs.map +0 -1
  172. package/dist/planConfig.cjs.map +0 -1
  173. package/dist/planConfig.mjs.map +0 -1
  174. package/dist/planMode.cjs.map +0 -1
  175. package/dist/planMode.d.cts.map +0 -1
  176. package/dist/planMode.d.mts.map +0 -1
  177. package/dist/planMode.mjs.map +0 -1
  178. package/dist/prompts.cjs.map +0 -1
  179. package/dist/prompts.d.cts.map +0 -1
  180. package/dist/prompts.d.mts.map +0 -1
  181. package/dist/prompts.mjs.map +0 -1
package/README.md CHANGED
@@ -1,41 +1,116 @@
1
1
  # @agimon-ai/doompi-plan
2
2
 
3
- Reusable Pi read-only planning mode extension.
3
+ Create and review stored plans in Pi with narrowed tools, explicit completion, and normal, debug, or Fable-assisted flows.
4
4
 
5
- Repository read-only planning, plan persistence, and approval handoff. Plan is a minor mode:
6
- it toggles mid-session 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
+ Plan mode removes `edit` and `write` from the active tool set and directs writes through
8
+ `write_plan`. It does not sandbox Bash, external tools, or the operating system, so treat it as
9
+ tool-level workflow protection rather than a repository permission boundary.
10
+
11
+ > **Alpha:** planning flows and tool contracts may change between releases.
12
+
13
+ ## Requirements
14
+
15
+ - Node.js 22.19.0 or newer
16
+ - Pi 0.85.0
11
17
 
12
18
  ## Install
13
19
 
20
+ The seeded `modes.yaml` selects Plan in `default.packages`. Keep it there or select it through a
21
+ layer; Plan remains inactive until requested. For standalone Pi:
22
+
14
23
  ```bash
15
- npm install @agimon-ai/doompi-plan
24
+ pi install npm:@agimon-ai/doompi-plan
16
25
  ```
17
26
 
18
- ## How it loads
27
+ DoomPi and standalone Pi use the same `@agimon-ai/doompi-plan/extensions/pi` extension.
19
28
 
20
- Name it in a layer in `.doom/modes.yaml`, then add that layer to a major mode:
29
+ ## Start and exit
21
30
 
22
- ```yaml
23
- layers:
24
- plan-mode:
25
- packages: ['@agimon-ai/doompi-plan/extensions/doom']
31
+ | Key | Flavor |
32
+ | --------- | ------------------------------------------------------ |
33
+ | `SPC p e` | Normal planning, and the way out once any flavor is on |
34
+ | `SPC p d` | Debug planning with a bounded evidence packet |
35
+ | `SPC p f` | Fable-assisted drafting followed by Pi verification |
36
+
37
+ `SPC p e` reads `enter` while the mode is off and `exit` while it is on, where exiting restores the
38
+ prior model, thinking level, and tool state.
39
+
40
+ Normal planning expects repository exploration and delegation where available. Debug planning
41
+ separates verified evidence from hypotheses. Fable is an optional Team-provided planning service.
42
+ When Team provides `doom/fable-plan`, Plan treats returned text as untrusted and requires Pi to
43
+ verify and synthesize the final plan. Its child capability ceiling comes from
44
+ `doom/subagent-policy` and is removed when either provider or Plan unloads.
45
+
46
+ A model or tool restoration failure leaves the narrowed Plan state active and reports the failure
47
+ rather than pretending the session was restored.
48
+
49
+ ## Write and complete a plan
50
+
51
+ `write_plan` accepts visible Markdown plan content and writes a unique file under `~/.pi/plans` by
52
+ default. It refuses a plan that is empty or was not presented in visible assistant output, and it
53
+ validates the destination before writing. The plan path and content become visible session state.
54
+
55
+ After a plan exists, `complete_plan` asks whether to exit or continue planning. The user must
56
+ explicitly approve exit. If the selected mode already exposes `ask_user_question`, Plan reuses it;
57
+ it does not activate an omitted feedback layer.
58
+
59
+ In autonomous Voice mode, review choices are narrated, the turn terminates, and the next user
60
+ message carries the decision.
26
61
 
27
- majorMode:
28
- dev: [plan-mode]
62
+ ## Read and edit the plan in the cockpit
63
+
64
+ Once `write_plan` succeeds, a `plan` group appears in the cockpit's activity dock and stays for the
65
+ rest of the session, including after Plan mode is exited: that is when the agent starts
66
+ implementing, which is when the plan is most worth having open. The row opens a temporary tab that
67
+ renders the plan as Markdown, with a `source` view that edits it and saves back to the plan file.
68
+
69
+ The agent reads the plan file at the start of every turn, so a saved edit is what it implements. A
70
+ save carries the hash the reader loaded and is refused if the agent rewrote the plan in the
71
+ meantime, rather than overwriting it.
72
+
73
+ The cockpit reaches the plan through this package's session API, mounted at `/api/plugin/plans`.
74
+ Because a host imports the built entry, a change here needs `pnpm build` and `doompi sync` before a
75
+ running cockpit sees it.
76
+
77
+ ## Configure models and storage
78
+
79
+ Put planning settings in the repository's `.doom/config.yaml` or the global
80
+ `~/.pi/.doom/config.yaml`:
81
+
82
+ ```yaml
83
+ modes:
84
+ planning:
85
+ main:
86
+ model: provider/planning-model
87
+ thinking: high
88
+ subagents:
89
+ model: provider/research-model
90
+ thinking: medium
91
+ plansDirectory: ~/.pi/plans
29
92
  ```
30
93
 
31
- ## Leader
94
+ `main` controls the planning model, `subagents` controls delegated research defaults, and
95
+ `plansDirectory` can be absolute, repository-relative, or under `~`. Planning and delegated model
96
+ calls consume provider quota.
97
+
98
+ ## Public API
99
+
100
+ The root exports planning configuration schemas, prompts, Fable flow helpers, and the Plan mode
101
+ service. Focused exports include `/config`, `/planConfig`, `/planMode`, `/fableFlow`, and `/prompts`.
102
+ `/session-api` is the entry a host mounts for the cockpit's plan tab.
32
103
 
33
- `SPC p p` plans, `SPC p c` cancels, `SPC p d` debugs, `SPC p f` runs the fable flow, once
34
- the extension is loaded.
104
+ ## Development
35
105
 
36
- ## Entry points
106
+ ```bash
107
+ pnpm build
108
+ pnpm typecheck
109
+ pnpm test
110
+ pnpm lint
111
+ ```
37
112
 
38
- 9 subpaths are declared in the `exports` field of `package.json`.
113
+ Maintained by [Agimon](https://agimon.ai/about).
39
114
 
40
115
  ## License
41
116
 
@@ -1 +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,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));exports.__toESM=s;
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,2 @@
1
+ const e=require("../../_virtual/_rolldown/runtime.cjs");let t=require("node:crypto"),n=require("node:fs");n=e.__toESM(n,1);let r=require("node:os");r=e.__toESM(r,1);let i=require("node:path");i=e.__toESM(i,1);const a=[`.pi`,`agent`];function o(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}var s=class{env;homeDirectory;constructor(e={}){this.env=e.env??process.env,this.homeDirectory=e.homeDirectory??r.default.homedir()}directory(){let e=this.env.PI_CODING_AGENT_DIR||i.default.join(this.homeDirectory,...a);return i.default.join(e,`doom-plan`)}pathFor(e){return i.default.join(this.directory(),`${this.hash(e)}.json`)}read(e){let t;try{t=n.default.readFileSync(this.pathFor(e),`utf8`)}catch{return}let r;try{r=JSON.parse(t)}catch{return}if(!o(r))return;let{path:a,title:s,writtenAt:c,planId:l}=r;if(typeof a==`string`&&i.default.isAbsolute(a)&&typeof s==`string`&&typeof c==`string`)return{path:a,title:s,writtenAt:c,...typeof l==`string`?{planId:l}:{}}}write(e,t){n.default.mkdirSync(this.directory(),{recursive:!0,mode:448}),n.default.writeFileSync(this.pathFor(e),JSON.stringify(t),{mode:384})}clear(e){n.default.rmSync(this.pathFor(e),{force:!0})}hash(e){return(0,t.createHash)(`sha256`).update(e).digest(`hex`).slice(0,16)}};exports.NodePlanPointerAdapter=s;
2
+ //# sourceMappingURL=planPointer.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planPointer.cjs","names":["os","path","fs","createHash"],"sources":["../../../src/adapters/node/planPointer.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport type { PlanPointerRecord } from '../../types/planApi.ts';\nimport type { PlanPointerPort } from '../../types/planPointer.ts';\n\n/**\n * Record and read where write_plan left this session's plan file.\n *\n * One technology per adapter. This is where node enters the package; the\n * services that depend on the capability keep importing the port.\n *\n * Pi already gives every session an agent directory, so the records live under\n * it rather than in a second place a reader would have to know about. The\n * posture matches the plan file itself, 0700 on the directory and 0600 on the\n * record: a plan is a private working document, not something to leave\n * world-readable in a shared home.\n */\n\nconst POINTER_DIRECTORY = 'doom-plan';\nconst AGENT_DIRECTORY = ['.pi', 'agent'];\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst PRIVATE_FILE_MODE = 0o600;\n\nexport interface NodePlanPointerOptions {\n env?: NodeJS.ProcessEnv;\n homeDirectory?: string;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport class NodePlanPointerAdapter implements PlanPointerPort {\n private readonly env: NodeJS.ProcessEnv;\n private readonly homeDirectory: string;\n\n constructor(options: NodePlanPointerOptions = {}) {\n this.env = options.env ?? process.env;\n this.homeDirectory = options.homeDirectory ?? os.homedir();\n }\n\n /** Where the records live; exposed so a test can look without guessing. */\n directory(): string {\n const agentDirectory = this.env.PI_CODING_AGENT_DIR || path.join(this.homeDirectory, ...AGENT_DIRECTORY);\n return path.join(agentDirectory, POINTER_DIRECTORY);\n }\n\n /**\n * The record for one session. The id is hashed rather than used as written:\n * it reaches here from a host that may word it however it likes, and a\n * filename is not the place to find that out.\n */\n pathFor(sessionId: string): string {\n return path.join(this.directory(), `${this.hash(sessionId)}.json`);\n }\n\n read(sessionId: string): PlanPointerRecord | undefined {\n let raw: string;\n try {\n raw = fs.readFileSync(this.pathFor(sessionId), 'utf8');\n } catch {\n return undefined;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return undefined;\n }\n if (!isRecord(parsed)) return undefined;\n const { path: planPath, title, writtenAt, planId } = parsed;\n // A record half-written by an interrupted run reads as no plan at all,\n // which is a state the cockpit already handles.\n if (typeof planPath !== 'string' || !path.isAbsolute(planPath)) return undefined;\n if (typeof title !== 'string' || typeof writtenAt !== 'string') return undefined;\n return { path: planPath, title, writtenAt, ...(typeof planId === 'string' ? { planId } : {}) };\n }\n\n write(sessionId: string, record: PlanPointerRecord): void {\n fs.mkdirSync(this.directory(), { recursive: true, mode: PRIVATE_DIRECTORY_MODE });\n fs.writeFileSync(this.pathFor(sessionId), JSON.stringify(record), { mode: PRIVATE_FILE_MODE });\n }\n\n clear(sessionId: string): void {\n fs.rmSync(this.pathFor(sessionId), { force: true });\n }\n\n private hash(value: string): string {\n return createHash('sha256').update(value).digest('hex').slice(0, 16);\n }\n}\n"],"mappings":"iNAoBA,MACM,EAAkB,CAAC,MAAO,OAAO,EASvC,SAAS,EAAS,EAAkD,CAClE,OAAO,OAAO,GAAU,YAAY,GAAkB,CAAC,MAAM,QAAQ,CAAK,CAC5E,CAEA,IAAa,EAAb,KAA+D,CAC7D,IACA,cAEA,YAAY,EAAkC,CAAC,EAAG,CAChD,KAAK,IAAM,EAAQ,KAAO,QAAQ,IAClC,KAAK,cAAgB,EAAQ,eAAiBA,EAAAA,QAAG,QAAQ,CAC3D,CAGA,WAAoB,CAClB,IAAM,EAAiB,KAAK,IAAI,qBAAuBC,EAAAA,QAAK,KAAK,KAAK,cAAe,GAAG,CAAe,EACvG,OAAOA,EAAAA,QAAK,KAAK,EAAgB,WAAiB,CACpD,CAOA,QAAQ,EAA2B,CACjC,OAAOA,EAAAA,QAAK,KAAK,KAAK,UAAU,EAAG,GAAG,KAAK,KAAK,CAAS,EAAE,MAAM,CACnE,CAEA,KAAK,EAAkD,CACrD,IAAI,EACJ,GAAI,CACF,EAAMC,EAAAA,QAAG,aAAa,KAAK,QAAQ,CAAS,EAAG,MAAM,CACvD,MAAQ,CACN,MACF,CACA,IAAI,EACJ,GAAI,CACF,EAAS,KAAK,MAAM,CAAG,CACzB,MAAQ,CACN,MACF,CACA,GAAI,CAAC,EAAS,CAAM,EAAG,OACvB,GAAM,CAAE,KAAM,EAAU,QAAO,YAAW,UAAW,EAGjD,UAAO,GAAa,UAAaD,EAAAA,QAAK,WAAW,CAAQ,GACzD,OAAO,GAAU,UAAY,OAAO,GAAc,SACtD,MAAO,CAAE,KAAM,EAAU,QAAO,YAAW,GAAI,OAAO,GAAW,SAAW,CAAE,QAAO,EAAI,CAAC,CAAG,CAC/F,CAEA,MAAM,EAAmB,EAAiC,CACxD,EAAA,QAAG,UAAU,KAAK,UAAU,EAAG,CAAE,UAAW,GAAM,KAAM,GAAuB,CAAC,EAChF,EAAA,QAAG,cAAc,KAAK,QAAQ,CAAS,EAAG,KAAK,UAAU,CAAM,EAAG,CAAE,KAAM,GAAkB,CAAC,CAC/F,CAEA,MAAM,EAAyB,CAC7B,EAAA,QAAG,OAAO,KAAK,QAAQ,CAAS,EAAG,CAAE,MAAO,EAAK,CAAC,CACpD,CAEA,KAAa,EAAuB,CAClC,OAAA,EAAOE,EAAAA,WAAAA,CAAW,QAAQ,CAAC,CAAC,OAAO,CAAK,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,EAAG,EAAE,CACrE,CACF"}
@@ -0,0 +1,2 @@
1
+ import{createHash as e}from"node:crypto";import t from"node:fs";import n from"node:os";import r from"node:path";const i=[`.pi`,`agent`];function a(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}var o=class{env;homeDirectory;constructor(e={}){this.env=e.env??process.env,this.homeDirectory=e.homeDirectory??n.homedir()}directory(){let e=this.env.PI_CODING_AGENT_DIR||r.join(this.homeDirectory,...i);return r.join(e,`doom-plan`)}pathFor(e){return r.join(this.directory(),`${this.hash(e)}.json`)}read(e){let n;try{n=t.readFileSync(this.pathFor(e),`utf8`)}catch{return}let i;try{i=JSON.parse(n)}catch{return}if(!a(i))return;let{path:o,title:s,writtenAt:c,planId:l}=i;if(typeof o==`string`&&r.isAbsolute(o)&&typeof s==`string`&&typeof c==`string`)return{path:o,title:s,writtenAt:c,...typeof l==`string`?{planId:l}:{}}}write(e,n){t.mkdirSync(this.directory(),{recursive:!0,mode:448}),t.writeFileSync(this.pathFor(e),JSON.stringify(n),{mode:384})}clear(e){t.rmSync(this.pathFor(e),{force:!0})}hash(t){return e(`sha256`).update(t).digest(`hex`).slice(0,16)}};export{o as NodePlanPointerAdapter};
2
+ //# sourceMappingURL=planPointer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planPointer.mjs","names":[],"sources":["../../../src/adapters/node/planPointer.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport type { PlanPointerRecord } from '../../types/planApi.ts';\nimport type { PlanPointerPort } from '../../types/planPointer.ts';\n\n/**\n * Record and read where write_plan left this session's plan file.\n *\n * One technology per adapter. This is where node enters the package; the\n * services that depend on the capability keep importing the port.\n *\n * Pi already gives every session an agent directory, so the records live under\n * it rather than in a second place a reader would have to know about. The\n * posture matches the plan file itself, 0700 on the directory and 0600 on the\n * record: a plan is a private working document, not something to leave\n * world-readable in a shared home.\n */\n\nconst POINTER_DIRECTORY = 'doom-plan';\nconst AGENT_DIRECTORY = ['.pi', 'agent'];\nconst PRIVATE_DIRECTORY_MODE = 0o700;\nconst PRIVATE_FILE_MODE = 0o600;\n\nexport interface NodePlanPointerOptions {\n env?: NodeJS.ProcessEnv;\n homeDirectory?: string;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport class NodePlanPointerAdapter implements PlanPointerPort {\n private readonly env: NodeJS.ProcessEnv;\n private readonly homeDirectory: string;\n\n constructor(options: NodePlanPointerOptions = {}) {\n this.env = options.env ?? process.env;\n this.homeDirectory = options.homeDirectory ?? os.homedir();\n }\n\n /** Where the records live; exposed so a test can look without guessing. */\n directory(): string {\n const agentDirectory = this.env.PI_CODING_AGENT_DIR || path.join(this.homeDirectory, ...AGENT_DIRECTORY);\n return path.join(agentDirectory, POINTER_DIRECTORY);\n }\n\n /**\n * The record for one session. The id is hashed rather than used as written:\n * it reaches here from a host that may word it however it likes, and a\n * filename is not the place to find that out.\n */\n pathFor(sessionId: string): string {\n return path.join(this.directory(), `${this.hash(sessionId)}.json`);\n }\n\n read(sessionId: string): PlanPointerRecord | undefined {\n let raw: string;\n try {\n raw = fs.readFileSync(this.pathFor(sessionId), 'utf8');\n } catch {\n return undefined;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return undefined;\n }\n if (!isRecord(parsed)) return undefined;\n const { path: planPath, title, writtenAt, planId } = parsed;\n // A record half-written by an interrupted run reads as no plan at all,\n // which is a state the cockpit already handles.\n if (typeof planPath !== 'string' || !path.isAbsolute(planPath)) return undefined;\n if (typeof title !== 'string' || typeof writtenAt !== 'string') return undefined;\n return { path: planPath, title, writtenAt, ...(typeof planId === 'string' ? { planId } : {}) };\n }\n\n write(sessionId: string, record: PlanPointerRecord): void {\n fs.mkdirSync(this.directory(), { recursive: true, mode: PRIVATE_DIRECTORY_MODE });\n fs.writeFileSync(this.pathFor(sessionId), JSON.stringify(record), { mode: PRIVATE_FILE_MODE });\n }\n\n clear(sessionId: string): void {\n fs.rmSync(this.pathFor(sessionId), { force: true });\n }\n\n private hash(value: string): string {\n return createHash('sha256').update(value).digest('hex').slice(0, 16);\n }\n}\n"],"mappings":"gHAoBA,MACM,EAAkB,CAAC,MAAO,OAAO,EASvC,SAAS,EAAS,EAAkD,CAClE,OAAO,OAAO,GAAU,YAAY,GAAkB,CAAC,MAAM,QAAQ,CAAK,CAC5E,CAEA,IAAa,EAAb,KAA+D,CAC7D,IACA,cAEA,YAAY,EAAkC,CAAC,EAAG,CAChD,KAAK,IAAM,EAAQ,KAAO,QAAQ,IAClC,KAAK,cAAgB,EAAQ,eAAiB,EAAG,QAAQ,CAC3D,CAGA,WAAoB,CAClB,IAAM,EAAiB,KAAK,IAAI,qBAAuB,EAAK,KAAK,KAAK,cAAe,GAAG,CAAe,EACvG,OAAO,EAAK,KAAK,EAAgB,WAAiB,CACpD,CAOA,QAAQ,EAA2B,CACjC,OAAO,EAAK,KAAK,KAAK,UAAU,EAAG,GAAG,KAAK,KAAK,CAAS,EAAE,MAAM,CACnE,CAEA,KAAK,EAAkD,CACrD,IAAI,EACJ,GAAI,CACF,EAAM,EAAG,aAAa,KAAK,QAAQ,CAAS,EAAG,MAAM,CACvD,MAAQ,CACN,MACF,CACA,IAAI,EACJ,GAAI,CACF,EAAS,KAAK,MAAM,CAAG,CACzB,MAAQ,CACN,MACF,CACA,GAAI,CAAC,EAAS,CAAM,EAAG,OACvB,GAAM,CAAE,KAAM,EAAU,QAAO,YAAW,UAAW,EAGjD,UAAO,GAAa,UAAa,EAAK,WAAW,CAAQ,GACzD,OAAO,GAAU,UAAY,OAAO,GAAc,SACtD,MAAO,CAAE,KAAM,EAAU,QAAO,YAAW,GAAI,OAAO,GAAW,SAAW,CAAE,QAAO,EAAI,CAAC,CAAG,CAC/F,CAEA,MAAM,EAAmB,EAAiC,CACxD,EAAG,UAAU,KAAK,UAAU,EAAG,CAAE,UAAW,GAAM,KAAM,GAAuB,CAAC,EAChF,EAAG,cAAc,KAAK,QAAQ,CAAS,EAAG,KAAK,UAAU,CAAM,EAAG,CAAE,KAAM,GAAkB,CAAC,CAC/F,CAEA,MAAM,EAAyB,CAC7B,EAAG,OAAO,KAAK,QAAQ,CAAS,EAAG,CAAE,MAAO,EAAK,CAAC,CACpD,CAEA,KAAa,EAAuB,CAClC,OAAO,EAAW,QAAQ,CAAC,CAAC,OAAO,CAAK,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,EAAG,EAAE,CACrE,CACF"}
@@ -0,0 +1,2 @@
1
+ const e=require("../../services/planMode.cjs");let t=require("@agimon-ai/doompi-extension-contracts/cordis-host"),n=require("@agimon-ai/doompi-extension-contracts/help");const r=`@agimon-ai/doompi-plan`;function i(t,n){e.planModeExtension(t,n)}async function a(e){let n=await(0,t.connectDoomCordisHost)(e,r),i=n.root.plugin(o,{pi:e});try{await i}catch(e){try{await i.dispose()}finally{await n.dispose()}throw e}let a;e.on(`session_shutdown`,()=>a??=(async()=>{try{await i.dispose()}finally{await n.dispose()}})())}function o(e,t){e.inject([n.DOOM_HELP_SERVICE],e=>{let t=(0,n.requireDoomHelpService)(e).register({source:r,moduleUrl:require("url").pathToFileURL(__filename).href,skills:[{name:`doompi-use-plan`,description:`Use Doom Pi Plan to draft reviewable normal, debug, or Fable-assisted plans, persist them, and exit safely.`}]});return()=>t.dispose()}),i(e,t.pi)}exports.activatePlanExtension=a,exports.default=a,exports.installPlanRuntime=i;
2
+ //# sourceMappingURL=extension.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.cjs","names":["connectDoomCordisHost","DOOM_HELP_SERVICE","requireDoomHelpService"],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { connectDoomCordisHost } from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport { DOOM_HELP_SERVICE, requireDoomHelpService } from '@agimon-ai/doompi-extension-contracts/help';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { planModeExtension } from '../../services/planMode.ts';\n\nconst PACKAGE_SOURCE = '@agimon-ai/doompi-plan';\n\n/** Install Plan state and external resources into its host-owned Cordis plugin fiber. */\nexport function installPlanRuntime(cordis: Context, pi: ExtensionAPI): void {\n planModeExtension(cordis, pi);\n}\n\n/** The package's single standard Pi factory, including all optional typed Doom integrations. */\nexport async function activatePlanExtension(pi: ExtensionAPI): Promise<void> {\n const connection = await connectDoomCordisHost(pi, PACKAGE_SOURCE);\n const fiber = connection.root.plugin(planPlugin, { pi });\n try {\n await fiber;\n } catch (error) {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\ninterface PlanPluginConfig {\n readonly pi: ExtensionAPI;\n}\n\nfunction planPlugin(cordis: Context, config: PlanPluginConfig): void {\n cordis.inject([DOOM_HELP_SERVICE], (helpContext) => {\n const contribution = requireDoomHelpService(helpContext).register({\n source: PACKAGE_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-use-plan',\n description:\n 'Use Doom Pi Plan to draft reviewable normal, debug, or Fable-assisted plans, persist them, and exit safely.',\n },\n ],\n });\n return () => contribution.dispose();\n });\n installPlanRuntime(cordis, config.pi);\n}\n\nexport default activatePlanExtension;\n"],"mappings":"0KAMA,MAAM,EAAiB,yBAGvB,SAAgB,EAAmB,EAAiB,EAAwB,CAC1E,EAAA,kBAAkB,EAAQ,CAAE,CAC9B,CAGA,eAAsB,EAAsB,EAAiC,CAC3E,IAAM,EAAa,MAAA,EAAMA,EAAAA,sBAAAA,CAAsB,EAAI,CAAc,EAC3D,EAAQ,EAAW,KAAK,OAAO,EAAY,CAAE,IAAG,CAAC,EACvD,GAAI,CACF,MAAM,CACR,OAAS,EAAO,CACd,GAAI,CACF,MAAM,EAAM,QAAQ,CACtB,QAAU,CACR,MAAM,EAAW,QAAQ,CAC3B,CACA,MAAM,CACR,CACA,IAAI,EACJ,EAAG,GACD,uBAEG,KAAc,SAAY,CACzB,GAAI,CACF,MAAM,EAAM,QAAQ,CACtB,QAAU,CACR,MAAM,EAAW,QAAQ,CAC3B,CACF,EAAA,CAAG,CACP,CACF,CAMA,SAAS,EAAW,EAAiB,EAAgC,CACnE,EAAO,OAAO,CAACC,EAAAA,iBAAiB,EAAI,GAAgB,CAClD,IAAM,GAAA,EAAeC,EAAAA,uBAAAA,CAAuB,CAAW,CAAC,CAAC,SAAS,CAChE,OAAQ,EACR,UAAA,QAAA,KAAA,CAAA,CAAA,cAAA,UAAA,CAAA,CAAA,KACA,OAAQ,CACN,CACE,KAAM,kBACN,YACE,6GACJ,CACF,CACF,CAAC,EACD,UAAa,EAAa,QAAQ,CACpC,CAAC,EACD,EAAmB,EAAQ,EAAO,EAAE,CACtC"}
@@ -0,0 +1,8 @@
1
+ import { Context } from "@deepseek-ai/cordis";
2
+ import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
+ //#region src/adapters/pi/extension.d.ts
4
+ /** The package's single standard Pi factory, including all optional typed Doom integrations. */
5
+ export declare function activatePlanExtension(pi: ExtensionAPI): Promise<void>;
6
+ //#endregion
7
+ export { activatePlanExtension as default };
8
+ //# sourceMappingURL=extension.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.d.cts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;wBAcsB,sBAAsB,IAAI,eAAe"}
@@ -0,0 +1,8 @@
1
+ import { Context } from "@deepseek-ai/cordis";
2
+ import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
+ //#region src/adapters/pi/extension.d.ts
4
+ /** The package's single standard Pi factory, including all optional typed Doom integrations. */
5
+ export declare function activatePlanExtension(pi: ExtensionAPI): Promise<void>;
6
+ //#endregion
7
+ export { activatePlanExtension as default };
8
+ //# sourceMappingURL=extension.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.d.mts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;wBAcsB,sBAAsB,IAAI,eAAe"}
@@ -0,0 +1,2 @@
1
+ import{planModeExtension as e}from"../../services/planMode.mjs";import{connectDoomCordisHost as t}from"@agimon-ai/doompi-extension-contracts/cordis-host";import{DOOM_HELP_SERVICE as n,requireDoomHelpService as r}from"@agimon-ai/doompi-extension-contracts/help";const i=`@agimon-ai/doompi-plan`;function a(t,n){e(t,n)}async function o(e){let n=await t(e,i),r=n.root.plugin(s,{pi:e});try{await r}catch(e){try{await r.dispose()}finally{await n.dispose()}throw e}let a;e.on(`session_shutdown`,()=>a??=(async()=>{try{await r.dispose()}finally{await n.dispose()}})())}function s(e,t){e.inject([n],e=>{let t=r(e).register({source:i,moduleUrl:import.meta.url,skills:[{name:`doompi-use-plan`,description:`Use Doom Pi Plan to draft reviewable normal, debug, or Fable-assisted plans, persist them, and exit safely.`}]});return()=>t.dispose()}),a(e,t.pi)}export{o as activatePlanExtension,o as default,a as installPlanRuntime};
2
+ //# sourceMappingURL=extension.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.mjs","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { connectDoomCordisHost } from '@agimon-ai/doompi-extension-contracts/cordis-host';\nimport { DOOM_HELP_SERVICE, requireDoomHelpService } from '@agimon-ai/doompi-extension-contracts/help';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { planModeExtension } from '../../services/planMode.ts';\n\nconst PACKAGE_SOURCE = '@agimon-ai/doompi-plan';\n\n/** Install Plan state and external resources into its host-owned Cordis plugin fiber. */\nexport function installPlanRuntime(cordis: Context, pi: ExtensionAPI): void {\n planModeExtension(cordis, pi);\n}\n\n/** The package's single standard Pi factory, including all optional typed Doom integrations. */\nexport async function activatePlanExtension(pi: ExtensionAPI): Promise<void> {\n const connection = await connectDoomCordisHost(pi, PACKAGE_SOURCE);\n const fiber = connection.root.plugin(planPlugin, { pi });\n try {\n await fiber;\n } catch (error) {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n throw error;\n }\n let disposal: Promise<void> | undefined;\n pi.on(\n 'session_shutdown',\n () =>\n (disposal ??= (async () => {\n try {\n await fiber.dispose();\n } finally {\n await connection.dispose();\n }\n })()),\n );\n}\n\ninterface PlanPluginConfig {\n readonly pi: ExtensionAPI;\n}\n\nfunction planPlugin(cordis: Context, config: PlanPluginConfig): void {\n cordis.inject([DOOM_HELP_SERVICE], (helpContext) => {\n const contribution = requireDoomHelpService(helpContext).register({\n source: PACKAGE_SOURCE,\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-use-plan',\n description:\n 'Use Doom Pi Plan to draft reviewable normal, debug, or Fable-assisted plans, persist them, and exit safely.',\n },\n ],\n });\n return () => contribution.dispose();\n });\n installPlanRuntime(cordis, config.pi);\n}\n\nexport default activatePlanExtension;\n"],"mappings":"qQAMA,MAAM,EAAiB,yBAGvB,SAAgB,EAAmB,EAAiB,EAAwB,CAC1E,EAAkB,EAAQ,CAAE,CAC9B,CAGA,eAAsB,EAAsB,EAAiC,CAC3E,IAAM,EAAa,MAAM,EAAsB,EAAI,CAAc,EAC3D,EAAQ,EAAW,KAAK,OAAO,EAAY,CAAE,IAAG,CAAC,EACvD,GAAI,CACF,MAAM,CACR,OAAS,EAAO,CACd,GAAI,CACF,MAAM,EAAM,QAAQ,CACtB,QAAU,CACR,MAAM,EAAW,QAAQ,CAC3B,CACA,MAAM,CACR,CACA,IAAI,EACJ,EAAG,GACD,uBAEG,KAAc,SAAY,CACzB,GAAI,CACF,MAAM,EAAM,QAAQ,CACtB,QAAU,CACR,MAAM,EAAW,QAAQ,CAC3B,CACF,EAAA,CAAG,CACP,CACF,CAMA,SAAS,EAAW,EAAiB,EAAgC,CACnE,EAAO,OAAO,CAAC,CAAiB,EAAI,GAAgB,CAClD,IAAM,EAAe,EAAuB,CAAW,CAAC,CAAC,SAAS,CAChE,OAAQ,EACR,UAAW,YAAY,IACvB,OAAQ,CACN,CACE,KAAM,kBACN,YACE,6GACJ,CACF,CACF,CAAC,EACD,UAAa,EAAa,QAAQ,CACpC,CAAC,EACD,EAAmB,EAAQ,EAAO,EAAE,CACtC"}
@@ -0,0 +1,2 @@
1
+ const e=require("../_virtual/_rolldown/runtime.cjs"),t=require("./node/planPointer.cjs"),n=require("../types/planApi.cjs");let r=require("node:crypto"),i=require("node:fs/promises");i=e.__toESM(i,1);let a=require("hono");const o=1048576,s=`This session has not written a plan yet.`;function c(e){return(0,r.createHash)(`sha256`).update(e,`utf8`).digest(`hex`)}async function l(e){let t;try{t=await i.default.readFile(e)}catch{return{content:``,hash:``,unavailable:!0,reason:`the plan file no longer exists`}}if(t.byteLength>1048576)return{content:``,hash:``,unavailable:!0,reason:`the plan is larger than ${o} bytes`};let n=t.toString(`utf8`);return{content:n,hash:c(n),unavailable:!1}}function u(e={}){let r=new a.Hono,o=e.pointers??new t.NodePlanPointerAdapter,u=()=>e.sessionId===void 0?void 0:o.read(e.sessionId);return r.get(n.currentPath(),async e=>{let t=u();if(t===void 0)return e.json({error:s},404);let n={path:t.path,title:t.title,writtenAt:t.writtenAt,...t.planId===void 0?{}:{planId:t.planId},...await l(t.path)};return e.json(n)}),r.put(n.contentPath(),async e=>{let t;try{t=await e.req.json()}catch{return e.json({error:`The save body is not JSON.`},400)}if(typeof t.content!=`string`||typeof t.expectedHash!=`string`)return e.json({error:`A save carries the content to write and the hash it was read at.`},400);let n=u();if(n===void 0)return e.json({error:s},404);let r=await l(n.path);if(r.unavailable)return e.json({error:r.reason??s},409);if(r.hash!==t.expectedHash)return e.json({error:`The plan changed since it was opened.`,hash:r.hash},409);let a=await i.default.lstat(n.path);return!a.isFile()||a.nlink!==1?e.json({error:`The plan file is no longer a regular file, so it was not written.`},409):(await i.default.writeFile(n.path,t.content,{encoding:`utf8`,mode:384}),e.json({hash:c(t.content)}))}),r}const d={basePath:n.API_BASE_PATH,start(e){let t=u(e.sessionId===void 0?{}:{sessionId:e.sessionId});return{fetch:e=>t.fetch(e),close:()=>void 0}}};exports.MAX_PLAN_BYTES=o,exports.api=d,exports.createPlanApi=u;
2
+ //# sourceMappingURL=planApi.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planApi.cjs","names":["createHash","fs","Hono","NodePlanPointerAdapter","currentPath","contentPath","API_BASE_PATH"],"sources":["../../src/adapters/planApi.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport fs from 'node:fs/promises';\nimport type { DoomApi, DoomApiContext, DoomApiHandler } from '@agimon-ai/doompi-extension-contracts/package-api';\nimport { Hono } from 'hono';\nimport {\n API_BASE_PATH,\n contentPath,\n currentPath,\n type PlanDetailView,\n type PlanSaveRequest,\n type PlanSaveView,\n} from '../types/planApi.ts';\nimport type { PlanPointerPort } from '../types/planPointer.ts';\nimport { NodePlanPointerAdapter } from './node/planPointer.ts';\n\n/**\n * This package's HTTP surface: the session's current plan, and the manual save.\n *\n * Routes are relative to the mount its host gives it, so nothing here repeats\n * where it was mounted. The host is one session's own server, which is what\n * makes the session id available without the page supplying it.\n *\n * Neither route takes a path. A session has exactly one current plan, and the\n * file both routes act on is the one the pointer names, so a page can address\n * the plan and nothing else; there is no traversal question to answer because\n * there is no path to traverse.\n *\n * The save refuses unless the reader proves they were looking at the content\n * that is still on disk. The agent may rewrite the plan while a tab is open,\n * and silently discarding whichever side finished second is the one outcome\n * worth ruling out.\n */\n\n/** Past this, the plan is reported rather than carried. */\nexport const MAX_PLAN_BYTES = 1024 * 1024;\n\nconst NO_PLAN = 'This session has not written a plan yet.';\nconst STALE_SAVE = 'The plan changed since it was opened.';\nconst NOT_A_FILE = 'The plan file is no longer a regular file, so it was not written.';\n\nexport interface PlanApiOptions {\n /** The session these routes answer for; absent when the host is the hub. */\n sessionId?: string;\n pointers?: PlanPointerPort;\n}\n\nfunction hashOf(content: string): string {\n return createHash('sha256').update(content, 'utf8').digest('hex');\n}\n\n/** Reads the plan as the source view will show it, or says why it cannot. */\nasync function readPlan(\n planPath: string,\n): Promise<Pick<PlanDetailView, 'content' | 'hash' | 'unavailable' | 'reason'>> {\n let raw: Buffer;\n try {\n raw = await fs.readFile(planPath);\n } catch {\n return { content: '', hash: '', unavailable: true, reason: 'the plan file no longer exists' };\n }\n if (raw.byteLength > MAX_PLAN_BYTES) {\n return { content: '', hash: '', unavailable: true, reason: `the plan is larger than ${MAX_PLAN_BYTES} bytes` };\n }\n const content = raw.toString('utf8');\n return { content, hash: hashOf(content), unavailable: false };\n}\n\nexport function createPlanApi(options: PlanApiOptions = {}): Hono {\n const app = new Hono();\n const pointers = options.pointers ?? new NodePlanPointerAdapter();\n const pointerFor = (): ReturnType<PlanPointerPort['read']> =>\n options.sessionId === undefined ? undefined : pointers.read(options.sessionId);\n\n app.get(currentPath(), async (context) => {\n const pointer = pointerFor();\n if (pointer === undefined) return context.json({ error: NO_PLAN }, 404);\n const view: PlanDetailView = {\n path: pointer.path,\n title: pointer.title,\n writtenAt: pointer.writtenAt,\n ...(pointer.planId === undefined ? {} : { planId: pointer.planId }),\n ...(await readPlan(pointer.path)),\n };\n return context.json(view);\n });\n\n app.put(contentPath(), async (context) => {\n let request: PlanSaveRequest;\n try {\n request = (await context.req.json()) as PlanSaveRequest;\n } catch {\n return context.json({ error: 'The save body is not JSON.' }, 400);\n }\n if (typeof request.content !== 'string' || typeof request.expectedHash !== 'string') {\n return context.json({ error: 'A save carries the content to write and the hash it was read at.' }, 400);\n }\n const pointer = pointerFor();\n if (pointer === undefined) return context.json({ error: NO_PLAN }, 404);\n\n const current = await readPlan(pointer.path);\n if (current.unavailable) return context.json({ error: current.reason ?? NO_PLAN }, 409);\n if (current.hash !== request.expectedHash) {\n return context.json({ error: STALE_SAVE, hash: current.hash }, 409);\n }\n // The same guard write_plan applies before it writes: a plan whose\n // destination has become a symlink or gained a second name is not written\n // through, whatever the pointer still says.\n const stats = await fs.lstat(pointer.path);\n if (!stats.isFile() || stats.nlink !== 1) return context.json({ error: NOT_A_FILE }, 409);\n\n await fs.writeFile(pointer.path, request.content, { encoding: 'utf8', mode: 0o600 });\n return context.json({ hash: hashOf(request.content) } satisfies PlanSaveView);\n });\n\n return app;\n}\n\n/** The named export a host imports from this package's built entry. */\nexport const api: DoomApi = {\n basePath: API_BASE_PATH,\n start(context: DoomApiContext): DoomApiHandler {\n const app = createPlanApi(context.sessionId === undefined ? {} : { sessionId: context.sessionId });\n return {\n fetch: (request) => app.fetch(request),\n // Nothing outlives a request here; an API that starts a watch or a timer\n // tears it down in this callback.\n close: () => undefined,\n };\n },\n};\n"],"mappings":"6NAkCA,MAAa,EAAiB,QAExB,EAAU,2CAUhB,SAAS,EAAO,EAAyB,CACvC,OAAA,EAAOA,EAAAA,WAAAA,CAAW,QAAQ,CAAC,CAAC,OAAO,EAAS,MAAM,CAAC,CAAC,OAAO,KAAK,CAClE,CAGA,eAAe,EACb,EAC8E,CAC9E,IAAI,EACJ,GAAI,CACF,EAAM,MAAMC,EAAAA,QAAG,SAAS,CAAQ,CAClC,MAAQ,CACN,MAAO,CAAE,QAAS,GAAI,KAAM,GAAI,YAAa,GAAM,OAAQ,gCAAiC,CAC9F,CACA,GAAI,EAAI,WAAA,QACN,MAAO,CAAE,QAAS,GAAI,KAAM,GAAI,YAAa,GAAM,OAAQ,2BAA2B,EAAe,OAAQ,EAE/G,IAAM,EAAU,EAAI,SAAS,MAAM,EACnC,MAAO,CAAE,UAAS,KAAM,EAAO,CAAO,EAAG,YAAa,EAAM,CAC9D,CAEA,SAAgB,EAAc,EAA0B,CAAC,EAAS,CAChE,IAAM,EAAM,IAAIC,EAAAA,KACV,EAAW,EAAQ,UAAY,IAAIC,EAAAA,uBACnC,MACJ,EAAQ,YAAc,IAAA,GAAY,IAAA,GAAY,EAAS,KAAK,EAAQ,SAAS,EA2C/E,OAzCA,EAAI,IAAIC,EAAAA,YAAY,EAAG,KAAO,IAAY,CACxC,IAAM,EAAU,EAAW,EAC3B,GAAI,IAAY,IAAA,GAAW,OAAO,EAAQ,KAAK,CAAE,MAAO,CAAQ,EAAG,GAAG,EACtE,IAAM,EAAuB,CAC3B,KAAM,EAAQ,KACd,MAAO,EAAQ,MACf,UAAW,EAAQ,UACnB,GAAI,EAAQ,SAAW,IAAA,GAAY,CAAC,EAAI,CAAE,OAAQ,EAAQ,MAAO,EACjE,GAAI,MAAM,EAAS,EAAQ,IAAI,CACjC,EACA,OAAO,EAAQ,KAAK,CAAI,CAC1B,CAAC,EAED,EAAI,IAAIC,EAAAA,YAAY,EAAG,KAAO,IAAY,CACxC,IAAI,EACJ,GAAI,CACF,EAAW,MAAM,EAAQ,IAAI,KAAK,CACpC,MAAQ,CACN,OAAO,EAAQ,KAAK,CAAE,MAAO,4BAA6B,EAAG,GAAG,CAClE,CACA,GAAI,OAAO,EAAQ,SAAY,UAAY,OAAO,EAAQ,cAAiB,SACzE,OAAO,EAAQ,KAAK,CAAE,MAAO,kEAAmE,EAAG,GAAG,EAExG,IAAM,EAAU,EAAW,EAC3B,GAAI,IAAY,IAAA,GAAW,OAAO,EAAQ,KAAK,CAAE,MAAO,CAAQ,EAAG,GAAG,EAEtE,IAAM,EAAU,MAAM,EAAS,EAAQ,IAAI,EAC3C,GAAI,EAAQ,YAAa,OAAO,EAAQ,KAAK,CAAE,MAAO,EAAQ,QAAU,CAAQ,EAAG,GAAG,EACtF,GAAI,EAAQ,OAAS,EAAQ,aAC3B,OAAO,EAAQ,KAAK,CAAE,MAAO,wCAAY,KAAM,EAAQ,IAAK,EAAG,GAAG,EAKpE,IAAM,EAAQ,MAAMJ,EAAAA,QAAG,MAAM,EAAQ,IAAI,EAIzC,MAHI,CAAC,EAAM,OAAO,GAAK,EAAM,QAAU,EAAU,EAAQ,KAAK,CAAE,MAAO,mEAAW,EAAG,GAAG,GAExF,MAAMA,EAAAA,QAAG,UAAU,EAAQ,KAAM,EAAQ,QAAS,CAAE,SAAU,OAAQ,KAAM,GAAM,CAAC,EAC5E,EAAQ,KAAK,CAAE,KAAM,EAAO,EAAQ,OAAO,CAAE,CAAwB,EAC9E,CAAC,EAEM,CACT,CAGA,MAAa,EAAe,CAC1B,SAAUK,EAAAA,cACV,MAAM,EAAyC,CAC7C,IAAM,EAAM,EAAc,EAAQ,YAAc,IAAA,GAAY,CAAC,EAAI,CAAE,UAAW,EAAQ,SAAU,CAAC,EACjG,MAAO,CACL,MAAQ,GAAY,EAAI,MAAM,CAAO,EAGrC,UAAa,IAAA,EACf,CACF,CACF"}
@@ -0,0 +1,14 @@
1
+ import { PlanPointerPort } from "../types/planPointer.cjs";
2
+ import { DoomApi } from "@agimon-ai/doompi-extension-contracts/package-api";
3
+ import { Hono } from "hono";
4
+ //#region src/adapters/planApi.d.ts
5
+ export interface PlanApiOptions {
6
+ /** The session these routes answer for; absent when the host is the hub. */
7
+ sessionId?: string;
8
+ pointers?: PlanPointerPort;
9
+ }
10
+ export declare function createPlanApi(options?: PlanApiOptions): Hono;
11
+ /** The named export a host imports from this package's built entry. */
12
+ export declare const api: DoomApi;
13
+ //#endregion
14
+ //# sourceMappingURL=planApi.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planApi.d.cts","names":[],"sources":["../../src/adapters/planApi.ts"],"mappings":";;;;iBAwCiB;;EAEf;EACA,WAAW;;wBAwBG,cAAc,UAAS,iBAAsB;;qBAmDhD,KAAK"}
@@ -0,0 +1,14 @@
1
+ import { PlanPointerPort } from "../types/planPointer.mjs";
2
+ import { Hono } from "hono";
3
+ import { DoomApi } from "@agimon-ai/doompi-extension-contracts/package-api";
4
+ //#region src/adapters/planApi.d.ts
5
+ export interface PlanApiOptions {
6
+ /** The session these routes answer for; absent when the host is the hub. */
7
+ sessionId?: string;
8
+ pointers?: PlanPointerPort;
9
+ }
10
+ export declare function createPlanApi(options?: PlanApiOptions): Hono;
11
+ /** The named export a host imports from this package's built entry. */
12
+ export declare const api: DoomApi;
13
+ //#endregion
14
+ //# sourceMappingURL=planApi.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planApi.d.mts","names":[],"sources":["../../src/adapters/planApi.ts"],"mappings":";;;;iBAwCiB;;EAEf;EACA,WAAW;;wBAwBG,cAAc,UAAS,iBAAsB;;qBAmDhD,KAAK"}
@@ -0,0 +1,2 @@
1
+ import{NodePlanPointerAdapter as e}from"./node/planPointer.mjs";import{API_BASE_PATH as t,contentPath as n,currentPath as r}from"../types/planApi.mjs";import{createHash as i}from"node:crypto";import a from"node:fs/promises";import{Hono as o}from"hono";const s=1048576,c=`This session has not written a plan yet.`;function l(e){return i(`sha256`).update(e,`utf8`).digest(`hex`)}async function u(e){let t;try{t=await a.readFile(e)}catch{return{content:``,hash:``,unavailable:!0,reason:`the plan file no longer exists`}}if(t.byteLength>1048576)return{content:``,hash:``,unavailable:!0,reason:`the plan is larger than ${s} bytes`};let n=t.toString(`utf8`);return{content:n,hash:l(n),unavailable:!1}}function d(t={}){let i=new o,s=t.pointers??new e,d=()=>t.sessionId===void 0?void 0:s.read(t.sessionId);return i.get(r(),async e=>{let t=d();if(t===void 0)return e.json({error:c},404);let n={path:t.path,title:t.title,writtenAt:t.writtenAt,...t.planId===void 0?{}:{planId:t.planId},...await u(t.path)};return e.json(n)}),i.put(n(),async e=>{let t;try{t=await e.req.json()}catch{return e.json({error:`The save body is not JSON.`},400)}if(typeof t.content!=`string`||typeof t.expectedHash!=`string`)return e.json({error:`A save carries the content to write and the hash it was read at.`},400);let n=d();if(n===void 0)return e.json({error:c},404);let r=await u(n.path);if(r.unavailable)return e.json({error:r.reason??c},409);if(r.hash!==t.expectedHash)return e.json({error:`The plan changed since it was opened.`,hash:r.hash},409);let i=await a.lstat(n.path);return!i.isFile()||i.nlink!==1?e.json({error:`The plan file is no longer a regular file, so it was not written.`},409):(await a.writeFile(n.path,t.content,{encoding:`utf8`,mode:384}),e.json({hash:l(t.content)}))}),i}const f={basePath:t,start(e){let t=d(e.sessionId===void 0?{}:{sessionId:e.sessionId});return{fetch:e=>t.fetch(e),close:()=>void 0}}};export{s as MAX_PLAN_BYTES,f as api,d as createPlanApi};
2
+ //# sourceMappingURL=planApi.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planApi.mjs","names":[],"sources":["../../src/adapters/planApi.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport fs from 'node:fs/promises';\nimport type { DoomApi, DoomApiContext, DoomApiHandler } from '@agimon-ai/doompi-extension-contracts/package-api';\nimport { Hono } from 'hono';\nimport {\n API_BASE_PATH,\n contentPath,\n currentPath,\n type PlanDetailView,\n type PlanSaveRequest,\n type PlanSaveView,\n} from '../types/planApi.ts';\nimport type { PlanPointerPort } from '../types/planPointer.ts';\nimport { NodePlanPointerAdapter } from './node/planPointer.ts';\n\n/**\n * This package's HTTP surface: the session's current plan, and the manual save.\n *\n * Routes are relative to the mount its host gives it, so nothing here repeats\n * where it was mounted. The host is one session's own server, which is what\n * makes the session id available without the page supplying it.\n *\n * Neither route takes a path. A session has exactly one current plan, and the\n * file both routes act on is the one the pointer names, so a page can address\n * the plan and nothing else; there is no traversal question to answer because\n * there is no path to traverse.\n *\n * The save refuses unless the reader proves they were looking at the content\n * that is still on disk. The agent may rewrite the plan while a tab is open,\n * and silently discarding whichever side finished second is the one outcome\n * worth ruling out.\n */\n\n/** Past this, the plan is reported rather than carried. */\nexport const MAX_PLAN_BYTES = 1024 * 1024;\n\nconst NO_PLAN = 'This session has not written a plan yet.';\nconst STALE_SAVE = 'The plan changed since it was opened.';\nconst NOT_A_FILE = 'The plan file is no longer a regular file, so it was not written.';\n\nexport interface PlanApiOptions {\n /** The session these routes answer for; absent when the host is the hub. */\n sessionId?: string;\n pointers?: PlanPointerPort;\n}\n\nfunction hashOf(content: string): string {\n return createHash('sha256').update(content, 'utf8').digest('hex');\n}\n\n/** Reads the plan as the source view will show it, or says why it cannot. */\nasync function readPlan(\n planPath: string,\n): Promise<Pick<PlanDetailView, 'content' | 'hash' | 'unavailable' | 'reason'>> {\n let raw: Buffer;\n try {\n raw = await fs.readFile(planPath);\n } catch {\n return { content: '', hash: '', unavailable: true, reason: 'the plan file no longer exists' };\n }\n if (raw.byteLength > MAX_PLAN_BYTES) {\n return { content: '', hash: '', unavailable: true, reason: `the plan is larger than ${MAX_PLAN_BYTES} bytes` };\n }\n const content = raw.toString('utf8');\n return { content, hash: hashOf(content), unavailable: false };\n}\n\nexport function createPlanApi(options: PlanApiOptions = {}): Hono {\n const app = new Hono();\n const pointers = options.pointers ?? new NodePlanPointerAdapter();\n const pointerFor = (): ReturnType<PlanPointerPort['read']> =>\n options.sessionId === undefined ? undefined : pointers.read(options.sessionId);\n\n app.get(currentPath(), async (context) => {\n const pointer = pointerFor();\n if (pointer === undefined) return context.json({ error: NO_PLAN }, 404);\n const view: PlanDetailView = {\n path: pointer.path,\n title: pointer.title,\n writtenAt: pointer.writtenAt,\n ...(pointer.planId === undefined ? {} : { planId: pointer.planId }),\n ...(await readPlan(pointer.path)),\n };\n return context.json(view);\n });\n\n app.put(contentPath(), async (context) => {\n let request: PlanSaveRequest;\n try {\n request = (await context.req.json()) as PlanSaveRequest;\n } catch {\n return context.json({ error: 'The save body is not JSON.' }, 400);\n }\n if (typeof request.content !== 'string' || typeof request.expectedHash !== 'string') {\n return context.json({ error: 'A save carries the content to write and the hash it was read at.' }, 400);\n }\n const pointer = pointerFor();\n if (pointer === undefined) return context.json({ error: NO_PLAN }, 404);\n\n const current = await readPlan(pointer.path);\n if (current.unavailable) return context.json({ error: current.reason ?? NO_PLAN }, 409);\n if (current.hash !== request.expectedHash) {\n return context.json({ error: STALE_SAVE, hash: current.hash }, 409);\n }\n // The same guard write_plan applies before it writes: a plan whose\n // destination has become a symlink or gained a second name is not written\n // through, whatever the pointer still says.\n const stats = await fs.lstat(pointer.path);\n if (!stats.isFile() || stats.nlink !== 1) return context.json({ error: NOT_A_FILE }, 409);\n\n await fs.writeFile(pointer.path, request.content, { encoding: 'utf8', mode: 0o600 });\n return context.json({ hash: hashOf(request.content) } satisfies PlanSaveView);\n });\n\n return app;\n}\n\n/** The named export a host imports from this package's built entry. */\nexport const api: DoomApi = {\n basePath: API_BASE_PATH,\n start(context: DoomApiContext): DoomApiHandler {\n const app = createPlanApi(context.sessionId === undefined ? {} : { sessionId: context.sessionId });\n return {\n fetch: (request) => app.fetch(request),\n // Nothing outlives a request here; an API that starts a watch or a timer\n // tears it down in this callback.\n close: () => undefined,\n };\n },\n};\n"],"mappings":"4PAkCA,MAAa,EAAiB,QAExB,EAAU,2CAUhB,SAAS,EAAO,EAAyB,CACvC,OAAO,EAAW,QAAQ,CAAC,CAAC,OAAO,EAAS,MAAM,CAAC,CAAC,OAAO,KAAK,CAClE,CAGA,eAAe,EACb,EAC8E,CAC9E,IAAI,EACJ,GAAI,CACF,EAAM,MAAM,EAAG,SAAS,CAAQ,CAClC,MAAQ,CACN,MAAO,CAAE,QAAS,GAAI,KAAM,GAAI,YAAa,GAAM,OAAQ,gCAAiC,CAC9F,CACA,GAAI,EAAI,WAAA,QACN,MAAO,CAAE,QAAS,GAAI,KAAM,GAAI,YAAa,GAAM,OAAQ,2BAA2B,EAAe,OAAQ,EAE/G,IAAM,EAAU,EAAI,SAAS,MAAM,EACnC,MAAO,CAAE,UAAS,KAAM,EAAO,CAAO,EAAG,YAAa,EAAM,CAC9D,CAEA,SAAgB,EAAc,EAA0B,CAAC,EAAS,CAChE,IAAM,EAAM,IAAI,EACV,EAAW,EAAQ,UAAY,IAAI,EACnC,MACJ,EAAQ,YAAc,IAAA,GAAY,IAAA,GAAY,EAAS,KAAK,EAAQ,SAAS,EA2C/E,OAzCA,EAAI,IAAI,EAAY,EAAG,KAAO,IAAY,CACxC,IAAM,EAAU,EAAW,EAC3B,GAAI,IAAY,IAAA,GAAW,OAAO,EAAQ,KAAK,CAAE,MAAO,CAAQ,EAAG,GAAG,EACtE,IAAM,EAAuB,CAC3B,KAAM,EAAQ,KACd,MAAO,EAAQ,MACf,UAAW,EAAQ,UACnB,GAAI,EAAQ,SAAW,IAAA,GAAY,CAAC,EAAI,CAAE,OAAQ,EAAQ,MAAO,EACjE,GAAI,MAAM,EAAS,EAAQ,IAAI,CACjC,EACA,OAAO,EAAQ,KAAK,CAAI,CAC1B,CAAC,EAED,EAAI,IAAI,EAAY,EAAG,KAAO,IAAY,CACxC,IAAI,EACJ,GAAI,CACF,EAAW,MAAM,EAAQ,IAAI,KAAK,CACpC,MAAQ,CACN,OAAO,EAAQ,KAAK,CAAE,MAAO,4BAA6B,EAAG,GAAG,CAClE,CACA,GAAI,OAAO,EAAQ,SAAY,UAAY,OAAO,EAAQ,cAAiB,SACzE,OAAO,EAAQ,KAAK,CAAE,MAAO,kEAAmE,EAAG,GAAG,EAExG,IAAM,EAAU,EAAW,EAC3B,GAAI,IAAY,IAAA,GAAW,OAAO,EAAQ,KAAK,CAAE,MAAO,CAAQ,EAAG,GAAG,EAEtE,IAAM,EAAU,MAAM,EAAS,EAAQ,IAAI,EAC3C,GAAI,EAAQ,YAAa,OAAO,EAAQ,KAAK,CAAE,MAAO,EAAQ,QAAU,CAAQ,EAAG,GAAG,EACtF,GAAI,EAAQ,OAAS,EAAQ,aAC3B,OAAO,EAAQ,KAAK,CAAE,MAAO,wCAAY,KAAM,EAAQ,IAAK,EAAG,GAAG,EAKpE,IAAM,EAAQ,MAAM,EAAG,MAAM,EAAQ,IAAI,EAIzC,MAHI,CAAC,EAAM,OAAO,GAAK,EAAM,QAAU,EAAU,EAAQ,KAAK,CAAE,MAAO,mEAAW,EAAG,GAAG,GAExF,MAAM,EAAG,UAAU,EAAQ,KAAM,EAAQ,QAAS,CAAE,SAAU,OAAQ,KAAM,GAAM,CAAC,EAC5E,EAAQ,KAAK,CAAE,KAAM,EAAO,EAAQ,OAAO,CAAE,CAAwB,EAC9E,CAAC,EAEM,CACT,CAGA,MAAa,EAAe,CAC1B,SAAU,EACV,MAAM,EAAyC,CAC7C,IAAM,EAAM,EAAc,EAAQ,YAAc,IAAA,GAAY,CAAC,EAAI,CAAE,UAAW,EAAQ,SAAU,CAAC,EACjG,MAAO,CACL,MAAQ,GAAY,EAAI,MAAM,CAAO,EAGrC,UAAa,IAAA,EACf,CACF,CACF"}
@@ -0,0 +1,2 @@
1
+ let e=require("@agimon-ai/doompi-telemetry");const t={configLoadFailed:`doom_plan.config_load_failed`,writePlanFailed:`doom_plan.write_plan_failed`,writePlanTimedOut:`doom_plan.write_plan_timed_out`,writePlanUnsafePath:`doom_plan.write_plan_unsafe_path`,modelResolveFailed:`doom_plan.model_resolve_failed`,modeEnabled:`doom_plan.mode_enabled`,modeDisabled:`doom_plan.mode_disabled`,planWritten:`doom_plan.plan_written`,planPointerFailed:`doom_plan.plan_pointer_failed`,planReviewCompleted:`doom_plan.plan_review_completed`};function n(t={}){let n=(0,e.createDoomTelemetry)({serviceName:`doom-plan`,packageName:`@agimon-ai/doompi-plan`,cwd:t.cwd,workspaceRoot:t.workspaceRoot,env:t.env,telemetryFactory:t.telemetryFactory,warn:t.warn,enableLogs:!0,enableTraces:!0});return{recordError:(e,t,r)=>n.recordError(e,t,r),recordWarning:(e,t,r)=>n.recordWarning(e,t,r),recordEvent:(e,t)=>n.recordEvent(e,t),flush:()=>n.flush(),shutdown:()=>n.shutdown()}}exports.PLAN_EVENT=t,exports.createPlanTelemetry=n;
2
+ //# sourceMappingURL=logSinkTelemetry.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logSinkTelemetry.cjs","names":["createDoomTelemetry"],"sources":["../../../src/adapters/telemetry/logSinkTelemetry.ts"],"sourcesContent":["import { createDoomTelemetry, type DoomTelemetry, type DoomTelemetryOptions } from '@agimon-ai/doompi-telemetry';\n\nconst SERVICE_NAME = 'doom-plan';\nconst PACKAGE_NAME = '@agimon-ai/doompi-plan';\n\nexport const PLAN_EVENT = {\n configLoadFailed: 'doom_plan.config_load_failed',\n writePlanFailed: 'doom_plan.write_plan_failed',\n writePlanTimedOut: 'doom_plan.write_plan_timed_out',\n writePlanUnsafePath: 'doom_plan.write_plan_unsafe_path',\n modelResolveFailed: 'doom_plan.model_resolve_failed',\n modeEnabled: 'doom_plan.mode_enabled',\n modeDisabled: 'doom_plan.mode_disabled',\n planWritten: 'doom_plan.plan_written',\n planPointerFailed: 'doom_plan.plan_pointer_failed',\n planReviewCompleted: 'doom_plan.plan_review_completed',\n} as const;\n\nexport type PlanEventName = (typeof PLAN_EVENT)[keyof typeof PLAN_EVENT];\nexport type PlanEventAttributes = Record<string, string | number | boolean>;\n\nexport interface PlanTelemetryOptions {\n cwd?: string;\n workspaceRoot?: string;\n env?: NodeJS.ProcessEnv;\n telemetryFactory?: NonNullable<DoomTelemetryOptions['telemetryFactory']>;\n warn?: (message: string) => void;\n}\n\nexport interface PlanTelemetry {\n recordError(event: PlanEventName, error: unknown, attributes?: PlanEventAttributes): Promise<void>;\n recordWarning(event: PlanEventName, error: unknown, attributes?: PlanEventAttributes): Promise<void>;\n recordEvent(event: PlanEventName, attributes?: PlanEventAttributes): Promise<void>;\n flush(): Promise<void>;\n shutdown(): Promise<void>;\n}\n\nexport function createPlanTelemetry(options: PlanTelemetryOptions = {}): PlanTelemetry {\n const telemetry: DoomTelemetry = createDoomTelemetry({\n serviceName: SERVICE_NAME,\n packageName: PACKAGE_NAME,\n cwd: options.cwd,\n workspaceRoot: options.workspaceRoot,\n env: options.env,\n telemetryFactory: options.telemetryFactory,\n warn: options.warn,\n enableLogs: true,\n enableTraces: true,\n });\n return {\n recordError: (event, error, attributes) => telemetry.recordError(event, error, attributes),\n recordWarning: (event, error, attributes) => telemetry.recordWarning(event, error, attributes),\n recordEvent: (event, attributes) => telemetry.recordEvent(event, attributes),\n flush: () => telemetry.flush(),\n shutdown: () => telemetry.shutdown(),\n };\n}\n"],"mappings":"6CAEA,MAGa,EAAa,CACxB,iBAAkB,+BAClB,gBAAiB,8BACjB,kBAAmB,iCACnB,oBAAqB,mCACrB,mBAAoB,iCACpB,YAAa,yBACb,aAAc,0BACd,YAAa,yBACb,kBAAmB,gCACnB,oBAAqB,iCACvB,EAqBA,SAAgB,EAAoB,EAAgC,CAAC,EAAkB,CACrF,IAAM,GAAA,EAA2BA,EAAAA,oBAAAA,CAAoB,CACnD,YAAa,YACb,YAAa,yBACb,IAAK,EAAQ,IACb,cAAe,EAAQ,cACvB,IAAK,EAAQ,IACb,iBAAkB,EAAQ,iBAC1B,KAAM,EAAQ,KACd,WAAY,GACZ,aAAc,EAChB,CAAC,EACD,MAAO,CACL,aAAc,EAAO,EAAO,IAAe,EAAU,YAAY,EAAO,EAAO,CAAU,EACzF,eAAgB,EAAO,EAAO,IAAe,EAAU,cAAc,EAAO,EAAO,CAAU,EAC7F,aAAc,EAAO,IAAe,EAAU,YAAY,EAAO,CAAU,EAC3E,UAAa,EAAU,MAAM,EAC7B,aAAgB,EAAU,SAAS,CACrC,CACF"}
@@ -0,0 +1,33 @@
1
+ import { DoomTelemetryOptions } from "@agimon-ai/doompi-telemetry";
2
+ //#region src/adapters/telemetry/logSinkTelemetry.d.ts
3
+ export declare const PLAN_EVENT: {
4
+ readonly configLoadFailed: 'doom_plan.config_load_failed';
5
+ readonly writePlanFailed: 'doom_plan.write_plan_failed';
6
+ readonly writePlanTimedOut: 'doom_plan.write_plan_timed_out';
7
+ readonly writePlanUnsafePath: 'doom_plan.write_plan_unsafe_path';
8
+ readonly modelResolveFailed: 'doom_plan.model_resolve_failed';
9
+ readonly modeEnabled: 'doom_plan.mode_enabled';
10
+ readonly modeDisabled: 'doom_plan.mode_disabled';
11
+ readonly planWritten: 'doom_plan.plan_written';
12
+ readonly planPointerFailed: 'doom_plan.plan_pointer_failed';
13
+ readonly planReviewCompleted: 'doom_plan.plan_review_completed';
14
+ };
15
+ export type PlanEventName = (typeof PLAN_EVENT)[keyof typeof PLAN_EVENT];
16
+ export type PlanEventAttributes = Record<string, string | number | boolean>;
17
+ export interface PlanTelemetryOptions {
18
+ cwd?: string;
19
+ workspaceRoot?: string;
20
+ env?: NodeJS.ProcessEnv;
21
+ telemetryFactory?: NonNullable<DoomTelemetryOptions['telemetryFactory']>;
22
+ warn?: (message: string) => void;
23
+ }
24
+ export interface PlanTelemetry {
25
+ recordError(event: PlanEventName, error: unknown, attributes?: PlanEventAttributes): Promise<void>;
26
+ recordWarning(event: PlanEventName, error: unknown, attributes?: PlanEventAttributes): Promise<void>;
27
+ recordEvent(event: PlanEventName, attributes?: PlanEventAttributes): Promise<void>;
28
+ flush(): Promise<void>;
29
+ shutdown(): Promise<void>;
30
+ }
31
+ export declare function createPlanTelemetry(options?: PlanTelemetryOptions): PlanTelemetry;
32
+ //#endregion
33
+ //# sourceMappingURL=logSinkTelemetry.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logSinkTelemetry.d.cts","names":[],"sources":["../../../src/adapters/telemetry/logSinkTelemetry.ts"],"mappings":";;qBAKa;WACX;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;YAGU,wBAAwB,yBAAyB;YACjD,sBAAsB;iBAEjB;EACf;EACA;EACA,MAAM,OAAO;EACb,mBAAmB,YAAY;EAC/B,QAAQ;;iBAGO;EACf,YAAY,OAAO,eAAe,gBAAgB,aAAa,sBAAsB;EACrF,cAAc,OAAO,eAAe,gBAAgB,aAAa,sBAAsB;EACvF,YAAY,OAAO,eAAe,aAAa,sBAAsB;EACrE,SAAS;EACT,YAAY;;wBAGE,oBAAoB,UAAS,uBAA4B"}
@@ -0,0 +1,33 @@
1
+ import { DoomTelemetryOptions } from "@agimon-ai/doompi-telemetry";
2
+ //#region src/adapters/telemetry/logSinkTelemetry.d.ts
3
+ export declare const PLAN_EVENT: {
4
+ readonly configLoadFailed: 'doom_plan.config_load_failed';
5
+ readonly writePlanFailed: 'doom_plan.write_plan_failed';
6
+ readonly writePlanTimedOut: 'doom_plan.write_plan_timed_out';
7
+ readonly writePlanUnsafePath: 'doom_plan.write_plan_unsafe_path';
8
+ readonly modelResolveFailed: 'doom_plan.model_resolve_failed';
9
+ readonly modeEnabled: 'doom_plan.mode_enabled';
10
+ readonly modeDisabled: 'doom_plan.mode_disabled';
11
+ readonly planWritten: 'doom_plan.plan_written';
12
+ readonly planPointerFailed: 'doom_plan.plan_pointer_failed';
13
+ readonly planReviewCompleted: 'doom_plan.plan_review_completed';
14
+ };
15
+ export type PlanEventName = (typeof PLAN_EVENT)[keyof typeof PLAN_EVENT];
16
+ export type PlanEventAttributes = Record<string, string | number | boolean>;
17
+ export interface PlanTelemetryOptions {
18
+ cwd?: string;
19
+ workspaceRoot?: string;
20
+ env?: NodeJS.ProcessEnv;
21
+ telemetryFactory?: NonNullable<DoomTelemetryOptions['telemetryFactory']>;
22
+ warn?: (message: string) => void;
23
+ }
24
+ export interface PlanTelemetry {
25
+ recordError(event: PlanEventName, error: unknown, attributes?: PlanEventAttributes): Promise<void>;
26
+ recordWarning(event: PlanEventName, error: unknown, attributes?: PlanEventAttributes): Promise<void>;
27
+ recordEvent(event: PlanEventName, attributes?: PlanEventAttributes): Promise<void>;
28
+ flush(): Promise<void>;
29
+ shutdown(): Promise<void>;
30
+ }
31
+ export declare function createPlanTelemetry(options?: PlanTelemetryOptions): PlanTelemetry;
32
+ //#endregion
33
+ //# sourceMappingURL=logSinkTelemetry.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logSinkTelemetry.d.mts","names":[],"sources":["../../../src/adapters/telemetry/logSinkTelemetry.ts"],"mappings":";;qBAKa;WACX;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;YAGU,wBAAwB,yBAAyB;YACjD,sBAAsB;iBAEjB;EACf;EACA;EACA,MAAM,OAAO;EACb,mBAAmB,YAAY;EAC/B,QAAQ;;iBAGO;EACf,YAAY,OAAO,eAAe,gBAAgB,aAAa,sBAAsB;EACrF,cAAc,OAAO,eAAe,gBAAgB,aAAa,sBAAsB;EACvF,YAAY,OAAO,eAAe,aAAa,sBAAsB;EACrE,SAAS;EACT,YAAY;;wBAGE,oBAAoB,UAAS,uBAA4B"}
@@ -0,0 +1,2 @@
1
+ import{createDoomTelemetry as e}from"@agimon-ai/doompi-telemetry";const t={configLoadFailed:`doom_plan.config_load_failed`,writePlanFailed:`doom_plan.write_plan_failed`,writePlanTimedOut:`doom_plan.write_plan_timed_out`,writePlanUnsafePath:`doom_plan.write_plan_unsafe_path`,modelResolveFailed:`doom_plan.model_resolve_failed`,modeEnabled:`doom_plan.mode_enabled`,modeDisabled:`doom_plan.mode_disabled`,planWritten:`doom_plan.plan_written`,planPointerFailed:`doom_plan.plan_pointer_failed`,planReviewCompleted:`doom_plan.plan_review_completed`};function n(t={}){let n=e({serviceName:`doom-plan`,packageName:`@agimon-ai/doompi-plan`,cwd:t.cwd,workspaceRoot:t.workspaceRoot,env:t.env,telemetryFactory:t.telemetryFactory,warn:t.warn,enableLogs:!0,enableTraces:!0});return{recordError:(e,t,r)=>n.recordError(e,t,r),recordWarning:(e,t,r)=>n.recordWarning(e,t,r),recordEvent:(e,t)=>n.recordEvent(e,t),flush:()=>n.flush(),shutdown:()=>n.shutdown()}}export{t as PLAN_EVENT,n as createPlanTelemetry};
2
+ //# sourceMappingURL=logSinkTelemetry.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logSinkTelemetry.mjs","names":[],"sources":["../../../src/adapters/telemetry/logSinkTelemetry.ts"],"sourcesContent":["import { createDoomTelemetry, type DoomTelemetry, type DoomTelemetryOptions } from '@agimon-ai/doompi-telemetry';\n\nconst SERVICE_NAME = 'doom-plan';\nconst PACKAGE_NAME = '@agimon-ai/doompi-plan';\n\nexport const PLAN_EVENT = {\n configLoadFailed: 'doom_plan.config_load_failed',\n writePlanFailed: 'doom_plan.write_plan_failed',\n writePlanTimedOut: 'doom_plan.write_plan_timed_out',\n writePlanUnsafePath: 'doom_plan.write_plan_unsafe_path',\n modelResolveFailed: 'doom_plan.model_resolve_failed',\n modeEnabled: 'doom_plan.mode_enabled',\n modeDisabled: 'doom_plan.mode_disabled',\n planWritten: 'doom_plan.plan_written',\n planPointerFailed: 'doom_plan.plan_pointer_failed',\n planReviewCompleted: 'doom_plan.plan_review_completed',\n} as const;\n\nexport type PlanEventName = (typeof PLAN_EVENT)[keyof typeof PLAN_EVENT];\nexport type PlanEventAttributes = Record<string, string | number | boolean>;\n\nexport interface PlanTelemetryOptions {\n cwd?: string;\n workspaceRoot?: string;\n env?: NodeJS.ProcessEnv;\n telemetryFactory?: NonNullable<DoomTelemetryOptions['telemetryFactory']>;\n warn?: (message: string) => void;\n}\n\nexport interface PlanTelemetry {\n recordError(event: PlanEventName, error: unknown, attributes?: PlanEventAttributes): Promise<void>;\n recordWarning(event: PlanEventName, error: unknown, attributes?: PlanEventAttributes): Promise<void>;\n recordEvent(event: PlanEventName, attributes?: PlanEventAttributes): Promise<void>;\n flush(): Promise<void>;\n shutdown(): Promise<void>;\n}\n\nexport function createPlanTelemetry(options: PlanTelemetryOptions = {}): PlanTelemetry {\n const telemetry: DoomTelemetry = createDoomTelemetry({\n serviceName: SERVICE_NAME,\n packageName: PACKAGE_NAME,\n cwd: options.cwd,\n workspaceRoot: options.workspaceRoot,\n env: options.env,\n telemetryFactory: options.telemetryFactory,\n warn: options.warn,\n enableLogs: true,\n enableTraces: true,\n });\n return {\n recordError: (event, error, attributes) => telemetry.recordError(event, error, attributes),\n recordWarning: (event, error, attributes) => telemetry.recordWarning(event, error, attributes),\n recordEvent: (event, attributes) => telemetry.recordEvent(event, attributes),\n flush: () => telemetry.flush(),\n shutdown: () => telemetry.shutdown(),\n };\n}\n"],"mappings":"kEAEA,MAGa,EAAa,CACxB,iBAAkB,+BAClB,gBAAiB,8BACjB,kBAAmB,iCACnB,oBAAqB,mCACrB,mBAAoB,iCACpB,YAAa,yBACb,aAAc,0BACd,YAAa,yBACb,kBAAmB,gCACnB,oBAAqB,iCACvB,EAqBA,SAAgB,EAAoB,EAAgC,CAAC,EAAkB,CACrF,IAAM,EAA2B,EAAoB,CACnD,YAAa,YACb,YAAa,yBACb,IAAK,EAAQ,IACb,cAAe,EAAQ,cACvB,IAAK,EAAQ,IACb,iBAAkB,EAAQ,iBAC1B,KAAM,EAAQ,KACd,WAAY,GACZ,aAAc,EAChB,CAAC,EACD,MAAO,CACL,aAAc,EAAO,EAAO,IAAe,EAAU,YAAY,EAAO,EAAO,CAAU,EACzF,eAAgB,EAAO,EAAO,IAAe,EAAU,cAAc,EAAO,EAAO,CAAU,EAC7F,aAAc,EAAO,IAAe,EAAU,YAAY,EAAO,CAAU,EAC3E,UAAa,EAAU,MAAM,EAC7B,aAAgB,EAAU,SAAS,CACrC,CACF"}
package/dist/config.cjs CHANGED
@@ -1,2 +1 @@
1
- require(`./_virtual/_rolldown/runtime.cjs`);let e=require(`@agimon-ai/doompi-config`);function t(t,n){let r=(0,e.parseDoomConfig)(t,n);return r.modes?{modes:r.modes}:{}}function n(t,n){let r=(0,e.mergeDoomConfigs)({...t,projectTrust:`ask`},{...n,projectTrust:`ask`});return r.modes?{modes:r.modes}:{}}function r(t,n){let r=(0,e.loadDoomConfig)(t,n);return r.modes?{modes:r.modes}:{}}exports.loadDoomConfig=r,exports.mergeDoomConfigs=n,exports.parseDoomConfig=t;
2
- //# sourceMappingURL=config.cjs.map
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./schemas/plan/config.cjs");let t=require("@agimon-ai/doompi-config");exports.getHarnessState=t.getHarnessState,exports.globalDoomConfigPath=t.globalDoomConfigPath,exports.loadDoomConfig=e.loadDoomConfig,exports.loadHarnessState=t.loadHarnessState,exports.mergeDoomConfigs=e.mergeDoomConfigs,exports.parseDoomConfig=e.parseDoomConfig,exports.parsePlanningModeConfig=t.parsePlanningModeConfig,exports.repositoryDoomConfigPath=t.repositoryDoomConfigPath,exports.resolvePlanningPlansDirectory=t.resolvePlanningPlansDirectory;
package/dist/config.d.cts CHANGED
@@ -1,14 +1,2 @@
1
- import { PlanningAgentConfig, PlanningModeConfig, PlanningThinkingLevel, getHarnessState, globalDoomConfigPath, loadHarnessState, parsePlanningModeConfig, repositoryDoomConfigPath, resolvePlanningPlansDirectory } from "@agimon-ai/doompi-config";
2
-
3
- //#region src/config.d.ts
4
- interface DoomConfig {
5
- modes?: {
6
- planning?: PlanningModeConfig;
7
- };
8
- }
9
- declare function parseDoomConfig(content: string, filePath: string): DoomConfig;
10
- declare function mergeDoomConfigs(globalConfig: DoomConfig, repositoryConfig: DoomConfig): DoomConfig;
11
- declare function loadDoomConfig(repoRoot: string, homeDirectory?: string): DoomConfig;
12
- //#endregion
13
- export { DoomConfig, type PlanningAgentConfig, type PlanningModeConfig, type PlanningThinkingLevel, getHarnessState, globalDoomConfigPath, loadDoomConfig, loadHarnessState, mergeDoomConfigs, parseDoomConfig, parsePlanningModeConfig, repositoryDoomConfigPath, resolvePlanningPlansDirectory };
14
- //# sourceMappingURL=config.d.cts.map
1
+ import { DoomConfig, PlanningAgentConfig, PlanningModeConfig, PlanningThinkingLevel, getHarnessState, globalDoomConfigPath, loadDoomConfig, loadHarnessState, mergeDoomConfigs, parseDoomConfig, parsePlanningModeConfig, repositoryDoomConfigPath, resolvePlanningPlansDirectory } from "./schemas/plan/config.cjs";
2
+ export { DoomConfig, type PlanningAgentConfig, type PlanningModeConfig, type PlanningThinkingLevel, getHarnessState, globalDoomConfigPath, loadDoomConfig, loadHarnessState, mergeDoomConfigs, parseDoomConfig, parsePlanningModeConfig, repositoryDoomConfigPath, resolvePlanningPlansDirectory };
package/dist/config.d.mts CHANGED
@@ -1,14 +1,2 @@
1
- import { PlanningAgentConfig, PlanningModeConfig, PlanningThinkingLevel, getHarnessState, globalDoomConfigPath as globalDoomConfigPath$1, loadHarnessState, parsePlanningModeConfig, repositoryDoomConfigPath, resolvePlanningPlansDirectory } from "@agimon-ai/doompi-config";
2
-
3
- //#region src/config.d.ts
4
- interface DoomConfig {
5
- modes?: {
6
- planning?: PlanningModeConfig;
7
- };
8
- }
9
- declare function parseDoomConfig$1(content: string, filePath: string): DoomConfig;
10
- declare function mergeDoomConfigs$1(globalConfig: DoomConfig, repositoryConfig: DoomConfig): DoomConfig;
11
- declare function loadDoomConfig$1(repoRoot: string, homeDirectory?: string): DoomConfig;
12
- //#endregion
13
- export { DoomConfig, type PlanningAgentConfig, type PlanningModeConfig, type PlanningThinkingLevel, getHarnessState, globalDoomConfigPath$1 as globalDoomConfigPath, loadDoomConfig$1 as loadDoomConfig, loadHarnessState, mergeDoomConfigs$1 as mergeDoomConfigs, parseDoomConfig$1 as parseDoomConfig, parsePlanningModeConfig, repositoryDoomConfigPath, resolvePlanningPlansDirectory };
14
- //# sourceMappingURL=config.d.mts.map
1
+ import { DoomConfig, PlanningAgentConfig, PlanningModeConfig, PlanningThinkingLevel, getHarnessState, globalDoomConfigPath, loadDoomConfig, loadHarnessState, mergeDoomConfigs, parseDoomConfig, parsePlanningModeConfig, repositoryDoomConfigPath, resolvePlanningPlansDirectory } from "./schemas/plan/config.mjs";
2
+ export { DoomConfig, type PlanningAgentConfig, type PlanningModeConfig, type PlanningThinkingLevel, getHarnessState, globalDoomConfigPath, loadDoomConfig, loadHarnessState, mergeDoomConfigs, parseDoomConfig, parsePlanningModeConfig, repositoryDoomConfigPath, resolvePlanningPlansDirectory };
package/dist/config.mjs CHANGED
@@ -1,2 +1 @@
1
- import{getHarnessState as e,globalDoomConfigPath as t,loadDoomConfig as n,loadHarnessState as r,mergeDoomConfigs as i,parseDoomConfig as a,parsePlanningModeConfig as o,repositoryDoomConfigPath as s,resolvePlanningPlansDirectory as c}from"@agimon-ai/doompi-config";function l(e,t){let n=a(e,t);return n.modes?{modes:n.modes}:{}}function u(e,t){let n=i({...e,projectTrust:`ask`},{...t,projectTrust:`ask`});return n.modes?{modes:n.modes}:{}}function d(e,t){let r=n(e,t);return r.modes?{modes:r.modes}:{}}export{e as getHarnessState,t as globalDoomConfigPath,d as loadDoomConfig,r as loadHarnessState,u as mergeDoomConfigs,l as parseDoomConfig,o as parsePlanningModeConfig,s as repositoryDoomConfigPath,c as resolvePlanningPlansDirectory};
2
- //# sourceMappingURL=config.mjs.map
1
+ import{getHarnessState as e,globalDoomConfigPath as t,loadDoomConfig as n,loadHarnessState as r,mergeDoomConfigs as i,parseDoomConfig as a,parsePlanningModeConfig as o,repositoryDoomConfigPath as s,resolvePlanningPlansDirectory as c}from"./schemas/plan/config.mjs";export{e as getHarnessState,t as globalDoomConfigPath,n as loadDoomConfig,r as loadHarnessState,i as mergeDoomConfigs,a as parseDoomConfig,o as parsePlanningModeConfig,s as repositoryDoomConfigPath,c as resolvePlanningPlansDirectory};
@@ -1,2 +1 @@
1
- var e=require(`../extension.cjs`).activateStandardPlanExtension;module.exports=e;
2
- //# sourceMappingURL=pi.cjs.map
1
+ const e=require("../adapters/pi/extension.cjs");module.exports=e.activatePlanExtension;
@@ -1,2 +1,2 @@
1
- import { activateStandardPlanExtension } from "../extension.cjs";
2
- export = activateStandardPlanExtension;
1
+ import { activatePlanExtension } from "../adapters/pi/extension.cjs";
2
+ export = activatePlanExtension;
@@ -1,2 +1,2 @@
1
- import { activateStandardPlanExtension } from "../extension.mjs";
2
- export { activateStandardPlanExtension as default };
1
+ import { activatePlanExtension } from "../adapters/pi/extension.mjs";
2
+ export { activatePlanExtension as default };
@@ -1,2 +1 @@
1
- import{activateStandardPlanExtension as e}from"../extension.mjs";var t=e;export{t as default};
2
- //# sourceMappingURL=pi.mjs.map
1
+ import{activatePlanExtension as e}from"../adapters/pi/extension.mjs";export{e as default};
@@ -1,3 +1 @@
1
- require(`./_virtual/_rolldown/runtime.cjs`);let e=require(`node:buffer`),t=require(`node:crypto`);const n=`@agimon-ai/doompi-plan`,r=`claude`,i=`fable`,a=`claude/fable-plan-v1`,o=[/(?:api[_-]?key|access[_-]?token|client[_-]?secret|password|private[_-]?key|authorization|bearer)\s*[:=]/iu,/-----BEGIN [A-Z ]*PRIVATE KEY-----/u,/\bsk-[A-Za-z0-9_-]{16,}\b/u,/\bgh[pousr]_[A-Za-z0-9_]{16,}\b/u];function s(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function c(e){for(let t of e){let e=t.codePointAt(0);if(e!==void 0&&(e<=31||e===127))return!0}return!1}function l(e){return o.some(t=>t.test(e))}function u(t,n,r=!0){if(typeof t!=`string`)throw Error(`${n} must be a string.`);let i=t.trim();if(!i&&r)throw Error(`${n} must not be empty.`);if(e.Buffer.byteLength(i,`utf8`)>4096||c(i))throw Error(`${n} exceeds the bounded Fable text limit or contains control characters.`);if(l(i))throw Error(`${n} appears to contain a credential.`);return i}function d(e,t,n=!0){if(!Array.isArray(e))throw Error(`${t} must be an array.`);if(e.length>24)throw Error(`${t} exceeds the bounded item limit.`);let r=e.map((e,n)=>u(e,`${t}[${n}]`));if(n&&r.length===0)throw Error(`${t} must contain at least one item.`);return r}function f(e,t){if(typeof e!=`string`)throw Error(`${t} must be a string.`);let n=e.trim();if(!n||n.length>512||c(n))throw Error(`${t} is not a safe source path.`);if(l(n))throw Error(`${t} appears to contain a credential.`);return n}function p(e){if(!Array.isArray(e))throw Error(`verifiedFindings must be an array.`);if(e.length>24)throw Error(`verifiedFindings exceeds the bounded item limit.`);return e.map((e,t)=>{if(!s(e))throw Error(`verifiedFindings[${t}] must be an object.`);if(Object.keys(e).some(e=>e!==`path`&&e!==`finding`))throw Error(`verifiedFindings[${t}] contains an unsupported field.`);return{path:f(e.path,`verifiedFindings[${t}].path`),finding:u(e.finding,`verifiedFindings[${t}].finding`)}})}function m(e,t,n){let r=new Set(t),i=Object.keys(e).find(e=>!r.has(e));if(i)throw Error(`${n} contains unsupported field '${i}'.`)}function h(t){if(!s(t))throw Error(`Fable packet must be an object.`);m(t,[`goal`,`constraints`,`decisions`,`verifiedFindings`,`inferredFindings`,`unresolvedQuestions`,`currentPlan`],`Fable packet`);let n={goal:d(t.goal,`goal`),constraints:d(t.constraints,`constraints`,!1),decisions:d(t.decisions,`decisions`,!1),verifiedFindings:p(t.verifiedFindings),inferredFindings:d(t.inferredFindings,`inferredFindings`,!1),unresolvedQuestions:d(t.unresolvedQuestions,`unresolvedQuestions`,!1),...t.currentPlan===void 0?{}:{currentPlan:u(t.currentPlan,`currentPlan`,!1)}};if(e.Buffer.byteLength(JSON.stringify(n),`utf8`)>32768)throw Error(`Fable packet exceeds the bounded packet size.`);return n}function g(e){return l([e.draft,e.review].filter(e=>e!==void 0).join(`
2
- `))?{operationId:e.operationId,status:`failed`,stage:`failed`,durationMs:e.durationMs,errorCode:`unsafe_output`}:e}function _(e,t){return{operationId:e,status:`timed_out`,stage:`interrupted`,durationMs:Math.max(0,Date.now()-t),errorCode:`timeout`}}function v(e){let o,s=(t=`Fable operation cancelled.`)=>{let n=o;if(n){if(!n.cancelSent){n.cancelSent=!0;try{e.broker?.cancel(n.operationId,t)}catch(t){e.onError?.(t)}}n.controller.abort(Error(t))}};return{run:async(c,l)=>{if(o)throw Error(`A Fable operation is already active for this session.`);if(!e.isAuthorized())throw Error(`The Fable capability profile is not authorized.`);let u=h(c),d=`fable-${(0,t.randomUUID)()}`,f=Date.now(),p=new AbortController;o={operationId:d,controller:p,cancelSent:!1},e.onStage?.(`draft`);let m=()=>p.abort(l?.reason);l&&(l.addEventListener(`abort`,m,{once:!0}),l.aborted&&m());let v={requester:n,operationId:d,runtime:r,model:i,profile:a,packet:u},y,b=!1;try{if(!e.broker)return _(d,f);let t=e.broker.start(v,p.signal),n=new Promise(e=>{p.signal.addEventListener(`abort`,()=>{b||e({operationId:d,status:`cancelled`,stage:`cancelled`,durationMs:Math.max(0,Date.now()-f),errorCode:`cancelled`})},{once:!0})}),r=e.timeoutMs===void 0?void 0:new Promise(t=>{y=setTimeout(()=>{b=!0,s(`Fable operation timed out.`),t(_(d,f))},e.timeoutMs)}),i=g(r===void 0?await Promise.race([t,n]):await Promise.race([t,r,n]));return e.onStage?.(i.status===`completed`?`completed`:i.status===`cancelled`?`cancelled`:i.stage),i}catch(t){e.onError?.(t);let n={operationId:d,status:`failed`,stage:`failed`,durationMs:Math.max(0,Date.now()-f),errorCode:`unavailable`};return e.onStage?.(`failed`),n}finally{y&&clearTimeout(y),l&&l.removeEventListener(`abort`,m),o=void 0}},cancel:s,isActive:()=>o!==void 0}}exports.FABLE_PLAN_MODEL=i,exports.FABLE_PLAN_PROFILE=a,exports.FABLE_PLAN_REQUESTER=n,exports.FABLE_PLAN_RUNTIME=r,exports.FABLE_PROVIDER_SOURCE=`@agimon-ai/doompi-team`,exports.MAX_FABLE_ARRAY_ITEMS=24,exports.MAX_FABLE_PACKET_BYTES=32768,exports.MAX_FABLE_TEXT_BYTES=4096,exports.containsSuspectedCredential=l,exports.createFablePlanFlow=v,exports.sanitizeFablePacket=h;
3
- //# sourceMappingURL=fableFlow.cjs.map
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./services/fableFlow.cjs");exports.FABLE_PLAN_MODEL=e.FABLE_PLAN_MODEL,exports.FABLE_PLAN_PROFILE=e.FABLE_PLAN_PROFILE,exports.FABLE_PLAN_REQUESTER=e.FABLE_PLAN_REQUESTER,exports.FABLE_PLAN_RUNTIME=e.FABLE_PLAN_RUNTIME,exports.FABLE_PROVIDER_SOURCE=e.FABLE_PROVIDER_SOURCE,exports.MAX_FABLE_ARRAY_ITEMS=e.MAX_FABLE_ARRAY_ITEMS,exports.MAX_FABLE_PACKET_BYTES=e.MAX_FABLE_PACKET_BYTES,exports.MAX_FABLE_TEXT_BYTES=e.MAX_FABLE_TEXT_BYTES,exports.containsSuspectedCredential=e.containsSuspectedCredential,exports.createFablePlanFlow=e.createFablePlanFlow,exports.sanitizeFablePacket=e.sanitizeFablePacket;