@posthog/wizard 2.81.1 → 2.83.0

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 (124) hide show
  1. package/dist/{agent-interface-DMP3DZRd.js → agent-interface-fcDXqb-_.js} +285 -66
  2. package/dist/agent-interface-fcDXqb-_.js.map +1 -0
  3. package/dist/{agent-prompt-loader-BrivWIna.js → agent-prompt-loader-F9gGPMt0.js} +6 -6
  4. package/dist/{agent-prompt-loader-BrivWIna.js.map → agent-prompt-loader-F9gGPMt0.js.map} +1 -1
  5. package/dist/analytics-C9QnGvuc.js +2 -0
  6. package/dist/{analytics-X7JfAmh6.js → analytics-GQv--mQm.js} +6 -4
  7. package/dist/analytics-GQv--mQm.js.map +1 -0
  8. package/dist/api-CsXfZKkq.js +2 -0
  9. package/dist/{api-BkDwZoL4.js → api-WUOSLXPJ.js} +71 -3
  10. package/dist/{api-BkDwZoL4.js.map → api-WUOSLXPJ.js.map} +1 -1
  11. package/dist/api-key-login-CDSxsYtP.js +2 -0
  12. package/dist/{api-key-login-DE0yKkP4.js → api-key-login-tysMeZnR.js} +5 -5
  13. package/dist/{api-key-login-DE0yKkP4.js.map → api-key-login-tysMeZnR.js.map} +1 -1
  14. package/dist/bin.js +1 -1
  15. package/dist/{bounded-fs-iDiqDQ9v.js → bounded-fs-B31zq2ir.js} +6 -4
  16. package/dist/bounded-fs-B31zq2ir.js.map +1 -0
  17. package/dist/{ci-install-BAftKh2Z.js → ci-install-CYSFbFXd.js} +4 -4
  18. package/dist/{ci-install-BAftKh2Z.js.map → ci-install-CYSFbFXd.js.map} +1 -1
  19. package/dist/{debug-C3tLP-ZW.js → debug-BTUMatFI.js} +3 -3
  20. package/dist/{debug-C3tLP-ZW.js.map → debug-BTUMatFI.js.map} +1 -1
  21. package/dist/{gateway-IQjQ582o.js → gateway-CJ8Jqbll.js} +20 -6
  22. package/dist/{gateway-IQjQ582o.js.map → gateway-CJ8Jqbll.js.map} +1 -1
  23. package/dist/{headless-XNvdWVEp.js → headless-DZ3mq07K.js} +1 -1
  24. package/dist/{headless-DOhxEmw5.js → headless-le-QqOuj.js} +2 -2
  25. package/dist/{headless-DOhxEmw5.js.map → headless-le-QqOuj.js.map} +1 -1
  26. package/dist/{host-resolution-DI2oucSK.js → host-resolution-Cht8bL39.js} +4 -4
  27. package/dist/{host-resolution-DI2oucSK.js.map → host-resolution-Cht8bL39.js.map} +1 -1
  28. package/dist/{install-DaZ6pvEl.js → install-55JbRsO-.js} +1 -1
  29. package/dist/{install-BixbBDLR.js → install-BhnFP3p3.js} +5 -5
  30. package/dist/{install-BixbBDLR.js.map → install-BhnFP3p3.js.map} +1 -1
  31. package/dist/{interactive-WLNQWF0D.js → interactive-9qRL8259.js} +3 -3
  32. package/dist/{interactive-WLNQWF0D.js.map → interactive-9qRL8259.js.map} +1 -1
  33. package/dist/{links-Bye4fsrj.js → links-5Blqk4Im.js} +3 -3
  34. package/dist/{links-Bye4fsrj.js.map → links-5Blqk4Im.js.map} +1 -1
  35. package/dist/{main-CN8nbuZO.js → main-CUIcozEG.js} +24 -21
  36. package/dist/main-CUIcozEG.js.map +1 -0
  37. package/dist/{mcp-B2o4d9DS.js → mcp-D73aCOHK.js} +3 -3
  38. package/dist/{mcp-B2o4d9DS.js.map → mcp-D73aCOHK.js.map} +1 -1
  39. package/dist/{mcp-prompt-streaming-COs1DfAm.js → mcp-prompt-streaming-B5lIQ0l1.js} +5 -5
  40. package/dist/{mcp-prompt-streaming-COs1DfAm.js.map → mcp-prompt-streaming-B5lIQ0l1.js.map} +1 -1
  41. package/dist/{models-Cow22jET.js → models-CLTglHFZ.js} +6 -2
  42. package/dist/models-CLTglHFZ.js.map +1 -0
  43. package/dist/{oauth-session-Bj_-BY7o.js → oauth-session-CfkZ339p.js} +45 -3
  44. package/dist/oauth-session-CfkZ339p.js.map +1 -0
  45. package/dist/{orchestrator-tools-lhFIBGnp.js → orchestrator-tools-lvNVQhzs.js} +3 -3
  46. package/dist/{orchestrator-tools-lhFIBGnp.js.map → orchestrator-tools-lvNVQhzs.js.map} +1 -1
  47. package/dist/{package-manager-DZ4wcTz3.js → package-manager-BqRNp5y_.js} +4 -4
  48. package/dist/{package-manager-DZ4wcTz3.js.map → package-manager-BqRNp5y_.js.map} +1 -1
  49. package/dist/{pi-DREdQRPP.js → pi-2pYz2OY3.js} +61 -24
  50. package/dist/pi-2pYz2OY3.js.map +1 -0
  51. package/dist/{playground-CJx3lwTH.js → playground-jxZNxRwC.js} +4 -4
  52. package/dist/{playground-CJx3lwTH.js.map → playground-jxZNxRwC.js.map} +1 -1
  53. package/dist/{posthog-integration-DDSPdbpw.js → posthog-integration-DxRkw5DI.js} +79 -36
  54. package/dist/posthog-integration-DxRkw5DI.js.map +1 -0
  55. package/dist/{programs-DvlhdeM_.js → programs-D2793-PK.js} +2 -2
  56. package/dist/{programs-6SFfUBmm.js → programs-eTv2T2rs.js} +142 -62
  57. package/dist/programs-eTv2T2rs.js.map +1 -0
  58. package/dist/provisioning-CtQ0GEHa.js +2 -0
  59. package/dist/{provisioning-tRDPH7EQ.js → provisioning-c5JJ30KX.js} +4 -4
  60. package/dist/{provisioning-tRDPH7EQ.js.map → provisioning-c5JJ30KX.js.map} +1 -1
  61. package/dist/{queue-tools-DrJKvFHZ.js → queue-tools-10w8lhEs.js} +14 -5
  62. package/dist/queue-tools-10w8lhEs.js.map +1 -0
  63. package/dist/{results-Crcubw0Q.js → results-C45prSKD.js} +2 -2
  64. package/dist/{results-Crcubw0Q.js.map → results-C45prSKD.js.map} +1 -1
  65. package/dist/{run-DVFTMbxf.js → run-CM24OgPF.js} +10 -10
  66. package/dist/{run-DVFTMbxf.js.map → run-CM24OgPF.js.map} +1 -1
  67. package/dist/{run-BrIGaPy7.js → run-jugssomh.js} +7 -7
  68. package/dist/{run-BrIGaPy7.js.map → run-jugssomh.js.map} +1 -1
  69. package/dist/run-tool-BZFgFb_2.js +2 -0
  70. package/dist/{run-tool-CxdPXmlY.js → run-tool-DZrZFoGq.js} +13 -13
  71. package/dist/{run-tool-CxdPXmlY.js.map → run-tool-DZrZFoGq.js.map} +1 -1
  72. package/dist/{runners-loOOmHyc.js → runners-CoIYt0iI.js} +8 -8
  73. package/dist/{runners-loOOmHyc.js.map → runners-CoIYt0iI.js.map} +1 -1
  74. package/dist/{security-C_grSgIM.js → security-ppK2MwCn.js} +6 -5
  75. package/dist/{security-C_grSgIM.js.map → security-ppK2MwCn.js.map} +1 -1
  76. package/dist/{setup-utils-BYXbb9NM.js → setup-utils-B5E1rXLa.js} +3 -3
  77. package/dist/{setup-utils-BYXbb9NM.js.map → setup-utils-B5E1rXLa.js.map} +1 -1
  78. package/dist/{start-playground-Blh0Swil.js → start-playground-DujiUNFT.js} +7 -7
  79. package/dist/{start-playground-Blh0Swil.js.map → start-playground-DujiUNFT.js.map} +1 -1
  80. package/dist/{subagent-DQ_enM8C.js → subagent-BdDWA8j5.js} +12 -4
  81. package/dist/subagent-BdDWA8j5.js.map +1 -0
  82. package/dist/{task-Dm9wZbVW.js → task-Y8lWoDE7.js} +46 -23
  83. package/dist/task-Y8lWoDE7.js.map +1 -0
  84. package/dist/{telemetry-NeZhrBeW.js → telemetry-Cwqf0iur.js} +2 -2
  85. package/dist/{telemetry-NeZhrBeW.js.map → telemetry-Cwqf0iur.js.map} +1 -1
  86. package/dist/{terminal-Z4hCXfie.js → terminal-BLL-X6YP.js} +401 -41
  87. package/dist/terminal-BLL-X6YP.js.map +1 -0
  88. package/dist/{tools-dUJHRo6X.js → tools-C8k90ISV.js} +13 -13
  89. package/dist/{tools-dUJHRo6X.js.map → tools-C8k90ISV.js.map} +1 -1
  90. package/dist/{tools-1aM6bI9Y.js → tools-g42e5kJz.js} +15 -11
  91. package/dist/tools-g42e5kJz.js.map +1 -0
  92. package/dist/{tui-CCO7VVTA.js → tui-BPWJ-J-k.js} +1 -1
  93. package/dist/{tui-Cmi_ckGg.js → tui-CBnRWnrm.js} +4 -4
  94. package/dist/tui-CBnRWnrm.js.map +1 -0
  95. package/dist/{upload-step-e2Jp2fcr.js → upload-step-CFoxwd5t.js} +3 -3
  96. package/dist/{upload-step-e2Jp2fcr.js.map → upload-step-CFoxwd5t.js.map} +1 -1
  97. package/dist/{urls-Cu4RO30x.js → urls-BTZhm5eA.js} +2 -2
  98. package/dist/{urls-Cu4RO30x.js.map → urls-BTZhm5eA.js.map} +1 -1
  99. package/dist/{wizard-abort-BPEiPCXk.js → wizard-abort-HtpiSsQO.js} +4 -4
  100. package/dist/{wizard-abort-BPEiPCXk.js.map → wizard-abort-HtpiSsQO.js.map} +1 -1
  101. package/dist/{yara-hooks-canFIYTc.js → yara-hooks-BPYhN9WM.js} +4 -4
  102. package/dist/{yara-hooks-canFIYTc.js.map → yara-hooks-BPYhN9WM.js.map} +1 -1
  103. package/dist/{yara-hooks-CFD60h78.js → yara-hooks-BwhEDXIt.js} +1 -1
  104. package/package.json +1 -1
  105. package/dist/agent-interface-DMP3DZRd.js.map +0 -1
  106. package/dist/analytics-X7JfAmh6.js.map +0 -1
  107. package/dist/analytics-dcL9EQ4r.js +0 -2
  108. package/dist/api-BrMGAI-b.js +0 -2
  109. package/dist/api-key-login-CZEgx2jb.js +0 -2
  110. package/dist/bounded-fs-iDiqDQ9v.js.map +0 -1
  111. package/dist/main-CN8nbuZO.js.map +0 -1
  112. package/dist/models-Cow22jET.js.map +0 -1
  113. package/dist/oauth-session-Bj_-BY7o.js.map +0 -1
  114. package/dist/pi-DREdQRPP.js.map +0 -1
  115. package/dist/posthog-integration-DDSPdbpw.js.map +0 -1
  116. package/dist/programs-6SFfUBmm.js.map +0 -1
  117. package/dist/provisioning-CPGWgv7p.js +0 -2
  118. package/dist/queue-tools-DrJKvFHZ.js.map +0 -1
  119. package/dist/run-tool-GfISLgEs.js +0 -2
  120. package/dist/subagent-DQ_enM8C.js.map +0 -1
  121. package/dist/task-Dm9wZbVW.js.map +0 -1
  122. package/dist/terminal-Z4hCXfie.js.map +0 -1
  123. package/dist/tools-1aM6bI9Y.js.map +0 -1
  124. package/dist/tui-Cmi_ckGg.js.map +0 -1
@@ -1,4 +1,32 @@
1
- import { o as logToFile } from "./debug-C3tLP-ZW.js";
1
+ import { o as logToFile } from "./debug-BTUMatFI.js";
2
+ //#region src/shared/auth-session-state.ts
3
+ /**
4
+ * Whether this run's OAuth grant is known to be dead.
5
+ *
6
+ * Process-global on purpose. A run has exactly one login, but the two sides of
7
+ * this fact are far apart: the pre-run refresh learns it in `authenticate.ts`,
8
+ * and the only consumer is the 401 handler inside the agent message loop, which
9
+ * holds no session. Threading it would mean a field on `AgentConfig` set at four
10
+ * `initializeAgent` call sites — and the session it would read from may be a
11
+ * shallow copy (`prepareRunSession`), so the value could be written to one
12
+ * object and read from another.
13
+ *
14
+ * A leaf module with no imports, so either side can depend on it without a cycle.
15
+ */
16
+ let grantRevoked = false;
17
+ /**
18
+ * Record that the token endpoint permanently refused this grant. Not an abort:
19
+ * the access token in hand may still have minutes of life, so the run continues
20
+ * and this only decides what a later 401 gets blamed on.
21
+ */
22
+ function markGrantRevoked() {
23
+ grantRevoked = true;
24
+ }
25
+ /** True once a token refresh failed because the grant itself is gone. */
26
+ function isGrantRevoked() {
27
+ return grantRevoked;
28
+ }
29
+ //#endregion
2
30
  //#region src/shared/oauth-session.ts
3
31
  const REFRESH_WHEN_REMAINING_MS = 3e3 * 1e3;
4
32
  let current = null;
@@ -23,6 +51,20 @@ function configureOAuthSession(credentials, options) {
23
51
  lineage.add(credentials.accessToken);
24
52
  current = credentials;
25
53
  }
54
+ /**
55
+ * Rotate the token after a 401 so the caller can retry once. `refused`: the
56
+ * grant is revoked, or `requireRefreshToken` is set and none is held, so no
57
+ * rotation was tried. `unchanged`: the rotation failed and the token is the
58
+ * same, so a retry would 401 again.
59
+ */
60
+ async function rotateAfterUnauthorized(credentials, options) {
61
+ if (options.requireRefreshToken && !credentials.refreshToken || isGrantRevoked()) return { kind: "refused" };
62
+ const rotated = await currentCredentials(credentials, true);
63
+ return rotated.accessToken === credentials.accessToken ? { kind: "unchanged" } : {
64
+ kind: "rotated",
65
+ credentials: rotated
66
+ };
67
+ }
26
68
  /** A key that stays the same across this login's rotations, so caches keyed on it survive one. */
27
69
  function oauthLoginKey(accessToken) {
28
70
  return lineageRoot && lineage.has(accessToken) ? lineageRoot : accessToken;
@@ -69,6 +111,6 @@ async function refresh(rotateWith, credentials) {
69
111
  return refreshed;
70
112
  }
71
113
  //#endregion
72
- export { onAccessTokenRotated as a, oauthLoginKey as i, currentAccessToken as n, currentCredentials as r, configureOAuthSession as t };
114
+ export { oauthLoginKey as a, isGrantRevoked as c, oauthCredentials as i, markGrantRevoked as l, currentAccessToken as n, onAccessTokenRotated as o, currentCredentials as r, rotateAfterUnauthorized as s, configureOAuthSession as t };
73
115
 
74
- //# sourceMappingURL=oauth-session-Bj_-BY7o.js.map
116
+ //# sourceMappingURL=oauth-session-CfkZ339p.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-session-CfkZ339p.js","names":[],"sources":["../src/shared/auth-session-state.ts","../src/shared/oauth-session.ts"],"sourcesContent":["/**\n * Whether this run's OAuth grant is known to be dead.\n *\n * Process-global on purpose. A run has exactly one login, but the two sides of\n * this fact are far apart: the pre-run refresh learns it in `authenticate.ts`,\n * and the only consumer is the 401 handler inside the agent message loop, which\n * holds no session. Threading it would mean a field on `AgentConfig` set at four\n * `initializeAgent` call sites — and the session it would read from may be a\n * shallow copy (`prepareRunSession`), so the value could be written to one\n * object and read from another.\n *\n * A leaf module with no imports, so either side can depend on it without a cycle.\n */\n\nlet grantRevoked = false;\n\n/**\n * Record that the token endpoint permanently refused this grant. Not an abort:\n * the access token in hand may still have minutes of life, so the run continues\n * and this only decides what a later 401 gets blamed on.\n */\nexport function markGrantRevoked(): void {\n grantRevoked = true;\n}\n\n/** True once a token refresh failed because the grant itself is gone. */\nexport function isGrantRevoked(): boolean {\n return grantRevoked;\n}\n\n/** Test hook, mirroring `resetGatewaySession`. */\nexport function resetAuthSessionState(): void {\n grantRevoked = false;\n}\n","// The run's one OAuth token, shaped like gateway-session. The host supplies the rotation.\n\nimport type { Credentials } from '@shared/api';\nimport { isGrantRevoked } from '@shared/auth-session-state';\nimport { logToFile } from '@utils/debug';\n\n// Below this remaining lifetime a run risks outliving its token; just-minted and 7-day tokens skip.\nconst REFRESH_WHEN_REMAINING_MS = 50 * 60 * 1000;\n\n/** Returns the rotated credentials, or the same object when the rotation failed. Never throws. */\nexport type RotateCredentials = (\n credentials: Credentials,\n) => Promise<Credentials>;\n\nlet current: Credentials | null = null;\nlet rotate: RotateCredentials | undefined;\nlet onRefreshed: ((credentials: Credentials) => void) | undefined;\n// Shared so concurrent callers rotate once: a second rotation would spend the refresh token the first replaced.\nlet inFlight: Promise<Credentials> | null = null;\nconst listeners = new Set<(accessToken: string) => void>();\n// Every access token this login has held; the first one names the login.\nlet lineage = new Set<string>();\nlet lineageRoot: string | undefined;\n\n/** Adopt the run's credentials; a stale copy of the held login gets the newer one back through `onRefreshed`. */\nexport function configureOAuthSession(\n credentials: Credentials,\n options: {\n rotate: RotateCredentials;\n onRefreshed?: (credentials: Credentials) => void;\n },\n): void {\n rotate = options.rotate;\n onRefreshed = options.onRefreshed;\n if (\n current &&\n sameLogin(current, credentials) &&\n (current.expiresAt ?? 0) > (credentials.expiresAt ?? 0)\n ) {\n onRefreshed?.(current);\n return;\n }\n if (!current || !sameLogin(current, credentials)) {\n lineage = new Set();\n lineageRoot = credentials.accessToken;\n }\n lineage.add(credentials.accessToken);\n current = credentials;\n}\n\n/** What a caller does after a 401: retry with `credentials`, or stop for the stated reason. */\nexport type UnauthorizedRecovery =\n | { kind: 'rotated'; credentials: Credentials }\n | { kind: 'refused' }\n | { kind: 'unchanged' };\n\n/**\n * Rotate the token after a 401 so the caller can retry once. `refused`: the\n * grant is revoked, or `requireRefreshToken` is set and none is held, so no\n * rotation was tried. `unchanged`: the rotation failed and the token is the\n * same, so a retry would 401 again.\n */\nexport async function rotateAfterUnauthorized(\n credentials: Credentials,\n options: { requireRefreshToken: boolean },\n): Promise<UnauthorizedRecovery> {\n if (\n (options.requireRefreshToken && !credentials.refreshToken) ||\n isGrantRevoked()\n ) {\n return { kind: 'refused' };\n }\n const rotated = await currentCredentials(credentials, true);\n return rotated.accessToken === credentials.accessToken\n ? { kind: 'unchanged' }\n : { kind: 'rotated', credentials: rotated };\n}\n\n/** A key that stays the same across this login's rotations, so caches keyed on it survive one. */\nexport function oauthLoginKey(accessToken: string): string {\n return lineageRoot && lineage.has(accessToken) ? lineageRoot : accessToken;\n}\n\n/** The current credentials, refreshed first when near expiry or when `force` is set. */\nexport async function oauthCredentials(\n force = false,\n): Promise<Credentials | null> {\n if (!current) return null;\n if (!rotate || !current.refreshToken || (!force && !nearExpiry(current)))\n return current;\n inFlight ??= refresh(rotate, current).finally(() => {\n inFlight = null;\n });\n return inFlight;\n}\n\n/** The credentials to use now for this login, or the fallback when another login is held. */\nexport async function currentCredentials(\n fallback: Credentials,\n force = false,\n): Promise<Credentials> {\n if (!current || !sameLogin(current, fallback)) return fallback;\n return (await oauthCredentials(force)) ?? fallback;\n}\n\n/** The access token to use now for this login. */\nexport async function currentAccessToken(\n fallback: Credentials,\n): Promise<string> {\n return (await currentCredentials(fallback)).accessToken;\n}\n\n/** Called with each new access token after a rotation. Returns the unsubscribe. */\nexport function onAccessTokenRotated(\n listener: (accessToken: string) => void,\n): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\n/** Test hook: drop the held credentials so the next run configures afresh. */\nexport function resetOAuthSession(): void {\n current = null;\n rotate = undefined;\n onRefreshed = undefined;\n inFlight = null;\n listeners.clear();\n lineage = new Set();\n lineageRoot = undefined;\n}\n\nfunction sameLogin(a: Credentials, b: Credentials): boolean {\n return a.host.apiHost === b.host.apiHost && a.projectId === b.projectId;\n}\n\nfunction nearExpiry(credentials: Credentials): boolean {\n // No expiry means we cannot tell how much life is left, so leave it alone.\n return (\n credentials.expiresAt !== undefined &&\n credentials.expiresAt - Date.now() < REFRESH_WHEN_REMAINING_MS\n );\n}\n\nasync function refresh(\n rotateWith: RotateCredentials,\n credentials: Credentials,\n): Promise<Credentials> {\n const refreshed = await rotateWith(credentials);\n if (refreshed === credentials) return credentials;\n logToFile('[oauth-session] token rotated');\n lineage.add(refreshed.accessToken);\n current = refreshed;\n onRefreshed?.(refreshed);\n for (const listener of listeners) listener(refreshed.accessToken);\n return refreshed;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAcA,IAAI,eAAe;;;;;;AAOnB,SAAgB,mBAAyB;AACvC,gBAAe;;;AAIjB,SAAgB,iBAA0B;AACxC,QAAO;;;;ACpBT,MAAM,4BAA4B,MAAU;AAO5C,IAAI,UAA8B;AAClC,IAAI;AACJ,IAAI;AAEJ,IAAI,WAAwC;AAC5C,MAAM,4BAAY,IAAI,KAAoC;AAE1D,IAAI,0BAAU,IAAI,KAAa;AAC/B,IAAI;;AAGJ,SAAgB,sBACd,aACA,SAIM;AACN,UAAS,QAAQ;AACjB,eAAc,QAAQ;AACtB,KACE,WACA,UAAU,SAAS,YAAY,KAC9B,QAAQ,aAAa,MAAM,YAAY,aAAa,IACrD;AACA,gBAAc,QAAQ;AACtB;;AAEF,KAAI,CAAC,WAAW,CAAC,UAAU,SAAS,YAAY,EAAE;AAChD,4BAAU,IAAI,KAAK;AACnB,gBAAc,YAAY;;AAE5B,SAAQ,IAAI,YAAY,YAAY;AACpC,WAAU;;;;;;;;AAeZ,eAAsB,wBACpB,aACA,SAC+B;AAC/B,KACG,QAAQ,uBAAuB,CAAC,YAAY,gBAC7C,gBAAgB,CAEhB,QAAO,EAAE,MAAM,WAAW;CAE5B,MAAM,UAAU,MAAM,mBAAmB,aAAa,KAAK;AAC3D,QAAO,QAAQ,gBAAgB,YAAY,cACvC,EAAE,MAAM,aAAa,GACrB;EAAE,MAAM;EAAW,aAAa;EAAS;;;AAI/C,SAAgB,cAAc,aAA6B;AACzD,QAAO,eAAe,QAAQ,IAAI,YAAY,GAAG,cAAc;;;AAIjE,eAAsB,iBACpB,QAAQ,OACqB;AAC7B,KAAI,CAAC,QAAS,QAAO;AACrB,KAAI,CAAC,UAAU,CAAC,QAAQ,gBAAiB,CAAC,SAAS,CAAC,WAAW,QAAQ,CACrE,QAAO;AACT,cAAa,QAAQ,QAAQ,QAAQ,CAAC,cAAc;AAClD,aAAW;GACX;AACF,QAAO;;;AAIT,eAAsB,mBACpB,UACA,QAAQ,OACc;AACtB,KAAI,CAAC,WAAW,CAAC,UAAU,SAAS,SAAS,CAAE,QAAO;AACtD,QAAQ,MAAM,iBAAiB,MAAM,IAAK;;;AAI5C,eAAsB,mBACpB,UACiB;AACjB,SAAQ,MAAM,mBAAmB,SAAS,EAAE;;;AAI9C,SAAgB,qBACd,UACY;AACZ,WAAU,IAAI,SAAS;AACvB,cAAa;AACX,YAAU,OAAO,SAAS;;;AAe9B,SAAS,UAAU,GAAgB,GAAyB;AAC1D,QAAO,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,cAAc,EAAE;;AAGhE,SAAS,WAAW,aAAmC;AAErD,QACE,YAAY,cAAc,KAAA,KAC1B,YAAY,YAAY,KAAK,KAAK,GAAG;;AAIzC,eAAe,QACb,YACA,aACsB;CACtB,MAAM,YAAY,MAAM,WAAW,YAAY;AAC/C,KAAI,cAAc,YAAa,QAAO;AACtC,WAAU,gCAAgC;AAC1C,SAAQ,IAAI,UAAU,YAAY;AAClC,WAAU;AACV,eAAc,UAAU;AACxB,MAAK,MAAM,YAAY,UAAW,UAAS,UAAU,YAAY;AACjE,QAAO"}
@@ -1,5 +1,5 @@
1
- import { n as analytics } from "./analytics-X7JfAmh6.js";
2
- import { a as REMARK_ASK, c as applyReadHandoffs, f as NotNeededReason, i as NOT_NEEDED_REASON_ASK, n as ENQUEUE_MODEL_DESCRIPTION, o as applyComplete, r as HANDOFF_FIELDS, s as applyEnqueue, t as COMPLETE_TASK_DESCRIPTION } from "./queue-tools-DrJKvFHZ.js";
1
+ import { n as analytics } from "./analytics-GQv--mQm.js";
2
+ import { a as REMARK_ASK, c as applyReadHandoffs, i as NOT_NEEDED_REASON_ASK, n as ENQUEUE_MODEL_DESCRIPTION, o as applyComplete, p as NotNeededReason, r as HANDOFF_FIELDS, s as applyEnqueue, t as COMPLETE_TASK_DESCRIPTION } from "./queue-tools-10w8lhEs.js";
3
3
  import { Type } from "typebox";
4
4
  import { defineTool } from "@earendil-works/pi-coding-agent";
5
5
  //#region src/agent/runner/harness/pi/orchestrator-tools.ts
@@ -110,4 +110,4 @@ function createPiOrchestratorTools(ctx) {
110
110
  //#endregion
111
111
  export { createPiOrchestratorTools };
112
112
 
113
- //# sourceMappingURL=orchestrator-tools-lhFIBGnp.js.map
113
+ //# sourceMappingURL=orchestrator-tools-lvNVQhzs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator-tools-lhFIBGnp.js","names":[],"sources":["../src/agent/runner/harness/pi/orchestrator-tools.ts"],"sourcesContent":["/**\n * Orchestrator queue tools as pi custom tools. The queue lives in-process, and\n * `applyEnqueue` / `applyComplete` / `applyReadHandoffs` are plain exported\n * functions — so pi needs no MCP transport, just `defineTool` wrappers around\n * the same guards and apply logic the anthropic path mounts through the\n * wizard-tools MCP server. Tool names match the MCP short names so the shared\n * agent prompts are unchanged.\n *\n * Lazily imported (typebox is ESM and must stay out of the static module graph\n * so CommonJS unit tests can load the backend seam without parsing it).\n */\n\nimport { Type } from 'typebox';\nimport { defineTool } from '@earendil-works/pi-coding-agent';\nimport type { ToolDefinition } from '@earendil-works/pi-coding-agent';\nimport { analytics } from '@utils/analytics';\nimport {\n applyComplete,\n applyEnqueue,\n applyReadHandoffs,\n COMPLETE_TASK_DESCRIPTION,\n ENQUEUE_MODEL_DESCRIPTION,\n HANDOFF_FIELDS,\n NOT_NEEDED_REASON_ASK,\n REMARK_ASK,\n type CompleteArgs,\n type EnqueueArgs,\n type OrchestratorToolsContext,\n} from '../../sequence/orchestrator/queue-tools';\nimport { NotNeededReason } from '../../sequence/orchestrator/queue';\n\nfunction text(s: string): {\n content: [{ type: 'text'; text: string }];\n details: unknown;\n} {\n return { content: [{ type: 'text', text: s }], details: {} };\n}\n\n/** Mirrors the zod `HANDOFF_SHAPE`; both read their text from HANDOFF_FIELDS. */\nconst HANDOFF_PARAMS = Type.Object({\n goals: Type.String({ description: HANDOFF_FIELDS.goals }),\n did: Type.String({ description: HANDOFF_FIELDS.did }),\n forNextAgent: Type.String({ description: HANDOFF_FIELDS.forNextAgent }),\n filesTouched: Type.Optional(\n Type.Array(Type.String(), { description: HANDOFF_FIELDS.filesTouched }),\n ),\n evidence: Type.Optional(\n Type.String({ description: HANDOFF_FIELDS.evidence }),\n ),\n assumptions: Type.Optional(\n Type.String({ description: HANDOFF_FIELDS.assumptions }),\n ),\n conflict: Type.Optional(\n Type.String({ description: HANDOFF_FIELDS.conflict }),\n ),\n reportSection: Type.Optional(\n Type.String({ description: HANDOFF_FIELDS.reportSection }),\n ),\n});\n\n/** Exported so the parity test can compare both harnesses' field sets. */\nexport const PI_HANDOFF_PARAM_KEYS: readonly string[] = Object.keys(\n HANDOFF_PARAMS.properties,\n);\n\n/** Mirrors the zod `COMPLETE_SHAPE`; ctx-independent, so it lives out here. */\nconst COMPLETE_PARAMS = Type.Object({\n status: Type.Union([\n Type.Literal('done'),\n Type.Literal('failed'),\n Type.Literal('not needed'),\n ]),\n handoff: HANDOFF_PARAMS,\n remark: Type.Optional(Type.String({ description: REMARK_ASK })),\n notNeededReason: Type.Optional(\n Type.Union(\n [\n Type.Literal(NotNeededReason.NotApplicable),\n Type.Literal(NotNeededReason.UserDeclined),\n Type.Literal(NotNeededReason.Blocked),\n ],\n { description: NOT_NEEDED_REASON_ASK },\n ),\n ),\n});\n\n/** Exported so the parity test can compare both harnesses' field sets. */\nexport const PI_COMPLETE_PARAM_KEYS: readonly string[] = Object.keys(\n COMPLETE_PARAMS.properties,\n);\n\n/** The three queue tools bound to one agent's orchestrator context. */\nexport function createPiOrchestratorTools(\n ctx: OrchestratorToolsContext,\n): ToolDefinition[] {\n const enqueueTask = defineTool({\n name: 'enqueue_task',\n label: 'Enqueue task',\n description:\n 'Add a task to the orchestrator queue. Use it to seed work and to enqueue follow-up work you discover. Keep tasks small and discrete.',\n promptSnippet:\n 'enqueue_task({type, label, dependsOn, reason}) — add a task to the queue; the task type goes in the \"type\" field, and it returns the task id',\n parameters: Type.Object({\n type: Type.String({\n description: `The task type. One of: ${ctx.validTypes.join(', ')}.`,\n }),\n label: Type.Optional(\n Type.String({\n description:\n 'A short label for the UI — the action in a few words (e.g. \"Add the PostHog SDK\", \"Initialize PostHog\"). Leave out file names, class names, and other specifics.',\n }),\n ),\n inputs: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n dependsOn: Type.Optional(\n Type.Array(Type.String(), {\n description: 'Task ids that must be done before this task runs.',\n }),\n ),\n model: Type.Optional(\n Type.String({ description: ENQUEUE_MODEL_DESCRIPTION }),\n ),\n reason: Type.String({\n description: 'One line on why this task is needed.',\n }),\n }),\n execute(_id, args) {\n const res = applyEnqueue(ctx, args as EnqueueArgs);\n if (!res.ok) {\n analytics.wizardCapture('orchestrator guard tripped', {\n guard: res.guard,\n type: (args as EnqueueArgs).type,\n });\n return Promise.resolve(text(`Error: ${res.message}`));\n }\n return Promise.resolve(text(JSON.stringify({ id: res.task.id })));\n },\n });\n\n const completeTask = defineTool({\n name: 'complete_task',\n label: 'Complete task',\n description: COMPLETE_TASK_DESCRIPTION,\n promptSnippet:\n 'complete_task(status, handoff) — report your outcome exactly once when done, with goals/did/forNextAgent nested inside handoff',\n parameters: COMPLETE_PARAMS,\n execute(_id, args) {\n const res = applyComplete(ctx, args as CompleteArgs);\n if (!res.ok) return Promise.resolve(text(`Error: ${res.message}`));\n return Promise.resolve(text('ok'));\n },\n });\n\n const readHandoffs = defineTool({\n name: 'read_handoffs',\n label: 'Read handoffs',\n description:\n 'Read structured handoffs from earlier tasks. With no argument, returns the handoffs of your dependencies.',\n promptSnippet:\n 'read_handoffs() — read what earlier tasks handed off (defaults to your dependencies)',\n parameters: Type.Object({\n type: Type.Optional(Type.String()),\n taskId: Type.Optional(Type.String()),\n }),\n execute(_id, args) {\n const handoffs = applyReadHandoffs(\n ctx,\n args as { type?: string; taskId?: string },\n );\n return Promise.resolve(text(JSON.stringify(handoffs, null, 2)));\n },\n });\n\n return [enqueueTask, completeTask, readHandoffs];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"orchestrator-tools-lvNVQhzs.js","names":[],"sources":["../src/agent/runner/harness/pi/orchestrator-tools.ts"],"sourcesContent":["/**\n * Orchestrator queue tools as pi custom tools. The queue lives in-process, and\n * `applyEnqueue` / `applyComplete` / `applyReadHandoffs` are plain exported\n * functions — so pi needs no MCP transport, just `defineTool` wrappers around\n * the same guards and apply logic the anthropic path mounts through the\n * wizard-tools MCP server. Tool names match the MCP short names so the shared\n * agent prompts are unchanged.\n *\n * Lazily imported (typebox is ESM and must stay out of the static module graph\n * so CommonJS unit tests can load the backend seam without parsing it).\n */\n\nimport { Type } from 'typebox';\nimport { defineTool } from '@earendil-works/pi-coding-agent';\nimport type { ToolDefinition } from '@earendil-works/pi-coding-agent';\nimport { analytics } from '@utils/analytics';\nimport {\n applyComplete,\n applyEnqueue,\n applyReadHandoffs,\n COMPLETE_TASK_DESCRIPTION,\n ENQUEUE_MODEL_DESCRIPTION,\n HANDOFF_FIELDS,\n NOT_NEEDED_REASON_ASK,\n REMARK_ASK,\n type CompleteArgs,\n type EnqueueArgs,\n type OrchestratorToolsContext,\n} from '../../sequence/orchestrator/queue-tools';\nimport { NotNeededReason } from '../../sequence/orchestrator/queue';\n\nfunction text(s: string): {\n content: [{ type: 'text'; text: string }];\n details: unknown;\n} {\n return { content: [{ type: 'text', text: s }], details: {} };\n}\n\n/** Mirrors the zod `HANDOFF_SHAPE`; both read their text from HANDOFF_FIELDS. */\nconst HANDOFF_PARAMS = Type.Object({\n goals: Type.String({ description: HANDOFF_FIELDS.goals }),\n did: Type.String({ description: HANDOFF_FIELDS.did }),\n forNextAgent: Type.String({ description: HANDOFF_FIELDS.forNextAgent }),\n filesTouched: Type.Optional(\n Type.Array(Type.String(), { description: HANDOFF_FIELDS.filesTouched }),\n ),\n evidence: Type.Optional(\n Type.String({ description: HANDOFF_FIELDS.evidence }),\n ),\n assumptions: Type.Optional(\n Type.String({ description: HANDOFF_FIELDS.assumptions }),\n ),\n conflict: Type.Optional(\n Type.String({ description: HANDOFF_FIELDS.conflict }),\n ),\n reportSection: Type.Optional(\n Type.String({ description: HANDOFF_FIELDS.reportSection }),\n ),\n});\n\n/** Exported so the parity test can compare both harnesses' field sets. */\nexport const PI_HANDOFF_PARAM_KEYS: readonly string[] = Object.keys(\n HANDOFF_PARAMS.properties,\n);\n\n/** Mirrors the zod `COMPLETE_SHAPE`; ctx-independent, so it lives out here. */\nconst COMPLETE_PARAMS = Type.Object({\n status: Type.Union([\n Type.Literal('done'),\n Type.Literal('failed'),\n Type.Literal('not needed'),\n ]),\n handoff: HANDOFF_PARAMS,\n remark: Type.Optional(Type.String({ description: REMARK_ASK })),\n notNeededReason: Type.Optional(\n Type.Union(\n [\n Type.Literal(NotNeededReason.NotApplicable),\n Type.Literal(NotNeededReason.UserDeclined),\n Type.Literal(NotNeededReason.Blocked),\n ],\n { description: NOT_NEEDED_REASON_ASK },\n ),\n ),\n});\n\n/** Exported so the parity test can compare both harnesses' field sets. */\nexport const PI_COMPLETE_PARAM_KEYS: readonly string[] = Object.keys(\n COMPLETE_PARAMS.properties,\n);\n\n/** The three queue tools bound to one agent's orchestrator context. */\nexport function createPiOrchestratorTools(\n ctx: OrchestratorToolsContext,\n): ToolDefinition[] {\n const enqueueTask = defineTool({\n name: 'enqueue_task',\n label: 'Enqueue task',\n description:\n 'Add a task to the orchestrator queue. Use it to seed work and to enqueue follow-up work you discover. Keep tasks small and discrete.',\n promptSnippet:\n 'enqueue_task({type, label, dependsOn, reason}) — add a task to the queue; the task type goes in the \"type\" field, and it returns the task id',\n parameters: Type.Object({\n type: Type.String({\n description: `The task type. One of: ${ctx.validTypes.join(', ')}.`,\n }),\n label: Type.Optional(\n Type.String({\n description:\n 'A short label for the UI — the action in a few words (e.g. \"Add the PostHog SDK\", \"Initialize PostHog\"). Leave out file names, class names, and other specifics.',\n }),\n ),\n inputs: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n dependsOn: Type.Optional(\n Type.Array(Type.String(), {\n description: 'Task ids that must be done before this task runs.',\n }),\n ),\n model: Type.Optional(\n Type.String({ description: ENQUEUE_MODEL_DESCRIPTION }),\n ),\n reason: Type.String({\n description: 'One line on why this task is needed.',\n }),\n }),\n execute(_id, args) {\n const res = applyEnqueue(ctx, args as EnqueueArgs);\n if (!res.ok) {\n analytics.wizardCapture('orchestrator guard tripped', {\n guard: res.guard,\n type: (args as EnqueueArgs).type,\n });\n return Promise.resolve(text(`Error: ${res.message}`));\n }\n return Promise.resolve(text(JSON.stringify({ id: res.task.id })));\n },\n });\n\n const completeTask = defineTool({\n name: 'complete_task',\n label: 'Complete task',\n description: COMPLETE_TASK_DESCRIPTION,\n promptSnippet:\n 'complete_task(status, handoff) — report your outcome exactly once when done, with goals/did/forNextAgent nested inside handoff',\n parameters: COMPLETE_PARAMS,\n execute(_id, args) {\n const res = applyComplete(ctx, args as CompleteArgs);\n if (!res.ok) return Promise.resolve(text(`Error: ${res.message}`));\n return Promise.resolve(text('ok'));\n },\n });\n\n const readHandoffs = defineTool({\n name: 'read_handoffs',\n label: 'Read handoffs',\n description:\n 'Read structured handoffs from earlier tasks. With no argument, returns the handoffs of your dependencies.',\n promptSnippet:\n 'read_handoffs() — read what earlier tasks handed off (defaults to your dependencies)',\n parameters: Type.Object({\n type: Type.Optional(Type.String()),\n taskId: Type.Optional(Type.String()),\n }),\n execute(_id, args) {\n const handoffs = applyReadHandoffs(\n ctx,\n args as { type?: string; taskId?: string },\n );\n return Promise.resolve(text(JSON.stringify(handoffs, null, 2)));\n },\n });\n\n return [enqueueTask, completeTask, readHandoffs];\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { n as analytics } from "./analytics-X7JfAmh6.js";
2
- import { r as readFileHead } from "./bounded-fs-iDiqDQ9v.js";
3
- import { t as withProgress } from "./telemetry-NeZhrBeW.js";
1
+ import { n as analytics } from "./analytics-GQv--mQm.js";
2
+ import { r as readFileHead } from "./bounded-fs-B31zq2ir.js";
3
+ import { t as withProgress } from "./telemetry-Cwqf0iur.js";
4
4
  import * as fs$1 from "fs";
5
5
  import * as path$1 from "path";
6
6
  //#region src/shared/utils/package-manager.ts
@@ -102,4 +102,4 @@ function detectNodePackageManagers(installDir) {
102
102
  //#endregion
103
103
  export { detectNodePackageManagers as n, detectAllPackageManagers as t };
104
104
 
105
- //# sourceMappingURL=package-manager-DZ4wcTz3.js.map
105
+ //# sourceMappingURL=package-manager-BqRNp5y_.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"package-manager-DZ4wcTz3.js","names":["fs","path"],"sources":["../src/shared/utils/package-manager.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { readFileHead } from './bounded-fs';\nimport { withProgress } from './telemetry';\nimport { analytics } from './analytics';\nimport type { WizardRunOptions } from './types';\n\ntype InstallDirOpt = Pick<WizardRunOptions, 'installDir'>;\n\nexport interface PackageManager {\n name: string;\n label: string;\n installCommand: string;\n buildCommand: string;\n /** Command the manager uses to execute a `package.json` script. */\n runScriptCommand: string;\n flags: string;\n detect: (opts: InstallDirOpt) => boolean;\n}\n\nfunction hasLockfile(installDir: string, file: string): boolean {\n return fs.existsSync(path.join(installDir, file));\n}\n\nfunction lockfileHeaderContains(\n installDir: string,\n file: string,\n needle: string,\n): boolean {\n // Reads only the first 500 bytes of the lockfile.\n return (\n readFileHead(path.join(installDir, file), 500)?.includes(needle) ?? false\n );\n}\n\nexport const BUN: PackageManager = {\n name: 'bun',\n label: 'Bun',\n installCommand: 'bun add',\n buildCommand: 'bun run build',\n runScriptCommand: 'bun run',\n flags: '',\n detect: ({ installDir }) =>\n hasLockfile(installDir, 'bun.lockb') || hasLockfile(installDir, 'bun.lock'),\n};\n\nexport const YARN_V1: PackageManager = {\n name: 'yarn',\n label: 'Yarn V1',\n installCommand: 'yarn add',\n buildCommand: 'yarn build',\n runScriptCommand: 'yarn',\n flags: '--ignore-workspace-root-check',\n detect: ({ installDir }) =>\n lockfileHeaderContains(installDir, 'yarn.lock', 'yarn lockfile v1'),\n};\n\n/** YARN V2/3/4 */\nexport const YARN_V2: PackageManager = {\n name: 'yarn',\n label: 'Yarn V2/3/4',\n installCommand: 'yarn add',\n buildCommand: 'yarn build',\n runScriptCommand: 'yarn',\n flags: '',\n detect: ({ installDir }) =>\n lockfileHeaderContains(installDir, 'yarn.lock', '__metadata'),\n};\n\nexport const PNPM: PackageManager = {\n name: 'pnpm',\n label: 'pnpm',\n installCommand: 'pnpm add',\n buildCommand: 'pnpm build',\n runScriptCommand: 'pnpm',\n flags: '--ignore-workspace-root-check',\n detect: ({ installDir }) => hasLockfile(installDir, 'pnpm-lock.yaml'),\n};\n\nexport const NPM: PackageManager = {\n name: 'npm',\n label: 'npm',\n installCommand: 'npm add',\n buildCommand: 'npm run build',\n runScriptCommand: 'npm run',\n flags: '',\n detect: ({ installDir }) => hasLockfile(installDir, 'package-lock.json'),\n};\n\n// Expo is selected by upstream config (app.json / app.config.*) rather than\n// a lockfile, so its detect always returns false here.\nexport const EXPO: PackageManager = {\n name: 'expo',\n label: 'Expo',\n installCommand: 'npx expo install',\n buildCommand: 'npx expo build',\n runScriptCommand: 'npx expo run',\n flags: '',\n detect: () => false,\n};\n\nexport const packageManagers: PackageManager[] = [\n BUN,\n YARN_V1,\n YARN_V2,\n PNPM,\n NPM,\n EXPO,\n];\n\nexport function detectAllPackageManagers({\n installDir,\n}: InstallDirOpt): PackageManager[] {\n return withProgress('detect-package-manager', () => {\n const matches = packageManagers.filter((pm) => pm.detect({ installDir }));\n if (matches.length === 0) {\n analytics.setTag('package-manager', 'not-detected');\n }\n return matches;\n });\n}\n\n// ---------------------------------------------------------------------------\n// The detector contract the agent's `detect_package_manager` tool calls\n// ---------------------------------------------------------------------------\n\n/** Structured package manager info the agent can act on */\nexport interface DetectedPackageManager {\n name: string;\n label: string;\n installCommand: string;\n runCommand?: string;\n}\n\n/** Result returned by every detector */\nexport interface PackageManagerInfo {\n detected: DetectedPackageManager[];\n primary: DetectedPackageManager | null;\n recommendation: string;\n}\n\n/** Signature each framework implements */\nexport type PackageManagerDetector = (\n installDir: string,\n) => Promise<PackageManagerInfo>;\n\n// ---------------------------------------------------------------------------\n// Node.js helper\n// ---------------------------------------------------------------------------\n\nfunction serializeNodePM(pm: PackageManager): DetectedPackageManager {\n return {\n name: pm.name,\n label: pm.label,\n installCommand: pm.installCommand,\n runCommand: pm.runScriptCommand,\n };\n}\n\n/**\n * Detect Node.js package managers via lockfiles.\n * Wraps detectAllPackageManagers() above.\n */\nexport function detectNodePackageManagers(\n installDir: string,\n): Promise<PackageManagerInfo> {\n const detected = detectAllPackageManagers({ installDir }).map(\n serializeNodePM,\n );\n\n if (detected.length === 0) {\n return Promise.resolve({\n detected: [],\n primary: null,\n recommendation: 'No lockfile found. Default to npm (npm add, npm run).',\n });\n }\n\n const primary = detected[0];\n return Promise.resolve({\n detected,\n primary,\n recommendation:\n detected.length === 1\n ? `Use ${primary.label} (${primary.installCommand}).`\n : `Multiple package managers detected. Prefer ${primary.label} (${primary.installCommand}).`,\n });\n}\n"],"mappings":";;;;;;AAoBA,SAAS,YAAY,YAAoB,MAAuB;AAC9D,QAAOA,KAAG,WAAWC,OAAK,KAAK,YAAY,KAAK,CAAC;;AAGnD,SAAS,uBACP,YACA,MACA,QACS;AAET,QACE,aAAaA,OAAK,KAAK,YAAY,KAAK,EAAE,IAAI,EAAE,SAAS,OAAO,IAAI;;AAsExE,MAAa,kBAAoC;CAlEd;EACjC,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,cAAc;EACd,kBAAkB;EAClB,OAAO;EACP,SAAS,EAAE,iBACT,YAAY,YAAY,YAAY,IAAI,YAAY,YAAY,WAAW;EAC9E;CAEsC;EACrC,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,cAAc;EACd,kBAAkB;EAClB,OAAO;EACP,SAAS,EAAE,iBACT,uBAAuB,YAAY,aAAa,mBAAmB;EACtE;CAGsC;EACrC,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,cAAc;EACd,kBAAkB;EAClB,OAAO;EACP,SAAS,EAAE,iBACT,uBAAuB,YAAY,aAAa,aAAa;EAChE;CAEmC;EAClC,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,cAAc;EACd,kBAAkB;EAClB,OAAO;EACP,SAAS,EAAE,iBAAiB,YAAY,YAAY,iBAAiB;EACtE;CAEkC;EACjC,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,cAAc;EACd,kBAAkB;EAClB,OAAO;EACP,SAAS,EAAE,iBAAiB,YAAY,YAAY,oBAAoB;EACzE;CAImC;EAClC,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,cAAc;EACd,kBAAkB;EAClB,OAAO;EACP,cAAc;EACf;CASA;AAED,SAAgB,yBAAyB,EACvC,cACkC;AAClC,QAAO,aAAa,gCAAgC;EAClD,MAAM,UAAU,gBAAgB,QAAQ,OAAO,GAAG,OAAO,EAAE,YAAY,CAAC,CAAC;AACzE,MAAI,QAAQ,WAAW,EACrB,WAAU,OAAO,mBAAmB,eAAe;AAErD,SAAO;GACP;;AA+BJ,SAAS,gBAAgB,IAA4C;AACnE,QAAO;EACL,MAAM,GAAG;EACT,OAAO,GAAG;EACV,gBAAgB,GAAG;EACnB,YAAY,GAAG;EAChB;;;;;;AAOH,SAAgB,0BACd,YAC6B;CAC7B,MAAM,WAAW,yBAAyB,EAAE,YAAY,CAAC,CAAC,IACxD,gBACD;AAED,KAAI,SAAS,WAAW,EACtB,QAAO,QAAQ,QAAQ;EACrB,UAAU,EAAE;EACZ,SAAS;EACT,gBAAgB;EACjB,CAAC;CAGJ,MAAM,UAAU,SAAS;AACzB,QAAO,QAAQ,QAAQ;EACrB;EACA;EACA,gBACE,SAAS,WAAW,IAChB,OAAO,QAAQ,MAAM,IAAI,QAAQ,eAAe,MAChD,8CAA8C,QAAQ,MAAM,IAAI,QAAQ,eAAe;EAC9F,CAAC"}
1
+ {"version":3,"file":"package-manager-BqRNp5y_.js","names":["fs","path"],"sources":["../src/shared/utils/package-manager.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { readFileHead } from './bounded-fs';\nimport { withProgress } from './telemetry';\nimport { analytics } from './analytics';\nimport type { WizardRunOptions } from './types';\n\ntype InstallDirOpt = Pick<WizardRunOptions, 'installDir'>;\n\nexport interface PackageManager {\n name: string;\n label: string;\n installCommand: string;\n buildCommand: string;\n /** Command the manager uses to execute a `package.json` script. */\n runScriptCommand: string;\n flags: string;\n detect: (opts: InstallDirOpt) => boolean;\n}\n\nfunction hasLockfile(installDir: string, file: string): boolean {\n return fs.existsSync(path.join(installDir, file));\n}\n\nfunction lockfileHeaderContains(\n installDir: string,\n file: string,\n needle: string,\n): boolean {\n // Reads only the first 500 bytes of the lockfile.\n return (\n readFileHead(path.join(installDir, file), 500)?.includes(needle) ?? false\n );\n}\n\nexport const BUN: PackageManager = {\n name: 'bun',\n label: 'Bun',\n installCommand: 'bun add',\n buildCommand: 'bun run build',\n runScriptCommand: 'bun run',\n flags: '',\n detect: ({ installDir }) =>\n hasLockfile(installDir, 'bun.lockb') || hasLockfile(installDir, 'bun.lock'),\n};\n\nexport const YARN_V1: PackageManager = {\n name: 'yarn',\n label: 'Yarn V1',\n installCommand: 'yarn add',\n buildCommand: 'yarn build',\n runScriptCommand: 'yarn',\n flags: '--ignore-workspace-root-check',\n detect: ({ installDir }) =>\n lockfileHeaderContains(installDir, 'yarn.lock', 'yarn lockfile v1'),\n};\n\n/** YARN V2/3/4 */\nexport const YARN_V2: PackageManager = {\n name: 'yarn',\n label: 'Yarn V2/3/4',\n installCommand: 'yarn add',\n buildCommand: 'yarn build',\n runScriptCommand: 'yarn',\n flags: '',\n detect: ({ installDir }) =>\n lockfileHeaderContains(installDir, 'yarn.lock', '__metadata'),\n};\n\nexport const PNPM: PackageManager = {\n name: 'pnpm',\n label: 'pnpm',\n installCommand: 'pnpm add',\n buildCommand: 'pnpm build',\n runScriptCommand: 'pnpm',\n flags: '--ignore-workspace-root-check',\n detect: ({ installDir }) => hasLockfile(installDir, 'pnpm-lock.yaml'),\n};\n\nexport const NPM: PackageManager = {\n name: 'npm',\n label: 'npm',\n installCommand: 'npm add',\n buildCommand: 'npm run build',\n runScriptCommand: 'npm run',\n flags: '',\n detect: ({ installDir }) => hasLockfile(installDir, 'package-lock.json'),\n};\n\n// Expo is selected by upstream config (app.json / app.config.*) rather than\n// a lockfile, so its detect always returns false here.\nexport const EXPO: PackageManager = {\n name: 'expo',\n label: 'Expo',\n installCommand: 'npx expo install',\n buildCommand: 'npx expo build',\n runScriptCommand: 'npx expo run',\n flags: '',\n detect: () => false,\n};\n\nexport const packageManagers: PackageManager[] = [\n BUN,\n YARN_V1,\n YARN_V2,\n PNPM,\n NPM,\n EXPO,\n];\n\nexport function detectAllPackageManagers({\n installDir,\n}: InstallDirOpt): PackageManager[] {\n return withProgress('detect-package-manager', () => {\n const matches = packageManagers.filter((pm) => pm.detect({ installDir }));\n if (matches.length === 0) {\n analytics.setTag('package-manager', 'not-detected');\n }\n return matches;\n });\n}\n\n// ---------------------------------------------------------------------------\n// The detector contract the agent's `detect_package_manager` tool calls\n// ---------------------------------------------------------------------------\n\n/** Structured package manager info the agent can act on */\nexport interface DetectedPackageManager {\n name: string;\n label: string;\n installCommand: string;\n runCommand?: string;\n}\n\n/** Result returned by every detector */\nexport interface PackageManagerInfo {\n detected: DetectedPackageManager[];\n primary: DetectedPackageManager | null;\n recommendation: string;\n}\n\n/** Signature each framework implements */\nexport type PackageManagerDetector = (\n installDir: string,\n) => Promise<PackageManagerInfo>;\n\n// ---------------------------------------------------------------------------\n// Node.js helper\n// ---------------------------------------------------------------------------\n\nfunction serializeNodePM(pm: PackageManager): DetectedPackageManager {\n return {\n name: pm.name,\n label: pm.label,\n installCommand: pm.installCommand,\n runCommand: pm.runScriptCommand,\n };\n}\n\n/**\n * Detect Node.js package managers via lockfiles.\n * Wraps detectAllPackageManagers() above.\n */\nexport function detectNodePackageManagers(\n installDir: string,\n): Promise<PackageManagerInfo> {\n const detected = detectAllPackageManagers({ installDir }).map(\n serializeNodePM,\n );\n\n if (detected.length === 0) {\n return Promise.resolve({\n detected: [],\n primary: null,\n recommendation: 'No lockfile found. Default to npm (npm add, npm run).',\n });\n }\n\n const primary = detected[0];\n return Promise.resolve({\n detected,\n primary,\n recommendation:\n detected.length === 1\n ? `Use ${primary.label} (${primary.installCommand}).`\n : `Multiple package managers detected. Prefer ${primary.label} (${primary.installCommand}).`,\n });\n}\n"],"mappings":";;;;;;AAoBA,SAAS,YAAY,YAAoB,MAAuB;AAC9D,QAAOA,KAAG,WAAWC,OAAK,KAAK,YAAY,KAAK,CAAC;;AAGnD,SAAS,uBACP,YACA,MACA,QACS;AAET,QACE,aAAaA,OAAK,KAAK,YAAY,KAAK,EAAE,IAAI,EAAE,SAAS,OAAO,IAAI;;AAsExE,MAAa,kBAAoC;CAlEd;EACjC,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,cAAc;EACd,kBAAkB;EAClB,OAAO;EACP,SAAS,EAAE,iBACT,YAAY,YAAY,YAAY,IAAI,YAAY,YAAY,WAAW;EAC9E;CAEsC;EACrC,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,cAAc;EACd,kBAAkB;EAClB,OAAO;EACP,SAAS,EAAE,iBACT,uBAAuB,YAAY,aAAa,mBAAmB;EACtE;CAGsC;EACrC,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,cAAc;EACd,kBAAkB;EAClB,OAAO;EACP,SAAS,EAAE,iBACT,uBAAuB,YAAY,aAAa,aAAa;EAChE;CAEmC;EAClC,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,cAAc;EACd,kBAAkB;EAClB,OAAO;EACP,SAAS,EAAE,iBAAiB,YAAY,YAAY,iBAAiB;EACtE;CAEkC;EACjC,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,cAAc;EACd,kBAAkB;EAClB,OAAO;EACP,SAAS,EAAE,iBAAiB,YAAY,YAAY,oBAAoB;EACzE;CAImC;EAClC,MAAM;EACN,OAAO;EACP,gBAAgB;EAChB,cAAc;EACd,kBAAkB;EAClB,OAAO;EACP,cAAc;EACf;CASA;AAED,SAAgB,yBAAyB,EACvC,cACkC;AAClC,QAAO,aAAa,gCAAgC;EAClD,MAAM,UAAU,gBAAgB,QAAQ,OAAO,GAAG,OAAO,EAAE,YAAY,CAAC,CAAC;AACzE,MAAI,QAAQ,WAAW,EACrB,WAAU,OAAO,mBAAmB,eAAe;AAErD,SAAO;GACP;;AA+BJ,SAAS,gBAAgB,IAA4C;AACnE,QAAO;EACL,MAAM,GAAG;EACT,OAAO,GAAG;EACV,gBAAgB,GAAG;EACnB,YAAY,GAAG;EAChB;;;;;;AAOH,SAAgB,0BACd,YAC6B;CAC7B,MAAM,WAAW,yBAAyB,EAAE,YAAY,CAAC,CAAC,IACxD,gBACD;AAED,KAAI,SAAS,WAAW,EACtB,QAAO,QAAQ,QAAQ;EACrB,UAAU,EAAE;EACZ,SAAS;EACT,gBAAgB;EACjB,CAAC;CAGJ,MAAM,UAAU,SAAS;AACzB,QAAO,QAAQ,QAAQ;EACrB;EACA;EACA,gBACE,SAAS,WAAW,IAChB,OAAO,QAAQ,MAAM,IAAI,QAAQ,eAAe,MAChD,8CAA8C,QAAQ,MAAM,IAAI,QAAQ,eAAe;EAC9F,CAAC"}
@@ -1,10 +1,10 @@
1
1
  import { n as ErrorCodes } from "./emit-BqLCdV8Y.js";
2
- import { f as VERSION, i as getLogFilePath, o as logToFile } from "./debug-C3tLP-ZW.js";
3
- import { $ as WIZARD_REMARK_EVENT_NAME, it as wizardUserAgentForProgram, n as analytics } from "./analytics-X7JfAmh6.js";
2
+ import { f as VERSION, i as getLogFilePath, o as logToFile } from "./debug-BTUMatFI.js";
3
+ import { at as wizardUserAgentForProgram, et as WIZARD_REMARK_EVENT_NAME, n as analytics } from "./analytics-GQv--mQm.js";
4
4
  import { t as classifyRunFailure } from "./errors-DhFeR8Sp.js";
5
- import { n as currentAccessToken } from "./oauth-session-Bj_-BY7o.js";
6
- import { c as REMARK_INSTRUCTION, d as gatewayAuth, o as withGatewayRemint, r as buildGatewayProvider, s as AgentSignals, t as GATEWAY_PROVIDER } from "./gateway-IQjQ582o.js";
7
- import { h as AgentOutputSignals, v as assembleCommandments } from "./agent-interface-DMP3DZRd.js";
5
+ import { n as currentAccessToken } from "./oauth-session-CfkZ339p.js";
6
+ import { c as REMARK_INSTRUCTION, f as gatewayAuth, o as withGatewayRemint, r as buildGatewayProvider, s as AgentSignals, t as GATEWAY_PROVIDER, u as policyAbortReason } from "./gateway-CJ8Jqbll.js";
7
+ import { g as assembleCommandments, h as AgentOutputSignals } from "./agent-interface-fcDXqb-_.js";
8
8
  import fs from "fs";
9
9
  import path from "path";
10
10
  function appendStatus(messages, message) {
@@ -338,6 +338,11 @@ function createAioCapture(args) {
338
338
  }
339
339
  //#endregion
340
340
  //#region src/agent/runner/harness/pi/completion.ts
341
+ /** Fatal setup signals use the same precedence as the legacy harness. */
342
+ function setupSignalFailure(signals) {
343
+ if (signals.has("MCP_MISSING")) return "WIZARD_MCP_MISSING";
344
+ if (signals.has("RESOURCE_MISSING")) return "WIZARD_RESOURCE_MISSING";
345
+ }
341
346
  /** Which completion guard should fail a pi run, or undefined for a clean finish. */
342
347
  function completionFailure(args) {
343
348
  if (args.toolCalls === 0) return "WIZARD_NO_PROGRESS";
@@ -371,10 +376,13 @@ function bindPiCancellation(signal, session, onAbortError) {
371
376
  };
372
377
  signal?.addEventListener("abort", onAbort, { once: true });
373
378
  if (signal?.aborted) onAbort();
374
- return { async settle() {
375
- signal?.removeEventListener("abort", onAbort);
376
- await abortPromise;
377
- } };
379
+ return {
380
+ abort: onAbort,
381
+ async settle() {
382
+ signal?.removeEventListener("abort", onAbort);
383
+ await abortPromise;
384
+ }
385
+ };
378
386
  }
379
387
  //#endregion
380
388
  //#region src/agent/runner/harness/pi/structured-output.ts
@@ -592,8 +600,9 @@ const piBackend = {
592
600
  duration_seconds: Math.round(durationMs / 1e3)
593
601
  };
594
602
  };
595
- const captureAborted = (failureMode) => analytics.wizardCapture("agent aborted", {
603
+ const captureAborted = (failureMode, source) => analytics.wizardCapture("agent aborted", {
596
604
  failure_mode: failureMode,
605
+ ...source && { source },
597
606
  ...runDurations(),
598
607
  model: modelId
599
608
  });
@@ -611,6 +620,13 @@ const piBackend = {
611
620
  let cancellation;
612
621
  let timedOut = false;
613
622
  let timeoutAbort;
623
+ let abortReason;
624
+ let remarkTurn = false;
625
+ const policyAbort = (reply) => {
626
+ if (remarkTurn) return;
627
+ abortReason ??= policyAbortReason(reply);
628
+ if (abortReason) cancellation?.abort();
629
+ };
614
630
  let securityState;
615
631
  const yaraViolationResult = () => {
616
632
  spinner.stop("Security violation detected");
@@ -644,7 +660,7 @@ const piBackend = {
644
660
  message: "pi: gateway model could not be resolved"
645
661
  };
646
662
  const askState = { pending: false };
647
- const { createSecurityExtension, READ_ONLY_PI_TOOLS } = await import("./security-C_grSgIM.js");
663
+ const { createSecurityExtension, READ_ONLY_PI_TOOLS } = await import("./security-ppK2MwCn.js");
648
664
  const security = createSecurityExtension({
649
665
  readOnly: config.readOnly,
650
666
  disallowedTools: runConfig.disallowedTools,
@@ -653,13 +669,13 @@ const piBackend = {
653
669
  workingDirectory: input.installDir
654
670
  });
655
671
  securityState = security.state;
656
- const { prewarmYaraScanner } = await import("./yara-hooks-CFD60h78.js");
672
+ const { prewarmYaraScanner } = await import("./yara-hooks-BwhEDXIt.js");
657
673
  prewarmYaraScanner();
658
674
  const extensionFactories = [security.factory];
659
675
  let mcpInstructions;
660
676
  let posthogMcp = false;
661
677
  if (!config.readOnly) try {
662
- const { setupPostHogMcp, fetchInstructions } = await import("./mcp-B2o4d9DS.js");
678
+ const { setupPostHogMcp, fetchInstructions } = await import("./mcp-D73aCOHK.js");
663
679
  const mcpToken = await currentAccessToken(boot.credentials);
664
680
  const mcpUserAgent = wizardUserAgentForProgram(config.integrationLabel);
665
681
  const instructionsPromise = fetchInstructions(boot.credentials.host.mcpUrl, mcpToken, mcpUserAgent);
@@ -705,9 +721,9 @@ const piBackend = {
705
721
  extensionFactories
706
722
  });
707
723
  await resourceLoader.reload();
708
- const { createWizardPiTools } = await import("./tools-1aM6bI9Y.js");
724
+ const { createWizardPiTools } = await import("./tools-g42e5kJz.js");
709
725
  const { createWizardPiTaskTools } = await import("./tasks-BfJhVky2.js");
710
- const { createDispatchAgentTool } = await import("./subagent-DQ_enM8C.js");
726
+ const { createDispatchAgentTool } = await import("./subagent-BdDWA8j5.js");
711
727
  const wizardTaskTools = createWizardPiTaskTools((tasks) => emit({
712
728
  kind: "tasks",
713
729
  tasks
@@ -729,6 +745,8 @@ const piBackend = {
729
745
  skillsBaseUrl: boot.skillsBaseUrl,
730
746
  triageProvider: boot.triageProvider,
731
747
  emit,
748
+ programId: boot.programId,
749
+ handoffNotebook: boot.handoffNotebook,
732
750
  detectPackageManager: config.detectPackageManager,
733
751
  askBridge: inputs.askBridge,
734
752
  maxQuestions: config.maxQuestions,
@@ -788,6 +806,7 @@ const piBackend = {
788
806
  turns.noteAssistantTurn(event.message);
789
807
  const blocks = textBlocks(event.message);
790
808
  const assistant = blocks.join("").trim();
809
+ policyAbort(assistant);
791
810
  lastAssistantText = (blocks.at(-1) ?? "").trim();
792
811
  if (structured) inputs.middleware?.onMessage({
793
812
  type: "assistant",
@@ -827,6 +846,7 @@ const piBackend = {
827
846
  }
828
847
  case "tool_execution_end":
829
848
  logToFile(`[pi] ${event.isError ? "✗" : "←"} ${event.toolName}: ${typeof event.result === "string" ? event.result : JSON.stringify(event.result ?? "")}`);
849
+ if (event.toolName === "dispatch_agent") policyAbort(extractText(event.result));
830
850
  break;
831
851
  case "agent_end":
832
852
  logToFile(`[pi] agent_end (willRetry=${String(event.willRetry)})`);
@@ -851,16 +871,19 @@ const piBackend = {
851
871
  await turns.prompt(prompt);
852
872
  terminal = turns.terminalFailure();
853
873
  let continueNudges = 0;
854
- while (!structured && continueNudges < MAX_CONTINUE_NUDGES && !security.state.criticalViolation && !inputs.signal?.aborted && !terminal && hasOpenTasks(wizardTaskTools.store)) {
874
+ while (!structured && continueNudges < MAX_CONTINUE_NUDGES && !security.state.criticalViolation && !inputs.signal?.aborted && !terminal && !abortReason && !setupSignalFailure(signals) && hasOpenTasks(wizardTaskTools.store)) {
855
875
  continueNudges += 1;
856
876
  logToFile(`[pi] completion guard: tasks still open, nudge ${continueNudges}/${MAX_CONTINUE_NUDGES}`);
857
877
  await turns.prompt(CONTINUE_INSTRUCTION);
858
878
  terminal = turns.terminalFailure();
859
879
  }
860
- if (!structured && !security.state.criticalViolation && !terminal && !inputs.signal?.aborted) try {
861
- await agentSession.prompt(REMARK_INSTRUCTION);
862
- } catch (err) {
863
- logToFile(`[pi] remark request failed: ${String(err)}`);
880
+ if (!structured && !security.state.criticalViolation && !terminal && !abortReason && !setupSignalFailure(signals) && !inputs.signal?.aborted) {
881
+ remarkTurn = true;
882
+ try {
883
+ await agentSession.prompt(REMARK_INSTRUCTION);
884
+ } catch (err) {
885
+ logToFile(`[pi] remark request failed: ${String(err)}`);
886
+ }
864
887
  }
865
888
  } finally {
866
889
  if (timeout) clearTimeout(timeout);
@@ -874,9 +897,13 @@ const piBackend = {
874
897
  message: "Agent run cancelled"
875
898
  };
876
899
  if (timedOut && structured && !security.state.criticalViolation) return timedOutResult(structured.timeoutMs);
900
+ if (abortReason) terminal = {
901
+ classification: "WIZARD_ABORT",
902
+ message: abortReason
903
+ };
877
904
  if (terminal && !security.state.criticalViolation) {
878
905
  spinner.stop(config.errorMessage ?? `${config.integrationLabel} failed`);
879
- captureAborted(terminal.classification);
906
+ captureAborted(terminal.classification, abortReason ? "gateway_policy" : void 0);
880
907
  if (terminal.status === 401) return {
881
908
  kind: "decided_failure",
882
909
  failure: {
@@ -896,6 +923,16 @@ const piBackend = {
896
923
  };
897
924
  }
898
925
  if (security.state.criticalViolation) return yaraViolationResult();
926
+ const setupFailure = setupSignalFailure(signals);
927
+ if (setupFailure) {
928
+ spinner.stop("Agent could not access setup instructions");
929
+ logToFile(`[pi] setup failed: ${setupFailure}`);
930
+ captureAborted(setupFailure);
931
+ return {
932
+ kind: "failure",
933
+ classification: setupFailure
934
+ };
935
+ }
899
936
  const openTasks = !structured && hasOpenTasks(wizardTaskTools.store);
900
937
  const failure = completionFailure({
901
938
  toolCalls,
@@ -997,11 +1034,11 @@ const piBackend = {
997
1034
  }
998
1035
  },
999
1036
  async runTask(inputs) {
1000
- const { runPiTask } = await import("./task-Dm9wZbVW.js");
1037
+ const { runPiTask } = await import("./task-Y8lWoDE7.js");
1001
1038
  return runPiTask(inputs);
1002
1039
  }
1003
1040
  };
1004
1041
  //#endregion
1005
- export { piBackend as a, runErrorType as c, createEmitSpinner as d, createProgressCollector as f, lastStatusLine as i, createAioCapture as l, buildScrubbedEnv as n, withMode as o, appendStatus as p, extractText as r, bindPiCancellation as s, applyOutroMarkers as t, createEmitLog as u };
1042
+ export { piBackend as a, runErrorType as c, createEmitLog as d, createEmitSpinner as f, lastStatusLine as i, setupSignalFailure as l, appendStatus as m, buildScrubbedEnv as n, withMode as o, createProgressCollector as p, extractText as r, bindPiCancellation as s, applyOutroMarkers as t, createAioCapture as u };
1006
1043
 
1007
- //# sourceMappingURL=pi-DREdQRPP.js.map
1044
+ //# sourceMappingURL=pi-2pYz2OY3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-2pYz2OY3.js","names":[],"sources":["../src/shared/status-history.ts","../src/agent/runner/shared/progress-collector.ts","../src/agent/aio-capture.ts","../src/agent/runner/harness/pi/completion.ts","../src/agent/runner/harness/pi/cancellation.ts","../src/agent/runner/harness/pi/structured-output.ts","../src/agent/runner/harness/pi/index.ts"],"sourcesContent":["/** Shared FIFO window for agent snapshots and the terminal status panel. */\nexport const MAX_STATUS_MESSAGES = 10;\n\nexport function appendStatus(messages: string[], message: string): string[] {\n if (messages.length > 0 && messages[messages.length - 1] === message) {\n return messages;\n }\n return [...messages.slice(-(MAX_STATUS_MESSAGES - 1)), message];\n}\n","/**\n * The agent's own record of what it reported.\n *\n * `runAgent` accumulates its final `RunSnapshot` here, independently of any\n * observer, so a missing or throwing `onProgress` never makes the result\n * incomplete. The emitter wraps the caller's callback: it applies the event\n * here first, then hands a copy to the observer, and logs rather than\n * propagates anything the observer throws.\n */\n\nimport { logToFile } from '@utils/debug';\nimport { appendStatus } from '@shared/status-history';\nimport type {\n AgentProgress,\n ProgressEmitter,\n SpinnerHandle,\n} from '../../progress';\nimport type { RunSnapshot } from './types';\n\nexport interface ProgressCollector {\n emit: ProgressEmitter;\n snapshot(): RunSnapshot;\n}\n\nexport function createProgressCollector(\n onProgress?: (event: AgentProgress) => unknown,\n): ProgressCollector {\n const snapshot: RunSnapshot = {\n tasks: [],\n statusMessages: [],\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheCreationTokens: 0,\n },\n };\n\n const apply = (event: AgentProgress): void => {\n switch (event.kind) {\n case 'tasks':\n snapshot.tasks = event.tasks.map((t) => ({ ...t }));\n break;\n case 'status':\n snapshot.statusMessages = appendStatus(\n snapshot.statusMessages,\n event.message,\n );\n break;\n case 'stage':\n snapshot.stage = event.stage;\n break;\n case 'url':\n if (event.which === 'dashboard') snapshot.dashboardUrl = event.url;\n else snapshot.notebookUrl = event.url;\n break;\n case 'usage':\n snapshot.usage.inputTokens += event.delta.inputTokens;\n snapshot.usage.outputTokens += event.delta.outputTokens;\n snapshot.usage.cacheReadTokens += event.delta.cacheReadTokens;\n snapshot.usage.cacheCreationTokens += event.delta.cacheCreationTokens;\n break;\n case 'finalCost':\n snapshot.finalCostUsd = event.usd;\n break;\n case 'handoff':\n snapshot.handoffText = event.text;\n break;\n default:\n break;\n }\n };\n\n const emit: ProgressEmitter = (event) => {\n apply(event);\n if (!onProgress) return;\n try {\n const observed = onProgress(structuredClone(event));\n if (\n observed &&\n typeof (observed as PromiseLike<unknown>).then === 'function'\n ) {\n void Promise.resolve(observed).catch((error: unknown) => {\n try {\n logToFile(\n `[agent] progress observer rejected on ${event.kind}:`,\n error,\n );\n } catch {\n // Logging is best effort.\n }\n });\n }\n } catch (error) {\n // A broken projection is the host's problem, not the run's. Say so in\n // the log and carry on; the snapshot above is the source of truth.\n try {\n logToFile(\n `[agent] progress observer threw on ${event.kind}:`,\n error instanceof Error ? error.message : error,\n );\n } catch {\n // Logging is best effort.\n }\n }\n };\n\n return {\n emit,\n snapshot: () => ({\n ...snapshot,\n tasks: snapshot.tasks.map((t) => ({ ...t })),\n statusMessages: [...snapshot.statusMessages],\n usage: { ...snapshot.usage },\n }),\n };\n}\n\n/** The run spinner as a progress emitter. One per run, like `getUI().spinner()`. */\nexport function createEmitSpinner(emit: ProgressEmitter): SpinnerHandle {\n return {\n start: (message) => emit({ kind: 'spinner', action: 'start', message }),\n stop: (message) => emit({ kind: 'spinner', action: 'stop', message }),\n message: (message) => emit({ kind: 'spinner', action: 'message', message }),\n };\n}\n\n/** A leveled logger as a progress emitter: each call is one `log` event. */\nexport function createEmitLog(emit: ProgressEmitter): {\n info(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n success(message: string): void;\n step(message: string): void;\n} {\n return {\n info: (message) => emit({ kind: 'log', level: 'info', message }),\n warn: (message) => emit({ kind: 'log', level: 'warn', message }),\n error: (message) => emit({ kind: 'log', level: 'error', message }),\n success: (message) => emit({ kind: 'log', level: 'success', message }),\n step: (message) => emit({ kind: 'log', level: 'step', message }),\n };\n}\n","/**\n * aio-capture — mirror wizard LLM calls into the authenticated project's\n * AI Observability tab as `$ai_generation` events. Gated on `--capture-aio`\n * (dev/test builds only); returns a no-op instance when disabled so the\n * wire-in points stay a no-op with zero overhead.\n *\n * The wizard's LLM calls happen inside subprocesses we don't own (the\n * claude-agent-sdk CLI on the anthropic path, pi's own runtime on pi), so we\n * can't wrap the client with `posthog-node`'s `wrapAnthropic`. Instead, each\n * harness surfaces assistant turns on the way back — the SDK message stream\n * on anthropic, `agentSession.subscribe(message_end)` on pi — and this module\n * composes an `$ai_generation` event from either shape.\n *\n * For the Conversation tab in AIO to render anything, each generation needs\n * `$ai_input` (the messages the model saw when it produced this turn). The\n * initial prompt is passed to the SDK subprocess and never echoed back on\n * the stream, so callers must hand it to `setInitialPrompt` before the run\n * starts. From there we track user/assistant turns as they flow through the\n * stream, snapshotting the running conversation into each generation's\n * `$ai_input` and firing `$ai_input_state` / `$ai_output_state` on the\n * terminal `$ai_trace` event.\n *\n * POSTs are fire-and-forget: failures are debug-logged and never surfaced to\n * the main agent flow. Losing an AIO event must never break a run.\n */\n\nimport { logToFile } from '@utils/debug';\nimport { VERSION } from '@shared/version';\n\n/** Conversation turn shape both harnesses normalize to. Matches Anthropic\n * message role/content conventions, which is also what AIO's Conversation\n * tab knows how to render. */\ntype Turn = { role: 'user' | 'assistant'; content: unknown };\n\n/** Common shape both harness transforms emit; fed to the shared POST. */\ntype LLMTurn = {\n provider: 'anthropic' | 'openai';\n model: string;\n /** Conversation up to (but not including) this assistant turn — the\n * messages the model saw. Sent as `$ai_input`. */\n input: Turn[];\n /** Content blocks (text + tool_use), passed through as $ai_output_choices. */\n outputChoices: unknown[];\n inputTokens?: number;\n outputTokens?: number;\n cacheReadTokens?: number;\n cacheCreationTokens?: number;\n /** Wall-clock ms since the previous assistant turn on this stream. */\n latencyMs: number;\n generationId?: string;\n isError: boolean;\n};\n\nexport type AioCapture = {\n /** Set the initial prompt the harness is about to send to the LLM. The\n * wizard passes this into the SDK subprocess out-of-band, so it never\n * appears on the return message stream — the caller must hand it to us\n * explicitly if we want `$ai_input` to include it. Safe to call multiple\n * times: latest wins, prior conversation state resets. */\n setInitialPrompt(prompt: string): void;\n /** Called for every SDK message on the anthropic harness stream. */\n captureFromAnthropicSDKMessage(msg: unknown): void;\n /** Called for every subscribe event on the pi harness. */\n captureFromPiMessageEndEvent(event: unknown): void;\n finishPiRun(isError: boolean): void;\n};\n\nconst noop = (_: unknown): void => undefined;\nconst NOOP: AioCapture = {\n setInitialPrompt: noop,\n captureFromAnthropicSDKMessage: noop,\n captureFromPiMessageEndEvent: noop,\n finishPiRun: noop,\n};\n\nexport function createAioCapture(args: {\n enabled: boolean;\n projectApiKey: string;\n apiHost: string;\n /** Trace tags from `buildRunTags` (program_id, integration, run_id, build, skill_id). */\n runTags: Record<string, string>;\n}): AioCapture {\n if (!args.enabled || !args.projectApiKey || !args.apiHost) return NOOP;\n\n const { projectApiKey, apiHost, runTags } = args;\n const distinctId = `wizard-cli-${VERSION}`;\n const captureUrl = `${apiHost.replace(/\\/$/, '')}/capture/`;\n const runStartAt = Date.now();\n // Latency is measured against the previous assistant turn on this stream —\n // a rough proxy for time-to-first-token that doesn't require SDK-internal\n // timings. Reset per createAioCapture (once per agent run).\n let prevTurnAt = runStartAt;\n // Fire the top-level `$ai_trace` event at most once per instance. Both\n // harnesses can emit terminal signals, and pi in particular may emit\n // multiple `agent_end` events across nudges — first-wins keeps trace\n // metadata stable in AIO.\n let traceEnded = false;\n\n // Running conversation state — grows as user and assistant turns flow\n // through the stream. Snapshotted into `$ai_input` on each generation.\n let initialPrompt: string | undefined;\n let conversation: Turn[] = [];\n let lastAssistantContent: unknown[] | undefined;\n\n const postEvent = (\n event: string,\n properties: Record<string, unknown>,\n ): void => {\n const body = {\n api_key: projectApiKey,\n event,\n distinct_id: distinctId,\n properties: {\n $ai_trace_id: runTags.run_id ?? '',\n ...runTags,\n ...properties,\n },\n timestamp: new Date().toISOString(),\n };\n\n // Fire-and-forget. `.then` + `.catch` (not `await`) so the caller returns\n // immediately; both branches only log. Errors must never propagate into\n // the agent stream loop.\n fetch(captureUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n .then((res) => {\n if (!res.ok) {\n logToFile(`[aio-capture] POST failed status=${res.status}`);\n }\n })\n .catch((err) => {\n logToFile(\n `[aio-capture] POST error: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n });\n };\n\n const postGeneration = (turn: LLMTurn): void => {\n postEvent('$ai_generation', {\n $ai_provider: turn.provider,\n $ai_model: turn.model,\n $ai_input: turn.input,\n $ai_output_choices: turn.outputChoices,\n $ai_input_tokens: turn.inputTokens ?? 0,\n $ai_output_tokens: turn.outputTokens ?? 0,\n $ai_cache_read_input_tokens: turn.cacheReadTokens ?? 0,\n $ai_cache_creation_input_tokens: turn.cacheCreationTokens ?? 0,\n $ai_latency: turn.latencyMs / 1000,\n $ai_generation_id: turn.generationId ?? '',\n $ai_is_error: turn.isError,\n });\n };\n\n // Emit the top-level `$ai_trace` event. Without this, PostHog builds a\n // pseudo-trace from the generations — the timeline and aggregates still\n // work, but the trace has no readable name and the Conversation tab shows\n // \"No top-level trace event\". Sending this once per run fills that in,\n // and `$ai_input_state` / `$ai_output_state` populate the trace-level\n // Conversation view.\n const sendTraceEnd = (opts: { isError: boolean }): void => {\n if (traceEnded) return;\n traceEnded = true;\n postEvent('$ai_trace', {\n $ai_span_name: runTags.program_id ?? 'wizard-run',\n $ai_latency: (Date.now() - runStartAt) / 1000,\n $ai_is_error: opts.isError,\n $ai_input_state: initialPrompt\n ? [{ role: 'user', content: [{ type: 'text', text: initialPrompt }] }]\n : [],\n $ai_output_state: lastAssistantContent ?? [],\n });\n };\n\n const anthropicAssistantTurn = (msg: unknown): LLMTurn | null => {\n const m = msg as {\n type?: string;\n message?: {\n id?: string;\n model?: string;\n content?: unknown;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n };\n };\n if (m?.type !== 'assistant' || !m.message) return null;\n const now = Date.now();\n const latencyMs = now - prevTurnAt;\n prevTurnAt = now;\n return {\n provider: 'anthropic',\n model: m.message.model ?? 'unknown',\n input: [...conversation],\n outputChoices: Array.isArray(m.message.content) ? m.message.content : [],\n inputTokens: m.message.usage?.input_tokens,\n outputTokens: m.message.usage?.output_tokens,\n cacheReadTokens: m.message.usage?.cache_read_input_tokens,\n cacheCreationTokens: m.message.usage?.cache_creation_input_tokens,\n latencyMs,\n generationId: m.message.id,\n isError: false,\n };\n };\n\n const piAssistantTurn = (event: unknown): LLMTurn | null => {\n const e = event as {\n type?: string;\n message?: {\n id?: string;\n role?: string;\n model?: string;\n content?: unknown;\n stopReason?: string;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n };\n };\n // Pi emits message_end for user prompts too — filter to assistant only,\n // mirroring the existing role guard at harness/pi/index.ts:434.\n if (e?.type !== 'message_end' || e.message?.role !== 'assistant') {\n return null;\n }\n const now = Date.now();\n const latencyMs = now - prevTurnAt;\n prevTurnAt = now;\n return {\n provider: 'anthropic',\n model: e.message.model ?? 'unknown',\n input: [...conversation],\n outputChoices: Array.isArray(e.message.content) ? e.message.content : [],\n inputTokens: e.message.usage?.input_tokens,\n outputTokens: e.message.usage?.output_tokens,\n cacheReadTokens: e.message.usage?.cache_read_input_tokens,\n cacheCreationTokens: e.message.usage?.cache_creation_input_tokens,\n latencyMs,\n generationId: e.message.id,\n isError:\n e.message.stopReason === 'error' || e.message.stopReason === 'aborted',\n };\n };\n\n return {\n setInitialPrompt(prompt) {\n initialPrompt = prompt;\n // Reset conversation to the initial user turn — this is the only way\n // the initial prompt gets into `$ai_input` for the first generation,\n // since the SDK subprocess consumes it internally and doesn't echo it\n // on the return stream.\n conversation = [\n { role: 'user', content: [{ type: 'text', text: prompt }] },\n ];\n lastAssistantContent = undefined;\n },\n captureFromAnthropicSDKMessage(msg) {\n try {\n // User turns (tool_result blocks between assistant turns) accumulate\n // in the conversation so the next assistant generation carries the\n // full context the model actually saw.\n const m = msg as {\n type?: string;\n message?: { role?: string; content?: unknown };\n is_error?: boolean;\n };\n if (m?.type === 'user' && m.message) {\n conversation.push({\n role: 'user',\n content: m.message.content ?? [],\n });\n }\n const turn = anthropicAssistantTurn(msg);\n if (turn) {\n postGeneration(turn);\n // Push the assistant turn AFTER posting so the current generation's\n // $ai_input is the conversation as the model saw it (not including\n // its own response), and later turns include this one.\n conversation.push({\n role: 'assistant',\n content: turn.outputChoices,\n });\n lastAssistantContent = turn.outputChoices;\n }\n // Terminal: SDK emits a `result` message at end of run.\n if (m?.type === 'result') {\n sendTraceEnd({ isError: !!m.is_error });\n }\n } catch (err) {\n logToFile(\n `[aio-capture] anthropic compose failed: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n },\n captureFromPiMessageEndEvent(event) {\n try {\n // Pi's subscribe callback surfaces both user and assistant\n // message_end events. Accumulate user turns the same way as the\n // anthropic path so `$ai_input` matches the model's view.\n const e = event as {\n type?: string;\n message?: { role?: string; content?: unknown };\n willRetry?: boolean;\n };\n if (\n e?.type === 'message_end' &&\n e.message?.role === 'user' &&\n e.message\n ) {\n conversation.push({\n role: 'user',\n content: e.message.content ?? [],\n });\n }\n const turn = piAssistantTurn(event);\n if (turn) {\n postGeneration(turn);\n conversation.push({\n role: 'assistant',\n content: turn.outputChoices,\n });\n lastAssistantContent = turn.outputChoices;\n }\n // The harness decides whether a final turn recovered before ending the trace.\n } catch (err) {\n logToFile(\n `[aio-capture] pi compose failed: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n },\n finishPiRun(isError) {\n sendTraceEnd({ isError });\n },\n };\n}\n","import { AgentErrorType } from '../../../signals';\nimport type { AgentOutputSignals } from '../../../output-signals';\n\n/** Fatal setup signals use the same precedence as the legacy harness. */\nexport function setupSignalFailure(\n signals: AgentOutputSignals,\n): AgentErrorType.MCP_MISSING | AgentErrorType.RESOURCE_MISSING | undefined {\n if (signals.has('MCP_MISSING')) return AgentErrorType.MCP_MISSING;\n if (signals.has('RESOURCE_MISSING')) return AgentErrorType.RESOURCE_MISSING;\n return undefined;\n}\n\n/** Which completion guard should fail a pi run, or undefined for a clean finish. */\nexport function completionFailure(args: {\n toolCalls: number;\n openTasks: boolean;\n}): AgentErrorType | undefined {\n // No tool call at all — the project was never touched.\n if (args.toolCalls === 0) return AgentErrorType.NO_PROGRESS;\n // Acted but left tasks in its own plan unfinished (skill install not required).\n if (args.openTasks) return AgentErrorType.INCOMPLETE_TASKS;\n return undefined;\n}\n\n/**\n * Which error type a thrown pi run reports.\n *\n * Both pi entry points classified the caught message inline with the same two\n * needles, and both did it *after* firing `agent aborted` — so the event that\n * announces the abort could not name it. Pulling the classification out lets\n * each entry point decide the type first and hand it to the event, and keeps\n * the one rule in one place.\n */\nexport function runErrorType(\n message: string,\n): AgentErrorType.RATE_LIMIT | AgentErrorType.API_ERROR {\n const lower = message.toLowerCase();\n if (lower.includes('rate limit') || lower.includes('429')) {\n return AgentErrorType.RATE_LIMIT;\n }\n return AgentErrorType.API_ERROR;\n}\n","/** Bind a host signal to Pi's abort-and-wait-for-idle operation. */\nexport function bindPiCancellation(\n signal: AbortSignal | undefined,\n session: { abort(): Promise<void> },\n onAbortError?: (error: unknown) => void,\n): { abort(): void; settle(): Promise<void> } {\n let abortPromise: Promise<void> | undefined;\n const onAbort = () => {\n abortPromise ??= Promise.resolve()\n .then(() => session.abort())\n .catch((error: unknown) => {\n try {\n onAbortError?.(error);\n } catch {\n /* Abort diagnostics are best effort. */\n }\n });\n };\n signal?.addEventListener('abort', onAbort, { once: true });\n if (signal?.aborted) onAbort();\n\n return {\n abort: onAbort,\n async settle() {\n signal?.removeEventListener('abort', onAbort);\n await abortPromise;\n },\n };\n}\n","import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport type { GatewayApi } from './gateway';\n\n/** Apply the output contract at the provider boundary on every agent turn. */\nexport function structuredOutputExtension(\n schema: Record<string, unknown>,\n api: GatewayApi,\n): (pi: ExtensionAPI) => void {\n return (pi) => {\n pi.on('before_provider_request', (event) => {\n const payload = event.payload as Record<string, unknown>;\n const format = { type: 'json_schema', schema };\n switch (api) {\n case 'anthropic-messages':\n return {\n ...payload,\n output_config: { ...(payload.output_config as object), format },\n };\n case 'openai-responses':\n return {\n ...payload,\n text: {\n ...(payload.text as object),\n format: { ...format, name: 'wizard_result', strict: true },\n },\n };\n case 'openai-completions':\n // `gatewayApiFor` never routes here, so no envelope is defined for it.\n throw new Error(\n 'Structured output is not supported on Chat Completions',\n );\n }\n });\n };\n}\n","/**\n * The `pi` backend — the challenger. Drives pi.dev's coding agent\n * (`@earendil-works/pi-coding-agent`) against the PostHog LLM gateway, behind\n * `wizard-orchestrator`. It owns the agent loop and model transport; prompt\n * assembly, error routing, and the outro stay in `linear.ts`, shared with the\n * `anthropic` control.\n *\n * Transport: the gateway is registered as an `anthropic-messages` provider\n * (same protocol the claude-agent-sdk path uses), bearer auth, Bedrock-fallback\n * + wizard metadata/flag headers, model id matched to `anthropic` for a clean\n * A/B. Security parity (canUseTool + YARA) and skills/MCP discovery are\n * follow-ups (#525, #524 skills) — v1 uses pi's built-in coding tools.\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport { getLogFilePath, logToFile } from '@utils/debug';\nimport {\n Harness,\n Sequence,\n WIZARD_REMARK_EVENT_NAME,\n wizardUserAgentForProgram,\n} from '@shared/constants';\nimport { analytics } from '@utils/analytics';\nimport { AgentErrorType } from '../../../agent-interface';\nimport {\n AgentSignals,\n REMARK_INSTRUCTION,\n policyAbortReason,\n} from '../../../signals';\nimport { AgentOutputSignals } from '../../../output-signals';\nimport { assembleCommandments } from '../../switchboard/commandments';\nimport { gatewayAuth, type GatewayAuth } from '../../../gateway-session';\nimport { currentAccessToken } from '@shared/oauth-session';\nimport {\n buildGatewayProvider,\n GATEWAY_PROVIDER,\n withGatewayRemint,\n} from './gateway';\nimport { createAioCapture } from '../../../aio-capture';\nimport type {\n AgentResult,\n AgentHarness,\n BackendRunInputs,\n TaskRunInputs,\n} from '../types';\nimport type { BootstrapResult } from '../../shared/types';\nimport type { ProgressEmitter } from '../../../progress';\nimport { createEmitLog } from '../../shared/progress-collector';\nimport type { TaskStore } from './tasks';\nimport type { SecurityState } from './security';\nimport {\n completionFailure,\n runErrorType,\n setupSignalFailure,\n} from './completion';\nimport { bindPiCancellation } from './cancellation';\nimport { structuredOutputExtension } from './structured-output';\nimport { classifyRunFailure, ErrorCodes } from '@shared/errors';\n\n/** Injects the MCP server `instructions` pi-mcp-adapter drops (project env, skill steer, tool domains) into the system prompt, falling back to a bootstrap-derived project block when the warm-connect captured none. */\nfunction piMcpContext(\n boot: BootstrapResult,\n instructions?: string,\n posthogMcp = true,\n): string {\n // No tool, no block. The fallback below names `posthog_exec`, so emitting it\n // after a failed handshake points the agent at a tool that is not registered.\n if (!posthogMcp) return '';\n if (instructions) {\n // Heading + verbatim server instructions (see PR #862 for a full sample).\n return ['', '## PostHog MCP server', instructions].join('\\n');\n }\n const project = boot.project?.name\n ? `${boot.project.name} (id ${boot.credentials.projectId})`\n : `id ${boot.credentials.projectId}`;\n // Fallback: a `## PostHog project` block with name/id, host, region.\n return [\n '',\n '## PostHog project',\n 'Your `posthog_exec` calls run against this project:',\n `- Project: ${project}`,\n `- Host: ${boot.credentials.host.apiHost}`,\n `- Region: ${boot.credentials.host.region}`,\n ].join('\\n');\n}\n\n/**\n * The ONLY environment variables pi's tool subprocesses (bash → npm/pip/…) are\n * allowed to see. Everything else — every secret (POSTHOG_PERSONAL_API_KEY,\n * ANTHROPIC_*, AWS_*), every ambient credential, the parent process's whole env\n * — is dropped before a child is spawned. pi's own gateway auth is programmatic\n * (the access token never lives in env), so a minimal env costs the agent\n * nothing while closing the leak that exposed the key before. Kept to what a\n * package manager genuinely needs to run.\n */\nconst ALLOWED_SUBPROCESS_ENV_KEYS = [\n 'PATH',\n 'HOME',\n 'SHELL',\n 'USER',\n 'LOGNAME',\n 'TMPDIR',\n 'TMP',\n 'TEMP',\n 'TERM',\n 'LANG',\n 'LC_ALL',\n 'LC_CTYPE',\n 'NODE_EXTRA_CA_CERTS',\n 'SSL_CERT_FILE',\n 'SSL_CERT_DIR',\n 'HTTP_PROXY',\n 'HTTPS_PROXY',\n 'NO_PROXY',\n 'http_proxy',\n 'https_proxy',\n 'no_proxy',\n];\n\n/** A fresh subprocess env holding only the allowlisted keys present in process.env. */\nexport function buildScrubbedEnv(): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = {};\n for (const key of ALLOWED_SUBPROCESS_ENV_KEYS) {\n const value = process.env[key];\n if (value !== undefined) env[key] = value;\n }\n return env;\n}\n\n/**\n * Tag a tool with an execution mode (mutates + returns it). Read-only tools are\n * `parallel` so a single turn that batches independent reads/searches runs them\n * at once; mutating/install tools are `sequential` so a batch never races writes\n * or concurrent installs. pi-agent-core runs a batch in parallel only when no\n * tool in it is `sequential`.\n */\nexport function withMode<T>(tool: T, mode: 'sequential' | 'parallel'): T {\n (tool as { executionMode?: 'sequential' | 'parallel' }).executionMode = mode;\n return tool;\n}\n\n/**\n * The text blocks of a pi AgentMessage (content is text/image blocks). A\n * Responses model can send several message items in one turn, commentary\n * before its answer, and each becomes its own block.\n */\nfunction textBlocks(message: unknown): string[] {\n const content = (message as { content?: unknown })?.content;\n if (typeof content === 'string') return [content];\n if (Array.isArray(content)) {\n return content\n .filter((c): c is { type: string; text: string } => {\n const block = c as { type?: string; text?: unknown };\n return block?.type === 'text' && typeof block.text === 'string';\n })\n .map((c) => c.text);\n }\n return [];\n}\n\n/** Pull plain text out of a pi AgentMessage. */\nexport function extractText(message: unknown): string {\n return textBlocks(message).join('');\n}\n\n/**\n * Surface `[DASHBOARD_URL]` / `[NOTEBOOK_URL]` markers the agent prints (after\n * the MCP creates them) into the outro link, mirroring the anthropic path's\n * signal parsing (#9). The marker carries the URL the MCP returned.\n */\nexport function applyOutroMarkers(\n textBlock: string,\n emit: ProgressEmitter,\n): void {\n const markers: Array<[string, (url: string) => void]> = [\n [\n AgentSignals.DASHBOARD_URL,\n (url) => emit({ kind: 'url', which: 'dashboard', url }),\n ],\n [\n AgentSignals.NOTEBOOK_URL,\n (url) => emit({ kind: 'url', which: 'notebook', url }),\n ],\n ];\n for (const [marker, apply] of markers) {\n const idx = textBlock.indexOf(marker);\n if (idx === -1) continue;\n const url = textBlock\n .slice(idx + marker.length)\n .trim()\n .split(/\\s/)[0];\n if (url) apply(url);\n }\n}\n\n/**\n * The text of the last `[STATUS] …` line in a block, if any. Last wins so the\n * spinner shows the most recent action when a turn prints several.\n */\nexport function lastStatusLine(textBlock: string): string | undefined {\n let status: string | undefined;\n for (const line of textBlock.split('\\n')) {\n const idx = line.indexOf(AgentSignals.STATUS);\n if (idx !== -1) {\n status = line.slice(idx + AgentSignals.STATUS.length).trim();\n }\n }\n return status || undefined;\n}\n\n/** Cap on completion-guard re-prompts while tasks remain open (see the run loop). */\nconst MAX_CONTINUE_NUDGES = 20;\n\n/** Nudge re-sent when the agent stops early with tasks still open. */\nconst CONTINUE_INSTRUCTION =\n 'You still have open tasks in your list (not all are marked `completed`). Do not stop — pick up the next `in_progress` or `pending` task and keep working until every task is `completed`. Continue now.';\n\n/** True while any task in the store is not yet `completed`. */\nfunction hasOpenTasks(store: TaskStore): boolean {\n for (const t of store.values()) if (t.status !== 'completed') return true;\n return false;\n}\n\nexport const piBackend: AgentHarness = {\n name: Harness.pi,\n\n async run(inputs: BackendRunInputs): Promise<AgentResult> {\n if (inputs.signal?.aborted) {\n return {\n kind: 'abort',\n classification: AgentErrorType.ABORT,\n message: 'Agent run cancelled',\n };\n }\n const {\n config: runConfig,\n input,\n boot,\n emit,\n prompt,\n spinner,\n structured,\n } = inputs;\n const config = runConfig.run;\n const modelId = inputs.model;\n const log = createEmitLog(emit);\n\n const capture = createAioCapture({\n enabled: input.flags.captureAio,\n projectApiKey: boot.credentials.projectApiKey,\n apiHost: boot.credentials.host.apiHost,\n runTags: boot.wizardMetadata,\n });\n\n // Init banner (parity #5).\n if (!structured) {\n log.step('Initializing Wizard agent...');\n log.step(`Verbose logs: ${getLogFilePath()}`);\n log.success(\"Agent initialized. Let's get cooking!\");\n }\n\n spinner.start(config.spinnerMessage ?? 'Customizing your PostHog setup...');\n\n // Same `agent completed`/`agent aborted` shape as anthropic.\n const startTime = Date.now();\n const signals = new AgentOutputSignals();\n let assistantTurns = 0;\n let lastAssistantText = '';\n // Tool calls across the whole run. Zero means the agent only ever produced\n // text and never acted — a no-op that leaves the project untouched.\n let toolCalls = 0;\n const runDurations = () => {\n const durationMs = Date.now() - startTime;\n return {\n duration_ms: durationMs,\n duration_seconds: Math.round(durationMs / 1000),\n };\n };\n // How this run failed: the closed AgentErrorType it is about to return.\n // Without it every terminal path below — a security termination, a no-op\n // run, a plan left open, a rate limit, a gateway error — arrived as the\n // same unlabelled event, so a run that died could be counted but not\n // diagnosed. Only two of those are errors; the rest are an enforcement\n // stop and two agent behaviours, hence \"failure mode\" over \"error\".\n //\n // Not `reason`: the linear sequence emits this same event with a `reason`\n // holding the agent's free-text [ABORT] string, and one property cannot be\n // both a closed enum and unbounded prose without making either unreadable.\n // `source` tells a gateway policy refusal apart from a program's [ABORT].\n const captureAborted = (\n failureMode: AgentErrorType,\n source?: 'gateway_policy',\n ) =>\n analytics.wizardCapture('agent aborted', {\n failure_mode: failureMode,\n ...(source && { source }),\n ...runDurations(),\n model: modelId,\n });\n const timedOutResult = (timeoutMs: number): AgentResult => {\n spinner.stop('Agent run timed out');\n captureAborted(AgentErrorType.AGENTIC_DETECTION_TIMEOUT);\n return {\n kind: 'failure',\n classification: AgentErrorType.AGENTIC_DETECTION_TIMEOUT,\n message: `Agent run timed out after ${timeoutMs / 1000}s`,\n };\n };\n\n let mcpCleanup: (() => void) | undefined;\n let aioFailed = true;\n let cancellation: ReturnType<typeof bindPiCancellation> | undefined;\n let timedOut = false;\n let timeoutAbort: Promise<void> | undefined;\n let abortReason: string | undefined;\n let remarkTurn = false;\n // The gateway's refusal marker ends the run from a work turn, never the remark.\n const policyAbort = (reply: string) => {\n if (remarkTurn) return;\n abortReason ??= policyAbortReason(reply);\n if (abortReason) cancellation?.abort();\n };\n // Read by the catch path; undefined until setup creates the extension.\n let securityState: SecurityState | undefined;\n // A latched violation outranks the timer on both the success and catch paths.\n const yaraViolationResult = (): AgentResult => {\n spinner.stop('Security violation detected');\n logToFile(\n `[pi] terminated: YARA violation (blocked ${securityState?.blockedCount} call(s))`,\n );\n captureAborted(AgentErrorType.YARA_VIOLATION);\n return {\n kind: 'failure',\n classification: AgentErrorType.YARA_VIOLATION,\n };\n };\n try {\n const {\n createAgentSession,\n DefaultResourceLoader,\n SessionManager,\n AuthStorage,\n ModelRegistry,\n getAgentDir,\n createLsToolDefinition,\n createFindToolDefinition,\n createGrepToolDefinition,\n createBashToolDefinition,\n createReadToolDefinition,\n createEditToolDefinition,\n createWriteToolDefinition,\n } = await import('@earendil-works/pi-coding-agent');\n\n // the claude-agent-sdk path. The provider spec is shared with the\n // orchestrator's per-task sessions (gateway.ts). gatewayAuth mints the\n // run's scoped token.\n // Reads the live OAuth token, so a mid-run rotation re-mints on the new one.\n const refreshAuth = async () =>\n gatewayAuth(\n boot.credentials.host,\n await currentAccessToken(boot.credentials),\n boot.programId,\n );\n const auth = await refreshAuth();\n const providerInputs = (current: GatewayAuth) => ({\n gatewayUrl: current.gatewayUrl,\n accessToken: current.token,\n teamId: current.teamId,\n wizardMetadata: boot.wizardMetadata,\n wizardFlags: boot.wizardFlags,\n modelId,\n effort: inputs.thinkingLevel,\n });\n const { provider, caps, api } = buildGatewayProvider(\n providerInputs(auth),\n );\n const registry = ModelRegistry.inMemory(AuthStorage.create());\n registry.registerProvider(GATEWAY_PROVIDER, provider as never);\n\n const model = registry.find(GATEWAY_PROVIDER, modelId);\n if (!model) {\n return {\n kind: 'failure',\n classification: AgentErrorType.API_ERROR,\n message: 'pi: gateway model could not be resolved',\n };\n }\n\n // System prompt = wizard commandments. Skip project context files /\n // user extensions / skills so the run is hermetic; skills discovery is a\n // follow-up (#524).\n //\n // Fail-closed security (#525): an extension intercepts EVERY tool call —\n // built-in and custom — and reuses the anthropic policy (canUseTool\n // allowlist + .env fencing + YARA). `noExtensions: true` only suppresses\n // disk-discovered extensions; explicit `extensionFactories` still load,\n // so the fence is on while the target project can't inject its own.\n // Shared flag: true while a wizard_ask overlay is open. The ask tool\n // flips it; the security gate reads it to block Write/Edit meanwhile.\n const askState = { pending: false };\n\n const { createSecurityExtension, READ_ONLY_PI_TOOLS } = await import(\n './security'\n );\n const security = createSecurityExtension({\n readOnly: config.readOnly,\n disallowedTools: runConfig.disallowedTools,\n getWizardAskPending: () => askState.pending,\n triageProvider: boot.triageProvider,\n // Where pi's bash runs; the rm allowance is confined to this tree.\n workingDirectory: input.installDir,\n });\n securityState = security.state;\n\n // Pay warlock's WASM-init + rule-compile cost now, off the tool-call\n // path, so the first scanned call doesn't eat cold-start latency.\n const { prewarmYaraScanner } = await import('../../../yara-hooks');\n void prewarmYaraScanner();\n\n // Wire the real PostHog MCP into pi (#10): load pi's MCP adapter and point\n // it at the hosted MCP the anthropic path uses, so dashboards/insights are\n // created through the sanctioned MCP. Best-effort — if it can't load or\n // connect, the run continues (minus the dashboard step) rather than failing\n // the whole integration. The security factory is always first.\n const extensionFactories = [security.factory] as Array<\n (pi: unknown) => void\n >;\n let mcpInstructions: string | undefined;\n // Whether the agent really got the tool. The commandments below claim\n // `posthog_exec` exists when this is true, so it must track the setup and\n // not the intent — a hardcoded `true` told the agent to call a tool the\n // failed handshake never registered. `task.ts` has always done this.\n let posthogMcp = false;\n if (!config.readOnly) {\n try {\n const { setupPostHogMcp, fetchInstructions } = await import('./mcp');\n const mcpToken = await currentAccessToken(boot.credentials);\n // The backend reads the `program:` marker off this UA to attribute what the run\n // creates (a self-driving run's warehouse sources become created_via=self_driving).\n // A plain WIZARD_USER_AGENT here records them as generic wizard work.\n const mcpUserAgent = wizardUserAgentForProgram(\n config.integrationLabel,\n );\n // Overlaps the network handshake with the adapter's jiti load.\n const instructionsPromise = fetchInstructions(\n boot.credentials.host.mcpUrl,\n mcpToken,\n mcpUserAgent,\n );\n const mcp = await setupPostHogMcp({\n mcpUrl: boot.credentials.host.mcpUrl,\n accessToken: mcpToken,\n userAgent: mcpUserAgent,\n });\n extensionFactories.push(mcp.extensionFactory);\n mcpCleanup = mcp.cleanup;\n mcpInstructions = await instructionsPromise;\n posthogMcp = true;\n } catch (err) {\n try {\n mcpCleanup?.();\n } catch {\n /* Setup cleanup is best effort. */\n }\n mcpCleanup = undefined;\n logToFile(`[pi] PostHog MCP setup skipped: ${String(err)}`);\n analytics.wizardCapture('mcp setup failed', {\n harness: 'pi',\n scope: 'run',\n error: String(err).slice(0, 300),\n });\n }\n }\n\n if (structured) {\n extensionFactories.push(\n structuredOutputExtension(structured.schema, api),\n );\n }\n\n const resourceLoader = new DefaultResourceLoader({\n cwd: input.installDir,\n agentDir: getAgentDir(),\n systemPrompt:\n assembleCommandments({\n program: runConfig.programId,\n sequence: Sequence.linear,\n harness: Harness.pi,\n caps: { bash: true, posthogMcp },\n }) +\n '\\n' +\n piMcpContext(boot, mcpInstructions, posthogMcp),\n noExtensions: true,\n noSkills: true,\n noContextFiles: true,\n noPromptTemplates: true,\n noThemes: true,\n extensionFactories,\n });\n await resourceLoader.reload();\n\n // Wizard capabilities as custom tools (pi has no MCP): skill\n // discovery/install + fenced .env edits, same names as the MCP server so\n // the shared prompt is unchanged. pi's built-in Read/Write/Edit/Bash do\n // the code changes. Loaded lazily — it pulls in typebox (ESM), which must\n // stay out of the static module graph so CommonJS unit tests can load the\n // backend seam without parsing it.\n const { createWizardPiTools } = await import('./tools');\n const { createWizardPiTaskTools } = await import('./tasks');\n const { createDispatchAgentTool } = await import('./subagent');\n // Created once so the run loop can read the store for the completion guard.\n const wizardTaskTools = createWizardPiTaskTools((tasks) =>\n emit({ kind: 'tasks', tasks }),\n );\n // The one bash the agent (and its subagents) may use: every subprocess it\n // spawns gets a scrubbed env, so no secret or ambient variable reaches an\n // `npm install`. Shared with the subagent so the lockdown is inherited.\n const scrubbedBash = withMode(\n createBashToolDefinition(input.installDir, {\n spawnHook: (ctx) => ({ ...ctx, env: buildScrubbedEnv() }),\n }),\n 'sequential',\n );\n\n const customTools = [\n // Built-ins re-registered explicitly. `noTools: 'builtin'` disables pi's\n // defaults so we can supply the env-scrubbed bash above; read/edit/write\n // are the stock definitions. Reads run in parallel so a batched turn of\n // independent reads executes at once; edit/write/bash stay sequential.\n withMode(createReadToolDefinition(input.installDir), 'parallel'),\n withMode(createEditToolDefinition(input.installDir), 'sequential'),\n withMode(createWriteToolDefinition(input.installDir), 'sequential'),\n scrubbedBash,\n // Native ls/find/grep so the agent explores with proper tools instead\n // of fence-blocked `bash {ls/find}` (the profiled retry-spirals came\n // from this gap). Parallel — exploration batches cleanly.\n withMode(createLsToolDefinition(input.installDir), 'parallel'),\n withMode(createFindToolDefinition(input.installDir), 'parallel'),\n withMode(createGrepToolDefinition(input.installDir), 'parallel'),\n ...createWizardPiTools({\n workingDirectory: input.installDir,\n skillsBaseUrl: boot.skillsBaseUrl,\n triageProvider: boot.triageProvider,\n emit,\n programId: boot.programId,\n handoffNotebook: boot.handoffNotebook,\n detectPackageManager: config.detectPackageManager,\n // The host ask bridge — lets interactive programs (self-driving) ask\n // the user through pi. Threaded from the runner, same path as the\n // anthropic harness. Absent in CI → the tool errors on call.\n askBridge: inputs.askBridge,\n maxQuestions: config.maxQuestions,\n onAskPendingChange: (pending) => {\n askState.pending = pending;\n },\n // Skip wizard_ask when the program disallows it (bare pi tool names\n // don't match the MCP-prefixed disallow list at the security gate).\n disallowedTools: runConfig.disallowedTools,\n }),\n // Task/todo tools (#526): render the todo list live in the TUI, parity\n // with the anthropic path.\n ...wizardTaskTools.tools,\n // Controlled subagent dispatch (#526): a nested fenced session with a\n // read-only toolset and no dispatch_agent of its own, so it can't\n // escape the fence or recurse.\n createDispatchAgentTool({\n model,\n modelRegistry: registry,\n cwd: input.installDir,\n agentDir: getAgentDir(),\n securityFactory: security.subagentFactory,\n bashTool: scrubbedBash,\n sdk: { createAgentSession, DefaultResourceLoader, SessionManager },\n }),\n ].filter((tool) => !config.readOnly || READ_ONLY_PI_TOOLS.has(tool.name));\n\n const { session: agentSession } = await createAgentSession({\n model,\n modelRegistry: registry,\n // Reasoning effort from the switchboard capability matrix (undefined =\n // pi's default). Sent as `reasoning_effort` for openai-completions.\n thinkingLevel: caps.thinkingLevel,\n cwd: input.installDir,\n sessionManager: SessionManager.inMemory(input.installDir),\n resourceLoader,\n // Disable the default built-in tools; `customTools` re-registers\n // read/edit/write + an env-scrubbed bash, so no subprocess inherits the\n // host env. Custom + extension tools stay enabled.\n noTools: 'builtin',\n customTools,\n });\n\n // Fire the extension lifecycle — what interactive mode does via\n // rebindCurrentSession. createAgentSession builds the session but does not\n // emit session_start on its own, and the MCP adapter connects on that\n // event; without this its tools report \"MCP not initialized\".\n cancellation = bindPiCancellation(\n inputs.signal,\n agentSession,\n (error) => {\n logToFile(`[pi] abort failed: ${String(error)}`);\n },\n );\n await agentSession.bindExtensions({});\n\n // A turn that ends on a 401 from an aged bearer re-mints once and\n // continues; pi resolves the provider's apiKey per request, so\n // re-registering is enough.\n const turns = withGatewayRemint({\n signal: inputs.signal,\n session: agentSession,\n registry,\n auth,\n refreshAuth,\n providerInputs,\n continueText: CONTINUE_INSTRUCTION,\n onRemint: () => {\n logToFile('[pi] gateway token renewed after a 401; continuing');\n analytics.wizardCapture('gateway token reminted', { harness: 'pi' });\n },\n });\n\n // Map pi events onto the run spinner + the log file, mirroring the\n // anthropic path's log shape (assistant turns + tool I/O) and driving the\n // single run spinner with one stable status at a time (no overlap).\n const unsubscribe = agentSession.subscribe((event) => {\n // Mirror the turn into AIO. No-op when --capture-aio is off. Runs\n // before the role guard so the module's own filter (assistant-only)\n // stays the single source of truth for what's captured.\n capture.captureFromPiMessageEndEvent(event);\n\n switch (event.type) {\n case 'message_end': {\n // User prompts also emit message_end; only assistant turns count.\n if ((event.message as { role?: string })?.role !== 'assistant') {\n break;\n }\n assistantTurns += 1;\n turns.noteAssistantTurn(event.message);\n const blocks = textBlocks(event.message);\n const assistant = blocks.join('').trim();\n policyAbort(assistant);\n // A schema-bound answer is the turn's last block, not the joined text.\n lastAssistantText = (blocks.at(-1) ?? '').trim();\n if (structured) {\n // One block per transcript line, so recovery can parse each.\n inputs.middleware?.onMessage({\n type: 'assistant',\n message: {\n content: blocks.map((text) => ({ type: 'text', text })),\n },\n });\n }\n if (assistant) {\n logToFile(`[pi] assistant: ${assistant.slice(0, 1000)}`);\n applyOutroMarkers(assistant, emit);\n // Surface [STATUS] lines into the live spinner + status history,\n // mirroring the anthropic path — pi otherwise drops them.\n const statusText = lastStatusLine(assistant);\n if (statusText) {\n emit({ kind: 'status', message: statusText });\n spinner.message(statusText);\n }\n for (const line of assistant.split('\\n')) signals.push(line);\n }\n break;\n }\n case 'tool_execution_start': {\n toolCalls += 1;\n const args = JSON.stringify(event.args ?? {}).slice(0, 200);\n logToFile(`[pi] → ${event.toolName} ${args}`);\n if (structured) {\n inputs.middleware?.onMessage({\n type: 'assistant',\n message: {\n content: [\n {\n type: 'tool_use',\n name: event.toolName,\n input: event.args,\n },\n ],\n },\n });\n }\n // Don't surface raw tool names in the spinner — the anthropic path\n // doesn't, and it reads as noise. The Task panel (syncTodos) is the\n // visible progress, matching the anthropic presentation.\n break;\n }\n case 'tool_execution_end': {\n // Log every result in full, matching the anthropic path's\n // SDK-message logging. Call-only logs make failed runs\n // undiagnosable: a tool can fail (or return something the model\n // misreads) with no trace of what came back.\n logToFile(\n `[pi] ${event.isError ? '✗' : '←'} ${event.toolName}: ${\n typeof event.result === 'string'\n ? event.result\n : JSON.stringify(event.result ?? '')\n }`,\n );\n // A subagent's refusal comes back as its tool result, not as parent text.\n if (event.toolName === 'dispatch_agent')\n policyAbort(extractText(event.result));\n break;\n }\n case 'agent_end': {\n logToFile(`[pi] agent_end (willRetry=${String(event.willRetry)})`);\n break;\n }\n default:\n break;\n }\n });\n\n // Seed AIO capture with the initial prompt so the first assistant\n // turn's `$ai_input` includes it — pi's subscribe stream doesn't emit\n // a message_end for the initial prompt, only for tool_result user\n // turns that follow.\n capture.setInitialPrompt(prompt);\n\n let terminal = turns.terminalFailure();\n // A structured run's budget starts once setup is done.\n const timeout =\n structured &&\n setTimeout(() => {\n timedOut = true;\n timeoutAbort = agentSession.abort().catch((error: unknown) => {\n logToFile(`[pi] timeout abort failed: ${String(error)}`);\n });\n }, structured.timeoutMs);\n try {\n if (inputs.signal?.aborted)\n return {\n kind: 'abort',\n classification: AgentErrorType.ABORT,\n message: 'Agent run cancelled',\n };\n // Non-streaming: resolves when the agent run completes. Throws if no\n // model/api key, or on a transport error.\n await turns.prompt(prompt);\n terminal = turns.terminalFailure();\n\n // Completion guard: pi's prompt() resolves the moment the model returns\n // a turn with no tool call (e.g. a lone [STATUS] line), even mid-plan.\n // While tasks remain open and we're under the cap, nudge it to continue.\n // A schema-bound scan has no plan to finish, so it never gets nudged.\n let continueNudges = 0;\n while (\n !structured &&\n continueNudges < MAX_CONTINUE_NUDGES &&\n !security.state.criticalViolation &&\n !inputs.signal?.aborted &&\n !terminal &&\n !abortReason &&\n !setupSignalFailure(signals) &&\n hasOpenTasks(wizardTaskTools.store)\n ) {\n continueNudges += 1;\n logToFile(\n `[pi] completion guard: tasks still open, nudge ${continueNudges}/${MAX_CONTINUE_NUDGES}`,\n );\n await turns.prompt(CONTINUE_INSTRUCTION);\n terminal = turns.terminalFailure();\n }\n\n // Best-effort remark ask — a failed turn never fails a successful run.\n if (\n !structured &&\n !security.state.criticalViolation &&\n !terminal &&\n !abortReason &&\n !setupSignalFailure(signals) &&\n !inputs.signal?.aborted\n ) {\n remarkTurn = true;\n try {\n await agentSession.prompt(REMARK_INSTRUCTION);\n } catch (err) {\n logToFile(`[pi] remark request failed: ${String(err)}`);\n }\n }\n } finally {\n if (timeout) clearTimeout(timeout);\n try {\n unsubscribe();\n } catch {\n /* Keep the terminal result. */\n }\n }\n\n if (inputs.signal?.aborted) {\n return {\n kind: 'abort',\n classification: AgentErrorType.ABORT,\n message: 'Agent run cancelled',\n };\n }\n if (timedOut && structured && !security.state.criticalViolation)\n return timedOutResult(structured.timeoutMs);\n\n if (abortReason)\n terminal = {\n classification: AgentErrorType.ABORT,\n message: abortReason,\n };\n if (terminal && !security.state.criticalViolation) {\n spinner.stop(\n config.errorMessage ?? `${config.integrationLabel} failed`,\n );\n captureAborted(\n terminal.classification,\n abortReason ? 'gateway_policy' : undefined,\n );\n if (terminal.status === 401) {\n return {\n kind: 'decided_failure',\n failure: {\n code: ErrorCodes.AuthInvalidOrExpired,\n message: 'Authentication failed (401)',\n detail: { providerMessage: terminal.message },\n },\n };\n }\n return terminal.classification === AgentErrorType.ABORT\n ? {\n kind: 'abort',\n classification: AgentErrorType.ABORT,\n message: terminal.message,\n }\n : {\n kind: 'failure',\n classification: terminal.classification,\n message: terminal.message,\n };\n }\n\n // A latched post-scan violation terminates the run as a YARA violation,\n // matching the anthropic path's AgentErrorType.YARA_VIOLATION.\n if (security.state.criticalViolation) return yaraViolationResult();\n\n const setupFailure = setupSignalFailure(signals);\n if (setupFailure) {\n spinner.stop('Agent could not access setup instructions');\n logToFile(`[pi] setup failed: ${setupFailure}`);\n captureAborted(setupFailure);\n return { kind: 'failure', classification: setupFailure };\n }\n\n // pi ends a run on any tool-call-less turn, so guard against a hollow\n // success reaching the outro (nothing done, or stopped mid-plan).\n const openTasks = !structured && hasOpenTasks(wizardTaskTools.store);\n const failure = completionFailure({ toolCalls, openTasks });\n if (failure === AgentErrorType.NO_PROGRESS) {\n spinner.stop('Agent made no changes');\n logToFile(\n `[pi] no progress: ${assistantTurns} assistant turn(s), 0 tool calls`,\n );\n analytics.wizardCapture('agent no progress', {\n assistant_turns: assistantTurns,\n });\n // A schema-bound run with no tool calls produced no typed result.\n const classification = structured\n ? AgentErrorType.INVALID_STRUCTURED_OUTPUT\n : failure;\n captureAborted(classification);\n return { kind: 'failure', classification };\n }\n if (failure === AgentErrorType.INCOMPLETE_TASKS) {\n spinner.stop('Agent stopped before finishing');\n logToFile('[pi] incomplete: tasks left open');\n analytics.wizardCapture('agent incomplete tasks', { open_tasks: true });\n captureAborted(failure);\n return { kind: 'failure', classification: failure };\n }\n\n const remark = signals.remark();\n if (remark) {\n analytics.capture(WIZARD_REMARK_EVENT_NAME, { remark });\n }\n\n // A failed install_skill is non-fatal — the agent continues best-effort\n // without the skill — but every such run must be measurable.\n const skillFailure = signals.skillInstallFailure();\n if (skillFailure !== undefined) {\n analytics.wizardCapture('agent continued without skill', {\n detail: skillFailure,\n });\n }\n\n // The skill plans events into .posthog-events.json then asks the agent to\n // remove it on completion; clean it up host-side too, so a skipped step\n // never leaves a stale (often empty) artifact (#15).\n try {\n const planFile = path.join(input.installDir, '.posthog-events.json');\n if (!structured && fs.existsSync(planFile))\n await fs.promises.rm(planFile);\n } catch (err) {\n logToFile(`[pi] .posthog-events.json cleanup skipped: ${String(err)}`);\n }\n\n const stats = agentSession.getSessionStats();\n analytics.wizardCapture('agent completed', {\n ...runDurations(),\n model: modelId,\n num_turns: assistantTurns,\n // API-reported tokens only; no total_cost_usd — the API returns no\n // cost, and $ai_generation already prices the run authoritatively.\n input_tokens: stats.tokens.input,\n output_tokens: stats.tokens.output,\n cache_creation_input_tokens: stats.tokens.cacheWrite,\n cache_read_input_tokens: stats.tokens.cacheRead,\n });\n spinner.stop(config.successMessage ?? 'PostHog integration complete');\n aioFailed = false;\n if (!structured) return { kind: 'success' };\n try {\n return {\n kind: 'success',\n structuredOutput: JSON.parse(lastAssistantText),\n };\n } catch {\n // The caller validates the result and owns its bounded retry.\n return { kind: 'success' };\n }\n } catch (err) {\n if (inputs.signal?.aborted) {\n return {\n kind: 'abort',\n classification: AgentErrorType.ABORT,\n message: 'Agent run cancelled',\n };\n }\n if (securityState?.criticalViolation) return yaraViolationResult();\n if (timedOut && structured) return timedOutResult(structured.timeoutMs);\n const message = err instanceof Error ? err.message : String(err);\n logToFile(`[pi] run error: ${message}`);\n spinner.stop(config.errorMessage ?? `${config.integrationLabel} failed`);\n log.error(`pi backend error: ${message}`);\n const coded = classifyRunFailure(err);\n if (coded.coded && err instanceof Error) {\n captureAborted(AgentErrorType.API_ERROR);\n return {\n kind: 'decided_failure',\n failure: { code: coded.code, message: coded.message, error: err },\n };\n }\n const classification = runErrorType(message);\n captureAborted(classification);\n return {\n kind: 'failure',\n classification,\n message,\n error: err instanceof Error ? err : undefined,\n };\n } finally {\n await cancellation?.settle();\n await timeoutAbort;\n try {\n mcpCleanup?.();\n } catch {\n /* Keep the terminal result. */\n }\n try {\n capture.finishPiRun(aioFailed);\n } catch {\n /* Telemetry is best effort. */\n }\n }\n },\n\n // Orchestrator mode: one fresh pi session per seed plan / drained task, with\n // the in-process queue tools registered as pi custom tools. Lazily imported —\n // task.ts pulls in typebox (ESM), which must stay out of the static module\n // graph so CommonJS unit tests can load the backend seam without parsing it.\n async runTask(inputs: TaskRunInputs): Promise<AgentResult> {\n const { runPiTask } = await import('./task');\n return runPiTask(inputs);\n },\n};\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { f as VERSION } from "./debug-C3tLP-ZW.js";
2
- import { s as exitWith } from "./runners-loOOmHyc.js";
3
- import { n as runPlayground$1 } from "./tui-Cmi_ckGg.js";
1
+ import { f as VERSION } from "./debug-BTUMatFI.js";
2
+ import { s as exitWith } from "./runners-CoIYt0iI.js";
3
+ import { n as runPlayground$1 } from "./tui-CBnRWnrm.js";
4
4
  //#region src/cli/commands/basic-integration/playground.ts
5
5
  /** Launch the TUI primitives playground. */
6
6
  function runPlayground() {
@@ -9,4 +9,4 @@ function runPlayground() {
9
9
  //#endregion
10
10
  export { runPlayground };
11
11
 
12
- //# sourceMappingURL=playground-CJx3lwTH.js.map
12
+ //# sourceMappingURL=playground-jxZNxRwC.js.map