@posthog/wizard 2.81.0 → 2.82.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 (120) hide show
  1. package/dist/{agent-interface-BFzBnz10.js → agent-interface-3YfIWZmY.js} +211 -46
  2. package/dist/agent-interface-3YfIWZmY.js.map +1 -0
  3. package/dist/{agent-prompt-loader-CbCW6YbP.js → agent-prompt-loader-hOHONY7u.js} +6 -6
  4. package/dist/{agent-prompt-loader-CbCW6YbP.js.map → agent-prompt-loader-hOHONY7u.js.map} +1 -1
  5. package/dist/{analytics-CGGE7OSa.js → analytics-B_xFshPY.js} +4 -3
  6. package/dist/analytics-B_xFshPY.js.map +1 -0
  7. package/dist/analytics-DGDr6-iD.js +2 -0
  8. package/dist/{api-ZZhiRtbb.js → api-C_9KsN-7.js} +71 -3
  9. package/dist/{api-ZZhiRtbb.js.map → api-C_9KsN-7.js.map} +1 -1
  10. package/dist/api-DhLSO3ai.js +2 -0
  11. package/dist/api-key-login-DiRuZ8Lm.js +2 -0
  12. package/dist/{api-key-login-D0KBr1dx.js → api-key-login-oUJQDmOV.js} +5 -5
  13. package/dist/{api-key-login-D0KBr1dx.js.map → api-key-login-oUJQDmOV.js.map} +1 -1
  14. package/dist/bin.js +1 -1
  15. package/dist/{bounded-fs-DwL2Tasp.js → bounded-fs-iRaQcKYL.js} +6 -4
  16. package/dist/bounded-fs-iRaQcKYL.js.map +1 -0
  17. package/dist/{ci-install-DKXrt_ow.js → ci-install-BGlijoTo.js} +4 -4
  18. package/dist/{ci-install-DKXrt_ow.js.map → ci-install-BGlijoTo.js.map} +1 -1
  19. package/dist/{debug-sB20p-Ek.js → debug-BvEbemym.js} +3 -3
  20. package/dist/{debug-sB20p-Ek.js.map → debug-BvEbemym.js.map} +1 -1
  21. package/dist/{gateway-Dg4Fm-nC.js → gateway-CWoYlPz7.js} +5 -5
  22. package/dist/{gateway-Dg4Fm-nC.js.map → gateway-CWoYlPz7.js.map} +1 -1
  23. package/dist/{headless-DhTDC9ga.js → headless-Bfi950Qh.js} +2 -2
  24. package/dist/{headless-DhTDC9ga.js.map → headless-Bfi950Qh.js.map} +1 -1
  25. package/dist/{headless-B3Ol1nkU.js → headless-Gisv3faN.js} +1 -1
  26. package/dist/{host-resolution-DDYJXiAQ.js → host-resolution-BxnNn8Jm.js} +4 -4
  27. package/dist/{host-resolution-DDYJXiAQ.js.map → host-resolution-BxnNn8Jm.js.map} +1 -1
  28. package/dist/{install-Dh8Z5R15.js → install-CDVeUT_5.js} +5 -5
  29. package/dist/{install-Dh8Z5R15.js.map → install-CDVeUT_5.js.map} +1 -1
  30. package/dist/{install-CZeR38cD.js → install-CX65IxGa.js} +1 -1
  31. package/dist/{interactive-hqHk6kz4.js → interactive-5-Numwwb.js} +3 -3
  32. package/dist/{interactive-hqHk6kz4.js.map → interactive-5-Numwwb.js.map} +1 -1
  33. package/dist/{links-rMot83W2.js → links-Dmj3Wj9X.js} +3 -3
  34. package/dist/{links-rMot83W2.js.map → links-Dmj3Wj9X.js.map} +1 -1
  35. package/dist/{main-DNIeasXx.js → main-5KNn80Vt.js} +20 -20
  36. package/dist/{main-DNIeasXx.js.map → main-5KNn80Vt.js.map} +1 -1
  37. package/dist/{mcp-SZcGfaOz.js → mcp-Buf9sfFm.js} +3 -3
  38. package/dist/{mcp-SZcGfaOz.js.map → mcp-Buf9sfFm.js.map} +1 -1
  39. package/dist/{mcp-prompt-streaming-BuRMBgbo.js → mcp-prompt-streaming-DHPxJK-F.js} +5 -5
  40. package/dist/{mcp-prompt-streaming-BuRMBgbo.js.map → mcp-prompt-streaming-DHPxJK-F.js.map} +1 -1
  41. package/dist/{models-G1j-wgwe.js → models-C9rjXPZ6.js} +2 -2
  42. package/dist/{models-G1j-wgwe.js.map → models-C9rjXPZ6.js.map} +1 -1
  43. package/dist/{oauth-session-C2fVSGfr.js → oauth-session-Bi1MLRCC.js} +45 -3
  44. package/dist/oauth-session-Bi1MLRCC.js.map +1 -0
  45. package/dist/{orchestrator-tools-BchqG7Qi.js → orchestrator-tools-DyKws92o.js} +3 -3
  46. package/dist/{orchestrator-tools-BchqG7Qi.js.map → orchestrator-tools-DyKws92o.js.map} +1 -1
  47. package/dist/{package-manager-B3_qSybg.js → package-manager-DpCdmMmB.js} +4 -4
  48. package/dist/{package-manager-B3_qSybg.js.map → package-manager-DpCdmMmB.js.map} +1 -1
  49. package/dist/{pi-Cw7CPXSl.js → pi-DTj1hsJe.js} +32 -15
  50. package/dist/pi-DTj1hsJe.js.map +1 -0
  51. package/dist/{playground-CPNrQfb3.js → playground-CiH6zZPb.js} +4 -4
  52. package/dist/{playground-CPNrQfb3.js.map → playground-CiH6zZPb.js.map} +1 -1
  53. package/dist/{posthog-integration-FAWfClH3.js → posthog-integration-CpinLWNO.js} +78 -35
  54. package/dist/posthog-integration-CpinLWNO.js.map +1 -0
  55. package/dist/{programs-Ml6OLybj.js → programs-Bq9Ju9xk.js} +28 -23
  56. package/dist/programs-Bq9Ju9xk.js.map +1 -0
  57. package/dist/programs-CnOSdQo1.js +3 -0
  58. package/dist/{provisioning-BTVL49jD.js → provisioning-D-AM_7DG.js} +4 -4
  59. package/dist/{provisioning-BTVL49jD.js.map → provisioning-D-AM_7DG.js.map} +1 -1
  60. package/dist/provisioning-D6Cqbc36.js +2 -0
  61. package/dist/{queue-tools-BQfRI_uD.js → queue-tools-BoIITT7w.js} +4 -4
  62. package/dist/{queue-tools-BQfRI_uD.js.map → queue-tools-BoIITT7w.js.map} +1 -1
  63. package/dist/{results-ycm_Tf31.js → results-CDqlHogZ.js} +2 -2
  64. package/dist/{results-ycm_Tf31.js.map → results-CDqlHogZ.js.map} +1 -1
  65. package/dist/{run-C6Ei6vvb.js → run-CfMArkpV.js} +7 -7
  66. package/dist/{run-C6Ei6vvb.js.map → run-CfMArkpV.js.map} +1 -1
  67. package/dist/{run-Bgg-ctbA.js → run-DcaVJSeI.js} +10 -10
  68. package/dist/{run-Bgg-ctbA.js.map → run-DcaVJSeI.js.map} +1 -1
  69. package/dist/{run-tool-CrN2xWzU.js → run-tool-DJZWnnR9.js} +18 -18
  70. package/dist/{run-tool-CrN2xWzU.js.map → run-tool-DJZWnnR9.js.map} +1 -1
  71. package/dist/run-tool-zMLQroVh.js +2 -0
  72. package/dist/{runners-GGYJs0Ny.js → runners-Cvnk9BcA.js} +8 -8
  73. package/dist/{runners-GGYJs0Ny.js.map → runners-Cvnk9BcA.js.map} +1 -1
  74. package/dist/{security-C36p8lu6.js → security-Cz3a-d7r.js} +5 -5
  75. package/dist/{security-C36p8lu6.js.map → security-Cz3a-d7r.js.map} +1 -1
  76. package/dist/{setup-utils-Dfgse6pY.js → setup-utils-C7kaDP5X.js} +3 -3
  77. package/dist/{setup-utils-Dfgse6pY.js.map → setup-utils-C7kaDP5X.js.map} +1 -1
  78. package/dist/{start-playground-D0TrdLmc.js → start-playground-B62_pYfu.js} +13 -13
  79. package/dist/{start-playground-D0TrdLmc.js.map → start-playground-B62_pYfu.js.map} +1 -1
  80. package/dist/{subagent-DR5caRzL.js → subagent-BBfETG17.js} +3 -3
  81. package/dist/{subagent-DR5caRzL.js.map → subagent-BBfETG17.js.map} +1 -1
  82. package/dist/{task-C1qKgsAf.js → task-CmNe3xeg.js} +28 -16
  83. package/dist/task-CmNe3xeg.js.map +1 -0
  84. package/dist/{telemetry-Ch9ZJvm7.js → telemetry-DKM7VGuJ.js} +2 -2
  85. package/dist/{telemetry-Ch9ZJvm7.js.map → telemetry-DKM7VGuJ.js.map} +1 -1
  86. package/dist/{terminal-D20JFN3J.js → terminal-Bkxwzkhn.js} +118 -93
  87. package/dist/terminal-Bkxwzkhn.js.map +1 -0
  88. package/dist/{tools-CmSMclOD.js → tools-Bm0FDT6f.js} +15 -11
  89. package/dist/tools-Bm0FDT6f.js.map +1 -0
  90. package/dist/{tools-BZseGChD.js → tools-DZCEvDv9.js} +13 -13
  91. package/dist/{tools-BZseGChD.js.map → tools-DZCEvDv9.js.map} +1 -1
  92. package/dist/{tui-BXe1D0tc.js → tui-B56jvkbi.js} +4 -4
  93. package/dist/{tui-BXe1D0tc.js.map → tui-B56jvkbi.js.map} +1 -1
  94. package/dist/{tui-DJf3ZPRh.js → tui-tKI95MSr.js} +1 -1
  95. package/dist/{upload-step-BlAN7MC5.js → upload-step-DqTgn6UB.js} +3 -3
  96. package/dist/{upload-step-BlAN7MC5.js.map → upload-step-DqTgn6UB.js.map} +1 -1
  97. package/dist/{urls-eFaChZ9d.js → urls-B82v7gfO.js} +2 -2
  98. package/dist/{urls-eFaChZ9d.js.map → urls-B82v7gfO.js.map} +1 -1
  99. package/dist/{wizard-abort-BX3O4Hg4.js → wizard-abort-Cd-7sfCw.js} +4 -4
  100. package/dist/{wizard-abort-BX3O4Hg4.js.map → wizard-abort-Cd-7sfCw.js.map} +1 -1
  101. package/dist/{yara-hooks-C4HOysrM.js → yara-hooks-BS0n3ekf.js} +4 -4
  102. package/dist/{yara-hooks-C4HOysrM.js.map → yara-hooks-BS0n3ekf.js.map} +1 -1
  103. package/dist/{yara-hooks-DV4EkkZY.js → yara-hooks-CxksH-GZ.js} +1 -1
  104. package/package.json +1 -1
  105. package/dist/agent-interface-BFzBnz10.js.map +0 -1
  106. package/dist/analytics-CGGE7OSa.js.map +0 -1
  107. package/dist/analytics-D6NAIJxP.js +0 -2
  108. package/dist/api-DM4uMJ00.js +0 -2
  109. package/dist/api-key-login-C30LRht2.js +0 -2
  110. package/dist/bounded-fs-DwL2Tasp.js.map +0 -1
  111. package/dist/oauth-session-C2fVSGfr.js.map +0 -1
  112. package/dist/pi-Cw7CPXSl.js.map +0 -1
  113. package/dist/posthog-integration-FAWfClH3.js.map +0 -1
  114. package/dist/programs-DjCmEcxb.js +0 -3
  115. package/dist/programs-Ml6OLybj.js.map +0 -1
  116. package/dist/provisioning-DL0xCJXH.js +0 -2
  117. package/dist/run-tool-tNjm8S-E.js +0 -2
  118. package/dist/task-C1qKgsAf.js.map +0 -1
  119. package/dist/terminal-D20JFN3J.js.map +0 -1
  120. package/dist/tools-CmSMclOD.js.map +0 -1
@@ -1,11 +1,13 @@
1
- import { a as initLogFile, i as getLogFilePath, o as logToFile, r as formatLogLine, v as runtimeEnv } from "./debug-sB20p-Ek.js";
2
- import { $ as WIZARD_REMARK_EVENT_NAME, it as wizardUserAgentForProgram, l as AWS_SKILLS_BASE_URL, n as analytics } from "./analytics-CGGE7OSa.js";
1
+ import { a as initLogFile, i as getLogFilePath, o as logToFile, r as formatLogLine, v as runtimeEnv } from "./debug-BvEbemym.js";
2
+ import { $ as WIZARD_REMARK_EVENT_NAME, it as wizardUserAgentForProgram, l as AWS_SKILLS_BASE_URL, n as analytics } from "./analytics-B_xFshPY.js";
3
3
  import { i as classifyAuthFailure } from "./errors-DhFeR8Sp.js";
4
- import { a as safeReadFile, i as readProjectFile, o as walkProjectFiles } from "./bounded-fs-DwL2Tasp.js";
5
- import { c as REMARK_INSTRUCTION, d as gatewayAuth, f as isPastRefresh, i as gatewayApiFor, l as RESUME_INSTRUCTION, n as buildGatewayModel, s as AgentSignals, u as buildWizardPropertiesBlob } from "./gateway-Dg4Fm-nC.js";
6
- import { i as modelCapabilities, o as triageModelFor } from "./models-G1j-wgwe.js";
7
- import { _ as makeMutex, l as buildOrchestratorTools, v as writeJsonAtomic } from "./queue-tools-BQfRI_uD.js";
8
- import { C as coerceAuditChecks, _ as downloadSkill, l as prewarmYaraScanner, n as createPostToolUseYaraHooks, p as scanInstalledSkill, r as createPreToolUseYaraHooks, x as AUDIT_CHECKS_FILE, y as fetchSkillMenu } from "./yara-hooks-C4HOysrM.js";
4
+ import { a as safeReadFile, i as readProjectFile, o as walkProjectFiles } from "./bounded-fs-iRaQcKYL.js";
5
+ import { c as isGrantRevoked, i as oauthCredentials, s as rotateAfterUnauthorized } from "./oauth-session-Bi1MLRCC.js";
6
+ import { c as REMARK_INSTRUCTION, d as gatewayAuth, f as isPastRefresh, i as gatewayApiFor, l as RESUME_INSTRUCTION, n as buildGatewayModel, s as AgentSignals, u as buildWizardPropertiesBlob } from "./gateway-CWoYlPz7.js";
7
+ import { i as modelCapabilities, o as triageModelFor } from "./models-C9rjXPZ6.js";
8
+ import { _ as makeMutex, l as buildOrchestratorTools, v as writeJsonAtomic } from "./queue-tools-BoIITT7w.js";
9
+ import { C as coerceAuditChecks, _ as downloadSkill, l as prewarmYaraScanner, n as createPostToolUseYaraHooks, p as scanInstalledSkill, r as createPreToolUseYaraHooks, x as AUDIT_CHECKS_FILE, y as fetchSkillMenu } from "./yara-hooks-BS0n3ekf.js";
10
+ import { a as createMarkdownNotebook, f as updateMarkdownNotebook, s as fetchMarkdownNotebook } from "./api-C_9KsN-7.js";
9
11
  import { createRequire } from "node:module";
10
12
  import * as fs$1 from "fs";
11
13
  import fs from "fs";
@@ -13,7 +15,8 @@ import path from "path";
13
15
  import path$1 from "node:path";
14
16
  import { spawnSync } from "node:child_process";
15
17
  import { closeSync, constants, fchmodSync, lstatSync, openSync, renameSync, unlinkSync, writeSync } from "node:fs";
16
- import { randomBytes, randomUUID } from "node:crypto";
18
+ import axios from "axios";
19
+ import { createHash, randomBytes, randomUUID } from "node:crypto";
17
20
  import * as os from "os";
18
21
  import { minimatch } from "minimatch";
19
22
  import { randomUUID as randomUUID$1 } from "crypto";
@@ -1518,6 +1521,173 @@ const WIZARD_TOOL_NAMES = {
1518
1521
  readHandoffs: `mcp__${SERVER_NAME}__read_handoffs`
1519
1522
  };
1520
1523
  //#endregion
1524
+ //#region src/agent/tools/handoff-notebook.ts
1525
+ /**
1526
+ * The PostHog notebook that mirrors a run's handoff report. The first call of a
1527
+ * run creates it, later calls (a report task retry) update the same one, so a
1528
+ * run owns one notebook. It never throws: a notebook that can't be written is a
1529
+ * skip the caller reports, not a failed handoff.
1530
+ */
1531
+ const NOTEBOOK_SCOPE = "notebook:write";
1532
+ const DEFAULT_TITLE = "PostHog setup report";
1533
+ /** One deadline for the whole sync, so a slow PostHog cannot hold the agent's tool call. */
1534
+ const SYNC_DEADLINE_MS = 8e3;
1535
+ /** The notebook each program of a run holds: where to update it and the version to send. */
1536
+ const notebooks = /* @__PURE__ */ new Map();
1537
+ /** An alphanumeric id of the 12 characters the backend allows, the same for one key every time. */
1538
+ const shortIdFor = (key) => createHash("sha256").update(key).digest("hex").slice(0, 12);
1539
+ /** The backend's title limit, the one the MCP's notebook tools enforce. */
1540
+ const MAX_TITLE_LENGTH = 256;
1541
+ /** The report's first H1, which the report is told to open with. */
1542
+ const titleOf = (markdown) => (/^# +(.+)$/m.exec(markdown)?.[1].trim() || DEFAULT_TITLE).slice(0, MAX_TITLE_LENGTH);
1543
+ const failed = (reason, description, heldUrl) => {
1544
+ logToFile(`[publish_handoff] notebook ${heldUrl ? "not updated" : "skipped"} (${reason})`);
1545
+ return heldUrl ? {
1546
+ outcome: "not_updated",
1547
+ reason,
1548
+ description,
1549
+ url: heldUrl
1550
+ } : {
1551
+ outcome: "skipped",
1552
+ reason,
1553
+ description
1554
+ };
1555
+ };
1556
+ const responseStatus = (err) => axios.isAxiosError(err) ? err.response?.status : void 0;
1557
+ const TIMEOUT_CODES = new Set([
1558
+ "ERR_CANCELED",
1559
+ "ECONNABORTED",
1560
+ "ETIMEDOUT"
1561
+ ]);
1562
+ const isTimeout = (err, signal) => signal.aborted || err instanceof Error && TIMEOUT_CODES.has(err.code ?? "");
1563
+ /** A short code for telemetry and a few words for the agent; neither carries a body or a token. */
1564
+ function failureFor(err, signal, heldUrl) {
1565
+ if (isTimeout(err, signal)) return failed("timeout", "PostHog did not answer in time", heldUrl);
1566
+ const status = responseStatus(err);
1567
+ if (status === 401) return failed("unauthorized", "PostHog rejected the login", heldUrl);
1568
+ if (status === 403) return failed("http_403", "PostHog denied access", heldUrl);
1569
+ if (status !== void 0) return failed(`http_${status}`, `PostHog returned HTTP ${status}`, heldUrl);
1570
+ return failed("error", "the request to PostHog failed", heldUrl);
1571
+ }
1572
+ /** A write worth one more try: no response at all (not a cancel), or a server error. */
1573
+ function isTransient(err, signal) {
1574
+ if (isTimeout(err, signal)) return false;
1575
+ const status = responseStatus(err);
1576
+ return status === void 0 || status >= 500;
1577
+ }
1578
+ /** Whether a failed create may still have made the notebook: lost response, server error, or an id clash. */
1579
+ function mayHaveLanded(err) {
1580
+ const status = responseStatus(err);
1581
+ return status === void 0 || status >= 500 || status === 400 || status === 409;
1582
+ }
1583
+ /** Give up on `work` when the deadline passes, even if the call under it ignores the signal. */
1584
+ function beforeDeadline(work, signal) {
1585
+ if (signal.aborted) return Promise.reject(signal.reason);
1586
+ return new Promise((resolve, reject) => {
1587
+ const onAbort = () => reject(signal.reason);
1588
+ signal.addEventListener("abort", onAbort, { once: true });
1589
+ work.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
1590
+ });
1591
+ }
1592
+ /** Create this program's notebook from `markdown`, or update it when an earlier call in the run made one. */
1593
+ async function syncHandoffNotebook(markdown, programId = "") {
1594
+ const controller = new AbortController();
1595
+ const timer = setTimeout(() => controller.abort(), SYNC_DEADLINE_MS);
1596
+ try {
1597
+ return await sync(markdown, programId, controller.signal);
1598
+ } finally {
1599
+ clearTimeout(timer);
1600
+ }
1601
+ }
1602
+ async function sync(markdown, programId, signal) {
1603
+ const key = `${analytics.runId}:${programId}`;
1604
+ const held = notebooks.get(key);
1605
+ const shortId = held?.shortId ?? shortIdFor(key);
1606
+ const heldUrl = held?.url;
1607
+ let fetched;
1608
+ try {
1609
+ fetched = await beforeDeadline(oauthCredentials(), signal);
1610
+ } catch (err) {
1611
+ return failureFor(err, signal, heldUrl);
1612
+ }
1613
+ const urlFor = (login) => `${login.host.appHost}/project/${login.projectId}/notebooks/${shortId}`;
1614
+ if (!fetched) return failed("no_login", "not logged in to PostHog", heldUrl);
1615
+ let credentials = fetched;
1616
+ if (credentials.missingScopes?.includes(NOTEBOOK_SCOPE)) return failed("missing_scope", `the login lacks the ${NOTEBOOK_SCOPE} permission`, heldUrl);
1617
+ /** Push `markdown` as this login: create, or update at the version the server holds. */
1618
+ const push = async (login, retried) => {
1619
+ const args = [
1620
+ login.accessToken,
1621
+ login.projectId,
1622
+ login.host.apiHost
1623
+ ];
1624
+ let version = held?.version;
1625
+ const lookup = async () => {
1626
+ try {
1627
+ return await fetchMarkdownNotebook(...args, shortId, signal);
1628
+ } catch {
1629
+ return null;
1630
+ }
1631
+ };
1632
+ if (retried) {
1633
+ const found = await lookup();
1634
+ if (found?.markdown === markdown) return found.version;
1635
+ version = found?.version ?? version;
1636
+ }
1637
+ if (version === void 0) try {
1638
+ return await createMarkdownNotebook(...args, {
1639
+ shortId,
1640
+ title: titleOf(markdown),
1641
+ markdown
1642
+ }, signal);
1643
+ } catch (err) {
1644
+ const found = mayHaveLanded(err) ? await lookup() : null;
1645
+ if (!found) throw err;
1646
+ if (found.markdown === markdown) return found.version;
1647
+ version = found.version;
1648
+ }
1649
+ return updateMarkdownNotebook(...args, {
1650
+ shortId,
1651
+ markdown,
1652
+ version
1653
+ }, signal);
1654
+ };
1655
+ /** One try, plus one more with a rotated token after a 401. */
1656
+ const authorized = async (retried) => {
1657
+ try {
1658
+ return await push(credentials, retried);
1659
+ } catch (err) {
1660
+ if (responseStatus(err) !== 401) throw err;
1661
+ const recovery = await beforeDeadline(rotateAfterUnauthorized(credentials, { requireRefreshToken: false }), signal);
1662
+ if (recovery.kind !== "rotated") throw err;
1663
+ credentials = recovery.credentials;
1664
+ return push(credentials, retried);
1665
+ }
1666
+ };
1667
+ let version;
1668
+ try {
1669
+ try {
1670
+ version = await beforeDeadline(authorized(false), signal);
1671
+ } catch (err) {
1672
+ if (!isTransient(err, signal)) throw err;
1673
+ version = await beforeDeadline(authorized(true), signal);
1674
+ }
1675
+ } catch (err) {
1676
+ return failureFor(err, signal, heldUrl);
1677
+ }
1678
+ const url = urlFor(credentials);
1679
+ notebooks.set(key, {
1680
+ shortId,
1681
+ version,
1682
+ url
1683
+ });
1684
+ logToFile(`[publish_handoff] notebook ${held ? "updated" : "created"}`);
1685
+ return {
1686
+ outcome: held ? "updated" : "created",
1687
+ url
1688
+ };
1689
+ }
1690
+ //#endregion
1521
1691
  //#region src/shared/utils/needs-attention.ts
1522
1692
  /** The heading of the warning block a handoff report opens with when work is left. */
1523
1693
  const NEEDS_ATTENTION_HEADING = "Needs your attention";
@@ -1557,7 +1727,7 @@ const PUBLISH_HANDOFF_TOOL_NAME = "publish_handoff";
1557
1727
  * full report per step, each replaced by the next, and a step that read the
1558
1728
  * call as its own finish skipped `complete_task` and was restarted.
1559
1729
  */
1560
- const PUBLISH_HANDOFF_DESCRIPTION = `Publish the handoff document — the full markdown report of what the whole run did — to the wizard session. A run publishes once: call it only when your own instructions ask you to write that report, passing the complete report as \`content\`, and never write the report to a file yourself. When anything is left for the user to do, open the report, right under the H1, with a \`> ⚠️ **${NEEDS_ATTENTION_HEADING}**\` block quote, one \`> - \` bullet per item. It is not how you report your own work — in a run made of several tasks each step finishes with complete_task, and a step that was not asked for the run report leaves this one uncalled, because the section it owns travels in its handoff.`;
1730
+ const PUBLISH_HANDOFF_DESCRIPTION = `Publish the handoff document — the full markdown report of what the whole run did — to the wizard session. A run publishes once: call it only when your own instructions ask you to write that report, passing the complete report as \`content\`, and never write the report to a file yourself. When anything is left for the user to do, open the report, right under the H1, with a \`> ⚠️ **${NEEDS_ATTENTION_HEADING}**\` block quote, one \`> - \` bullet per item. It is not how you report your own work — in a run made of several tasks each step finishes with complete_task, and a step that was not asked for the run report leaves this one uncalled, because the section it owns travels in its handoff. When the result names a PostHog notebook, the wizard already mirrored the report there: never create a notebook yourself.`;
1561
1731
  /** Appended for a task agent: the reminder lands as it decides it has finished. */
1562
1732
  const TASK_REPORTING_NOTE = " This does not report your task: call complete_task to finish.";
1563
1733
  const PUBLISH_HANDOFF_CONTENT_DESCRIPTION = "The complete handoff report as markdown, starting with an H1 heading.";
@@ -1621,7 +1791,14 @@ function writeHandoffFileAtomically(targetPath, text) {
1621
1791
  };
1622
1792
  }
1623
1793
  }
1624
- function publishHandoff(content, emit, opts = {}) {
1794
+ const notebookNote = (notebook) => {
1795
+ switch (notebook.outcome) {
1796
+ case "skipped": return `Notebook not created: ${notebook.description}.`;
1797
+ case "not_updated": return `Notebook not updated: ${notebook.description}. It still holds the earlier report: ${notebook.url}.`;
1798
+ default: return `Notebook ${notebook.outcome}: ${notebook.url}. Do not create another notebook.`;
1799
+ }
1800
+ };
1801
+ async function publishHandoff(content, emit, opts = {}) {
1625
1802
  if (content.trim() === "") {
1626
1803
  analytics.wizardCapture("handoff published", {
1627
1804
  handoff_ok: false,
@@ -1649,18 +1826,28 @@ function publishHandoff(content, emit, opts = {}) {
1649
1826
  logToFile(`[publish_handoff] host output write failed (${write.reason}): ${write.detail}`);
1650
1827
  }
1651
1828
  }
1829
+ const notebookRequested = opts.handoffNotebook === true;
1830
+ const notebook = notebookRequested ? await syncHandoffNotebook(text, opts.programId) : void 0;
1831
+ if (notebook?.outcome === "created" || notebook?.outcome === "updated") emit?.({
1832
+ kind: "url",
1833
+ which: "notebook",
1834
+ url: notebook.url
1835
+ });
1652
1836
  analytics.wizardCapture("handoff published", {
1653
1837
  handoff_ok: true,
1654
1838
  handoff_chars: text.length,
1655
1839
  handoff_truncated: truncated,
1656
- handoff_output_written: handoffOutputWritten
1840
+ handoff_output_written: handoffOutputWritten,
1841
+ notebook_requested: notebookRequested,
1842
+ notebook_outcome: notebook?.outcome,
1843
+ notebook_skip_reason: notebook?.outcome === "skipped" || notebook?.outcome === "not_updated" ? notebook.reason : void 0
1657
1844
  });
1658
1845
  const notes = [];
1659
1846
  if (truncated) notes.push("truncated to the 64 KB limit");
1660
1847
  if (handoffOutputError) notes.push(`host output write failed: ${handoffOutputError}`);
1661
1848
  return {
1662
1849
  ok: true,
1663
- message: `Handoff published (${text.length} chars${notes.length > 0 ? `, ${notes.join("; ")}` : ""}).${opts.taskAgent ? TASK_REPORTING_NOTE : ""}`
1850
+ message: `Handoff published (${text.length} chars${notes.length > 0 ? `, ${notes.join("; ")}` : ""}).${notebook ? ` ${notebookNote(notebook)}` : ""}${opts.taskAgent ? TASK_REPORTING_NOTE : ""}`
1664
1851
  };
1665
1852
  }
1666
1853
  //#endregion
@@ -1746,7 +1933,7 @@ async function getSDKModule$1() {
1746
1933
  * Must be called asynchronously because the SDK is an ESM module loaded via dynamic import.
1747
1934
  */
1748
1935
  async function createWizardToolsServer(options) {
1749
- const { workingDirectory, detectPackageManager, skillsBaseUrl, askBridge, askMaxQuestions = 10, secretVault = createSecretVault(), orchestrator, triageProvider, emit } = options;
1936
+ const { workingDirectory, detectPackageManager, skillsBaseUrl, askBridge, askMaxQuestions = 10, secretVault = createSecretVault(), orchestrator, triageProvider, emit, programId, handoffNotebook } = options;
1750
1937
  const { tool, createSdkMcpServer } = await getSDKModule$1();
1751
1938
  const askAccounting = createAskAccounting(askMaxQuestions);
1752
1939
  let cachedSkillMenu = {};
@@ -2032,8 +2219,12 @@ async function createWizardToolsServer(options) {
2032
2219
  };
2033
2220
  }
2034
2221
  }),
2035
- tool(PUBLISH_HANDOFF_TOOL_NAME, PUBLISH_HANDOFF_DESCRIPTION, { content: z.string().describe(PUBLISH_HANDOFF_CONTENT_DESCRIPTION) }, (args) => {
2036
- const result = publishHandoff(args.content, emit, { taskAgent: orchestrator?.currentTaskId !== void 0 });
2222
+ tool(PUBLISH_HANDOFF_TOOL_NAME, PUBLISH_HANDOFF_DESCRIPTION, { content: z.string().describe(PUBLISH_HANDOFF_CONTENT_DESCRIPTION) }, async (args) => {
2223
+ const result = await publishHandoff(args.content, emit, {
2224
+ taskAgent: orchestrator?.currentTaskId !== void 0,
2225
+ programId,
2226
+ handoffNotebook
2227
+ });
2037
2228
  logToFile(`publish_handoff: ${result.message}`);
2038
2229
  return {
2039
2230
  content: [{
@@ -2200,34 +2391,6 @@ function classifyToolToStage(toolName) {
2200
2391
  return null;
2201
2392
  }
2202
2393
  //#endregion
2203
- //#region src/shared/auth-session-state.ts
2204
- /**
2205
- * Whether this run's OAuth grant is known to be dead.
2206
- *
2207
- * Process-global on purpose. A run has exactly one login, but the two sides of
2208
- * this fact are far apart: the pre-run refresh learns it in `authenticate.ts`,
2209
- * and the only consumer is the 401 handler inside the agent message loop, which
2210
- * holds no session. Threading it would mean a field on `AgentConfig` set at four
2211
- * `initializeAgent` call sites — and the session it would read from may be a
2212
- * shallow copy (`prepareRunSession`), so the value could be written to one
2213
- * object and read from another.
2214
- *
2215
- * A leaf module with no imports, so either side can depend on it without a cycle.
2216
- */
2217
- let grantRevoked = false;
2218
- /**
2219
- * Record that the token endpoint permanently refused this grant. Not an abort:
2220
- * the access token in hand may still have minutes of life, so the run continues
2221
- * and this only decides what a later 401 gets blamed on.
2222
- */
2223
- function markGrantRevoked() {
2224
- grantRevoked = true;
2225
- }
2226
- /** True once a token refresh failed because the grant itself is gone. */
2227
- function isGrantRevoked() {
2228
- return grantRevoked;
2229
- }
2230
- //#endregion
2231
2394
  //#region src/agent/output-signals.ts
2232
2395
  /**
2233
2396
  * Parses the signal-bearing lines out of agent output and discards the rest.
@@ -3101,7 +3264,9 @@ async function initializeAgent(config, options) {
3101
3264
  askMaxQuestions: config.askMaxQuestions,
3102
3265
  orchestrator: config.orchestrator,
3103
3266
  triageProvider,
3104
- emit: config.emit
3267
+ emit: config.emit,
3268
+ programId: config.programId,
3269
+ handoffNotebook: config.handoffNotebook
3105
3270
  });
3106
3271
  const model = config.modelOverride ?? "claude-sonnet-5";
3107
3272
  const agentRunConfig = {
@@ -4052,6 +4217,6 @@ function handleSDKMessage(message, options, spinner, signals, emit, receivedSucc
4052
4217
  }
4053
4218
  }
4054
4219
  //#endregion
4055
- export { seedAuditChecks as $, AUDIT_SEED_CHECKS_DESCRIPTION as A, WIZARD_TOOL_NAMES as B, publishHandoff as C, AUDIT_ADD_CHECKS_PARAM_DESCRIPTION as D, AUDIT_ADD_CHECKS_DESCRIPTION as E, ENV_FILE_PATH_DESCRIPTION as F, ensureGitignoreCoverage as G, checkEnvKeys as H, WIZARD_ASK_KIND_DESCRIPTION as I, normaliseAskSubject as J, legacyKeyNameRefusal as K, WIZARD_ASK_SENSITIVE_DESCRIPTION as L, AUDIT_STATUSES as M, CHECK_ENV_KEYS_DESCRIPTION as N, AUDIT_RESOLVE_CHECKS_DESCRIPTION as O, CHECK_ENV_KEYS_FILE_PATH_DESCRIPTION as P, resolveEnvSecretRefs as Q, WIZARD_ASK_SUBJECT_DESCRIPTION as R, PUBLISH_HANDOFF_TOOL_NAME as S, readNeedsAttention as T, createAskAccounting as U, addAuditChecks as V, describeAskCancellation as W, resolveAuditChecks as X, resolveAskQuestionKinds as Y, resolveEnvPath as Z, markGrantRevoked as _, wizardCanUseTool as a, shouldDisableAsk as at, PUBLISH_HANDOFF_CONTENT_DESCRIPTION as b, checkAllSettingsConflicts as c, parseEnvKeyNames as ct, restoreClaudeSettings as d, templateEnvWriteRefusal as et, sanitizeAgentSubprocessEnv as f, isGrantRevoked as g, AgentOutputSignals as h, runAgent as i, LONGER_ASK_TIMEOUT_MS as it, AUDIT_SEED_CHECKS_PARAM_DESCRIPTION as j, AUDIT_RESOLVE_CHECKS_PARAM_DESCRIPTION as k, classifySettingsConflicts as l, toPromptSafeRelativePath as lt, runCleanups as m, buildRunTags as n, createWizardAskBridge as nt, createIsolatedAgentConfigDir as o, MAX_ENV_KEY_SET as ot, registerCleanup as p, mergeEnvValues as q, initializeAgent as r, isFullyCancelled as rt, backupAndFixClaudeSettings as s, isEnvFileName as st, buildAgentEnv as t, vaultSensitiveAnswers as tt, recoverOrphanedSettingsBackups as u, createTriageLLMProvider as ut, assembleCommandments as v, NEEDS_ATTENTION_HEADING as w, PUBLISH_HANDOFF_DESCRIPTION as x, createSecretVault as y, WIZARD_ASK_TOOL_DESCRIPTION as z };
4220
+ export { vaultSensitiveAnswers as $, AUDIT_STATUSES as A, checkEnvKeys as B, readNeedsAttention as C, AUDIT_RESOLVE_CHECKS_PARAM_DESCRIPTION as D, AUDIT_RESOLVE_CHECKS_DESCRIPTION as E, WIZARD_ASK_SENSITIVE_DESCRIPTION as F, mergeEnvValues as G, describeAskCancellation as H, WIZARD_ASK_SUBJECT_DESCRIPTION as I, resolveAuditChecks as J, normaliseAskSubject as K, WIZARD_ASK_TOOL_DESCRIPTION as L, CHECK_ENV_KEYS_FILE_PATH_DESCRIPTION as M, ENV_FILE_PATH_DESCRIPTION as N, AUDIT_SEED_CHECKS_DESCRIPTION as O, WIZARD_ASK_KIND_DESCRIPTION as P, templateEnvWriteRefusal as Q, WIZARD_TOOL_NAMES as R, NEEDS_ATTENTION_HEADING as S, AUDIT_ADD_CHECKS_PARAM_DESCRIPTION as T, ensureGitignoreCoverage as U, createAskAccounting as V, legacyKeyNameRefusal as W, resolveEnvSecretRefs as X, resolveEnvPath as Y, seedAuditChecks as Z, createSecretVault as _, wizardCanUseTool as a, isEnvFileName as at, PUBLISH_HANDOFF_TOOL_NAME as b, checkAllSettingsConflicts as c, createTriageLLMProvider as ct, restoreClaudeSettings as d, createWizardAskBridge as et, sanitizeAgentSubprocessEnv as f, assembleCommandments as g, AgentOutputSignals as h, runAgent as i, MAX_ENV_KEY_SET as it, CHECK_ENV_KEYS_DESCRIPTION as j, AUDIT_SEED_CHECKS_PARAM_DESCRIPTION as k, classifySettingsConflicts as l, runCleanups as m, buildRunTags as n, LONGER_ASK_TIMEOUT_MS as nt, createIsolatedAgentConfigDir as o, parseEnvKeyNames as ot, registerCleanup as p, resolveAskQuestionKinds as q, initializeAgent as r, shouldDisableAsk as rt, backupAndFixClaudeSettings as s, toPromptSafeRelativePath as st, buildAgentEnv as t, isFullyCancelled as tt, recoverOrphanedSettingsBackups as u, PUBLISH_HANDOFF_CONTENT_DESCRIPTION as v, AUDIT_ADD_CHECKS_DESCRIPTION as w, publishHandoff as x, PUBLISH_HANDOFF_DESCRIPTION as y, addAuditChecks as z };
4056
4221
 
4057
- //# sourceMappingURL=agent-interface-BFzBnz10.js.map
4222
+ //# sourceMappingURL=agent-interface-3YfIWZmY.js.map