@posthog/wizard 2.67.0 → 2.69.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.
- package/dist/{add-mcp-server-to-clients-DHTRbyJX.js → add-mcp-server-to-clients-Cl2HBuxp.js} +4 -4
- package/dist/{add-mcp-server-to-clients-DHTRbyJX.js.map → add-mcp-server-to-clients-Cl2HBuxp.js.map} +1 -1
- package/dist/{agent-interface-tM_b0l__.js → agent-interface-CI89BrWE.js} +301 -51
- package/dist/agent-interface-CI89BrWE.js.map +1 -0
- package/dist/{agent-prompt-loader-BSMh5bfD.js → agent-prompt-loader-Dc1g5Oub.js} +5 -5
- package/dist/{agent-prompt-loader-BSMh5bfD.js.map → agent-prompt-loader-Dc1g5Oub.js.map} +1 -1
- package/dist/{agent-runner-DD65OMkB.js → agent-runner-D5dhuE4z.js} +38 -18
- package/dist/agent-runner-D5dhuE4z.js.map +1 -0
- package/dist/{analytics-CtIYzkK4.js → analytics-D90QbLf5.js} +2 -2
- package/dist/{analytics-CtIYzkK4.js.map → analytics-D90QbLf5.js.map} +1 -1
- package/dist/analytics-Dmf_Jm3K.js +2 -0
- package/dist/{api-BJft9v6K.js → api-BHhrT6wb.js} +3 -3
- package/dist/{api-BJft9v6K.js.map → api-BHhrT6wb.js.map} +1 -1
- package/dist/bin.js +51 -51
- package/dist/{bounded-fs-BWqoFQvQ.js → bounded-fs-BhlVkP1r.js} +3 -3
- package/dist/{bounded-fs-BWqoFQvQ.js.map → bounded-fs-BhlVkP1r.js.map} +1 -1
- package/dist/{ci-install-BXGnVI7T.js → ci-install-94wC3a4K.js} +5 -5
- package/dist/{ci-install-BXGnVI7T.js.map → ci-install-94wC3a4K.js.map} +1 -1
- package/dist/{debug-BsHD83Vy.js → debug-CifTS9lQ.js} +3 -3
- package/dist/{debug-BsHD83Vy.js.map → debug-CifTS9lQ.js.map} +1 -1
- package/dist/{debug-mO3yg4Z7.js → debug-DtixqVEY.js} +1 -1
- package/dist/{env-api-key-DS0ghlcO.js → env-api-key-CwhtZrik.js} +2 -2
- package/dist/{env-api-key-DS0ghlcO.js.map → env-api-key-CwhtZrik.js.map} +1 -1
- package/dist/environment-DhacWZf7.js +44 -0
- package/dist/environment-DhacWZf7.js.map +1 -0
- package/dist/{errors-BHervYGs.js → errors-BSdz2lsl.js} +3 -2
- package/dist/errors-BSdz2lsl.js.map +1 -0
- package/dist/{file-watcher-D1bdo9mq.js → file-watcher-L28OpUV2.js} +2 -2
- package/dist/{file-watcher-D1bdo9mq.js.map → file-watcher-L28OpUV2.js.map} +1 -1
- package/dist/{headless-ui-6QuByWZ_.js → headless-ui-DNcOVJxU.js} +2 -2
- package/dist/{headless-ui-6QuByWZ_.js.map → headless-ui-DNcOVJxU.js.map} +1 -1
- package/dist/{interactive-DUpW84WU.js → interactive-DlNrV77o.js} +2 -2
- package/dist/{interactive-DUpW84WU.js.map → interactive-DlNrV77o.js.map} +1 -1
- package/dist/{mcp-CHo9h-WV.js → mcp-CJEem9qs.js} +2 -2
- package/dist/{mcp-CHo9h-WV.js.map → mcp-CJEem9qs.js.map} +1 -1
- package/dist/{mcp-prompt-streaming-CHRPxxd0.js → mcp-prompt-streaming-DER7MG3q.js} +13 -12
- package/dist/mcp-prompt-streaming-DER7MG3q.js.map +1 -0
- package/dist/{non-interactive-Cr-chffe.js → non-interactive-CbvniKHm.js} +3 -3
- package/dist/{non-interactive-Cr-chffe.js.map → non-interactive-CbvniKHm.js.map} +1 -1
- package/dist/{orchestrator-tools-Tx18_TMb.js → orchestrator-tools-Czf3Wo_y.js} +3 -3
- package/dist/{orchestrator-tools-Tx18_TMb.js.map → orchestrator-tools-Czf3Wo_y.js.map} +1 -1
- package/dist/{package-manager-CLfc31yf.js → package-manager-CNNlFA2q.js} +2 -2
- package/dist/{package-manager-CLfc31yf.js.map → package-manager-CNNlFA2q.js.map} +1 -1
- package/dist/{pi-RlnYUHdb.js → pi-kpN-bO9z.js} +17 -14
- package/dist/pi-kpN-bO9z.js.map +1 -0
- package/dist/{playground-DQ633rje.js → playground-ZYaQmfBa.js} +7 -7
- package/dist/{playground-DQ633rje.js.map → playground-ZYaQmfBa.js.map} +1 -1
- package/dist/{posthog-DSn9bIZc.js → posthog-D1zHPgYJ.js} +2 -2
- package/dist/{posthog-DSn9bIZc.js.map → posthog-D1zHPgYJ.js.map} +1 -1
- package/dist/{posthog-integration-DFfBRGOC.js → posthog-integration-DdeIUkYw.js} +17 -16
- package/dist/posthog-integration-DdeIUkYw.js.map +1 -0
- package/dist/{provisioning-Cvy_vQHV.js → provisioning-e3roaLgp.js} +3 -3
- package/dist/{provisioning-Cvy_vQHV.js.map → provisioning-e3roaLgp.js.map} +1 -1
- package/dist/{queue-tools-BC9HxOV6.js → queue-tools-zrqCiy6q.js} +3 -3
- package/dist/{queue-tools-BC9HxOV6.js.map → queue-tools-zrqCiy6q.js.map} +1 -1
- package/dist/{registry-DCAElOyj.js → registry-C1t8v5tE.js} +5 -5
- package/dist/{registry-DCAElOyj.js.map → registry-C1t8v5tE.js.map} +1 -1
- package/dist/{security-CuSX3XVo.js → security-CIfhIscL.js} +5 -5
- package/dist/{security-CuSX3XVo.js.map → security-CIfhIscL.js.map} +1 -1
- package/dist/{setup-utils-D1tv0v_R.js → setup-utils-B_06xag2.js} +9 -9
- package/dist/{setup-utils-D1tv0v_R.js.map → setup-utils-B_06xag2.js.map} +1 -1
- package/dist/{start-tui-B5YfmqNr.js → start-tui-BafJXVNT.js} +20 -20
- package/dist/{start-tui-B5YfmqNr.js.map → start-tui-BafJXVNT.js.map} +1 -1
- package/dist/{steps-CLaSMwfR.js → steps-DR-Yo_IT.js} +7 -7
- package/dist/{steps-CLaSMwfR.js.map → steps-DR-Yo_IT.js.map} +1 -1
- package/dist/{store-DzEgsAPN.js → store-DSUCWMRO.js} +5 -5
- package/dist/{store-DzEgsAPN.js.map → store-DSUCWMRO.js.map} +1 -1
- package/dist/{subagent-BUV6aD7p.js → subagent-DjZM3G7y.js} +2 -2
- package/dist/{subagent-BUV6aD7p.js.map → subagent-DjZM3G7y.js.map} +1 -1
- package/dist/{task-GnWId75q.js → task-Czzz3tzt.js} +18 -15
- package/dist/task-Czzz3tzt.js.map +1 -0
- package/dist/{task-stream-DSzvwJrD.js → task-stream-uxG6wJfj.js} +6 -6
- package/dist/{task-stream-DSzvwJrD.js.map → task-stream-uxG6wJfj.js.map} +1 -1
- package/dist/{tasks-BO0W8ocx.js → tasks-CVmG8qFw.js} +2 -2
- package/dist/{tasks-BO0W8ocx.js.map → tasks-CVmG8qFw.js.map} +1 -1
- package/dist/{telemetry-Vi9dWddJ.js → telemetry-B1VEXHpL.js} +3 -3
- package/dist/{telemetry-Vi9dWddJ.js.map → telemetry-B1VEXHpL.js.map} +1 -1
- package/dist/{terminal-B5wZK7aS.js → terminal-Czuo0x8i.js} +12 -12
- package/dist/{terminal-B5wZK7aS.js.map → terminal-Czuo0x8i.js.map} +1 -1
- package/dist/{tools-C9cNluqc.js → tools-DOZg9n3A.js} +10 -7
- package/dist/tools-DOZg9n3A.js.map +1 -0
- package/dist/{wizard-abort-BsNbguJt.js → wizard-abort-BZOeapsf.js} +1 -1
- package/dist/{wizard-abort-CGv3lVxw.js → wizard-abort-CFMdj6sZ.js} +5 -5
- package/dist/{wizard-abort-CGv3lVxw.js.map → wizard-abort-CFMdj6sZ.js.map} +1 -1
- package/dist/{wizard-session-Cex1BiXs.js → wizard-session-C_7r3-rO.js} +2 -1
- package/dist/wizard-session-C_7r3-rO.js.map +1 -0
- package/dist/{wizard-session-DHbUcjI7.js → wizard-session-D1KQqUml.js} +1 -1
- package/dist/yara-hooks-BhNAWw7W.js +2 -0
- package/dist/{yara-hooks-DZIVzhA6.js → yara-hooks-CmQT-oBy.js} +4 -4
- package/dist/{yara-hooks-DZIVzhA6.js.map → yara-hooks-CmQT-oBy.js.map} +1 -1
- package/package.json +1 -1
- package/dist/agent-interface-tM_b0l__.js.map +0 -1
- package/dist/agent-runner-DD65OMkB.js.map +0 -1
- package/dist/analytics-B4Igh5nv.js +0 -2
- package/dist/environment-C7CKGIOE.js +0 -22
- package/dist/environment-C7CKGIOE.js.map +0 -1
- package/dist/errors-BHervYGs.js.map +0 -1
- package/dist/mcp-prompt-streaming-CHRPxxd0.js.map +0 -1
- package/dist/pi-RlnYUHdb.js.map +0 -1
- package/dist/posthog-integration-DFfBRGOC.js.map +0 -1
- package/dist/task-GnWId75q.js.map +0 -1
- package/dist/tools-C9cNluqc.js.map +0 -1
- package/dist/wizard-session-Cex1BiXs.js.map +0 -1
- package/dist/yara-hooks-C3Vm2Gow.js +0 -2
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-B_-DWIq7.js";
|
|
2
|
-
import "./debug-BsHD83Vy.js";
|
|
3
|
-
import "./bounded-fs-BWqoFQvQ.js";
|
|
4
|
-
import "./setup-utils-D1tv0v_R.js";
|
|
5
|
-
import readEnvModule from "read-env";
|
|
6
|
-
//#region src/utils/environment.ts
|
|
7
|
-
var environment_exports = /* @__PURE__ */ __exportAll({
|
|
8
|
-
isNonInteractiveEnvironment: () => isNonInteractiveEnvironment,
|
|
9
|
-
readEnvironment: () => readEnvironment
|
|
10
|
-
});
|
|
11
|
-
const readEnv = typeof readEnvModule === "function" ? readEnvModule : readEnvModule.default;
|
|
12
|
-
function isNonInteractiveEnvironment() {
|
|
13
|
-
if (!process.stdout.isTTY || !process.stderr.isTTY) return true;
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
function readEnvironment() {
|
|
17
|
-
return readEnv("POSTHOG_WIZARD");
|
|
18
|
-
}
|
|
19
|
-
//#endregion
|
|
20
|
-
export { isNonInteractiveEnvironment as n, environment_exports as t };
|
|
21
|
-
|
|
22
|
-
//# sourceMappingURL=environment-C7CKGIOE.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"environment-C7CKGIOE.js","names":[],"sources":["../src/utils/environment.ts"],"sourcesContent":["import readEnvModule from 'read-env';\n\nconst readEnv =\n typeof readEnvModule === 'function'\n ? readEnvModule\n : (readEnvModule as any).default;\nimport { tryGetPackageJson } from './setup-utils';\nimport type { WizardRunOptions } from './types';\nimport { boundedGlob } from './bounded-fs';\nimport { IS_DEV } from '@lib/constants';\n\nexport function isNonInteractiveEnvironment(): boolean {\n if (IS_DEV) {\n return false;\n }\n\n if (!process.stdout.isTTY || !process.stderr.isTTY) {\n return true;\n }\n\n return false;\n}\n\nexport function readEnvironment(): Record<string, unknown> {\n const result = readEnv('POSTHOG_WIZARD');\n\n return result;\n}\n\nexport async function detectEnvVarPrefix(\n options: WizardRunOptions,\n): Promise<string> {\n const packageJson = await tryGetPackageJson(options);\n if (!packageJson) return 'VITE_PUBLIC_';\n\n const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };\n const has = (name: string) => name in deps;\n // O(1) matches per probe: one config file existing anywhere answers it.\n const hasAnyFile = async (patterns: string[]) => {\n const matches = await boundedGlob(patterns, {\n cwd: options.installDir,\n limit: 1,\n });\n return matches.length > 0;\n };\n\n // --- Next.js\n if (has('next') || (await hasAnyFile(['**/next.config.{js,ts,mjs,cjs}']))) {\n return 'NEXT_PUBLIC_';\n }\n\n // --- Create React App\n if (\n has('react-scripts') ||\n has('create-react-app') ||\n (await hasAnyFile(['**/config-overrides.js']))\n ) {\n return 'REACT_APP_';\n }\n\n // --- Vite (vanilla, TanStack, Solid, etc.)\n // Note: Vite does not need PUBLIC_ but we use it to follow the docs, to improve the chances of an LLM getting it right.\n if (has('vite') || (await hasAnyFile(['**/vite.config.{js,ts,mjs,cjs}']))) {\n return 'VITE_PUBLIC_';\n }\n\n // --- SvelteKit\n if (\n has('@sveltejs/kit') ||\n (await hasAnyFile(['**/svelte.config.{js,ts}']))\n ) {\n return 'PUBLIC_';\n }\n\n // --- TanStack Start (uses Vite)\n if (\n has('@tanstack/start') ||\n (await hasAnyFile(['**/tanstack.config.{js,ts}']))\n ) {\n return 'VITE_PUBLIC_';\n }\n\n // --- SolidStart (uses Vite)\n if (has('solid-start') || (await hasAnyFile(['**/solid.config.{js,ts}']))) {\n return 'VITE_PUBLIC_';\n }\n\n // --- Astro\n if (has('astro') || (await hasAnyFile(['**/astro.config.{js,ts,mjs}']))) {\n return 'PUBLIC_';\n }\n\n // We default to Vite if we can't detect a specific framework, since it's the most commonly used.\n return 'VITE_PUBLIC_';\n}\n"],"mappings":";;;;;;;;;;AAEA,MAAM,UACJ,OAAO,kBAAkB,aACrB,gBACC,cAAsB;AAM7B,SAAgB,8BAAuC;AAKrD,KAAI,CAAC,QAAQ,OAAO,SAAS,CAAC,QAAQ,OAAO,MAC3C,QAAO;AAGT,QAAO;;AAGT,SAAgB,kBAA2C;AAGzD,QAFe,QAAQ,iBAAiB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors-BHervYGs.js","names":[],"sources":["../src/lib/errors/codes.ts","../src/lib/errors/emit.ts","../src/lib/errors/catalog.ts","../src/lib/errors/auth.ts","../src/lib/agent/signals.ts","../src/lib/errors/agent-map.ts","../src/lib/errors/detect-map.ts","../src/lib/errors/skill-map.ts","../src/lib/errors/sanitize.ts"],"sourcesContent":["export const ErrorCodes = {\n CliNodeVersion: 'PHW_CLI_NODE_VERSION',\n CliBadArgs: 'PHW_CLI_BAD_ARGS',\n CliFlagUnavailable: 'PHW_CLI_FLAG_UNAVAILABLE',\n CliInteractiveRequired: 'PHW_CLI_INTERACTIVE_REQUIRED',\n ArgsMissingApiKey: 'PHW_ARGS_MISSING_API_KEY',\n ArgsMissingInstallDir: 'PHW_ARGS_MISSING_INSTALL_DIR',\n ArgsMissingEmail: 'PHW_ARGS_MISSING_EMAIL',\n ArgsSignupProvisionFailed: 'PHW_ARGS_SIGNUP_PROVISION_FAILED',\n AuthKeyType: 'PHW_AUTH_KEY_TYPE',\n AuthMissingScope: 'PHW_AUTH_MISSING_SCOPE',\n AuthRegionMismatch: 'PHW_AUTH_REGION_MISMATCH',\n AuthInvalidOrExpired: 'PHW_AUTH_INVALID_OR_EXPIRED',\n AuthSettingsConflict: 'PHW_AUTH_SETTINGS_CONFLICT',\n AuthStoredLoginConflict: 'PHW_AUTH_STORED_LOGIN_CONFLICT',\n AuthProjectFetchFailed: 'PHW_AUTH_PROJECT_FETCH_FAILED',\n EnvLocalServicesDown: 'PHW_ENV_LOCAL_SERVICES_DOWN',\n EnvServiceOutage: 'PHW_ENV_SERVICE_OUTAGE',\n DetectBadDirectory: 'PHW_DETECT_BAD_DIRECTORY',\n DetectNoFramework: 'PHW_DETECT_NO_FRAMEWORK',\n DetectUnsupportedVersion: 'PHW_DETECT_UNSUPPORTED_VERSION',\n DetectUnsupportedPlatform: 'PHW_DETECT_UNSUPPORTED_PLATFORM',\n DetectNoPosthogSdk: 'PHW_DETECT_NO_POSTHOG_SDK',\n DetectNoProjectFiles: 'PHW_DETECT_NO_PROJECT_FILES',\n DetectNoSources: 'PHW_DETECT_NO_SOURCES',\n DetectNoPackageJson: 'PHW_DETECT_NO_PACKAGE_JSON',\n DetectNoSdks: 'PHW_DETECT_NO_SDKS',\n DetectMissingStripe: 'PHW_DETECT_MISSING_STRIPE',\n DetectUnclassified: 'PHW_DETECT_UNCLASSIFIED',\n SkillMenuFetchFailed: 'PHW_SKILL_MENU_FETCH_FAILED',\n SkillNotFound: 'PHW_SKILL_NOT_FOUND',\n SkillDownloadFailed: 'PHW_SKILL_DOWNLOAD_FAILED',\n AgentAbort: 'PHW_AGENT_ABORT',\n AgentMcpMissing: 'PHW_AGENT_MCP_MISSING',\n AgentResourceMissing: 'PHW_AGENT_RESOURCE_MISSING',\n AgentRateLimit: 'PHW_AGENT_RATE_LIMIT',\n AgentApiError: 'PHW_AGENT_API_ERROR',\n AgentYaraViolation: 'PHW_AGENT_YARA_VIOLATION',\n AgentNoProgress: 'PHW_AGENT_NO_PROGRESS',\n AgentIncompleteTasks: 'PHW_AGENT_INCOMPLETE_TASKS',\n AgentOrchestratorSkillVariantMissing:\n 'PHW_AGENT_ORCHESTRATOR_SKILL_VARIANT_MISSING',\n AgentOrchestratorTasksFailed: 'PHW_AGENT_ORCHESTRATOR_TASKS_FAILED',\n AgentOrchestratorSinkInvariant: 'PHW_AGENT_ORCHESTRATOR_SINK_INVARIANT',\n SettingsUnfixableConflict: 'PHW_SETTINGS_UNFIXABLE_CONFLICT',\n InternalUnhandled: 'PHW_INTERNAL_UNHANDLED',\n} as const;\n\nexport type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];\n\nexport const ERROR_CODE_PATTERN = /^PHW_[A-Z][A-Z0-9_]*$/;\n\nexport function isErrorCode(value: string): value is ErrorCode {\n return (Object.values(ErrorCodes) as string[]).includes(value);\n}\n","import type { ErrorCode } from './codes';\n\nexport const PHW_ERROR_PREFIX = 'phw-error:';\n\nexport interface WizardErrorLine {\n code: ErrorCode;\n message: string;\n detail?: Record<string, unknown>;\n}\n\nexport function formatWizardErrorLine(line: WizardErrorLine): string {\n return `${PHW_ERROR_PREFIX} ${JSON.stringify(line)}`;\n}\n\nexport function emitWizardError(line: WizardErrorLine): void {\n process.stderr.write(`${formatWizardErrorLine(line)}\\n`);\n}\n","import { ErrorCodes, type ErrorCode } from './codes';\nimport type { ErrorCatalogEntry } from './types';\n\nexport const ERROR_CATALOG: Record<ErrorCode, ErrorCatalogEntry> = {\n [ErrorCodes.CliNodeVersion]: {\n group: 'cli',\n retry: 'no',\n description: 'Node.js runtime is older than the required range.',\n },\n [ErrorCodes.CliBadArgs]: {\n group: 'cli',\n retry: 'no',\n description: 'Unrecognized command or option.',\n },\n [ErrorCodes.CliFlagUnavailable]: {\n group: 'cli',\n retry: 'no',\n description: 'A dev-only flag or env var was passed to a published build.',\n },\n [ErrorCodes.CliInteractiveRequired]: {\n group: 'cli',\n retry: 'no',\n description:\n 'The command requires an interactive terminal and has no non-interactive fallback.',\n },\n [ErrorCodes.ArgsMissingApiKey]: {\n group: 'args',\n retry: 'no',\n description: 'Non-interactive run without --api-key.',\n },\n [ErrorCodes.ArgsMissingInstallDir]: {\n group: 'args',\n retry: 'no',\n description: 'Non-interactive run without --install-dir.',\n },\n [ErrorCodes.ArgsMissingEmail]: {\n group: 'args',\n retry: 'no',\n description: 'Signup run without --email.',\n },\n [ErrorCodes.ArgsSignupProvisionFailed]: {\n group: 'args',\n retry: 'yes',\n description: 'Account provisioning for --signup failed.',\n },\n [ErrorCodes.AuthKeyType]: {\n group: 'auth',\n retry: 'no',\n description: 'The API key has the wrong type or prefix for this mode.',\n },\n [ErrorCodes.AuthInvalidOrExpired]: {\n group: 'auth',\n retry: 'no',\n description: 'The credential was rejected by the LLM gateway or API.',\n },\n [ErrorCodes.AuthMissingScope]: {\n group: 'auth',\n retry: 'no',\n description: 'The personal API key lacks a scope the run requires.',\n },\n [ErrorCodes.AuthRegionMismatch]: {\n group: 'auth',\n retry: 'no',\n description: 'The resolved region does not match the credential.',\n },\n [ErrorCodes.AuthSettingsConflict]: {\n group: 'auth',\n retry: 'no',\n description: 'A Claude settings file overrides the gateway credential.',\n },\n [ErrorCodes.AuthStoredLoginConflict]: {\n group: 'auth',\n retry: 'no',\n description:\n 'The agent SDK used a stored Claude login instead of the gateway token.',\n },\n [ErrorCodes.AuthProjectFetchFailed]: {\n group: 'auth',\n retry: 'yes',\n description: 'Fetching user or project data from the PostHog API failed.',\n },\n [ErrorCodes.EnvLocalServicesDown]: {\n group: 'env',\n retry: 'yes',\n description: 'A local dev target service is not running.',\n },\n [ErrorCodes.EnvServiceOutage]: {\n group: 'env',\n retry: 'yes',\n description: 'Blocking external services are down.',\n },\n [ErrorCodes.DetectBadDirectory]: {\n group: 'detect',\n retry: 'no',\n description:\n 'The install directory is missing, not a directory, or unreadable.',\n },\n [ErrorCodes.DetectNoFramework]: {\n group: 'detect',\n retry: 'no',\n description: 'Framework auto-detection found no supported framework.',\n },\n [ErrorCodes.DetectUnsupportedVersion]: {\n group: 'detect',\n retry: 'no',\n description:\n 'The detected framework version is below the supported minimum.',\n },\n [ErrorCodes.DetectUnsupportedPlatform]: {\n group: 'detect',\n retry: 'no',\n description: 'The project platform has no matching skill variant.',\n },\n [ErrorCodes.DetectNoPosthogSdk]: {\n group: 'detect',\n retry: 'no',\n description:\n 'The program requires an installed PostHog SDK and none was found.',\n },\n [ErrorCodes.DetectNoProjectFiles]: {\n group: 'detect',\n retry: 'no',\n description: 'The project has no files for the program to work on.',\n },\n [ErrorCodes.DetectNoSources]: {\n group: 'detect',\n retry: 'no',\n description: 'No data warehouse sources were found.',\n },\n [ErrorCodes.DetectNoPackageJson]: {\n group: 'detect',\n retry: 'no',\n description: 'The project has no package.json for the program to scan.',\n },\n [ErrorCodes.DetectNoSdks]: {\n group: 'detect',\n retry: 'no',\n description: 'None of the SDKs the program needs are installed.',\n },\n [ErrorCodes.DetectMissingStripe]: {\n group: 'detect',\n retry: 'no',\n description: 'Revenue analytics requires a Stripe SDK and none was found.',\n },\n [ErrorCodes.DetectUnclassified]: {\n group: 'detect',\n // A detect step reported a precondition failure we have no code for yet.\n // Every known cause is a property of the user's project, so retrying can\n // only burn budget — fail closed rather than inheriting `internal`'s 'yes'.\n retry: 'no',\n description: 'A detect step failed with a kind absent from the catalog.',\n },\n [ErrorCodes.SkillMenuFetchFailed]: {\n group: 'skill',\n retry: 'yes',\n description: 'The context-mill skill menu could not be fetched.',\n },\n [ErrorCodes.SkillNotFound]: {\n group: 'skill',\n retry: 'no',\n description: 'The skill id is absent from the context-mill menu.',\n },\n [ErrorCodes.SkillDownloadFailed]: {\n group: 'skill',\n retry: 'yes',\n description: 'The skill download or extraction failed.',\n },\n [ErrorCodes.AgentAbort]: {\n group: 'agent',\n retry: 'case-by-case',\n description: 'The agent emitted an [ABORT] signal with a reason.',\n },\n [ErrorCodes.AgentMcpMissing]: {\n group: 'agent',\n retry: 'yes',\n description: 'The agent could not reach the PostHog MCP server.',\n },\n [ErrorCodes.AgentResourceMissing]: {\n group: 'agent',\n retry: 'yes',\n description: 'The agent could not access a setup resource.',\n },\n [ErrorCodes.AgentRateLimit]: {\n group: 'agent',\n retry: 'yes',\n description: 'The LLM gateway rate-limited the run.',\n },\n [ErrorCodes.AgentApiError]: {\n group: 'agent',\n retry: 'yes',\n description: 'The agent hit an API error other than a rate limit.',\n },\n [ErrorCodes.AgentYaraViolation]: {\n group: 'agent',\n retry: 'no',\n description: 'The security scanner terminated the run.',\n },\n [ErrorCodes.AgentNoProgress]: {\n group: 'agent',\n retry: 'case-by-case',\n description: 'The agent ended without a single tool call.',\n },\n [ErrorCodes.AgentIncompleteTasks]: {\n group: 'agent',\n retry: 'case-by-case',\n description: 'The agent stopped with planned tasks still open.',\n },\n [ErrorCodes.AgentOrchestratorSkillVariantMissing]: {\n group: 'agent',\n retry: 'yes',\n description: 'The orchestrator could not download a needed skill variant.',\n },\n [ErrorCodes.AgentOrchestratorTasksFailed]: {\n group: 'agent',\n retry: 'case-by-case',\n description: 'The orchestrator queue drained with failed or blocked tasks.',\n },\n [ErrorCodes.AgentOrchestratorSinkInvariant]: {\n group: 'agent',\n retry: 'no',\n description: 'The orchestrator plan failed the sink coverage invariant.',\n },\n [ErrorCodes.SettingsUnfixableConflict]: {\n group: 'settings',\n retry: 'no',\n description:\n 'A Claude settings conflict cannot be neutralized automatically.',\n },\n [ErrorCodes.InternalUnhandled]: {\n group: 'internal',\n retry: 'yes',\n description: 'An unexpected error escaped the pipeline.',\n },\n};\n","import { ErrorCodes, type ErrorCode } from './codes';\n\nexport interface AuthFailureInput {\n hasSettingsConflict?: boolean;\n usingManagedLogin?: boolean;\n apiKey?: string;\n missingScopes?: readonly string[];\n gatewayRegion?: 'us' | 'eu' | 'local';\n sessionRegion?: 'us' | 'eu';\n}\n\nexport function classifyAuthFailure(input: AuthFailureInput): ErrorCode {\n if (input.usingManagedLogin) return ErrorCodes.AuthStoredLoginConflict;\n if (input.hasSettingsConflict) return ErrorCodes.AuthSettingsConflict;\n if (\n input.apiKey &&\n !input.apiKey.startsWith('phx_') &&\n !input.apiKey.startsWith('pha_')\n ) {\n return ErrorCodes.AuthKeyType;\n }\n if (input.missingScopes && input.missingScopes.length > 0) {\n return ErrorCodes.AuthMissingScope;\n }\n if (\n input.gatewayRegion &&\n input.sessionRegion &&\n input.gatewayRegion !== 'local' &&\n input.gatewayRegion !== input.sessionRegion\n ) {\n return ErrorCodes.AuthRegionMismatch;\n }\n return ErrorCodes.AuthInvalidOrExpired;\n}\n","/**\n * Agent signal vocabulary — the marker strings the agent emits and the error\n * taxonomy the runner returns. Kept as a dependency-free leaf module so both\n * `agent-interface.ts` and `output-signals.ts` can import it without a cycle.\n */\n\nexport const AgentSignals = {\n /** Signal emitted when the agent reports progress to the user */\n STATUS: '[STATUS]',\n /** Signal emitted when the agent cannot access the PostHog MCP server */\n ERROR_MCP_MISSING: '[ERROR-MCP-MISSING]',\n /** Signal emitted when the agent cannot access the setup resource */\n ERROR_RESOURCE_MISSING: '[ERROR-RESOURCE-MISSING]',\n /**\n * Signal emitted when `install_skill` failed and the agent is continuing\n * the integration WITHOUT the skill (best-effort from its own knowledge).\n * Format: \"[SKILL-INSTALL-FAILED] <skill id — reason>\". Non-fatal by\n * design: a freestyled integration beats an outright failure, but the run\n * must be measurable — the runner captures it as an analytics event.\n */\n SKILL_INSTALL_FAILED: '[SKILL-INSTALL-FAILED]',\n /**\n * Signal emitted when the agent cannot complete the program and is\n * aborting intentionally (distinct from errors). Format: \"[ABORT] <reason>\".\n * Programs can declare an onAbort handler to render a custom screen.\n */\n ABORT: '[ABORT]',\n /** Signal emitted when the agent provides a remark about its run */\n WIZARD_REMARK: '[WIZARD-REMARK]',\n /** Signal prefix for benchmark logging */\n BENCHMARK: '[BENCHMARK]',\n /**\n * Signal emitted when the agent has created a PostHog dashboard for the\n * user. Format: `[DASHBOARD_URL] <full https url>`. The URL is captured\n * onto `session.dashboardUrl` and surfaced by programs in their outro.\n */\n DASHBOARD_URL: '[DASHBOARD_URL]',\n /**\n * Signal emitted when the agent has uploaded a report to a PostHog\n * notebook. Format: `[NOTEBOOK_URL] <full https url>`. The URL is captured\n * onto `session.notebookUrl` and surfaced by programs in their outro.\n */\n NOTEBOOK_URL: '[NOTEBOOK_URL]',\n} as const;\n\nexport type AgentSignal = (typeof AgentSignals)[keyof typeof AgentSignals];\n\n/**\n * End-of-run reflection ask, shared by both harnesses so remarks are\n * comparable. The format clause comes FIRST and nothing trails the marker —\n * literal models (gpt-5-mini) echo whatever text follows it. The parser also\n * drops remarks that quote this instruction (see AgentOutputSignals.remark).\n */\nexport const REMARK_INSTRUCTION = `Reply with a single line that starts with ${AgentSignals.WIZARD_REMARK} and no other lines. In that line, state briefly what information or guidance would have been useful to have in the integration prompt or documentation for this run — specifically anything that would have prevented tool failures, erroneous edits, or other wasted turns.`;\n\n/**\n * Error types that can be returned from agent execution.\n * These correspond to the error signals that the agent emits.\n */\nexport enum AgentErrorType {\n /** Agent could not access the PostHog MCP server */\n MCP_MISSING = 'WIZARD_MCP_MISSING',\n /** Agent could not access the setup resource */\n RESOURCE_MISSING = 'WIZARD_RESOURCE_MISSING',\n /** API rate limit exceeded */\n RATE_LIMIT = 'WIZARD_RATE_LIMIT',\n /** Generic API error */\n API_ERROR = 'WIZARD_API_ERROR',\n /** YARA scanner detected a security violation */\n YARA_VIOLATION = 'WIZARD_YARA_VIOLATION',\n /** Agent intentionally aborted the program (emitted [ABORT] <reason>) */\n ABORT = 'WIZARD_ABORT',\n /** Agent ended without making a single tool call — a no-op run that did no work */\n NO_PROGRESS = 'WIZARD_NO_PROGRESS',\n /** Agent acted but stopped short — planned tasks left open and/or no skill installed */\n INCOMPLETE_TASKS = 'WIZARD_INCOMPLETE_TASKS',\n}\n","import { AgentErrorType } from '../agent/signals';\nimport { ErrorCodes, type ErrorCode } from './codes';\n\nexport const AGENT_ERROR_CODE: Record<AgentErrorType, ErrorCode> = {\n [AgentErrorType.MCP_MISSING]: ErrorCodes.AgentMcpMissing,\n [AgentErrorType.RESOURCE_MISSING]: ErrorCodes.AgentResourceMissing,\n [AgentErrorType.RATE_LIMIT]: ErrorCodes.AgentRateLimit,\n [AgentErrorType.API_ERROR]: ErrorCodes.AgentApiError,\n [AgentErrorType.YARA_VIOLATION]: ErrorCodes.AgentYaraViolation,\n [AgentErrorType.ABORT]: ErrorCodes.AgentAbort,\n [AgentErrorType.NO_PROGRESS]: ErrorCodes.AgentNoProgress,\n [AgentErrorType.INCOMPLETE_TASKS]: ErrorCodes.AgentIncompleteTasks,\n};\n","import { ErrorCodes, type ErrorCode } from './codes';\nimport type { RevenueDetectError } from '@lib/programs/revenue-analytics/detect';\nimport type { SelfDrivingDetectError } from '@lib/programs/self-driving/detect';\nimport type { SourceMapsDetectError } from '@lib/programs/error-tracking-upload-source-maps/detect';\nimport type { WarehouseDetectError } from '@lib/programs/warehouse-source/detect';\nimport type { WebAnalyticsDetectError } from '@lib/programs/web-analytics-doctor/detect';\n\n/**\n * Every `kind` a program detect step can write into\n * `frameworkContext.detectError`, assembled from the programs' own unions.\n * Type-only imports, so this adds no runtime edge from the catalog to the\n * programs (same shape as `skill-map.ts` keying on `InstallSkillResult`).\n *\n * The point is the compile error: add a kind to any program's `DetectError`\n * and `DETECT_CODES` stops type-checking until it gets a code.\n */\nexport type DetectErrorKind =\n | RevenueDetectError['kind']\n | SelfDrivingDetectError['kind']\n | SourceMapsDetectError['kind']\n | WarehouseDetectError['kind']\n | WebAnalyticsDetectError['kind'];\n\nconst DETECT_CODES: Record<DetectErrorKind, ErrorCode> = {\n 'bad-directory': ErrorCodes.DetectBadDirectory,\n 'unsupported-platform': ErrorCodes.DetectUnsupportedPlatform,\n 'no-project-files': ErrorCodes.DetectNoProjectFiles,\n 'no-sources': ErrorCodes.DetectNoSources,\n 'no-package-json': ErrorCodes.DetectNoPackageJson,\n 'no-sdks': ErrorCodes.DetectNoSdks,\n 'missing-stripe': ErrorCodes.DetectMissingStripe,\n // Three kinds, one failure class: the program needs a PostHog SDK and the\n // project has none. Hosts that care which program asked read `detail.kind`.\n 'no-posthog-sdk': ErrorCodes.DetectNoPosthogSdk,\n 'no-posthog': ErrorCodes.DetectNoPosthogSdk,\n 'missing-posthog': ErrorCodes.DetectNoPosthogSdk,\n};\n\n/**\n * `kind` arrives as a bare string — `frameworkContext.detectError` is untyped\n * storage — so the lookup can still miss. It falls back to a detect-group code\n * with `retry: 'no'`, never to `InternalUnhandled`: an unrecognized precondition\n * failure is still a precondition failure, and telling a sandbox to retry one\n * costs it the whole budget.\n */\nexport function detectErrorCode(kind: string): ErrorCode {\n return DETECT_CODES[kind as DetectErrorKind] ?? ErrorCodes.DetectUnclassified;\n}\n","import { ErrorCodes, type ErrorCode } from './codes';\nimport type { InstallSkillResult } from '@lib/wizard-tools';\n\nconst SKILL_CODES: Record<\n Exclude<InstallSkillResult['kind'], 'ok'>,\n ErrorCode\n> = {\n 'menu-fetch-failed': ErrorCodes.SkillMenuFetchFailed,\n 'skill-not-found': ErrorCodes.SkillNotFound,\n 'download-failed': ErrorCodes.SkillDownloadFailed,\n};\n\nexport function skillErrorCode(result: InstallSkillResult): ErrorCode | null {\n if (result.kind === 'ok') return null;\n return SKILL_CODES[result.kind];\n}\n","const DETAIL_ALLOWLIST = ['reason', 'detected', 'platform'] as const;\n\nexport function sanitizeErrorDetail(\n detail: Record<string, unknown> | undefined,\n): Record<string, unknown> | undefined {\n if (!detail) return undefined;\n const safe: Record<string, unknown> = {};\n for (const key of DETAIL_ALLOWLIST) {\n if (detail[key] !== undefined) safe[key] = detail[key];\n }\n return Object.keys(safe).length > 0 ? safe : undefined;\n}\n"],"mappings":";AAAA,MAAa,aAAa;CACxB,gBAAgB;CAChB,YAAY;CACZ,oBAAoB;CACpB,wBAAwB;CACxB,mBAAmB;CACnB,uBAAuB;CACvB,kBAAkB;CAClB,2BAA2B;CAC3B,aAAa;CACb,kBAAkB;CAClB,oBAAoB;CACpB,sBAAsB;CACtB,sBAAsB;CACtB,yBAAyB;CACzB,wBAAwB;CACxB,sBAAsB;CACtB,kBAAkB;CAClB,oBAAoB;CACpB,mBAAmB;CACnB,0BAA0B;CAC1B,2BAA2B;CAC3B,oBAAoB;CACpB,sBAAsB;CACtB,iBAAiB;CACjB,qBAAqB;CACrB,cAAc;CACd,qBAAqB;CACrB,oBAAoB;CACpB,sBAAsB;CACtB,eAAe;CACf,qBAAqB;CACrB,YAAY;CACZ,iBAAiB;CACjB,sBAAsB;CACtB,gBAAgB;CAChB,eAAe;CACf,oBAAoB;CACpB,iBAAiB;CACjB,sBAAsB;CACtB,sCACE;CACF,8BAA8B;CAC9B,gCAAgC;CAChC,2BAA2B;CAC3B,mBAAmB;CACpB;;;AC5CD,MAAa,mBAAmB;AAQhC,SAAgB,sBAAsB,MAA+B;AACnE,QAAO,GAAG,iBAAiB,GAAG,KAAK,UAAU,KAAK;;AAGpD,SAAgB,gBAAgB,MAA6B;AAC3D,SAAQ,OAAO,MAAM,GAAG,sBAAsB,KAAK,CAAC,IAAI;;ACXvD,WAAW,gBAKX,WAAW,YAKX,WAAW,oBAKX,WAAW,wBAMX,WAAW,mBAKX,WAAW,uBAKX,WAAW,kBAKX,WAAW,2BAKX,WAAW,aAKX,WAAW,sBAKX,WAAW,kBAKX,WAAW,oBAKX,WAAW,sBAKX,WAAW,yBAMX,WAAW,wBAKX,WAAW,sBAKX,WAAW,kBAKX,WAAW,oBAMX,WAAW,mBAKX,WAAW,0BAMX,WAAW,2BAKX,WAAW,oBAMX,WAAW,sBAKX,WAAW,iBAKX,WAAW,qBAKX,WAAW,cAKX,WAAW,qBAKX,WAAW,oBAQX,WAAW,sBAKX,WAAW,eAKX,WAAW,qBAKX,WAAW,YAKX,WAAW,iBAKX,WAAW,sBAKX,WAAW,gBAKX,WAAW,eAKX,WAAW,oBAKX,WAAW,iBAKX,WAAW,sBAKX,WAAW,sCAKX,WAAW,8BAKX,WAAW,gCAKX,WAAW,2BAMX,WAAW;;;ACzNd,SAAgB,oBAAoB,OAAoC;AACtE,KAAI,MAAM,kBAAmB,QAAO,WAAW;AAC/C,KAAI,MAAM,oBAAqB,QAAO,WAAW;AACjD,KACE,MAAM,UACN,CAAC,MAAM,OAAO,WAAW,OAAO,IAChC,CAAC,MAAM,OAAO,WAAW,OAAO,CAEhC,QAAO,WAAW;AAEpB,KAAI,MAAM,iBAAiB,MAAM,cAAc,SAAS,EACtD,QAAO,WAAW;AAEpB,KACE,MAAM,iBACN,MAAM,iBACN,MAAM,kBAAkB,WACxB,MAAM,kBAAkB,MAAM,cAE9B,QAAO,WAAW;AAEpB,QAAO,WAAW;;;;;;;;;AC1BpB,MAAa,eAAe;CAE1B,QAAQ;CAER,mBAAmB;CAEnB,wBAAwB;CAQxB,sBAAsB;CAMtB,OAAO;CAEP,eAAe;CAEf,WAAW;CAMX,eAAe;CAMf,cAAc;CACf;;;;;;;AAUD,MAAa,qBAAqB,6CAA6C,aAAa,cAAc;;;AClD1G,MAAa,mBAAsD;yBACnC,WAAW;8BACN,WAAW;wBACjB,WAAW;uBACZ,WAAW;4BACN,WAAW;mBACpB,WAAW;yBACL,WAAW;8BACN,WAAW;CAC/C;;;ACWD,MAAM,eAAmD;CACvD,iBAAiB,WAAW;CAC5B,wBAAwB,WAAW;CACnC,oBAAoB,WAAW;CAC/B,cAAc,WAAW;CACzB,mBAAmB,WAAW;CAC9B,WAAW,WAAW;CACtB,kBAAkB,WAAW;CAG7B,kBAAkB,WAAW;CAC7B,cAAc,WAAW;CACzB,mBAAmB,WAAW;CAC/B;;;;;;;;AASD,SAAgB,gBAAgB,MAAyB;AACvD,QAAO,aAAa,SAA4B,WAAW;;;;AC3C7D,MAAM,cAGF;CACF,qBAAqB,WAAW;CAChC,mBAAmB,WAAW;CAC9B,mBAAmB,WAAW;CAC/B;AAED,SAAgB,eAAe,QAA8C;AAC3E,KAAI,OAAO,SAAS,KAAM,QAAO;AACjC,QAAO,YAAY,OAAO;;;;ACd5B,MAAM,mBAAmB;CAAC;CAAU;CAAY;CAAW;AAE3D,SAAgB,oBACd,QACqC;AACrC,KAAI,CAAC,OAAQ,QAAO,KAAA;CACpB,MAAM,OAAgC,EAAE;AACxC,MAAK,MAAM,OAAO,iBAChB,KAAI,OAAO,SAAS,KAAA,EAAW,MAAK,OAAO,OAAO;AAEpD,QAAO,OAAO,KAAK,KAAK,CAAC,SAAS,IAAI,OAAO,KAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-prompt-streaming-CHRPxxd0.js","names":[],"sources":["../src/lib/agent/mcp-prompt-streaming.ts"],"sourcesContent":["/**\n * Streaming prompt runner for the McpSuggestedPromptsScreen.\n *\n * Calls the Claude Agent SDK's `query()` directly with just the PostHog\n * MCP server configured — no skills, no sandbox, no settings sources,\n * no wizard-tools. This is the lightweight cousin of `runAgent` in\n * `agent-interface.ts`: same SDK, much narrower surface, suitable for\n * \"user asked a question, show the answer\" interactions.\n *\n * The function is an async generator that yields `AgentChunk`s extracted\n * from the SDK's message stream. Callers (the screen) consume them via\n * `for await (...)` and render as they arrive.\n */\n\nimport type { AgentChunk } from '@ui/tui/services/mcp-suggested-prompts-services';\nimport type { Credentials } from '@lib/wizard-session';\nimport { DEFAULT_AGENT_MODEL, WIZARD_USER_AGENT } from '@lib/constants';\nimport { logToFile } from '@utils/debug';\nimport { buildAgentEnv, buildRunTags } from '@lib/agent/agent-interface';\nimport { sanitizeAgentSubprocessEnv } from '@lib/agent/agent-env-isolation';\nimport { analytics } from '@utils/analytics';\n\n// Cached SDK module — first call pays the dynamic-import cost; later\n// calls reuse the same module.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _sdkModule: any | null = null;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function loadSdk(): Promise<any> {\n if (!_sdkModule) {\n _sdkModule = await import('@anthropic-ai/claude-agent-sdk');\n }\n return _sdkModule;\n}\n\nconst MODEL = DEFAULT_AGENT_MODEL;\n\n// Bounded turn count so a single prompt can't loop forever on the\n// user's nickel. 20 gives the agent room for non-trivial multi-step\n// chains (multi-tool reads → reason → write → verify → summarize) while\n// still capping runaway loops. Worth tuning down once we see real\n// telemetry on average turn counts per prompt.\nconst MAX_TURNS = 30;\n\n/**\n * Extract a short, single-line summary from an arbitrary value. Used\n * for tool-call args and tool-result bodies so the screen has something\n * compact to render.\n */\nfunction summarize(value: unknown, maxLen = 120): string {\n if (value == null) return '';\n let text: string;\n if (typeof value === 'string') text = value;\n else {\n try {\n text = JSON.stringify(value);\n } catch {\n text = String(value);\n }\n }\n text = text.replace(/\\s+/g, ' ').trim();\n if (text.length > maxLen) text = text.slice(0, maxLen - 1) + '…';\n return text;\n}\n\n/**\n * Convert one SDK message into zero or more AgentChunks. Mirrors the\n * subset of message shapes the wizard's main runAgent middleware\n * handles, but narrowed to just the kinds the screen needs to render.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction messageToChunks(message: any): AgentChunk[] {\n const chunks: AgentChunk[] = [];\n\n if (message?.type === 'assistant') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const content = message.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n const type = (block as { type?: string }).type;\n if (type === 'text') {\n const text = (block as { text?: string }).text ?? '';\n if (text) chunks.push({ kind: 'text', text });\n } else if (type === 'tool_use') {\n const name = (block as { name?: string }).name ?? 'tool';\n const input = (block as { input?: unknown }).input;\n // CLI mode's exec tool takes a `command` string; keep it verbatim so\n // the screen can recover the inner tool name for follow-ups.\n const command = (input as { command?: unknown })?.command;\n chunks.push({\n kind: 'tool-call',\n toolName: name,\n detail: summarize(input),\n command: typeof command === 'string' ? command : undefined,\n });\n }\n }\n }\n }\n\n if (message?.type === 'user') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const content = message.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n const type = (block as { type?: string }).type;\n if (type === 'tool_result') {\n const detail = summarize((block as { content?: unknown }).content);\n chunks.push({ kind: 'tool-result', toolName: 'tool', detail });\n }\n }\n }\n }\n\n if (message?.type === 'result') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const sessionId = (message as { session_id?: string }).session_id;\n chunks.push({ kind: 'done', sessionId });\n }\n\n return chunks;\n}\n\n/**\n * Build a system-prompt append that nudges the agent to fit its response\n * inside the current terminal window. We can't actually constrain Claude\n * — this is a soft cap that the model usually honors. The screen also\n * applies a hard truncation cap as a fallback for non-compliant runs.\n *\n * Core principle nudged at the model: TALL CONTENT IS BAD, WIDE CONTENT\n * IS GOOD. Default terminal is 120 columns × 24 rows — that's a lot of\n * horizontal space, not much vertical. Spread data across columns, never\n * stack it down rows when a horizontal layout would work.\n */\nfunction buildTerminalFitPrompt(): string {\n const cols = process.stdout.columns ?? 120;\n const rows = process.stdout.rows ?? 24;\n // Reserve rows for wizard chrome (title, status, hint, margins).\n const messageBudget = Math.max(8, rows - 10);\n\n return [\n `You are responding inside a CLI window that is exactly ${cols} columns wide and ${rows} rows tall. The user CAN'T SCROLL — your entire reply must fit on screen.`,\n ``,\n `LAYOUT PRINCIPLE: tall content is the enemy, wide content is your friend. You have ${cols} columns of horizontal space; use them. Spread data across columns instead of stacking it down rows.`,\n ``,\n `Tables:`,\n `- Max 5 body rows. The prompts the user picks already constrain results to 5 or fewer — honor that and do not pad with extra rows.`,\n `- If a tool result returns more than 5 items, show the top 5 and mention the rest count inline (e.g. \"...and 12 more\").`,\n `- Prefer transposing wide-but-short data (items across columns, metrics down rows) when labels are short.`,\n `- A two-column table with many rows is the tall layout to AVOID.`,\n ``,\n `Other limits:`,\n `- Aim for 3-5 lines of prose. Maximum ${messageBudget} lines total.`,\n `- DO NOT announce what you are about to do. Skip preamble like \"I'll query…\", \"Let me check…\", \"Now I'll…\", \"I'm going to…\". Go straight to running tools and then the answer.`,\n `- Lists: if there are 6+ short items, format them inline (comma-separated), not as a vertical bullet list.`,\n `- For tool results, summarize the 1-3 numbers that matter. Do NOT echo raw JSON or the full payload.`,\n `- Code blocks: no language tag, no leading blank lines.`,\n `- No closing pleasantries (\"let me know if…\", \"feel free to…\"). Stop when the answer is delivered.`,\n `- No section headers unless the response actually has multiple sections.`,\n ``,\n `Naming saved artifacts:`,\n `- Every dashboard, insight, notebook, or annotation you create MUST include \"(wizard MCP tutorial)\" at the end of its title or name field. Examples: \"Weekly signups (wizard MCP tutorial)\", \"Top errors this week (wizard MCP tutorial)\", \"Onboarding analysis (wizard MCP tutorial)\".`,\n `- This applies on both create AND rename calls. If the user asks you to rename a saved artifact, preserve the \"(wizard MCP tutorial)\" suffix unless they explicitly ask you to drop it.`,\n `- Reason: lets the user find / clean up everything this tutorial created from one search in PostHog. Don't skip it — it's the only signal they'll have that an artifact came from the wizard.`,\n ``,\n `Tone & framing:`,\n `- This is a tutorial demoing PostHog (the product the user just installed). You are showing it off, not auditing it. Stay constructive and neutral about PostHog throughout.`,\n `- Don't editorialize about PostHog's reliability, performance, or cost. Describe what the data shows; treat anomalies as the user's data, not a platform issue.`,\n `- If a tool call fails or returns nothing, say \"the query didn't return data — try a different angle\" or similar. Do NOT speculate about outages, gateway issues, MCP problems, or service health.`,\n `- Avoid value-laden phrases like \"worth investigating\", \"concerning\", \"red flag\", \"problematic\", \"suspicious\", \"alarming\" when describing the user's metrics. Stick to what the numbers show; the user draws conclusions.`,\n ].join('\\n');\n}\n\n/**\n * Gateway trace tags for a tutorial prompt run — without them the gateway has\n * nothing to attribute its `$ai_generation` events to. Returns `{}` when no\n * program is supplied. Exported so the contract is testable without the SDK.\n */\nexport function buildTutorialRunTags(args: {\n programId?: string;\n integration?: string;\n}): Record<string, string> {\n if (!args.programId) return {};\n return buildRunTags({\n programId: args.programId,\n // The tutorial usually has no detected framework; fall back to the\n // program so the axis is never an empty string.\n integration: args.integration ?? args.programId,\n runId: analytics.runId,\n build: analytics.build,\n });\n}\n\nexport async function* runMcpPromptViaSdk(args: {\n prompt: string;\n credentials: Credentials;\n signal: AbortSignal;\n /** When set, the SDK loads the named session's prior turns as\n * context so the follow-up prompt can reference what the agent\n * already showed. */\n resumeSessionId?: string;\n /** Program this run's gateway spend attributes to; omitting it leaves the\n * spend unattributed. */\n programId?: string;\n /** Integration label for the trace tags; the tutorial usually has none. */\n integration?: string;\n}): AsyncIterable<AgentChunk> {\n const { prompt, credentials, signal, resumeSessionId } = args;\n\n // Assembled here rather than passed in so the TUI service layer doesn't\n // have to import this module's dependencies.\n const wizardMetadata = buildTutorialRunTags(args);\n\n // Route the SDK's LLM calls through the PostHog LLM gateway, authed\n // with the user's OAuth access token. Set BEFORE loading the SDK in\n // case any in-process code reads env at module init (cached base\n // URLs, OAuth setup, etc.) — same reason `initializeAgent` does this\n // before its query() call. Without these the SDK tries to\n // authenticate directly against Anthropic and 401s with \"Invalid\n // authentication credentials\".\n process.env.CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS = 'true';\n\n // Route through the PostHog LLM gateway, authed with the user's OAuth token.\n const gatewayUrl = credentials.host.gatewayUrl;\n process.env.ANTHROPIC_BASE_URL = gatewayUrl;\n process.env.ANTHROPIC_AUTH_TOKEN = credentials.accessToken;\n process.env.CLAUDE_CODE_OAUTH_TOKEN = credentials.accessToken;\n\n logToFile(\n `[runMcpPromptViaSdk] gatewayUrl=${gatewayUrl} tokenPrefix=${\n credentials.accessToken\n ? credentials.accessToken.slice(0, 4) + '***'\n : '(missing)'\n }`,\n );\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const { query } = await loadSdk();\n\n // Bridge external AbortSignal → SDK AbortController.\n const abortController = new AbortController();\n if (signal.aborted) abortController.abort();\n else\n signal.addEventListener('abort', () => abortController.abort(), {\n once: true,\n });\n\n const mcpUrl = credentials.host.mcpUrl;\n logToFile(\n `[runMcpPromptViaSdk] mcpUrl=${mcpUrl} model=${MODEL} resume=${\n resumeSessionId ?? '(none)'\n }`,\n );\n\n // The SDK expects an async generator for the prompt that stays open\n // until the result is received. For a single-turn prompt we yield one\n // user message and then await an abort (which fires when streaming\n // completes or the caller cancels).\n const createPromptStream = async function* () {\n yield {\n type: 'user' as const,\n session_id: '',\n message: { role: 'user' as const, content: prompt },\n parent_tool_use_id: null,\n };\n // Hold the stream open until abort. The SDK closes its end when it\n // sees a `result` message; we close ours via the abortController in\n // the finally block below.\n await new Promise<void>((resolve) => {\n if (abortController.signal.aborted) {\n resolve();\n return;\n }\n abortController.signal.addEventListener('abort', () => resolve(), {\n once: true,\n });\n });\n };\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n const response = query({\n prompt: createPromptStream(),\n options: {\n abortController,\n model: MODEL,\n cwd: process.cwd(),\n permissionMode: 'acceptEdits',\n maxTurns: MAX_TURNS,\n // Match agent-interface.ts — the 1M context beta is what keeps\n // resumed follow-up sessions from truncating after a few turns.\n betas: ['context-1m-2025-08-07'],\n // Only load project-level skills/settings. Without this the SDK\n // defaults to ['user', 'project'] and a user's\n // `~/.claude/settings.json` (apiKeyHelper / env block) can\n // override the OAuth routing we set above.\n settingSources: ['project'],\n // When set, the SDK replays the named session's turns into the\n // new query so the follow-up prompt has full conversation\n // context. Omit on the first prompt for a fresh session.\n ...(resumeSessionId ? { resume: resumeSessionId } : {}),\n // Without `canUseTool` the SDK falls back to \"ask the user\" on\n // every MCP tool call — `permissionMode: 'acceptEdits'` only\n // relaxes Edit/Write, not MCP. Our Ink TUI has no surface to\n // answer that prompt, so the agent would stall mid-stream\n // saying things like \"needs your approval to create dashboard\".\n // The tutorial's whole point is demoing the MCP tools against\n // the user's project, so we auto-allow everything that matches\n // the prefix and deny anything else (defense in depth — the\n // `allowedTools` filter above already enforces this).\n canUseTool: (toolName: string, input: unknown) => {\n if (toolName.startsWith('mcp__posthog-wizard__')) {\n return Promise.resolve({\n behavior: 'allow' as const,\n updatedInput: (input ?? {}) as Record<string, unknown>,\n });\n }\n logToFile(`[runMcpPromptViaSdk] denying non-MCP tool: ${toolName}`);\n return Promise.resolve({\n behavior: 'deny' as const,\n message: `${toolName} is not available in the MCP tutorial — only PostHog MCP tools are permitted.`,\n });\n },\n systemPrompt: {\n type: 'preset',\n preset: 'claude_code',\n append: buildTerminalFitPrompt(),\n },\n mcpServers: {\n 'posthog-wizard': {\n type: 'http',\n url: mcpUrl,\n headers: {\n // Env reference, not the token: the SDK puts this config on the\n // spawned CLI's argv, where `ps` shows it to any local process.\n Authorization: 'Bearer ${POSTHOG_MCP_TOKEN}',\n 'User-Agent': WIZARD_USER_AGENT,\n },\n // CLI mode's single `exec` tool carries the full command reference\n // on its schema — keep it in context, never deferred behind tool\n // search.\n alwaysLoad: true,\n },\n },\n // Only let the agent use MCP tools — no shell, no file I/O,\n // no Read/Edit/Write. This is a chat-with-MCP run, not a\n // wizard skill execution.\n allowedTools: ['mcp__posthog-wizard__*'],\n env: {\n // Drop the ENTIRE ANTHROPIC_*/CLAUDE_CODE_* namespace from the\n // inherited env so no shell/settings value can silently bypass the\n // PostHog gateway and defeat quota tracking / the OAuth flow; the\n // wizard's own gateway routing is injected fresh below. See\n // agent-env-isolation.ts.\n ...sanitizeAgentSubprocessEnv(process.env),\n // Gateway routing — injected explicitly (set on process.env above;\n // the strip removed them from the inherited copy, so re-add here).\n ANTHROPIC_BASE_URL: process.env.ANTHROPIC_BASE_URL,\n ANTHROPIC_AUTH_TOKEN: process.env.ANTHROPIC_AUTH_TOKEN,\n CLAUDE_CODE_OAUTH_TOKEN: process.env.CLAUDE_CODE_OAUTH_TOKEN,\n CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: 'true',\n // The MCP config resolves this in the child; sending the value would\n // put it on the CLI's argv.\n POSTHOG_MCP_TOKEN: credentials.accessToken,\n // SDK 0.3.142+ connects MCP servers in the background by\n // default; without this the agent may try to call tools\n // before posthog-wizard is connected on turn 1.\n MCP_CONNECTION_NONBLOCKING: '0',\n // Bedrock fallback plus this run's trace tags — the gateway reads\n // these to attribute its `$ai_generation` events. Flags stay empty:\n // the tutorial doesn't fork on any.\n ANTHROPIC_CUSTOM_HEADERS: buildAgentEnv(wizardMetadata ?? {}, {}),\n },\n },\n });\n\n for await (const message of response as AsyncIterable<unknown>) {\n if (signal.aborted) return;\n for (const chunk of messageToChunks(message)) {\n yield chunk;\n if (chunk.kind === 'done') return;\n }\n }\n } catch (err) {\n const text = err instanceof Error ? err.message : String(err);\n logToFile(`[runMcpPromptViaSdk] error: ${text}`);\n yield { kind: 'error', text };\n } finally {\n // Closes the prompt stream so `query()` shuts down cleanly even if\n // we never saw a 'result' message.\n abortController.abort();\n }\n}\n"],"mappings":"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"}
|
package/dist/pi-RlnYUHdb.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pi-RlnYUHdb.js","names":[],"sources":["../src/lib/agent/aio-capture.ts","../src/lib/agent/runner/harness/pi/completion.ts","../src/lib/agent/runner/harness/pi/index.ts"],"sourcesContent":["/**\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 '@lib/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};\n\nconst noop = (_: unknown): void => undefined;\nconst NOOP: AioCapture = {\n setInitialPrompt: noop,\n captureFromAnthropicSDKMessage: noop,\n captureFromPiMessageEndEvent: 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 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: false,\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 // Terminal: pi emits `agent_end` when the session's prompt() resolves.\n if (e?.type === 'agent_end' && !e.willRetry) {\n sendTraceEnd({ isError: false });\n }\n } catch (err) {\n logToFile(\n `[aio-capture] pi compose failed: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n },\n };\n}\n","import { AgentErrorType } from '@lib/agent/signals';\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 * 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 { getUI } from '@ui';\nimport { getLogFilePath, logToFile } from '@utils/debug';\nimport {\n Harness,\n Sequence,\n WIZARD_REMARK_EVENT_NAME,\n WIZARD_USER_AGENT,\n} from '@lib/constants';\nimport { analytics } from '@utils/analytics';\nimport { AgentErrorType } from '@lib/agent/agent-interface';\nimport { AgentSignals, REMARK_INSTRUCTION } from '@lib/agent/signals';\nimport { AgentOutputSignals } from '@lib/agent/output-signals';\nimport { assembleCommandments } from '../../switchboard/commandments';\nimport { buildGatewayProvider, GATEWAY_PROVIDER } from './gateway';\nimport { createAioCapture } from '@lib/agent/aio-capture';\nimport type {\n AgentResult,\n AgentHarness,\n BackendRunInputs,\n TaskRunInputs,\n} from '../types';\nimport type { BootstrapResult } from '@lib/agent/runner/shared/types';\nimport type { TaskStore } from './tasks';\nimport { completionFailure } from './completion';\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(boot: BootstrapResult, instructions?: string): string {\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/** Pull plain text out of a pi AgentMessage (content is text/image blocks). */\nexport function extractText(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 .join('');\n }\n return '';\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(textBlock: string): void {\n const markers: Array<[string, (url: string) => void]> = [\n [AgentSignals.DASHBOARD_URL, (url) => getUI().setDashboardUrl(url)],\n [AgentSignals.NOTEBOOK_URL, (url) => getUI().setNotebookUrl(url)],\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 const { session, boot, prompt, spinner, config, programConfig } = inputs;\n const modelId = inputs.model;\n\n const capture = createAioCapture({\n enabled: session.captureAio,\n projectApiKey: boot.credentials.projectApiKey,\n apiHost: boot.credentials.host.apiHost,\n runTags: boot.wizardMetadata,\n });\n\n // Init banner (parity #5).\n getUI().log.step('Initializing Wizard agent...');\n getUI().log.step(`Verbose logs: ${getLogFilePath()}`);\n getUI().log.success(\"Agent initialized. Let's get cooking!\");\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 // 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 const captureAborted = () =>\n analytics.wizardCapture('agent aborted', {\n ...runDurations(),\n model: modelId,\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).\n const { provider, caps } = buildGatewayProvider({\n gatewayUrl: boot.credentials.host.gatewayUrl,\n accessToken: boot.credentials.accessToken,\n wizardMetadata: boot.wizardMetadata,\n wizardFlags: boot.wizardFlags,\n modelId,\n effort: inputs.thinkingLevel,\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 error: 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 } = await import('./security');\n const security = createSecurityExtension({\n disallowedTools: programConfig.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: session.installDir,\n });\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('@lib/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 mcpCleanup: (() => void) | undefined;\n let mcpInstructions: string | undefined;\n try {\n const { setupPostHogMcp, fetchInstructions } = await import('./mcp');\n // Overlaps the network handshake with the adapter's jiti load.\n const instructionsPromise = fetchInstructions(\n boot.credentials.host.mcpUrl,\n boot.credentials.accessToken,\n WIZARD_USER_AGENT,\n );\n const mcp = await setupPostHogMcp({\n mcpUrl: boot.credentials.host.mcpUrl,\n accessToken: boot.credentials.accessToken,\n userAgent: WIZARD_USER_AGENT,\n });\n extensionFactories.push(mcp.extensionFactory);\n mcpCleanup = mcp.cleanup;\n mcpInstructions = await instructionsPromise;\n } catch (err) {\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 const resourceLoader = new DefaultResourceLoader({\n cwd: session.installDir,\n agentDir: getAgentDir(),\n systemPrompt:\n assembleCommandments({\n program: programConfig.id,\n sequence: Sequence.linear,\n harness: Harness.pi,\n caps: { bash: true, posthogMcp: true },\n }) +\n '\\n' +\n piMcpContext(boot, mcpInstructions),\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();\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(session.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(session.installDir), 'parallel'),\n withMode(createEditToolDefinition(session.installDir), 'sequential'),\n withMode(createWriteToolDefinition(session.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(session.installDir), 'parallel'),\n withMode(createFindToolDefinition(session.installDir), 'parallel'),\n withMode(createGrepToolDefinition(session.installDir), 'parallel'),\n ...createWizardPiTools({\n workingDirectory: session.installDir,\n skillsBaseUrl: boot.skillsBaseUrl,\n triageProvider: boot.triageProvider,\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: programConfig.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: session.installDir,\n agentDir: getAgentDir(),\n securityFactory: security.factory as (pi: unknown) => void,\n bashTool: scrubbedBash,\n sdk: { createAgentSession, DefaultResourceLoader, SessionManager },\n }),\n ];\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: session.installDir,\n sessionManager: SessionManager.inMemory(session.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 await agentSession.bindExtensions({});\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 const assistant = extractText(event.message).trim();\n if (assistant) {\n logToFile(`[pi] assistant: ${assistant.slice(0, 1000)}`);\n applyOutroMarkers(assistant);\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 getUI().pushStatus(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 // 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 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 try {\n // Non-streaming: resolves when the agent run completes. Throws if no\n // model/api key, or on a transport error.\n await agentSession.prompt(prompt);\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 let continueNudges = 0;\n while (\n continueNudges < MAX_CONTINUE_NUDGES &&\n !security.state.criticalViolation &&\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 agentSession.prompt(CONTINUE_INSTRUCTION);\n }\n\n // Best-effort remark ask — a failed turn never fails a successful run.\n if (!security.state.criticalViolation) {\n try {\n await agentSession.prompt(REMARK_INSTRUCTION);\n } catch (err) {\n logToFile(`[pi] remark request failed: ${String(err)}`);\n }\n }\n } finally {\n unsubscribe();\n mcpCleanup?.();\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) {\n spinner.stop('Security violation detected');\n logToFile(\n `[pi] terminated: YARA violation (blocked ${security.state.blockedCount} call(s))`,\n );\n captureAborted();\n return { error: AgentErrorType.YARA_VIOLATION };\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 = 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 captureAborted();\n return { error: failure };\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();\n return { error: 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 to remove it\n // on completion; pi's `rm` is fence-blocked, so the agent can't — clean it\n // up host-side rather than leave a stale (often empty) artifact (#15).\n try {\n const planFile = path.join(session.installDir, '.posthog-events.json');\n if (fs.existsSync(planFile)) 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 return {};\n } catch (err) {\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 getUI().log.error(`pi backend error: ${message}`);\n captureAborted();\n\n const lower = message.toLowerCase();\n if (lower.includes('rate limit') || lower.includes('429')) {\n return { error: AgentErrorType.RATE_LIMIT, message };\n }\n return { error: AgentErrorType.API_ERROR, message };\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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"}
|