@agimon-ai/doompi-plan 0.0.1-alpha.22 → 0.0.1-alpha.24

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 (80) hide show
  1. package/README.md +7 -2
  2. package/dist/adapters/pi/extension.cjs +1 -1
  3. package/dist/adapters/pi/extension.cjs.map +1 -1
  4. package/dist/adapters/pi/extension.d.cts +4 -3
  5. package/dist/adapters/pi/extension.d.cts.map +1 -1
  6. package/dist/adapters/pi/extension.d.mts +4 -3
  7. package/dist/adapters/pi/extension.d.mts.map +1 -1
  8. package/dist/adapters/pi/extension.mjs +1 -1
  9. package/dist/adapters/pi/extension.mjs.map +1 -1
  10. package/dist/extensions/pi.cjs +1 -2
  11. package/dist/extensions/pi.d.cts +2 -2
  12. package/dist/extensions/pi.d.mts +2 -2
  13. package/dist/extensions/pi.mjs +1 -2
  14. package/dist/fableFlow.cjs +1 -1
  15. package/dist/fableFlow.d.cts +1 -1
  16. package/dist/fableFlow.d.mts +1 -1
  17. package/dist/fableFlow.mjs +1 -1
  18. package/dist/index.cjs +1 -1
  19. package/dist/index.d.cts +3 -3
  20. package/dist/index.d.mts +3 -3
  21. package/dist/index.mjs +1 -1
  22. package/dist/planMode.cjs +1 -1
  23. package/dist/planMode.d.cts +2 -2
  24. package/dist/planMode.d.mts +2 -2
  25. package/dist/planMode.mjs +1 -1
  26. package/dist/prompts.cjs +1 -1
  27. package/dist/prompts.d.cts +1 -1
  28. package/dist/prompts.d.mts +1 -1
  29. package/dist/prompts.mjs +1 -1
  30. package/dist/services/fableFlow.cjs +3 -0
  31. package/dist/services/fableFlow.cjs.map +1 -0
  32. package/dist/services/{plan/fableFlow.d.cts → fableFlow.d.cts} +3 -1
  33. package/dist/services/fableFlow.d.cts.map +1 -0
  34. package/dist/services/{plan/fableFlow.d.mts → fableFlow.d.mts} +3 -1
  35. package/dist/services/fableFlow.d.mts.map +1 -0
  36. package/dist/services/fableFlow.mjs +3 -0
  37. package/dist/services/fableFlow.mjs.map +1 -0
  38. package/dist/services/planMode.cjs +6 -0
  39. package/dist/services/planMode.cjs.map +1 -0
  40. package/dist/services/{plan/planMode.d.cts → planMode.d.cts} +5 -4
  41. package/dist/services/planMode.d.cts.map +1 -0
  42. package/dist/services/{plan/planMode.d.mts → planMode.d.mts} +5 -4
  43. package/dist/services/planMode.d.mts.map +1 -0
  44. package/dist/services/planMode.mjs +6 -0
  45. package/dist/services/planMode.mjs.map +1 -0
  46. package/dist/services/prompts.cjs.map +1 -0
  47. package/dist/services/{plan/prompts.d.cts → prompts.d.cts} +1 -1
  48. package/dist/services/prompts.d.cts.map +1 -0
  49. package/dist/services/{plan/prompts.d.mts → prompts.d.mts} +1 -1
  50. package/dist/services/prompts.d.mts.map +1 -0
  51. package/dist/services/prompts.mjs.map +1 -0
  52. package/package.json +56 -18
  53. package/dist/extensions/doom.cjs +0 -2
  54. package/dist/extensions/doom.cjs.map +0 -1
  55. package/dist/extensions/doom.d.cts +0 -8
  56. package/dist/extensions/doom.d.cts.map +0 -1
  57. package/dist/extensions/doom.d.mts +0 -8
  58. package/dist/extensions/doom.d.mts.map +0 -1
  59. package/dist/extensions/doom.mjs +0 -2
  60. package/dist/extensions/doom.mjs.map +0 -1
  61. package/dist/extensions/pi.cjs.map +0 -1
  62. package/dist/extensions/pi.mjs.map +0 -1
  63. package/dist/services/plan/fableFlow.cjs +0 -3
  64. package/dist/services/plan/fableFlow.cjs.map +0 -1
  65. package/dist/services/plan/fableFlow.d.cts.map +0 -1
  66. package/dist/services/plan/fableFlow.d.mts.map +0 -1
  67. package/dist/services/plan/fableFlow.mjs +0 -3
  68. package/dist/services/plan/fableFlow.mjs.map +0 -1
  69. package/dist/services/plan/planMode.cjs +0 -6
  70. package/dist/services/plan/planMode.cjs.map +0 -1
  71. package/dist/services/plan/planMode.d.cts.map +0 -1
  72. package/dist/services/plan/planMode.d.mts.map +0 -1
  73. package/dist/services/plan/planMode.mjs +0 -6
  74. package/dist/services/plan/planMode.mjs.map +0 -1
  75. package/dist/services/plan/prompts.cjs.map +0 -1
  76. package/dist/services/plan/prompts.d.cts.map +0 -1
  77. package/dist/services/plan/prompts.d.mts.map +0 -1
  78. package/dist/services/plan/prompts.mjs.map +0 -1
  79. /package/dist/services/{plan/prompts.cjs → prompts.cjs} +0 -0
  80. /package/dist/services/{plan/prompts.mjs → prompts.mjs} +0 -0
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  A reviewable planning lifecycle for Pi with narrowed tools, plan storage, normal/debug/Fable flavors, and explicit completion.
4
4
 
5
+ Part of the [DoomPi distribution](https://www.npmjs.com/package/@agimon-ai/doompi).
6
+
5
7
  Plan mode removes `edit` and `write` from the active tool set and directs writes through `write_plan`. It does not sandbox Bash, external tools, or the operating system, so treat it as tool-level workflow protection rather than a repository permission boundary.
6
8
 
7
9
  > **Alpha:** planning flows and tool contracts may change between releases.
@@ -13,13 +15,14 @@ Plan mode removes `edit` and `write` from the active tool set and directs writes
13
15
 
14
16
  ## Install
15
17
 
16
- DoomPi includes Plan as an inactive core minor mode. For standalone Pi:
18
+ DoomPi includes Plan in every composition; Plan mode itself remains inactive until requested. For
19
+ standalone Pi:
17
20
 
18
21
  ```bash
19
22
  pi install npm:@agimon-ai/doompi-plan
20
23
  ```
21
24
 
22
- Use `/extensions/doom` for DoomPi integrations or `/extensions/pi` for the plain Pi adapter.
25
+ DoomPi and plain Pi use the same `@agimon-ai/doompi-plan/extensions/pi` factory.
23
26
 
24
27
  ## Start and exit
25
28
 
@@ -71,6 +74,8 @@ pnpm test
71
74
  pnpm lint
72
75
  ```
73
76
 
77
+ Maintained by [Agimon](https://agimon.ai/about).
78
+
74
79
  ## License
75
80
 
76
81
  MIT
@@ -1,2 +1,2 @@
1
- const e=require(`../../services/plan/planMode.cjs`),t={recordError:async()=>void 0,recordWarning:async()=>void 0,recordEvent:async()=>void 0,flush:async()=>void 0,shutdown:async()=>void 0};function n(n){e.planModeExtension(n,()=>void 0,t,{doomIntegrations:!1})}exports.activateStandardPlanExtension=n;
1
+ require(`../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../services/planMode.cjs`);let t=require(`@deepseek-ai/cordis`);function n(t,n){e.planModeExtension(t,n)}async function r(e){let r=new t.Context,i,a=()=>(i??=r.fiber.dispose(),i);try{n(r,e)}catch(e){throw await a(),e}e.on(`session_shutdown`,a)}exports.default=r;
2
2
  //# sourceMappingURL=extension.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"extension.cjs","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { planModeExtension } from '../../services/plan/planMode.ts';\nimport type { PlanTelemetry } from '../telemetry/logSinkTelemetry.ts';\n\nconst standardTelemetry: PlanTelemetry = {\n recordError: async () => undefined,\n recordWarning: async () => undefined,\n recordEvent: async () => undefined,\n flush: async () => undefined,\n shutdown: async () => undefined,\n};\n\n/** Standard Pi composition using session APIs without Doom config or UI providers. */\nexport function activateStandardPlanExtension(pi: ExtensionAPI): void {\n planModeExtension(pi, () => undefined, standardTelemetry, { doomIntegrations: false });\n}\n"],"mappings":"oDAIM,EAAmC,CACvC,YAAa,SAAY,IAAA,GACzB,cAAe,SAAY,IAAA,GAC3B,YAAa,SAAY,IAAA,GACzB,MAAO,SAAY,IAAA,GACnB,SAAU,SAAY,IAAA,GACvB,CAGD,SAAgB,EAA8B,EAAwB,CACpE,EAAA,kBAAkB,MAAU,IAAA,GAAW,EAAmB,CAAE,iBAAkB,GAAO,CAAC"}
1
+ {"version":3,"file":"extension.cjs","names":["Context"],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { planModeExtension } from '../../services/planMode.ts';\n\nconst SESSION_SHUTDOWN_EVENT = 'session_shutdown';\n\n/** Install Plan state and external resources into one package-local Cordis root. */\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 cordis = new Context();\n let disposal: Promise<void> | undefined;\n const dispose = (): Promise<void> => {\n disposal ??= cordis.fiber.dispose();\n return disposal;\n };\n\n try {\n installPlanRuntime(cordis, pi);\n } catch (error) {\n await dispose();\n throw error;\n }\n\n pi.on(SESSION_SHUTDOWN_EVENT, dispose);\n}\n\nexport default activatePlanExtension;\n"],"mappings":"oIAOA,SAAgB,EAAmB,EAAiB,EAAwB,CAC1E,EAAA,kBAAkB,EAAQ,EAAG,CAI/B,eAAsB,EAAsB,EAAiC,CAC3E,IAAM,EAAS,IAAIA,EAAAA,QACf,EACE,OACJ,IAAa,EAAO,MAAM,SAAS,CAC5B,GAGT,GAAI,CACF,EAAmB,EAAQ,EAAG,OACvB,EAAO,CAEd,MADA,MAAM,GAAS,CACT,EAGR,EAAG,GAAG,mBAAwB,EAAQ"}
@@ -1,8 +1,9 @@
1
+ import { Context } from "@deepseek-ai/cordis";
1
2
  import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
3
 
3
4
  //#region src/adapters/pi/extension.d.ts
4
- /** Standard Pi composition using session APIs without Doom config or UI providers. */
5
- declare function activateStandardPlanExtension(pi: ExtensionAPI): void;
5
+ /** The package's single standard Pi factory, including all optional typed Doom integrations. */
6
+ declare function activatePlanExtension(pi: ExtensionAPI): Promise<void>;
6
7
  //#endregion
7
- export { activateStandardPlanExtension };
8
+ export { activatePlanExtension };
8
9
  //# sourceMappingURL=extension.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extension.d.cts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;iBAagB,6BAAA,CAA8B,EAAA,EAAI,YAAA"}
1
+ {"version":3,"file":"extension.d.cts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;AAYA;AAAA,iBAAsB,qBAAA,CAAsB,EAAA,EAAI,YAAA,GAAe,OAAA"}
@@ -1,8 +1,9 @@
1
+ import { Context } from "@deepseek-ai/cordis";
1
2
  import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
3
 
3
4
  //#region src/adapters/pi/extension.d.ts
4
- /** Standard Pi composition using session APIs without Doom config or UI providers. */
5
- declare function activateStandardPlanExtension(pi: ExtensionAPI): void;
5
+ /** The package's single standard Pi factory, including all optional typed Doom integrations. */
6
+ declare function activatePlanExtension(pi: ExtensionAPI): Promise<void>;
6
7
  //#endregion
7
- export { activateStandardPlanExtension };
8
+ export { activatePlanExtension };
8
9
  //# sourceMappingURL=extension.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extension.d.mts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;iBAagB,6BAAA,CAA8B,EAAA,EAAI,YAAA"}
1
+ {"version":3,"file":"extension.d.mts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;;AAYA;AAAA,iBAAsB,qBAAA,CAAsB,EAAA,EAAI,YAAA,GAAe,OAAA"}
@@ -1,2 +1,2 @@
1
- import{planModeExtension as e}from"../../services/plan/planMode.mjs";const t={recordError:async()=>void 0,recordWarning:async()=>void 0,recordEvent:async()=>void 0,flush:async()=>void 0,shutdown:async()=>void 0};function n(n){e(n,()=>void 0,t,{doomIntegrations:!1})}export{n as activateStandardPlanExtension};
1
+ import{planModeExtension as e}from"../../services/planMode.mjs";import{Context as t}from"@deepseek-ai/cordis";function n(t,n){e(t,n)}async function r(e){let r=new t,i,a=()=>(i??=r.fiber.dispose(),i);try{n(r,e)}catch(e){throw await a(),e}e.on(`session_shutdown`,a)}export{r as default};
2
2
  //# sourceMappingURL=extension.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"extension.mjs","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { planModeExtension } from '../../services/plan/planMode.ts';\nimport type { PlanTelemetry } from '../telemetry/logSinkTelemetry.ts';\n\nconst standardTelemetry: PlanTelemetry = {\n recordError: async () => undefined,\n recordWarning: async () => undefined,\n recordEvent: async () => undefined,\n flush: async () => undefined,\n shutdown: async () => undefined,\n};\n\n/** Standard Pi composition using session APIs without Doom config or UI providers. */\nexport function activateStandardPlanExtension(pi: ExtensionAPI): void {\n planModeExtension(pi, () => undefined, standardTelemetry, { doomIntegrations: false });\n}\n"],"mappings":"qEAIA,MAAM,EAAmC,CACvC,YAAa,SAAY,IAAA,GACzB,cAAe,SAAY,IAAA,GAC3B,YAAa,SAAY,IAAA,GACzB,MAAO,SAAY,IAAA,GACnB,SAAU,SAAY,IAAA,GACvB,CAGD,SAAgB,EAA8B,EAAwB,CACpE,EAAkB,MAAU,IAAA,GAAW,EAAmB,CAAE,iBAAkB,GAAO,CAAC"}
1
+ {"version":3,"file":"extension.mjs","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { planModeExtension } from '../../services/planMode.ts';\n\nconst SESSION_SHUTDOWN_EVENT = 'session_shutdown';\n\n/** Install Plan state and external resources into one package-local Cordis root. */\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 cordis = new Context();\n let disposal: Promise<void> | undefined;\n const dispose = (): Promise<void> => {\n disposal ??= cordis.fiber.dispose();\n return disposal;\n };\n\n try {\n installPlanRuntime(cordis, pi);\n } catch (error) {\n await dispose();\n throw error;\n }\n\n pi.on(SESSION_SHUTDOWN_EVENT, dispose);\n}\n\nexport default activatePlanExtension;\n"],"mappings":"8GAOA,SAAgB,EAAmB,EAAiB,EAAwB,CAC1E,EAAkB,EAAQ,EAAG,CAI/B,eAAsB,EAAsB,EAAiC,CAC3E,IAAM,EAAS,IAAI,EACf,EACE,OACJ,IAAa,EAAO,MAAM,SAAS,CAC5B,GAGT,GAAI,CACF,EAAmB,EAAQ,EAAG,OACvB,EAAO,CAEd,MADA,MAAM,GAAS,CACT,EAGR,EAAG,GAAG,mBAAwB,EAAQ"}
@@ -1,2 +1 @@
1
- var e=require(`../adapters/pi/extension.cjs`).activateStandardPlanExtension;module.exports=e;
2
- //# sourceMappingURL=pi.cjs.map
1
+ const e=require(`../adapters/pi/extension.cjs`);module.exports=e;
@@ -1,2 +1,2 @@
1
- import { activateStandardPlanExtension } from "../adapters/pi/extension.cjs";
2
- export = activateStandardPlanExtension;
1
+ import { activatePlanExtension } from "../adapters/pi/extension.cjs";
2
+ export = activatePlanExtension;
@@ -1,2 +1,2 @@
1
- import { activateStandardPlanExtension } from "../adapters/pi/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"../adapters/pi/extension.mjs";var t=e;export{t as default};
2
- //# sourceMappingURL=pi.mjs.map
1
+ import e from"../adapters/pi/extension.mjs";export{e as default};
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./services/plan/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;
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;
@@ -1,2 +1,2 @@
1
- import { FABLE_PLAN_MODEL, FABLE_PLAN_PROFILE, FABLE_PLAN_REQUESTER, FABLE_PLAN_RUNTIME, FABLE_PROVIDER_SOURCE, FableFlowOptions, FablePlanBroker, FablePlanFinding, FablePlanFlow, FablePlanPacket, FablePlanRequest, FablePlanResult, FablePlanStage, FablePlanStatus, FableStage, MAX_FABLE_ARRAY_ITEMS, MAX_FABLE_PACKET_BYTES, MAX_FABLE_TEXT_BYTES, containsSuspectedCredential, createFablePlanFlow, sanitizeFablePacket } from "./services/plan/fableFlow.cjs";
1
+ import { FABLE_PLAN_MODEL, FABLE_PLAN_PROFILE, FABLE_PLAN_REQUESTER, FABLE_PLAN_RUNTIME, FABLE_PROVIDER_SOURCE, FableFlowOptions, FablePlanBroker, FablePlanFinding, FablePlanFlow, FablePlanPacket, FablePlanRequest, FablePlanResult, FablePlanStage, FablePlanStatus, FableStage, MAX_FABLE_ARRAY_ITEMS, MAX_FABLE_PACKET_BYTES, MAX_FABLE_TEXT_BYTES, containsSuspectedCredential, createFablePlanFlow, sanitizeFablePacket } from "./services/fableFlow.cjs";
2
2
  export { FABLE_PLAN_MODEL, FABLE_PLAN_PROFILE, FABLE_PLAN_REQUESTER, FABLE_PLAN_RUNTIME, FABLE_PROVIDER_SOURCE, FableFlowOptions, FablePlanBroker, FablePlanFinding, FablePlanFlow, FablePlanPacket, FablePlanRequest, FablePlanResult, FablePlanStage, FablePlanStatus, FableStage, MAX_FABLE_ARRAY_ITEMS, MAX_FABLE_PACKET_BYTES, MAX_FABLE_TEXT_BYTES, containsSuspectedCredential, createFablePlanFlow, sanitizeFablePacket };
@@ -1,2 +1,2 @@
1
- import { FABLE_PLAN_MODEL, FABLE_PLAN_PROFILE, FABLE_PLAN_REQUESTER, FABLE_PLAN_RUNTIME, FABLE_PROVIDER_SOURCE, FableFlowOptions, FablePlanBroker, FablePlanFinding, FablePlanFlow, FablePlanPacket, FablePlanRequest, FablePlanResult, FablePlanStage, FablePlanStatus, FableStage, MAX_FABLE_ARRAY_ITEMS, MAX_FABLE_PACKET_BYTES, MAX_FABLE_TEXT_BYTES, containsSuspectedCredential, createFablePlanFlow, sanitizeFablePacket } from "./services/plan/fableFlow.mjs";
1
+ import { FABLE_PLAN_MODEL, FABLE_PLAN_PROFILE, FABLE_PLAN_REQUESTER, FABLE_PLAN_RUNTIME, FABLE_PROVIDER_SOURCE, FableFlowOptions, FablePlanBroker, FablePlanFinding, FablePlanFlow, FablePlanPacket, FablePlanRequest, FablePlanResult, FablePlanStage, FablePlanStatus, FableStage, MAX_FABLE_ARRAY_ITEMS, MAX_FABLE_PACKET_BYTES, MAX_FABLE_TEXT_BYTES, containsSuspectedCredential, createFablePlanFlow, sanitizeFablePacket } from "./services/fableFlow.mjs";
2
2
  export { FABLE_PLAN_MODEL, FABLE_PLAN_PROFILE, FABLE_PLAN_REQUESTER, FABLE_PLAN_RUNTIME, FABLE_PROVIDER_SOURCE, FableFlowOptions, FablePlanBroker, FablePlanFinding, FablePlanFlow, FablePlanPacket, FablePlanRequest, FablePlanResult, FablePlanStage, FablePlanStatus, FableStage, MAX_FABLE_ARRAY_ITEMS, MAX_FABLE_PACKET_BYTES, MAX_FABLE_TEXT_BYTES, containsSuspectedCredential, createFablePlanFlow, sanitizeFablePacket };
@@ -1 +1 @@
1
- import{FABLE_PLAN_MODEL as e,FABLE_PLAN_PROFILE as t,FABLE_PLAN_REQUESTER as n,FABLE_PLAN_RUNTIME as r,FABLE_PROVIDER_SOURCE as i,MAX_FABLE_ARRAY_ITEMS as a,MAX_FABLE_PACKET_BYTES as o,MAX_FABLE_TEXT_BYTES as s,containsSuspectedCredential as c,createFablePlanFlow as l,sanitizeFablePacket as u}from"./services/plan/fableFlow.mjs";export{e as FABLE_PLAN_MODEL,t as FABLE_PLAN_PROFILE,n as FABLE_PLAN_REQUESTER,r as FABLE_PLAN_RUNTIME,i as FABLE_PROVIDER_SOURCE,a as MAX_FABLE_ARRAY_ITEMS,o as MAX_FABLE_PACKET_BYTES,s as MAX_FABLE_TEXT_BYTES,c as containsSuspectedCredential,l as createFablePlanFlow,u as sanitizeFablePacket};
1
+ import{FABLE_PLAN_MODEL as e,FABLE_PLAN_PROFILE as t,FABLE_PLAN_REQUESTER as n,FABLE_PLAN_RUNTIME as r,FABLE_PROVIDER_SOURCE as i,MAX_FABLE_ARRAY_ITEMS as a,MAX_FABLE_PACKET_BYTES as o,MAX_FABLE_TEXT_BYTES as s,containsSuspectedCredential as c,createFablePlanFlow as l,sanitizeFablePacket as u}from"./services/fableFlow.mjs";export{e as FABLE_PLAN_MODEL,t as FABLE_PLAN_PROFILE,n as FABLE_PLAN_REQUESTER,r as FABLE_PLAN_RUNTIME,i as FABLE_PROVIDER_SOURCE,a as MAX_FABLE_ARRAY_ITEMS,o as MAX_FABLE_PACKET_BYTES,s as MAX_FABLE_TEXT_BYTES,c as containsSuspectedCredential,l as createFablePlanFlow,u as sanitizeFablePacket};
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./_virtual/_rolldown/runtime.cjs`);const e=require(`./schemas/plan/config.cjs`),t=require(`./services/plan/fableFlow.cjs`),n=require(`./services/plan/prompts.cjs`),r=require(`./services/plan/planMode.cjs`);let i=require(`@agimon-ai/doompi-config`);exports.FABLE_PLAN_MODEL=t.FABLE_PLAN_MODEL,exports.FABLE_PLAN_PROFILE=t.FABLE_PLAN_PROFILE,exports.FABLE_PLAN_REQUESTER=t.FABLE_PLAN_REQUESTER,exports.FABLE_PLAN_RUNTIME=t.FABLE_PLAN_RUNTIME,exports.FABLE_PROVIDER_SOURCE=t.FABLE_PROVIDER_SOURCE,exports.MAX_FABLE_ARRAY_ITEMS=t.MAX_FABLE_ARRAY_ITEMS,exports.MAX_FABLE_PACKET_BYTES=t.MAX_FABLE_PACKET_BYTES,exports.MAX_FABLE_TEXT_BYTES=t.MAX_FABLE_TEXT_BYTES,exports.WRITE_PLAN_TIMEOUT_MS=r.WRITE_PLAN_TIMEOUT_MS,exports.buildDebugPlanningPrompt=n.buildDebugPlanningPrompt,exports.buildFablePlanningPrompt=n.buildFablePlanningPrompt,exports.buildFlavorPlanningPrompt=n.buildFlavorPlanningPrompt,exports.buildNormalPlanningPrompt=n.buildNormalPlanningPrompt,exports.configurePlanningSubagentInput=r.configurePlanningSubagentInput,exports.configurePlanningTaskInput=r.configurePlanningTaskInput,exports.constrainSubagentInput=r.constrainSubagentInput,exports.containsSuspectedCredential=t.containsSuspectedCredential,exports.createFablePlanFlow=t.createFablePlanFlow,exports.createPlanIdentifier=r.createPlanIdentifier,exports.getHarnessState=i.getHarnessState,exports.globalDoomConfigPath=i.globalDoomConfigPath,exports.isBlockedSubagentManagementAction=r.isBlockedSubagentManagementAction,exports.loadDoomConfig=e.loadDoomConfig,exports.loadHarnessState=i.loadHarnessState,exports.loadPlanningModeConfig=r.loadPlanningModeConfig,exports.mergeDoomConfigs=e.mergeDoomConfigs,exports.parseDebugEvidencePacket=r.parseDebugEvidencePacket,exports.parseDoomConfig=e.parseDoomConfig,exports.parsePersistedPlanState=r.parsePersistedPlanState,exports.parsePlanningModeConfig=i.parsePlanningModeConfig,exports.planModeExtension=r.planModeExtension,exports.planModeTools=r.planModeTools,exports.planSessionIdentifier=r.planSessionIdentifier,exports.planTitleSlug=r.planTitleSlug,exports.planningSubagentModel=r.planningSubagentModel,exports.repositoryDoomConfigPath=i.repositoryDoomConfigPath,exports.resolvePlanningPlansDirectory=i.resolvePlanningPlansDirectory,exports.sanitizeFablePacket=t.sanitizeFablePacket,exports.visiblePlanForToolCall=r.visiblePlanForToolCall;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./_virtual/_rolldown/runtime.cjs`);const e=require(`./schemas/plan/config.cjs`),t=require(`./services/fableFlow.cjs`),n=require(`./services/prompts.cjs`),r=require(`./services/planMode.cjs`);let i=require(`@agimon-ai/doompi-config`);exports.FABLE_PLAN_MODEL=t.FABLE_PLAN_MODEL,exports.FABLE_PLAN_PROFILE=t.FABLE_PLAN_PROFILE,exports.FABLE_PLAN_REQUESTER=t.FABLE_PLAN_REQUESTER,exports.FABLE_PLAN_RUNTIME=t.FABLE_PLAN_RUNTIME,exports.FABLE_PROVIDER_SOURCE=t.FABLE_PROVIDER_SOURCE,exports.MAX_FABLE_ARRAY_ITEMS=t.MAX_FABLE_ARRAY_ITEMS,exports.MAX_FABLE_PACKET_BYTES=t.MAX_FABLE_PACKET_BYTES,exports.MAX_FABLE_TEXT_BYTES=t.MAX_FABLE_TEXT_BYTES,exports.WRITE_PLAN_TIMEOUT_MS=r.WRITE_PLAN_TIMEOUT_MS,exports.buildDebugPlanningPrompt=n.buildDebugPlanningPrompt,exports.buildFablePlanningPrompt=n.buildFablePlanningPrompt,exports.buildFlavorPlanningPrompt=n.buildFlavorPlanningPrompt,exports.buildNormalPlanningPrompt=n.buildNormalPlanningPrompt,exports.configurePlanningSubagentInput=r.configurePlanningSubagentInput,exports.configurePlanningTaskInput=r.configurePlanningTaskInput,exports.constrainSubagentInput=r.constrainSubagentInput,exports.containsSuspectedCredential=t.containsSuspectedCredential,exports.createFablePlanFlow=t.createFablePlanFlow,exports.createPlanIdentifier=r.createPlanIdentifier,exports.getHarnessState=i.getHarnessState,exports.globalDoomConfigPath=i.globalDoomConfigPath,exports.isBlockedSubagentManagementAction=r.isBlockedSubagentManagementAction,exports.loadDoomConfig=e.loadDoomConfig,exports.loadHarnessState=i.loadHarnessState,exports.loadPlanningModeConfig=r.loadPlanningModeConfig,exports.mergeDoomConfigs=e.mergeDoomConfigs,exports.parseDebugEvidencePacket=r.parseDebugEvidencePacket,exports.parseDoomConfig=e.parseDoomConfig,exports.parsePersistedPlanState=r.parsePersistedPlanState,exports.parsePlanningModeConfig=i.parsePlanningModeConfig,exports.planModeExtension=r.planModeExtension,exports.planModeTools=r.planModeTools,exports.planSessionIdentifier=r.planSessionIdentifier,exports.planTitleSlug=r.planTitleSlug,exports.planningSubagentModel=r.planningSubagentModel,exports.repositoryDoomConfigPath=i.repositoryDoomConfigPath,exports.resolvePlanningPlansDirectory=i.resolvePlanningPlansDirectory,exports.sanitizeFablePacket=t.sanitizeFablePacket,exports.visiblePlanForToolCall=r.visiblePlanForToolCall;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { DoomConfig, PlanningAgentConfig, PlanningModeConfig, PlanningThinkingLevel, getHarnessState, globalDoomConfigPath, loadDoomConfig, loadHarnessState, mergeDoomConfigs, parseDoomConfig, parsePlanningModeConfig, repositoryDoomConfigPath, resolvePlanningPlansDirectory } from "./schemas/plan/config.cjs";
2
- import { FABLE_PLAN_MODEL, FABLE_PLAN_PROFILE, FABLE_PLAN_REQUESTER, FABLE_PLAN_RUNTIME, FABLE_PROVIDER_SOURCE, FableFlowOptions, FablePlanBroker, FablePlanFinding, FablePlanFlow, FablePlanPacket, FablePlanRequest, FablePlanResult, FablePlanStage, FablePlanStatus, FableStage, MAX_FABLE_ARRAY_ITEMS, MAX_FABLE_PACKET_BYTES, MAX_FABLE_TEXT_BYTES, containsSuspectedCredential, createFablePlanFlow, sanitizeFablePacket } from "./services/plan/fableFlow.cjs";
3
- import { DebugEvidencePacket, PlanningFlavor, buildDebugPlanningPrompt, buildFablePlanningPrompt, buildFlavorPlanningPrompt, buildNormalPlanningPrompt } from "./services/plan/prompts.cjs";
4
- import { ModelIdentity, PlanModeExtensionOptions, PlanSnapshot, PlanningConfigProvider, WRITE_PLAN_TIMEOUT_MS, configurePlanningSubagentInput, configurePlanningTaskInput, constrainSubagentInput, createPlanIdentifier, isBlockedSubagentManagementAction, loadPlanningModeConfig, parseDebugEvidencePacket, parsePersistedPlanState, planModeExtension, planModeTools, planSessionIdentifier, planTitleSlug, planningSubagentModel, visiblePlanForToolCall } from "./services/plan/planMode.cjs";
2
+ import { FABLE_PLAN_MODEL, FABLE_PLAN_PROFILE, FABLE_PLAN_REQUESTER, FABLE_PLAN_RUNTIME, FABLE_PROVIDER_SOURCE, FableFlowOptions, FablePlanBroker, FablePlanFinding, FablePlanFlow, FablePlanPacket, FablePlanRequest, FablePlanResult, FablePlanStage, FablePlanStatus, FableStage, MAX_FABLE_ARRAY_ITEMS, MAX_FABLE_PACKET_BYTES, MAX_FABLE_TEXT_BYTES, containsSuspectedCredential, createFablePlanFlow, sanitizeFablePacket } from "./services/fableFlow.cjs";
3
+ import { DebugEvidencePacket, PlanningFlavor, buildDebugPlanningPrompt, buildFablePlanningPrompt, buildFlavorPlanningPrompt, buildNormalPlanningPrompt } from "./services/prompts.cjs";
4
+ import { ModelIdentity, PlanModeExtensionOptions, PlanSnapshot, PlanningConfigProvider, WRITE_PLAN_TIMEOUT_MS, configurePlanningSubagentInput, configurePlanningTaskInput, constrainSubagentInput, createPlanIdentifier, isBlockedSubagentManagementAction, loadPlanningModeConfig, parseDebugEvidencePacket, parsePersistedPlanState, planModeExtension, planModeTools, planSessionIdentifier, planTitleSlug, planningSubagentModel, visiblePlanForToolCall } from "./services/planMode.cjs";
5
5
  export { DebugEvidencePacket, DoomConfig, FABLE_PLAN_MODEL, FABLE_PLAN_PROFILE, FABLE_PLAN_REQUESTER, FABLE_PLAN_RUNTIME, FABLE_PROVIDER_SOURCE, FableFlowOptions, FablePlanBroker, FablePlanFinding, FablePlanFlow, FablePlanPacket, FablePlanRequest, FablePlanResult, FablePlanStage, FablePlanStatus, FableStage, MAX_FABLE_ARRAY_ITEMS, MAX_FABLE_PACKET_BYTES, MAX_FABLE_TEXT_BYTES, ModelIdentity, PlanModeExtensionOptions, PlanSnapshot, PlanningAgentConfig, PlanningConfigProvider, PlanningFlavor, PlanningModeConfig, PlanningThinkingLevel, WRITE_PLAN_TIMEOUT_MS, buildDebugPlanningPrompt, buildFablePlanningPrompt, buildFlavorPlanningPrompt, buildNormalPlanningPrompt, configurePlanningSubagentInput, configurePlanningTaskInput, constrainSubagentInput, containsSuspectedCredential, createFablePlanFlow, createPlanIdentifier, getHarnessState, globalDoomConfigPath, isBlockedSubagentManagementAction, loadDoomConfig, loadHarnessState, loadPlanningModeConfig, mergeDoomConfigs, parseDebugEvidencePacket, parseDoomConfig, parsePersistedPlanState, parsePlanningModeConfig, planModeExtension, planModeTools, planSessionIdentifier, planTitleSlug, planningSubagentModel, repositoryDoomConfigPath, resolvePlanningPlansDirectory, sanitizeFablePacket, visiblePlanForToolCall };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { DoomConfig, PlanningAgentConfig, PlanningModeConfig, PlanningThinkingLevel, getHarnessState, globalDoomConfigPath, loadDoomConfig, loadHarnessState, mergeDoomConfigs, parseDoomConfig, parsePlanningModeConfig, repositoryDoomConfigPath, resolvePlanningPlansDirectory } from "./schemas/plan/config.mjs";
2
- import { FABLE_PLAN_MODEL, FABLE_PLAN_PROFILE, FABLE_PLAN_REQUESTER, FABLE_PLAN_RUNTIME, FABLE_PROVIDER_SOURCE, FableFlowOptions, FablePlanBroker, FablePlanFinding, FablePlanFlow, FablePlanPacket, FablePlanRequest, FablePlanResult, FablePlanStage, FablePlanStatus, FableStage, MAX_FABLE_ARRAY_ITEMS, MAX_FABLE_PACKET_BYTES, MAX_FABLE_TEXT_BYTES, containsSuspectedCredential, createFablePlanFlow, sanitizeFablePacket } from "./services/plan/fableFlow.mjs";
3
- import { DebugEvidencePacket, PlanningFlavor, buildDebugPlanningPrompt, buildFablePlanningPrompt, buildFlavorPlanningPrompt, buildNormalPlanningPrompt } from "./services/plan/prompts.mjs";
4
- import { ModelIdentity, PlanModeExtensionOptions, PlanSnapshot, PlanningConfigProvider, WRITE_PLAN_TIMEOUT_MS, configurePlanningSubagentInput, configurePlanningTaskInput, constrainSubagentInput, createPlanIdentifier, isBlockedSubagentManagementAction, loadPlanningModeConfig, parseDebugEvidencePacket, parsePersistedPlanState, planModeExtension, planModeTools, planSessionIdentifier, planTitleSlug, planningSubagentModel, visiblePlanForToolCall } from "./services/plan/planMode.mjs";
2
+ import { FABLE_PLAN_MODEL, FABLE_PLAN_PROFILE, FABLE_PLAN_REQUESTER, FABLE_PLAN_RUNTIME, FABLE_PROVIDER_SOURCE, FableFlowOptions, FablePlanBroker, FablePlanFinding, FablePlanFlow, FablePlanPacket, FablePlanRequest, FablePlanResult, FablePlanStage, FablePlanStatus, FableStage, MAX_FABLE_ARRAY_ITEMS, MAX_FABLE_PACKET_BYTES, MAX_FABLE_TEXT_BYTES, containsSuspectedCredential, createFablePlanFlow, sanitizeFablePacket } from "./services/fableFlow.mjs";
3
+ import { DebugEvidencePacket, PlanningFlavor, buildDebugPlanningPrompt, buildFablePlanningPrompt, buildFlavorPlanningPrompt, buildNormalPlanningPrompt } from "./services/prompts.mjs";
4
+ import { ModelIdentity, PlanModeExtensionOptions, PlanSnapshot, PlanningConfigProvider, WRITE_PLAN_TIMEOUT_MS, configurePlanningSubagentInput, configurePlanningTaskInput, constrainSubagentInput, createPlanIdentifier, isBlockedSubagentManagementAction, loadPlanningModeConfig, parseDebugEvidencePacket, parsePersistedPlanState, planModeExtension, planModeTools, planSessionIdentifier, planTitleSlug, planningSubagentModel, visiblePlanForToolCall } from "./services/planMode.mjs";
5
5
  export { DebugEvidencePacket, DoomConfig, FABLE_PLAN_MODEL, FABLE_PLAN_PROFILE, FABLE_PLAN_REQUESTER, FABLE_PLAN_RUNTIME, FABLE_PROVIDER_SOURCE, FableFlowOptions, FablePlanBroker, FablePlanFinding, FablePlanFlow, FablePlanPacket, FablePlanRequest, FablePlanResult, FablePlanStage, FablePlanStatus, FableStage, MAX_FABLE_ARRAY_ITEMS, MAX_FABLE_PACKET_BYTES, MAX_FABLE_TEXT_BYTES, ModelIdentity, PlanModeExtensionOptions, PlanSnapshot, PlanningAgentConfig, PlanningConfigProvider, PlanningFlavor, PlanningModeConfig, PlanningThinkingLevel, WRITE_PLAN_TIMEOUT_MS, buildDebugPlanningPrompt, buildFablePlanningPrompt, buildFlavorPlanningPrompt, buildNormalPlanningPrompt, configurePlanningSubagentInput, configurePlanningTaskInput, constrainSubagentInput, containsSuspectedCredential, createFablePlanFlow, createPlanIdentifier, getHarnessState, globalDoomConfigPath, isBlockedSubagentManagementAction, loadDoomConfig, loadHarnessState, loadPlanningModeConfig, mergeDoomConfigs, parseDebugEvidencePacket, parseDoomConfig, parsePersistedPlanState, parsePlanningModeConfig, planModeExtension, planModeTools, planSessionIdentifier, planTitleSlug, planningSubagentModel, repositoryDoomConfigPath, resolvePlanningPlansDirectory, sanitizeFablePacket, visiblePlanForToolCall };
package/dist/index.mjs CHANGED
@@ -1 +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"./schemas/plan/config.mjs";import{FABLE_PLAN_MODEL as l,FABLE_PLAN_PROFILE as u,FABLE_PLAN_REQUESTER as d,FABLE_PLAN_RUNTIME as f,FABLE_PROVIDER_SOURCE as p,MAX_FABLE_ARRAY_ITEMS as m,MAX_FABLE_PACKET_BYTES as h,MAX_FABLE_TEXT_BYTES as g,containsSuspectedCredential as _,createFablePlanFlow as v,sanitizeFablePacket as y}from"./services/plan/fableFlow.mjs";import{buildDebugPlanningPrompt as b,buildFablePlanningPrompt as x,buildFlavorPlanningPrompt as S,buildNormalPlanningPrompt as C}from"./services/plan/prompts.mjs";import{WRITE_PLAN_TIMEOUT_MS as w,configurePlanningSubagentInput as T,configurePlanningTaskInput as E,constrainSubagentInput as D,createPlanIdentifier as O,isBlockedSubagentManagementAction as k,loadPlanningModeConfig as A,parseDebugEvidencePacket as j,parsePersistedPlanState as M,planModeExtension as N,planModeTools as P,planSessionIdentifier as F,planTitleSlug as I,planningSubagentModel as L,visiblePlanForToolCall as R}from"./services/plan/planMode.mjs";export{l as FABLE_PLAN_MODEL,u as FABLE_PLAN_PROFILE,d as FABLE_PLAN_REQUESTER,f as FABLE_PLAN_RUNTIME,p as FABLE_PROVIDER_SOURCE,m as MAX_FABLE_ARRAY_ITEMS,h as MAX_FABLE_PACKET_BYTES,g as MAX_FABLE_TEXT_BYTES,w as WRITE_PLAN_TIMEOUT_MS,b as buildDebugPlanningPrompt,x as buildFablePlanningPrompt,S as buildFlavorPlanningPrompt,C as buildNormalPlanningPrompt,T as configurePlanningSubagentInput,E as configurePlanningTaskInput,D as constrainSubagentInput,_ as containsSuspectedCredential,v as createFablePlanFlow,O as createPlanIdentifier,e as getHarnessState,t as globalDoomConfigPath,k as isBlockedSubagentManagementAction,n as loadDoomConfig,r as loadHarnessState,A as loadPlanningModeConfig,i as mergeDoomConfigs,j as parseDebugEvidencePacket,a as parseDoomConfig,M as parsePersistedPlanState,o as parsePlanningModeConfig,N as planModeExtension,P as planModeTools,F as planSessionIdentifier,I as planTitleSlug,L as planningSubagentModel,s as repositoryDoomConfigPath,c as resolvePlanningPlansDirectory,y as sanitizeFablePacket,R as visiblePlanForToolCall};
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";import{FABLE_PLAN_MODEL as l,FABLE_PLAN_PROFILE as u,FABLE_PLAN_REQUESTER as d,FABLE_PLAN_RUNTIME as f,FABLE_PROVIDER_SOURCE as p,MAX_FABLE_ARRAY_ITEMS as m,MAX_FABLE_PACKET_BYTES as h,MAX_FABLE_TEXT_BYTES as g,containsSuspectedCredential as _,createFablePlanFlow as v,sanitizeFablePacket as y}from"./services/fableFlow.mjs";import{buildDebugPlanningPrompt as b,buildFablePlanningPrompt as x,buildFlavorPlanningPrompt as S,buildNormalPlanningPrompt as C}from"./services/prompts.mjs";import{WRITE_PLAN_TIMEOUT_MS as w,configurePlanningSubagentInput as T,configurePlanningTaskInput as E,constrainSubagentInput as D,createPlanIdentifier as O,isBlockedSubagentManagementAction as k,loadPlanningModeConfig as A,parseDebugEvidencePacket as j,parsePersistedPlanState as M,planModeExtension as N,planModeTools as P,planSessionIdentifier as F,planTitleSlug as I,planningSubagentModel as L,visiblePlanForToolCall as R}from"./services/planMode.mjs";export{l as FABLE_PLAN_MODEL,u as FABLE_PLAN_PROFILE,d as FABLE_PLAN_REQUESTER,f as FABLE_PLAN_RUNTIME,p as FABLE_PROVIDER_SOURCE,m as MAX_FABLE_ARRAY_ITEMS,h as MAX_FABLE_PACKET_BYTES,g as MAX_FABLE_TEXT_BYTES,w as WRITE_PLAN_TIMEOUT_MS,b as buildDebugPlanningPrompt,x as buildFablePlanningPrompt,S as buildFlavorPlanningPrompt,C as buildNormalPlanningPrompt,T as configurePlanningSubagentInput,E as configurePlanningTaskInput,D as constrainSubagentInput,_ as containsSuspectedCredential,v as createFablePlanFlow,O as createPlanIdentifier,e as getHarnessState,t as globalDoomConfigPath,k as isBlockedSubagentManagementAction,n as loadDoomConfig,r as loadHarnessState,A as loadPlanningModeConfig,i as mergeDoomConfigs,j as parseDebugEvidencePacket,a as parseDoomConfig,M as parsePersistedPlanState,o as parsePlanningModeConfig,N as planModeExtension,P as planModeTools,F as planSessionIdentifier,I as planTitleSlug,L as planningSubagentModel,s as repositoryDoomConfigPath,c as resolvePlanningPlansDirectory,y as sanitizeFablePacket,R as visiblePlanForToolCall};
package/dist/planMode.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./services/plan/planMode.cjs`);exports.WRITE_PLAN_TIMEOUT_MS=e.WRITE_PLAN_TIMEOUT_MS,exports.configurePlanningSubagentInput=e.configurePlanningSubagentInput,exports.configurePlanningTaskInput=e.configurePlanningTaskInput,exports.constrainSubagentInput=e.constrainSubagentInput,exports.createPlanIdentifier=e.createPlanIdentifier,exports.isBlockedSubagentManagementAction=e.isBlockedSubagentManagementAction,exports.loadPlanningModeConfig=e.loadPlanningModeConfig,exports.parseDebugEvidencePacket=e.parseDebugEvidencePacket,exports.parsePersistedPlanState=e.parsePersistedPlanState,exports.planModeExtension=e.planModeExtension,exports.planModeTools=e.planModeTools,exports.planSessionIdentifier=e.planSessionIdentifier,exports.planTitleSlug=e.planTitleSlug,exports.planningSubagentModel=e.planningSubagentModel,exports.visiblePlanForToolCall=e.visiblePlanForToolCall;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./services/planMode.cjs`);exports.WRITE_PLAN_TIMEOUT_MS=e.WRITE_PLAN_TIMEOUT_MS,exports.configurePlanningSubagentInput=e.configurePlanningSubagentInput,exports.configurePlanningTaskInput=e.configurePlanningTaskInput,exports.constrainSubagentInput=e.constrainSubagentInput,exports.createPlanIdentifier=e.createPlanIdentifier,exports.isBlockedSubagentManagementAction=e.isBlockedSubagentManagementAction,exports.loadPlanningModeConfig=e.loadPlanningModeConfig,exports.parseDebugEvidencePacket=e.parseDebugEvidencePacket,exports.parsePersistedPlanState=e.parsePersistedPlanState,exports.planModeExtension=e.planModeExtension,exports.planModeTools=e.planModeTools,exports.planSessionIdentifier=e.planSessionIdentifier,exports.planTitleSlug=e.planTitleSlug,exports.planningSubagentModel=e.planningSubagentModel,exports.visiblePlanForToolCall=e.visiblePlanForToolCall;
@@ -1,3 +1,3 @@
1
- import { PlanningFlavor } from "./services/plan/prompts.cjs";
2
- import { ModelIdentity, PlanModeExtensionOptions, PlanSnapshot, PlanningConfigProvider, WRITE_PLAN_TIMEOUT_MS, configurePlanningSubagentInput, configurePlanningTaskInput, constrainSubagentInput, createPlanIdentifier, isBlockedSubagentManagementAction, loadPlanningModeConfig, parseDebugEvidencePacket, parsePersistedPlanState, planModeExtension, planModeTools, planSessionIdentifier, planTitleSlug, planningSubagentModel, visiblePlanForToolCall } from "./services/plan/planMode.cjs";
1
+ import { PlanningFlavor } from "./services/prompts.cjs";
2
+ import { ModelIdentity, PlanModeExtensionOptions, PlanSnapshot, PlanningConfigProvider, WRITE_PLAN_TIMEOUT_MS, configurePlanningSubagentInput, configurePlanningTaskInput, constrainSubagentInput, createPlanIdentifier, isBlockedSubagentManagementAction, loadPlanningModeConfig, parseDebugEvidencePacket, parsePersistedPlanState, planModeExtension, planModeTools, planSessionIdentifier, planTitleSlug, planningSubagentModel, visiblePlanForToolCall } from "./services/planMode.cjs";
3
3
  export { ModelIdentity, PlanModeExtensionOptions, PlanSnapshot, PlanningConfigProvider, PlanningFlavor, WRITE_PLAN_TIMEOUT_MS, configurePlanningSubagentInput, configurePlanningTaskInput, constrainSubagentInput, createPlanIdentifier, isBlockedSubagentManagementAction, loadPlanningModeConfig, parseDebugEvidencePacket, parsePersistedPlanState, planModeExtension, planModeTools, planSessionIdentifier, planTitleSlug, planningSubagentModel, visiblePlanForToolCall };
@@ -1,3 +1,3 @@
1
- import { PlanningFlavor } from "./services/plan/prompts.mjs";
2
- import { ModelIdentity, PlanModeExtensionOptions, PlanSnapshot, PlanningConfigProvider, WRITE_PLAN_TIMEOUT_MS, configurePlanningSubagentInput, configurePlanningTaskInput, constrainSubagentInput, createPlanIdentifier, isBlockedSubagentManagementAction, loadPlanningModeConfig, parseDebugEvidencePacket, parsePersistedPlanState, planModeExtension, planModeTools, planSessionIdentifier, planTitleSlug, planningSubagentModel, visiblePlanForToolCall } from "./services/plan/planMode.mjs";
1
+ import { PlanningFlavor } from "./services/prompts.mjs";
2
+ import { ModelIdentity, PlanModeExtensionOptions, PlanSnapshot, PlanningConfigProvider, WRITE_PLAN_TIMEOUT_MS, configurePlanningSubagentInput, configurePlanningTaskInput, constrainSubagentInput, createPlanIdentifier, isBlockedSubagentManagementAction, loadPlanningModeConfig, parseDebugEvidencePacket, parsePersistedPlanState, planModeExtension, planModeTools, planSessionIdentifier, planTitleSlug, planningSubagentModel, visiblePlanForToolCall } from "./services/planMode.mjs";
3
3
  export { ModelIdentity, PlanModeExtensionOptions, PlanSnapshot, PlanningConfigProvider, PlanningFlavor, WRITE_PLAN_TIMEOUT_MS, configurePlanningSubagentInput, configurePlanningTaskInput, constrainSubagentInput, createPlanIdentifier, isBlockedSubagentManagementAction, loadPlanningModeConfig, parseDebugEvidencePacket, parsePersistedPlanState, planModeExtension, planModeTools, planSessionIdentifier, planTitleSlug, planningSubagentModel, visiblePlanForToolCall };
package/dist/planMode.mjs CHANGED
@@ -1 +1 @@
1
- import{WRITE_PLAN_TIMEOUT_MS as e,configurePlanningSubagentInput as t,configurePlanningTaskInput as n,constrainSubagentInput as r,createPlanIdentifier as i,isBlockedSubagentManagementAction as a,loadPlanningModeConfig as o,parseDebugEvidencePacket as s,parsePersistedPlanState as c,planModeExtension as l,planModeTools as u,planSessionIdentifier as d,planTitleSlug as f,planningSubagentModel as p,visiblePlanForToolCall as m}from"./services/plan/planMode.mjs";export{e as WRITE_PLAN_TIMEOUT_MS,t as configurePlanningSubagentInput,n as configurePlanningTaskInput,r as constrainSubagentInput,i as createPlanIdentifier,a as isBlockedSubagentManagementAction,o as loadPlanningModeConfig,s as parseDebugEvidencePacket,c as parsePersistedPlanState,l as planModeExtension,u as planModeTools,d as planSessionIdentifier,f as planTitleSlug,p as planningSubagentModel,m as visiblePlanForToolCall};
1
+ import{WRITE_PLAN_TIMEOUT_MS as e,configurePlanningSubagentInput as t,configurePlanningTaskInput as n,constrainSubagentInput as r,createPlanIdentifier as i,isBlockedSubagentManagementAction as a,loadPlanningModeConfig as o,parseDebugEvidencePacket as s,parsePersistedPlanState as c,planModeExtension as l,planModeTools as u,planSessionIdentifier as d,planTitleSlug as f,planningSubagentModel as p,visiblePlanForToolCall as m}from"./services/planMode.mjs";export{e as WRITE_PLAN_TIMEOUT_MS,t as configurePlanningSubagentInput,n as configurePlanningTaskInput,r as constrainSubagentInput,i as createPlanIdentifier,a as isBlockedSubagentManagementAction,o as loadPlanningModeConfig,s as parseDebugEvidencePacket,c as parsePersistedPlanState,l as planModeExtension,u as planModeTools,d as planSessionIdentifier,f as planTitleSlug,p as planningSubagentModel,m as visiblePlanForToolCall};
package/dist/prompts.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./services/plan/prompts.cjs`);exports.buildDebugPlanningPrompt=e.buildDebugPlanningPrompt,exports.buildFablePlanningPrompt=e.buildFablePlanningPrompt,exports.buildFlavorPlanningPrompt=e.buildFlavorPlanningPrompt,exports.buildNormalPlanningPrompt=e.buildNormalPlanningPrompt;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./services/prompts.cjs`);exports.buildDebugPlanningPrompt=e.buildDebugPlanningPrompt,exports.buildFablePlanningPrompt=e.buildFablePlanningPrompt,exports.buildFlavorPlanningPrompt=e.buildFlavorPlanningPrompt,exports.buildNormalPlanningPrompt=e.buildNormalPlanningPrompt;
@@ -1,2 +1,2 @@
1
- import { DebugEvidencePacket, PlanningFlavor, buildDebugPlanningPrompt, buildFablePlanningPrompt, buildFlavorPlanningPrompt, buildNormalPlanningPrompt } from "./services/plan/prompts.cjs";
1
+ import { DebugEvidencePacket, PlanningFlavor, buildDebugPlanningPrompt, buildFablePlanningPrompt, buildFlavorPlanningPrompt, buildNormalPlanningPrompt } from "./services/prompts.cjs";
2
2
  export { DebugEvidencePacket, PlanningFlavor, buildDebugPlanningPrompt, buildFablePlanningPrompt, buildFlavorPlanningPrompt, buildNormalPlanningPrompt };
@@ -1,2 +1,2 @@
1
- import { DebugEvidencePacket, PlanningFlavor, buildDebugPlanningPrompt, buildFablePlanningPrompt, buildFlavorPlanningPrompt, buildNormalPlanningPrompt } from "./services/plan/prompts.mjs";
1
+ import { DebugEvidencePacket, PlanningFlavor, buildDebugPlanningPrompt, buildFablePlanningPrompt, buildFlavorPlanningPrompt, buildNormalPlanningPrompt } from "./services/prompts.mjs";
2
2
  export { DebugEvidencePacket, PlanningFlavor, buildDebugPlanningPrompt, buildFablePlanningPrompt, buildFlavorPlanningPrompt, buildNormalPlanningPrompt };
package/dist/prompts.mjs CHANGED
@@ -1 +1 @@
1
- import{buildDebugPlanningPrompt as e,buildFablePlanningPrompt as t,buildFlavorPlanningPrompt as n,buildNormalPlanningPrompt as r}from"./services/plan/prompts.mjs";export{e as buildDebugPlanningPrompt,t as buildFablePlanningPrompt,n as buildFlavorPlanningPrompt,r as buildNormalPlanningPrompt};
1
+ import{buildDebugPlanningPrompt as e,buildFablePlanningPrompt as t,buildFlavorPlanningPrompt as n,buildNormalPlanningPrompt as r}from"./services/prompts.mjs";export{e as buildDebugPlanningPrompt,t as buildFablePlanningPrompt,n as buildFlavorPlanningPrompt,r as buildNormalPlanningPrompt};
@@ -0,0 +1,3 @@
1
+ require(`../_virtual/_rolldown/runtime.cjs`);let e=require(`node:buffer`);const t=`@agimon-ai/doompi-plan`,n=`claude`,r=`fable`,i=`claude/fable-plan-v1`,a=[/(?: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 o(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function s(e){for(let t of e){let e=t.codePointAt(0);if(e!==void 0&&(e<=31||e===127))return!0}return!1}function c(e){return a.some(t=>t.test(e))}function l(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||s(i))throw Error(`${n} exceeds the bounded Fable text limit or contains control characters.`);if(c(i))throw Error(`${n} appears to contain a credential.`);return i}function u(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)=>l(e,`${t}[${n}]`));if(n&&r.length===0)throw Error(`${t} must contain at least one item.`);return r}function d(e,t){if(typeof e!=`string`)throw Error(`${t} must be a string.`);let n=e.trim();if(!n||n.length>512||s(n))throw Error(`${t} is not a safe source path.`);if(c(n))throw Error(`${t} appears to contain a credential.`);return n}function f(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(!o(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:d(e.path,`verifiedFindings[${t}].path`),finding:l(e.finding,`verifiedFindings[${t}].finding`)}})}function p(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 m(t){if(!o(t))throw Error(`Fable packet must be an object.`);p(t,[`goal`,`constraints`,`decisions`,`verifiedFindings`,`inferredFindings`,`unresolvedQuestions`,`currentPlan`],`Fable packet`);let n={goal:u(t.goal,`goal`),constraints:u(t.constraints,`constraints`,!1),decisions:u(t.decisions,`decisions`,!1),verifiedFindings:f(t.verifiedFindings),inferredFindings:u(t.inferredFindings,`inferredFindings`,!1),unresolvedQuestions:u(t.unresolvedQuestions,`unresolvedQuestions`,!1),...t.currentPlan===void 0?{}:{currentPlan:l(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 h(e){return c([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 g(e,t){return{operationId:e,status:`timed_out`,stage:`interrupted`,durationMs:Math.max(0,Date.now()-t),errorCode:`timeout`}}function _(e){let a=e.newOperationId??(()=>crypto.randomUUID()),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=m(c),d=`fable-${a()}`,f=Date.now(),p=new AbortController;o={operationId:d,controller:p,cancelSent:!1},e.onStage?.(`draft`);let _=()=>p.abort(l?.reason);l&&(l.addEventListener(`abort`,_,{once:!0}),l.aborted&&_());let v={requester:t,operationId:d,runtime:n,model:r,profile:i,packet:u},y,b=!1;try{if(!e.broker)return g(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(g(d,f))},e.timeoutMs)}),i=h(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`,_),o=void 0}},cancel:s,isActive:()=>o!==void 0}}exports.FABLE_PLAN_MODEL=r,exports.FABLE_PLAN_PROFILE=i,exports.FABLE_PLAN_REQUESTER=t,exports.FABLE_PLAN_RUNTIME=n,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=c,exports.createFablePlanFlow=_,exports.sanitizeFablePacket=m;
3
+ //# sourceMappingURL=fableFlow.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fableFlow.cjs","names":["Buffer"],"sources":["../../src/services/fableFlow.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\n\nexport const FABLE_PROVIDER_SOURCE = '@agimon-ai/doompi-team';\nexport const FABLE_PLAN_REQUESTER = '@agimon-ai/doompi-plan';\nexport const FABLE_PLAN_RUNTIME = 'claude';\nexport const FABLE_PLAN_MODEL = 'fable';\nexport const FABLE_PLAN_PROFILE = 'claude/fable-plan-v1';\nexport const MAX_FABLE_PACKET_BYTES = 32 * 1024;\nexport const MAX_FABLE_TEXT_BYTES = 4 * 1024;\nexport const MAX_FABLE_ARRAY_ITEMS = 24;\n\nconst SECRET_PATTERNS = [\n /(?:api[_-]?key|access[_-]?token|client[_-]?secret|password|private[_-]?key|authorization|bearer)\\s*[:=]/iu,\n /-----BEGIN [A-Z ]*PRIVATE KEY-----/u,\n /\\bsk-[A-Za-z0-9_-]{16,}\\b/u,\n /\\bgh[pousr]_[A-Za-z0-9_]{16,}\\b/u,\n];\nconst CONTROL_CHARACTER_MAX = 31;\nconst DELETE_CHARACTER = 127;\nconst MAX_SOURCE_PATH_LENGTH = 512;\n\nexport interface FablePlanFinding {\n path: string;\n finding: string;\n}\n\nexport interface FablePlanPacket {\n goal: string[];\n constraints: string[];\n decisions: string[];\n verifiedFindings: FablePlanFinding[];\n inferredFindings: string[];\n unresolvedQuestions: string[];\n currentPlan?: string;\n}\n\nexport type FablePlanStatus = 'completed' | 'failed' | 'timed_out' | 'cancelled' | 'interrupted';\nexport type FablePlanStage = 'draft' | 'review' | 'completed' | 'failed' | 'cancelled' | 'interrupted';\n\nexport interface FablePlanResult {\n operationId: string;\n status: FablePlanStatus;\n stage: FablePlanStage;\n draft?: string;\n review?: string;\n draftRunId?: string;\n reviewRunId?: string;\n durationMs: number;\n errorCode?: string;\n}\n\nexport interface FablePlanRequest {\n requester: typeof FABLE_PLAN_REQUESTER;\n operationId: string;\n runtime: typeof FABLE_PLAN_RUNTIME;\n model: typeof FABLE_PLAN_MODEL;\n profile: typeof FABLE_PLAN_PROFILE;\n packet: FablePlanPacket;\n}\n\nexport interface FablePlanBroker {\n start(request: FablePlanRequest, signal: AbortSignal): Promise<FablePlanResult>;\n cancel(operationId: string, reason: string): void;\n}\n\nexport interface FableFlowOptions {\n broker?: FablePlanBroker;\n isAuthorized: () => boolean;\n /** Supplies operation ids. Injected so a test can pin them. */\n newOperationId?: () => string;\n timeoutMs?: number;\n onStage?: (stage: FableStage) => void;\n onError?: (error: unknown) => void;\n}\n\nexport type FableStage = 'idle' | 'draft' | 'review' | 'completed' | 'failed' | 'cancelled' | 'interrupted';\n\nexport interface FablePlanFlow {\n run(value: unknown, signal?: AbortSignal): Promise<FablePlanResult>;\n cancel(reason?: string): void;\n isActive(): boolean;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction hasControlCharacter(value: string): boolean {\n for (const character of value) {\n const code = character.codePointAt(0);\n if (code !== undefined && (code <= CONTROL_CHARACTER_MAX || code === DELETE_CHARACTER)) return true;\n }\n return false;\n}\n\nexport function containsSuspectedCredential(value: string): boolean {\n return SECRET_PATTERNS.some((pattern) => pattern.test(value));\n}\n\nfunction boundedText(value: unknown, field: string, required = true): string {\n if (typeof value !== 'string') throw new Error(`${field} must be a string.`);\n const text = value.trim();\n if (!text && required) throw new Error(`${field} must not be empty.`);\n if (Buffer.byteLength(text, 'utf8') > MAX_FABLE_TEXT_BYTES || hasControlCharacter(text)) {\n throw new Error(`${field} exceeds the bounded Fable text limit or contains control characters.`);\n }\n if (containsSuspectedCredential(text)) throw new Error(`${field} appears to contain a credential.`);\n return text;\n}\n\nfunction boundedList(value: unknown, field: string, required = true): string[] {\n if (!Array.isArray(value)) throw new Error(`${field} must be an array.`);\n if (value.length > MAX_FABLE_ARRAY_ITEMS) throw new Error(`${field} exceeds the bounded item limit.`);\n const items = value.map((item, index) => boundedText(item, `${field}[${index}]`));\n if (required && items.length === 0) throw new Error(`${field} must contain at least one item.`);\n return items;\n}\n\nfunction boundedPath(value: unknown, field: string): string {\n if (typeof value !== 'string') throw new Error(`${field} must be a string.`);\n const sourcePath = value.trim();\n if (!sourcePath || sourcePath.length > MAX_SOURCE_PATH_LENGTH || hasControlCharacter(sourcePath)) {\n throw new Error(`${field} is not a safe source path.`);\n }\n if (containsSuspectedCredential(sourcePath)) throw new Error(`${field} appears to contain a credential.`);\n return sourcePath;\n}\n\nfunction boundedFindings(value: unknown): FablePlanFinding[] {\n if (!Array.isArray(value)) throw new Error('verifiedFindings must be an array.');\n if (value.length > MAX_FABLE_ARRAY_ITEMS) throw new Error('verifiedFindings exceeds the bounded item limit.');\n return value.map((item, index) => {\n if (!isRecord(item)) throw new Error(`verifiedFindings[${index}] must be an object.`);\n const keys = Object.keys(item);\n if (keys.some((key) => key !== 'path' && key !== 'finding')) {\n throw new Error(`verifiedFindings[${index}] contains an unsupported field.`);\n }\n return {\n path: boundedPath(item.path, `verifiedFindings[${index}].path`),\n finding: boundedText(item.finding, `verifiedFindings[${index}].finding`),\n };\n });\n}\n\nfunction assertAllowedKeys(value: Record<string, unknown>, keys: readonly string[], field: string): void {\n const allowed = new Set(keys);\n const unexpected = Object.keys(value).find((key) => !allowed.has(key));\n if (unexpected) throw new Error(`${field} contains unsupported field '${unexpected}'.`);\n}\n\nexport function sanitizeFablePacket(value: unknown): FablePlanPacket {\n if (!isRecord(value)) throw new Error('Fable packet must be an object.');\n assertAllowedKeys(\n value,\n ['goal', 'constraints', 'decisions', 'verifiedFindings', 'inferredFindings', 'unresolvedQuestions', 'currentPlan'],\n 'Fable packet',\n );\n const packet: FablePlanPacket = {\n goal: boundedList(value.goal, 'goal'),\n constraints: boundedList(value.constraints, 'constraints', false),\n decisions: boundedList(value.decisions, 'decisions', false),\n verifiedFindings: boundedFindings(value.verifiedFindings),\n inferredFindings: boundedList(value.inferredFindings, 'inferredFindings', false),\n unresolvedQuestions: boundedList(value.unresolvedQuestions, 'unresolvedQuestions', false),\n ...(value.currentPlan === undefined ? {} : { currentPlan: boundedText(value.currentPlan, 'currentPlan', false) }),\n };\n if (Buffer.byteLength(JSON.stringify(packet), 'utf8') > MAX_FABLE_PACKET_BYTES) {\n throw new Error('Fable packet exceeds the bounded packet size.');\n }\n return packet;\n}\n\nfunction safeResult(result: FablePlanResult): FablePlanResult {\n const output = [result.draft, result.review].filter((value): value is string => value !== undefined).join('\\n');\n if (containsSuspectedCredential(output)) {\n return {\n operationId: result.operationId,\n status: 'failed',\n stage: 'failed',\n durationMs: result.durationMs,\n errorCode: 'unsafe_output',\n };\n }\n return result;\n}\n\nfunction timedOutResult(operationId: string, startedAt: number): FablePlanResult {\n return {\n operationId,\n status: 'timed_out',\n stage: 'interrupted',\n durationMs: Math.max(0, Date.now() - startedAt),\n errorCode: 'timeout',\n };\n}\n\nexport function createFablePlanFlow(options: FableFlowOptions): FablePlanFlow {\n const newOperationId = options.newOperationId ?? (() => crypto.randomUUID());\n let active:\n | {\n operationId: string;\n controller: AbortController;\n cancelSent: boolean;\n }\n | undefined;\n\n const cancel = (reason = 'Fable operation cancelled.'): void => {\n const current = active;\n if (!current) return;\n if (!current.cancelSent) {\n current.cancelSent = true;\n try {\n options.broker?.cancel(current.operationId, reason);\n } catch (error) {\n options.onError?.(error);\n }\n }\n current.controller.abort(new Error(reason));\n };\n\n const run = async (value: unknown, signal?: AbortSignal): Promise<FablePlanResult> => {\n if (active) throw new Error('A Fable operation is already active for this session.');\n if (!options.isAuthorized()) throw new Error('The Fable capability profile is not authorized.');\n const packet = sanitizeFablePacket(value);\n const operationId = `fable-${newOperationId()}`;\n const startedAt = Date.now();\n const controller = new AbortController();\n active = { operationId, controller, cancelSent: false };\n options.onStage?.('draft');\n\n const parentAbort = (): void => controller.abort(signal?.reason);\n if (signal) {\n signal.addEventListener('abort', parentAbort, { once: true });\n if (signal.aborted) parentAbort();\n }\n\n const brokerRequest: FablePlanRequest = {\n requester: FABLE_PLAN_REQUESTER,\n operationId,\n runtime: FABLE_PLAN_RUNTIME,\n model: FABLE_PLAN_MODEL,\n profile: FABLE_PLAN_PROFILE,\n packet,\n };\n let timeout: ReturnType<typeof setTimeout> | undefined;\n let timeoutTriggered = false;\n try {\n if (!options.broker) return timedOutResult(operationId, startedAt);\n const brokerResult = options.broker.start(brokerRequest, controller.signal);\n const cancelledResult = new Promise<FablePlanResult>((resolve) => {\n const onAbort = (): void => {\n if (timeoutTriggered) return;\n resolve({\n operationId,\n status: 'cancelled',\n stage: 'cancelled',\n durationMs: Math.max(0, Date.now() - startedAt),\n errorCode: 'cancelled',\n });\n };\n controller.signal.addEventListener('abort', onAbort, { once: true });\n });\n const timeoutResult =\n options.timeoutMs === undefined\n ? undefined\n : new Promise<FablePlanResult>((resolve) => {\n timeout = setTimeout(() => {\n timeoutTriggered = true;\n cancel('Fable operation timed out.');\n resolve(timedOutResult(operationId, startedAt));\n }, options.timeoutMs);\n });\n const result =\n timeoutResult === undefined\n ? await Promise.race([brokerResult, cancelledResult])\n : await Promise.race([brokerResult, timeoutResult, cancelledResult]);\n const safe = safeResult(result);\n options.onStage?.(\n safe.status === 'completed' ? 'completed' : safe.status === 'cancelled' ? 'cancelled' : safe.stage,\n );\n return safe;\n } catch (error) {\n options.onError?.(error);\n const failure: FablePlanResult = {\n operationId,\n status: 'failed',\n stage: 'failed',\n durationMs: Math.max(0, Date.now() - startedAt),\n errorCode: 'unavailable',\n };\n options.onStage?.('failed');\n return failure;\n } finally {\n if (timeout) clearTimeout(timeout);\n if (signal) signal.removeEventListener('abort', parentAbort);\n active = undefined;\n }\n };\n\n return {\n run,\n cancel,\n isActive: () => active !== undefined,\n };\n}\n"],"mappings":"0EAEA,MACa,EAAuB,yBACvB,EAAqB,SACrB,EAAmB,QACnB,EAAqB,uBAK5B,EAAkB,CACtB,4GACA,sCACA,6BACA,mCACD,CAmED,SAAS,EAAS,EAAkD,CAClE,OAAO,OAAO,GAAU,YAAY,GAAkB,CAAC,MAAM,QAAQ,EAAM,CAG7E,SAAS,EAAoB,EAAwB,CACnD,IAAK,IAAM,KAAa,EAAO,CAC7B,IAAM,EAAO,EAAU,YAAY,EAAE,CACrC,GAAI,IAAS,IAAA,KAAc,GAAQ,IAAyB,IAAS,KAAmB,MAAO,GAEjG,MAAO,GAGT,SAAgB,EAA4B,EAAwB,CAClE,OAAO,EAAgB,KAAM,GAAY,EAAQ,KAAK,EAAM,CAAC,CAG/D,SAAS,EAAY,EAAgB,EAAe,EAAW,GAAc,CAC3E,GAAI,OAAO,GAAU,SAAU,MAAU,MAAM,GAAG,EAAM,oBAAoB,CAC5E,IAAM,EAAO,EAAM,MAAM,CACzB,GAAI,CAAC,GAAQ,EAAU,MAAU,MAAM,GAAG,EAAM,qBAAqB,CACrE,GAAIA,EAAAA,OAAO,WAAW,EAAM,OAAO,CAAA,MAA2B,EAAoB,EAAK,CACrF,MAAU,MAAM,GAAG,EAAM,uEAAuE,CAElG,GAAI,EAA4B,EAAK,CAAE,MAAU,MAAM,GAAG,EAAM,mCAAmC,CACnG,OAAO,EAGT,SAAS,EAAY,EAAgB,EAAe,EAAW,GAAgB,CAC7E,GAAI,CAAC,MAAM,QAAQ,EAAM,CAAE,MAAU,MAAM,GAAG,EAAM,oBAAoB,CACxE,GAAI,EAAM,OAAA,GAAgC,MAAU,MAAM,GAAG,EAAM,kCAAkC,CACrG,IAAM,EAAQ,EAAM,KAAK,EAAM,IAAU,EAAY,EAAM,GAAG,EAAM,GAAG,EAAM,GAAG,CAAC,CACjF,GAAI,GAAY,EAAM,SAAW,EAAG,MAAU,MAAM,GAAG,EAAM,kCAAkC,CAC/F,OAAO,EAGT,SAAS,EAAY,EAAgB,EAAuB,CAC1D,GAAI,OAAO,GAAU,SAAU,MAAU,MAAM,GAAG,EAAM,oBAAoB,CAC5E,IAAM,EAAa,EAAM,MAAM,CAC/B,GAAI,CAAC,GAAc,EAAW,OAAS,KAA0B,EAAoB,EAAW,CAC9F,MAAU,MAAM,GAAG,EAAM,6BAA6B,CAExD,GAAI,EAA4B,EAAW,CAAE,MAAU,MAAM,GAAG,EAAM,mCAAmC,CACzG,OAAO,EAGT,SAAS,EAAgB,EAAoC,CAC3D,GAAI,CAAC,MAAM,QAAQ,EAAM,CAAE,MAAU,MAAM,qCAAqC,CAChF,GAAI,EAAM,OAAA,GAAgC,MAAU,MAAM,mDAAmD,CAC7G,OAAO,EAAM,KAAK,EAAM,IAAU,CAChC,GAAI,CAAC,EAAS,EAAK,CAAE,MAAU,MAAM,oBAAoB,EAAM,sBAAsB,CAErF,GADa,OAAO,KAAK,EACjB,CAAC,KAAM,GAAQ,IAAQ,QAAU,IAAQ,UAAU,CACzD,MAAU,MAAM,oBAAoB,EAAM,kCAAkC,CAE9E,MAAO,CACL,KAAM,EAAY,EAAK,KAAM,oBAAoB,EAAM,QAAQ,CAC/D,QAAS,EAAY,EAAK,QAAS,oBAAoB,EAAM,WAAW,CACzE,EACD,CAGJ,SAAS,EAAkB,EAAgC,EAAyB,EAAqB,CACvG,IAAM,EAAU,IAAI,IAAI,EAAK,CACvB,EAAa,OAAO,KAAK,EAAM,CAAC,KAAM,GAAQ,CAAC,EAAQ,IAAI,EAAI,CAAC,CACtE,GAAI,EAAY,MAAU,MAAM,GAAG,EAAM,+BAA+B,EAAW,IAAI,CAGzF,SAAgB,EAAoB,EAAiC,CACnE,GAAI,CAAC,EAAS,EAAM,CAAE,MAAU,MAAM,kCAAkC,CACxE,EACE,EACA,CAAC,OAAQ,cAAe,YAAa,mBAAoB,mBAAoB,sBAAuB,cAAc,CAClH,eACD,CACD,IAAM,EAA0B,CAC9B,KAAM,EAAY,EAAM,KAAM,OAAO,CACrC,YAAa,EAAY,EAAM,YAAa,cAAe,GAAM,CACjE,UAAW,EAAY,EAAM,UAAW,YAAa,GAAM,CAC3D,iBAAkB,EAAgB,EAAM,iBAAiB,CACzD,iBAAkB,EAAY,EAAM,iBAAkB,mBAAoB,GAAM,CAChF,oBAAqB,EAAY,EAAM,oBAAqB,sBAAuB,GAAM,CACzF,GAAI,EAAM,cAAgB,IAAA,GAAY,EAAE,CAAG,CAAE,YAAa,EAAY,EAAM,YAAa,cAAe,GAAM,CAAE,CACjH,CACD,GAAIA,EAAAA,OAAO,WAAW,KAAK,UAAU,EAAO,CAAE,OAAO,CAAA,MACnD,MAAU,MAAM,gDAAgD,CAElE,OAAO,EAGT,SAAS,EAAW,EAA0C,CAW5D,OATI,EADW,CAAC,EAAO,MAAO,EAAO,OAAO,CAAC,OAAQ,GAA2B,IAAU,IAAA,GAAU,CAAC,KAAK;EACpE,CAAC,CAC9B,CACL,YAAa,EAAO,YACpB,OAAQ,SACR,MAAO,SACP,WAAY,EAAO,WACnB,UAAW,gBACZ,CAEI,EAGT,SAAS,EAAe,EAAqB,EAAoC,CAC/E,MAAO,CACL,cACA,OAAQ,YACR,MAAO,cACP,WAAY,KAAK,IAAI,EAAG,KAAK,KAAK,CAAG,EAAU,CAC/C,UAAW,UACZ,CAGH,SAAgB,EAAoB,EAA0C,CAC5E,IAAM,EAAiB,EAAQ,qBAAyB,OAAO,YAAY,EACvE,EAQE,GAAU,EAAS,+BAAuC,CAC9D,IAAM,EAAU,EACX,KACL,IAAI,CAAC,EAAQ,WAAY,CACvB,EAAQ,WAAa,GACrB,GAAI,CACF,EAAQ,QAAQ,OAAO,EAAQ,YAAa,EAAO,OAC5C,EAAO,CACd,EAAQ,UAAU,EAAM,EAG5B,EAAQ,WAAW,MAAU,MAAM,EAAO,CAAC,GAkF7C,MAAO,CACL,UAhFiB,EAAgB,IAAmD,CACpF,GAAI,EAAQ,MAAU,MAAM,wDAAwD,CACpF,GAAI,CAAC,EAAQ,cAAc,CAAE,MAAU,MAAM,kDAAkD,CAC/F,IAAM,EAAS,EAAoB,EAAM,CACnC,EAAc,SAAS,GAAgB,GACvC,EAAY,KAAK,KAAK,CACtB,EAAa,IAAI,gBACvB,EAAS,CAAE,cAAa,aAAY,WAAY,GAAO,CACvD,EAAQ,UAAU,QAAQ,CAE1B,IAAM,MAA0B,EAAW,MAAM,GAAQ,OAAO,CAC5D,IACF,EAAO,iBAAiB,QAAS,EAAa,CAAE,KAAM,GAAM,CAAC,CACzD,EAAO,SAAS,GAAa,EAGnC,IAAM,EAAkC,CACtC,UAAW,EACX,cACA,QAAS,EACT,MAAO,EACP,QAAS,EACT,SACD,CACG,EACA,EAAmB,GACvB,GAAI,CACF,GAAI,CAAC,EAAQ,OAAQ,OAAO,EAAe,EAAa,EAAU,CAClE,IAAM,EAAe,EAAQ,OAAO,MAAM,EAAe,EAAW,OAAO,CACrE,EAAkB,IAAI,QAA0B,GAAY,CAWhE,EAAW,OAAO,iBAAiB,YAVP,CACtB,GACJ,EAAQ,CACN,cACA,OAAQ,YACR,MAAO,YACP,WAAY,KAAK,IAAI,EAAG,KAAK,KAAK,CAAG,EAAU,CAC/C,UAAW,YACZ,CAAC,EAEiD,CAAE,KAAM,GAAM,CAAC,EACpE,CACI,EACJ,EAAQ,YAAc,IAAA,GAClB,IAAA,GACA,IAAI,QAA0B,GAAY,CACxC,EAAU,eAAiB,CACzB,EAAmB,GACnB,EAAO,6BAA6B,CACpC,EAAQ,EAAe,EAAa,EAAU,CAAC,EAC9C,EAAQ,UAAU,EACrB,CAKF,EAAO,EAHX,IAAkB,IAAA,GACd,MAAM,QAAQ,KAAK,CAAC,EAAc,EAAgB,CAAC,CACnD,MAAM,QAAQ,KAAK,CAAC,EAAc,EAAe,EAAgB,CAAC,CACzC,CAI/B,OAHA,EAAQ,UACN,EAAK,SAAW,YAAc,YAAc,EAAK,SAAW,YAAc,YAAc,EAAK,MAC9F,CACM,QACA,EAAO,CACd,EAAQ,UAAU,EAAM,CACxB,IAAM,EAA2B,CAC/B,cACA,OAAQ,SACR,MAAO,SACP,WAAY,KAAK,IAAI,EAAG,KAAK,KAAK,CAAG,EAAU,CAC/C,UAAW,cACZ,CAED,OADA,EAAQ,UAAU,SAAS,CACpB,SACC,CACJ,GAAS,aAAa,EAAQ,CAC9B,GAAQ,EAAO,oBAAoB,QAAS,EAAY,CAC5D,EAAS,IAAA,KAMX,SACA,aAAgB,IAAW,IAAA,GAC5B"}
@@ -1,4 +1,4 @@
1
- //#region src/services/plan/fableFlow.d.ts
1
+ //#region src/services/fableFlow.d.ts
2
2
  declare const FABLE_PROVIDER_SOURCE = "@agimon-ai/doompi-team";
3
3
  declare const FABLE_PLAN_REQUESTER = "@agimon-ai/doompi-plan";
4
4
  declare const FABLE_PLAN_RUNTIME = "claude";
@@ -48,6 +48,8 @@ interface FablePlanBroker {
48
48
  interface FableFlowOptions {
49
49
  broker?: FablePlanBroker;
50
50
  isAuthorized: () => boolean;
51
+ /** Supplies operation ids. Injected so a test can pin them. */
52
+ newOperationId?: () => string;
51
53
  timeoutMs?: number;
52
54
  onStage?: (stage: FableStage) => void;
53
55
  onError?: (error: unknown) => void;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fableFlow.d.cts","names":[],"sources":["../../src/services/fableFlow.ts"],"mappings":";cAEa,qBAAA;AAAA,cACA,oBAAA;AAAA,cACA,kBAAA;AAAA,cACA,gBAAA;AAAA,cACA,kBAAA;AAAA,cACA,sBAAA;AAAA,cACA,oBAAA;AAAA,cACA,qBAAA;AAAA,UAYI,gBAAA;EACf,IAAA;EACA,OAAA;AAAA;AAAA,UAGe,eAAA;EACf,IAAA;EACA,WAAA;EACA,SAAA;EACA,gBAAA,EAAkB,gBAAA;EAClB,gBAAA;EACA,mBAAA;EACA,WAAA;AAAA;AAAA,KAGU,eAAA;AAAA,KACA,cAAA;AAAA,UAEK,eAAA;EACf,WAAA;EACA,MAAA,EAAQ,eAAA;EACR,KAAA,EAAO,cAAA;EACP,KAAA;EACA,MAAA;EACA,UAAA;EACA,WAAA;EACA,UAAA;EACA,SAAA;AAAA;AAAA,UAGe,gBAAA;EACf,SAAA,SAAkB,oBAAA;EAClB,WAAA;EACA,OAAA,SAAgB,kBAAA;EAChB,KAAA,SAAc,gBAAA;EACd,OAAA,SAAgB,kBAAA;EAChB,MAAA,EAAQ,eAAA;AAAA;AAAA,UAGO,eAAA;EACf,KAAA,CAAM,OAAA,EAAS,gBAAA,EAAkB,MAAA,EAAQ,WAAA,GAAc,OAAA,CAAQ,eAAA;EAC/D,MAAA,CAAO,WAAA,UAAqB,MAAA;AAAA;AAAA,UAGb,gBAAA;EACf,MAAA,GAAS,eAAA;EACT,YAAA;EArCkC;EAuClC,cAAA;EACA,SAAA;EACA,OAAA,IAAW,KAAA,EAAO,UAAA;EAClB,OAAA,IAAW,KAAA;AAAA;AAAA,KAGD,UAAA;AAAA,UAEK,aAAA;EACf,GAAA,CAAI,KAAA,WAAgB,MAAA,GAAS,WAAA,GAAc,OAAA,CAAQ,eAAA;EACnD,MAAA,CAAO,MAAA;EACP,QAAA;AAAA;AAAA,iBAec,2BAAA,CAA4B,KAAA;AAAA,iBAuD5B,mBAAA,CAAoB,KAAA,YAAiB,eAAA;AAAA,iBA8CrC,mBAAA,CAAoB,OAAA,EAAS,gBAAA,GAAmB,aAAA"}
@@ -1,4 +1,4 @@
1
- //#region src/services/plan/fableFlow.d.ts
1
+ //#region src/services/fableFlow.d.ts
2
2
  declare const FABLE_PROVIDER_SOURCE = "@agimon-ai/doompi-team";
3
3
  declare const FABLE_PLAN_REQUESTER = "@agimon-ai/doompi-plan";
4
4
  declare const FABLE_PLAN_RUNTIME = "claude";
@@ -48,6 +48,8 @@ interface FablePlanBroker {
48
48
  interface FableFlowOptions {
49
49
  broker?: FablePlanBroker;
50
50
  isAuthorized: () => boolean;
51
+ /** Supplies operation ids. Injected so a test can pin them. */
52
+ newOperationId?: () => string;
51
53
  timeoutMs?: number;
52
54
  onStage?: (stage: FableStage) => void;
53
55
  onError?: (error: unknown) => void;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fableFlow.d.mts","names":[],"sources":["../../src/services/fableFlow.ts"],"mappings":";cAEa,qBAAA;AAAA,cACA,oBAAA;AAAA,cACA,kBAAA;AAAA,cACA,gBAAA;AAAA,cACA,kBAAA;AAAA,cACA,sBAAA;AAAA,cACA,oBAAA;AAAA,cACA,qBAAA;AAAA,UAYI,gBAAA;EACf,IAAA;EACA,OAAA;AAAA;AAAA,UAGe,eAAA;EACf,IAAA;EACA,WAAA;EACA,SAAA;EACA,gBAAA,EAAkB,gBAAA;EAClB,gBAAA;EACA,mBAAA;EACA,WAAA;AAAA;AAAA,KAGU,eAAA;AAAA,KACA,cAAA;AAAA,UAEK,eAAA;EACf,WAAA;EACA,MAAA,EAAQ,eAAA;EACR,KAAA,EAAO,cAAA;EACP,KAAA;EACA,MAAA;EACA,UAAA;EACA,WAAA;EACA,UAAA;EACA,SAAA;AAAA;AAAA,UAGe,gBAAA;EACf,SAAA,SAAkB,oBAAA;EAClB,WAAA;EACA,OAAA,SAAgB,kBAAA;EAChB,KAAA,SAAc,gBAAA;EACd,OAAA,SAAgB,kBAAA;EAChB,MAAA,EAAQ,eAAA;AAAA;AAAA,UAGO,eAAA;EACf,KAAA,CAAM,OAAA,EAAS,gBAAA,EAAkB,MAAA,EAAQ,WAAA,GAAc,OAAA,CAAQ,eAAA;EAC/D,MAAA,CAAO,WAAA,UAAqB,MAAA;AAAA;AAAA,UAGb,gBAAA;EACf,MAAA,GAAS,eAAA;EACT,YAAA;EArCkC;EAuClC,cAAA;EACA,SAAA;EACA,OAAA,IAAW,KAAA,EAAO,UAAA;EAClB,OAAA,IAAW,KAAA;AAAA;AAAA,KAGD,UAAA;AAAA,UAEK,aAAA;EACf,GAAA,CAAI,KAAA,WAAgB,MAAA,GAAS,WAAA,GAAc,OAAA,CAAQ,eAAA;EACnD,MAAA,CAAO,MAAA;EACP,QAAA;AAAA;AAAA,iBAec,2BAAA,CAA4B,KAAA;AAAA,iBAuD5B,mBAAA,CAAoB,KAAA,YAAiB,eAAA;AAAA,iBA8CrC,mBAAA,CAAoB,OAAA,EAAS,gBAAA,GAAmB,aAAA"}
@@ -0,0 +1,3 @@
1
+ import{Buffer as e}from"node:buffer";const t=`@agimon-ai/doompi-team`,n=`@agimon-ai/doompi-plan`,r=`claude`,i=`fable`,a=`claude/fable-plan-v1`,o=32*1024,s=4*1024,c=24,l=[/(?: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 u(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function d(e){for(let t of e){let e=t.codePointAt(0);if(e!==void 0&&(e<=31||e===127))return!0}return!1}function f(e){return l.some(t=>t.test(e))}function p(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.byteLength(i,`utf8`)>4096||d(i))throw Error(`${n} exceeds the bounded Fable text limit or contains control characters.`);if(f(i))throw Error(`${n} appears to contain a credential.`);return i}function m(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)=>p(e,`${t}[${n}]`));if(n&&r.length===0)throw Error(`${t} must contain at least one item.`);return r}function h(e,t){if(typeof e!=`string`)throw Error(`${t} must be a string.`);let n=e.trim();if(!n||n.length>512||d(n))throw Error(`${t} is not a safe source path.`);if(f(n))throw Error(`${t} appears to contain a credential.`);return n}function g(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(!u(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:h(e.path,`verifiedFindings[${t}].path`),finding:p(e.finding,`verifiedFindings[${t}].finding`)}})}function _(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 v(t){if(!u(t))throw Error(`Fable packet must be an object.`);_(t,[`goal`,`constraints`,`decisions`,`verifiedFindings`,`inferredFindings`,`unresolvedQuestions`,`currentPlan`],`Fable packet`);let n={goal:m(t.goal,`goal`),constraints:m(t.constraints,`constraints`,!1),decisions:m(t.decisions,`decisions`,!1),verifiedFindings:g(t.verifiedFindings),inferredFindings:m(t.inferredFindings,`inferredFindings`,!1),unresolvedQuestions:m(t.unresolvedQuestions,`unresolvedQuestions`,!1),...t.currentPlan===void 0?{}:{currentPlan:p(t.currentPlan,`currentPlan`,!1)}};if(e.byteLength(JSON.stringify(n),`utf8`)>32768)throw Error(`Fable packet exceeds the bounded packet size.`);return n}function y(e){return f([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 b(e,t){return{operationId:e,status:`timed_out`,stage:`interrupted`,durationMs:Math.max(0,Date.now()-t),errorCode:`timeout`}}function x(e){let t=e.newOperationId??(()=>crypto.randomUUID()),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=v(c),d=`fable-${t()}`,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 h={requester:n,operationId:d,runtime:r,model:i,profile:a,packet:u},g,_=!1;try{if(!e.broker)return b(d,f);let t=e.broker.start(h,p.signal),n=new Promise(e=>{p.signal.addEventListener(`abort`,()=>{_||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=>{g=setTimeout(()=>{_=!0,s(`Fable operation timed out.`),t(b(d,f))},e.timeoutMs)}),i=y(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{g&&clearTimeout(g),l&&l.removeEventListener(`abort`,m),o=void 0}},cancel:s,isActive:()=>o!==void 0}}export{i as FABLE_PLAN_MODEL,a as FABLE_PLAN_PROFILE,n as FABLE_PLAN_REQUESTER,r as FABLE_PLAN_RUNTIME,t as FABLE_PROVIDER_SOURCE,c as MAX_FABLE_ARRAY_ITEMS,o as MAX_FABLE_PACKET_BYTES,s as MAX_FABLE_TEXT_BYTES,f as containsSuspectedCredential,x as createFablePlanFlow,v as sanitizeFablePacket};
3
+ //# sourceMappingURL=fableFlow.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fableFlow.mjs","names":[],"sources":["../../src/services/fableFlow.ts"],"sourcesContent":["import { Buffer } from 'node:buffer';\n\nexport const FABLE_PROVIDER_SOURCE = '@agimon-ai/doompi-team';\nexport const FABLE_PLAN_REQUESTER = '@agimon-ai/doompi-plan';\nexport const FABLE_PLAN_RUNTIME = 'claude';\nexport const FABLE_PLAN_MODEL = 'fable';\nexport const FABLE_PLAN_PROFILE = 'claude/fable-plan-v1';\nexport const MAX_FABLE_PACKET_BYTES = 32 * 1024;\nexport const MAX_FABLE_TEXT_BYTES = 4 * 1024;\nexport const MAX_FABLE_ARRAY_ITEMS = 24;\n\nconst SECRET_PATTERNS = [\n /(?:api[_-]?key|access[_-]?token|client[_-]?secret|password|private[_-]?key|authorization|bearer)\\s*[:=]/iu,\n /-----BEGIN [A-Z ]*PRIVATE KEY-----/u,\n /\\bsk-[A-Za-z0-9_-]{16,}\\b/u,\n /\\bgh[pousr]_[A-Za-z0-9_]{16,}\\b/u,\n];\nconst CONTROL_CHARACTER_MAX = 31;\nconst DELETE_CHARACTER = 127;\nconst MAX_SOURCE_PATH_LENGTH = 512;\n\nexport interface FablePlanFinding {\n path: string;\n finding: string;\n}\n\nexport interface FablePlanPacket {\n goal: string[];\n constraints: string[];\n decisions: string[];\n verifiedFindings: FablePlanFinding[];\n inferredFindings: string[];\n unresolvedQuestions: string[];\n currentPlan?: string;\n}\n\nexport type FablePlanStatus = 'completed' | 'failed' | 'timed_out' | 'cancelled' | 'interrupted';\nexport type FablePlanStage = 'draft' | 'review' | 'completed' | 'failed' | 'cancelled' | 'interrupted';\n\nexport interface FablePlanResult {\n operationId: string;\n status: FablePlanStatus;\n stage: FablePlanStage;\n draft?: string;\n review?: string;\n draftRunId?: string;\n reviewRunId?: string;\n durationMs: number;\n errorCode?: string;\n}\n\nexport interface FablePlanRequest {\n requester: typeof FABLE_PLAN_REQUESTER;\n operationId: string;\n runtime: typeof FABLE_PLAN_RUNTIME;\n model: typeof FABLE_PLAN_MODEL;\n profile: typeof FABLE_PLAN_PROFILE;\n packet: FablePlanPacket;\n}\n\nexport interface FablePlanBroker {\n start(request: FablePlanRequest, signal: AbortSignal): Promise<FablePlanResult>;\n cancel(operationId: string, reason: string): void;\n}\n\nexport interface FableFlowOptions {\n broker?: FablePlanBroker;\n isAuthorized: () => boolean;\n /** Supplies operation ids. Injected so a test can pin them. */\n newOperationId?: () => string;\n timeoutMs?: number;\n onStage?: (stage: FableStage) => void;\n onError?: (error: unknown) => void;\n}\n\nexport type FableStage = 'idle' | 'draft' | 'review' | 'completed' | 'failed' | 'cancelled' | 'interrupted';\n\nexport interface FablePlanFlow {\n run(value: unknown, signal?: AbortSignal): Promise<FablePlanResult>;\n cancel(reason?: string): void;\n isActive(): boolean;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction hasControlCharacter(value: string): boolean {\n for (const character of value) {\n const code = character.codePointAt(0);\n if (code !== undefined && (code <= CONTROL_CHARACTER_MAX || code === DELETE_CHARACTER)) return true;\n }\n return false;\n}\n\nexport function containsSuspectedCredential(value: string): boolean {\n return SECRET_PATTERNS.some((pattern) => pattern.test(value));\n}\n\nfunction boundedText(value: unknown, field: string, required = true): string {\n if (typeof value !== 'string') throw new Error(`${field} must be a string.`);\n const text = value.trim();\n if (!text && required) throw new Error(`${field} must not be empty.`);\n if (Buffer.byteLength(text, 'utf8') > MAX_FABLE_TEXT_BYTES || hasControlCharacter(text)) {\n throw new Error(`${field} exceeds the bounded Fable text limit or contains control characters.`);\n }\n if (containsSuspectedCredential(text)) throw new Error(`${field} appears to contain a credential.`);\n return text;\n}\n\nfunction boundedList(value: unknown, field: string, required = true): string[] {\n if (!Array.isArray(value)) throw new Error(`${field} must be an array.`);\n if (value.length > MAX_FABLE_ARRAY_ITEMS) throw new Error(`${field} exceeds the bounded item limit.`);\n const items = value.map((item, index) => boundedText(item, `${field}[${index}]`));\n if (required && items.length === 0) throw new Error(`${field} must contain at least one item.`);\n return items;\n}\n\nfunction boundedPath(value: unknown, field: string): string {\n if (typeof value !== 'string') throw new Error(`${field} must be a string.`);\n const sourcePath = value.trim();\n if (!sourcePath || sourcePath.length > MAX_SOURCE_PATH_LENGTH || hasControlCharacter(sourcePath)) {\n throw new Error(`${field} is not a safe source path.`);\n }\n if (containsSuspectedCredential(sourcePath)) throw new Error(`${field} appears to contain a credential.`);\n return sourcePath;\n}\n\nfunction boundedFindings(value: unknown): FablePlanFinding[] {\n if (!Array.isArray(value)) throw new Error('verifiedFindings must be an array.');\n if (value.length > MAX_FABLE_ARRAY_ITEMS) throw new Error('verifiedFindings exceeds the bounded item limit.');\n return value.map((item, index) => {\n if (!isRecord(item)) throw new Error(`verifiedFindings[${index}] must be an object.`);\n const keys = Object.keys(item);\n if (keys.some((key) => key !== 'path' && key !== 'finding')) {\n throw new Error(`verifiedFindings[${index}] contains an unsupported field.`);\n }\n return {\n path: boundedPath(item.path, `verifiedFindings[${index}].path`),\n finding: boundedText(item.finding, `verifiedFindings[${index}].finding`),\n };\n });\n}\n\nfunction assertAllowedKeys(value: Record<string, unknown>, keys: readonly string[], field: string): void {\n const allowed = new Set(keys);\n const unexpected = Object.keys(value).find((key) => !allowed.has(key));\n if (unexpected) throw new Error(`${field} contains unsupported field '${unexpected}'.`);\n}\n\nexport function sanitizeFablePacket(value: unknown): FablePlanPacket {\n if (!isRecord(value)) throw new Error('Fable packet must be an object.');\n assertAllowedKeys(\n value,\n ['goal', 'constraints', 'decisions', 'verifiedFindings', 'inferredFindings', 'unresolvedQuestions', 'currentPlan'],\n 'Fable packet',\n );\n const packet: FablePlanPacket = {\n goal: boundedList(value.goal, 'goal'),\n constraints: boundedList(value.constraints, 'constraints', false),\n decisions: boundedList(value.decisions, 'decisions', false),\n verifiedFindings: boundedFindings(value.verifiedFindings),\n inferredFindings: boundedList(value.inferredFindings, 'inferredFindings', false),\n unresolvedQuestions: boundedList(value.unresolvedQuestions, 'unresolvedQuestions', false),\n ...(value.currentPlan === undefined ? {} : { currentPlan: boundedText(value.currentPlan, 'currentPlan', false) }),\n };\n if (Buffer.byteLength(JSON.stringify(packet), 'utf8') > MAX_FABLE_PACKET_BYTES) {\n throw new Error('Fable packet exceeds the bounded packet size.');\n }\n return packet;\n}\n\nfunction safeResult(result: FablePlanResult): FablePlanResult {\n const output = [result.draft, result.review].filter((value): value is string => value !== undefined).join('\\n');\n if (containsSuspectedCredential(output)) {\n return {\n operationId: result.operationId,\n status: 'failed',\n stage: 'failed',\n durationMs: result.durationMs,\n errorCode: 'unsafe_output',\n };\n }\n return result;\n}\n\nfunction timedOutResult(operationId: string, startedAt: number): FablePlanResult {\n return {\n operationId,\n status: 'timed_out',\n stage: 'interrupted',\n durationMs: Math.max(0, Date.now() - startedAt),\n errorCode: 'timeout',\n };\n}\n\nexport function createFablePlanFlow(options: FableFlowOptions): FablePlanFlow {\n const newOperationId = options.newOperationId ?? (() => crypto.randomUUID());\n let active:\n | {\n operationId: string;\n controller: AbortController;\n cancelSent: boolean;\n }\n | undefined;\n\n const cancel = (reason = 'Fable operation cancelled.'): void => {\n const current = active;\n if (!current) return;\n if (!current.cancelSent) {\n current.cancelSent = true;\n try {\n options.broker?.cancel(current.operationId, reason);\n } catch (error) {\n options.onError?.(error);\n }\n }\n current.controller.abort(new Error(reason));\n };\n\n const run = async (value: unknown, signal?: AbortSignal): Promise<FablePlanResult> => {\n if (active) throw new Error('A Fable operation is already active for this session.');\n if (!options.isAuthorized()) throw new Error('The Fable capability profile is not authorized.');\n const packet = sanitizeFablePacket(value);\n const operationId = `fable-${newOperationId()}`;\n const startedAt = Date.now();\n const controller = new AbortController();\n active = { operationId, controller, cancelSent: false };\n options.onStage?.('draft');\n\n const parentAbort = (): void => controller.abort(signal?.reason);\n if (signal) {\n signal.addEventListener('abort', parentAbort, { once: true });\n if (signal.aborted) parentAbort();\n }\n\n const brokerRequest: FablePlanRequest = {\n requester: FABLE_PLAN_REQUESTER,\n operationId,\n runtime: FABLE_PLAN_RUNTIME,\n model: FABLE_PLAN_MODEL,\n profile: FABLE_PLAN_PROFILE,\n packet,\n };\n let timeout: ReturnType<typeof setTimeout> | undefined;\n let timeoutTriggered = false;\n try {\n if (!options.broker) return timedOutResult(operationId, startedAt);\n const brokerResult = options.broker.start(brokerRequest, controller.signal);\n const cancelledResult = new Promise<FablePlanResult>((resolve) => {\n const onAbort = (): void => {\n if (timeoutTriggered) return;\n resolve({\n operationId,\n status: 'cancelled',\n stage: 'cancelled',\n durationMs: Math.max(0, Date.now() - startedAt),\n errorCode: 'cancelled',\n });\n };\n controller.signal.addEventListener('abort', onAbort, { once: true });\n });\n const timeoutResult =\n options.timeoutMs === undefined\n ? undefined\n : new Promise<FablePlanResult>((resolve) => {\n timeout = setTimeout(() => {\n timeoutTriggered = true;\n cancel('Fable operation timed out.');\n resolve(timedOutResult(operationId, startedAt));\n }, options.timeoutMs);\n });\n const result =\n timeoutResult === undefined\n ? await Promise.race([brokerResult, cancelledResult])\n : await Promise.race([brokerResult, timeoutResult, cancelledResult]);\n const safe = safeResult(result);\n options.onStage?.(\n safe.status === 'completed' ? 'completed' : safe.status === 'cancelled' ? 'cancelled' : safe.stage,\n );\n return safe;\n } catch (error) {\n options.onError?.(error);\n const failure: FablePlanResult = {\n operationId,\n status: 'failed',\n stage: 'failed',\n durationMs: Math.max(0, Date.now() - startedAt),\n errorCode: 'unavailable',\n };\n options.onStage?.('failed');\n return failure;\n } finally {\n if (timeout) clearTimeout(timeout);\n if (signal) signal.removeEventListener('abort', parentAbort);\n active = undefined;\n }\n };\n\n return {\n run,\n cancel,\n isActive: () => active !== undefined,\n };\n}\n"],"mappings":"qCAEA,MAAa,EAAwB,yBACxB,EAAuB,yBACvB,EAAqB,SACrB,EAAmB,QACnB,EAAqB,uBACrB,EAAyB,GAAK,KAC9B,EAAuB,EAAI,KAC3B,EAAwB,GAE/B,EAAkB,CACtB,4GACA,sCACA,6BACA,mCACD,CAmED,SAAS,EAAS,EAAkD,CAClE,OAAO,OAAO,GAAU,YAAY,GAAkB,CAAC,MAAM,QAAQ,EAAM,CAG7E,SAAS,EAAoB,EAAwB,CACnD,IAAK,IAAM,KAAa,EAAO,CAC7B,IAAM,EAAO,EAAU,YAAY,EAAE,CACrC,GAAI,IAAS,IAAA,KAAc,GAAQ,IAAyB,IAAS,KAAmB,MAAO,GAEjG,MAAO,GAGT,SAAgB,EAA4B,EAAwB,CAClE,OAAO,EAAgB,KAAM,GAAY,EAAQ,KAAK,EAAM,CAAC,CAG/D,SAAS,EAAY,EAAgB,EAAe,EAAW,GAAc,CAC3E,GAAI,OAAO,GAAU,SAAU,MAAU,MAAM,GAAG,EAAM,oBAAoB,CAC5E,IAAM,EAAO,EAAM,MAAM,CACzB,GAAI,CAAC,GAAQ,EAAU,MAAU,MAAM,GAAG,EAAM,qBAAqB,CACrE,GAAI,EAAO,WAAW,EAAM,OAAO,CAAA,MAA2B,EAAoB,EAAK,CACrF,MAAU,MAAM,GAAG,EAAM,uEAAuE,CAElG,GAAI,EAA4B,EAAK,CAAE,MAAU,MAAM,GAAG,EAAM,mCAAmC,CACnG,OAAO,EAGT,SAAS,EAAY,EAAgB,EAAe,EAAW,GAAgB,CAC7E,GAAI,CAAC,MAAM,QAAQ,EAAM,CAAE,MAAU,MAAM,GAAG,EAAM,oBAAoB,CACxE,GAAI,EAAM,OAAA,GAAgC,MAAU,MAAM,GAAG,EAAM,kCAAkC,CACrG,IAAM,EAAQ,EAAM,KAAK,EAAM,IAAU,EAAY,EAAM,GAAG,EAAM,GAAG,EAAM,GAAG,CAAC,CACjF,GAAI,GAAY,EAAM,SAAW,EAAG,MAAU,MAAM,GAAG,EAAM,kCAAkC,CAC/F,OAAO,EAGT,SAAS,EAAY,EAAgB,EAAuB,CAC1D,GAAI,OAAO,GAAU,SAAU,MAAU,MAAM,GAAG,EAAM,oBAAoB,CAC5E,IAAM,EAAa,EAAM,MAAM,CAC/B,GAAI,CAAC,GAAc,EAAW,OAAS,KAA0B,EAAoB,EAAW,CAC9F,MAAU,MAAM,GAAG,EAAM,6BAA6B,CAExD,GAAI,EAA4B,EAAW,CAAE,MAAU,MAAM,GAAG,EAAM,mCAAmC,CACzG,OAAO,EAGT,SAAS,EAAgB,EAAoC,CAC3D,GAAI,CAAC,MAAM,QAAQ,EAAM,CAAE,MAAU,MAAM,qCAAqC,CAChF,GAAI,EAAM,OAAA,GAAgC,MAAU,MAAM,mDAAmD,CAC7G,OAAO,EAAM,KAAK,EAAM,IAAU,CAChC,GAAI,CAAC,EAAS,EAAK,CAAE,MAAU,MAAM,oBAAoB,EAAM,sBAAsB,CAErF,GADa,OAAO,KAAK,EACjB,CAAC,KAAM,GAAQ,IAAQ,QAAU,IAAQ,UAAU,CACzD,MAAU,MAAM,oBAAoB,EAAM,kCAAkC,CAE9E,MAAO,CACL,KAAM,EAAY,EAAK,KAAM,oBAAoB,EAAM,QAAQ,CAC/D,QAAS,EAAY,EAAK,QAAS,oBAAoB,EAAM,WAAW,CACzE,EACD,CAGJ,SAAS,EAAkB,EAAgC,EAAyB,EAAqB,CACvG,IAAM,EAAU,IAAI,IAAI,EAAK,CACvB,EAAa,OAAO,KAAK,EAAM,CAAC,KAAM,GAAQ,CAAC,EAAQ,IAAI,EAAI,CAAC,CACtE,GAAI,EAAY,MAAU,MAAM,GAAG,EAAM,+BAA+B,EAAW,IAAI,CAGzF,SAAgB,EAAoB,EAAiC,CACnE,GAAI,CAAC,EAAS,EAAM,CAAE,MAAU,MAAM,kCAAkC,CACxE,EACE,EACA,CAAC,OAAQ,cAAe,YAAa,mBAAoB,mBAAoB,sBAAuB,cAAc,CAClH,eACD,CACD,IAAM,EAA0B,CAC9B,KAAM,EAAY,EAAM,KAAM,OAAO,CACrC,YAAa,EAAY,EAAM,YAAa,cAAe,GAAM,CACjE,UAAW,EAAY,EAAM,UAAW,YAAa,GAAM,CAC3D,iBAAkB,EAAgB,EAAM,iBAAiB,CACzD,iBAAkB,EAAY,EAAM,iBAAkB,mBAAoB,GAAM,CAChF,oBAAqB,EAAY,EAAM,oBAAqB,sBAAuB,GAAM,CACzF,GAAI,EAAM,cAAgB,IAAA,GAAY,EAAE,CAAG,CAAE,YAAa,EAAY,EAAM,YAAa,cAAe,GAAM,CAAE,CACjH,CACD,GAAI,EAAO,WAAW,KAAK,UAAU,EAAO,CAAE,OAAO,CAAA,MACnD,MAAU,MAAM,gDAAgD,CAElE,OAAO,EAGT,SAAS,EAAW,EAA0C,CAW5D,OATI,EADW,CAAC,EAAO,MAAO,EAAO,OAAO,CAAC,OAAQ,GAA2B,IAAU,IAAA,GAAU,CAAC,KAAK;EACpE,CAAC,CAC9B,CACL,YAAa,EAAO,YACpB,OAAQ,SACR,MAAO,SACP,WAAY,EAAO,WACnB,UAAW,gBACZ,CAEI,EAGT,SAAS,EAAe,EAAqB,EAAoC,CAC/E,MAAO,CACL,cACA,OAAQ,YACR,MAAO,cACP,WAAY,KAAK,IAAI,EAAG,KAAK,KAAK,CAAG,EAAU,CAC/C,UAAW,UACZ,CAGH,SAAgB,EAAoB,EAA0C,CAC5E,IAAM,EAAiB,EAAQ,qBAAyB,OAAO,YAAY,EACvE,EAQE,GAAU,EAAS,+BAAuC,CAC9D,IAAM,EAAU,EACX,KACL,IAAI,CAAC,EAAQ,WAAY,CACvB,EAAQ,WAAa,GACrB,GAAI,CACF,EAAQ,QAAQ,OAAO,EAAQ,YAAa,EAAO,OAC5C,EAAO,CACd,EAAQ,UAAU,EAAM,EAG5B,EAAQ,WAAW,MAAU,MAAM,EAAO,CAAC,GAkF7C,MAAO,CACL,UAhFiB,EAAgB,IAAmD,CACpF,GAAI,EAAQ,MAAU,MAAM,wDAAwD,CACpF,GAAI,CAAC,EAAQ,cAAc,CAAE,MAAU,MAAM,kDAAkD,CAC/F,IAAM,EAAS,EAAoB,EAAM,CACnC,EAAc,SAAS,GAAgB,GACvC,EAAY,KAAK,KAAK,CACtB,EAAa,IAAI,gBACvB,EAAS,CAAE,cAAa,aAAY,WAAY,GAAO,CACvD,EAAQ,UAAU,QAAQ,CAE1B,IAAM,MAA0B,EAAW,MAAM,GAAQ,OAAO,CAC5D,IACF,EAAO,iBAAiB,QAAS,EAAa,CAAE,KAAM,GAAM,CAAC,CACzD,EAAO,SAAS,GAAa,EAGnC,IAAM,EAAkC,CACtC,UAAW,EACX,cACA,QAAS,EACT,MAAO,EACP,QAAS,EACT,SACD,CACG,EACA,EAAmB,GACvB,GAAI,CACF,GAAI,CAAC,EAAQ,OAAQ,OAAO,EAAe,EAAa,EAAU,CAClE,IAAM,EAAe,EAAQ,OAAO,MAAM,EAAe,EAAW,OAAO,CACrE,EAAkB,IAAI,QAA0B,GAAY,CAWhE,EAAW,OAAO,iBAAiB,YAVP,CACtB,GACJ,EAAQ,CACN,cACA,OAAQ,YACR,MAAO,YACP,WAAY,KAAK,IAAI,EAAG,KAAK,KAAK,CAAG,EAAU,CAC/C,UAAW,YACZ,CAAC,EAEiD,CAAE,KAAM,GAAM,CAAC,EACpE,CACI,EACJ,EAAQ,YAAc,IAAA,GAClB,IAAA,GACA,IAAI,QAA0B,GAAY,CACxC,EAAU,eAAiB,CACzB,EAAmB,GACnB,EAAO,6BAA6B,CACpC,EAAQ,EAAe,EAAa,EAAU,CAAC,EAC9C,EAAQ,UAAU,EACrB,CAKF,EAAO,EAHX,IAAkB,IAAA,GACd,MAAM,QAAQ,KAAK,CAAC,EAAc,EAAgB,CAAC,CACnD,MAAM,QAAQ,KAAK,CAAC,EAAc,EAAe,EAAgB,CAAC,CACzC,CAI/B,OAHA,EAAQ,UACN,EAAK,SAAW,YAAc,YAAc,EAAK,SAAW,YAAc,YAAc,EAAK,MAC9F,CACM,QACA,EAAO,CACd,EAAQ,UAAU,EAAM,CACxB,IAAM,EAA2B,CAC/B,cACA,OAAQ,SACR,MAAO,SACP,WAAY,KAAK,IAAI,EAAG,KAAK,KAAK,CAAG,EAAU,CAC/C,UAAW,cACZ,CAED,OADA,EAAQ,UAAU,SAAS,CACpB,SACC,CACJ,GAAS,aAAa,EAAQ,CAC9B,GAAQ,EAAO,oBAAoB,QAAS,EAAY,CAC5D,EAAS,IAAA,KAMX,SACA,aAAgB,IAAW,IAAA,GAC5B"}
@@ -0,0 +1,6 @@
1
+ const e=require(`../_virtual/_rolldown/runtime.cjs`),t=require(`../schemas/plan/config.cjs`),n=require(`./fableFlow.cjs`),r=require(`../adapters/telemetry/logSinkTelemetry.cjs`),i=require(`../schemas/plan/planConfig.cjs`),a=require(`./prompts.cjs`);let o=require(`@agimon-ai/doompi-config`),s=require(`node:buffer`),c=require(`node:crypto`),l=require(`node:fs`);l=e.__toESM(l,1);let ee=require(`node:os`);ee=e.__toESM(ee,1);let te=require(`node:path`);te=e.__toESM(te,1);let ne=require(`@agimon-ai/doompi-config/configWriter`),u=require(`@agimon-ai/doompi-extension-contracts/fable-plan`),d=require(`@agimon-ai/doompi-extension-contracts/mode`),re=require(`@agimon-ai/doompi-extension-contracts/protocol`),f=require(`@agimon-ai/doompi-extension-contracts/subagent-policy`),p=require(`@agimon-ai/doompi-extension-contracts/subagent-tool`),m=require(`@agimon-ai/doompi-extension-contracts/voice-tools`),h=require(`@agimon-ai/doompi-ui/config`),ie=require(`@agimon-ai/doompi-ui/leader`),g=require(`@agimon-ai/doompi-user-feedback/voice-question-handoff`);const _=`agent-harness-plan-mode`,ae=`agent-harness-plan-document`,v=`complete_plan`,y=`write_plan`,b=`ask_user_question`,x=`bash`,S=`find`,C=`grep`,w=`read`,oe=`subagent`,se=`task`,ce=`record_debug_evidence`,T=`run_fable_plan`,E=`implementation-plan`,D=`@agimon-ai/doompi-plan`,le=`activate`,ue=`deactivate`,O=`warning`,de=`info`,fe=`Refused to write the plan because its destination is not a regular file.`,k=`plan.trigger`,pe=`plan.model`,A=`plan.flavor`,me=`not_found`,he=`unauthenticated`,ge=`restore_failed`,_e=new Set,ve=5e3,ye=`Exit plan mode and start implementation`,be=`Continue planning`,xe=`exit`,Se=`continue`,Ce={questions:[{question:`Plan complete. What would you like to do?`,header:`Plan review`,options:[{label:ye,description:`Leave read-only plan mode and begin implementing the approved plan.`},{label:be,description:`Remain in read-only plan mode and refine the implementation plan.`}]}]},we=new Set([`add_directory`,b,x,v,S,C,`intercom`,`ls`,d.MINOR_MODE_TOOL_NAME,...m.VOICE_MODE_TOOL_NAMES,w,`search_external_files`,oe,`subagent_supervisor`,`subagent_wait`,se,y]),j=new Set([`edit`,`write`,`mcp`]),Te=[w,x,C,S,`ls`],Ee=[...Te,`mcp`],M=`leader`,De=`voice_tool`,Oe=[`off`,`minimal`,`low`,`medium`,`high`,`xhigh`,`max`],ke=[`idle`,`draft`,`review`,`completed`,`failed`,`cancelled`,`interrupted`],Ae=`@agimon-ai/doompi-plan`,N={type:`string`,enum:[...[`normal`,`debug`,`fable`]]},je={type:`object`,properties:{flavor:N},required:[`flavor`],additionalProperties:!1},Me={type:`object`,properties:{},additionalProperties:!1},Ne={type:`object`,properties:{active:{type:`boolean`},flavor:{anyOf:[{...N},{type:`null`}]},changed:{type:`boolean`}},required:[`active`,`flavor`,`changed`],additionalProperties:!1},P=new Set([v,y,ce,T,d.MINOR_MODE_TOOL_NAME,...m.VOICE_MODE_TOOL_NAMES]);function Pe(e){return(e.match(/^#\s+(.+?)\s*$/m)?.[1]??E).normalize(`NFKD`).replace(/[\u0300-\u036f]/g,``).toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,64)||E}function Fe(e){return`${encodeURIComponent(e).slice(0,48)||`session`}--${(0,c.createHash)(`sha256`).update(e).digest(`hex`)}`}function Ie(e=new Date,t=(0,c.randomUUID)()){return`${e.toISOString().replace(/[-:]/g,``).replace(/\.\d{3}Z$/,`Z`)}--${t}`}function Le(e,t){for(let n=e.length-1;n>=0;--n){let r=e[n];if(!r||typeof r!=`object`)continue;let i=r;if(i.type!==`message`||i.message?.role!==`assistant`||!Array.isArray(i.message.content))continue;let a=i.message.content.findIndex(e=>{if(!e||typeof e!=`object`)return!1;let n=e;return n.type===`toolCall`&&n.id===t&&n.name===y});if(!(a<0))return i.message.content.slice(0,a).flatMap(e=>{if(!e||typeof e!=`object`)return[];let t=e;return t.type===`text`&&typeof t.text==`string`?[t.text]:[]}).join(`
2
+
3
+ `).trim()||void 0}}function Re(e){return e.reason instanceof Error?e.reason:Error(`Plan write cancelled.`)}async function F(e,t){if(t.aborted)throw Re(t);let n,r=new Promise((e,r)=>{n=()=>r(Re(t)),t.addEventListener(`abort`,n,{once:!0})});try{return await Promise.race([e(),r])}finally{n&&t.removeEventListener(`abort`,n)}}function I(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function L(e){return typeof e==`string`}function R(e){if(!(!I(e)||!L(e.provider)||!L(e.id))&&!(!e.provider||!e.id||e.provider.length>128||e.id.length>128))return{provider:e.provider,id:e.id}}function z(e){return L(e)&&Oe.includes(e)?e:void 0}function B(e){return L(e)&&ke.includes(e)?e:void 0}function V(e){if(!(!Array.isArray(e)||e.some(e=>!L(e))))return e.map(e=>e)}function ze(e){if(!I(e))return;let t=V(e.tools),n=z(e.thinking);if(!t||n===void 0)return;let r=e.model===void 0?void 0:R(e.model);if(!(e.model!==void 0&&!r))return{tools:t,...r?{model:r}:{},thinking:n}}function Be(e){return e===`normal`||e===`debug`||e===`fable`?e:void 0}function H(e){if(e.version!==2)return;let t=e.activeFlavor===void 0?void 0:Be(e.activeFlavor);if(e.activeFlavor!==void 0&&!t)return;let n=e.originalSnapshot===void 0?void 0:ze(e.originalSnapshot);if(e.originalSnapshot!==void 0&&!n)return;let r=e.planId===void 0?void 0:L(e.planId)?e.planId:void 0;if(e.planId!==void 0&&r===void 0)return;let i=e.interruptedFableStage===void 0?void 0:B(e.interruptedFableStage);if(!(e.interruptedFableStage!==void 0&&!i))return{version:2,...t?{activeFlavor:t}:{},...n?{originalSnapshot:n}:{},...r?{planId:r}:{},...i?{interruptedFableStage:i}:{}}}function Ve(e){if(e.enabled!==!0&&e.enabled!==!1)return;let t=e.toolsBeforePlanMode===void 0?void 0:V(e.toolsBeforePlanMode);if(e.toolsBeforePlanMode!==void 0&&!t)return;let n=e.modelBeforePlanMode===void 0?void 0:R(e.modelBeforePlanMode);if(e.modelBeforePlanMode!==void 0&&!n)return;let r=e.thinkingBeforePlanMode===void 0?void 0:z(e.thinkingBeforePlanMode);if(e.thinkingBeforePlanMode!==void 0&&r===void 0)return;let i=e.planId===void 0?void 0:L(e.planId)?e.planId:void 0;if(e.planId!==void 0&&i===void 0)return;let a=t&&r!==void 0?{tools:t,...n?{model:n}:{},thinking:r}:void 0;return{version:2,...e.enabled?{activeFlavor:`normal`}:{},...a?{originalSnapshot:a}:{},...i?{planId:i}:{}}}function He(e){if(I(e))return H(e)??Ve(e)}function Ue(e){if(!I(e)||!L(e.content)||!L(e.path)||!L(e.sessionId)||!L(e.title)||!L(e.writtenAt))return;let t=e.planId===void 0?void 0:L(e.planId)?e.planId:void 0;if(!(e.planId!==void 0&&t===void 0))return{content:e.content,path:e.path,sessionId:e.sessionId,...t?{planId:t}:{},title:e.title,writtenAt:e.writtenAt}}function U(e,t,n){if(!L(e))throw Error(`${t} must be a string.`);let r=e.trim();if(n&&!r)throw Error(`${t} must not be empty.`);if(s.Buffer.byteLength(r,`utf8`)>4096)throw Error(`${t} exceeds the bounded debug evidence limit.`);return r}function W(e,t){if(!Array.isArray(e)||e.length>32)throw Error(`${t} must be a bounded string array.`);return e.map((e,n)=>U(e,`${t}[${n}]`,!1))}function G(e,t){return e===void 0?``:U(e,t,!1)}function K(e,t){return e===void 0?[]:W(e,t)}function q(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 We(e){if(!I(e))throw Error(`Debug evidence must be an object.`);q(e,[`issue`,`expectedBehavior`,`reproductionAttempt`,`actualBehavior`,`logs`,`correlatedTraceEvidence`,`processOutput`,`browserConsoleEvidence`,`correlationIds`,`timestamps`,`verifiedFacts`,`hypotheses`,`unavailableEvidence`],`Debug evidence`);let t={issue:U(e.issue,`issue`,!0),expectedBehavior:G(e.expectedBehavior,`expectedBehavior`),reproductionAttempt:G(e.reproductionAttempt,`reproductionAttempt`),actualBehavior:G(e.actualBehavior,`actualBehavior`),logs:K(e.logs,`logs`),correlatedTraceEvidence:K(e.correlatedTraceEvidence,`correlatedTraceEvidence`),processOutput:K(e.processOutput,`processOutput`),browserConsoleEvidence:K(e.browserConsoleEvidence,`browserConsoleEvidence`),correlationIds:K(e.correlationIds,`correlationIds`),timestamps:K(e.timestamps,`timestamps`),verifiedFacts:K(e.verifiedFacts,`verifiedFacts`),hypotheses:K(e.hypotheses,`hypotheses`),unavailableEvidence:K(e.unavailableEvidence,`unavailableEvidence`)};if(s.Buffer.byteLength(JSON.stringify(t),`utf8`)>32768)throw Error(`Debug evidence exceeds the bounded packet size.`);return t}function Ge(e,t){let n=new Set(t),r=e.filter(e=>we.has(e)&&n.has(e)),i=e.filter(e=>!we.has(e)&&!j.has(e)&&!P.has(e)&&n.has(e)),a=Te.filter(e=>n.has(e)),o=[v,se,y].filter(e=>n.has(e));return[...new Set([...r,...i,...a,...o])]}function Ke(e,t,n,r,i){let a=new Set(n),o=t.filter(e=>!we.has(e)&&!j.has(e)&&!P.has(e)),s=Ge([...new Set([...e,...o])].filter(e=>!P.has(e)),n),c=r===`debug`?[ce,...i].filter(e=>a.has(e)):[];r===`fable`&&a.has(T)&&c.push(T);for(let e of[d.MINOR_MODE_TOOL_NAME,...m.VOICE_MODE_TOOL_NAMES])t.includes(e)&&a.has(e)&&c.push(e);return[...new Set([...s,...c])]}function qe(e,t,n){let r=new Set(n),i=new Set(t),a=e.filter(e=>!P.has(e)&&r.has(e)&&(e!==b||i.has(e))),o=t.filter(e=>!we.has(e)&&!j.has(e)&&!P.has(e)&&r.has(e)),s=[d.MINOR_MODE_TOOL_NAME,...m.VOICE_MODE_TOOL_NAMES].filter(e=>i.has(e)&&r.has(e));return[...new Set([...a,...o,...s])]}function J(e){if(e.output=!1,e.progress=!1,e.worktree=!1,Array.isArray(e.parallel))for(let t of e.parallel)J(t);else e.parallel&&J(e.parallel)}function Je(e){if(e.action!==void 0){(0,p.isSubagentAction)(e.action)&&(0,p.subagentActionAcceptsField)(e.action,`artifacts`)&&(e.artifacts=!1);return}e.artifacts=!1,e.output=!1,e.share=!1,e.progress=!1,e.worktree=!1,delete e.chainDir,delete e.outputSchema,delete e.sessionDir;for(let t of e.tasks??[])J(t);for(let t of e.chain??[])J(t)}function Ye(e,t){if(!e?.model&&!e?.thinking)return;let n=e.model??(t?`${t.provider}/${t.id}`:void 0);if(n)return e.thinking?`${n.replace(/:(?:off|minimal|low|medium|high|xhigh|max)$/,``)}:${e.thinking}`:n}function Xe(e,t){if(e.action===`run`)for(let n of e.requests??[])n.model=t}function Ze(e,t){if(e.action===`assign`)for(let n of e.assignments??[])n.model=t}function Qe(e){return new Set([`append-step`,`create`,`delete`,`disable`,`eject`,`enable`,`grant-spawn-budget`,`reset`,`schedule`,`schedule-cancel`,`update`,`watchdog.configure`]).has(e??``)}function $e(e,t){let n=e.indexOf(`/`);if(n>0)return t.modelRegistry.find(e.slice(0,n),e.slice(n+1));let r=t.modelRegistry.getAvailable().filter(t=>t.id===e);return r.find(e=>e.provider===t.model?.provider)??(r.length===1?r[0]:void 0)}function et(e=process.env,n=process.cwd()){return t.loadDoomConfig((0,o.loadHarnessState)(e).state.root??n).modes?.planning}function tt(e){let t={key:`p`,label:`plan`,order:60};return[{id:`plan.normal`,path:[t,{key:`p`,label:`normal`,detail:`read-only planning`}],action:{name:`plan.normal`}},{id:`plan.debug`,path:[t,{key:`d`,label:`debug`,detail:`adaptive debug planning`}],action:{name:`plan.debug`}},{id:`plan.fable`,path:[t,{key:`f`,label:`fable`,detail:`repository-aware draft`}],action:{name:`plan.fable`}},...e?[{id:`plan.exit`,path:[t,{key:`e`,label:`exit`,detail:`restore and exit`}],action:{name:`plan.exit`}}]:[]]}function Y(e,t,c=et,p=r.createPlanTelemetry(),b={}){let S=!0,C=0,w,E,j,Te,Oe,ke=[],N=!1,P,L,R,z,B,V,ze=!1,H=!1,Ve,U,W=`idle`,G,K,q,Ge,J=Promise.resolve(),Y=b.doomIntegrations??!0,nt=new Set(b.debugDiagnosticTools??_e),rt=new AbortController;e.effect(()=>()=>ct(),`${D}/runtime`);let it=(0,u.createFablePlanBrokerClient)(()=>K?.sessionManager.getSessionId()),at=b.fableBroker??{start:(e,t)=>it.start(e,t),cancel:(e,t)=>it.cancel({requester:u.FABLE_PLAN_REQUESTER,operationId:e,reason:t})},ot=()=>b.fableBroker!==void 0||it.isAvailable();E=Y?(0,d.registerMinorModeOwner)(t,{descriptor:{source:D,id:`plan`,label:`Plan`,description:`Read-only planning with normal, debug, and Fable flavors.`,order:40,actions:[{id:le,label:`Activate`,description:`Activate plan mode or switch its planning flavor.`,contexts:[`tui`,`headless`],parameters:[{name:`flavor`,label:`Flavor`,kind:`enum`,required:!0,choices:[{value:`normal`,label:`Normal`},{value:`debug`,label:`Debug`},{value:`fable`,label:`Fable`}]}]},{id:ue,label:`Deactivate`,description:`Exit plan mode and restore the previous agent configuration.`,contexts:[`tui`,`headless`],parameters:[]}]},initialState:{activation:`inactive`,condition:`ready`,actions:[{id:le,enabled:!0},{id:ue,enabled:!1,disabledReason:`Plan mode is inactive.`}]},async handleAction(e,t,n){if(!S)throw Error(`Plan runtime is disposed.`);if(e===le){let e=t.flavor;if(e!==`normal`&&e!==`debug`&&e!==`fable`)throw Error(`A valid plan flavor is required.`);return await $(()=>gt(n.context,e,M,!1)),{message:`Plan mode is active with the ${e} flavor.`}}if(e===ue)return{message:await $(()=>_t(n.context,M))?`Plan mode deactivated.`:`Plan mode remains active.`};throw Error(`Unknown plan mode action: ${e}`)},onError:e=>void p.recordError(r.PLAN_EVENT.configLoadFailed,e)}):{publish:()=>void 0,dispose:()=>void 0},j=Y?(0,ie.createDoomLeaderContribution)(t,{source:D,bindings:tt(!1)}):{update:()=>void 0,dispose:()=>void 0};let st;Te=Y?(0,h.registerDoomConfigContribution)(t,{source:D,listSections:()=>{try{return i.planConfigSections(c(),st)}catch(e){return i.planConfigSections(void 0,e instanceof Error?e.message:String(e))}},handlers:{[h.CONFIG_ACTION.set]:async({fieldId:e,value:t})=>{let n=i.planSettingByFieldId(e);!n||!t||(st=void 0,await(0,ne.setDoomConfigValue)((0,o.globalDoomConfigPath)(),[...n.keyPath],t))},[h.CONFIG_ACTION.clear]:async({fieldId:e})=>{let t=i.planSettingByFieldId(e);t&&(st=void 0,await(0,ne.unsetDoomConfigValue)((0,o.globalDoomConfigPath)(),[...t.keyPath]))}},onError:e=>{S&&(st=e instanceof Error?e.message:String(e))}}):{dispose:()=>void 0,update:()=>void 0};function X(e=C){if(!S||e!==C)throw Error(`Plan runtime is disposed or stale.`)}function ct(){return w??=(async()=>{S=!1,C+=1,rt.abort(Error(`Plan runtime is shutting down.`));let e=K,n=L,r=[];Ge?.cancel(`Plan runtime is shutting down.`);let i=[J,...q?[q]:[]],a=await Promise.allSettled(i);for(let e of a)e.status===`rejected`&&r.push(e.reason);if(N&&n&&e)try{await pt(e,n,!0)&&t.setActiveTools(qe(n.tools,t.getActiveTools(),t.getAllTools().map(e=>e.name)))}catch(e){r.push(e)}let o=[()=>z?.dispose(),()=>Ve?.dispose(),()=>Oe?.(),()=>Te?.dispose(),...ke.map(e=>()=>e.dispose()),()=>j?.dispose(),()=>E?.dispose()];for(let e of o)try{e()}catch(e){r.push(e)}z=void 0,Ve=void 0,Oe=void 0,Te=void 0,ke.length=0,j=void 0,E=void 0,q=void 0,K=void 0,H=!1,N=!1,P=void 0,L=void 0,R=void 0;try{await p.shutdown()}catch(e){r.push(e)}if(r.length>0)throw AggregateError(r,`Plan runtime cleanup failed.`)})(),w}function lt(){S&&j?.update(tt(N))}function Z(e){if(!S)return;lt();let t=P,n=N&&t?`plan:${t}`:void 0,r=t===`fable`&&W!==`idle`?` · ${W}`:``;e.ui.setStatus(`plan-mode`,n?e.ui.theme.fg(O,n):void 0);let i={activation:N?`active`:`inactive`,condition:W===`failed`?`failed`:W===`interrupted`?`degraded`:`ready`,...N&&t?{detail:`${t}${r} - read only`,color:O}:{},actions:[{id:le,enabled:!0},...N?[{id:ue,enabled:!0}]:[{id:ue,enabled:!1,disabledReason:`Plan mode is inactive.`}]]};E?.publish(i)}function ut(){if(!S||!Y||!N||!P||!K)return;let e={owner:D,allowedTools:[...Ee],requiredTools:[x,`mcp`],allowMcpTools:!0,allowedExternalProfiles:P===`fable`?[n.FABLE_PLAN_PROFILE]:[],denyExtensions:!1};z?z.update(e):z=(0,f.registerSubagentPolicy)((0,re.createProtocolRuntime)({bus:t.events,source:D,sessionId:K.sessionManager.getSessionId()}),e)}function Q(){S&&t.appendEntry(_,{version:2,...N&&P?{activeFlavor:P}:{},...L?{originalSnapshot:{tools:[...L.tools],...L.model?{model:{...L.model}}:{},thinking:L.thinking}}:{},...V?{planId:V}:{},...G?{interruptedFableStage:G}:{}})}function dt(e,t,n){p.recordWarning(r.PLAN_EVENT.modelResolveFailed,`Planning model ${n}: ${t}`,{[pe]:t,"plan.model.phase":e,"plan.model.reason":n})}async function ft(e){let n=C;X(n);let r=R?.main;if(r){if(r.model){let i=$e(r.model,e);if(!i)e.ui.notify(`Planning model not found: ${r.model}`,O),dt(`apply`,r.model,me);else{let a=await t.setModel(i);X(n),a||(e.ui.notify(`Planning model is unavailable without authentication: ${r.model}`,O),dt(`apply`,r.model,he))}}X(n),r.thinking&&t.setThinkingLevel(r.thinking)}}async function pt(e,n,i=!1){let a=C;if(i||X(a),!n)return!1;if(n.model){let o=`${n.model.provider}/${n.model.id}`,s=e.modelRegistry.find(n.model.provider,n.model.id);if(!s)return e.ui.notify(`Previous model not found: ${o}`,O),dt(`restore`,o,me),!1;try{let n=await t.setModel(s);if(i||X(a),!n)return e.ui.notify(`Previous model is unavailable without authentication: ${o}`,O),dt(`restore`,o,he),!1}catch(t){return i||X(a),e.ui.notify(`Previous model could not be restored: ${o}`,O),dt(`restore`,o,ge),p.recordError(r.PLAN_EVENT.modelResolveFailed,t,{[pe]:o,"plan.model.phase":`restore`,"plan.model.reason":ge}),!1}}return i||X(a),t.setThinkingLevel(n.thinking),!0}function mt(e){N&&P?e.ui.notify(`Already in plan:${P}.`,de):e.ui.notify(`Plan mode is inactive.`,de)}function $(e){let t=C,n=async()=>{X(t);let n=await e();return X(t),n},r=J.then(n,n);return J=r.then(()=>void 0,()=>void 0),r}async function ht(e){let t=C;if(X(t),!q&&!W.match(/^(draft|review)$/u))return;(W===`draft`||W===`review`)&&(G=W),Ge?.cancel(e);let n=q;if(n)try{await n,X(t)}catch(e){X(t),p.recordError(r.PLAN_EVENT.modeDisabled,e,{[A]:`fable`,"plan.fable.reason":`cancel_failed`})}X(t),q=void 0,G&&(W=`interrupted`),K&&Z(K),Q()}async function gt(e,n,i,a){let o=C;if(X(o),K=e,N){if(P===n){mt(e);return}P===`fable`&&await ht(`Leaving Fable for plan:${n}.`),X(o),P=n,ut(),t.setActiveTools(Ke(L?.tools??[],t.getActiveTools(),t.getAllTools().map(e=>e.name),n,nt)),Z(e),Q(),p.recordEvent(r.PLAN_EVENT.modeEnabled,{[k]:i,[A]:n,"plan.tool.count":t.getActiveTools().length});return}let s;try{s=c()}catch(e){throw p.recordError(r.PLAN_EVENT.configLoadFailed,e,{[k]:i}),e}a?V??=Ie():(B=void 0,ze=!1,H=!1,V=Ie(),G=void 0,W=`idle`),R=s,L??={tools:[...t.getActiveTools()],...e.model?{model:{provider:e.model.provider,id:e.model.id}}:{},thinking:t.getThinkingLevel()},N=!0,P=n,t.setActiveTools(Ke(L.tools,t.getActiveTools(),t.getAllTools().map(e=>e.name),n,nt)),ut(),await ft(e),X(o),Z(e),Q(),p.recordEvent(r.PLAN_EVENT.modeEnabled,{[k]:i,[A]:n,"plan.tool.count":t.getActiveTools().length,...R?.main?.model?{[pe]:R.main.model}:{},...R?.main?.thinking?{"plan.thinking":R.main.thinking}:{}})}async function _t(e,n){let i=C;if(X(i),!N)return mt(e),!1;await ht(`Plan mode is exiting.`),X(i);let a=L,o=await pt(e,a);if(X(i),!o)return e.ui.notify(`Previous model was not restored. Plan mode remains read-only.`,O),Z(e),Q(),p.recordWarning(r.PLAN_EVENT.modeDisabled,`Plan mode restoration failed.`,{[k]:n,[A]:P??`unknown`,"plan.restored":!1}),!1;let s=!!B;return t.setActiveTools(qe(a?.tools??[],t.getActiveTools(),t.getAllTools().map(e=>e.name))),z?.dispose(),z=void 0,N=!1,P=void 0,R=void 0,H=!1,L=void 0,U=void 0,W=`idle`,G=void 0,Z(e),Q(),p.recordEvent(r.PLAN_EVENT.modeDisabled,{[k]:n,[A]:`normal`,"plan.written":s,"plan.restored":!0}),!0}if(Y){let e=t,n=e=>{if(X(),e.aborted)throw e.reason instanceof Error?e.reason:Error(`Plan voice transition was cancelled.`)},r={descriptor:{source:Ae,id:`plan-activate`,name:`activate_plan`,label:`Activate Plan`,description:`Activate or switch the serialized read-only planning mode flavor.`,order:10,inputSchema:je,resultSchema:Ne},execute(e,t){let r=Be(I(e)?e.flavor:void 0);if(!r)throw Error(`A valid plan flavor is required.`);return n(t.signal),$(async()=>{n(t.signal);let e=N,i=P;return await gt(t.context,r,De,!1),{active:N,flavor:P??r,changed:e!==N||i!==P}})}},i={descriptor:{source:Ae,id:`plan-exit`,name:`exit_plan`,label:`Exit Plan`,description:`Exit read-only planning mode and restore the previous agent configuration.`,order:20,inputSchema:Me,resultSchema:Ne},execute(e,t){return n(t.signal),$(async()=>{n(t.signal);let e=N,r=await _t(t.context,De);return{active:N,flavor:P??null,changed:e!==N||r}})}};ke.push((0,m.registerVoiceToolContribution)(e,r)),ke.push((0,m.registerVoiceToolContribution)(e,i))}Ge=n.createFablePlanFlow({broker:at,isAuthorized:()=>S&&N&&P===`fable`&&ot(),onStage:e=>{S&&(W=e,(e===`completed`||e===`failed`||e===`cancelled`)&&(G=void 0),K&&Z(K),N&&Q())},onError:e=>{S&&p.recordError(r.PLAN_EVENT.modeEnabled,e,{[A]:`fable`,"plan.fable.reason":`flow_error`})}}),t.registerTool({name:ce,label:`Record Debug Evidence`,description:`Record optional bounded debug evidence while planning a repository fix.`,promptSnippet:`Record the issue and any relevant reproduction, logs, traces, process output, or browser evidence`,parameters:{type:`object`,properties:{issue:{type:`string`},expectedBehavior:{type:`string`},reproductionAttempt:{type:`string`},actualBehavior:{type:`string`},logs:{type:`array`,items:{type:`string`}},correlatedTraceEvidence:{type:`array`,items:{type:`string`}},processOutput:{type:`array`,items:{type:`string`}},browserConsoleEvidence:{type:`array`,items:{type:`string`}},correlationIds:{type:`array`,items:{type:`string`}},timestamps:{type:`array`,items:{type:`string`}},verifiedFacts:{type:`array`,items:{type:`string`}},hypotheses:{type:`array`,items:{type:`string`}},unavailableEvidence:{type:`array`,items:{type:`string`}}},required:[`issue`],additionalProperties:!1},async execute(e,t){if(X(),!N||P!==`debug`)return{content:[{type:`text`,text:`Debug planning is not active.`}],details:{recorded:!1}};try{U=We(t)}catch(e){throw p.recordWarning(r.PLAN_EVENT.modeEnabled,e,{[A]:`debug`,"plan.debug.reason":`invalid_evidence`}),e}return K&&Z(K),{content:[{type:`text`,text:`Debug evidence recorded as optional planning context.`}],details:{recorded:!0}}}}),t.registerTool({name:T,label:`Run Fable Plan`,description:`Send a bounded, sanitized planning packet to the local Fable broker for one repository-aware draft.`,promptSnippet:`Run the local Fable draft with the bounded planning packet`,parameters:{type:`object`,properties:{goal:{type:`array`,items:{type:`string`}},constraints:{type:`array`,items:{type:`string`}},decisions:{type:`array`,items:{type:`string`}},verifiedFindings:{type:`array`,items:{type:`object`}},inferredFindings:{type:`array`,items:{type:`string`}},unresolvedQuestions:{type:`array`,items:{type:`string`}},currentPlan:{type:`string`}},additionalProperties:!1},async execute(e,t,n){let r=C;if(X(r),!N||P!==`fable`)return{content:[{type:`text`,text:`Fable planning is not active.`}],details:{started:!1}};if(!ot())return{content:[{type:`text`,text:`The local Fable broker is unavailable. Fable planning remains disabled.`}],details:{started:!1,errorCode:`broker_unavailable`}};let i=Ge;if(!i)throw Error(`Fable planning flow is unavailable.`);let a=i.run(t,n);q=a;try{let e=await a;return X(r),{content:[{type:`text`,text:e.draft?`Fable draft:\n${e.draft}`:`Fable planning ${e.status}: ${e.errorCode??`no output`}.`}],details:{...e,started:!0}}}finally{S&&r===C&&q===a&&(q=void 0)}}}),t.registerTool({name:y,label:`Write Plan`,description:`After presenting the complete implementation plan as Markdown in chat, save that visible plan to a unique Markdown file in the configured plans directory.`,promptSnippet:`Save the implementation plan already presented in chat to the configured plans directory`,parameters:{type:`object`,properties:{},additionalProperties:!1},async execute(e,n,i,a,c){let ne=C;if(X(ne),!N)return{content:[{type:`text`,text:`Plan mode is disabled. Use normal file tools instead.`}],details:{written:!1}};let u=Le(c.sessionManager.getBranch(),e);if(!u){let e=Error(`Present the complete implementation plan as visible Markdown in chat before calling write_plan.`);throw p.recordError(r.PLAN_EVENT.writePlanFailed,e,{"plan.reason":`missing_visible_plan`}),e}let d=Date.now(),re=(0,o.getHarnessState)().root??c.cwd,f=(0,o.resolvePlanningPlansDirectory)(R?.plansDirectory,re,ee.default.homedir()),m=Fe(c.sessionManager.getSessionId());V??=Ie();let h=B?.planId===V&&te.default.dirname(B.path)===f?B.path:void 0,ie=Pe(u),g=V,_=h??te.default.join(f,`${ie}--${g}.md`),v=new AbortController,y=Error(`Writing ${_} timed out after ${ve}ms.`),b=setTimeout(()=>v.abort(y),ve),x=AbortSignal.any([v.signal,rt.signal,...i?[i]:[]]),w=`checking`,oe=()=>{a?.({content:[{type:`text`,text:`${w===`checking`?`Checking`:`Writing`} ${_}...`}],details:{phase:w,path:_,startedAt:d}})},se=(e,t)=>{p.recordWarning(r.PLAN_EVENT.writePlanUnsafePath,t,{"plan.phase":w,"plan.refusal":e})};try{oe();try{await F(()=>l.default.promises.mkdir(f,{recursive:!0,mode:448}),x)}catch(e){throw x.aborted?Re(x):Error(`Could not create the configured plans directory ${f}.`,{cause:e})}let e=await F(()=>l.default.promises.lstat(f),x),n=await F(()=>l.default.promises.realpath(f),x);if(e.isSymbolicLink()||!e.isDirectory())return se(`unsafe_plans_directory`,`Refused to write the plan because the configured path is unsafe.`),{content:[{type:`text`,text:`Refused to write the plan because the configured path is unsafe.`}],details:{written:!1,path:_,phase:w,durationMs:Date.now()-d}};X(ne),w=`writing`,oe();let i;try{for(let e=0;e<3;e+=1)try{let e=h?0:l.default.constants.O_EXCL;i=await F(()=>l.default.promises.open(_,l.default.constants.O_CREAT|l.default.constants.O_WRONLY|l.default.constants.O_NONBLOCK|l.default.constants.O_NOFOLLOW|e,384),x);break}catch(t){if(!(!h&&t instanceof Error&&`code`in t&&String(t.code)===`EEXIST`)||e===2)throw t;g=Ie(),V=g,_=te.default.join(f,`${ie}--${g}.md`),Q()}if(!i)throw Error(`Could not allocate a unique plan filename in ${f}.`);let e=await F(()=>l.default.promises.realpath(f),x),t=await F(()=>i.stat(),x);if(e!==n||!t.isFile()||t.nlink!==1)return se(`invalid_destination`,fe),{content:[{type:`text`,text:fe}],details:{written:!1,path:_,phase:w,durationMs:Date.now()-d}};await F(()=>i.truncate(0),x),await F(()=>i.writeFile(u,{encoding:`utf8`,signal:x}),x)}catch(e){if(e instanceof Error&&`code`in e&&[`EISDIR`,`ELOOP`,`ENXIO`].includes(String(e.code)))return se(`invalid_destination`,fe),{content:[{type:`text`,text:fe}],details:{written:!1,path:_,phase:w,durationMs:Date.now()-d}};throw e}finally{await i?.close()}return X(ne),B={content:u,path:_,sessionId:m,planId:g,title:ie,writtenAt:new Date().toISOString()},t.appendEntry(ae,B),ze=!0,H=!1,p.recordEvent(r.PLAN_EVENT.planWritten,{"plan.written":!0,"plan.bytes":s.Buffer.byteLength(u,`utf8`),"plan.duration_ms":Date.now()-d,"plan.revised":!!h}),{content:[{type:`text`,text:`Wrote implementation plan to ${_}.`}],details:{written:!0,path:_,phase:w,durationMs:Date.now()-d}}}catch(e){if(!S||ne!==C)throw Re(rt.signal);let t={"plan.phase":w,"plan.duration_ms":Date.now()-d};if(v.signal.aborted&&!i?.aborted){let n=Error(`write_plan timed out during ${w} for ${_}.`,{cause:e});throw p.recordError(r.PLAN_EVENT.writePlanTimedOut,n,{...t,"plan.timeout_ms":ve}),n}throw p.recordError(r.PLAN_EVENT.writePlanFailed,e,{...t,"plan.cancelled":i?.aborted??!1}),e}finally{clearTimeout(b)}}});async function vt(e,t){if(X(),p.recordEvent(r.PLAN_EVENT.planReviewCompleted,{"plan.outcome":e===xe?`exited`:`continued`}),e===xe){let e=await $(()=>_t(t,`plan_approved`));return{content:[{type:`text`,text:e?`The user approved exiting plan mode. Full tool access is restored. Begin implementing the approved plan.`:`The previous model could not be restored. Plan mode remains read-only.`}],details:{exited:e}}}return ze=!1,{content:[{type:`text`,text:`The user chose to continue planning. Remain read-only and refine the plan.`}],details:{exited:!1}}}t.registerTool({name:v,label:`Complete Plan`,description:`Present the saved implementation plan for exit-or-continue approval. Interactive sessions use the normal selector; autonomous voice narrates a plain-text handoff and waits for the next user message.`,promptSnippet:`Request explicit exit-or-continue approval after the saved plan has been presented`,promptGuidelines:[`After write_plan succeeds, call complete_plan without a decision so it can present the review question.`,`When autonomous voice returns an awaiting-response result, stop. Interpret the next ordinary user message, then call complete_plan again with decision "exit" or "continue".`,`Never pass decision "${xe}" without the user explicitly choosing "${ye}".`],parameters:{type:`object`,properties:{decision:{type:`string`,enum:[xe,Se]}},additionalProperties:!1},async execute(e,t,n,i,a){let o=C;if(X(o),!N)return{content:[{type:`text`,text:`Plan mode is already disabled.`}],details:{exited:!1}};if(!ze)return{content:[{type:`text`,text:`Present the complete plan in chat and save it with write_plan before requesting approval.`}],details:{exited:!1}};if(!a.hasUI)return p.recordEvent(r.PLAN_EVENT.planReviewCompleted,{"plan.outcome":`no_ui`}),{content:[{type:`text`,text:`The plan is complete, but this run cannot ask the user interactively. Remain in plan mode until the user uses SPC p e.`}],details:{exited:!1}};let s=I(t)?t.decision:void 0,c=s===xe||s===Se;if(H){if(!c)throw Error(`The narrated plan review is waiting for an explicit exit or continue decision.`);return H=!1,vt(s,a)}if(s!==void 0)throw Error(`Call complete_plan without a decision before submitting a narrated plan-review answer.`);let l=Ve?.handoff(Ce);if(l)return H=!0,(0,g.buildVoiceToolResult)(l);let ee=await a.ui.select(`Plan complete. What would you like to do?`,[ye,be]);return X(o),vt(ee===ye?xe:Se,a)}}),Y&&(Oe=(0,ie.registerDoomLeaderActionHandlers)(t,{source:D,handlers:{"plan.normal":()=>{let e=S?K:void 0;return e?$(()=>gt(e,`normal`,M,!1)):void 0},"plan.exit":()=>{let e=S?K:void 0;return e?$(async()=>{await _t(e,M)}):void 0},"plan.debug":()=>{let e=S?K:void 0;return e?$(()=>gt(e,`debug`,M,!1)):void 0},"plan.fable":()=>{let e=S?K:void 0;return e?$(()=>gt(e,`fable`,M,!1)):void 0}},onError:(e,t)=>{S&&(K?.hasUI&&K.ui.notify(`Leader action ${t} failed. Plan mode remains read-only.`,O),p.recordError(r.PLAN_EVENT.modeEnabled,e,{[k]:M,"plan.action":t}))}})),t.on(`tool_call`,async(e,t)=>{if(!S||!N)return;let n=P===`debug`&&(e.toolName===ce||nt.has(e.toolName))||P===`fable`&&e.toolName===T;if(!we.has(e.toolName)&&!n)return{block:!0,reason:`Plan mode blocks the ${e.toolName} tool. Use SPC p e to restore access.`};let r=Ye(R?.subagents,t.model);if(e.toolName===se){r&&Ze(e.input,r);return}if(e.toolName!==oe)return;let i=e.input;if(Qe(i.action))return{block:!0,reason:`Plan mode blocks subagent management action '${i.action}'. Use SPC p e first.`};Je(i),r&&Xe(i,r)}),t.on(`before_agent_start`,async(e,t)=>{if(!S)return;let n=[];if(N){let e=(0,o.getHarnessState)().root??t.cwd,r=(0,o.resolvePlanningPlansDirectory)(R?.plansDirectory,e,ee.default.homedir());n.push(`[PLAN MODE ACTIVE]\nYou are in repository read-only plan mode. The dedicated write_plan tool may write one unique Markdown plan file under ${r}.\n\nExplore the codebase and produce a concrete implementation plan. For every plan, first call subagent with action "agents", cluster the exploration by independent domain, subsystem, or integration boundary, and create a provisional task graph with the task tool. Select specialized agents by matching their names and descriptions to each cluster. Assign every unblocked delegated task through the task tool, and use a one-shot inlineAgent with a focused systemPrompt when no discovered specialist fits. Treat the initial graph as provisional, not as a fixed contract. After findings arrive, review the entire graph at least once and perform one to three review passes in total. In each pass, use the evidence to add, rewrite, delete, cancel, reassign, or change blockedBy relationships for tasks when warranted. Do not keep following tasks that new information has made stale. Stop revising early when the graph is stable, or after the third pass.\n\nEvery plan must end with a delegated planning-draft stage blocked by all exploration and decision tasks. A single-boundary plan gets one planning draft. A complex plan spanning multiple subsystems, domains, packages, apps, or integration boundaries gets two planning drafts concurrently. Use three concurrent drafts instead when the work is cross-layer, migration-sensitive, security-sensitive, or similarly high risk. Assign each draft through the task tool to the discovered "planner" agent with context "fork" so it receives the conversation and gathered evidence. If the planner agent is unavailable, assign the same draft task through the task tool with a focused inlineAgent. All children receive read, Bash, grep, find, ls, and configured MCP tools with artifacts disabled. Bash and MCP tools are for read-only inspection and must not modify files, external systems, or repository state. Doom Team runs asynchronously, so do not poll. After launch, continue non-overlapping exploration or end your turn; completion notifications wake the parent session.\n\nAfter all planning drafts complete, the main agent must compare the candidates, pick the strongest draft, cross-check it against the gathered evidence and the other drafts, resolve conflicts and gaps, and ask the user only for product decisions. A child produces the draft, but the main agent owns and synthesizes the final plan. Do not modify files or repository state except through write_plan. Start the final plan with a meaningful Markdown H1 because write_plan derives the filename from it. Present the complete plan as visible Markdown in chat, then call write_plan with no arguments. After write_plan succeeds, clear the completed durable task graph and call complete_plan without a decision. In an interactive text session, complete_plan uses the normal exit-or-continue selector. Under autonomous voice, it displays and narrates the choices without opening a blocking dialog, then ends the turn. Interpret the user's next ordinary message and call complete_plan again with decision "exit" or "continue". Do not exit plan mode without explicit approval.`,a.buildFlavorPlanningPrompt(P,r,U,W))}if(B&&n.push(`[CURRENT PLAN]\nSource: ${B.path}\n\n${B.content}`),n.length!==0)return{systemPrompt:`${e.systemPrompt}\n\n${n.join(`
4
+
5
+ `)}`}}),t.on(`context`,async e=>{if(S)return{messages:e.messages.filter(e=>e.customType!==`agent-harness-plan-mode-context`)}}),t.on(`session_start`,async(e,n)=>{if(!S)return;let r=++C,i=n.sessionManager.getEntries(),a=i.flatMap(e=>e.type===`custom`&&e.customType===_?[He(e.data)]:[]).filter(e=>e!==void 0).at(-1),o=n.sessionManager.getSessionId(),s=Fe(o);Ve?.dispose(),Ve=Y?(0,g.createVoiceQuestionHandoff)({bus:t.events,source:D,sessionId:o}):void 0;let c=i.flatMap(e=>e.type===`custom`&&e.customType===ae?[Ue(e.data)]:[]).filter(e=>e!==void 0).at(-1),l=L;if(z?.dispose(),z=void 0,B=c?.sessionId===s?c:void 0,V=a?.planId??B?.planId,ze=!1,H=!1,R=void 0,U=void 0,N=!1,P=void 0,lt(),L=a?.originalSnapshot,G=a?.interruptedFableStage,W=G?`interrupted`:`idle`,K=n,a?.activeFlavor)await gt(n,a.activeFlavor,`session_restore`,!0),X(r);else{let e=a?.originalSnapshot??l;if(e){let i=await pt(n,e);X(r),i&&t.setActiveTools(qe(e.tools,t.getActiveTools(),t.getAllTools().map(e=>e.name)))}else t.setActiveTools(t.getActiveTools().filter(e=>e!==v&&e!==y&&e!==ce&&e!==T));X(r),L=void 0,Z(n)}})}exports.WRITE_PLAN_TIMEOUT_MS=ve,exports.configurePlanningSubagentInput=Xe,exports.configurePlanningTaskInput=Ze,exports.constrainSubagentInput=Je,exports.createPlanIdentifier=Ie,exports.isBlockedSubagentManagementAction=Qe,exports.loadPlanningModeConfig=et,exports.parseDebugEvidencePacket=We,exports.parsePersistedPlanState=He,exports.planModeExtension=Y,exports.planModeTools=Ge,exports.planSessionIdentifier=Fe,exports.planTitleSlug=Pe,exports.planningSubagentModel=Ye,exports.visiblePlanForToolCall=Le;
6
+ //# sourceMappingURL=planMode.cjs.map