pk-agent 0.7.2
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/LICENSE +13 -0
- package/README.md +403 -0
- package/bin/cli.js +2 -0
- package/dist/index.js +20549 -0
- package/dist/index.js.map +120 -0
- package/package.json +98 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["..\\src\\auth\\storage.ts", "..\\src\\auth\\anthropic.ts", "..\\src\\auth\\codex.ts", "..\\src\\utils\\redaction.ts", "..\\src\\utils\\logger.ts", "..\\src\\utils\\names.ts", "..\\src\\storage\\paths.ts", "..\\src\\utils\\pk-agent-dirs.ts", "..\\src\\tools\\path-validator.ts", "..\\src\\tools\\edit-replacers.ts", "..\\src\\tools\\filesystem.ts", "..\\src\\tools\\bash-parser.ts", "..\\src\\tools\\wildcard.ts", "..\\src\\tools\\command-validator.ts", "..\\src\\tools\\bash.ts", "..\\src\\tools\\capture-window.ts", "..\\src\\tools\\fullstack.ts", "..\\src\\tools\\types.ts", "..\\src\\tools\\doom-loop-detector.ts", "..\\src\\tools\\codex-sdk.ts", "..\\src\\tools\\openai-agents-sdk.ts", "..\\src\\agent-builder\\schemas.ts", "..\\src\\agent-builder\\utils.ts", "..\\src\\scheduler\\types.ts", "..\\src\\scheduler\\parser.ts", "..\\src\\tools\\pk-agent-builder.ts", "..\\src\\tools\\index.ts", "..\\src\\scheduler\\scheduler.ts", "..\\src\\scheduler\\index.ts", "..\\src\\parser.ts", "..\\src\\storage\\storage.ts", "..\\src\\storage\\index.ts", "..\\src\\utils\\config.ts", "..\\src\\generated\\models.ts", "..\\src\\skill\\types.ts", "..\\src\\skill\\parser.ts", "..\\src\\skill\\discovery.ts", "..\\src\\session\\conversation-snapshot.ts", "..\\src\\utils\\model-utils.ts", "..\\src\\providers\\demo.ts", "..\\src\\models.ts", "..\\src\\model-fallback.ts", "..\\src\\utils\\models-api.ts", "..\\src\\context-manager.ts", "..\\src\\compactor.ts", "..\\src\\utils\\retry.ts", "..\\src\\runner\\execution.ts", "..\\src\\utils\\env.ts", "..\\src\\mcp-cache.ts", "..\\src\\mcp.ts", "..\\src\\utils\\remote-agent.ts", "..\\src\\runner\\prompt.ts", "..\\src\\runner\\stream.ts", "..\\src\\runner\\run-stream.ts", "..\\src\\runner.ts", "..\\src\\session\\manager.ts", "..\\src\\utils\\agents-guidance.ts", "..\\src\\hooks\\index.ts", "..\\src\\utils\\file-attachments.ts", "..\\src\\utils\\prompt-variables.ts", "..\\src\\references.ts", "..\\src\\subagent.ts", "..\\src\\skill\\validate.ts", "..\\src\\skill\\tool.ts", "..\\src\\skill\\index.ts", "..\\src\\utils\\cli-helpers.ts", "..\\src\\runner\\preparation.ts", "..\\src\\runner\\run.ts", "..\\src\\session\\index.ts", "..\\src\\index.ts", "..\\src\\cli\\auth.ts", "..\\src\\auth\\types.ts", "..\\src\\auth\\index.ts", "..\\src\\utils\\open-url.ts", "..\\src\\cli\\sessions.ts", "..\\src\\utils\\project.ts", "..\\src\\cli\\serve.ts", "..\\src\\utils\\branding.ts", "..\\src\\watcher\\file-watcher.ts", "..\\src\\telemetry\\index.ts", "..\\src\\telemetry\\id.ts", "..\\src\\utils\\env-validation.ts", "..\\src\\utils\\server-registry.ts", "..\\src\\config\\app-config.ts", "..\\src\\cli\\models.ts", "..\\src\\cli\\skills.ts", "..\\src\\cli\\benchmark.ts", "..\\src\\benchmark\\loader.ts", "..\\src\\benchmark\\types.ts", "..\\src\\benchmark\\runner.ts", "..\\src\\benchmark\\evaluator\\completion.ts", "..\\src\\benchmark\\evaluator\\artifacts.ts", "..\\src\\benchmark\\goal-tracker.ts", "..\\src\\benchmark\\goal-tools.ts", "..\\src\\benchmark\\reporter\\json.ts", "..\\src\\benchmark\\calculator.ts", "..\\src\\benchmark\\reporter\\markdown.ts", "..\\src\\benchmark\\reporter\\shared.ts", "..\\src\\benchmark\\reporter\\html.ts", "..\\src\\benchmark\\reporter\\index.ts", "..\\src\\cli\\agents.ts", "..\\src\\cli\\add.ts", "..\\src\\cli\\create.ts", "..\\src\\cli\\run.ts", "..\\src\\plugin\\index.ts", "..\\src\\utils\\trace.ts", "..\\src\\cli\\lint.ts", "..\\src\\cli\\config.ts", "..\\src\\cli\\test.ts", "..\\src\\validator\\agent-validator.ts", "..\\src\\cli\\worker.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import fs from \"fs/promises\";\nimport path from \"path\";\nimport os from \"os\";\nimport type { AuthInfo, OAuthTokens, CodexOAuthTokens, ApiKeyAuth, ProviderAuth } from \"./types.js\";\n\nexport class AuthStorage {\n private static readonly AUTH_FILE = path.join(\n os.homedir(),\n \".local\",\n \"share\",\n \"pk-agent\",\n \"auth.json\"\n );\n\n private static async ensureDir() {\n const dir = path.dirname(this.AUTH_FILE);\n await fs.mkdir(dir, { recursive: true });\n }\n\n /**\n * Get raw auth info for a provider (legacy single-value format)\n * Prefer using getOAuth/getApiKey for new code\n */\n static async get(providerID: string): Promise<AuthInfo | undefined> {\n try {\n const content = await fs.readFile(this.AUTH_FILE, \"utf-8\");\n const data = JSON.parse(content);\n return data[providerID] as AuthInfo | undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Get OAuth tokens for a provider\n * Checks both new format ({provider}:oauth) and legacy format ({provider})\n */\n static async getOAuth(providerID: string): Promise<OAuthTokens | CodexOAuthTokens | undefined> {\n try {\n const content = await fs.readFile(this.AUTH_FILE, \"utf-8\");\n const data = JSON.parse(content);\n\n // Check new format first\n const oauthKey = `${providerID}:oauth`;\n if (data[oauthKey]) {\n const auth = data[oauthKey] as AuthInfo;\n if (auth.type === \"oauth\" || auth.type === \"codex-oauth\") {\n return auth;\n }\n }\n\n // Fall back to legacy format\n const legacy = data[providerID] as AuthInfo | undefined;\n if (legacy && (legacy.type === \"oauth\" || legacy.type === \"codex-oauth\")) {\n return legacy;\n }\n\n return undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Get API key for a provider\n * Checks both new format ({provider}:api) and legacy format ({provider})\n */\n static async getApiKey(providerID: string): Promise<ApiKeyAuth | undefined> {\n try {\n const content = await fs.readFile(this.AUTH_FILE, \"utf-8\");\n const data = JSON.parse(content);\n\n // Check new format first\n const apiKey = `${providerID}:api`;\n if (data[apiKey]) {\n const auth = data[apiKey] as AuthInfo;\n if (auth.type === \"api\") {\n return auth;\n }\n }\n\n // Fall back to legacy format\n const legacy = data[providerID] as AuthInfo | undefined;\n if (legacy && legacy.type === \"api\") {\n return legacy;\n }\n\n return undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Get all auth methods for a provider (both OAuth and API key)\n */\n static async getProviderAuth(providerID: string): Promise<ProviderAuth> {\n const result: ProviderAuth = {};\n\n const oauth = await this.getOAuth(providerID);\n if (oauth) {\n result.oauth = oauth;\n }\n\n const api = await this.getApiKey(providerID);\n if (api) {\n result.api = api;\n }\n\n return result;\n }\n\n static async all(): Promise<Record<string, AuthInfo>> {\n try {\n const content = await fs.readFile(this.AUTH_FILE, \"utf-8\");\n return JSON.parse(content);\n } catch {\n return {};\n }\n }\n\n /**\n * Set auth info (legacy format - stores under provider key)\n * Prefer using setOAuth/setApiKey for new code\n */\n static async set(providerID: string, info: AuthInfo): Promise<void> {\n await this.ensureDir();\n const data = await this.all();\n data[providerID] = info;\n await fs.writeFile(this.AUTH_FILE, JSON.stringify(data, null, 2));\n // Set file permissions to user read/write only\n await fs.chmod(this.AUTH_FILE, 0o600);\n }\n\n /**\n * Set OAuth tokens for a provider\n * Stores under {provider}:oauth key (does not overwrite API key)\n */\n static async setOAuth(providerID: string, info: OAuthTokens | CodexOAuthTokens): Promise<void> {\n await this.ensureDir();\n const data = await this.all();\n\n // Store in new format\n data[`${providerID}:oauth`] = info;\n\n // Clean up legacy format if it was OAuth (migrate to new format)\n const legacy = data[providerID];\n if (legacy && (legacy.type === \"oauth\" || legacy.type === \"codex-oauth\")) {\n delete data[providerID];\n }\n\n await fs.writeFile(this.AUTH_FILE, JSON.stringify(data, null, 2));\n await fs.chmod(this.AUTH_FILE, 0o600);\n }\n\n /**\n * Set API key for a provider\n * Stores under {provider}:api key (does not overwrite OAuth)\n */\n static async setApiKey(providerID: string, info: ApiKeyAuth): Promise<void> {\n await this.ensureDir();\n const data = await this.all();\n\n // Store in new format\n data[`${providerID}:api`] = info;\n\n // Clean up legacy format if it was API key (migrate to new format)\n const legacy = data[providerID];\n if (legacy && legacy.type === \"api\") {\n delete data[providerID];\n }\n\n await fs.writeFile(this.AUTH_FILE, JSON.stringify(data, null, 2));\n await fs.chmod(this.AUTH_FILE, 0o600);\n }\n\n static async remove(providerID: string): Promise<void> {\n const data = await this.all();\n delete data[providerID];\n await this.ensureDir();\n await fs.writeFile(this.AUTH_FILE, JSON.stringify(data, null, 2));\n }\n\n /**\n * Remove OAuth tokens for a provider\n */\n static async removeOAuth(providerID: string): Promise<void> {\n const data = await this.all();\n delete data[`${providerID}:oauth`];\n\n // Also remove legacy format if it was OAuth\n const legacy = data[providerID];\n if (legacy && (legacy.type === \"oauth\" || legacy.type === \"codex-oauth\")) {\n delete data[providerID];\n }\n\n await this.ensureDir();\n await fs.writeFile(this.AUTH_FILE, JSON.stringify(data, null, 2));\n }\n\n /**\n * Remove API key for a provider\n */\n static async removeApiKey(providerID: string): Promise<void> {\n const data = await this.all();\n delete data[`${providerID}:api`];\n\n // Also remove legacy format if it was API key\n const legacy = data[providerID];\n if (legacy && legacy.type === \"api\") {\n delete data[providerID];\n }\n\n await this.ensureDir();\n await fs.writeFile(this.AUTH_FILE, JSON.stringify(data, null, 2));\n }\n\n static getFilePath(): string {\n return this.AUTH_FILE;\n }\n}",
|
|
6
|
+
"import { generatePKCE } from \"@openauthjs/openauth/pkce\";\nimport { AuthStorage } from \"./storage.js\";\n\nexport namespace AnthropicAuth {\n const CLIENT_ID = \"9d1c250a-e61b-44d9-88ed-5944d1962f5e\";\n\n export async function authorize(mode: \"max\" | \"console\") {\n const pkce = await generatePKCE();\n\n const url = new URL(\n `https://${mode === \"console\" ? \"console.anthropic.com\" : \"claude.ai\"}/oauth/authorize`\n );\n \n url.searchParams.set(\"code\", \"true\");\n url.searchParams.set(\"client_id\", CLIENT_ID);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"redirect_uri\", \"https://console.anthropic.com/oauth/code/callback\");\n url.searchParams.set(\"scope\", \"org:create_api_key user:profile user:inference\");\n url.searchParams.set(\"code_challenge\", pkce.challenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n url.searchParams.set(\"state\", pkce.verifier);\n \n return {\n url: url.toString(),\n verifier: pkce.verifier,\n };\n }\n\n export async function exchange(code: string, verifier: string) {\n const splits = code.split(\"#\");\n const result = await fetch(\"https://console.anthropic.com/v1/oauth/token\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n code: splits[0],\n state: splits[1],\n grant_type: \"authorization_code\",\n client_id: CLIENT_ID,\n redirect_uri: \"https://console.anthropic.com/oauth/code/callback\",\n code_verifier: verifier,\n }),\n });\n if (!result.ok) throw new ExchangeFailed();\n const json = await result.json();\n return {\n refresh: json.refresh_token as string,\n access: json.access_token as string,\n expires: Date.now() + json.expires_in * 1000,\n };\n }\n\n export async function access() {\n // Priority 1: Check CLAUDE_CODE_OAUTH_TOKEN (long-lived token from `claude setup-token`)\n // This token is valid for 1 year and doesn't require refresh\n const claudeCodeOAuthToken = process.env.CLAUDE_CODE_OAUTH_TOKEN;\n if (claudeCodeOAuthToken) {\n return claudeCodeOAuthToken;\n }\n\n // Priority 2: Fall back to file-based storage\n const info = await AuthStorage.getOAuth(\"anthropic\");\n if (!info || info.type !== \"oauth\") return;\n if (info.access && info.expires > Date.now()) return info.access;\n\n const refreshed = await refreshToken(info.refresh);\n if (!refreshed) return;\n\n await AuthStorage.setOAuth(\"anthropic\", {\n type: \"oauth\",\n refresh: refreshed.refresh,\n access: refreshed.access,\n expires: refreshed.expires,\n });\n return refreshed.access;\n }\n\n async function refreshToken(refresh: string) {\n const response = await fetch(\"https://console.anthropic.com/v1/oauth/token\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n grant_type: \"refresh_token\",\n refresh_token: refresh,\n client_id: CLIENT_ID,\n }),\n });\n if (!response.ok) return null;\n const json = await response.json();\n return {\n refresh: json.refresh_token as string,\n access: json.access_token as string,\n expires: Date.now() + json.expires_in * 1000,\n };\n }\n\n export class ExchangeFailed extends Error {\n constructor() {\n super(\"Exchange failed\");\n }\n }\n}",
|
|
7
|
+
"import { AuthStorage } from \"./storage.js\";\r\nimport fs from \"fs/promises\";\r\nimport path from \"path\";\r\nimport os from \"os\";\r\nimport http from \"http\";\r\n\r\nconst CLIENT_ID = \"app_EMoamEEZ73f0CkXaXp7hrann\";\r\nconst ISSUER = \"https://auth.openai.com\";\r\nconst DEFAULT_CALLBACK_PORT = 1455;\r\n\r\nfunction getCallbackPort(port?: number): number {\r\n if (port !== undefined) return port;\r\n const envPort = process.env.CODEX_CALLBACK_PORT;\r\n if (!envPort) return DEFAULT_CALLBACK_PORT;\r\n const parsed = Number.parseInt(envPort, 10);\r\n return Number.isNaN(parsed) ? DEFAULT_CALLBACK_PORT : parsed;\r\n}\r\n\r\nfunction getRedirectUri(port: number): string {\r\n return `http://localhost:${port}/auth/callback`;\r\n}\r\n\r\ninterface PkceCodes {\r\n verifier: string;\r\n challenge: string;\r\n}\r\n\r\nasync function generatePKCE(): Promise<PkceCodes> {\r\n const verifier = generateRandomString(43);\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(verifier);\r\n const hash = await crypto.subtle.digest(\"SHA-256\", data);\r\n const challenge = base64UrlEncode(hash);\r\n return { verifier, challenge };\r\n}\r\n\r\nfunction generateRandomString(length: number): string {\r\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~\";\r\n const bytes = crypto.getRandomValues(new Uint8Array(length));\r\n return Array.from(bytes)\r\n .map((b) => chars[b % chars.length])\r\n .join(\"\");\r\n}\r\n\r\nfunction base64UrlEncode(buffer: ArrayBuffer): string {\r\n const bytes = new Uint8Array(buffer);\r\n const binary = String.fromCharCode(...bytes);\r\n return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\r\n}\r\n\r\nexport interface IdTokenClaims {\r\n chatgpt_account_id?: string;\r\n organizations?: Array<{ id: string }>;\r\n email?: string;\r\n \"https://api.openai.com/auth\"?: {\r\n chatgpt_account_id?: string;\r\n };\r\n}\r\n\r\nexport function parseJwtClaims(token: string): IdTokenClaims | undefined {\r\n const parts = token.split(\".\");\r\n if (parts.length !== 3) return undefined;\r\n try {\r\n return JSON.parse(Buffer.from(parts[1], \"base64url\").toString());\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\nexport function extractAccountIdFromClaims(claims: IdTokenClaims): string | undefined {\r\n return (\r\n claims.chatgpt_account_id ||\r\n claims[\"https://api.openai.com/auth\"]?.chatgpt_account_id ||\r\n claims.organizations?.[0]?.id\r\n );\r\n}\r\n\r\ninterface TokenResponse {\r\n id_token: string;\r\n access_token: string;\r\n refresh_token: string;\r\n expires_in?: number;\r\n}\r\n\r\nfunction extractAccountId(tokens: TokenResponse): string | undefined {\r\n if (tokens.id_token) {\r\n const claims = parseJwtClaims(tokens.id_token);\r\n const accountId = claims && extractAccountIdFromClaims(claims);\r\n if (accountId) return accountId;\r\n }\r\n if (tokens.access_token) {\r\n const claims = parseJwtClaims(tokens.access_token);\r\n return claims ? extractAccountIdFromClaims(claims) : undefined;\r\n }\r\n return undefined;\r\n}\r\n\r\nasync function refreshAccessToken(refreshToken: string): Promise<TokenResponse> {\r\n const response = await fetch(`${ISSUER}/oauth/token`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\r\n body: new URLSearchParams({\r\n grant_type: \"refresh_token\",\r\n refresh_token: refreshToken,\r\n client_id: CLIENT_ID,\r\n }).toString(),\r\n });\r\n if (!response.ok) {\r\n throw new Error(`Token refresh failed: ${response.status}`);\r\n }\r\n return response.json();\r\n}\r\n\r\nexport namespace CodexAuth {\r\n export async function authorize(options?: { port?: number }): Promise<{\r\n url: string;\r\n pkce: PkceCodes;\r\n }> {\r\n const pkce = await generatePKCE();\r\n const port = getCallbackPort(options?.port);\r\n if (port === 0) {\r\n throw new Error(\"OAuth redirect port cannot be 0\");\r\n }\r\n\r\n const params = new URLSearchParams({\r\n response_type: \"code\",\r\n client_id: CLIENT_ID,\r\n redirect_uri: getRedirectUri(port),\r\n scope: \"openid profile email offline_access\",\r\n code_challenge: pkce.challenge,\r\n code_challenge_method: \"S256\",\r\n id_token_add_organizations: \"true\",\r\n codex_cli_simplified_flow: \"true\",\r\n state: pkce.verifier,\r\n originator: \"codex_cli_rs\",\r\n });\r\n\r\n return {\r\n url: `${ISSUER}/oauth/authorize?${params.toString()}`,\r\n pkce,\r\n };\r\n }\r\n\r\n export async function exchange(\r\n code: string,\r\n pkce: PkceCodes,\r\n options?: { port?: number }\r\n ): Promise<{\r\n refresh: string;\r\n access: string;\r\n expires: number;\r\n accountId: string | undefined;\r\n }> {\r\n const port = getCallbackPort(options?.port);\r\n if (port === 0) {\r\n throw new Error(\"OAuth redirect port cannot be 0\");\r\n }\r\n\r\n const response = await fetch(`${ISSUER}/oauth/token`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\r\n body: new URLSearchParams({\r\n grant_type: \"authorization_code\",\r\n code,\r\n redirect_uri: getRedirectUri(port),\r\n client_id: CLIENT_ID,\r\n code_verifier: pkce.verifier,\r\n }).toString(),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new ExchangeFailed();\r\n }\r\n\r\n const tokens: TokenResponse = await response.json();\r\n const accountId = extractAccountId(tokens);\r\n\r\n return {\r\n refresh: tokens.refresh_token,\r\n access: tokens.access_token,\r\n expires: Date.now() + (tokens.expires_in ?? 3600) * 1000,\r\n accountId,\r\n };\r\n }\r\n\r\n export async function access(): Promise<{ token: string; accountId: string | undefined } | undefined> {\r\n const info = await AuthStorage.getOAuth(\"openai\");\r\n if (!info || info.type !== \"codex-oauth\") return undefined;\r\n\r\n // Check if token is still valid (with 5 minute buffer)\r\n if (info.access && info.expires > Date.now() + 5 * 60 * 1000) {\r\n return { token: info.access, accountId: info.accountId };\r\n }\r\n\r\n // Refresh the token\r\n try {\r\n const tokens = await refreshAccessToken(info.refresh);\r\n const accountId = extractAccountId(tokens) || info.accountId;\r\n const newInfo = {\r\n type: \"codex-oauth\" as const,\r\n refresh: tokens.refresh_token,\r\n access: tokens.access_token,\r\n expires: Date.now() + (tokens.expires_in ?? 3600) * 1000,\r\n accountId,\r\n };\r\n await AuthStorage.setOAuth(\"openai\", newInfo);\r\n return { token: tokens.access_token, accountId };\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n export class ExchangeFailed extends Error {\r\n constructor() {\r\n super(\"Token exchange failed\");\r\n }\r\n }\r\n\r\n /**\r\n * Import credentials from an existing Codex CLI installation.\r\n * Reads ~/.codex/auth.json and stores in pk-agent's auth storage.\r\n * Returns the imported account ID if available.\r\n */\r\n export async function importFromCodexCli(): Promise<{\r\n success: boolean;\r\n accountId?: string | undefined;\r\n error?: string | undefined;\r\n }> {\r\n const codexAuthPath = path.join(os.homedir(), \".codex\", \"auth.json\");\r\n\r\n try {\r\n const content = await fs.readFile(codexAuthPath, \"utf-8\");\r\n const codexAuth = JSON.parse(content);\r\n\r\n // Codex CLI auth format has changed over time.\r\n // - Legacy: { access_token, refresh_token, expires_at, ... }\r\n // - Current: { tokens: { access_token, refresh_token, ... }, ... }\r\n const accessToken = codexAuth.access_token ?? codexAuth.tokens?.access_token;\r\n const refreshToken = codexAuth.refresh_token ?? codexAuth.tokens?.refresh_token ?? \"\";\r\n const expiresAt = codexAuth.expires_at ?? codexAuth.tokens?.expires_at;\r\n\r\n if (!accessToken) {\r\n return {\r\n success: false,\r\n error: \"No access_token found in Codex auth.json (expected access_token or tokens.access_token)\",\r\n };\r\n }\r\n\r\n // Extract account ID from the JWT\r\n const claims = parseJwtClaims(accessToken);\r\n const accountId =\r\n (claims ? extractAccountIdFromClaims(claims) : undefined) ??\r\n codexAuth.account_id ??\r\n codexAuth.tokens?.account_id;\r\n\r\n // Convert to pk-agent format\r\n const authInfo = {\r\n type: \"codex-oauth\" as const,\r\n refresh: refreshToken,\r\n access: accessToken,\r\n expires: expiresAt\r\n ? expiresAt * 1000 // Codex uses seconds, we use milliseconds\r\n : Date.now() + 3600 * 1000,\r\n accountId,\r\n };\r\n\r\n await AuthStorage.setOAuth(\"openai\", authInfo);\r\n\r\n return { success: true, accountId: accountId || undefined };\r\n } catch (err) {\r\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\r\n return {\r\n success: false,\r\n error: `Codex CLI auth file not found at ${codexAuthPath}. Install and login with: npm install -g @openai/codex && codex`,\r\n };\r\n }\r\n return {\r\n success: false,\r\n error: `Failed to read Codex auth: ${err instanceof Error ? err.message : String(err)}`,\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Start a local HTTP server (default port 1455) to capture the OAuth callback.\r\n * Returns a promise that resolves with the authorization code.\r\n * Times out after 5 minutes.\r\n */\r\n export type CallbackServerResult = {\r\n code: string;\r\n close: () => void;\r\n };\r\n\r\n export type CallbackServerPromise = Promise<CallbackServerResult> & {\r\n port: Promise<number>;\r\n host: string;\r\n stop: () => void;\r\n };\r\n\r\n export function startCallbackServer(\r\n timeoutMs = 5 * 60 * 1000,\r\n opts?: { port?: number; host?: string; expectedState?: string }\r\n ): CallbackServerPromise {\r\n // We intentionally default to binding on all interfaces (by omitting host in\r\n // server.listen) because the redirect target is `localhost`, which may\r\n // resolve to IPv6 (::1) on some machines. We then strictly gate requests to\r\n // loopback addresses only.\r\n const baseHost = opts?.host ?? \"localhost\";\r\n const envPort = process.env.CODEX_CALLBACK_PORT\r\n ? Number.parseInt(process.env.CODEX_CALLBACK_PORT, 10)\r\n : undefined;\r\n const port = opts?.port ?? envPort ?? 1455;\r\n\r\n let resolvePort: (value: number) => void;\r\n let rejectPort: (reason?: unknown) => void;\r\n const portPromise = new Promise<number>((res, rej) => {\r\n resolvePort = res;\r\n rejectPort = rej;\r\n });\r\n\r\n let server: http.Server | undefined;\r\n\r\n const promise = new Promise<CallbackServerResult>((resolve, reject) => {\r\n const isLoopback = (addr: string | undefined): boolean => {\r\n if (!addr) return false;\r\n if (addr === \"127.0.0.1\" || addr === \"::1\") return true;\r\n if (addr.startsWith(\"::ffff:127.\")) return true; // IPv4-mapped loopback\r\n return false;\r\n };\r\n\r\n const httpServer = http.createServer((req, res) => {\r\n if (!isLoopback(req.socket.remoteAddress)) {\r\n res.writeHead(403);\r\n res.end(\"Forbidden\");\r\n return;\r\n }\r\n\r\n const url = new URL(req.url || \"/\", `http://${baseHost}:${port}`);\r\n\r\n if (url.pathname === \"/auth/callback\") {\r\n const code = url.searchParams.get(\"code\");\r\n const state = url.searchParams.get(\"state\");\r\n\r\n if (opts?.expectedState && state !== opts.expectedState) {\r\n res.writeHead(400, { \"Content-Type\": \"text/plain\" });\r\n res.end(\"Invalid state\");\r\n return;\r\n }\r\n\r\n // Send a success page\r\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\r\n res.end(`\r\n <html>\r\n <head><title>PK Agent - Authentication</title></head>\r\n <body style=\"font-family: system-ui; text-align: center; padding: 60px;\">\r\n <h1>${code ? \"[OK] Authentication Successful!\" : \"[X] Authentication Failed\"}</h1>\r\n <p>${code ? \"You can close this tab and return to the terminal.\" : \"No authorization code received.\"}</p>\r\n </body>\r\n </html>\r\n `);\r\n\r\n if (code) {\r\n resolve({\r\n code,\r\n close: () => httpServer.close(),\r\n });\r\n } else {\r\n reject(new Error(\"No authorization code in callback\"));\r\n httpServer.close();\r\n }\r\n } else {\r\n res.writeHead(404);\r\n res.end(\"Not found\");\r\n }\r\n });\r\n\r\n server = httpServer;\r\n\r\n // Handle server errors (e.g., port in use)\r\n httpServer.on(\"error\", (err) => {\r\n rejectPort(err);\r\n reject(err);\r\n });\r\n\r\n // Timeout\r\n const timer = setTimeout(() => {\r\n httpServer.close();\r\n reject(new Error(\"OAuth callback timed out after 5 minutes\"));\r\n }, timeoutMs);\r\n\r\n httpServer.on(\"close\", () => clearTimeout(timer));\r\n\r\n if (opts?.host) {\r\n httpServer.listen(port, opts.host, () => {\r\n const addr = httpServer.address();\r\n const actualPort =\r\n addr && typeof addr === \"object\" && \"port\" in addr ? addr.port : port;\r\n resolvePort(actualPort);\r\n });\r\n return;\r\n }\r\n\r\n httpServer.listen(port, () => {\r\n const addr = httpServer.address();\r\n const actualPort =\r\n addr && typeof addr === \"object\" && \"port\" in addr ? addr.port : port;\r\n resolvePort(actualPort);\r\n });\r\n });\r\n\r\n (promise as CallbackServerPromise).port = portPromise;\r\n (promise as CallbackServerPromise).host = baseHost;\r\n (promise as CallbackServerPromise).stop = () => {\r\n // If the server has already been closed, this is a no-op.\r\n // We intentionally don't expose errors here; callers should treat stop as best-effort cleanup.\r\n try {\r\n server?.close();\r\n } catch {\r\n // ignore\r\n }\r\n };\r\n return promise as CallbackServerPromise;\r\n }\r\n}\r\n",
|
|
8
|
+
"export interface SecretMatch {\n kind: string;\n value: string;\n index: number;\n}\n\nconst SECRET_PATTERNS: Array<{ kind: string; re: RegExp }> = [\n { kind: 'openai', re: /sk-[A-Za-z0-9_-]{16,}/g },\n { kind: 'anthropic', re: /sk-ant-[A-Za-z0-9_-]{16,}/g },\n { kind: 'github', re: /ghp_[A-Za-z0-9]{20,}/g },\n { kind: 'slack', re: /xox[baprs]-[A-Za-z0-9-]{10,}/g },\n { kind: 'pk-agent', re: /AQ\\.[A-Za-z0-9_-]{16,}/g },\n { kind: 'bearer', re: /Bearer\\s+[A-Za-z0-9._-]{16,}/g },\n];\n\nconst SUSPICIOUS_ASSIGNMENT =\n /\\b(token|secret|password|api[_-]?key|authorization|webhook)\\b\\s*[:=]\\s*(['\"]?)([A-Za-z0-9._-]{12,})\\2/gi;\n\nfunction looksLikePlaceholder(value: string): boolean {\n const v = value.toLowerCase();\n return (\n v.includes('your') ||\n v.includes('replace') ||\n v.includes('example') ||\n v.includes('dummy') ||\n v.includes('changeme') ||\n v.includes('redacted')\n );\n}\n\nexport function stripNonAscii(text: string): string {\n return text.replace(/[^\\x00-\\x7F]/g, '');\n}\n\nexport function truncateText(text: string, maxLen: number): string {\n if (maxLen <= 0) return '';\n if (text.length <= maxLen) return text;\n return text.slice(0, maxLen) + '... (truncated)';\n}\n\nexport function maskSecret(value: string): string {\n if (value.length <= 8) return '*'.repeat(value.length);\n return value.slice(0, 4) + '...' + value.slice(-4);\n}\n\nexport function findSecretMatches(text: string, maxMatches: number = 50): SecretMatch[] {\n const matches: SecretMatch[] = [];\n\n for (const { kind, re } of SECRET_PATTERNS) {\n re.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n matches.push({ kind, value: m[0], index: m.index });\n if (matches.length >= maxMatches) return matches;\n }\n }\n\n SUSPICIOUS_ASSIGNMENT.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = SUSPICIOUS_ASSIGNMENT.exec(text)) !== null) {\n const kind = (m[1] || 'secret').toLowerCase();\n const value = m[3] || '';\n if (!looksLikePlaceholder(value)) {\n matches.push({ kind, value, index: m.index });\n if (matches.length >= maxMatches) return matches;\n }\n }\n\n return matches;\n}\n\nexport function redactText(text: string): string {\n let out = text;\n for (const { re } of SECRET_PATTERNS) {\n re.lastIndex = 0;\n out = out.replace(re, '[REDACTED]');\n }\n out = out.replace(/(Authorization\\s*:\\s*Bearer\\s+)[A-Za-z0-9._-]{16,}/gi, '$1[REDACTED]');\n return out;\n}\n\nexport function redactObjectDeep(input: unknown, depth: number = 0): unknown {\n if (depth > 6) return '[TRUNCATED]';\n if (input === null || input === undefined) return input;\n\n if (typeof input === 'string') {\n return redactText(input);\n }\n\n if (Array.isArray(input)) {\n return input.map((v) => redactObjectDeep(v, depth + 1));\n }\n\n if (typeof input === 'object') {\n const obj = input as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) {\n const key = k.toLowerCase();\n if (\n key.includes('token') ||\n key.includes('secret') ||\n key.includes('password') ||\n key.includes('authorization') ||\n key.endsWith('key') ||\n key.includes('webhook')\n ) {\n if (typeof v === 'string' && !looksLikePlaceholder(v)) {\n out[k] = '[REDACTED]';\n continue;\n }\n }\n out[k] = redactObjectDeep(v, depth + 1);\n }\n return out;\n }\n\n return input;\n}\n\nexport function redactForLog(input: unknown, maxLen: number = 10_000): string {\n let text: string;\n if (typeof input === 'string') {\n text = input;\n } else {\n try {\n text = JSON.stringify(redactObjectDeep(input));\n } catch {\n text = String(input);\n }\n }\n return truncateText(redactText(text), maxLen);\n}\n\nexport function redactForTrace(input: unknown, maxLen: number = 5_000): string {\n // Trace artifacts must be ASCII-only.\n return stripNonAscii(redactForLog(input, maxLen));\n}\n\n",
|
|
9
|
+
"import chalk from 'chalk';\nimport ora, { type Ora } from 'ora';\nimport { redactForLog, redactObjectDeep } from './redaction';\n\r\n/**\r\n * Logger for internal operational messages (errors, warnings, progress).\r\n *\r\n * IMPORTANT: For CLI command output (tables, lists, formatted data), use console.* instead.\r\n * See docs/development/logging-conventions.md for the full pattern.\r\n *\r\n * TL;DR:\r\n * - CLI output -> console.log() / console.error()\r\n * - Internal logging -> logger.*\r\n */\r\n\r\nexport enum LogLevel {\r\n DEBUG = 0,\r\n INFO = 1,\r\n WARN = 2,\r\n ERROR = 3,\r\n}\r\n\r\nexport interface ExecutionSummary {\r\n success: boolean;\r\n durationMs: number;\r\n tokensUsed?: number;\r\n toolCallCount?: number;\r\n}\r\n\r\n/**\r\n * Format a warning message with tool context and error details\r\n * In debug mode, shows full error; otherwise shows shortened version\r\n */\r\nexport function formatWarning(tool: string, operation: string, error: string, enableDebug: boolean = false): string {\r\n if (enableDebug) {\r\n // In debug mode, show full error with additional context\r\n const lines = error.split('\\n');\r\n const mainError = lines[0].replace(/^Error:\\s*/i, '').trim();\r\n \r\n let formatted = `${tool}: ${operation} failed - ${mainError}`;\r\n \r\n // Add additional lines if they exist and are meaningful\r\n if (lines.length > 1) {\r\n const additionalInfo = lines.slice(1)\r\n .map(line => line.trim())\r\n .filter(line => line.length > 0 && !line.match(/^\\s*at\\s+/)) // Skip stack trace lines\r\n .join(' | ');\r\n \r\n if (additionalInfo) {\r\n formatted += ` (${additionalInfo})`;\r\n }\r\n }\r\n \r\n return formatted;\r\n } else {\r\n // Normal mode: Take first line, remove common \"Error:\" prefix, trim whitespace, cap at 80 chars\r\n const cleanError = error\r\n .split('\\n')[0]\r\n .replace(/^Error:\\s*/i, '')\r\n .trim()\r\n .substring(0, 80);\r\n \r\n const reason = cleanError.length === 80 ? cleanError + '...' : cleanError;\r\n \r\n return `${tool}: ${operation} failed - ${reason}`;\r\n }\r\n}\r\n\r\nfunction isEnvDebugFlagEnabled(): boolean {\r\n const candidates = [process.env.PK_AGENT_DEBUG, process.env.DEBUG];\r\n return candidates.some(value => {\r\n if (!value) {\r\n return false;\r\n }\r\n const normalized = value.toLowerCase();\r\n return normalized === 'true' || normalized === '1';\r\n });\r\n}\r\n\r\nfunction isEnvNoTTYEnabled(): boolean {\r\n const value = process.env.NO_TTY;\r\n if (!value) return false;\r\n const normalized = value.toLowerCase();\r\n return normalized === 'true' || normalized === '1' || normalized === 'yes';\r\n}\r\n\r\nfunction isNoTTYArgPresent(): boolean {\r\n return process.argv?.some(arg => arg === '--no-tty' || arg === '--noTTY') ?? false;\r\n}\r\n\r\nfunction isQuietArgPresent(): boolean {\r\n return process.argv?.some(arg => arg === '--quiet' || arg === '-q') ?? false;\r\n}\r\n\r\n/**\r\n * Detect if running in a CI environment\r\n * CI environments may report isTTY incorrectly or have issues with ora spinners\r\n */\r\nfunction isCI(): boolean {\r\n return Boolean(\r\n process.env.CI ||\r\n process.env.GITHUB_ACTIONS ||\r\n process.env.GITLAB_CI ||\r\n process.env.CIRCLECI ||\r\n process.env.JENKINS_URL ||\r\n process.env.BUILDKITE ||\r\n process.env.TRAVIS ||\r\n process.env.TF_BUILD // Azure Pipelines\r\n );\r\n}\r\n\r\n// Log channels for future use\r\n// enum LogChannel {\r\n// RESPONSE = 'response',\r\n// ERROR = 'error',\r\n// WARNING = 'warning',\r\n// DEBUG = 'debug',\r\n// INFO = 'info',\r\n// SYSTEM = 'system',\r\n// }\r\n\r\n/**\r\n * Truncation budget for tool argument formatting\r\n */\r\nconst TRUNCATION_BUDGET = {\r\n // Never truncate these types\r\n neverTruncate: {\r\n filePath: true,\r\n url: true,\r\n id: true,\r\n },\r\n\r\n // Only truncate these\r\n truncate: {\r\n string: 100, // Regular strings\r\n object: {\r\n maxKeys: 3, // Show first 3 keys\r\n perKey: 40, // Chars per key-value in preview\r\n },\r\n array: {\r\n maxItems: 3, // Show first 3 items\r\n perItem: 30, // Chars per item in preview\r\n }\r\n },\r\n\r\n // Important field names - never truncate\r\n importantFields: new Set([\r\n 'id', 'key', 'page_id', 'parent_id', 'database_id',\r\n 'error', 'type', 'status', 'message', 'name', 'title'\r\n ])\r\n} as const;\r\n\r\n/**\r\n * Detect value type based on key name and content\r\n */\r\nfunction detectValueType(key: string, _value: string): 'filePath' | 'url' | 'id' | 'default' {\r\n const keyLower = key.toLowerCase();\r\n\r\n // File path detection\r\n if (keyLower.includes('path') || keyLower.includes('file') || keyLower.includes('dir')) {\r\n return 'filePath';\r\n }\r\n\r\n // URL detection\r\n if (keyLower.includes('url') || keyLower.includes('uri') || keyLower.includes('link')) {\r\n return 'url';\r\n }\r\n\r\n // ID detection\r\n if (keyLower.endsWith('_id') || keyLower.endsWith('id') || key === 'key') {\r\n return 'id';\r\n }\r\n\r\n return 'default';\r\n}\r\n\r\n/**\r\n * Format a string value with context-aware truncation\r\n */\r\nfunction formatStringValue(key: string, value: string): string {\r\n // Check if it's an important field - never truncate\r\n if (TRUNCATION_BUDGET.importantFields.has(key)) {\r\n return `\"${value}\"`;\r\n }\r\n\r\n const valueType = detectValueType(key, value);\r\n\r\n // Never truncate file paths, URLs, or IDs\r\n if (valueType === 'filePath' || valueType === 'url' || valueType === 'id') {\r\n return `\"${value}\"`;\r\n }\r\n\r\n // Truncate regular strings\r\n const limit = TRUNCATION_BUDGET.truncate.string;\r\n if (value.length <= limit) {\r\n return `\"${value}\"`;\r\n }\r\n\r\n return `\"${value.substring(0, limit)}...\"`;\r\n}\r\n\r\n/**\r\n * Format an object value showing structure preview\r\n */\r\nfunction formatObjectValue(obj: Record<string, any>): string {\r\n const keys = Object.keys(obj);\r\n\r\n if (keys.length === 0) {\r\n return '{}';\r\n }\r\n\r\n const maxKeys = TRUNCATION_BUDGET.truncate.object.maxKeys;\r\n const keyBudget = TRUNCATION_BUDGET.truncate.object.perKey;\r\n\r\n const preview = keys.slice(0, maxKeys).map(key => {\r\n const value = obj[key];\r\n let valueStr: string;\r\n\r\n if (value === null || value === undefined) {\r\n valueStr = String(value);\r\n } else if (typeof value === 'string') {\r\n valueStr = value.length > keyBudget\r\n ? `\"${value.substring(0, keyBudget)}...\"`\r\n : `\"${value}\"`;\r\n } else if (typeof value === 'number' || typeof value === 'boolean') {\r\n valueStr = String(value);\r\n } else if (Array.isArray(value)) {\r\n valueStr = `[${value.length}]`;\r\n } else if (typeof value === 'object') {\r\n // Nested objects - show key count\r\n const nestedKeys = Object.keys(value).length;\r\n valueStr = nestedKeys > 0 ? `{...${nestedKeys}}` : '{}';\r\n } else {\r\n valueStr = String(value);\r\n }\r\n\r\n return `${key}: ${valueStr}`;\r\n });\r\n\r\n const remaining = keys.length - maxKeys;\r\n\r\n if (remaining > 0) {\r\n return `{${preview.join(', ')}, ... +${remaining}}`;\r\n } else {\r\n return `{${preview.join(', ')}}`;\r\n }\r\n}\r\n\r\n/**\r\n * Format an array value showing preview\r\n */\r\nfunction formatArrayValue(arr: any[]): string {\r\n if (arr.length === 0) {\r\n return '[]';\r\n }\r\n\r\n const maxItems = TRUNCATION_BUDGET.truncate.array.maxItems;\r\n const itemBudget = TRUNCATION_BUDGET.truncate.array.perItem;\r\n\r\n const preview = arr.slice(0, maxItems).map(item => {\r\n if (item === null || item === undefined) {\r\n return String(item);\r\n } else if (typeof item === 'string') {\r\n return item.length > itemBudget\r\n ? `\"${item.substring(0, itemBudget)}...\"`\r\n : `\"${item}\"`;\r\n } else if (typeof item === 'number' || typeof item === 'boolean') {\r\n return String(item);\r\n } else if (typeof item === 'object' && !Array.isArray(item)) {\r\n // For objects in arrays, show compact preview\r\n const keys = Object.keys(item);\r\n if (keys.length > 0) {\r\n const firstKey = keys[0];\r\n const firstVal = item[firstKey];\r\n const valStr = typeof firstVal === 'string' && firstVal.length > 15\r\n ? `\"${firstVal.substring(0, 15)}...\"`\r\n : JSON.stringify(firstVal);\r\n return `{${firstKey}: ${valStr}}`;\r\n }\r\n return '{}';\r\n } else if (Array.isArray(item)) {\r\n return `[${item.length}]`;\r\n } else {\r\n return String(item);\r\n }\r\n });\r\n\r\n const remaining = arr.length - maxItems;\r\n\r\n if (remaining > 0) {\r\n return `[${preview.join(', ')}, ... +${remaining} (${arr.length} total)]`;\r\n } else {\r\n return `[${preview.join(', ')}]`;\r\n }\r\n}\r\n\r\n/**\r\n * Format a single parameter (key-value pair)\r\n */\r\nfunction formatParameter(key: string, value: any): string {\r\n let valueStr: string;\r\n\r\n if (value === null || value === undefined) {\r\n valueStr = String(value);\r\n } else if (typeof value === 'string') {\r\n valueStr = formatStringValue(key, value);\r\n } else if (Array.isArray(value)) {\r\n valueStr = formatArrayValue(value);\r\n } else if (typeof value === 'object') {\r\n valueStr = formatObjectValue(value);\r\n } else {\r\n valueStr = String(value);\r\n }\r\n\r\n return `${key}: ${valueStr}`;\r\n}\r\n\r\n/**\r\n * Format tool arguments with granular truncation\r\n */\r\nfunction formatToolArgsGranular(args: any, options?: { disableTruncation?: boolean }): string {\n if (options?.disableTruncation) {\n try {\n return redactForLog(typeof args === 'string' ? args : args, 10_000);\n } catch {\n return redactForLog(String(args), 10_000);\n }\n }\n\n if (!args || typeof args !== 'object' || Array.isArray(args)) {\n if (args) {\n // For non-object args, just stringify\n const argsStr = redactForLog(args, 200);\n return argsStr.length > 100 ? `${argsStr.substring(0, 100)}...` : argsStr;\n }\n return '';\n }\n\r\n const entries = Object.entries(args);\r\n if (entries.length === 0) {\r\n return '';\r\n }\r\n\r\n const formatted = entries.map(([key, value]) => formatParameter(key, value));\r\n\r\n return formatted.join(', ');\r\n}\n\nfunction indentLines(text: string, indent: string): string {\n return text\n .split(/\\r?\\n/g)\n .map((l) => (l.length ? indent + l : l))\n .join('\\n');\n}\n\ninterface LoggerOptions {\r\n level?: LogLevel;\r\n enableDebug?: boolean;\r\n disableTUI?: boolean;\r\n quiet?: boolean;\r\n audit?: boolean;\r\n}\r\n\r\n/**\r\n * Consolidated TUI (Terminal User Interface) state\r\n *\r\n * Manages all spinner and interactive terminal state in one place for easier debugging.\r\n *\r\n * State relationships:\r\n * - disableTUI: Permanent setting (from env/args/config) - if true, TUI is never used\r\n * - useTUI: Current computed state - true only if disableTUI=false AND all conditions met\r\n * - spinner: Active spinner instance, managed by useTUI state\r\n * - spinnerStoppedByOutput: Tracks if spinner was stopped by response streaming (prevents double-stop)\r\n * - activeLlmModel: Model name for current LLM spinner (used to update latency)\r\n */\r\ninterface TUIState {\r\n /** Permanent TUI disable setting (from env/args/config) */\r\n disableTUI: boolean;\r\n /** Current computed TUI state (recomputed on each refresh) */\r\n useTUI: boolean;\r\n /** Active ora spinner instance */\r\n spinner: Ora | null;\r\n /** Flag: spinner was stopped by streaming response output */\r\n spinnerStoppedByOutput: boolean;\r\n /** Model name for active LLM spinner (for latency updates) */\r\n activeLlmModel: string | null;\r\n}\r\n\r\nclass Logger {\r\n private level: LogLevel;\r\n private enableDebug: boolean;\r\n private quietMode: boolean;\r\n private auditMode: boolean;\r\n private captureBuffer: string[] = [];\r\n private isCapturing: boolean = false;\r\n\r\n /** Consolidated TUI state - all spinner and interactive terminal state */\r\n private tui: TUIState = {\r\n disableTUI: false,\r\n useTUI: false,\r\n spinner: null,\r\n spinnerStoppedByOutput: false,\r\n activeLlmModel: null,\r\n };\r\n\r\n constructor(options: LoggerOptions = {}) {\r\n const quietFromArgs = isQuietArgPresent();\r\n this.quietMode = options.quiet ?? quietFromArgs;\r\n this.level = options.level ?? (this.quietMode ? LogLevel.WARN : LogLevel.INFO);\r\n this.enableDebug = options.enableDebug ?? isEnvDebugFlagEnabled();\r\n this.auditMode = options.audit ?? (process.env.PK_AGENT_AUDIT === 'true' || process.env.PK_AGENT_AUDIT === '1');\r\n const noTTYRequested = options.disableTUI ?? (isEnvNoTTYEnabled() || isNoTTYArgPresent());\r\n this.tui.disableTUI = noTTYRequested;\r\n if (noTTYRequested) {\r\n this.forcePlainOutput();\r\n } else {\r\n this.refreshTUIState();\r\n }\r\n }\r\n\r\n private isDebugEnabled(): boolean {\r\n return this.enableDebug || isEnvDebugFlagEnabled();\r\n }\r\n\r\n private shouldUseTUI(): boolean {\r\n return !this.tui.disableTUI && !this.quietMode && !isCI() && process.stdout.isTTY && this.level <= LogLevel.INFO && !this.isDebugEnabled();\r\n }\r\n\r\n private isInfoEnabled(): boolean {\r\n return !this.quietMode && this.level <= LogLevel.INFO;\r\n }\r\n\r\n /**\r\n * Stop active spinner with optional persistence\r\n * Centralized spinner cleanup to avoid duplication\r\n *\r\n * @param persist - If true, spinner persists with '...' symbol; if false, spinner is cleared\r\n */\r\n private stopSpinner(persist: boolean = true) {\r\n if (!this.tui.spinner?.isSpinning) {\r\n return;\r\n }\r\n\r\n if (persist) {\r\n this.tui.spinner.stopAndPersist({ symbol: '...' });\r\n } else {\r\n this.tui.spinner.stop();\r\n }\r\n\r\n this.tui.spinner = null;\r\n }\r\n\r\n /**\r\n * Recompute TUI setting and stop any active spinner if TUI is disabled\r\n */\r\n private refreshTUIState() {\r\n // Re-evaluate in case NO_TTY env/argv was set after construction\r\n if (isEnvNoTTYEnabled() || isNoTTYArgPresent()) {\r\n this.tui.disableTUI = true;\r\n }\r\n\r\n const nextUseTUI = this.shouldUseTUI();\r\n if (this.tui.useTUI && !nextUseTUI) {\r\n this.stopSpinner(false);\r\n }\r\n this.tui.useTUI = nextUseTUI;\r\n }\r\n\r\n /**\r\n * Permanently switch to plain (non-TUI) mode for this process.\r\n * Stops any active spinner and prevents new ones from starting.\r\n */\r\n forcePlainOutput() {\r\n this.tui.disableTUI = true;\r\n this.tui.useTUI = false;\r\n this.stopSpinner(false);\r\n }\r\n\r\n /**\r\n * Format a tool name as a colored badge\r\n */\r\n private formatToolBadge(toolName: string, isSubAgent: boolean = false): string {\r\n const displayName = this.getToolDisplayName(toolName);\r\n\r\n if (!this.tui.useTUI) {\r\n return `[${displayName}]`; // Fallback for non-TTY\r\n }\r\n\r\n // Check prefix-based detection first, then fall back to isSubAgent flag\r\n if (toolName.startsWith('subagent__') || isSubAgent) {\r\n // Sub-agents: Magenta background, white text\r\n return chalk.bgMagenta.white.bold(` ${displayName} `);\r\n }\r\n\r\n if (toolName.startsWith('mcp__')) {\r\n // MCP tools: Cyan background, black text\r\n return chalk.bgCyan.black.bold(` ${displayName} `);\r\n }\r\n\r\n // Native tools: Blue background, white text\r\n return chalk.bgBlue.white.bold(` ${displayName} `);\r\n }\r\n\r\n private getToolDisplayName(toolName: string): string {\r\n if (toolName.startsWith('mcp__')) {\r\n const parts = toolName.split('__').slice(1);\r\n if (parts.length >= 2) {\r\n const [provider, ...rest] = parts;\r\n return `${provider}:${rest.join('__')} (MCP)`;\r\n }\r\n }\r\n if (toolName.startsWith('subagent__')) {\r\n const name = toolName.substring(10); // Remove 'subagent__' prefix\r\n return `${name} (Subagent)`;\r\n }\r\n return toolName;\r\n }\r\n\r\n /**\r\n * Get agent activity prefix\r\n */\r\n private getAgentPrefix(): string {\r\n return this.tui.useTUI ? '...' : '';\r\n }\r\n\r\n private formatLlmSpinnerText(model: string, latencyMs?: number): string {\r\n const badge = chalk.bgGreen.black.bold(' LLM ');\r\n const latencySuffix = latencyMs !== undefined\r\n ? chalk.gray(` * ${latencyMs >= 1000 ? `${(latencyMs / 1000).toFixed(1)}s` : `${Math.round(latencyMs)}ms`}`)\r\n : '';\r\n return ` ${badge} ${chalk.gray(model)}${latencySuffix}`;\r\n }\r\n\r\n configure(options: LoggerOptions) {\r\n if (options.level !== undefined) {\r\n this.level = options.level;\r\n }\r\n if (options.enableDebug !== undefined) {\r\n this.enableDebug = options.enableDebug;\r\n }\r\n if (options.audit !== undefined) {\r\n this.auditMode = options.audit;\r\n }\r\n if (options.disableTUI !== undefined) {\r\n this.tui.disableTUI = options.disableTUI;\r\n }\r\n if (options.quiet !== undefined) {\r\n this.quietMode = options.quiet;\r\n }\r\n // Update TUI setting based on new configuration\r\n if (this.tui.disableTUI) {\r\n this.forcePlainOutput();\r\n } else {\r\n this.refreshTUIState();\r\n }\r\n }\r\n\r\n startCapture() {\r\n this.isCapturing = true;\r\n this.captureBuffer = [];\r\n }\r\n\r\n stopCapture(): string {\r\n this.isCapturing = false;\r\n const output = this.captureBuffer.join('');\r\n this.captureBuffer = [];\r\n return output;\r\n }\r\n\r\n private capture(text: string) {\r\n if (this.isCapturing) {\r\n this.captureBuffer.push(text);\r\n }\r\n }\r\n\r\n private writeToStderr(message: string) {\r\n const output = message + '\\n';\r\n this.capture(output);\r\n process.stderr.write(output);\r\n }\r\n\r\n response(message: string) {\r\n // Stop spinner on first response output to avoid conflicts\r\n if (this.tui.spinner?.isSpinning && !this.tui.spinnerStoppedByOutput) {\r\n // LLM spinner should be cleared (not persisted) - it's just a loading indicator\r\n // The streaming response replaces it\r\n this.stopSpinner(false);\r\n this.tui.spinnerStoppedByOutput = true;\r\n this.tui.activeLlmModel = null;\r\n }\r\n\r\n // For streaming responses, don't add newline\r\n this.capture(message);\r\n process.stdout.write(message);\r\n }\r\n \r\n responseComplete() {\r\n // Add newline after complete response\r\n const newline = '\\n';\r\n this.capture(newline);\r\n process.stdout.write(newline);\r\n }\r\n\r\n error(message: string, error?: Error) {\r\n // Stop spinner before writing to avoid cursor conflicts\r\n this.stopSpinner(true);\r\n\r\n const prefix = this.getAgentPrefix();\r\n const badge = this.tui.useTUI ? chalk.bgRed.white.bold(' ERROR ') : '[ERROR]';\r\n const errorMessage = error ? `${message}: ${error.message}` : message;\r\n const formattedMessage = this.tui.useTUI\r\n ? `${prefix} ${badge} ${errorMessage}`\r\n : `${badge} ${errorMessage}`;\r\n\r\n this.writeToStderr(chalk.red(formattedMessage));\r\n if (error?.stack && this.isDebugEnabled()) {\r\n this.writeToStderr(chalk.gray(error.stack));\r\n }\r\n }\r\n\r\n warn(message: string) {\r\n if (this.level <= LogLevel.WARN) {\r\n // Stop spinner before writing to avoid cursor conflicts\r\n this.stopSpinner(true);\r\n\r\n const prefix = this.getAgentPrefix();\r\n const badge = this.tui.useTUI ? chalk.bgYellow.black.bold(' WARN ') : '[WARN]';\r\n const formattedMessage = this.tui.useTUI\r\n ? `${prefix} ${badge} ${message}`\r\n : `${badge} ${message}`;\r\n\r\n this.writeToStderr(chalk.yellow(formattedMessage));\r\n }\r\n }\r\n\r\n info(message: string) {\r\n if (this.isInfoEnabled()) {\r\n // Stop spinner before writing to avoid cursor conflicts\r\n this.stopSpinner(true);\r\n\r\n const prefix = this.getAgentPrefix();\r\n const badge = this.tui.useTUI ? chalk.bgBlue.white.bold(' INFO ') : '[INFO]';\r\n const formattedMessage = this.tui.useTUI\r\n ? `${prefix} ${badge} ${message}`\r\n : `\\n${badge} ${message}`;\r\n\r\n this.writeToStderr(chalk.blue(formattedMessage));\r\n }\r\n }\r\n\r\n debug(message: string) {\r\n if (this.isDebugEnabled() && this.level <= LogLevel.DEBUG) {\r\n this.writeToStderr(chalk.gray(`[DEBUG] ${message}`));\r\n }\r\n }\r\n\r\n /**\r\n * Format and log a warning with tool context\r\n * Automatically uses debug mode based on logger configuration\r\n */\r\n warnWithTool(tool: string, operation: string, error: string) {\r\n const formatted = formatWarning(tool, operation, error, this.isDebugEnabled());\r\n this.warn(formatted);\r\n }\r\n\r\n private isAuditEnabled(): boolean {\r\n return this.auditMode || process.env.PK_AGENT_AUDIT === 'true' || process.env.PK_AGENT_AUDIT === '1';\r\n }\r\n\r\n /**\r\n * Log tool result with formatting and optional timing/status\r\n */\r\n toolResult(result: string, options?: { duration?: number; success?: boolean; tokens?: number }) {\n this.refreshTUIState();\r\n\r\n // Stop spinner and persist the line\r\n this.stopSpinner(true);\r\n this.tui.spinnerStoppedByOutput = false;\r\n\r\n const debugMode = this.isDebugEnabled();\r\n const useTUI = this.tui.useTUI && !debugMode;\r\n\r\n // Format duration if provided\r\n let durationStr = '';\r\n if (options?.duration !== undefined) {\r\n const ms = options.duration;\r\n if (ms < 100) {\r\n durationStr = ` ${chalk.gray('')} ${chalk.gray(`${ms}ms`)}`;\r\n } else if (ms < 1000) {\r\n durationStr = ` ${chalk.gray(`${ms}ms`)}`;\r\n } else {\r\n durationStr = ` ${chalk.gray(`${(ms / 1000).toFixed(1)}s`)}`;\r\n }\r\n }\r\n\r\n // Format tokens if provided\r\n let tokensStr = '';\r\n if (options?.tokens !== undefined) {\r\n tokensStr = ` ${chalk.gray(`(${options.tokens.toLocaleString()} tokens)`)}`;\r\n }\r\n\r\n // Status icon\r\n const statusIcon = options?.success === false\r\n ? chalk.red('[X]')\r\n : options?.success === true\r\n ? chalk.green('[OK]')\r\n : chalk.gray('->');\r\n\r\n const auditMode = this.isAuditEnabled();\r\n\r\n // In audit mode, render multi-line output as a block to avoid mangling the UI.\r\n // Keep it bounded to avoid flooding the terminal.\r\n const MAX_RESULT_LENGTH = auditMode ? 10_000 : 100;\r\n const MAX_LINES = auditMode ? 80 : 1;\r\n\r\n const full = redactForLog(result ?? '', 10_000);\n const lines = full.split(/\\r?\\n/);\r\n const isMultiline = lines.length > 1;\r\n\r\n let headerText = full;\r\n if (!debugMode && headerText.length > MAX_RESULT_LENGTH) {\r\n headerText = headerText.substring(0, MAX_RESULT_LENGTH) + '...';\r\n }\r\n\r\n if (auditMode && isMultiline) {\r\n // Header: first line (trimmed) plus duration/tokens.\r\n const first = lines[0] ?? '';\r\n const header = ` ${statusIcon} ${first}${durationStr}${tokensStr}`;\r\n this.writeToStderr(header);\r\n\r\n const bodyLines = lines.slice(1);\r\n const shown = bodyLines.slice(0, MAX_LINES);\r\n for (const l of shown) {\r\n this.writeToStderr(chalk.gray(` | ${l}`));\r\n }\r\n if (bodyLines.length > shown.length) {\r\n this.writeToStderr(chalk.gray(` | ... (${bodyLines.length - shown.length} more lines)`));\r\n }\r\n return;\r\n }\r\n\r\n const line = ` ${statusIcon} ${headerText}${durationStr}${tokensStr}`;\r\n\r\n if (!useTUI) {\r\n this.writeToStderr(line);\r\n return;\r\n }\r\n\r\n this.writeToStderr(line);\r\n }\r\n\r\n system(message: string) {\r\n this.writeToStderr(chalk.magenta(`[SYSTEM] ${message}`));\r\n }\r\n\r\n /**\r\n * Start LLM spinner in TUI mode or log a message in non-TUI mode\r\n * Displays the model name and starts tracking for first-token latency\r\n * @param model - The name of the LLM model being called (e.g., \"claude-sonnet-4\")\r\n */\r\n llmStart(model: string) {\r\n this.refreshTUIState();\r\n\r\n // Stop any existing spinner - just clear it, don't persist\r\n // LLM spinners are loading indicators, not permanent output\r\n this.stopSpinner(false);\r\n\r\n this.tui.activeLlmModel = null;\r\n this.tui.spinnerStoppedByOutput = false;\r\n const debugMode = this.isDebugEnabled();\r\n const useTUI = this.tui.useTUI && !debugMode;\r\n\r\n if (useTUI) {\r\n let text = this.formatLlmSpinnerText(model);\r\n\r\n const MAX_LINE_LENGTH = 140;\r\n if (text.length > MAX_LINE_LENGTH) {\r\n text = text.substring(0, MAX_LINE_LENGTH - 3) + '...';\r\n }\r\n\r\n this.tui.spinner = ora({\n text,\n stream: process.stderr,\n spinner: {\n interval: 90,\n frames: ['|', '/', '-', '\\\\']\n },\n isEnabled: useTUI\n }).start();\n\r\n this.capture(`${this.getAgentPrefix()}${text}\\n`);\r\n this.tui.activeLlmModel = model;\r\n } else {\r\n // In non-TUI mode, just log to debug (model already in metadata)\r\n this.debug(`Calling model: ${model}`);\r\n this.tui.activeLlmModel = null;\r\n }\r\n\r\n }\r\n\r\n /**\r\n * Update LLM spinner with first-token latency\r\n * Called after receiving the first token from the LLM to display response time\r\n * @param model - The name of the LLM model\r\n * @param latencyMs - Time in milliseconds from request start to first token\r\n */\r\n llmFirstToken(model: string, latencyMs: number) {\r\n if (!this.tui.spinner?.isSpinning || this.tui.activeLlmModel !== model) {\r\n return;\r\n }\r\n\r\n let text = this.formatLlmSpinnerText(model, latencyMs);\r\n const MAX_LINE_LENGTH = 140;\r\n if (text.length > MAX_LINE_LENGTH) {\r\n text = text.substring(0, MAX_LINE_LENGTH - 3) + '...';\r\n }\r\n\r\n this.tui.spinner.text = text;\r\n }\r\n\r\n /**\r\n * Format built-in tool display for cleaner output\r\n * Returns { badge, detail } for TUI mode or { displayText } for non-TUI mode\r\n */\r\n private formatBuiltinTool(name: string, args: unknown, useTUI: boolean): { badge: string; detail: string } | null {\r\n const argsObj = args as Record<string, unknown>;\r\n\r\n // Skill load tool\r\n if (name === 'tools__skill_load' && argsObj?.name) {\r\n const badge = useTUI ? chalk.bgMagenta.white.bold(' Skill ') : 'Skill';\r\n return { badge, detail: `Loading \"${argsObj.name}\"` };\r\n }\r\n\r\n // Skill read tool\r\n if (name === 'tools__skill_read' && argsObj?.skill && argsObj?.path) {\r\n const badge = useTUI ? chalk.bgMagenta.white.bold(' Skill ') : 'Skill';\r\n return { badge, detail: `Reading \"${argsObj.path}\" from \"${argsObj.skill}\"` };\r\n }\r\n\r\n // Bash tool\r\n if (name === 'tools__bash' && argsObj?.command) {\r\n const badge = useTUI ? chalk.bgYellow.black.bold(' Bash ') : 'Bash';\r\n const cmd = String(argsObj.command);\r\n // Truncate long commands\r\n const truncatedCmd = cmd.length > 80 ? cmd.substring(0, 80) + '...' : cmd;\r\n return { badge, detail: truncatedCmd };\r\n }\r\n\r\n // Read tool\r\n if (name === 'tools__filesystem_read' && argsObj?.file_path) {\r\n const badge = useTUI ? chalk.bgGreen.black.bold(' Read ') : 'Read';\r\n return { badge, detail: String(argsObj.file_path) };\r\n }\r\n\r\n // Write tool\r\n if (name === 'tools__filesystem_write' && argsObj?.file_path) {\r\n const badge = useTUI ? chalk.bgBlue.white.bold(' Write ') : 'Write';\r\n return { badge, detail: String(argsObj.file_path) };\r\n }\r\n\r\n // Edit tool\r\n if (name === 'tools__filesystem_edit' && argsObj?.file_path) {\r\n const badge = useTUI ? chalk.bgCyan.black.bold(' Edit ') : 'Edit';\r\n return { badge, detail: String(argsObj.file_path) };\r\n }\r\n\r\n return null;\r\n }\r\n\r\n tool(name: string, args?: unknown, result?: unknown, isSubAgent?: boolean) {\n this.refreshTUIState();\r\n\r\n // Only show when tool is being called, not when returning results\r\n if (args !== undefined) {\r\n // Stop any existing spinner and persist the line\r\n this.stopSpinner(true);\r\n\r\n this.tui.activeLlmModel = null;\r\n\r\n // Reset flag for new tool execution\r\n this.tui.spinnerStoppedByOutput = false;\r\n\r\n const debugMode = this.isDebugEnabled();\r\n const useTUI = this.tui.useTUI && !debugMode;\r\n\r\n // Try to format as built-in tool first\r\n const builtinFormat = this.formatBuiltinTool(name, args, useTUI);\r\n\r\n // Format with new TUI style\r\n if (useTUI) {\r\n let text: string;\r\n\r\n if (builtinFormat) {\r\n text = ` ${builtinFormat.badge} ${chalk.gray(builtinFormat.detail)}`;\r\n } else {\r\n // Format args with granular truncation for non-builtin tools\r\n let argsDisplay = '';\r\n if (args) {\r\n const formatted = formatToolArgsGranular(args, { disableTruncation: debugMode });\r\n if (formatted) {\r\n argsDisplay = ` ${chalk.gray(formatted)}`;\r\n }\r\n }\r\n const badge = this.formatToolBadge(name, isSubAgent);\r\n text = ` ${badge}${argsDisplay}`;\r\n }\r\n\r\n // Truncate to prevent terminal wrapping (which causes duplicate lines)\r\n // Symbol (1) + space (2) + text = total line length\r\n // Leave room for terminal width variations (use 140 chars as safe limit)\r\n const MAX_LINE_LENGTH = 140;\r\n if (text.length > MAX_LINE_LENGTH) {\r\n text = text.substring(0, MAX_LINE_LENGTH - 3) + '...';\r\n }\r\n\r\n // Create and start ora spinner\r\n this.tui.spinner = ora({\r\n text,\r\n stream: process.stderr,\r\n spinner: {\r\n interval: 120,\r\n frames: ['...', '...', '...', '...']\r\n },\r\n isEnabled: useTUI\r\n }).start();\r\n\r\n // Capture for testing/debugging (include prefix for logging)\r\n this.capture(`${this.getAgentPrefix()}${text}\\n`);\r\n } else {\r\n // Fallback for non-TTY\r\n if (builtinFormat) {\r\n this.info(`${builtinFormat.badge}: ${chalk.cyan(builtinFormat.detail)}`);\r\n } else {\r\n // Format args with granular truncation for non-builtin tools\r\n let argsDisplay = '';\r\n if (args) {\r\n const formatted = formatToolArgsGranular(args, { disableTruncation: debugMode });\r\n if (formatted) {\r\n argsDisplay = ` ${chalk.gray(formatted)}`;\r\n }\r\n }\r\n const callType = (name.startsWith('subagent__') || isSubAgent) ? 'Calling subagent:' : 'Calling tool:';\r\n const displayName = this.getToolDisplayName(name);\r\n this.info(`${callType} ${chalk.cyan(displayName)}${argsDisplay}`);\r\n }\r\n }\r\n\r\n // Show full args in debug or audit mode\n if (debugMode) {\n try {\n this.writeToStderr(chalk.gray(`[DEBUG] Tool parameters: ${redactForLog(args)}`));\n } catch {\n this.writeToStderr(chalk.gray(`[DEBUG] Tool parameters: ${redactForLog(String(args))}`));\n }\n } else if (this.isAuditEnabled()) {\n // Audit mode is intended for real-time verification. Keep output readable and redacted.\n try {\n const json = JSON.stringify(redactObjectDeep(args), null, 2);\n this.writeToStderr(chalk.gray('[AUDIT] Tool parameters:\\n' + indentLines(json, ' ')));\n } catch {\n this.writeToStderr(chalk.gray(`[AUDIT] Tool parameters: ${redactForLog(String(args))}`));\n }\n }\n } else if (result !== undefined) {\n const debugMode = this.isDebugEnabled();\n if (debugMode) {\n const resultStr = redactForLog(result);\n this.writeToStderr(chalk.gray(`[DEBUG] Tool ${name} result: ${resultStr}`));\n } else if (this.isAuditEnabled()) {\n const resultStr = redactForLog(result, 10_000);\n const multiline = resultStr.includes('\\n');\n if (multiline) {\n this.writeToStderr(chalk.gray('[AUDIT] Tool result:\\n' + indentLines(resultStr, ' ')));\n } else {\n this.writeToStderr(chalk.gray(`[AUDIT] Tool result: ${resultStr}`));\n }\n }\n }\n }\n\r\n /**\r\n * Print a thin horizontal separator line\r\n */\r\n separator() {\r\n if (!this.isInfoEnabled()) {\r\n return;\r\n }\r\n\r\n this.refreshTUIState();\r\n\r\n // Stop any existing spinner before printing separator\r\n this.stopSpinner(true);\r\n\r\n const line = '-'.repeat(50);\r\n const output = this.tui.useTUI ? chalk.gray(line) : line;\r\n this.writeToStderr(output);\r\n }\r\n\r\n /**\r\n * Print execution summary with timing and token info\r\n */\r\n summary(data: ExecutionSummary) {\r\n if (!this.isInfoEnabled()) {\r\n return;\r\n }\r\n\r\n this.refreshTUIState();\r\n\r\n // Stop any existing spinner\r\n this.stopSpinner(true);\r\n\r\n const icon = data.success ? chalk.green('[OK]') : chalk.red('[X]');\r\n const status = data.success ? 'Completed' : 'Failed';\r\n\r\n // Format duration\r\n let durationStr: string;\r\n if (data.durationMs < 1000) {\r\n durationStr = `${Math.round(data.durationMs)}ms`;\r\n } else {\r\n durationStr = `${(data.durationMs / 1000).toFixed(1)}s`;\r\n }\r\n\r\n // Build summary parts\r\n const parts = [`${status} in ${durationStr}`];\r\n\r\n if (data.tokensUsed !== undefined) {\r\n parts.push(`${data.tokensUsed.toLocaleString()} tokens`);\r\n }\r\n\r\n if (data.toolCallCount !== undefined && data.toolCallCount > 0) {\r\n parts.push(`${data.toolCallCount} tool call${data.toolCallCount === 1 ? '' : 's'}`);\r\n }\r\n\r\n const message = `${icon} ${parts.join(' * ')}`;\r\n this.writeToStderr(message);\r\n }\r\n\r\n /**\r\n * Print grouped metadata lines (key: value format)\r\n */\r\n metadata(lines: string[]) {\r\n // Stop any existing spinner\r\n this.stopSpinner(true);\r\n\r\n for (const line of lines) {\r\n this.writeToStderr(line);\r\n }\r\n }\r\n\r\n /**\r\n * Print grouped warnings as a block\r\n */\r\n groupedWarnings(warnings: string[]) {\r\n if (warnings.length === 0) return;\r\n\r\n // Stop any existing spinner\r\n this.stopSpinner(true);\r\n\r\n const icon = chalk.yellow('WARNING');\r\n const count = warnings.length;\r\n const header = `${icon} ${count} warning${count === 1 ? '' : 's'}:`;\r\n\r\n this.writeToStderr(header);\r\n for (const warning of warnings) {\r\n this.writeToStderr(chalk.yellow(` * ${warning}`));\r\n }\r\n }\r\n}\r\n\r\n// Use globalThis to ensure singleton across bundler chunks\r\nconst LOGGER_SYMBOL = Symbol.for('pk-agent.logger');\r\n\r\nfunction getOrCreateLogger(): Logger {\r\n const globalAny = globalThis as any;\r\n if (!globalAny[LOGGER_SYMBOL]) {\r\n globalAny[LOGGER_SYMBOL] = new Logger({\r\n level: process.env.LOG_LEVEL ?\r\n (LogLevel[process.env.LOG_LEVEL as keyof typeof LogLevel] ?? LogLevel.INFO) :\r\n LogLevel.INFO,\r\n enableDebug: isEnvDebugFlagEnabled(),\r\n disableTUI: process.env.NO_TTY === 'true',\r\n });\r\n }\r\n return globalAny[LOGGER_SYMBOL];\r\n}\r\n\r\nexport const logger = getOrCreateLogger();\r\n\r\n/**\r\n * Utility functions for agent execution logging (used by serve and scheduler)\r\n */\r\nexport const executionLog = {\r\n formatTimestamp(): string {\r\n const now = new Date();\r\n return `[${now.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' })}]`;\r\n },\r\n\r\n formatDuration(ms: number): string {\r\n if (ms < 1000) return `${ms}ms`;\r\n const seconds = Math.round(ms / 1000);\r\n return `${seconds}s`;\r\n },\r\n\r\n start(agentPath: string): void {\r\n console.log(`${this.formatTimestamp()} ${chalk.cyan('Starting:')} ${agentPath}`);\r\n },\r\n\r\n complete(agentPath: string, durationMs: number): void {\r\n console.log(`${this.formatTimestamp()} ${chalk.green('Completed:')} ${agentPath} (${this.formatDuration(durationMs)})`);\r\n },\r\n\r\n failed(agentPath: string, durationMs: number, error?: string): void {\r\n const errorSuffix = error ? ` - ${error}` : '';\r\n console.log(`${this.formatTimestamp()} ${chalk.red('Failed:')} ${agentPath} (${this.formatDuration(durationMs)})${errorSuffix}`);\r\n },\r\n\r\n timeout(agentPath: string, durationMs: number): void {\r\n console.log(`${this.formatTimestamp()} ${chalk.red('Timeout:')} ${agentPath} (${this.formatDuration(durationMs)})`);\r\n },\r\n};\r\n",
|
|
10
|
+
"/**\n * Shared string normalization helpers.\n *\n * NOTE: Keep ASCII-only (repo policy).\n */\n\n/**\n * Sanitize an agent name for safe use in filesystem paths.\n * Converts to lowercase and replaces invalid characters with hyphens.\n */\nexport function sanitizeAgentName(name: string): string {\n if (!name || name.trim() === '') {\n return 'default';\n }\n\n return (\n name\n .toLowerCase()\n .replace(/[^a-z0-9-_]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n || 'default'\n );\n}\n\n",
|
|
11
|
+
"import path from 'path';\nimport os from 'os';\nimport crypto from 'crypto';\nimport { sanitizeAgentName as sanitizeAgentNameImpl } from '../utils/names';\n\n/**\n * Get XDG data directory (using Linux XDG conventions on all platforms)\n * Returns ~/.local/share or $XDG_DATA_HOME if set\n */\nexport function getXdgDataDir(): string {\n return process.env.XDG_DATA_HOME || path.join(os.homedir(), '.local', 'share');\n}\n\n/**\n * Get git root directory if in a git repo\n */\nexport async function getGitRoot(cwd: string): Promise<string | null> {\n try {\n const { execSync } = await import('child_process');\n const gitRoot = execSync('git rev-parse --show-toplevel', {\n cwd,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'ignore']\n }).trim();\n return gitRoot;\n } catch {\n return null;\n }\n}\n\n/**\n * Get project directory based on git root or global\n * Returns: {xdgData}/pk-agent/project/{git-hash} or {xdgData}/pk-agent/project/global\n */\nexport async function getProjectDir(projectRoot: string): Promise<string> {\n const baseDir = path.join(getXdgDataDir(), 'pk-agent', 'project');\n\n const gitRoot = await getGitRoot(projectRoot);\n\n if (gitRoot) {\n // Hash git root for directory name\n const hash = crypto.createHash('sha256')\n .update(gitRoot)\n .digest('hex')\n .substring(0, 16);\n return path.join(baseDir, hash);\n } else {\n // Use global for non-git projects\n return path.join(baseDir, 'global');\n }\n}\n\n/**\n * Get session storage directory\n * Returns: {xdgData}/pk-agent/project/{git-hash}/session\n */\nexport async function getSessionStorageDir(projectRoot: string): Promise<string> {\n const projectDir = await getProjectDir(projectRoot);\n return path.join(projectDir, 'session');\n}\n\n/**\n * Sanitize agent name for use in filesystem paths\n * Converts to lowercase and replaces invalid characters with hyphens\n */\nexport function sanitizeAgentName(name: string): string {\n return sanitizeAgentNameImpl(name);\n}\n",
|
|
12
|
+
"import { mkdirSync } from 'fs';\nimport { homedir } from 'os';\nimport { join } from 'path';\n\nexport interface EnsurePkAgentDirsOptions {\n homeDir?: string | undefined;\n}\n\nfunction safeMkdir(dir: string): void {\n try {\n mkdirSync(dir, { recursive: true });\n } catch {\n // Best-effort: directory creation should not hard-fail the CLI.\n // Callers that require these dirs should surface a clearer error later.\n }\n}\n\nexport function ensurePkAgentUserDirs(opts?: EnsurePkAgentDirsOptions): string {\n const home = opts?.homeDir ?? homedir();\n const base = join(home, '.pk-agent');\n\n // Create base and standard subdirs for user scope.\n safeMkdir(base);\n safeMkdir(join(base, 'agents'));\n safeMkdir(join(base, 'skills'));\n safeMkdir(join(base, 'plugins'));\n safeMkdir(join(base, 'cache'));\n safeMkdir(join(base, 'cache', 'mcp-tools'));\n\n return base;\n}\n\nexport function ensurePkAgentProjectDirs(projectRoot: string): string {\n const base = join(projectRoot, '.pk-agent');\n\n // Create base and standard subdirs for project scope.\n safeMkdir(base);\n safeMkdir(join(base, 'agents'));\n safeMkdir(join(base, 'skills'));\n safeMkdir(join(base, 'plugins'));\n safeMkdir(join(base, 'runs'));\n\n return base;\n}\n\n/**\n * Ensure pk-agent's expected directory layout exists.\n *\n * Creation order is USER first, PROJECT second.\n */\nexport function ensurePkAgentDirs(projectRoot: string, opts?: EnsurePkAgentDirsOptions): {\n userBase: string;\n projectBase: string;\n} {\n const userBase = ensurePkAgentUserDirs(opts);\n const projectBase = ensurePkAgentProjectDirs(projectRoot);\n return { userBase, projectBase };\n}\n\n",
|
|
13
|
+
"import * as path from 'path';\r\nimport * as fs from 'fs';\r\nimport * as os from 'os';\r\nimport { minimatch } from 'minimatch';\r\nimport type { FilesystemPathConfig, FilesystemPermission, PathValidationResult } from './types.js';\r\n\r\n// Sensitive file patterns that are blocked by default\r\nconst SENSITIVE_FILE_PATTERNS = [\r\n // Environment files with secrets\r\n '.env',\r\n '.env.local',\r\n '.env.development',\r\n '.env.production',\r\n '.env.staging',\r\n '.env.*',\r\n];\r\n\r\n// Exceptions to sensitive file patterns (safe to read)\r\nconst SENSITIVE_FILE_EXCEPTIONS = [\r\n '.env.sample',\r\n '.env.example',\r\n '.env.template',\r\n '.env.defaults',\r\n];\r\n\r\nexport interface PathResolverContext {\r\n projectRoot: string;\r\n agentDir?: string | undefined;\r\n tmpDir?: string | undefined;\r\n}\r\n\r\n/**\r\n * Resolve a path to its real path, following symlinks.\r\n * Handles macOS /var -> /private/var and similar symlinks.\r\n * For non-existent paths, resolves the nearest existing ancestor directory.\r\n */\r\nexport function resolveRealPath(inputPath: string): string {\r\n try {\r\n // For existing paths, resolve symlinks directly\r\n return fs.realpathSync(inputPath);\r\n } catch {\r\n // For non-existing paths, traverse up to find the nearest existing ancestor\r\n const parts: string[] = [];\r\n let current = inputPath;\r\n\r\n while (current !== path.dirname(current)) {\r\n parts.unshift(path.basename(current));\r\n current = path.dirname(current);\r\n\r\n try {\r\n const realAncestor = fs.realpathSync(current);\r\n return path.join(realAncestor, ...parts);\r\n } catch {\r\n // Keep traversing up\r\n }\r\n }\r\n\r\n // Reached root without finding an existing ancestor\r\n return inputPath;\r\n }\r\n}\r\n\r\n/**\r\n * Resolve safe variable placeholders in a string.\r\n * Only resolves ${root}, ${agentDir}, ${tmpDir} - NOT ${env:*} to prevent secret exposure.\r\n *\r\n * @param text The text that may contain variable placeholders\r\n * @param context Path resolver context with projectRoot, agentDir, and tmpDir\r\n * @returns The text with safe variables resolved\r\n */\r\nexport function resolveSafeVariables(text: string, context: PathResolverContext): string {\r\n const tmpDir = resolveRealPath(context.tmpDir ?? os.tmpdir());\r\n let result = text\r\n .replace(/\\$\\{root\\}/g, context.projectRoot)\r\n .replace(/\\$\\{tmpDir\\}/g, tmpDir);\r\n\r\n // Only replace ${agentDir} if it's defined\r\n if (context.agentDir) {\r\n result = result.replace(/\\$\\{agentDir\\}/g, context.agentDir);\r\n }\r\n\r\n return result;\r\n}\r\n\r\nexport class PathValidator {\r\n private readonly projectRoot: string;\r\n private readonly agentDir: string | undefined;\r\n private readonly tmpDir: string;\r\n private readonly configs: FilesystemPathConfig[];\r\n\r\n constructor(configs: FilesystemPathConfig[], context: PathResolverContext) {\r\n this.configs = configs;\r\n this.projectRoot = context.projectRoot;\r\n this.agentDir = context.agentDir;\r\n this.tmpDir = resolveRealPath(context.tmpDir ?? os.tmpdir());\r\n }\r\n\r\n /**\r\n * Resolve variable placeholders in a path pattern\r\n * Supported: ${root}, ${agentDir}, ${tmpDir}, ~\r\n */\r\n private resolveVariables(pattern: string): string {\r\n let result = pattern\r\n .replace(/\\$\\{root\\}/g, this.projectRoot)\r\n .replace(/\\$\\{tmpDir\\}/g, this.tmpDir)\r\n .replace(/^~/, os.homedir());\r\n\r\n // Only replace ${agentDir} if it's defined\r\n if (this.agentDir) {\r\n result = result.replace(/\\$\\{agentDir\\}/g, this.agentDir);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Resolve a file path to absolute, normalized form\r\n */\r\n resolvePath(filePath: string): string {\r\n // Handle ~ for home directory\r\n if (filePath.startsWith('~')) {\r\n filePath = filePath.replace(/^~/, os.homedir());\r\n }\r\n\r\n // Resolve to absolute path\r\n const absolutePath = path.isAbsolute(filePath)\r\n ? filePath\r\n : path.resolve(this.projectRoot, filePath);\r\n\r\n // Normalize to remove . and ..\r\n return path.normalize(absolutePath);\r\n }\r\n\r\n /**\r\n * Check if a file is a sensitive file that should be blocked\r\n */\r\n private isSensitiveFile(filePath: string): boolean {\r\n const basename = path.basename(filePath);\r\n\r\n // Check if it's an exception (safe files)\r\n for (const exception of SENSITIVE_FILE_EXCEPTIONS) {\r\n if (basename === exception || basename.toLowerCase() === exception.toLowerCase()) {\r\n return false;\r\n }\r\n }\r\n\r\n // Check if it matches sensitive patterns\r\n for (const pattern of SENSITIVE_FILE_PATTERNS) {\r\n if (pattern.includes('*')) {\r\n // Wildcard pattern\r\n if (minimatch(basename, pattern, { dot: true })) {\r\n return true;\r\n }\r\n } else {\r\n // Exact match\r\n if (basename === pattern || basename.toLowerCase() === pattern.toLowerCase()) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Resolve symlinks to get the real path\r\n */\r\n private resolveSymlinks(filePath: string): string {\r\n try {\r\n // For existing files, resolve symlinks\r\n return fs.realpathSync(filePath);\r\n } catch {\r\n // For non-existing files (write), resolve parent directory\r\n const dir = path.dirname(filePath);\r\n try {\r\n const realDir = fs.realpathSync(dir);\r\n return path.join(realDir, path.basename(filePath));\r\n } catch {\r\n // Parent doesn't exist either, return as-is\r\n return filePath;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Check if a path matches a pattern.\r\n * - If pattern has no glob chars (*, ?, [): uses containment (path is within directory)\r\n * - If pattern has glob chars: uses glob matching via minimatch\r\n */\r\n private matchesPattern(filePath: string, pattern: string): boolean {\r\n const resolvedPattern = this.resolveVariables(pattern);\r\n\r\n // Normalize both for consistent matching\r\n const normalizedPath = path.normalize(filePath);\r\n const normalizedPattern = path.normalize(resolvedPattern);\r\n\r\n // If no glob characters, use containment (industry standard: path = path/**)\r\n // Note: only check for actual glob chars (*, ?, [) - NOT backslash which is\r\n // a path separator on Windows\r\n if (!/[*?\\[]/.test(normalizedPattern)) {\r\n const relative = path.relative(normalizedPattern, normalizedPath);\r\n return !relative.startsWith('..') && !path.isAbsolute(relative);\r\n }\r\n\r\n // minimatch requires forward slashes - convert Windows backslashes\r\n const forwardPath = normalizedPath.replace(/\\\\/g, '/');\r\n const forwardPattern = normalizedPattern.replace(/\\\\/g, '/');\r\n\r\n // Otherwise use glob matching\r\n return minimatch(forwardPath, forwardPattern, {\r\n dot: true, // Match dotfiles\r\n matchBase: false, // Don't match basename only\r\n nocase: process.platform === 'darwin' || process.platform === 'win32', // Case-insensitive on macOS/Windows\r\n });\r\n }\r\n\r\n /**\r\n * Find all patterns that match a path and have the required permission\r\n */\r\n private findMatchingConfigs(\r\n filePath: string,\r\n permission: FilesystemPermission\r\n ): { config: FilesystemPathConfig; pattern: string }[] {\r\n const matches: { config: FilesystemPathConfig; pattern: string }[] = [];\r\n\r\n for (const config of this.configs) {\r\n if (!config.permissions.includes(permission)) {\r\n continue;\r\n }\r\n\r\n const patterns = config.paths ?? (config.path ? [config.path] : []);\r\n\r\n for (const pattern of patterns) {\r\n if (this.matchesPattern(filePath, pattern)) {\r\n matches.push({ config, pattern });\r\n }\r\n }\r\n }\r\n\r\n return matches;\r\n }\r\n\r\n /**\r\n * Validate if a path is allowed for the given operation\r\n */\r\n validate(\r\n filePath: string,\r\n operation: FilesystemPermission\r\n ): PathValidationResult {\r\n // Resolve the path to absolute form\r\n const resolvedPath = this.resolvePath(filePath);\r\n\r\n // Resolve symlinks to prevent symlink-based escapes\r\n const realPath = this.resolveSymlinks(resolvedPath);\r\n\r\n // Check for sensitive files (e.g., .env)\r\n if (this.isSensitiveFile(realPath)) {\r\n return {\r\n allowed: false,\r\n resolvedPath: realPath,\r\n error: `Access denied: '${path.basename(realPath)}' is a sensitive file that may contain secrets`,\r\n };\r\n }\r\n\r\n // If no configs, nothing is allowed\r\n if (this.configs.length === 0) {\r\n return {\r\n allowed: false,\r\n resolvedPath: realPath,\r\n error: 'No filesystem paths configured',\r\n };\r\n }\r\n\r\n // Find matching patterns with required permission\r\n const matches = this.findMatchingConfigs(realPath, operation);\r\n\r\n if (matches.length === 0) {\r\n // Check if path matches any pattern (wrong permission)\r\n const allPatterns = this.configs.flatMap(c => c.paths ?? (c.path ? [c.path] : []));\r\n const matchesAnyPattern = allPatterns.some(p => this.matchesPattern(realPath, p));\r\n\r\n if (matchesAnyPattern) {\r\n return {\r\n allowed: false,\r\n resolvedPath: realPath,\r\n error: `Permission denied: '${operation}' not allowed for this path`,\r\n };\r\n }\r\n\r\n return {\r\n allowed: false,\r\n resolvedPath: realPath,\r\n error: `Path not in allowed directories: ${realPath}`,\r\n };\r\n }\r\n\r\n return {\r\n allowed: true,\r\n resolvedPath: realPath,\r\n matchedPattern: matches[0].pattern,\r\n };\r\n }\r\n\r\n /**\r\n * Get all configured patterns for a specific permission\r\n */\r\n getPatternsForPermission(permission: FilesystemPermission): string[] {\r\n const patterns: string[] = [];\r\n\r\n for (const config of this.configs) {\r\n if (config.permissions.includes(permission)) {\r\n const configPatterns = config.paths ?? (config.path ? [config.path] : []);\r\n patterns.push(...configPatterns.map(p => this.resolveVariables(p)));\r\n }\r\n }\r\n\r\n return patterns;\r\n }\r\n}\r\n",
|
|
14
|
+
"/**\n * Fuzzy string replacement strategies for edit tool\n *\n * These replacers try progressively fuzzier matching strategies to find\n * the old_string in the content. This helps recover from common LLM errors\n * like whitespace differences, indentation issues, etc.\n *\n * Inspired by opencode's edit.ts implementation.\n */\n\nexport type Replacer = (content: string, find: string) => Generator<string, void, unknown>;\n\n/**\n * Levenshtein distance for fuzzy matching\n */\nfunction levenshtein(a: string, b: string): number {\n if (a === '' || b === '') {\n return Math.max(a.length, b.length);\n }\n const matrix = Array.from({ length: a.length + 1 }, (_, i) =>\n Array.from({ length: b.length + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0)),\n );\n\n for (let i = 1; i <= a.length; i++) {\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);\n }\n }\n return matrix[a.length][b.length];\n}\n\n// Similarity thresholds for block anchor fallback matching\nconst SINGLE_CANDIDATE_SIMILARITY_THRESHOLD = 0.0;\nconst MULTIPLE_CANDIDATES_SIMILARITY_THRESHOLD = 0.3;\n\n/**\n * Exact match - tries to find the exact string\n */\nexport const SimpleReplacer: Replacer = function* (_content, find) {\n yield find;\n};\n\n/**\n * Line-trimmed matching - matches lines with trimmed whitespace\n */\nexport const LineTrimmedReplacer: Replacer = function* (content, find) {\n const originalLines = content.split('\\n');\n const searchLines = find.split('\\n');\n\n if (searchLines[searchLines.length - 1] === '') {\n searchLines.pop();\n }\n\n for (let i = 0; i <= originalLines.length - searchLines.length; i++) {\n let matches = true;\n\n for (let j = 0; j < searchLines.length; j++) {\n const originalTrimmed = originalLines[i + j].trim();\n const searchTrimmed = searchLines[j].trim();\n\n if (originalTrimmed !== searchTrimmed) {\n matches = false;\n break;\n }\n }\n\n if (matches) {\n let matchStartIndex = 0;\n for (let k = 0; k < i; k++) {\n matchStartIndex += originalLines[k].length + 1;\n }\n\n let matchEndIndex = matchStartIndex;\n for (let k = 0; k < searchLines.length; k++) {\n matchEndIndex += originalLines[i + k].length;\n if (k < searchLines.length - 1) {\n matchEndIndex += 1; // Add newline character except for the last line\n }\n }\n\n yield content.substring(matchStartIndex, matchEndIndex);\n }\n }\n};\n\n/**\n * Block anchor matching - uses first and last lines as anchors with similarity matching\n */\nexport const BlockAnchorReplacer: Replacer = function* (content, find) {\n const originalLines = content.split('\\n');\n const searchLines = find.split('\\n');\n\n if (searchLines.length < 3) {\n return;\n }\n\n if (searchLines[searchLines.length - 1] === '') {\n searchLines.pop();\n }\n\n const firstLineSearch = searchLines[0].trim();\n const lastLineSearch = searchLines[searchLines.length - 1].trim();\n const searchBlockSize = searchLines.length;\n\n // Collect all candidate positions where both anchors match\n const candidates: Array<{ startLine: number; endLine: number }> = [];\n for (let i = 0; i < originalLines.length; i++) {\n if (originalLines[i].trim() !== firstLineSearch) {\n continue;\n }\n\n // Look for the matching last line after this first line\n for (let j = i + 2; j < originalLines.length; j++) {\n if (originalLines[j].trim() === lastLineSearch) {\n candidates.push({ startLine: i, endLine: j });\n break; // Only match the first occurrence of the last line\n }\n }\n }\n\n // Return immediately if no candidates\n if (candidates.length === 0) {\n return;\n }\n\n // Handle single candidate scenario (using relaxed threshold)\n if (candidates.length === 1) {\n const { startLine, endLine } = candidates[0];\n const actualBlockSize = endLine - startLine + 1;\n\n let similarity = 0;\n const linesToCheck = Math.min(searchBlockSize - 2, actualBlockSize - 2); // Middle lines only\n\n if (linesToCheck > 0) {\n for (let j = 1; j < searchBlockSize - 1 && j < actualBlockSize - 1; j++) {\n const originalLine = originalLines[startLine + j].trim();\n const searchLine = searchLines[j].trim();\n const maxLen = Math.max(originalLine.length, searchLine.length);\n if (maxLen === 0) {\n continue;\n }\n const distance = levenshtein(originalLine, searchLine);\n similarity += (1 - distance / maxLen) / linesToCheck;\n\n // Exit early when threshold is reached\n if (similarity >= SINGLE_CANDIDATE_SIMILARITY_THRESHOLD) {\n break;\n }\n }\n } else {\n // No middle lines to compare, just accept based on anchors\n similarity = 1.0;\n }\n\n if (similarity >= SINGLE_CANDIDATE_SIMILARITY_THRESHOLD) {\n let matchStartIndex = 0;\n for (let k = 0; k < startLine; k++) {\n matchStartIndex += originalLines[k].length + 1;\n }\n let matchEndIndex = matchStartIndex;\n for (let k = startLine; k <= endLine; k++) {\n matchEndIndex += originalLines[k].length;\n if (k < endLine) {\n matchEndIndex += 1; // Add newline character except for the last line\n }\n }\n yield content.substring(matchStartIndex, matchEndIndex);\n }\n return;\n }\n\n // Calculate similarity for multiple candidates\n let bestMatch: { startLine: number; endLine: number } | null = null;\n let maxSimilarity = -1;\n\n for (const candidate of candidates) {\n const { startLine, endLine } = candidate;\n const actualBlockSize = endLine - startLine + 1;\n\n let similarity = 0;\n const linesToCheck = Math.min(searchBlockSize - 2, actualBlockSize - 2); // Middle lines only\n\n if (linesToCheck > 0) {\n for (let j = 1; j < searchBlockSize - 1 && j < actualBlockSize - 1; j++) {\n const originalLine = originalLines[startLine + j].trim();\n const searchLine = searchLines[j].trim();\n const maxLen = Math.max(originalLine.length, searchLine.length);\n if (maxLen === 0) {\n continue;\n }\n const distance = levenshtein(originalLine, searchLine);\n similarity += 1 - distance / maxLen;\n }\n similarity /= linesToCheck; // Average similarity\n } else {\n // No middle lines to compare, just accept based on anchors\n similarity = 1.0;\n }\n\n if (similarity > maxSimilarity) {\n maxSimilarity = similarity;\n bestMatch = candidate;\n }\n }\n\n // Threshold judgment\n if (maxSimilarity >= MULTIPLE_CANDIDATES_SIMILARITY_THRESHOLD && bestMatch) {\n const { startLine, endLine } = bestMatch;\n let matchStartIndex = 0;\n for (let k = 0; k < startLine; k++) {\n matchStartIndex += originalLines[k].length + 1;\n }\n let matchEndIndex = matchStartIndex;\n for (let k = startLine; k <= endLine; k++) {\n matchEndIndex += originalLines[k].length;\n if (k < endLine) {\n matchEndIndex += 1;\n }\n }\n yield content.substring(matchStartIndex, matchEndIndex);\n }\n};\n\n/**\n * Whitespace normalized matching - normalizes all whitespace to single spaces\n */\nexport const WhitespaceNormalizedReplacer: Replacer = function* (content, find) {\n const normalizeWhitespace = (text: string) => text.replace(/\\s+/g, ' ').trim();\n const normalizedFind = normalizeWhitespace(find);\n\n // Handle single line matches\n const lines = content.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (normalizeWhitespace(line) === normalizedFind) {\n yield line;\n } else {\n // Only check for substring matches if the full line doesn't match\n const normalizedLine = normalizeWhitespace(line);\n if (normalizedLine.includes(normalizedFind)) {\n // Find the actual substring in the original line that matches\n const words = find.trim().split(/\\s+/);\n if (words.length > 0) {\n const pattern = words.map((word) => word.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('\\\\s+');\n try {\n const regex = new RegExp(pattern);\n const match = line.match(regex);\n if (match) {\n yield match[0];\n }\n } catch {\n // Invalid regex pattern, skip\n }\n }\n }\n }\n }\n\n // Handle multi-line matches\n const findLines = find.split('\\n');\n if (findLines.length > 1) {\n for (let i = 0; i <= lines.length - findLines.length; i++) {\n const block = lines.slice(i, i + findLines.length);\n if (normalizeWhitespace(block.join('\\n')) === normalizedFind) {\n yield block.join('\\n');\n }\n }\n }\n};\n\n/**\n * Indentation flexible matching - ignores leading indentation differences\n */\nexport const IndentationFlexibleReplacer: Replacer = function* (content, find) {\n const removeIndentation = (text: string) => {\n const lines = text.split('\\n');\n const nonEmptyLines = lines.filter((line) => line.trim().length > 0);\n if (nonEmptyLines.length === 0) return text;\n\n const minIndent = Math.min(\n ...nonEmptyLines.map((line) => {\n const match = line.match(/^(\\s*)/);\n return match ? match[1].length : 0;\n }),\n );\n\n return lines.map((line) => (line.trim().length === 0 ? line : line.slice(minIndent))).join('\\n');\n };\n\n const normalizedFind = removeIndentation(find);\n const contentLines = content.split('\\n');\n const findLines = find.split('\\n');\n\n for (let i = 0; i <= contentLines.length - findLines.length; i++) {\n const block = contentLines.slice(i, i + findLines.length).join('\\n');\n if (removeIndentation(block) === normalizedFind) {\n yield block;\n }\n }\n};\n\n/**\n * Trimmed boundary matching - tries matching with trimmed leading/trailing whitespace\n */\nexport const TrimmedBoundaryReplacer: Replacer = function* (content, find) {\n const trimmedFind = find.trim();\n\n if (trimmedFind === find) {\n // Already trimmed, no point in trying\n return;\n }\n\n // Try to find the trimmed version\n if (content.includes(trimmedFind)) {\n yield trimmedFind;\n }\n\n // Also try finding blocks where trimmed content matches\n const lines = content.split('\\n');\n const findLines = find.split('\\n');\n\n for (let i = 0; i <= lines.length - findLines.length; i++) {\n const block = lines.slice(i, i + findLines.length).join('\\n');\n\n if (block.trim() === trimmedFind) {\n yield block;\n }\n }\n};\n\n/**\n * Line ending normalized - handles \\r\\n vs \\n differences\n */\nexport const LineEndingNormalizedReplacer: Replacer = function* (content, find) {\n // Normalize line endings in both\n const normalizedContent = content.replace(/\\r\\n/g, '\\n');\n const normalizedFind = find.replace(/\\r\\n/g, '\\n');\n\n if (normalizedFind !== find && normalizedContent.includes(normalizedFind)) {\n // Find the actual match in original content\n const index = normalizedContent.indexOf(normalizedFind);\n if (index !== -1) {\n // Map back to original content position\n let originalIndex = 0;\n let normalizedIndex = 0;\n while (normalizedIndex < index) {\n if (content[originalIndex] === '\\r' && content[originalIndex + 1] === '\\n') {\n originalIndex += 2;\n normalizedIndex += 1;\n } else {\n originalIndex++;\n normalizedIndex++;\n }\n }\n // Calculate original length\n let length = 0;\n let normalizedLength = 0;\n while (normalizedLength < normalizedFind.length) {\n if (content[originalIndex + length] === '\\r' && content[originalIndex + length + 1] === '\\n') {\n length += 2;\n normalizedLength += 1;\n } else {\n length++;\n normalizedLength++;\n }\n }\n yield content.substring(originalIndex, originalIndex + length);\n }\n }\n};\n\n/**\n * All replacers in order of preference (exact to fuzzy)\n */\nexport const REPLACERS: Replacer[] = [\n SimpleReplacer,\n LineTrimmedReplacer,\n BlockAnchorReplacer,\n WhitespaceNormalizedReplacer,\n IndentationFlexibleReplacer,\n TrimmedBoundaryReplacer,\n LineEndingNormalizedReplacer,\n];\n\nexport interface ReplaceResult {\n success: true;\n matchedString: string;\n newContent: string;\n replacerUsed: string;\n}\n\nexport interface ReplaceError {\n success: false;\n error: string;\n}\n\n/**\n * Try to replace old_string with new_string in content using fuzzy matching\n *\n * Returns the matched string from content and the new content with replacement applied.\n * Tries exact match first, then falls back to progressively fuzzier strategies.\n */\nexport function fuzzyReplace(\n content: string,\n oldString: string,\n newString: string,\n replaceAll: boolean = false\n): ReplaceResult | ReplaceError {\n if (oldString === newString) {\n return { success: false, error: 'oldString and newString must be different' };\n }\n\n const replacerNames = [\n 'exact',\n 'line-trimmed',\n 'block-anchor',\n 'whitespace-normalized',\n 'indentation-flexible',\n 'trimmed-boundary',\n 'line-ending-normalized',\n ];\n\n for (let i = 0; i < REPLACERS.length; i++) {\n const replacer = REPLACERS[i];\n for (const search of replacer(content, oldString)) {\n const index = content.indexOf(search);\n if (index === -1) continue;\n\n if (replaceAll) {\n return {\n success: true,\n matchedString: search,\n newContent: content.split(search).join(newString),\n replacerUsed: replacerNames[i],\n };\n }\n\n // For single replacement, check for ambiguity\n const lastIndex = content.lastIndexOf(search);\n if (index !== lastIndex) {\n // Multiple matches found - ambiguous\n continue;\n }\n\n return {\n success: true,\n matchedString: search,\n newContent: content.substring(0, index) + newString + content.substring(index + search.length),\n replacerUsed: replacerNames[i],\n };\n }\n }\n\n // Check if we found matches but they were all ambiguous\n for (const replacer of REPLACERS) {\n for (const search of replacer(content, oldString)) {\n if (content.indexOf(search) !== -1) {\n const occurrences = content.split(search).length - 1;\n return {\n success: false,\n error: `Found ${occurrences} matches for oldString. Use replace_all=true or provide more context in old_string.`,\n };\n }\n }\n }\n\n return { success: false, error: 'oldString not found in content' };\n}\n",
|
|
15
|
+
"import type { Tool } from 'ai';\nimport { z } from 'zod';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { PathValidator, type PathResolverContext } from './path-validator.js';\nimport { fuzzyReplace } from './edit-replacers.js';\nimport type { FilesystemPathConfig, ToolOutput, ToolErrorOutput } from './types.js';\n\nconst DEFAULT_MAX_LINES = 2000;\nconst DEFAULT_MAX_LINE_LENGTH = 2000;\n\n/**\n * Format file content with line numbers (cat -n style)\n */\nfunction formatWithLineNumbers(content: string, offset: number = 1): string {\n const lines = content.split('\\n');\n const maxLineNumWidth = String(offset + lines.length - 1).length;\n\n return lines\n .map((line, i) => {\n const lineNum = String(offset + i).padStart(maxLineNumWidth, ' ');\n // Truncate long lines\n const truncatedLine = line.length > DEFAULT_MAX_LINE_LENGTH\n ? line.slice(0, DEFAULT_MAX_LINE_LENGTH) + '... (truncated)'\n : line;\n return `${lineNum}\\t${truncatedLine}`;\n })\n .join('\\n');\n}\n\n/**\n * Resolve variable placeholders in a path pattern\n * Supported: ${root}, ${agentDir}, ${tmpDir}, ~\n */\nfunction resolvePathVariables(pattern: string, context: PathResolverContext): string {\n let result = pattern\n .replace(/\\$\\{root\\}/g, context.projectRoot)\n .replace(/\\$\\{tmpDir\\}/g, context.tmpDir ?? os.tmpdir())\n .replace(/^~/, os.homedir());\n\n // Only replace ${agentDir} if it's defined\n if (context.agentDir) {\n result = result.replace(/\\$\\{agentDir\\}/g, context.agentDir);\n }\n\n return result;\n}\n\n/**\n * Format path configurations for tool description\n */\nfunction formatPathsForDescription(\n configs: FilesystemPathConfig[],\n permission: 'read' | 'write' | 'edit',\n context: PathResolverContext\n): string {\n const relevantConfigs = configs.filter(c => c.permissions.includes(permission));\n if (relevantConfigs.length === 0) {\n return ' (none configured)';\n }\n\n const paths: string[] = [];\n for (const config of relevantConfigs) {\n if (config.path) {\n paths.push(` - ${resolvePathVariables(config.path, context)}`);\n }\n if (config.paths) {\n for (const p of config.paths) {\n paths.push(` - ${resolvePathVariables(p, context)}`);\n }\n }\n }\n return paths.join('\\n');\n}\n\n/**\n * Create the filesystem read tool\n */\nexport function createReadTool(\n configs: FilesystemPathConfig[],\n context: PathResolverContext\n): Tool {\n const validator = new PathValidator(configs, context);\n\n const allowedPaths = formatPathsForDescription(configs, 'read', context);\n const description = `Read file contents from the filesystem. Returns content with line numbers.\n\n**You can only read files from these paths:**\n${allowedPaths}\n\nUse absolute paths within these directories. Other paths will be rejected.`;\n\n return {\n description,\n inputSchema: z.object({\n file_path: z.string().describe('Absolute path to the file to read'),\n offset: z.number().optional().describe('Line number to start from (1-indexed)'),\n limit: z.number().optional().describe('Maximum number of lines to read'),\n }),\n execute: async ({ file_path, offset, limit }: {\n file_path: string;\n offset?: number;\n limit?: number;\n }): Promise<ToolOutput> => {\n // Validate path\n const validation = validator.validate(file_path, 'read');\n if (!validation.allowed) {\n const error: ToolErrorOutput = {\n success: false,\n error: validation.error || 'Path validation failed',\n };\n return { output: JSON.stringify(error) };\n }\n\n try {\n // Check if file exists\n const stats = await fs.stat(validation.resolvedPath);\n if (!stats.isFile()) {\n const error: ToolErrorOutput = {\n success: false,\n error: `Not a file: ${validation.resolvedPath}`,\n };\n return { output: JSON.stringify(error) };\n }\n\n // Read file content\n const content = await fs.readFile(validation.resolvedPath, 'utf-8');\n const lines = content.split('\\n');\n const totalLines = lines.length;\n\n // Apply offset and limit\n const startLine = Math.max(1, offset || 1);\n const maxLines = limit || DEFAULT_MAX_LINES;\n const endLine = Math.min(startLine + maxLines - 1, totalLines);\n\n const selectedLines = lines.slice(startLine - 1, endLine);\n const formattedContent = formatWithLineNumbers(selectedLines.join('\\n'), startLine);\n\n // Add metadata header\n const header = endLine < totalLines\n ? `[Reading lines ${startLine}-${endLine} of ${totalLines} total]\\n\\n`\n : '';\n\n return { output: header + formattedContent };\n } catch (err) {\n const error: ToolErrorOutput = {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n return { output: JSON.stringify(error) };\n }\n },\n };\n}\n\n/**\n * Create the filesystem write tool\n */\nexport function createWriteTool(\n configs: FilesystemPathConfig[],\n context: PathResolverContext\n): Tool {\n const validator = new PathValidator(configs, context);\n\n const allowedPaths = formatPathsForDescription(configs, 'write', context);\n const description = `Write content to a file. Creates the file if it does not exist, overwrites if it does.\n\n**You must write files to these paths:**\n${allowedPaths}\n\nUse absolute paths within these directories. Other paths will be rejected.`;\n\n return {\n description,\n inputSchema: z.object({\n file_path: z.string().describe('Absolute path to the file to write'),\n content: z.string().describe('Content to write to the file'),\n }),\n execute: async ({ file_path, content }: {\n file_path: string;\n content: string;\n }): Promise<ToolOutput> => {\n // Validate path\n const validation = validator.validate(file_path, 'write');\n if (!validation.allowed) {\n const error: ToolErrorOutput = {\n success: false,\n error: validation.error || 'Path validation failed',\n };\n return { output: JSON.stringify(error) };\n }\n\n try {\n // Ensure parent directory exists\n const dir = path.dirname(validation.resolvedPath);\n await fs.mkdir(dir, { recursive: true });\n\n // Check if file exists (for metadata)\n let created = false;\n try {\n await fs.access(validation.resolvedPath);\n } catch {\n created = true;\n }\n\n // Write file\n await fs.writeFile(validation.resolvedPath, content, 'utf-8');\n\n return {\n output: JSON.stringify({\n success: true,\n path: validation.resolvedPath,\n bytesWritten: Buffer.byteLength(content, 'utf-8'),\n created,\n }),\n };\n } catch (err) {\n const error: ToolErrorOutput = {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n return { output: JSON.stringify(error) };\n }\n },\n };\n}\n\n/**\n * Create the filesystem edit tool\n */\nexport function createEditTool(\n configs: FilesystemPathConfig[],\n context: PathResolverContext\n): Tool {\n const validator = new PathValidator(configs, context);\n\n const allowedPaths = formatPathsForDescription(configs, 'edit', context);\n const description = `Edit a file by replacing a string with a new string. Uses fuzzy matching to handle minor whitespace/indentation differences.\n\n**You can only edit files in these paths:**\n${allowedPaths}\n\nUse absolute paths within these directories. Other paths will be rejected.`;\n\n return {\n description,\n inputSchema: z.object({\n file_path: z.string().describe('Absolute path to the file to edit'),\n old_string: z.string().describe('Exact string to find and replace'),\n new_string: z.string().describe('String to replace with'),\n replace_all: z.boolean().optional().describe('Replace all occurrences (default: false, replaces first only)'),\n }),\n execute: async ({ file_path, old_string, new_string, replace_all }: {\n file_path: string;\n old_string: string;\n new_string: string;\n replace_all?: boolean;\n }): Promise<ToolOutput> => {\n // Validate path\n const validation = validator.validate(file_path, 'edit');\n if (!validation.allowed) {\n const error: ToolErrorOutput = {\n success: false,\n error: validation.error || 'Path validation failed',\n };\n return { output: JSON.stringify(error) };\n }\n\n try {\n // Read current content\n const content = await fs.readFile(validation.resolvedPath, 'utf-8');\n\n // Use fuzzy replace with fallback strategies\n const result = fuzzyReplace(content, old_string, new_string, replace_all);\n\n if (!result.success) {\n const error: ToolErrorOutput = {\n success: false,\n error: result.error,\n };\n return { output: JSON.stringify(error) };\n }\n\n // Write back\n await fs.writeFile(validation.resolvedPath, result.newContent, 'utf-8');\n\n // Count replacements for replace_all mode\n const replacements = replace_all\n ? content.split(result.matchedString).length - 1\n : 1;\n\n return {\n output: JSON.stringify({\n success: true,\n path: validation.resolvedPath,\n replacements,\n matchStrategy: result.replacerUsed,\n }),\n };\n } catch (err) {\n const error: ToolErrorOutput = {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n return { output: JSON.stringify(error) };\n }\n },\n };\n}\n",
|
|
16
|
+
"import { Parser, Language } from 'web-tree-sitter';\nimport { fileURLToPath } from 'url';\nimport path from 'path';\nimport fs from 'fs';\n\nlet parserInstance: Parser | null = null;\n\n/**\n * Find the node_modules directory from the current location\n */\nfunction findNodeModules(): string {\n let currentDir = path.dirname(fileURLToPath(import.meta.url));\n\n // Try up to 5 levels up\n for (let i = 0; i < 5; i++) {\n const nodeModulesPath = path.join(currentDir, 'node_modules');\n if (fs.existsSync(nodeModulesPath)) {\n return nodeModulesPath;\n }\n currentDir = path.dirname(currentDir);\n }\n\n throw new Error('Could not find node_modules directory');\n}\n\n/**\n * Initialize tree-sitter parser for bash\n */\nasync function initParser(): Promise<Parser> {\n if (parserInstance) return parserInstance;\n\n // Initialize Parser with WASM\n await Parser.init();\n\n // Load bash language from node_modules (works in both dev and built versions)\n const nodeModulesPath = findNodeModules();\n const bashWasmPath = path.join(\n nodeModulesPath,\n 'tree-sitter-bash/tree-sitter-bash.wasm'\n );\n\n if (!fs.existsSync(bashWasmPath)) {\n throw new Error(`Bash WASM file not found at: ${bashWasmPath}`);\n }\n\n const bashLanguage = await Language.load(bashWasmPath);\n\n const parser = new Parser();\n parser.setLanguage(bashLanguage);\n\n parserInstance = parser;\n return parser;\n}\n\n/**\n * Represents a parsed bash command with structured arguments\n */\nexport interface ParsedCommand {\n head: string; // Command name (e.g., \"git\", \"npm\", \"cd\")\n tail: string[]; // Arguments (e.g., [\"push\", \"origin\", \"main\"])\n raw: string; // Original command text\n}\n\n/**\n * Parse a bash command string into structured commands\n * Returns array of commands found in the input (handles pipelines, &&, ||, etc.)\n */\nexport async function parseBashCommand(commandString: string): Promise<ParsedCommand[]> {\n const parser = await initParser();\n const tree = parser.parse(commandString as any);\n\n if (!tree) {\n throw new Error('Failed to parse command');\n }\n\n const commands: ParsedCommand[] = [];\n\n // Find all command nodes in the tree\n const commandNodes = tree.rootNode.descendantsOfType('command');\n\n for (const node of commandNodes) {\n const parts: string[] = [];\n\n // Extract command parts from AST\n for (let i = 0; i < node.childCount; i++) {\n const child = node.child(i);\n if (!child) continue;\n\n // Only extract actual command parts (not syntax elements)\n if (\n child.type === 'command_name' ||\n child.type === 'word' ||\n child.type === 'string' ||\n child.type === 'raw_string' ||\n child.type === 'concatenation'\n ) {\n parts.push(child.text);\n }\n }\n\n if (parts.length > 0) {\n commands.push({\n head: parts[0],\n tail: parts.slice(1),\n raw: node.text,\n });\n }\n }\n\n return commands;\n}\n\n/**\n * Check if a command accesses paths and extract them\n * Used for external directory checking\n */\nexport async function extractPaths(commandString: string): Promise<string[]> {\n const commands = await parseBashCommand(commandString);\n const paths: string[] = [];\n\n for (const cmd of commands) {\n // Commands that commonly operate on paths\n const pathCommands = [\n 'cd', 'rm', 'cp', 'mv', 'mkdir', 'touch', 'chmod', 'chown', 'cat', 'ls',\n // Script interpreters that execute files\n 'bash', 'sh', 'zsh', 'fish', 'python', 'python3', 'node', 'ruby', 'perl',\n ];\n\n if (pathCommands.includes(cmd.head)) {\n for (const arg of cmd.tail) {\n // Skip flags\n if (arg.startsWith('-') || (cmd.head === 'chmod' && arg.startsWith('+'))) {\n continue;\n }\n\n // Check if it looks like a path\n if (\n arg.startsWith('/') ||\n arg.startsWith('./') ||\n arg.startsWith('../') ||\n arg.startsWith('~/') ||\n arg.includes('/') ||\n arg === '.' ||\n arg === '..'\n ) {\n // Remove quotes if present\n const cleanPath = arg.replace(/^['\"]|['\"]$/g, '');\n paths.push(cleanPath);\n }\n }\n }\n }\n\n return paths;\n}\n",
|
|
17
|
+
"export interface StructuredCommand {\n head: string;\n tail: string[];\n}\n\n/**\n * Match a string against a wildcard pattern\n * Supports * (any chars) and ? (single char)\n */\nexport function match(str: string, pattern: string): boolean {\n const regex = new RegExp(\n '^' +\n pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&') // escape special regex chars\n .replace(/\\*/g, '.*') // * becomes .*\n .replace(/\\?/g, '.') + // ? becomes .\n '$',\n 's' // s flag enables multiline matching\n );\n return regex.test(str);\n}\n\n/**\n * Match a string against multiple patterns, returning the matching pattern\n * Patterns are sorted by length (shorter first) to allow specific overrides\n */\nexport function matchAny(input: string, patterns: Record<string, any>): any {\n // Sort by pattern length (ascending) then alphabetically\n const sorted = Object.entries(patterns).sort((a, b) => {\n const lenDiff = a[0].length - b[0].length;\n if (lenDiff !== 0) return lenDiff;\n return a[0].localeCompare(b[0]);\n });\n\n let result: any = undefined;\n\n for (const [pattern, value] of sorted) {\n if (match(input, pattern)) {\n result = value;\n }\n }\n\n return result;\n}\n\n/**\n * Match a structured command against patterns\n * Example: { head: \"git\", tail: [\"push\", \"origin\"] } matches \"git push *\"\n */\nexport function matchStructured(\n input: StructuredCommand,\n patterns: Record<string, any>\n): any {\n // Sort by pattern length (ascending) then alphabetically\n const sorted = Object.entries(patterns).sort((a, b) => {\n const lenDiff = a[0].length - b[0].length;\n if (lenDiff !== 0) return lenDiff;\n return a[0].localeCompare(b[0]);\n });\n\n let result: any = undefined;\n\n for (const [pattern, value] of sorted) {\n const parts = pattern.split(/\\s+/);\n\n // Match head (command name)\n if (!match(input.head, parts[0])) continue;\n\n // If pattern is just the command name, it matches\n if (parts.length === 1) {\n result = value;\n continue;\n }\n\n // Match tail (arguments) as a sequence\n if (matchSequence(input.tail, parts.slice(1))) {\n result = value;\n }\n }\n\n return result;\n}\n\n/**\n * Match a sequence of arguments against a sequence of patterns\n * Handles wildcards in argument patterns\n */\nfunction matchSequence(items: string[], patterns: string[]): boolean {\n if (patterns.length === 0) return true;\n\n const [pattern, ...rest] = patterns;\n\n // * wildcard matches any number of items (including zero)\n if (pattern === '*') {\n return matchSequence(items, rest);\n }\n\n // Try to match pattern against each item\n for (let i = 0; i < items.length; i++) {\n if (match(items[i], pattern) && matchSequence(items.slice(i + 1), rest)) {\n return true;\n }\n }\n\n return false;\n}\n",
|
|
18
|
+
"import * as path from 'path';\nimport * as os from 'os';\nimport type { CommandValidationResult } from './types.js';\nimport { parseBashCommand, extractPaths, type ParsedCommand } from './bash-parser.js';\nimport { matchStructured, type StructuredCommand } from './wildcard.js';\nimport { resolveRealPath, type PathResolverContext } from './path-validator.js';\n\n// Built-in denylist - always blocked, cannot be overridden\nconst BUILTIN_DENYLIST: Record<string, boolean> = {\n // Destructive filesystem operations\n 'rm -rf /': true,\n 'rm -rf ~': true,\n 'rm -rf /*': true,\n 'rm -rf ~/*': true,\n 'rm -rf *': true,\n\n // Privilege escalation\n 'sudo *': true,\n 'su *': true,\n 'doas *': true,\n\n // Dangerous permissions\n 'chmod -R 777 /': true,\n 'chmod -R 777 ~': true,\n 'chmod 777 /': true,\n\n // Disk operations\n 'mkfs*': true,\n 'dd of=/dev/*': true,\n 'dd if=* of=/dev/*': true,\n\n // System operations\n 'shutdown*': true,\n 'reboot*': true,\n 'halt*': true,\n 'poweroff*': true,\n 'init 0': true,\n 'init 6': true,\n\n // Network exfiltration patterns\n '* | nc *': true,\n '* | netcat *': true,\n '* | ncat *': true,\n '* | curl *': true,\n '* | wget *': true,\n '* > /dev/tcp/*': true,\n '* > /dev/udp/*': true,\n\n // Reverse shell patterns\n 'nc -e *': true,\n 'nc * -e *': true,\n 'netcat -e *': true,\n 'netcat * -e *': true,\n 'ncat -e *': true,\n 'ncat * -e *': true,\n 'bash -i *': true,\n 'bash -c *sh -i*': true,\n\n // History/credential theft\n 'cat *history*': true,\n 'cat *_history': true,\n 'cat *.ssh/*': true,\n 'cat *id_rsa*': true,\n 'cat *id_ed25519*': true,\n 'cat /etc/passwd': true,\n 'cat /etc/shadow': true,\n};\n\nexport class CommandValidator {\n private readonly allowedPatterns: Record<string, 'allow' | 'deny'>;\n private readonly projectRoot: string | null;\n private readonly allowedPaths: string[];\n private readonly context: PathResolverContext | null;\n\n constructor(\n allowedPatterns: string[],\n projectRoot?: string,\n allowedPaths?: string[],\n context?: PathResolverContext\n ) {\n // Convert array of patterns to Record with \"allow\" value\n this.allowedPatterns = {};\n for (const pattern of allowedPatterns) {\n this.allowedPatterns[pattern] = 'allow';\n }\n\n // Auto-allow cd within project (it's just navigation)\n this.allowedPatterns['cd *'] = 'allow';\n\n this.projectRoot = projectRoot ?? null;\n this.allowedPaths = allowedPaths ?? [];\n this.context = context ?? (projectRoot ? { projectRoot } : null);\n }\n\n /**\n * Resolve variable placeholders in an allowed path.\n * Supported: ${root}, ${agentDir}, ${tmpDir}, ~\n */\n private resolveAllowedPath(allowedPath: string): string {\n let result = allowedPath;\n\n // Resolve ~ for home directory\n if (result.startsWith('~')) {\n // Only support \"~\" and \"~/\" (not \"~user\")\n result = result.replace(/^~(?=$|[\\\\/])/, os.homedir());\n }\n\n // Resolve variables if context is available\n if (this.context) {\n const tmpDir = resolveRealPath(this.context.tmpDir ?? os.tmpdir());\n result = result\n .replace(/\\$\\{root\\}/g, this.context.projectRoot)\n .replace(/\\$\\{tmpDir\\}/g, tmpDir);\n\n // Only replace ${agentDir} if it's defined\n if (this.context.agentDir) {\n result = result.replace(/\\$\\{agentDir\\}/g, this.context.agentDir);\n }\n }\n\n return result;\n }\n\n /**\n * Resolve a path to absolute, handling ~ and relative paths.\n * Also resolves symlinks for consistent comparison with allowedPaths.\n */\n private resolvePath(filePath: string): string {\n // Handle ~ for home directory\n if (filePath.startsWith('~')) {\n // Only support \"~\" and \"~/\" (not \"~user\")\n filePath = filePath.replace(/^~(?=$|[\\\\/])/, os.homedir());\n }\n\n // Resolve relative paths against project root or cwd\n if (!path.isAbsolute(filePath)) {\n const base = this.projectRoot || process.cwd();\n filePath = path.resolve(base, filePath);\n }\n\n // Resolve symlinks for consistent comparison (e.g., /var -> /private/var on macOS)\n return resolveRealPath(filePath);\n }\n\n /**\n * Check if a path is within a given root directory\n */\n private isPathWithin(filePath: string, rootDir: string): boolean {\n try {\n const resolvedPath = this.resolvePath(filePath);\n // Also resolve symlinks for rootDir for consistent comparison\n const normalizedRoot = resolveRealPath(rootDir);\n\n // Check if the path is within root\n const relative = path.relative(normalizedRoot, resolvedPath);\n\n // Path is within if:\n // 1. relative path doesn't start with '..' (not going up)\n // 2. relative path is not absolute (not a completely different path)\n return !relative.startsWith('..') && !path.isAbsolute(relative);\n } catch {\n return false;\n }\n }\n\n /**\n * Check if a path is within any allowed directory (project root or allowedPaths)\n */\n private isWithinAllowedPaths(filePath: string): boolean {\n // No project root = no restriction\n if (!this.projectRoot) return true;\n\n // Check project root first\n if (this.isPathWithin(filePath, this.projectRoot)) {\n return true;\n }\n\n // Check allowedPaths with variable resolution\n for (const allowedPath of this.allowedPaths) {\n const resolvedAllowedPath = this.resolveAllowedPath(allowedPath);\n\n if (this.isPathWithin(filePath, resolvedAllowedPath)) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Check for external directory access in parsed commands\n */\n private async checkExternalDirectoryAccess(\n commandString: string\n ): Promise<string | null> {\n if (!this.projectRoot) return null; // No project root = no restriction\n\n const paths = await extractPaths(commandString);\n\n for (const p of paths) {\n if (!this.isWithinAllowedPaths(p)) {\n return `Access to path outside allowed directories: ${p}`;\n }\n }\n\n return null;\n }\n\n /**\n * Check if a command matches built-in denylist\n */\n private checkBuiltinDenylist(cmd: ParsedCommand): string | null {\n // Check full command\n const fullCmd = [cmd.head, ...cmd.tail].join(' ');\n\n for (const pattern in BUILTIN_DENYLIST) {\n if (this.matchesPattern(fullCmd, pattern)) {\n return `Command blocked by built-in security policy: \"${pattern}\"`;\n }\n }\n\n // Check if piping to dangerous targets (sh, bash, python, etc.)\n const dangerousTargets = ['sh', 'bash', 'zsh', 'fish', 'python', 'python3', 'node', 'perl', 'ruby'];\n if (dangerousTargets.includes(cmd.head)) {\n // It's ok if it's a direct call like \"python script.py\"\n // But not if it appears after a pipe in the original command\n // This is simplified - in practice, we'd need to check if this command\n // is the target of a pipe operator\n }\n\n return null;\n }\n\n /**\n * Match a string against a pattern (for simple checks)\n */\n private matchesPattern(str: string, pattern: string): boolean {\n const regexPattern = pattern\n .split('*')\n .map(part => part.replace(/[.+?^${}()|[\\]\\\\]/g, char => '\\\\' + char))\n .join('.*');\n const regex = new RegExp(`^${regexPattern}$`, 'is');\n return regex.test(str);\n }\n\n /**\n * Validate a single parsed command\n */\n private validateSingleCommand(cmd: ParsedCommand): CommandValidationResult {\n // Check built-in denylist first\n const denyError = this.checkBuiltinDenylist(cmd);\n if (denyError) {\n return { allowed: false, error: denyError };\n }\n\n // cd is always allowed (only checked for external paths)\n if (cmd.head === 'cd') {\n return { allowed: true, matchedPattern: 'cd *' };\n }\n\n // Check allowlist using structured matching\n const structured: StructuredCommand = {\n head: cmd.head,\n tail: cmd.tail,\n };\n\n const result = matchStructured(structured, this.allowedPatterns);\n\n if (result === 'allow') {\n // Find which pattern matched for reporting\n const pattern = this.findMatchingPattern(structured);\n return { allowed: true, matchedPattern: pattern };\n }\n\n // Not in allowlist\n const allowedHint = Object.keys(this.allowedPatterns)\n .filter(p => this.allowedPatterns[p] === 'allow')\n .slice(0, 5)\n .join(', ');\n const moreCount =\n Object.keys(this.allowedPatterns).length > 5\n ? ` (+${Object.keys(this.allowedPatterns).length - 5} more)`\n : '';\n\n return {\n allowed: false,\n error: `Command not in allowlist: \"${cmd.raw}\". Allowed patterns: ${allowedHint}${moreCount}`,\n };\n }\n\n /**\n * Find which pattern matched a command (for reporting)\n */\n private findMatchingPattern(cmd: StructuredCommand): string {\n const sorted = Object.entries(this.allowedPatterns)\n .filter(([_, value]) => value === 'allow')\n .sort((a, b) => {\n const lenDiff = b[0].length - a[0].length; // Reverse sort (longest first)\n if (lenDiff !== 0) return lenDiff;\n return a[0].localeCompare(b[0]);\n });\n\n for (const [pattern] of sorted) {\n if (matchStructured(cmd, { [pattern]: 'allow' })) {\n return pattern;\n }\n }\n\n return 'unknown';\n }\n\n /**\n * Validate a command (handles compound commands)\n */\n async validate(command: string): Promise<CommandValidationResult> {\n const normalizedCommand = command.trim();\n\n if (!normalizedCommand) {\n return { allowed: false, error: 'Empty command' };\n }\n\n // Parse command using tree-sitter\n let parsedCommands: ParsedCommand[];\n try {\n parsedCommands = await parseBashCommand(normalizedCommand);\n } catch (error) {\n return {\n allowed: false,\n error: `Failed to parse command: ${error instanceof Error ? error.message : 'unknown error'}`,\n };\n }\n\n if (parsedCommands.length === 0) {\n return { allowed: false, error: 'No valid commands found' };\n }\n\n // Validate each command individually (includes denylist check)\n const matchedPatterns: string[] = [];\n\n for (const cmd of parsedCommands) {\n const result = this.validateSingleCommand(cmd);\n if (!result.allowed) {\n return {\n allowed: false,\n error: result.error!,\n };\n }\n if (result.matchedPattern) {\n matchedPatterns.push(result.matchedPattern);\n }\n }\n\n // Check for external directory access last (after denylist and allowlist)\n // Only check if we have a project root configured\n const externalError = await this.checkExternalDirectoryAccess(normalizedCommand);\n if (externalError) {\n return { allowed: false, error: externalError };\n }\n\n return {\n allowed: true,\n matchedPattern: matchedPatterns.join(', '),\n };\n }\n\n /**\n * Get the list of allowed patterns\n */\n getAllowedPatterns(): string[] {\n return Object.keys(this.allowedPatterns).filter(\n (p) => this.allowedPatterns[p] === 'allow'\n );\n }\n}\n",
|
|
19
|
+
"import type { Tool } from 'ai';\r\nimport { z } from 'zod';\r\nimport { spawn } from 'child_process';\r\nimport * as path from 'path';\r\nimport * as os from 'os';\r\nimport { CommandValidator } from './command-validator.js';\r\nimport type { BashConfig, ToolOutput, ToolErrorOutput } from './types.js';\nimport { resolveRealPath, type PathResolverContext } from './path-validator.js';\nimport { logger } from '../utils/logger.js';\nimport { redactText } from '../utils/redaction.js';\n\r\nconst DEFAULT_TIMEOUT = 120000; // 2 minutes\r\nconst DEFAULT_MAX_OUTPUT = 30 * 1024; // 30KB\r\nconst FORCE_RESOLVE_AFTER_KILL_MS = 2000; // Prevent hanging when kill fails (Windows process trees).\r\n\r\n// Environment variables that should be cleared for security\r\n// These can be used for library injection, path hijacking, or other attacks\r\nconst DANGEROUS_ENV_VARS = [\r\n // Library injection (Linux)\r\n 'LD_PRELOAD',\r\n 'LD_LIBRARY_PATH',\r\n 'LD_AUDIT',\r\n 'LD_DEBUG',\r\n 'LD_DEBUG_OUTPUT',\r\n 'LD_DYNAMIC_WEAK',\r\n 'LD_ORIGIN_PATH',\r\n 'LD_PROFILE',\r\n 'LD_SHOW_AUXV',\r\n\r\n // Library injection (macOS)\r\n 'DYLD_INSERT_LIBRARIES',\r\n 'DYLD_LIBRARY_PATH',\r\n 'DYLD_FRAMEWORK_PATH',\r\n 'DYLD_FALLBACK_LIBRARY_PATH',\r\n 'DYLD_FALLBACK_FRAMEWORK_PATH',\r\n 'DYLD_IMAGE_SUFFIX',\r\n 'DYLD_PRINT_LIBRARIES',\r\n\r\n // Python injection\r\n 'PYTHONPATH',\r\n 'PYTHONSTARTUP',\r\n 'PYTHONHOME',\r\n\r\n // Node.js injection\r\n 'NODE_OPTIONS',\r\n 'NODE_PATH',\r\n\r\n // Ruby injection\r\n 'RUBYLIB',\r\n 'RUBYOPT',\r\n\r\n // Perl injection\r\n 'PERL5LIB',\r\n 'PERL5OPT',\r\n 'PERLLIB',\r\n\r\n // Bash startup injection\r\n 'BASH_ENV',\r\n 'ENV',\r\n 'CDPATH',\r\n\r\n // Git hooks (can execute arbitrary code)\r\n 'GIT_TEMPLATE_DIR',\r\n 'GIT_EXEC_PATH',\r\n\r\n // IFS manipulation (word splitting attacks)\r\n 'IFS',\r\n\r\n // Proxy hijacking\r\n 'http_proxy',\r\n 'https_proxy',\r\n 'HTTP_PROXY',\r\n 'HTTPS_PROXY',\r\n 'ALL_PROXY',\r\n 'all_proxy',\r\n 'ftp_proxy',\r\n 'FTP_PROXY',\r\n];\r\n\r\n/**\r\n * Create a sanitized environment for command execution\r\n * Removes dangerous environment variables that could be used for attacks\r\n */\r\nexport function createSafeEnvironment(projectRoot: string): NodeJS.ProcessEnv {\r\n const env: NodeJS.ProcessEnv = { ...process.env };\r\n\r\n // Clear all dangerous environment variables\r\n for (const varName of DANGEROUS_ENV_VARS) {\r\n delete env[varName];\r\n }\r\n\r\n // Set safe defaults\r\n env['SHELL'] = '/bin/sh';\r\n env['PWD'] = projectRoot;\r\n\r\n // Ensure PATH doesn't include current directory (PATH injection).\r\n // On Windows, the key is often \"Path\" (mixed case) and the delimiter is \";\" (not \":\"),\r\n // so we detect the actual key and use path.delimiter.\r\n const existingPathKey = Object.keys(env).find((k) => k.toUpperCase() === 'PATH');\r\n const pathValue = existingPathKey ? env[existingPathKey] : env['PATH'];\r\n\r\n if (pathValue !== undefined) {\r\n const sep = path.delimiter;\r\n const parts = pathValue.split(sep).filter((p) => p !== '.' && p !== '');\r\n const sanitized = parts.join(sep);\r\n\r\n // Canonicalize to PATH to avoid case-related surprises when passing env to shells.\r\n if (existingPathKey && existingPathKey !== 'PATH') {\r\n delete env[existingPathKey];\r\n }\r\n env['PATH'] = sanitized;\r\n }\r\n\r\n return env;\r\n}\r\n\r\n/**\r\n * Kill a process and all its children\r\n */\r\nasync function killProcessTree(pid: number): Promise<void> {\r\n if (process.platform === 'win32') {\r\n // Windows: kill process tree via taskkill.\r\n // This is the most reliable way to terminate child processes spawned by shells.\r\n await new Promise<void>((resolve) => {\r\n const child = spawn('taskkill', ['/PID', String(pid), '/T', '/F'], {\r\n stdio: 'ignore',\r\n windowsHide: true,\r\n });\r\n child.on('close', () => resolve());\r\n child.on('error', () => resolve());\r\n });\r\n return;\r\n }\r\n\r\n try {\r\n // On Unix, use negative PID to kill process group\r\n process.kill(-pid, 'SIGKILL');\r\n } catch {\r\n // Fallback to just killing the process\r\n try {\r\n process.kill(pid, 'SIGKILL');\r\n } catch {\r\n // Process already dead\r\n }\r\n }\r\n}\r\n\r\nfunction createPrefixedLineWriter(prefix: string) {\n let carry = '';\r\n return {\r\n writeChunk: (chunk: string) => {\r\n carry += chunk;\r\n const parts = carry.split(/\\r?\\n/);\r\n carry = parts.pop() ?? '';\r\n for (const line of parts) {\r\n process.stderr.write(`${prefix}${line}\\n`);\r\n }\r\n },\r\n flush: () => {\r\n if (carry) {\r\n process.stderr.write(`${prefix}${carry}\\n`);\r\n carry = '';\r\n }\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Resolve variable placeholders in an allowed path.\r\n * Supported: ${root}, ${agentDir}, ${tmpDir}, ~\r\n */\r\nfunction resolveAllowedPath(allowedPath: string, context: PathResolverContext): string {\r\n let result = allowedPath;\r\n\r\n // Resolve ~ for home directory\r\n if (result.startsWith('~')) {\r\n result = result.replace(/^~/, os.homedir());\r\n }\r\n\r\n // Resolve variables\r\n const tmpDir = resolveRealPath(context.tmpDir ?? os.tmpdir());\r\n result = result\r\n .replace(/\\$\\{root\\}/g, context.projectRoot)\r\n .replace(/\\$\\{tmpDir\\}/g, tmpDir);\r\n\r\n // Only replace ${agentDir} if it's defined\r\n if (context.agentDir) {\r\n result = result.replace(/\\$\\{agentDir\\}/g, context.agentDir);\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Check if a path is within any of the allowed directories\r\n */\r\nfunction isPathWithinAllowed(\r\n targetPath: string,\r\n projectRoot: string,\r\n allowedPaths: string[],\r\n context: PathResolverContext\r\n): boolean {\r\n const normalizedTarget = path.normalize(targetPath);\r\n\r\n // Check project root\r\n const normalizedProjectRoot = path.normalize(projectRoot);\r\n const relativeToProject = path.relative(normalizedProjectRoot, normalizedTarget);\r\n if (!relativeToProject.startsWith('..') && !path.isAbsolute(relativeToProject)) {\r\n return true;\r\n }\r\n\r\n // Check allowedPaths with variable resolution\r\n for (const allowedPath of allowedPaths) {\r\n const resolvedAllowedPath = resolveAllowedPath(allowedPath, context);\r\n const normalizedAllowed = path.normalize(resolvedAllowedPath);\r\n const relative = path.relative(normalizedAllowed, normalizedTarget);\r\n if (!relative.startsWith('..') && !path.isAbsolute(relative)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Create the bash tool\r\n */\r\nexport function createBashTool(\r\n config: BashConfig,\r\n projectRoot: string,\r\n context?: PathResolverContext\r\n): Tool {\r\n const allowedPaths = config.allowedPaths ?? [];\r\n const resolverContext: PathResolverContext = context ?? { projectRoot };\r\n const validator = new CommandValidator(config.commands, projectRoot, allowedPaths, resolverContext);\r\n const timeoutConfigured = config.timeout !== undefined;\r\n const envTimeoutMs = process.env.PK_AGENT_BASH_TIMEOUT_MS\r\n ? Number.parseInt(process.env.PK_AGENT_BASH_TIMEOUT_MS, 10)\r\n : undefined;\r\n const defaultTimeout = config.timeout ?? (Number.isFinite(envTimeoutMs) ? envTimeoutMs! : DEFAULT_TIMEOUT);\r\n\r\n // Build description with allowed commands and paths\r\n const allowedCommandsList = config.commands.map(cmd => ` - ${cmd}`).join('\\n');\r\n\r\n // Resolve allowed paths for display\r\n const allowedPathsList = allowedPaths.length > 0\r\n ? allowedPaths.map(p => {\r\n const resolved = resolveAllowedPath(p, resolverContext);\r\n // If path contains ${tmpDir}, show the resolved path for clarity\r\n if (p.includes('${tmpDir}')) {\r\n return ` - ${resolved} (use this for temporary files)`;\r\n }\r\n return ` - ${resolved}`;\r\n }).join('\\n')\r\n : ` - ${projectRoot} (project root)`;\r\n\r\n const description = `Execute a shell command. Only commands matching the configured allowlist patterns are permitted.\r\n\r\nAllowed command patterns:\r\n${allowedCommandsList}\r\n\r\nAllowed file paths (use these for any file operations):\r\n${allowedPathsList}\r\n\r\nCommands not matching these patterns will be rejected.`;\r\n\r\n // Build input schema - only expose timeout if not configured by user\r\n const baseSchema = {\r\n command: z.string().describe('The shell command to execute'),\r\n workdir: z.string().optional().describe(`Working directory for command execution. Must be within the project. Defaults to project root. Use this instead of 'cd' commands.`),\r\n };\r\n\r\n const inputSchema = timeoutConfigured\r\n ? z.object(baseSchema)\r\n : z.object({\r\n ...baseSchema,\r\n timeout: z.number().optional().describe(`Optional timeout in milliseconds (default: ${DEFAULT_TIMEOUT}ms)`),\r\n });\r\n\r\n return {\r\n description,\r\n inputSchema,\r\n execute: async ({ command, workdir, timeout }: {\r\n command: string;\r\n workdir?: string;\r\n timeout?: number;\r\n }): Promise<ToolOutput> => {\r\n // Validate command (async with tree-sitter)\r\n const validation = await validator.validate(command);\r\n if (!validation.allowed) {\r\n const error: ToolErrorOutput = {\r\n success: false,\r\n error: validation.error || 'Command validation failed',\r\n };\r\n\r\n // Log warning after tool result is displayed (next tick)\r\n setImmediate(() => {\r\n logger.warn(`Bash command blocked: \"${command}\"`);\r\n });\r\n\r\n return { output: JSON.stringify(error) };\r\n }\r\n\r\n // Resolve and validate workdir\r\n let cwd = projectRoot;\r\n if (workdir) {\r\n const resolvedWorkdir = path.isAbsolute(workdir)\r\n ? workdir\r\n : path.resolve(projectRoot, workdir);\r\n\r\n // Security: ensure workdir is within allowed directories\r\n if (!isPathWithinAllowed(resolvedWorkdir, projectRoot, allowedPaths, resolverContext)) {\r\n const error: ToolErrorOutput = {\r\n success: false,\r\n error: `Working directory must be within allowed paths: ${workdir}`,\r\n };\r\n return { output: JSON.stringify(error) };\r\n }\r\n cwd = resolvedWorkdir;\r\n }\r\n\r\n // If user configured timeout, use it strictly; otherwise let model decide\r\n const timeoutMs = timeoutConfigured\r\n ? defaultTimeout\r\n : (timeout ?? defaultTimeout);\r\n\r\n return new Promise((resolve) => {\r\n let stdout = '';\r\n let stderr = '';\r\n let timedOut = false;\r\n let settled = false;\r\n let stdoutTruncated = false;\r\n let stderrTruncated = false;\r\n const streamOutput = process.env.PK_AGENT_AUDIT === 'true' || process.env.PK_AGENT_AUDIT === '1';\r\n const stdoutWriter = streamOutput ? createPrefixedLineWriter('| ') : null;\r\n const stderrWriter = streamOutput ? createPrefixedLineWriter('| [stderr] ') : null;\r\n\r\n // Spawn the command with sanitized environment\r\n const child = spawn(command, {\r\n shell: true,\r\n cwd,\r\n detached: true, // Create new process group for cleanup\r\n env: createSafeEnvironment(cwd),\r\n });\r\n\r\n const finish = (code: number | null, forced: boolean) => {\r\n if (settled) return;\r\n settled = true;\r\n\r\n // Flush any partial streaming line.\r\n stdoutWriter?.flush();\r\n stderrWriter?.flush();\r\n\r\n // Build output\r\n let output = '';\r\n\r\n if (!streamOutput && stdout) {\r\n output += stdout;\r\n }\r\n\r\n if (!streamOutput && stderr) {\r\n if (output) output += '\\n\\n';\r\n output += `[stderr]\\n${stderr}`;\r\n }\r\n\r\n // Build metadata hints for LLM (OpenCode pattern)\r\n const resultMetadata: string[] = ['<bash_metadata>'];\r\n\r\n if (stdoutTruncated || stderrTruncated) {\r\n resultMetadata.push(`bash tool truncated output as it exceeded ${DEFAULT_MAX_OUTPUT} byte limit`);\r\n }\r\n\r\n if (timedOut) {\r\n resultMetadata.push(`bash tool terminated command after exceeding timeout ${timeoutMs}ms`);\r\n }\r\n\r\n if (forced) {\r\n resultMetadata.push(`bash tool resolved before process exit (kill may have failed)`);\r\n }\r\n\r\n if (code !== 0 && code !== null) {\r\n resultMetadata.push(`exit code: ${code}`);\r\n }\r\n\r\n // Append metadata if any warnings/info\r\n if (resultMetadata.length > 1) {\r\n resultMetadata.push('</bash_metadata>');\r\n if (!streamOutput) {\r\n output += '\\n\\n' + resultMetadata.join('\\n');\r\n }\r\n }\r\n\r\n resolve({\r\n output: streamOutput ? '(output streamed)' : (output || '(no output)'),\r\n metadata: {\r\n exitCode: code,\r\n timedOut,\r\n truncated: stdoutTruncated || stderrTruncated,\r\n ...(streamOutput && { streamed: true }),\r\n ...(forced && { forcedResolve: true }),\r\n },\r\n });\r\n };\r\n\r\n // Set up timeout\r\n const timeoutHandle = setTimeout(async () => {\r\n timedOut = true;\r\n if (child.pid) {\r\n await killProcessTree(child.pid);\r\n }\r\n // Some platforms (notably Windows) may fail to kill the full tree (or emit \"close\")\r\n // reliably. Force-resolve after a grace period so the agent doesn't hang forever.\r\n setTimeout(() => {\r\n finish(null, true);\r\n }, FORCE_RESOLVE_AFTER_KILL_MS);\r\n }, timeoutMs);\r\n\r\n // Collect stdout\n child.stdout?.on('data', (data: Buffer) => {\n if (streamOutput) {\n stdoutWriter?.writeChunk(redactText(data.toString()));\n }\n if (stdout.length < DEFAULT_MAX_OUTPUT) {\n stdout += redactText(data.toString());\n if (stdout.length > DEFAULT_MAX_OUTPUT) {\n stdout = stdout.slice(0, DEFAULT_MAX_OUTPUT);\n stdoutTruncated = true;\n }\n }\n });\n\n // Collect stderr\n child.stderr?.on('data', (data: Buffer) => {\n if (streamOutput) {\n stderrWriter?.writeChunk(redactText(data.toString()));\n }\n if (stderr.length < DEFAULT_MAX_OUTPUT) {\n stderr += redactText(data.toString());\n if (stderr.length > DEFAULT_MAX_OUTPUT) {\n stderr = stderr.slice(0, DEFAULT_MAX_OUTPUT);\n stderrTruncated = true;\n }\n }\n });\r\n\r\n // Handle process exit\r\n child.on('close', (code) => {\r\n clearTimeout(timeoutHandle);\r\n finish(code, false);\r\n });\r\n\r\n // Handle errors\r\n child.on('error', (err) => {\r\n clearTimeout(timeoutHandle);\r\n const error: ToolErrorOutput = {\r\n success: false,\r\n error: `Failed to execute command: ${err.message}`,\r\n };\r\n if (settled) return;\r\n settled = true;\r\n resolve({ output: JSON.stringify(error) });\r\n });\r\n });\r\n },\r\n };\r\n}\r\n",
|
|
20
|
+
"import type { Tool } from 'ai';\r\nimport { z } from 'zod';\r\nimport { spawn } from 'child_process';\r\nimport * as readline from 'readline';\r\nimport { tmpdir } from 'os';\r\nimport { join } from 'path';\r\nimport { readFile, unlink } from 'fs/promises';\r\nimport type { ToolOutput } from './types.js';\r\n\r\n// --- Browser process detection ------------------------------------------------\r\n\r\nconst BROWSER_PROCESSES = new Set([\r\n 'chrome', 'msedge', 'firefox', 'safari', 'brave', 'opera', 'vivaldi',\r\n 'chromium', 'arc', 'waterfox', 'librewolf', 'tor browser', 'iexplore',\r\n 'microsoftedge',\r\n]);\r\n\r\n/**\r\n * Check if a process name belongs to a known browser.\r\n * Handles case-insensitive matching and `.exe` suffix stripping.\r\n */\r\nexport function isBrowserProcess(processName: string): boolean {\r\n const normalized = processName.replace(/\\.exe$/i, '').toLowerCase();\r\n return BROWSER_PROCESSES.has(normalized);\r\n}\r\n\r\n// --- Window info parsing ------------------------------------------------------\r\n\r\nexport interface WindowInfo {\r\n title: string;\r\n processName: string;\r\n pid: number;\r\n isBrowser: boolean;\r\n}\r\n\r\n/**\r\n * Parse the JSON output from the PowerShell foreground-window script.\r\n */\r\nexport function deriveWindowInfo(raw: string): WindowInfo {\r\n const parsed = JSON.parse(raw);\r\n const title: string = parsed.title ?? '';\r\n const processName: string = parsed.processName ?? '';\r\n const pid: number = parsed.pid ?? 0;\r\n return {\r\n title,\r\n processName,\r\n pid,\r\n isBrowser: isBrowserProcess(processName),\r\n };\r\n}\r\n\r\n// --- Platform helpers ---------------------------------------------------------\r\n\r\nfunction runPowershell(script: string): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n const child = spawn('powershell', ['-NoProfile', '-Command', script], {\r\n stdio: ['ignore', 'pipe', 'pipe'],\r\n });\r\n let stdout = '';\r\n let stderr = '';\r\n child.stdout.on('data', (d: Buffer) => { stdout += d.toString(); });\r\n child.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\r\n child.on('close', (code) => {\r\n if (code === 0) resolve(stdout.trim());\r\n else reject(new Error(`PowerShell exited ${code}: ${stderr.trim()}`));\r\n });\r\n child.on('error', reject);\r\n });\r\n}\r\n\r\nfunction runCommand(cmd: string, args: string[]): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n const child = spawn(cmd, args, { stdio: ['ignore', 'pipe', 'pipe'] });\r\n let stdout = '';\r\n let stderr = '';\r\n child.stdout.on('data', (d: Buffer) => { stdout += d.toString(); });\r\n child.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });\r\n child.on('close', (code) => {\r\n if (code === 0) resolve(stdout.trim());\r\n else reject(new Error(`${cmd} exited ${code}: ${stderr.trim()}`));\r\n });\r\n child.on('error', reject);\r\n });\r\n}\r\n\r\n// --- Platform: get foreground window info -------------------------------------\r\n\r\nconst PS_GET_WINDOW = `\r\nAdd-Type @\"\r\nusing System;\r\nusing System.Runtime.InteropServices;\r\nusing System.Text;\r\nusing System.Diagnostics;\r\npublic class Win32Window {\r\n [DllImport(\"user32.dll\")] public static extern IntPtr GetForegroundWindow();\r\n [DllImport(\"user32.dll\", SetLastError=true, CharSet=CharSet.Auto)]\r\n public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);\r\n [DllImport(\"user32.dll\", SetLastError=true)]\r\n public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint pid);\r\n public static string GetInfo() {\r\n IntPtr hwnd = GetForegroundWindow();\r\n StringBuilder sb = new StringBuilder(256);\r\n GetWindowText(hwnd, sb, 256);\r\n uint pid = 0;\r\n GetWindowThreadProcessId(hwnd, out pid);\r\n string procName = \"\";\r\n try { procName = Process.GetProcessById((int)pid).ProcessName; } catch {}\r\n return \"{\\\\\"title\\\\\":\\\\\"\" + sb.ToString().Replace(\"\\\\\\\\\",\"\\\\\\\\\\\\\\\\\").Replace(\"\\\\\"\",\"\\\\\\\\\\\\\"\") +\r\n \"\\\\\",\\\\\"processName\\\\\":\\\\\"\" + procName +\r\n \"\\\\\",\\\\\"pid\\\\\":\" + pid + \"}\";\r\n }\r\n}\r\n\"@\r\n[Win32Window]::GetInfo()\r\n`;\r\n\r\nasync function getWindowInfoWin32(): Promise<WindowInfo> {\r\n const raw = await runPowershell(PS_GET_WINDOW);\r\n return deriveWindowInfo(raw);\r\n}\r\n\r\nasync function getWindowInfoDarwin(): Promise<WindowInfo> {\r\n const script = `\r\n tell application \"System Events\"\r\n set fp to first application process whose frontmost is true\r\n set t to name of first window of fp\r\n set n to name of fp\r\n set p to unix id of fp\r\n end tell\r\n return \"{\" & quote & \"title\" & quote & \":\" & quote & t & quote & \",\" & quote & \"processName\" & quote & \":\" & quote & n & quote & \",\" & quote & \"pid\" & quote & \":\" & p & \"}\"\r\n `;\r\n const raw = await runCommand('osascript', ['-e', script]);\r\n return deriveWindowInfo(raw);\r\n}\r\n\r\nasync function getWindowInfoLinux(): Promise<WindowInfo> {\r\n const title = await runCommand('xdotool', ['getactivewindow', 'getwindowname']);\r\n const pidStr = await runCommand('xdotool', ['getactivewindow', 'getwindowpid']);\r\n const pid = parseInt(pidStr, 10);\r\n let processName = '';\r\n try {\r\n processName = await runCommand('ps', ['-p', String(pid), '-o', 'comm=']);\r\n } catch { /* best-effort */ }\r\n return {\r\n title,\r\n processName,\r\n pid,\r\n isBrowser: isBrowserProcess(processName),\r\n };\r\n}\r\n\r\nasync function getWindowInfo(): Promise<WindowInfo> {\r\n switch (process.platform) {\r\n case 'win32': return getWindowInfoWin32();\r\n case 'darwin': return getWindowInfoDarwin();\r\n case 'linux': return getWindowInfoLinux();\r\n default: throw new Error(`Window capture not yet supported on ${process.platform}`);\r\n }\r\n}\r\n\r\n// --- Platform: capture browser text -------------------------------------------\r\n\r\nconst PS_CAPTURE_TEXT = `\r\nAdd-Type -AssemblyName System.Windows.Forms\r\n[System.Windows.Forms.SendKeys]::SendWait(\"^a\")\r\nStart-Sleep -Milliseconds 200\r\n[System.Windows.Forms.SendKeys]::SendWait(\"^c\")\r\nStart-Sleep -Milliseconds 300\r\nGet-Clipboard\r\n`;\r\n\r\nasync function captureTextWin32(): Promise<string> {\r\n return runPowershell(PS_CAPTURE_TEXT);\r\n}\r\n\r\nasync function captureTextDarwin(): Promise<string> {\r\n // Cmd+A, Cmd+C, then read clipboard\r\n await runCommand('osascript', ['-e', `\r\n tell application \"System Events\"\r\n keystroke \"a\" using command down\r\n delay 0.2\r\n keystroke \"c\" using command down\r\n delay 0.3\r\n end tell\r\n `]);\r\n return runCommand('pbpaste', []);\r\n}\r\n\r\nasync function captureTextLinux(): Promise<string> {\r\n // Ctrl+A, Ctrl+C, then read clipboard via xclip\r\n await runCommand('xdotool', ['key', 'ctrl+a']);\r\n await new Promise(r => setTimeout(r, 200));\r\n await runCommand('xdotool', ['key', 'ctrl+c']);\r\n await new Promise(r => setTimeout(r, 300));\r\n return runCommand('xclip', ['-selection', 'clipboard', '-o']);\r\n}\r\n\r\nasync function captureText(): Promise<string> {\r\n switch (process.platform) {\r\n case 'win32': return captureTextWin32();\r\n case 'darwin': return captureTextDarwin();\r\n case 'linux': return captureTextLinux();\r\n default: throw new Error(`Text capture not yet supported on ${process.platform}`);\r\n }\r\n}\r\n\r\n// --- Platform: capture screenshot ---------------------------------------------\r\n\r\nconst PS_SCREENSHOT = `\r\nparam([string]$OutPath)\r\nAdd-Type @\"\r\nusing System;\r\nusing System.Drawing;\r\nusing System.Drawing.Imaging;\r\nusing System.Runtime.InteropServices;\r\nusing System.IO;\r\npublic class ScreenCapture {\r\n [DllImport(\"user32.dll\")] public static extern IntPtr GetForegroundWindow();\r\n [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left, Top, Right, Bottom; }\r\n [DllImport(\"user32.dll\")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT rect);\r\n public static string Capture(string path) {\r\n IntPtr hwnd = GetForegroundWindow();\r\n RECT r; GetWindowRect(hwnd, out r);\r\n int w = r.Right - r.Left; int h = r.Bottom - r.Top;\r\n if (w <= 0 || h <= 0) return \"ERROR:Invalid window dimensions\";\r\n using (Bitmap bmp = new Bitmap(w, h))\r\n using (Graphics g = Graphics.FromImage(bmp)) {\r\n g.CopyFromScreen(r.Left, r.Top, 0, 0, new Size(w, h));\r\n bmp.Save(path, ImageFormat.Png);\r\n }\r\n return \"OK\";\r\n }\r\n}\r\n\"@\r\n[ScreenCapture]::Capture($OutPath)\r\n`;\r\n\r\nasync function captureScreenshotWin32(): Promise<{ data: string; path: string }> {\r\n const outPath = join(tmpdir(), `pk-capture-${Date.now()}.png`);\r\n const result = await runPowershell(\r\n PS_SCREENSHOT.replace('param([string]$OutPath)', `$OutPath = \"${outPath.replace(/\\\\/g, '\\\\\\\\')}\"`)\r\n );\r\n if (result.startsWith('ERROR:')) throw new Error(result);\r\n const buf = await readFile(outPath);\r\n const data = buf.toString('base64');\r\n // Clean up temp file\r\n await unlink(outPath).catch(() => {});\r\n return { data, path: outPath };\r\n}\r\n\r\nasync function captureScreenshotDarwin(): Promise<{ data: string; path: string }> {\r\n const outPath = join(tmpdir(), `pk-capture-${Date.now()}.png`);\r\n // screencapture -l <windowid> would be ideal, but -x (no sound) + current window is simpler\r\n await runCommand('screencapture', ['-x', '-o', outPath]);\r\n const buf = await readFile(outPath);\r\n const data = buf.toString('base64');\r\n await unlink(outPath).catch(() => {});\r\n return { data, path: outPath };\r\n}\r\n\r\nasync function captureScreenshotLinux(): Promise<{ data: string; path: string }> {\r\n const outPath = join(tmpdir(), `pk-capture-${Date.now()}.png`);\r\n const windowId = await runCommand('xdotool', ['getactivewindow']);\r\n await runCommand('import', ['-window', windowId, outPath]);\r\n const buf = await readFile(outPath);\r\n const data = buf.toString('base64');\r\n await unlink(outPath).catch(() => {});\r\n return { data, path: outPath };\r\n}\r\n\r\nasync function captureScreenshot(): Promise<{ data: string; path: string }> {\r\n switch (process.platform) {\r\n case 'win32': return captureScreenshotWin32();\r\n case 'darwin': return captureScreenshotDarwin();\r\n case 'linux': return captureScreenshotLinux();\r\n default: throw new Error(`Screenshot capture not yet supported on ${process.platform}`);\r\n }\r\n}\r\n\r\n// --- User interaction ---------------------------------------------------------\r\n\r\nfunction promptUser(reason: string): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n if (!process.stdin.isTTY) {\r\n resolve(false);\r\n return;\r\n }\r\n\r\n const border = '-'.repeat(60);\r\n process.stdout.write(`\\n+- Window Capture ${border.slice(17)}+\\n`);\r\n process.stdout.write(`| Agent says: \"${reason}\"\\n`);\r\n process.stdout.write(`|\\n`);\r\n process.stdout.write(`| Press [Enter] when ready, then click the target window.\\n`);\r\n process.stdout.write(`| You have 3 seconds after pressing Enter.\\n`);\r\n process.stdout.write(`| Type \"cancel\" to abort.\\n`);\r\n process.stdout.write(`+${border}+\\n`);\r\n\r\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\r\n rl.question('> ', (answer) => {\r\n rl.close();\r\n resolve(answer.trim().toLowerCase() !== 'cancel');\r\n });\r\n });\r\n}\r\n\r\nfunction countdown(seconds: number): Promise<void> {\r\n return new Promise((resolve) => {\r\n let remaining = seconds;\r\n const tick = () => {\r\n if (remaining <= 0) {\r\n process.stdout.write('\\n');\r\n resolve();\r\n return;\r\n }\r\n process.stdout.write(` Capturing in ${remaining}...${remaining > 1 ? ' ' : '\\n'}`);\r\n remaining--;\r\n setTimeout(tick, 1000);\r\n };\r\n tick();\r\n });\r\n}\r\n\r\n// --- Tool factory -------------------------------------------------------------\r\n\r\nexport interface CaptureWindowOptions {\r\n defaultDelay?: number | undefined;\r\n}\r\n\r\nexport function createCaptureWindowTool(options: CaptureWindowOptions = {}): Tool {\r\n const delaySeconds = options.defaultDelay ?? 3;\r\n\r\n const tool: Tool = {\r\n description:\r\n 'Capture the content of a window on the user\\'s screen. For browsers, extracts the page text. ' +\r\n 'For other applications, takes a screenshot. The user must click the target window during the countdown.',\r\n inputSchema: z.object({\r\n reason: z.string().describe('Why you need to see the window - shown to the user'),\r\n mode: z.enum(['auto', 'text', 'screenshot']).optional().default('auto')\r\n .describe('Override capture mode: auto detects browser vs non-browser'),\r\n }),\r\n execute: async ({ reason, mode }: { reason: string; mode?: string }): Promise<ToolOutput> => {\r\n // Check for interactive terminal\r\n if (!process.stdin.isTTY) {\r\n return { output: 'Capture requires an interactive terminal.' };\r\n }\r\n\r\n // Prompt user\r\n const proceed = await promptUser(reason);\r\n if (!proceed) {\r\n return { output: 'User cancelled the capture.' };\r\n }\r\n\r\n // Countdown\r\n await countdown(delaySeconds);\r\n\r\n // Get window info\r\n let windowInfo: WindowInfo;\r\n try {\r\n windowInfo = await getWindowInfo();\r\n } catch (err: any) {\r\n return { output: `Failed to get window info: ${err.message}` };\r\n }\r\n\r\n const effectiveMode = mode === 'auto' || !mode\r\n ? (windowInfo.isBrowser ? 'text' : 'screenshot')\r\n : mode;\r\n\r\n process.stdout.write(` Captured: \"${windowInfo.title}\" (${windowInfo.processName})`);\r\n\r\n if (effectiveMode === 'text') {\r\n process.stdout.write(` -> extracting text\\n`);\r\n try {\r\n const text = await captureText();\r\n if (!text || text.trim().length === 0) {\r\n // Fallback to screenshot if clipboard is empty\r\n process.stdout.write(` Clipboard empty, falling back to screenshot...\\n`);\r\n return await doScreenshot(windowInfo);\r\n }\r\n process.stdout.write(` [OK] Done (${text.length} chars)\\n`);\r\n return {\r\n output: `Window: ${windowInfo.title}\\nProcess: ${windowInfo.processName}\\n\\n${text}`,\r\n };\r\n } catch (err: any) {\r\n // Fallback to screenshot on text capture failure\r\n process.stdout.write(` Text capture failed, falling back to screenshot...\\n`);\r\n return await doScreenshot(windowInfo);\r\n }\r\n } else {\r\n process.stdout.write(` -> taking screenshot\\n`);\r\n return await doScreenshot(windowInfo);\r\n }\r\n },\r\n };\r\n\r\n // Attach toModelOutput for image support at runtime.\r\n // AI SDK v6 reads this to convert tool results into model-compatible content.\r\n (tool as any).toModelOutput = ({ output }: { output: ToolOutput }) => {\r\n if (output.metadata?.imageBase64) {\r\n return {\r\n type: 'content' as const,\r\n value: [\r\n { type: 'text' as const, text: `Window: ${output.metadata.windowTitle}\\nProcess: ${output.metadata.processName}` },\r\n { type: 'image-data' as const, data: output.metadata.imageBase64 as string, mediaType: 'image/png' as const },\r\n ],\r\n };\r\n }\r\n return { type: 'text' as const, value: output.output };\r\n };\r\n\r\n return tool;\r\n}\r\n\r\n// --- Internal helpers ---------------------------------------------------------\r\n\r\nasync function doScreenshot(windowInfo: WindowInfo): Promise<ToolOutput> {\r\n try {\r\n const { data } = await captureScreenshot();\r\n process.stdout.write(` [OK] Done (screenshot captured)\\n`);\r\n return {\r\n output: `Screenshot captured of: ${windowInfo.title} (${windowInfo.processName})`,\r\n metadata: {\r\n imageBase64: data,\r\n windowTitle: windowInfo.title,\r\n processName: windowInfo.processName,\r\n },\r\n };\r\n } catch (err: any) {\r\n return { output: `Screenshot failed: ${err.message}` };\r\n }\r\n}\r\n",
|
|
21
|
+
"import type { Tool } from 'ai';\nimport { z } from 'zod';\nimport { spawn } from 'child_process';\nimport * as fs from 'fs/promises';\nimport { PathValidator, type PathResolverContext } from './path-validator.js';\nimport { CommandValidator } from './command-validator.js';\nimport type { BashConfig, FilesystemPathConfig, FullstackApiSmokeRequest, FullstackToolsConfig, ToolOutput, ToolErrorOutput } from './types.js';\nimport { createSafeEnvironment } from './bash.js';\n\nconst DEFAULT_TEST_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes\nconst DEFAULT_HTTP_TIMEOUT_MS = 15_000;\nconst DEFAULT_MAX_OUTPUT = 64 * 1024; // 64KB total per stream\nconst FORCE_RESOLVE_AFTER_KILL_MS = 2000;\nconst DEFAULT_SERVER_STARTUP_TIMEOUT_MS = 20_000;\nconst DEFAULT_SERVER_READY_POLL_INTERVAL_MS = 250;\nconst DEFAULT_SERVER_STARTUP_DELAY_MS = 250;\n\nfunction truncateHead(text: string, maxBytes: number): { text: string; truncated: boolean } {\n const buf = Buffer.from(text, 'utf8');\n if (buf.length <= maxBytes) return { text, truncated: false };\n const truncatedBuf = buf.subarray(0, maxBytes);\n return { text: truncatedBuf.toString('utf8'), truncated: true };\n}\n\nclass TailBuffer {\n private readonly maxBytes: number;\n private chunks: Buffer[] = [];\n private totalBytes = 0;\n private didTruncate = false;\n\n constructor(maxBytes: number) {\n this.maxBytes = maxBytes;\n }\n\n append(buf: Buffer) {\n if (buf.length === 0) return;\n this.chunks.push(buf);\n this.totalBytes += buf.length;\n\n // Drop from the head to keep the last maxBytes (tail).\n while (this.totalBytes > this.maxBytes && this.chunks.length > 0) {\n const first = this.chunks[0]!;\n const over = this.totalBytes - this.maxBytes;\n if (first.length <= over) {\n this.chunks.shift();\n this.totalBytes -= first.length;\n this.didTruncate = true;\n continue;\n }\n // Partially drop from the first chunk.\n this.chunks[0] = first.subarray(over);\n this.totalBytes -= over;\n this.didTruncate = true;\n break;\n }\n }\n\n toString(): string {\n if (this.chunks.length === 0) return '';\n return Buffer.concat(this.chunks, this.totalBytes).toString('utf8');\n }\n\n truncated(): boolean {\n return this.didTruncate;\n }\n}\n\nasync function killProcessTree(pid: number): Promise<void> {\n if (process.platform === 'win32') {\n await new Promise<void>((resolve) => {\n const child = spawn('taskkill', ['/PID', String(pid), '/T', '/F'], {\n stdio: 'ignore',\n windowsHide: true,\n });\n child.on('close', () => resolve());\n child.on('error', () => resolve());\n });\n return;\n }\n\n try {\n process.kill(-pid, 'SIGKILL');\n } catch {\n try {\n process.kill(pid, 'SIGKILL');\n } catch {\n // ignore\n }\n }\n}\n\nasync function runShellCommand(opts: {\n command: string;\n cwd: string;\n timeoutMs: number;\n}): Promise<{\n success: boolean;\n exitCode: number | null;\n durationMs: number;\n timedOut: boolean;\n stdout: string;\n stderr: string;\n truncated: boolean;\n error?: string | undefined;\n}> {\n const start = Date.now();\n const stdoutTail = new TailBuffer(DEFAULT_MAX_OUTPUT);\n const stderrTail = new TailBuffer(DEFAULT_MAX_OUTPUT);\n let timedOut = false;\n let settled = false;\n\n return await new Promise((resolve) => {\n const child = spawn(opts.command, {\n shell: true,\n cwd: opts.cwd,\n // On Windows, detached processes may not reliably pipe stdout/stderr for console apps.\n // We can still kill the tree via taskkill, so keep detached=false there.\n detached: process.platform !== 'win32',\n env: createSafeEnvironment(opts.cwd),\n windowsHide: true,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n const finish = (exitCode: number | null, forced: boolean) => {\n if (settled) return;\n settled = true;\n const durationMs = Date.now() - start;\n resolve({\n success: exitCode === 0 && !timedOut,\n exitCode,\n durationMs,\n timedOut,\n stdout: stdoutTail.toString(),\n stderr: stderrTail.toString(),\n truncated: stdoutTail.truncated() || stderrTail.truncated() || forced,\n });\n };\n\n const timeoutHandle = setTimeout(async () => {\n timedOut = true;\n if (child.pid) {\n await killProcessTree(child.pid);\n }\n setTimeout(() => finish(null, true), FORCE_RESOLVE_AFTER_KILL_MS);\n }, opts.timeoutMs);\n\n child.stdout?.on('data', (d: Buffer) => {\n stdoutTail.append(d);\n });\n\n child.stderr?.on('data', (d: Buffer) => {\n stderrTail.append(d);\n });\n\n child.on('close', (code) => {\n clearTimeout(timeoutHandle);\n finish(typeof code === 'number' ? code : null, false);\n });\n\n child.on('error', (err) => {\n clearTimeout(timeoutHandle);\n if (settled) return;\n settled = true;\n resolve({\n success: false,\n exitCode: null,\n durationMs: Date.now() - start,\n timedOut,\n stdout: '',\n stderr: '',\n truncated: false,\n error: `Failed to execute command: ${err.message}`,\n });\n });\n });\n}\n\nasync function waitForHttpReady(opts: {\n url: string;\n expectStatus?: number | undefined;\n timeoutMs: number;\n pollIntervalMs: number;\n}): Promise<{ ok: boolean; status?: number; error?: string; durationMs: number }> {\n const start = Date.now();\n const deadline = start + opts.timeoutMs;\n while (Date.now() < deadline) {\n const controller = new AbortController();\n const reqTimeout = setTimeout(() => controller.abort(), Math.min(DEFAULT_HTTP_TIMEOUT_MS, opts.pollIntervalMs * 4));\n try {\n const res = await fetch(opts.url, { method: 'GET', signal: controller.signal });\n const ok = opts.expectStatus ? res.status === opts.expectStatus : res.ok;\n if (ok) {\n clearTimeout(reqTimeout);\n return { ok: true, status: res.status, durationMs: Date.now() - start };\n }\n } catch (err: any) {\n // ignore and keep polling\n void err;\n } finally {\n clearTimeout(reqTimeout);\n }\n\n await new Promise((r) => setTimeout(r, opts.pollIntervalMs));\n }\n return { ok: false, error: 'ready check timed out', durationMs: Date.now() - start };\n}\n\nfunction buildTestTool(opts: {\n name: 'backend' | 'frontend';\n command: string;\n timeoutMs: number;\n projectRoot: string;\n bashConfig?: BashConfig | undefined;\n pathContext: PathResolverContext;\n}): Tool {\n const label = opts.name === 'backend' ? 'backend' : 'frontend';\n const description =\n `Run ${label} tests for the current project and return a structured summary.\\n\\n` +\n `Default command:\\n` +\n ` ${opts.command}\\n\\n` +\n `Notes:\\n` +\n `- Requires tools.bash allowlist to be configured (command patterns).\\n` +\n `- Output is truncated for safety.\\n` +\n `- This tool does not attempt to auto-fix; it is intended to power a reliable test -> fix loop.\\n`;\n\n return {\n description,\n inputSchema: z.object({\n timeoutMs: z.number().int().positive().optional().describe(`Timeout in ms (default: ${opts.timeoutMs})`),\n }),\n execute: async ({ timeoutMs }: { timeoutMs?: number }): Promise<ToolOutput> => {\n const cmd = opts.command;\n const t = timeoutMs ?? opts.timeoutMs;\n\n // Do not bypass pk-agent's bash allowlist: require tools.bash to be configured.\n if (!opts.bashConfig || !opts.bashConfig.commands || opts.bashConfig.commands.length === 0) {\n const error: ToolErrorOutput = {\n success: false,\n error: 'Fullstack test tools require tools.bash to be configured (command allowlist).',\n };\n return { output: JSON.stringify(error) };\n }\n\n const validator = new CommandValidator(\n opts.bashConfig.commands,\n opts.projectRoot,\n opts.bashConfig.allowedPaths ?? [],\n opts.pathContext\n );\n const validation = await validator.validate(cmd);\n if (!validation.allowed) {\n const error: ToolErrorOutput = {\n success: false,\n error: validation.error || 'Command validation failed',\n };\n return { output: JSON.stringify(error) };\n }\n\n const result = await runShellCommand({\n command: cmd,\n cwd: opts.projectRoot,\n timeoutMs: t,\n });\n\n const payload = {\n success: result.success,\n command: cmd,\n exitCode: result.exitCode,\n timedOut: result.timedOut,\n durationMs: result.durationMs,\n truncated: result.truncated,\n stdoutTail: result.stdout,\n stderrTail: result.stderr,\n ...(result.error ? { error: result.error } : {}),\n };\n\n return { output: JSON.stringify(payload) };\n },\n };\n}\n\nfunction buildFrontendDebugTool(opts: {\n command: string;\n timeoutMs: number;\n projectRoot: string;\n bashConfig?: BashConfig | undefined;\n pathContext: PathResolverContext;\n}): Tool {\n const description =\n `Run a frontend debug command and (optionally) capture the current foreground window.\\n\\n` +\n `This is a \"shape-only\" harness tool aligned with FullStack-Agent's frontend debugging loop.\\n` +\n `It returns structured logs for deterministic iteration. A future implementation can swap in\\n` +\n `Playwright-based console/network collection without changing the interface.\\n\\n` +\n `Notes:\\n` +\n `- Requires tools.bash allowlist to be configured (command patterns).\\n` +\n `- Output is truncated for safety.\\n`;\n\n return {\n description,\n inputSchema: z.object({\n timeoutMs: z.number().int().positive().optional().describe(`Timeout in ms (default: ${opts.timeoutMs})`),\n capture: z.boolean().optional().describe('If true, capture the current foreground window after running the command (interactive only).'),\n captureOnFail: z.boolean().optional().describe('If true, capture only when the command fails (interactive only). Default true.'),\n captureReason: z.string().optional().describe('Optional reason shown to the user for the capture prompt.'),\n captureMode: z.enum(['auto', 'text', 'screenshot']).optional().describe('Capture mode override (auto detects browser).'),\n }),\n execute: async ({\n timeoutMs,\n capture,\n captureOnFail,\n captureReason,\n captureMode,\n }: {\n timeoutMs?: number;\n capture?: boolean;\n captureOnFail?: boolean;\n captureReason?: string;\n captureMode?: 'auto' | 'text' | 'screenshot';\n }): Promise<ToolOutput> => {\n const cmd = opts.command;\n const t = timeoutMs ?? opts.timeoutMs;\n\n if (!opts.bashConfig || !opts.bashConfig.commands || opts.bashConfig.commands.length === 0) {\n const error: ToolErrorOutput = {\n success: false,\n error: 'Fullstack frontend debug tool requires tools.bash to be configured (command allowlist).',\n };\n return { output: JSON.stringify(error) };\n }\n\n const validator = new CommandValidator(\n opts.bashConfig.commands,\n opts.projectRoot,\n opts.bashConfig.allowedPaths ?? [],\n opts.pathContext\n );\n const validation = await validator.validate(cmd);\n if (!validation.allowed) {\n const error: ToolErrorOutput = {\n success: false,\n error: validation.error || 'Command validation failed',\n };\n return { output: JSON.stringify(error) };\n }\n\n const result = await runShellCommand({\n command: cmd,\n cwd: opts.projectRoot,\n timeoutMs: t,\n });\n\n const shouldCapture = (() => {\n if (capture === true) return true;\n const onFail = captureOnFail ?? true;\n if (!onFail) return false;\n return !result.success;\n })();\n\n let captureResult: any = { attempted: false, skipped: true, reason: 'capture not requested or not applicable' };\n let captureMetadata: Record<string, unknown> | undefined;\n\n if (shouldCapture) {\n // Reuse the existing captureWindow implementation by invoking its tool.\n // This avoids a hard dependency on Playwright while still providing a user-in-the-loop\n // way to capture browser/app context when tests fail.\n try {\n const { createCaptureWindowTool } = await import('./capture-window.js');\n const captureTool: any = createCaptureWindowTool({});\n const reason = captureReason ?? `Frontend debug context capture (command failed): ${cmd}`;\n const res: any = await captureTool.execute({ reason, mode: captureMode ?? 'auto' });\n captureResult = { attempted: true, output: res?.output };\n if (res?.metadata && typeof res.metadata === 'object') {\n captureMetadata = res.metadata;\n captureResult.metadata = {\n windowTitle: (res.metadata as any).windowTitle,\n processName: (res.metadata as any).processName,\n };\n }\n } catch (err: any) {\n captureResult = { attempted: true, ok: false, error: err?.message ?? String(err) };\n }\n }\n\n const payload = {\n success: result.success,\n command: cmd,\n exitCode: result.exitCode,\n timedOut: result.timedOut,\n durationMs: result.durationMs,\n truncated: result.truncated,\n stdoutTail: result.stdout,\n stderrTail: result.stderr,\n ...(result.error ? { error: result.error } : {}),\n capture: captureResult,\n };\n\n // If capture produced an image, surface it via metadata so AI SDK can render it.\n if (captureMetadata && (captureMetadata as any).imageBase64) {\n return {\n output: JSON.stringify(payload),\n metadata: captureMetadata,\n };\n }\n\n return { output: JSON.stringify(payload) };\n },\n };\n}\n\nfunction buildApiSmokeTool(config: { requests?: FullstackApiSmokeRequest[] | undefined }): Tool {\n const description =\n `Run one or more HTTP requests (API smoke tests) and return structured results.\\n\\n` +\n `If 'requests' is omitted, this tool will use the configured apiSmoke list from the agent.\\n`;\n\n const RequestSchema = z.object({\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']).optional(),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n body: z.string().optional(),\n expectStatus: z.number().int().positive().optional(),\n timeoutMs: z.number().int().positive().optional(),\n }).strict();\n\n return {\n description,\n inputSchema: z.object({\n requests: z.array(RequestSchema).optional(),\n }),\n execute: async ({ requests }: { requests?: FullstackApiSmokeRequest[] }): Promise<ToolOutput> => {\n const list = (requests && requests.length > 0) ? requests : (config.requests ?? []);\n if (!list || list.length === 0) {\n const error: ToolErrorOutput = { success: false, error: 'No api smoke requests configured. Provide requests[] or set tools.fullstack.apiSmoke.' };\n return { output: JSON.stringify(error) };\n }\n\n const results: any[] = [];\n for (const req of list) {\n const method = (req.method ?? 'GET').toUpperCase();\n const timeoutMs = req.timeoutMs ?? DEFAULT_HTTP_TIMEOUT_MS;\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const start = Date.now();\n\n try {\n const init: RequestInit = {\n method,\n signal: controller.signal,\n };\n if (req.headers) init.headers = req.headers;\n if (req.body !== undefined) init.body = req.body;\n\n const res = await fetch(req.url, init);\n const durationMs = Date.now() - start;\n const ok = req.expectStatus ? res.status === req.expectStatus : res.ok;\n const text = await res.text().catch(() => '');\n const t = truncateHead(text, DEFAULT_MAX_OUTPUT);\n results.push({\n url: req.url,\n method,\n status: res.status,\n ok,\n durationMs,\n truncated: t.truncated,\n body: t.text,\n ...(req.expectStatus ? { expectStatus: req.expectStatus } : {}),\n });\n } catch (err: any) {\n const durationMs = Date.now() - start;\n results.push({\n url: req.url,\n method,\n ok: false,\n durationMs,\n error: err?.message ?? String(err),\n });\n } finally {\n clearTimeout(timer);\n }\n }\n\n const success = results.every((r) => r.ok === true);\n return { output: JSON.stringify({ success, results }) };\n },\n };\n}\n\nfunction buildBackendDebugTool(opts: {\n projectRoot: string;\n bashConfig?: BashConfig | undefined;\n pathContext: PathResolverContext;\n defaultServerCommand?: string | undefined;\n defaultReadyUrl?: string | undefined;\n defaultReadyExpectStatus?: number | undefined;\n defaultStartupTimeoutMs: number;\n defaultStartupDelayMs: number;\n defaultReadyPollIntervalMs: number;\n defaultRequests?: FullstackApiSmokeRequest[] | undefined;\n}): Tool {\n const description =\n `Start a backend server, wait for readiness, then run one or more HTTP smoke requests.\\n\\n` +\n `This is intended to mirror the \"Postman-like\" backend debugging tool described in FullStack-Agent.\\n` +\n `It captures backend stdout/stderr tails and returns them alongside the HTTP results.\\n\\n` +\n `Notes:\\n` +\n `- Requires tools.bash allowlist to be configured (command patterns).\\n` +\n `- Output is truncated for safety.\\n`;\n\n const RequestSchema = z.object({\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']).optional(),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n body: z.string().optional(),\n expectStatus: z.number().int().positive().optional(),\n timeoutMs: z.number().int().positive().optional(),\n }).strict();\n\n return {\n description,\n inputSchema: z.object({\n serverCommand: z.string().optional(),\n readyUrl: z.string().optional(),\n readyExpectStatus: z.number().int().positive().optional(),\n startupTimeoutMs: z.number().int().positive().optional(),\n startupDelayMs: z.number().int().nonnegative().optional(),\n readyPollIntervalMs: z.number().int().positive().optional(),\n requests: z.array(RequestSchema).optional(),\n }),\n execute: async (input: {\n serverCommand?: string;\n readyUrl?: string;\n readyExpectStatus?: number;\n startupTimeoutMs?: number;\n startupDelayMs?: number;\n readyPollIntervalMs?: number;\n requests?: FullstackApiSmokeRequest[];\n }): Promise<ToolOutput> => {\n const serverCommand = input.serverCommand ?? opts.defaultServerCommand;\n if (!serverCommand) {\n const error: ToolErrorOutput = { success: false, error: 'No backend serverCommand provided. Set tools.fullstack.backendServerCommand or pass serverCommand.' };\n return { output: JSON.stringify(error) };\n }\n\n // Do not bypass pk-agent's bash allowlist: require tools.bash to be configured.\n if (!opts.bashConfig || !opts.bashConfig.commands || opts.bashConfig.commands.length === 0) {\n const error: ToolErrorOutput = { success: false, error: 'Fullstack backend debug tool requires tools.bash to be configured (command allowlist).' };\n return { output: JSON.stringify(error) };\n }\n\n const validator = new CommandValidator(\n opts.bashConfig.commands,\n opts.projectRoot,\n opts.bashConfig.allowedPaths ?? [],\n opts.pathContext\n );\n const validation = await validator.validate(serverCommand);\n if (!validation.allowed) {\n const error: ToolErrorOutput = { success: false, error: validation.error || 'Command validation failed' };\n return { output: JSON.stringify(error) };\n }\n\n const readyUrl = input.readyUrl ?? opts.defaultReadyUrl;\n const readyExpectStatus = input.readyExpectStatus ?? opts.defaultReadyExpectStatus;\n const startupTimeoutMs = input.startupTimeoutMs ?? opts.defaultStartupTimeoutMs;\n const startupDelayMs = input.startupDelayMs ?? opts.defaultStartupDelayMs;\n const readyPollIntervalMs = input.readyPollIntervalMs ?? opts.defaultReadyPollIntervalMs;\n\n const requests = (input.requests && input.requests.length > 0) ? input.requests : (opts.defaultRequests ?? []);\n if (!requests || requests.length === 0) {\n const error: ToolErrorOutput = { success: false, error: 'No API smoke requests provided. Pass requests[] or set tools.fullstack.apiSmoke.' };\n return { output: JSON.stringify(error) };\n }\n\n const start = Date.now();\n const stdoutTail = new TailBuffer(DEFAULT_MAX_OUTPUT);\n const stderrTail = new TailBuffer(DEFAULT_MAX_OUTPUT);\n let exitCode: number | null = null;\n let pid: number | undefined;\n\n const child = spawn(serverCommand, {\n shell: true,\n cwd: opts.projectRoot,\n detached: process.platform !== 'win32',\n env: createSafeEnvironment(opts.projectRoot),\n windowsHide: true,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n pid = child.pid ?? undefined;\n\n const exitPromise = new Promise<void>((resolve) => {\n child.on('close', (code) => {\n exitCode = typeof code === 'number' ? code : null;\n resolve();\n });\n child.on('error', () => {\n exitCode = null;\n resolve();\n });\n });\n\n child.stdout?.on('data', (d: Buffer) => stdoutTail.append(d));\n child.stderr?.on('data', (d: Buffer) => stderrTail.append(d));\n\n let readyResult: any = null;\n let smokeResults: any[] | null = null;\n let smokeSuccess: boolean | null = null;\n let success = false;\n let toolError: string | undefined;\n try {\n // Best-effort delay for services that take a moment before binding a port.\n if (startupDelayMs > 0) {\n await new Promise((r) => setTimeout(r, startupDelayMs));\n }\n\n if (readyUrl) {\n const ready = await waitForHttpReady({\n url: readyUrl,\n expectStatus: readyExpectStatus,\n timeoutMs: startupTimeoutMs,\n pollIntervalMs: readyPollIntervalMs,\n });\n readyResult = ready;\n if (!ready.ok) {\n toolError = 'backend server did not become ready';\n success = false;\n }\n }\n\n if (!toolError) {\n // Run HTTP requests\n smokeResults = [];\n for (const req of requests) {\n const method = (req.method ?? 'GET').toUpperCase();\n const timeoutMs = req.timeoutMs ?? DEFAULT_HTTP_TIMEOUT_MS;\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const reqStart = Date.now();\n\n try {\n const init: RequestInit = { method, signal: controller.signal };\n if (req.headers) init.headers = req.headers;\n if (req.body !== undefined) init.body = req.body;\n\n const res = await fetch(req.url, init);\n const durationMs = Date.now() - reqStart;\n const ok = req.expectStatus ? res.status === req.expectStatus : res.ok;\n const text = await res.text().catch(() => '');\n const t = truncateHead(text, DEFAULT_MAX_OUTPUT);\n smokeResults.push({\n url: req.url,\n method,\n status: res.status,\n ok,\n durationMs,\n truncated: t.truncated,\n body: t.text,\n ...(req.expectStatus ? { expectStatus: req.expectStatus } : {}),\n });\n } catch (err: any) {\n const durationMs = Date.now() - reqStart;\n smokeResults.push({\n url: req.url,\n method,\n ok: false,\n durationMs,\n error: err?.message ?? String(err),\n });\n } finally {\n clearTimeout(timer);\n }\n }\n\n smokeSuccess = smokeResults.every((r) => r.ok === true);\n success = smokeSuccess;\n }\n } finally {\n if (pid) {\n await killProcessTree(pid);\n }\n // Make sure close handlers run to settle state (best-effort).\n await Promise.race([\n exitPromise,\n new Promise((r) => setTimeout(r, FORCE_RESOLVE_AFTER_KILL_MS)),\n ]);\n }\n\n const payload = {\n success,\n server: {\n command: serverCommand,\n pid,\n readyUrl,\n readyExpectStatus,\n ready: readyResult,\n exitCode,\n stdoutTail: stdoutTail.toString(),\n stderrTail: stderrTail.toString(),\n truncated: stdoutTail.truncated() || stderrTail.truncated(),\n },\n smoke: smokeResults ? { success: Boolean(smokeSuccess), results: smokeResults } : null,\n durationMs: Date.now() - start,\n ...(toolError ? { error: toolError } : {}),\n };\n\n return { output: JSON.stringify(payload) };\n },\n };\n}\n\nfunction buildReplaceTool(configs: FilesystemPathConfig[] | undefined, context: PathResolverContext): Tool {\n const description =\n `Deterministically edit a file by replacing an exact string with a new string.\\n\\n` +\n `This is stricter than fuzzy edit and is intended for reliable harness-style code edits.\\n` +\n `If the old string is not found, this tool fails.\\n`;\n\n const validator = new PathValidator(configs ?? [], context);\n\n return {\n description,\n inputSchema: z.object({\n file_path: z.string().describe('File path to edit (absolute or relative to project root)'),\n old_string: z.string().describe('Exact string to replace'),\n new_string: z.string().describe('Replacement string'),\n replace_all: z.boolean().optional().describe('Replace all occurrences (default false)'),\n }),\n execute: async ({ file_path, old_string, new_string, replace_all }: {\n file_path: string;\n old_string: string;\n new_string: string;\n replace_all?: boolean;\n }): Promise<ToolOutput> => {\n const validation = validator.validate(file_path, 'edit');\n if (!validation.allowed) {\n const error: ToolErrorOutput = {\n success: false,\n error: validation.error || 'Path validation failed',\n };\n return { output: JSON.stringify(error) };\n }\n\n const absPath = validation.resolvedPath;\n\n try {\n const content = await fs.readFile(absPath, 'utf8');\n const has = content.includes(old_string);\n if (!has) {\n const error: ToolErrorOutput = {\n success: false,\n error: 'old_string not found in file (strict replace)',\n };\n return { output: JSON.stringify(error) };\n }\n\n let updated: string;\n let replacements: number;\n if (replace_all) {\n const parts = content.split(old_string);\n replacements = parts.length - 1;\n updated = parts.join(new_string);\n } else {\n replacements = 1;\n updated = content.replace(old_string, new_string);\n }\n\n await fs.writeFile(absPath, updated, 'utf8');\n\n return { output: JSON.stringify({ success: true, path: absPath, replacements }) };\n } catch (err: any) {\n const error: ToolErrorOutput = {\n success: false,\n error: err?.message ?? String(err),\n };\n return { output: JSON.stringify(error) };\n }\n },\n };\n}\n\nfunction quoteSqliteIdent(name: string): string {\n // SQLite identifier quoting: double quotes, escape embedded quotes.\n return `\"${name.replace(/\"/g, '\"\"')}\"`;\n}\n\nfunction buildSqliteSnapshotTool(configs: FilesystemPathConfig[] | undefined, context: PathResolverContext): Tool {\n const description =\n `Snapshot an on-disk SQLite database into a structured JSON representation.\\n\\n` +\n `This is intended for FullStack-Agent-style \"valid DB\" checks where the harness needs to verify\\n` +\n `that UI/API actions correspond to real database state changes.\\n\\n` +\n `Notes:\\n` +\n `- Enforces tools.filesystem allowlist (read permission).\\n` +\n `- Uses Bun's SQLite module when available.\\n`;\n\n const validator = new PathValidator(configs ?? [], context);\n\n return {\n description,\n inputSchema: z.object({\n db_path: z.string().describe('Path to the SQLite database file (absolute or relative to project root)'),\n tables: z.array(z.string()).optional().describe('Optional list of tables to snapshot (default: all user tables)'),\n maxRows: z.number().int().positive().optional().describe('Maximum rows to include per table (default: 5)'),\n }),\n execute: async ({ db_path, tables, maxRows }: { db_path: string; tables?: string[]; maxRows?: number }): Promise<ToolOutput> => {\n const validation = validator.validate(db_path, 'read');\n if (!validation.allowed) {\n const error: ToolErrorOutput = {\n success: false,\n error: validation.error || 'Path validation failed',\n };\n return { output: JSON.stringify(error) };\n }\n\n // bun:sqlite is Bun-only. Keep this behind a dynamic import so Node runtimes can still load pk-agent.\n if ((globalThis as any).Bun === undefined) {\n const error: ToolErrorOutput = {\n success: false,\n error: 'SQLite snapshot requires Bun runtime (bun:sqlite).',\n };\n return { output: JSON.stringify(error) };\n }\n\n const absPath = validation.resolvedPath;\n const limit = maxRows ?? 5;\n\n try {\n const sqlite = await import('bun:sqlite');\n const db = new sqlite.Database(absPath, { readonly: true });\n\n try {\n const requested = tables && tables.length > 0 ? tables : undefined;\n\n const tableNames: string[] = requested ?? (db.query(\n \"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name\"\n ).all() as any[]).map((r) => String((r as any).name));\n\n const snapshotTables: any[] = [];\n for (const name of tableNames) {\n const qname = quoteSqliteIdent(name);\n const cols = (db.query(`PRAGMA table_info(${qname})`).all() as any[]).map((r) => String((r as any).name));\n const rows = db.query(`SELECT * FROM ${qname} LIMIT ${limit}`).all() as any[];\n snapshotTables.push({\n name,\n columns: cols,\n rows,\n });\n }\n\n return {\n output: JSON.stringify({\n success: true,\n path: absPath,\n maxRows: limit,\n tables: snapshotTables,\n }),\n };\n } finally {\n db.close();\n }\n } catch (err: any) {\n const error: ToolErrorOutput = {\n success: false,\n error: err?.message ?? String(err),\n };\n return { output: JSON.stringify(error) };\n }\n },\n };\n}\n\nfunction buildPlanValidateTool(): Tool {\n const description =\n `Validate a structured full-stack plan object.\\n\\n` +\n `This is intended to support a FullStack-Agent-style workflow where a planning step produces\\n` +\n `typed JSON that downstream backend/frontend agents consume.\\n` +\n `The schema is intentionally permissive (passthrough) but requires top-level keys.\\n`;\n\n const PlanSchema = z.object({\n backend: z.object({}).passthrough(),\n frontend: z.object({}).passthrough(),\n database: z.object({}).passthrough(),\n }).passthrough();\n\n return {\n description,\n inputSchema: z.object({\n plan: z.any().optional().describe('Plan object to validate (preferred)'),\n planJson: z.string().optional().describe('Plan as a JSON string (will be parsed)'),\n }).refine((v) => v.plan !== undefined || v.planJson !== undefined, {\n message: 'Provide either plan or planJson',\n }),\n execute: async ({ plan, planJson }: { plan?: any; planJson?: string }): Promise<ToolOutput> => {\n let obj: any = plan;\n if (obj === undefined && planJson !== undefined) {\n try {\n obj = JSON.parse(planJson);\n } catch (err: any) {\n const error: ToolErrorOutput = { success: false, error: `Invalid JSON: ${err?.message ?? String(err)}` };\n return { output: JSON.stringify(error) };\n }\n }\n\n const parsed = PlanSchema.safeParse(obj);\n if (!parsed.success) {\n return {\n output: JSON.stringify({\n success: false,\n error: 'Invalid fullstack plan',\n issues: parsed.error.issues.map((i) => ({\n path: i.path,\n message: i.message,\n code: i.code,\n })),\n }),\n };\n }\n\n return { output: JSON.stringify({ success: true, plan: parsed.data }) };\n },\n };\n}\n\nexport function createFullstackTools(\n fullstackConfig: FullstackToolsConfig,\n toolsConfig: { filesystem?: FilesystemPathConfig[] | undefined; bash?: BashConfig | undefined } | undefined,\n context: PathResolverContext\n): Record<string, Tool> {\n const cfg: any = fullstackConfig === true ? {} : (fullstackConfig ?? {});\n const backendCmd = String(cfg.backendTestCommand ?? 'bun test');\n const frontendCmd = String(cfg.frontendTestCommand ?? 'bun test');\n const frontendDebugCmd = String(cfg.frontendDebugCommand ?? cfg.frontendTestCommand ?? 'bun test');\n const timeoutMs = Number.isFinite(Number(cfg.testTimeoutMs)) ? Number(cfg.testTimeoutMs) : DEFAULT_TEST_TIMEOUT_MS;\n\n const projectRoot = context.projectRoot;\n const backendServerCommand = cfg.backendServerCommand !== undefined ? String(cfg.backendServerCommand) : undefined;\n const backendServerReadyUrl = cfg.backendServerReadyUrl !== undefined ? String(cfg.backendServerReadyUrl) : undefined;\n const backendServerReadyExpectStatus = Number.isFinite(Number(cfg.backendServerReadyExpectStatus))\n ? Number(cfg.backendServerReadyExpectStatus)\n : undefined;\n const backendServerStartupTimeoutMs = Number.isFinite(Number(cfg.backendServerStartupTimeoutMs))\n ? Number(cfg.backendServerStartupTimeoutMs)\n : DEFAULT_SERVER_STARTUP_TIMEOUT_MS;\n const backendServerStartupDelayMs = Number.isFinite(Number(cfg.backendServerStartupDelayMs))\n ? Number(cfg.backendServerStartupDelayMs)\n : DEFAULT_SERVER_STARTUP_DELAY_MS;\n const backendServerReadyPollIntervalMs = Number.isFinite(Number(cfg.backendServerReadyPollIntervalMs))\n ? Number(cfg.backendServerReadyPollIntervalMs)\n : DEFAULT_SERVER_READY_POLL_INTERVAL_MS;\n\n const tools: Record<string, Tool> = {};\n tools['tools__fullstack_backend_test'] = buildTestTool({\n name: 'backend',\n command: backendCmd,\n timeoutMs,\n projectRoot,\n bashConfig: toolsConfig?.bash,\n pathContext: context,\n });\n tools['tools__fullstack_frontend_test'] = buildTestTool({\n name: 'frontend',\n command: frontendCmd,\n timeoutMs,\n projectRoot,\n bashConfig: toolsConfig?.bash,\n pathContext: context,\n });\n tools['tools__fullstack_frontend_debug'] = buildFrontendDebugTool({\n command: frontendDebugCmd,\n timeoutMs,\n projectRoot,\n bashConfig: toolsConfig?.bash,\n pathContext: context,\n });\n tools['tools__fullstack_api_smoke'] = buildApiSmokeTool({\n requests: cfg.apiSmoke as FullstackApiSmokeRequest[] | undefined,\n });\n tools['tools__fullstack_backend_debug'] = buildBackendDebugTool({\n projectRoot,\n bashConfig: toolsConfig?.bash,\n pathContext: context,\n defaultServerCommand: backendServerCommand,\n defaultReadyUrl: backendServerReadyUrl,\n defaultReadyExpectStatus: backendServerReadyExpectStatus,\n defaultStartupTimeoutMs: backendServerStartupTimeoutMs,\n defaultStartupDelayMs: backendServerStartupDelayMs,\n defaultReadyPollIntervalMs: backendServerReadyPollIntervalMs,\n defaultRequests: cfg.apiSmoke as FullstackApiSmokeRequest[] | undefined,\n });\n tools['tools__fullstack_plan_validate'] = buildPlanValidateTool();\n tools['tools__fullstack_sqlite_snapshot'] = buildSqliteSnapshotTool(toolsConfig?.filesystem, context);\n tools['tools__fullstack_replace'] = buildReplaceTool(toolsConfig?.filesystem, context);\n\n return tools;\n}\n",
|
|
22
|
+
"import { z } from 'zod';\r\n\r\n// Zod schemas for validation\r\nexport const FilesystemPermissionSchema = z.enum(['read', 'write', 'edit']);\r\n\r\nexport const FilesystemPathConfigSchema = z.object({\r\n path: z.string().optional(),\r\n paths: z.array(z.string()).optional(),\r\n permissions: z.array(FilesystemPermissionSchema),\r\n}).refine(\r\n (data) => data.path !== undefined || data.paths !== undefined,\r\n { message: 'Either \"path\" or \"paths\" must be specified' }\r\n);\r\n\r\nexport const BashConfigSchema = z.object({\r\n commands: z.array(z.string()),\r\n timeout: z.number().positive().optional(),\r\n allowedPaths: z.array(z.string()).optional(),\r\n});\r\n\r\n// Optional OpenAI SDK tools (enabled explicitly in agent YAML under tools:)\r\nexport const CodexSdkToolConfigSchema = z.union([\r\n z.literal(true),\r\n z.object({}).strict(),\r\n]);\r\n\r\nexport const AgentsSdkToolConfigSchema = z.union([\r\n z.literal(true),\r\n z.object({\r\n // Default model override for the Agents SDK (OpenAI model id, e.g. \"gpt-5\").\r\n model: z.string().optional(),\r\n }).strict(),\r\n]);\r\n\r\nexport const CaptureWindowConfigSchema = z.union([\n z.literal(true),\n z.object({\n defaultDelay: z.number().positive().optional(),\n }).strict(),\n]);\n\nexport const FullstackApiSmokeRequestSchema = z.object({\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']).optional(),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n body: z.string().optional(),\n expectStatus: z.number().int().positive().optional(),\n timeoutMs: z.number().int().positive().optional(),\n}).strict();\n\nexport const FullstackToolsConfigSchema = z.union([\n z.literal(true),\n z.object({\n backendTestCommand: z.string().optional(),\n frontendTestCommand: z.string().optional(),\n // Optional command for frontend debugging runs (e.g., e2e runner).\n // If unset, frontend debug tool can fall back to frontendTestCommand.\n frontendDebugCommand: z.string().optional(),\n testTimeoutMs: z.number().int().positive().optional(),\n apiSmoke: z.array(FullstackApiSmokeRequestSchema).optional(),\n // Backend debug harness: start a backend server and run API smoke requests.\n // This mirrors the \"Postman-like\" backend debugging tool described in the FullStack-Agent paper.\n backendServerCommand: z.string().optional(),\n backendServerReadyUrl: z.string().optional(),\n backendServerReadyExpectStatus: z.number().int().positive().optional(),\n backendServerStartupTimeoutMs: z.number().int().positive().optional(),\n backendServerStartupDelayMs: z.number().int().nonnegative().optional(),\n backendServerReadyPollIntervalMs: z.number().int().positive().optional(),\n }).strict(),\n]);\n\n// Internal helper tool for building validated .pk-agent files (opt-in per agent).\nexport const PkAgentBuilderConfigSchema = z.union([\n z.literal(true),\n z.object({}).strict(),\n]);\n\nexport const ToolsConfigSchema = z.object({\n filesystem: z.array(FilesystemPathConfigSchema).optional(),\n bash: BashConfigSchema.optional(),\n codexSdk: CodexSdkToolConfigSchema.optional(),\n agentsSdk: AgentsSdkToolConfigSchema.optional(),\n captureWindow: CaptureWindowConfigSchema.optional(),\n fullstack: FullstackToolsConfigSchema.optional(),\n pkAgentBuilder: PkAgentBuilderConfigSchema.optional(),\n});\n\n// Derive types from Zod schemas\nexport type FilesystemPermission = z.infer<typeof FilesystemPermissionSchema>;\nexport type FilesystemPathConfig = z.infer<typeof FilesystemPathConfigSchema>;\nexport type BashConfig = z.infer<typeof BashConfigSchema>;\nexport type FullstackApiSmokeRequest = z.infer<typeof FullstackApiSmokeRequestSchema>;\nexport type FullstackToolsConfig = z.infer<typeof FullstackToolsConfigSchema>;\nexport type ToolsConfig = z.infer<typeof ToolsConfigSchema>;\n\r\n// Path validation result\r\nexport interface PathValidationResult {\r\n allowed: boolean;\r\n resolvedPath: string;\r\n error?: string;\r\n matchedPattern?: string;\r\n}\r\n\r\n// Command validation result\r\nexport interface CommandValidationResult {\r\n allowed: boolean;\r\n error?: string;\r\n matchedPattern?: string;\r\n}\r\n\r\n// Tool output format (matches existing MCP tools pattern)\r\nexport interface ToolOutput {\r\n output: string;\r\n metadata?: Record<string, unknown>;\r\n}\r\n\r\n// Error output format\r\nexport interface ToolErrorOutput {\r\n success: false;\r\n error: string;\r\n}\r\n",
|
|
23
|
+
"/**\n * Doom Loop Detector\n *\n * Detects when an agent is stuck in a loop calling the same tool\n * with identical arguments repeatedly.\n */\n\nexport interface ToolCall {\n name: string;\n args: unknown;\n}\n\nexport interface DoomLoopConfig {\n /** Maximum identical consecutive calls before triggering (default: 3) */\n threshold?: number;\n /** Action to take when loop detected: 'error' throws, 'warn' logs warning */\n action?: 'error' | 'warn';\n}\n\nexport class DoomLoopDetector {\n private readonly threshold: number;\n private readonly action: 'error' | 'warn';\n private readonly history: ToolCall[] = [];\n private readonly maxHistorySize = 10;\n\n constructor(config: DoomLoopConfig = {}) {\n this.threshold = config.threshold ?? 3;\n this.action = config.action ?? 'error';\n }\n\n /**\n * Recursively sort object keys for consistent comparison\n * Handles nested objects and arrays\n */\n private sortDeep(obj: unknown): unknown {\n if (Array.isArray(obj)) {\n return obj.map(item => this.sortDeep(item));\n }\n if (obj !== null && typeof obj === 'object') {\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(obj as Record<string, unknown>).sort()) {\n sorted[key] = this.sortDeep((obj as Record<string, unknown>)[key]);\n }\n return sorted;\n }\n return obj;\n }\n\n /**\n * Normalize arguments for comparison\n * Handles undefined, null, and deep object ordering\n */\n private normalizeArgs(args: unknown): string {\n if (args === undefined || args === null) {\n return 'null';\n }\n try {\n // Deep sort object keys for consistent comparison\n return JSON.stringify(this.sortDeep(args));\n } catch {\n return String(args);\n }\n }\n\n /**\n * Check if two tool calls are identical\n */\n private areIdentical(a: ToolCall, b: ToolCall): boolean {\n if (a.name !== b.name) return false;\n return this.normalizeArgs(a.args) === this.normalizeArgs(b.args);\n }\n\n /**\n * Count consecutive identical calls at the end of history\n */\n private countConsecutiveIdentical(): number {\n if (this.history.length < 2) return this.history.length;\n\n const latest = this.history[this.history.length - 1];\n let count = 1;\n\n for (let i = this.history.length - 2; i >= 0; i--) {\n if (this.areIdentical(this.history[i], latest)) {\n count++;\n } else {\n break;\n }\n }\n\n return count;\n }\n\n /**\n * Record a tool call and check for doom loop\n *\n * @param toolName Name of the tool being called\n * @param args Arguments passed to the tool\n * @returns Object with isLoop flag and count of consecutive identical calls\n * @throws Error if loop detected and action is 'error'\n */\n check(toolName: string, args: unknown): { isLoop: boolean; count: number } {\n const call: ToolCall = { name: toolName, args };\n\n // Add to history\n this.history.push(call);\n\n // Keep history bounded\n if (this.history.length > this.maxHistorySize) {\n this.history.shift();\n }\n\n // Check for consecutive identical calls\n const count = this.countConsecutiveIdentical();\n const isLoop = count >= this.threshold;\n\n if (isLoop) {\n const message = `Doom loop detected: ${toolName} called ${count} times with identical arguments`;\n\n if (this.action === 'error') {\n throw new DoomLoopError(message, toolName, args, count);\n } else {\n console.warn(`[DoomLoopDetector] ${message}`);\n }\n }\n\n return { isLoop, count };\n }\n\n /**\n * Reset the history (e.g., when starting a new task)\n */\n reset(): void {\n this.history.length = 0;\n }\n\n /**\n * Get the current history (for debugging)\n */\n getHistory(): readonly ToolCall[] {\n return this.history;\n }\n}\n\n/**\n * Error thrown when a doom loop is detected\n */\nexport class DoomLoopError extends Error {\n readonly toolName: string;\n readonly args: unknown;\n readonly count: number;\n\n constructor(message: string, toolName: string, args: unknown, count: number) {\n super(message);\n this.name = 'DoomLoopError';\n this.toolName = toolName;\n this.args = args;\n this.count = count;\n }\n}\n",
|
|
24
|
+
"import type { Tool } from 'ai';\nimport { z } from 'zod';\nimport type { ToolOutput } from './types.js';\nimport { logger } from '../utils/logger';\n\n// Lazy, memoized Codex client. This keeps startup fast for agents that don't use it.\nlet codexClient: any | undefined;\n\nasync function getCodexClient(): Promise<any> {\n if (codexClient) return codexClient;\n\n // The Codex SDK is optional (only needed when tools.codexSdk is enabled).\n const mod: any = await import('@openai/codex-sdk');\n codexClient = new mod.Codex();\n return codexClient;\n}\n\n/**\n * Codex SDK tool\n *\n * Runs a local Codex agent via @openai/codex-sdk.\n */\nexport function createCodexSdkTool(): Tool {\n return {\n description:\n 'Run a local Codex agent via the Codex SDK (@openai/codex-sdk). Returns the final output text and (when available) the thread id.',\n inputSchema: z.object({\n prompt: z.string().describe('Prompt to run in Codex'),\n threadId: z.string().optional().describe('Optional thread id to resume (e.g., thread_...)'),\n }),\n execute: async ({ prompt, threadId }): Promise<ToolOutput> => {\n try {\n const codex = await getCodexClient();\n const thread = threadId ? codex.resumeThread(threadId) : codex.startThread();\n\n const result = await thread.run(prompt);\n const output = typeof result === 'string' ? result : JSON.stringify(result, null, 2);\n\n const resolvedThreadId = thread?.id ?? threadId;\n\n return {\n output,\n ...(resolvedThreadId ? { metadata: { threadId: resolvedThreadId } } : {}),\n };\n } catch (err: any) {\n const message = err?.message || String(err);\n if (message.includes('Cannot find module') || message.includes('MODULE_NOT_FOUND')) {\n return {\n output: 'Codex SDK is not installed. Install it with: pnpm add @openai/codex-sdk',\n };\n }\n logger.debug(`[codex-sdk] tool failed: ${message}`);\n return { output: `Codex SDK tool failed: ${message}` };\n }\n },\n };\n}\n\n",
|
|
25
|
+
"import type { Tool } from 'ai';\nimport { z } from 'zod';\nimport type { ToolOutput } from './types.js';\nimport { logger } from '../utils/logger';\n\nexport interface AgentsSdkToolConfig {\n /** Default OpenAI model id (e.g., \"gpt-5\") */\n model?: string;\n}\n\nlet agentsSdkModule: any | undefined;\n\nasync function getAgentsSdkModule(): Promise<any> {\n if (agentsSdkModule) return agentsSdkModule;\n agentsSdkModule = await import('@openai/agents');\n return agentsSdkModule;\n}\n\n/**\n * OpenAI Agents SDK tool\n *\n * Runs an @openai/agents Agent as a single call (no PK Agent tool loop inside).\n */\nexport function createOpenAIAgentsSdkTool(config?: AgentsSdkToolConfig): Tool {\n return {\n description:\n 'Run an OpenAI Agents SDK agent (@openai/agents) with given instructions + input. Useful for delegating a self-contained task to the Agents SDK runtime.',\n inputSchema: z.object({\n instructions: z.string().describe('System instructions for the agent'),\n input: z.string().describe('User input / task for the agent'),\n name: z.string().optional().describe('Optional agent name'),\n model: z.string().optional().describe('Optional OpenAI model id override (e.g., gpt-5)'),\n }),\n execute: async ({ instructions, input, name, model }): Promise<ToolOutput> => {\n try {\n const mod: any = await getAgentsSdkModule();\n const Agent = mod.Agent;\n const run = mod.run;\n\n if (!Agent || !run) {\n return { output: 'Agents SDK is installed but missing expected exports (Agent, run).' };\n }\n\n const agentConfig: any = {\n name: name ?? 'pk-agent-agents-sdk',\n instructions,\n ...(model || config?.model ? { model: model ?? config?.model } : {}),\n };\n\n const agent = new Agent(agentConfig);\n const result = await run(agent, input);\n\n const output =\n result?.finalOutput ??\n result?.output_text ??\n result?.outputText ??\n result?.text ??\n (typeof result === 'string' ? result : JSON.stringify(result, null, 2));\n\n return { output: String(output ?? '') };\n } catch (err: any) {\n const message = err?.message || String(err);\n if (message.includes('Cannot find module') || message.includes('MODULE_NOT_FOUND')) {\n return {\n output: 'OpenAI Agents SDK is not installed. Install it with: pnpm add @openai/agents',\n };\n }\n if (message.toLowerCase().includes('api key') || message.includes('OPENAI_API_KEY')) {\n return { output: 'OpenAI Agents SDK tool failed: missing OPENAI_API_KEY.' };\n }\n logger.debug(`[openai-agents-sdk] tool failed: ${message}`);\n return { output: `OpenAI Agents SDK tool failed: ${message}` };\n }\n },\n };\n}\n\n",
|
|
26
|
+
"import { z } from 'zod';\n\n/**\n * Path safety\n * - Default policy: only safe, project-relative paths.\n * - Absolute paths are rejected here; allow them only with an explicit opt-in\n * at the builder layer (NOT recommended for default behavior).\n */\nexport function isSafeRelativePath(p: string): boolean {\n if (!p) return false;\n if (p.includes('\\0')) return false;\n\n // Disallow absolute Unix paths, Windows drive letters, and UNC paths\n if (p.startsWith('/') || /^[A-Za-z]:[\\\\/]/.test(p) || p.startsWith('\\\\\\\\')) return false;\n\n // Disallow parent traversal segments (posix + win separators)\n if (/(^|[\\\\/])\\.\\.([\\\\/]|$)/.test(p)) return false;\n\n return true;\n}\n\nexport function isHttpsUrl(s: string): boolean {\n try {\n const u = new URL(s);\n return u.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\nexport function isOpenAIFileId(s: string): boolean {\n return /^file-[A-Za-z0-9_-]+$/.test(s);\n}\n\nconst ProviderModelSchema = z\n .string()\n .min(3)\n .refine((s) => s.includes(':'), \"model must be 'provider:model-id'\");\n\nexport const ArchetypeSchema = z.enum([\n 'Writer',\n 'Engineer',\n 'Researcher',\n 'Sentinel',\n 'Connector',\n 'Orchestrator',\n]);\n\nexport const PermissionSchema = z.enum(['read', 'write', 'edit']);\n\nexport const FilesystemScopeSchema = z\n .object({\n paths: z.array(z.string().min(1)).min(1),\n permissions: z.array(PermissionSchema).min(1),\n })\n .strict()\n .superRefine((v, ctx) => {\n for (const p of v.paths) {\n if (!isSafeRelativePath(p)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `unsafe filesystem path: ${p}`,\n path: ['paths'],\n });\n }\n }\n });\n\nexport const BashToolSchema = z\n .object({\n commands: z.array(z.string().min(1)).min(1),\n timeout: z.number().int().positive().optional(),\n allowedPaths: z.array(z.string().min(1)).optional(),\n })\n .strict()\n .superRefine((v, ctx) => {\n if (v.allowedPaths) {\n for (const p of v.allowedPaths) {\n // Allow \".\" / \"./\" only with explicit confirmation in builder flow (enforce elsewhere).\n if (p === '.' || p === './') continue;\n if (!isSafeRelativePath(p)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `unsafe bash allowedPath: ${p}`,\n path: ['allowedPaths'],\n });\n }\n }\n }\n });\n\n/** Optional tool flags/objects (runtime extensions). */\nconst CodexSdkSchema = z.literal(true);\nconst AgentsSdkSchema = z.union([\n z.literal(true),\n z\n .object({\n model: ProviderModelSchema.optional(),\n })\n .strict(),\n]);\n\nconst CaptureWindowSchema = z.union([\n z.literal(true),\n z\n .object({\n defaultDelay: z.number().int().nonnegative().optional(),\n })\n .strict(),\n]);\n\nexport const ToolsSchema = z\n .object({\n filesystem: z.array(FilesystemScopeSchema).optional(),\n bash: BashToolSchema.optional(),\n codexSdk: CodexSdkSchema.optional(),\n agentsSdk: AgentsSdkSchema.optional(),\n captureWindow: CaptureWindowSchema.optional(),\n })\n .strict()\n .superRefine((v, ctx) => {\n if (!v.filesystem && !v.bash && !v.codexSdk && !v.agentsSdk && !v.captureWindow) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'tools cannot be empty (omit tools entirely if none are enabled)',\n });\n }\n });\n\nconst McpAuthSchema = z\n .object({\n type: z.enum(['bearer', 'api-key', 'oauth']),\n token: z.string().min(1),\n })\n .strict();\n\nexport const McpServerStdioSchema = z\n .object({\n command: z.string().min(1),\n args: z.array(z.string().min(1)).optional(),\n env: z.record(z.string(), z.string().min(1)).optional(),\n requiredEnvVars: z.array(z.string().min(1)).optional(),\n allowedEnvVars: z.array(z.string().min(1)).optional(),\n disallowedTools: z.array(z.string().min(1)).optional(),\n toolTimeout: z.number().int().positive().optional(),\n })\n .strict();\n\nexport const McpServerHttpSchema = z\n .object({\n url: z.string().url(),\n auth: McpAuthSchema.optional(),\n headers: z.record(z.string(), z.string().min(1)).optional(),\n requiredEnvVars: z.array(z.string().min(1)).optional(),\n })\n .strict();\n\nexport const McpServerSchema = z.union([McpServerStdioSchema, McpServerHttpSchema]);\n\nexport const McpServersSchema = z\n .record(z.string().min(1), McpServerSchema)\n .superRefine((m, ctx) => {\n if (Object.keys(m).length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'mcpServers cannot be empty (omit mcpServers entirely if none)',\n });\n }\n });\n\nexport const SubagentSchema = z\n .object({\n path: z.string().min(1),\n name: z.string().min(1).optional(),\n maxSteps: z.number().int().positive().optional(),\n })\n .strict()\n .superRefine((v, ctx) => {\n if (!isSafeRelativePath(v.path)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `unsafe subagent path: ${v.path}`,\n path: ['path'],\n });\n }\n });\n\nexport const OpenAISettingsSchema = z\n .object({\n reasoningEffort: z.enum(['low', 'medium', 'high']).optional(),\n textVerbosity: z.enum(['low', 'medium', 'high']).optional(),\n })\n .strict()\n .superRefine((v, ctx) => {\n if (!v.reasoningEffort && !v.textVerbosity) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'openai settings cannot be empty (omit openai entirely if unset)',\n });\n }\n });\n\n/**\n * FileRef:\n * - safe relative path (default)\n * - https URL\n * - OpenAI file id (\"file-...\")\n *\n * NOTE: This allows URLs/file-ids only in `files`, and only when model starts with \"openai:\".\n */\nexport const FileRefSchema = z\n .string()\n .min(1)\n .superRefine((s, ctx) => {\n const ok = isSafeRelativePath(s) || isHttpsUrl(s) || isOpenAIFileId(s);\n if (!ok) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `invalid file ref (must be safe relative path, https URL, or file-... id): ${s}`,\n });\n }\n });\n\nexport const FrontmatterSchema = z\n .object({\n model: ProviderModelSchema,\n description: z.string().min(1),\n version: z.string().min(1).default('0.1.0'),\n\n timeout: z.number().int().positive().optional(),\n maxSteps: z.number().int().positive().optional(),\n schedule: z.string().min(1).optional(),\n\n tools: ToolsSchema.optional(),\n mcpServers: McpServersSchema.optional(),\n subagents: z.array(SubagentSchema).optional(),\n\n openai: OpenAISettingsSchema.optional(),\n files: z.array(FileRefSchema).min(1).optional(),\n })\n .strict()\n .superRefine((fm, ctx) => {\n const isOpenAI = fm.model.startsWith('openai:');\n if (!isOpenAI && fm.openai) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"openai section is only allowed when model starts with 'openai:'\",\n path: ['openai'],\n });\n }\n if (!isOpenAI && fm.files) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"files section is only allowed when model starts with 'openai:'\",\n path: ['files'],\n });\n }\n });\n\nexport const InferenceCoreSchema = z\n .object({\n archetype: ArchetypeSchema,\n reasoning: z.string().min(1),\n filename: z\n .string()\n .min(1)\n .regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, 'filename must be kebab-case'),\n confidence: z\n .object({\n archetype: z.number().min(0).max(1),\n model: z.number().min(0).max(1),\n tools: z.number().min(0).max(1),\n schedule: z.number().min(0).max(1),\n mcp: z.number().min(0).max(1),\n subagents: z.number().min(0).max(1),\n })\n .strict(),\n frontmatter: FrontmatterSchema,\n markdown_body: z.string(),\n })\n .strict();\n\nexport type Frontmatter = z.infer<typeof FrontmatterSchema>;\nexport type InferenceCore = z.infer<typeof InferenceCoreSchema>;\n",
|
|
27
|
+
"import matter from 'gray-matter';\nimport YAML from 'yaml';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { InferenceCoreSchema, type InferenceCore, type Frontmatter } from './schemas.js';\n\n/**\n * Deep-omit empty values:\n * - removes: undefined, null\n * - removes: \"\" (optional toggle; default true)\n * - removes: empty arrays []\n * - removes: empty objects {}\n */\nexport function deepOmitEmpty<T>(\n value: T,\n opts: { omitEmptyString?: boolean } = { omitEmptyString: true }\n): T {\n const omitEmptyString = opts.omitEmptyString ?? true;\n\n const isEmptyString = (v: unknown) => omitEmptyString && typeof v === 'string' && v.trim() === '';\n const isNil = (v: unknown) => v === undefined || v === null;\n\n const recur = (v: any): any => {\n if (isNil(v)) return undefined;\n if (isEmptyString(v)) return undefined;\n\n if (Array.isArray(v)) {\n const arr = v.map(recur).filter((x) => x !== undefined);\n return arr.length ? arr : undefined;\n }\n\n if (typeof v === 'object') {\n const out: Record<string, any> = {};\n for (const [k, val] of Object.entries(v)) {\n const next = recur(val);\n if (next !== undefined) out[k] = next;\n }\n return Object.keys(out).length ? out : undefined;\n }\n\n return v;\n };\n\n return recur(value) as T;\n}\n\n/**\n * Keep YAML output stable by normalizing key order.\n * This intentionally does NOT include any wrapper metadata; only canonical frontmatter keys.\n */\nexport function canonicalizeFrontmatter(fm: Frontmatter): Record<string, any> {\n const out: Record<string, any> = {};\n\n // Canonical top-level order\n out.model = fm.model;\n out.description = fm.description;\n out.version = fm.version;\n\n if (fm.timeout !== undefined) out.timeout = fm.timeout;\n if (fm.maxSteps !== undefined) out.maxSteps = fm.maxSteps;\n if (fm.schedule !== undefined) out.schedule = fm.schedule;\n\n if (fm.tools) {\n const tools: Record<string, any> = {};\n if (fm.tools.filesystem) tools.filesystem = fm.tools.filesystem;\n if (fm.tools.bash) tools.bash = fm.tools.bash;\n if (fm.tools.codexSdk) tools.codexSdk = fm.tools.codexSdk;\n if (fm.tools.agentsSdk) tools.agentsSdk = fm.tools.agentsSdk;\n if (fm.tools.captureWindow) tools.captureWindow = fm.tools.captureWindow;\n out.tools = tools;\n }\n\n if (fm.mcpServers) out.mcpServers = fm.mcpServers;\n if (fm.subagents) out.subagents = fm.subagents;\n if (fm.openai) out.openai = fm.openai;\n if (fm.files) out.files = fm.files;\n\n return out;\n}\n\n/**\n * Deterministic YAML stringify settings (stable formatting).\n * - 2-space indent\n * - no line wrapping (so diffs are stable)\n * - no anchors\n */\nexport function stableYamlStringify(frontmatter: Record<string, any>): string {\n const doc = new YAML.Document(frontmatter, {\n // Prevent anchors/aliases.\n aliasDuplicateObjects: false,\n // Stable formatting defaults.\n toStringDefaults: {\n indent: 2,\n lineWidth: 0,\n },\n });\n\n return String(doc).trimEnd();\n}\n\n/**\n * Serialize the InferenceCore into a .pk-agent file:\n * - deep omit empties\n * - validate (core schema)\n * - stable YAML frontmatter\n * - round-trip parse to ensure it stays valid\n */\nexport function serializePkAgent(coreInput: InferenceCore): string {\n // 1) Normalize / omit empties\n const core = deepOmitEmpty(coreInput);\n\n // 2) Validate schema\n const parsed = InferenceCoreSchema.parse(core);\n\n // 3) Build file with stable YAML\n const yamlStr = stableYamlStringify(canonicalizeFrontmatter(parsed.frontmatter));\n const body = parsed.markdown_body ?? '';\n const file = `---\\n${yamlStr}\\n---\\n${body.startsWith('\\n') ? body.slice(1) : body}`;\n\n // 4) Round-trip parse and revalidate shape\n const roundTrip = matter(file);\n const roundTripCore: InferenceCore = {\n ...parsed,\n frontmatter: roundTrip.data as any,\n markdown_body: roundTrip.content,\n };\n InferenceCoreSchema.parse(roundTripCore);\n\n return file;\n}\n\n/**\n * Convenience: given filename, produce canonical file path under project or user scope.\n */\nexport function defaultAgentPath(filename: string, location: 'project' | 'user' = 'project'): string {\n const base = location === 'project'\n ? join('.pk-agent', 'agents')\n : join(homedir(), '.pk-agent', 'agents');\n return join(base, `${filename}.pk-agent`);\n}\n",
|
|
28
|
+
"import { z } from \"zod\";\n\n/**\n * Regex for interval format: 5s, 10m, 2h (sub-daily only)\n */\nexport const INTERVAL_REGEX = /^(\\d+)(s|m|h)$/;\n\n/**\n * Regex to detect cron expressions (5 or 6 space-separated fields)\n */\nexport const CRON_REGEX = /^[\\d*\\/,-]+(\\s+[\\d*\\/,-]+){4,5}$/;\n\n/**\n * Zod schema for schedule configuration in .pk-agent files\n *\n * Supports:\n * schedule: \"5m\" # interval\n * schedule: \"0 9 * * *\" # cron\n * schedule: \"daily at 9am\" # natural language\n */\nexport const ScheduleConfigSchema = z.string().min(1, \"Schedule value is required\");\n\nexport type ScheduleConfig = z.infer<typeof ScheduleConfigSchema>;\n\n/**\n * Runtime schedule state managed by Scheduler\n */\nexport interface Schedule {\n id: string;\n agentPath: string;\n expression: string; // Normalized cron expression\n timezone: string;\n enabled: boolean;\n source: \"yaml\";\n\n // Runtime state\n nextRun: Date | null;\n lastRun?: Date;\n lastResult?: {\n success: boolean;\n duration: number;\n error?: string;\n sessionId?: string;\n };\n\n createdAt: Date;\n}\n",
|
|
29
|
+
"import cronstrue from \"cronstrue\";\nimport { INTERVAL_REGEX, CRON_REGEX } from \"./types\";\n\n/**\n * Convert interval string to cron expression\n * @example \"5m\" -> every 5 minutes, \"1h\" -> every hour\n */\nfunction intervalToCron(interval: string): string {\n const match = interval.match(INTERVAL_REGEX);\n if (!match) {\n throw new Error(`Invalid interval format: ${interval}. Expected: 5s, 10m, 2h`);\n }\n\n const [, value, unit] = match;\n const num = parseInt(value, 10);\n\n switch (unit) {\n case \"s\":\n // Croner supports seconds as 6-field cron\n if (num >= 60) throw new Error(\"Seconds interval must be less than 60\");\n return `*/${num} * * * * *`;\n case \"m\":\n if (num >= 60) throw new Error(\"Minutes interval must be less than 60\");\n return `*/${num} * * * *`;\n case \"h\":\n if (num >= 24) throw new Error(\"Hours interval must be less than 24\");\n return `0 */${num} * * *`;\n default:\n throw new Error(`Unknown interval unit: ${unit}`);\n }\n}\n\n/**\n * Parse schedule expression into normalized cron expression\n *\n * Supports two formats (auto-detected):\n * - Interval: \"5s\", \"10m\", \"2h\", \"1d\"\n * - Cron: \"0 9 * * *\"\n */\nexport function parseScheduleExpression(value: string): string {\n const trimmed = value.trim();\n\n if (!trimmed) {\n throw new Error(\"Schedule expression cannot be empty\");\n }\n\n // 1. Check if it's an interval format (e.g., \"5m\", \"1h\")\n if (INTERVAL_REGEX.test(trimmed)) {\n return intervalToCron(trimmed);\n }\n\n // 2. Check if it's a cron expression (5 or 6 space-separated fields)\n if (CRON_REGEX.test(trimmed)) {\n return trimmed;\n }\n\n throw new Error(\n `Invalid schedule format: \"${value}\". Use interval (e.g., \"5m\", \"2h\") or cron (e.g., \"0 0 * * *\").`\n );\n}\n\n/**\n * Format a schedule expression into human-readable text\n * @example \"5m\" -> \"Every 5 minutes\", \"0 9 * * *\" -> \"At 09:00 AM\"\n */\nexport function formatScheduleHuman(value: string): string {\n const trimmed = value.trim();\n\n // Handle interval format\n if (INTERVAL_REGEX.test(trimmed)) {\n const match = trimmed.match(INTERVAL_REGEX);\n if (match) {\n const [, num, unit] = match;\n const n = parseInt(num, 10);\n const unitNames: Record<string, [string, string]> = {\n s: [\"second\", \"seconds\"],\n m: [\"minute\", \"minutes\"],\n h: [\"hour\", \"hours\"],\n };\n const [singular, plural] = unitNames[unit] || [unit, unit];\n return n === 1 ? `Every ${singular}` : `Every ${n} ${plural}`;\n }\n }\n\n // Handle cron format using cronstrue\n if (CRON_REGEX.test(trimmed)) {\n try {\n return cronstrue.toString(trimmed, { use24HourTimeFormat: false });\n } catch {\n return trimmed;\n }\n }\n\n return trimmed;\n}\n",
|
|
30
|
+
"import type { Tool } from 'ai';\nimport { z } from 'zod';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\nimport { homedir } from 'os';\nimport { InferenceCoreSchema, type InferenceCore, type Frontmatter } from '../agent-builder/schemas.js';\nimport { serializePkAgent, deepOmitEmpty } from '../agent-builder/utils.js';\nimport { findSecretMatches } from '../utils/redaction.js';\nimport { parseScheduleExpression } from '../scheduler/parser.js';\n\ntype LocationKind = 'project' | 'user' | 'custom';\n\ntype BuilderQuestion = {\n id: string;\n message: string;\n field?: string;\n default?: string;\n};\n\nfunction toTitleCaseFromKebab(name: string): string {\n const parts = name.split('-').filter(Boolean);\n if (!parts.length) return 'Agent';\n return parts.map((p) => p.slice(0, 1).toUpperCase() + p.slice(1)).join(' ');\n}\n\nfunction deriveKebabFilename(description: string): string {\n return description\n .toLowerCase()\n .slice(0, 80)\n .replace(/[^a-z0-9\\s-]/g, '')\n .trim()\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 50)\n || 'my-agent';\n}\n\nfunction isSafeCustomOutputPath(p: string): boolean {\n // Custom output is still constrained: no null bytes, no traversal, no absolute paths.\n if (!p) return false;\n if (p.includes('\\0')) return false;\n if (p.startsWith('/') || /^[A-Za-z]:[\\\\/]/.test(p) || p.startsWith('\\\\\\\\')) return false;\n if (/(^|[\\\\/])\\.\\.([\\\\/]|$)/.test(p)) return false;\n return true;\n}\n\nfunction looksLikeEnvPlaceholder(s: string): boolean {\n return /\\$\\{env:[A-Z0-9_]+\\}/.test(s);\n}\n\nfunction looksLikePlaceholderText(s: string): boolean {\n const v = s.toLowerCase();\n return v.includes('replace') || v.includes('changeme') || v.includes('example') || v.includes('dummy');\n}\n\nfunction suggestEnvVarName(keyPath: string[]): string {\n // Best-effort heuristics. Caller should still confirm with user.\n const lower = keyPath.map((k) => k.toLowerCase());\n\n const mcpIdx = lower.indexOf('mcpservers');\n if (mcpIdx >= 0 && lower.length > mcpIdx + 1) {\n const serverName = String(keyPath[mcpIdx + 1] ?? 'mcp').toUpperCase().replace(/[^A-Z0-9]+/g, '_');\n const last = String(keyPath[keyPath.length - 1] ?? '').toUpperCase().replace(/[^A-Z0-9]+/g, '_');\n if (last.includes('KEY')) return `${serverName}_API_KEY`;\n if (last.includes('TOKEN') || last.includes('AUTH')) return `${serverName}_TOKEN`;\n return `${serverName}_SECRET`;\n }\n\n const joined = lower.join('.');\n if (joined.includes('openai')) return 'OPENAI_API_KEY';\n if (joined.includes('anthropic')) return 'ANTHROPIC_API_KEY';\n if (joined.includes('github')) return 'GITHUB_TOKEN';\n if (joined.includes('slack')) return 'SLACK_TOKEN';\n\n return 'REPLACE_ME';\n}\n\nfunction scrubSecretsInFrontmatter(input: Frontmatter): {\n frontmatter: Frontmatter;\n warnings: string[];\n questions: BuilderQuestion[];\n} {\n const warnings: string[] = [];\n const questions: BuilderQuestion[] = [];\n\n const scrub = (obj: any, keyPath: string[]): any => {\n if (obj === null || obj === undefined) return obj;\n if (typeof obj === 'string') {\n const key = (keyPath[keyPath.length - 1] ?? '').toLowerCase();\n const isSecretKey =\n key.includes('token') ||\n key.includes('secret') ||\n key.includes('password') ||\n key.includes('authorization') ||\n key.includes('api_key') ||\n key.includes('apikey') ||\n key.endsWith('key') ||\n key.includes('webhook');\n\n if (isSecretKey) {\n if (!looksLikeEnvPlaceholder(obj) && !looksLikePlaceholderText(obj) && obj.trim().length >= 12) {\n const field = keyPath.join('.') || 'root';\n const envVar = suggestEnvVarName(keyPath);\n warnings.push(`Replaced secret-like value at ${field} with \\${env:${envVar}}`);\n questions.push({\n id: `env_var:${field}`,\n field,\n default: envVar,\n message: `Confirm env var for ${field} (suggested: ${envVar}).`,\n });\n return `\\${env:${envVar}}`;\n }\n }\n\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((v, i) => scrub(v, [...keyPath, String(i)]));\n }\n\n if (typeof obj === 'object') {\n const out: Record<string, any> = {};\n for (const [k, v] of Object.entries(obj)) {\n out[k] = scrub(v, [...keyPath, k]);\n }\n return out;\n }\n\n return obj;\n };\n\n const fm = scrub(input, []) as Frontmatter;\n return { frontmatter: fm, warnings, questions };\n}\n\nfunction removeBroadWriteScopes(\n input: Frontmatter,\n opts: { allowBroadWrite: boolean }\n): { frontmatter: Frontmatter; warnings: string[] } {\n if (opts.allowBroadWrite) return { frontmatter: input, warnings: [] };\n if (!input.tools?.filesystem?.length) return { frontmatter: input, warnings: [] };\n\n const warnings: string[] = [];\n const next = { ...input, tools: { ...input.tools } } as any;\n const fsScopes = (input.tools.filesystem ?? []).map((scope) => ({ ...scope, paths: [...scope.paths] }));\n\n const filtered = fsScopes\n .map((scope) => {\n const perms = new Set(scope.permissions);\n const hasWrite = perms.has('write') || perms.has('edit');\n const isBroad = scope.paths.some((p) => p === '.' || p === './');\n if (hasWrite && isBroad) {\n const removedWrite = perms.delete('write');\n const removedEdit = perms.delete('edit');\n if (removedWrite || removedEdit) {\n warnings.push('Removed write/edit permissions for filesystem scope with broad path \".\" or \"./\".');\n }\n }\n const permissions = Array.from(perms);\n return { ...scope, permissions };\n })\n .filter((scope) => scope.permissions.length > 0);\n\n next.tools.filesystem = filtered.length ? filtered : undefined;\n return { frontmatter: next as Frontmatter, warnings };\n}\n\nfunction normalizeSchedule(\n input: Frontmatter\n): { frontmatter: Frontmatter; warnings: string[]; questions: BuilderQuestion[] } {\n const warnings: string[] = [];\n const questions: BuilderQuestion[] = [];\n if (!input.schedule) return { frontmatter: input, warnings, questions };\n\n const raw = String(input.schedule).trim();\n if (!raw) {\n const next = { ...input } as any;\n next.schedule = undefined;\n return { frontmatter: next as Frontmatter, warnings, questions };\n }\n\n // If runtime parser accepts it, keep as-is (cron or interval).\n try {\n parseScheduleExpression(raw);\n return { frontmatter: { ...input, schedule: raw }, warnings, questions };\n } catch {\n // handled below\n }\n\n const normalized = raw.toLowerCase();\n const isDaily = normalized === 'daily' || normalized === 'every day' || normalized === 'each day';\n if (isDaily) {\n const cron = '0 9 * * *';\n warnings.push(`Normalized schedule \"${raw}\" -> \"${cron}\" (default daily at 9:00).`);\n questions.push({\n id: 'schedule:daily_confirm',\n field: 'schedule',\n default: cron,\n message: 'You asked for a daily schedule. Confirm the default cron (0 9 * * *) or provide a different cron/interval.',\n });\n return { frontmatter: { ...input, schedule: cron }, warnings, questions };\n }\n\n const next = { ...input } as any;\n next.schedule = undefined;\n warnings.push(`Omitted unsupported schedule \"${raw}\".`);\n questions.push({\n id: 'schedule:provide_valid',\n field: 'schedule',\n message: `Provide a supported schedule (interval like \"5m\" or cron like \"0 9 * * *\"). The previous value \"${raw}\" was not supported.`,\n });\n return { frontmatter: next as Frontmatter, warnings, questions };\n}\n\nfunction isRiskyBashPattern(pattern: string): boolean {\n const p = pattern.toLowerCase().trim();\n if (!p) return false;\n\n // Very conservative: block common destructive / escalation primitives.\n if (p.startsWith('sudo ') || p.startsWith('su ') || p.startsWith('doas ')) return true;\n if (p.startsWith('shutdown') || p.startsWith('reboot') || p.startsWith('halt') || p.startsWith('poweroff')) return true;\n if (p.startsWith('mkfs')) return true;\n if (/\\bdd\\b/.test(p) && /\\/dev\\//.test(p)) return true;\n\n // rm patterns (especially recursive/force or broad globs)\n if (/\\brm\\b/.test(p)) {\n if (/\\s-rf?\\b/.test(p) || /\\s-f\\b/.test(p) || /\\s-r\\b/.test(p)) return true;\n if (p.includes('*') || p.includes('~') || p.includes('/') || p.includes('\\\\')) return true;\n }\n\n // Pipes to network tools are commonly exfil patterns.\n if (p.includes('|') && /\\b(curl|wget|nc|netcat|ncat)\\b/.test(p)) {\n return true;\n }\n\n return false;\n}\n\nfunction stripRiskyBashAllowlist(\n input: Frontmatter,\n opts: { allowRiskyBash: boolean }\n): { frontmatter: Frontmatter; warnings: string[]; questions: BuilderQuestion[] } {\n const warnings: string[] = [];\n const questions: BuilderQuestion[] = [];\n if (opts.allowRiskyBash) return { frontmatter: input, warnings, questions };\n if (!input.tools?.bash?.commands?.length) return { frontmatter: input, warnings, questions };\n\n const original = input.tools.bash.commands;\n const kept = original.filter((cmd) => !isRiskyBashPattern(cmd));\n const removed = original.filter((cmd) => isRiskyBashPattern(cmd));\n\n if (!removed.length) return { frontmatter: input, warnings, questions };\n\n warnings.push(`Removed ${removed.length} risky bash allowlist pattern(s).`);\n questions.push({\n id: 'bash:risky_confirm',\n field: 'tools.bash.commands',\n message:\n `Some bash allowlist patterns were considered risky and were removed: ${removed.join(', ')}. ` +\n `Confirm you want them by re-running with confirm.allow_risky_bash=true.`,\n });\n\n const next = { ...input, tools: { ...input.tools, bash: { ...input.tools.bash, commands: kept } } } as any;\n if (!kept.length) {\n next.tools.bash = undefined;\n }\n return { frontmatter: next as Frontmatter, warnings, questions };\n}\n\nfunction buildFallbackCore(intent: {\n description: string;\n filename?: string;\n model?: string;\n title?: string;\n}): InferenceCore {\n const filename = intent.filename && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(intent.filename)\n ? intent.filename\n : deriveKebabFilename(intent.description);\n\n const title = (intent.title?.trim() || toTitleCaseFromKebab(filename)).slice(0, 80);\n\n return {\n archetype: 'Writer',\n reasoning: 'Manual fallback: generated minimal, valid agent from intent.',\n filename,\n confidence: {\n archetype: 0.0,\n model: 0.0,\n tools: 0.0,\n schedule: 0.0,\n mcp: 0.0,\n subagents: 0.0,\n },\n frontmatter: {\n model: intent.model?.trim() || 'anthropic:claude-sonnet-4-5',\n description: intent.description.trim(),\n version: '0.1.0',\n },\n markdown_body:\n `# ${title}\\n\\n` +\n `## Purpose\\n` +\n `${intent.description.trim()}\\n\\n` +\n `## Workflow\\n` +\n `1. Clarify inputs and outputs.\\n` +\n `2. Do the work.\\n` +\n `3. Report results and what changed.\\n\\n` +\n `## Rules\\n` +\n `- Never hardcode secrets; use \\${env:VAR}.\\n` +\n `- Prefer minimal tool scopes and project-relative paths.\\n`,\n };\n}\n\nfunction resolveOutputPath(params: {\n projectRoot: string;\n kind: LocationKind;\n filename: string;\n customPath?: string;\n}): string {\n if (params.kind === 'project') {\n return path.resolve(params.projectRoot, '.pk-agent', 'agents', `${params.filename}.pk-agent`);\n }\n if (params.kind === 'user') {\n return path.resolve(homedir(), '.pk-agent', 'agents', `${params.filename}.pk-agent`);\n }\n // custom\n if (!params.customPath) throw new Error('custom location requires path');\n if (!isSafeCustomOutputPath(params.customPath)) throw new Error(`unsafe custom output path: ${params.customPath}`);\n return path.resolve(params.projectRoot, params.customPath);\n}\n\nexport function createPkAgentBuilderTool(context: { projectRoot: string }): Tool {\n return {\n description:\n 'Build and write a validated .pk-agent file from strict InferenceCore JSON (or from minimal intent). ' +\n 'This tool enforces schema validation, deep-omits empty sections, scrubs secrets, and writes to a safe path.',\n inputSchema: z.object({\n // Either provide `core` or `intent`.\n core: InferenceCoreSchema.optional(),\n intent: z.object({\n description: z.string().min(1),\n filename: z.string().min(1).optional(),\n model: z.string().min(3).optional(),\n title: z.string().min(1).optional(),\n }).optional(),\n\n location: z.object({\n kind: z.enum(['project', 'user', 'custom']).default('project'),\n path: z.string().min(1).optional(),\n }).optional(),\n\n overwrite: z.boolean().optional(),\n dry_run: z.boolean().optional(),\n fallback_on_invalid_core: z.boolean().optional().default(true),\n confirm: z.object({\n allow_broad_write: z.boolean().optional(),\n allow_risky_bash: z.boolean().optional(),\n }).optional(),\n }),\n execute: async (input: any) => {\n const warnings: string[] = [];\n const questions: BuilderQuestion[] = [];\n const overwrite = Boolean(input.overwrite);\n const dryRun = Boolean(input.dry_run);\n const fallbackOnInvalid = input.fallback_on_invalid_core !== false;\n const allowBroadWrite = Boolean(input.confirm?.allow_broad_write);\n const allowRiskyBash = Boolean(input.confirm?.allow_risky_bash);\n\n let core: InferenceCore | null = null;\n\n if (input.core) {\n try {\n core = InferenceCoreSchema.parse(deepOmitEmpty(input.core));\n } catch (e: any) {\n if (!fallbackOnInvalid || !input.intent?.description) {\n return { output: JSON.stringify({ success: false, error: `Invalid core: ${e?.message ?? String(e)}` }) };\n }\n warnings.push('Core JSON was invalid; used fallback intent-based core instead.');\n }\n }\n\n if (!core) {\n if (!input.intent?.description) {\n return { output: JSON.stringify({ success: false, error: 'Provide either core or intent.description' }) };\n }\n core = buildFallbackCore(input.intent);\n }\n\n // Schedule normalization (write-time only). Never write unsupported natural language schedules.\n const sched = normalizeSchedule(core.frontmatter as any);\n core = { ...core, frontmatter: sched.frontmatter as any };\n warnings.push(...sched.warnings);\n questions.push(...sched.questions);\n\n // Bash allowlist safety gating (write-time only).\n const bashGate = stripRiskyBashAllowlist(core.frontmatter as any, { allowRiskyBash });\n core = { ...core, frontmatter: bashGate.frontmatter as any };\n warnings.push(...bashGate.warnings);\n questions.push(...bashGate.questions);\n\n // Enforce \"no broad write scopes\" unless explicitly allowed.\n const broad = removeBroadWriteScopes(core.frontmatter as any, { allowBroadWrite });\n core = { ...core, frontmatter: broad.frontmatter as any };\n warnings.push(...broad.warnings);\n\n // Scrub secret-like values in frontmatter before serialization.\n const scrubbed = scrubSecretsInFrontmatter(core.frontmatter as any);\n core = { ...core, frontmatter: scrubbed.frontmatter as any };\n warnings.push(...scrubbed.warnings);\n questions.push(...scrubbed.questions);\n\n // Serialize (schema-validated, stable YAML, round-trip checked).\n let content = '';\n try {\n content = serializePkAgent(core);\n } catch (e: any) {\n return { output: JSON.stringify({ success: false, error: e?.message ?? String(e) }) };\n }\n\n // Last-chance secret scan. If any secrets remain, redact them and warn.\n const matches = findSecretMatches(content, 50);\n if (matches.length) {\n warnings.push(`Redacted ${matches.length} secret-like value(s) in output. Replace with \\${env:VAR} placeholders.`);\n questions.push({\n id: 'secrets:review_redactions',\n message: 'Secret-like values were detected and replaced with ${env:REPLACE_ME}. Review the generated file and replace placeholders with real env var references.',\n });\n for (const m of matches) {\n content = content.replaceAll(m.value, '${env:REPLACE_ME}');\n }\n }\n\n const kind: LocationKind = (input.location?.kind ?? 'project') as LocationKind;\n const customPath: string | undefined = input.location?.path;\n\n const filePath = resolveOutputPath({\n projectRoot: context.projectRoot,\n kind,\n filename: core.filename,\n ...(customPath ? { customPath } : {}),\n });\n\n // Enforce .pk-agent extension.\n if (!filePath.toLowerCase().endsWith('.pk-agent')) {\n return { output: JSON.stringify({ success: false, error: `Output path must end with .pk-agent: ${filePath}` }) };\n }\n\n // Prevent writing outside projectRoot for custom paths (unless under projectRoot).\n if (kind === 'custom') {\n const rel = path.relative(context.projectRoot, filePath);\n if (rel.startsWith('..') || path.isAbsolute(rel)) {\n return { output: JSON.stringify({ success: false, error: 'Custom path must be within the project root' }) };\n }\n }\n\n // Check exists\n try {\n await fs.access(filePath);\n if (!overwrite) {\n return { output: JSON.stringify({ success: false, error: `File exists: ${filePath}`, path: filePath }) };\n }\n } catch {\n // ok\n }\n\n if (!dryRun) {\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await fs.writeFile(filePath, content, 'utf8');\n }\n\n return {\n output: JSON.stringify({\n success: true,\n path: filePath,\n bytesWritten: Buffer.byteLength(content, 'utf8'),\n wrote: !dryRun,\n warnings,\n questions,\n }),\n };\n },\n };\n}\n",
|
|
31
|
+
"import type { Tool } from 'ai';\r\nimport { createReadTool, createWriteTool, createEditTool } from './filesystem.js';\nimport type { ToolsConfig, FilesystemPathConfig } from './types.js';\nimport type { PathResolverContext } from './path-validator.js';\nimport { createFullstackTools } from './fullstack.js';\n\nexport { ToolsConfigSchema } from './types.js';\nexport type { ToolsConfig, FilesystemPathConfig, BashConfig } from './types.js';\nexport { DoomLoopDetector, DoomLoopError, type DoomLoopConfig, type ToolCall } from './doom-loop-detector.js';\nexport { resolveSafeVariables, type PathResolverContext } from './path-validator.js';\n\r\n/**\r\n * Create all configured tools\r\n *\r\n * @param config Tools configuration from agent YAML\r\n * @param context Path resolver context with projectRoot, agentDir, and tmpDir\r\n * @returns Record of tool name to Tool instance\r\n */\r\nexport async function getTools(\r\n config: ToolsConfig,\r\n context: PathResolverContext\r\n): Promise<Record<string, Tool>> {\r\n const tools: Record<string, Tool> = {};\r\n\r\n // Create filesystem tools if configured\r\n if (config.filesystem && config.filesystem.length > 0) {\r\n // Check which permissions are configured\r\n const hasRead = config.filesystem.some((c: FilesystemPathConfig) => c.permissions.includes('read'));\r\n const hasWrite = config.filesystem.some((c: FilesystemPathConfig) => c.permissions.includes('write'));\r\n const hasEdit = config.filesystem.some((c: FilesystemPathConfig) => c.permissions.includes('edit'));\r\n\r\n if (hasRead) {\r\n tools['tools__filesystem_read'] = createReadTool(config.filesystem, context);\r\n }\r\n\r\n if (hasWrite) {\r\n tools['tools__filesystem_write'] = createWriteTool(config.filesystem, context);\r\n }\r\n\r\n if (hasEdit) {\r\n tools['tools__filesystem_edit'] = createEditTool(config.filesystem, context);\r\n }\r\n }\r\n\r\n // Create bash tool if configured (lazy-load to defer tree-sitter WASM init)\r\n if (config.bash && config.bash.commands.length > 0) {\r\n const { createBashTool } = await import('./bash.js');\r\n tools['tools__bash'] = createBashTool(config.bash, context.projectRoot, context);\r\n }\r\n\r\n // Optional OpenAI SDK tools (lazy loaded to keep core lightweight)\r\n if (config.codexSdk) {\r\n const { createCodexSdkTool } = await import('./codex-sdk.js');\r\n tools['tools__codex_sdk'] = createCodexSdkTool();\r\n }\r\n\r\n if (config.agentsSdk) {\r\n const { createOpenAIAgentsSdkTool } = await import('./openai-agents-sdk.js');\r\n const agentsSdkConfig =\r\n typeof config.agentsSdk === 'object'\r\n ? (config.agentsSdk.model ? { model: config.agentsSdk.model } : {})\r\n : undefined;\r\n tools['tools__openai_agents_sdk'] = createOpenAIAgentsSdkTool(agentsSdkConfig);\r\n }\r\n\r\n if (config.captureWindow) {\n const { createCaptureWindowTool } = await import('./capture-window.js');\n tools['tools__capture_window'] = createCaptureWindowTool(\n typeof config.captureWindow === 'object' ? config.captureWindow : {}\n );\n }\n\n if (config.fullstack) {\n const fullstackTools = createFullstackTools(config.fullstack, { filesystem: config.filesystem, bash: config.bash }, context);\n Object.assign(tools, fullstackTools);\n }\n\n if (config.pkAgentBuilder) {\n const { createPkAgentBuilderTool } = await import('./pk-agent-builder.js');\n tools['tools__pk_agent_builder'] = createPkAgentBuilderTool({ projectRoot: context.projectRoot });\n }\n\n return tools;\n}\n",
|
|
32
|
+
"import { Cron } from \"croner\";\nimport { randomUUID } from \"crypto\";\nimport type { Schedule, ScheduleConfig } from \"./types\";\nimport { parseScheduleExpression } from \"./parser\";\nimport { logger, executionLog } from \"../utils/logger\";\n\nexport interface SchedulerOptions {\n onExecute: (schedule: Schedule) => Promise<{ success: boolean; duration: number; error?: string; sessionId?: string }>;\n}\n\n/**\n * In-memory scheduler for running agents on cron schedules\n */\nexport class Scheduler {\n private schedules: Map<string, Schedule> = new Map();\n private jobs: Map<string, Cron> = new Map();\n private onExecute: SchedulerOptions[\"onExecute\"];\n\n constructor(options: SchedulerOptions) {\n this.onExecute = options.onExecute;\n }\n\n /**\n * Add a schedule for an agent\n */\n add(agentPath: string, config: ScheduleConfig): Schedule {\n const id = randomUUID();\n const expression = parseScheduleExpression(config);\n const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n\n const schedule: Schedule = {\n id,\n agentPath,\n expression,\n timezone,\n enabled: true,\n source: \"yaml\",\n nextRun: null,\n createdAt: new Date(),\n };\n\n this.schedules.set(id, schedule);\n this.startJob(schedule);\n\n return schedule;\n }\n\n /**\n * Start a cron job for a schedule\n */\n private startJob(schedule: Schedule): void {\n const job = new Cron(\n schedule.expression,\n {\n timezone: schedule.timezone,\n },\n async () => {\n await this.runSchedule(schedule.id);\n }\n );\n\n this.jobs.set(schedule.id, job);\n schedule.nextRun = job.nextRun() || null;\n }\n\n /**\n * Execute a scheduled agent run\n */\n private async runSchedule(scheduleId: string): Promise<void> {\n const schedule = this.schedules.get(scheduleId);\n if (!schedule || !schedule.enabled) return;\n\n executionLog.start(schedule.agentPath);\n\n const startTime = Date.now();\n\n try {\n const result = await this.onExecute(schedule);\n\n schedule.lastRun = new Date();\n schedule.lastResult = result;\n\n // Update next run time\n const job = this.jobs.get(scheduleId);\n schedule.nextRun = job?.nextRun() || null;\n\n if (result.success) {\n executionLog.complete(schedule.agentPath, result.duration);\n } else {\n executionLog.failed(schedule.agentPath, result.duration, result.error);\n }\n } catch (error) {\n const duration = Date.now() - startTime;\n schedule.lastRun = new Date();\n schedule.lastResult = {\n success: false,\n duration,\n error: (error as Error).message,\n };\n\n // Update next run time\n const job = this.jobs.get(scheduleId);\n schedule.nextRun = job?.nextRun() || null;\n\n executionLog.failed(schedule.agentPath, duration, (error as Error).message);\n logger.debug(`Schedule ${scheduleId} failed: ${(error as Error).message}`);\n }\n }\n\n /**\n * Trigger immediate execution of a schedule\n */\n async trigger(scheduleId: string): Promise<void> {\n await this.runSchedule(scheduleId);\n }\n\n /**\n * Get a schedule by ID\n */\n get(scheduleId: string): Schedule | undefined {\n return this.schedules.get(scheduleId);\n }\n\n /**\n * List all schedules\n */\n list(): Schedule[] {\n return Array.from(this.schedules.values());\n }\n\n /**\n * Find a schedule by agent path\n */\n getByAgentPath(agentPath: string): Schedule | undefined {\n for (const schedule of this.schedules.values()) {\n if (schedule.agentPath === agentPath) {\n return schedule;\n }\n }\n return undefined;\n }\n\n /**\n * Remove a schedule by agent path\n * @returns true if a schedule was removed, false if not found\n */\n removeByAgentPath(agentPath: string): boolean {\n const schedule = this.getByAgentPath(agentPath);\n if (!schedule) {\n return false;\n }\n\n // Stop the cron job\n const job = this.jobs.get(schedule.id);\n if (job) {\n job.stop();\n this.jobs.delete(schedule.id);\n }\n\n // Remove the schedule\n this.schedules.delete(schedule.id);\n\n logger.debug(`Scheduler: Removed schedule for ${agentPath}`);\n return true;\n }\n\n /**\n * Update a schedule for an agent (removes old, adds new)\n * @returns The new schedule, or undefined if no schedule config provided\n */\n update(agentPath: string, config: ScheduleConfig | undefined): Schedule | undefined {\n // Always remove existing schedule first\n this.removeByAgentPath(agentPath);\n\n // Add new schedule if config provided\n if (config) {\n return this.add(agentPath, config);\n }\n\n return undefined;\n }\n\n /**\n * Get count of enabled schedules\n */\n get count(): number {\n return this.schedules.size;\n }\n\n /**\n * Stop all jobs (for graceful shutdown)\n */\n shutdown(): void {\n for (const job of this.jobs.values()) {\n job.stop();\n }\n this.jobs.clear();\n logger.debug(\"Scheduler: All scheduled jobs stopped\");\n }\n\n /**\n * Convert cron expression to human-readable format\n */\n private cronToHuman(expression: string): string {\n const parts = expression.split(\" \");\n if (parts.length !== 5) return expression;\n\n const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;\n\n const dayNames: Record<string, string> = {\n \"0\": \"Sun\",\n \"1\": \"Mon\",\n \"2\": \"Tue\",\n \"3\": \"Wed\",\n \"4\": \"Thu\",\n \"5\": \"Fri\",\n \"6\": \"Sat\",\n \"7\": \"Sun\",\n };\n\n const formatTime = (h: string, m: string): string => {\n const hourNum = parseInt(h, 10);\n const minNum = parseInt(m, 10);\n const period = hourNum >= 12 ? \"pm\" : \"am\";\n const hour12 = hourNum === 0 ? 12 : hourNum > 12 ? hourNum - 12 : hourNum;\n return minNum === 0 ? `${hour12}${period}` : `${hour12}:${m.padStart(2, \"0\")}${period}`;\n };\n\n const formatDays = (dow: string): string => {\n if (dow === \"*\") return \"\";\n const days = dow.split(\",\").map((d) => dayNames[d] || d);\n return days.join(\", \");\n };\n\n // Every N hours pattern: 0 */N * * *\n if (hour.startsWith(\"*/\") && minute === \"0\" && dayOfMonth === \"*\" && month === \"*\" && dayOfWeek === \"*\") {\n const interval = hour.slice(2);\n return `Every ${interval}h`;\n }\n\n // Daily pattern: M H * * *\n if (dayOfMonth === \"*\" && month === \"*\" && dayOfWeek === \"*\" && !hour.includes(\"*\") && !minute.includes(\"*\")) {\n return `Daily ${formatTime(hour, minute)}`;\n }\n\n // Specific days pattern: M H * * D,D\n if (dayOfMonth === \"*\" && month === \"*\" && dayOfWeek !== \"*\" && !hour.includes(\"*\") && !minute.includes(\"*\")) {\n const days = formatDays(dayOfWeek);\n return `${days} ${formatTime(hour, minute)}`;\n }\n\n // Fallback to original expression\n return expression;\n }\n\n /**\n * Format schedules for display on server startup\n */\n formatScheduleTable(): string {\n const schedules = this.list();\n if (schedules.length === 0) {\n return \"\";\n }\n\n // Sort by next run time (soonest first, null/disabled at end)\n schedules.sort((a, b) => {\n if (!a.nextRun) return 1;\n if (!b.nextRun) return -1;\n return a.nextRun.getTime() - b.nextRun.getTime();\n });\n\n // Pre-calculate human-readable schedules for width calculation\n const schedulesWithHuman = schedules.map((s) => ({\n schedule: s,\n humanSchedule: this.cronToHuman(s.expression),\n nextRunStr: s.nextRun\n ? s.nextRun.toLocaleString(\"en-US\", {\n month: \"short\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false,\n })\n : \"N/A\",\n }));\n\n // Calculate column widths for alignment\n const maxNextRunWidth = Math.max(...schedulesWithHuman.map((s) => s.nextRunStr.length));\n const maxAgentWidth = Math.max(...schedulesWithHuman.map((s) => s.schedule.agentPath.length));\n\n const lines: string[] = [];\n\n for (const { schedule, humanSchedule, nextRunStr } of schedulesWithHuman) {\n const nextRunCol = nextRunStr.padEnd(maxNextRunWidth);\n const agentCol = schedule.agentPath.padEnd(maxAgentWidth);\n\n lines.push(` ${nextRunCol} ${agentCol} ${humanSchedule}`);\n }\n\n return lines.join(\"\\n\");\n }\n}\n",
|
|
33
|
+
"export { Scheduler, type SchedulerOptions } from \"./scheduler\";\nexport { ScheduleConfigSchema, type ScheduleConfig, type Schedule } from \"./types\";\nexport { parseScheduleExpression } from \"./parser\";\n",
|
|
34
|
+
"import matter from 'gray-matter';\nimport { z } from 'zod';\nimport { readFile } from 'fs/promises';\nimport { resolve, basename, parse as parsePath } from 'path';\nimport { ToolsConfigSchema } from './tools/index.js';\r\nimport { ScheduleConfigSchema } from './scheduler/index.js';\r\n\r\n/**\r\n * Error thrown when agent configuration is invalid\r\n * Used for telemetry to track common config issues without exposing sensitive data\r\n */\r\nexport class ConfigError extends Error {\r\n constructor(\r\n message: string,\r\n public field: string, // e.g., \"model\", \"mcpServers.foo\" (for telemetry)\r\n public issue: string // Zod error code: \"invalid_type\", \"unrecognized_keys\", etc. (for telemetry)\r\n ) {\r\n super(message);\r\n this.name = 'ConfigError';\r\n }\r\n}\r\n\r\nfunction isOpenAIModel(model: string): boolean {\r\n const parts = model.split(':');\r\n return parts.length === 1 || parts[0] === 'openai';\r\n}\r\n\r\n// Schema for MCP server configuration\nconst MCPHttpAuthSchema = z.object({\n // Default to bearer when omitted (legacy config).\n type: z.enum(['bearer', 'api-key', 'oauth']).optional(),\n // If auth is present, a non-empty token must be provided.\n token: z.string().min(1),\n}).strict();\n\nconst MCPServerSchema = z.union([\n // Stdio configuration (has command)\n z.object({\n command: z.string(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\r\n requiredEnvVars: z.array(z.string()).optional(),\r\n allowedEnvVars: z.array(z.string()).optional(),\r\n disallowedTools: z.array(z.string()).optional(),\r\n toolTimeout: z.number().positive().optional()\r\n }),\r\n // HTTP configuration (has url)\r\n z.object({\n url: z.string().url().refine(\n (url) => url.startsWith('http://') || url.startsWith('https://'),\n { message: 'URL must use http:// or https:// protocol' }\n ),\n sessionId: z.string().optional(),\n auth: MCPHttpAuthSchema.optional(),\n headers: z.record(z.string(), z.string()).optional(),\n requiredEnvVars: z.array(z.string()).optional(),\n allowedEnvVars: z.array(z.string()).optional(),\n disallowedTools: z.array(z.string()).optional(),\n toolTimeout: z.number().positive().optional()\r\n })\r\n]);\r\n\r\n// Schema for agent configuration as per spec\r\nconst AgentSchema = z.object({\r\n model: z.string(),\r\n description: z.string().optional(),\r\n version: z.string().optional(),\r\n notes: z.string().optional(),\r\n timeout: z.number().positive().optional(),\r\n maxSteps: z.number().positive().int().optional(),\r\n /**\r\n * Optional file attachments (currently PDF only via OpenAI).\r\n *\r\n * Accepted values:\r\n * - Local path (resolved relative to the agent file)\r\n * - HTTPS URL\r\n * - OpenAI Files API id (e.g. file-xxxx)\r\n */\r\n files: z.array(z.string()).optional(),\r\n openai: z.object({\r\n reasoningEffort: z.enum(['low', 'medium', 'high']).optional(),\r\n textVerbosity: z.enum(['low', 'medium', 'high']).optional()\r\n }).strict().optional(),\r\n mcpServers: z.record(z.string(), MCPServerSchema).optional(),\r\n subagents: z.array(z.object({\r\n path: z.string(),\r\n name: z.string().optional(),\r\n maxSteps: z.number().optional()\r\n })).optional(),\r\n tools: ToolsConfigSchema.optional(),\r\n schedule: ScheduleConfigSchema.optional()\r\n}).superRefine((data, ctx) => {\r\n if (data.openai && !isOpenAIModel(data.model)) {\r\n ctx.addIssue({\r\n code: z.ZodIssueCode.custom,\r\n path: ['openai'],\r\n message: 'OpenAI options are only valid when using an OpenAI model.'\r\n });\r\n }\r\n if (data.files && data.files.length > 0 && !isOpenAIModel(data.model)) {\r\n ctx.addIssue({\r\n code: z.ZodIssueCode.custom,\r\n path: ['files'],\r\n message: 'File attachments are only supported when using an OpenAI model.'\r\n });\r\n }\r\n});\r\n\r\nexport type AgentConfig = z.infer<typeof AgentSchema>;\r\n\r\nexport interface ParsedAgent {\r\n name: string;\r\n config: AgentConfig;\r\n instructions: string;\r\n description?: string;\r\n}\r\n\r\n/**\r\n * Parse agent from markdown content with YAML frontmatter\r\n * @param content The markdown content with YAML frontmatter\r\n * @param name The name of the agent\r\n * @returns Parsed agent configuration and instructions\r\n */\r\nexport function parseAgentContent(content: string, name: string): ParsedAgent {\n try {\n // Parse YAML frontmatter\n const { data, content: instructions } = matter(content);\n\n // Validate configuration with Zod\n const config = AgentSchema.parse(data);\n\r\n // Return parsed agent\r\n return {\r\n name,\r\n config,\r\n instructions: instructions.trim(),\r\n ...(config.description && { description: config.description })\r\n };\r\n } catch (error) {\n const errAny: any = error as any;\n const hasYamlMark = !!errAny?.mark && typeof errAny?.mark?.line === 'number' && typeof errAny?.mark?.column === 'number';\n const looksLikeYamlError =\n hasYamlMark ||\n (typeof errAny?.name === 'string' && errAny.name.toLowerCase().includes('yaml'));\n\n if (looksLikeYamlError) {\n const reason = String(errAny?.reason ?? errAny?.message ?? 'Invalid YAML');\n if (hasYamlMark) {\n const line = Number(errAny.mark.line) + 1;\n const column = Number(errAny.mark.column) + 1;\n throw new ConfigError(\n `YAML syntax error at line ${line}, column ${column}: ${reason}`,\n 'yaml',\n 'syntax_error'\n );\n }\n\n throw new ConfigError(\n `YAML syntax error: ${reason}`,\n 'yaml',\n 'syntax_error'\n );\n }\n\n if (error instanceof z.ZodError) {\n // Zod v4 uses `issues`; Zod v3 used `errors`. Support both.\n const issues: any[] = (error as any).issues ?? (error as any).errors ?? [];\n const firstError = issues[0];\n const message = issues.map(e => `${(e.path ?? []).join('.')}: ${e.message}`).join(', ');\r\n // Sanitize field path: only include top-level field name to avoid exposing user-defined keys\r\n // e.g., \"mcpServers.my-secret-server.command\" -> \"mcpServers\"\r\n const topLevelField = String(firstError?.path?.[0] ?? 'root');\r\n throw new ConfigError(\r\n `Invalid agent configuration: ${message}`,\r\n topLevelField,\r\n String(firstError?.code ?? 'invalid')\r\n );\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Parse agent from a local file with YAML frontmatter\n * @param filePath Path to the local agent file\n * @returns Parsed agent configuration and instructions\n */\nexport async function parseAgent(filePath: string): Promise<ParsedAgent> {\n try {\n // Resolve to absolute path\n const absolutePath = resolve(filePath);\n\n // Read file content\n const content = await readFile(absolutePath, 'utf-8');\n\n // Extract agent name from filename by stripping one trailing extension.\n // Examples: \"agent.pk-agent\" -> \"agent\", \"agent.md\" -> \"agent\", \"agent\" -> \"agent\".\n const parsed = parsePath(filePath);\n const name = parsed.name || basename(filePath).replace(/\\.pk-agent$/, '');\n\r\n // Parse using the content parser\r\n return parseAgentContent(content, name);\r\n } catch (error) {\r\n if ((error as unknown as NodeJS.ErrnoException).code === 'ENOENT') {\r\n throw new Error(`File not found: ${filePath}`);\r\n }\r\n throw error;\r\n }\r\n}\r\n",
|
|
35
|
+
"import fs from 'fs/promises';\nimport path from 'path';\nimport { getSessionStorageDir } from './paths';\n\nexport interface StorageState {\n dir: string;\n}\n\nlet storageState: Promise<StorageState> | null = null;\n\n/**\n * Initialize storage for a project\n */\nexport async function initStorage(projectRoot: string): Promise<StorageState> {\n if (storageState) {\n return storageState;\n }\n\n storageState = (async () => {\n const dir = await getSessionStorageDir(projectRoot);\n\n // Ensure base directory exists\n await fs.mkdir(dir, { recursive: true });\n\n return { dir };\n })();\n\n return storageState;\n}\n\n/**\n * Get current storage state\n */\nexport function getStorageState(): Promise<StorageState> {\n if (!storageState) {\n throw new Error('Storage not initialized. Call initStorage first.');\n }\n return storageState;\n}\n\n/**\n * Write JSON with atomic operation\n */\nexport async function writeJSON<T>(key: string, content: T): Promise<void> {\n const state = await getStorageState();\n const target = path.join(state.dir, key + '.json');\n\n // Ensure directory exists\n await fs.mkdir(path.dirname(target), { recursive: true });\n\n // Atomic write: temp file + rename\n const tmp = target + '.' + Date.now() + '.tmp';\n\n try {\n await fs.writeFile(tmp, JSON.stringify(content, null, 2), 'utf-8');\n await fs.rename(tmp, target);\n } catch (error) {\n // Clean up temp file on error\n try {\n await fs.unlink(tmp);\n } catch {\n // Ignore unlink errors\n }\n throw error;\n }\n}\n\n/**\n * Read JSON\n */\nexport async function readJSON<T>(key: string): Promise<T | null> {\n const state = await getStorageState();\n const target = path.join(state.dir, key + '.json');\n\n try {\n const content = await fs.readFile(target, 'utf-8');\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n\n/**\n * List all keys matching a pattern (e.g., \"session/info/*\")\n */\nexport async function listKeys(pattern: string): Promise<string[]> {\n const state = await getStorageState();\n const baseDir = path.join(state.dir, pattern);\n\n try {\n const files = await fs.readdir(baseDir, { recursive: true });\n return files\n .filter(f => f.endsWith('.json'))\n .map(f => path.relative(state.dir, path.join(baseDir, f)).replace(/\\.json$/, ''));\n } catch {\n return [];\n }\n}\n",
|
|
36
|
+
"export { initStorage, getStorageState, writeJSON, readJSON, listKeys } from './storage';\nexport { getXdgDataDir, getGitRoot, getProjectDir, getSessionStorageDir, sanitizeAgentName } from './paths';\nexport type { StorageState } from './storage';\n",
|
|
37
|
+
"/**\n * Configuration resolution utilities\n */\n\nexport const DEFAULT_TIMEOUT = 300; // 5 minutes in seconds\nexport const DEFAULT_MAX_STEPS = 100;\nexport const DEFAULT_TOOL_TIMEOUT = 60; // 60 seconds for individual tool calls\n\n/**\n * Resolve effective timeout based on precedence: CLI > Agent YAML > Default\n */\nexport function resolveTimeout(\n cliTimeout: number,\n wasExplicit: boolean,\n agentTimeout?: number\n): number {\n if (wasExplicit) {\n return cliTimeout;\n }\n return agentTimeout ?? DEFAULT_TIMEOUT;\n}\n\n/**\n * Resolve effective max steps based on precedence: CLI > Agent YAML > Default\n */\nexport function resolveMaxSteps(\n cliMaxSteps?: number,\n agentMaxSteps?: number\n): number {\n return cliMaxSteps ?? agentMaxSteps ?? DEFAULT_MAX_STEPS;\n}\n\n/**\n * Resolve effective tool timeout based on precedence: Server Config > Global Env > Default\n * @param serverTimeout Optional timeout from server configuration (in seconds)\n * @returns Timeout in seconds (0 means no timeout)\n */\nexport function resolveToolTimeout(serverTimeout?: number): number {\n // Server-specific timeout takes precedence\n if (serverTimeout !== undefined) {\n return serverTimeout;\n }\n\n // Check global environment variable\n const envTimeout = process.env.MCP_TOOL_TIMEOUT;\n if (envTimeout !== undefined) {\n const parsed = parseInt(envTimeout);\n if (!isNaN(parsed) && parsed >= 0) {\n return parsed;\n }\n }\n\n // Fall back to default\n return DEFAULT_TOOL_TIMEOUT;\n}\n",
|
|
38
|
+
"// AUTO-GENERATED FILE - DO NOT EDIT\n// Generated by: pnpm generate:models\n// Source: https://models.dev/api.json\n// Last updated: 2026-01-04T20:12:22.245Z\n\nexport interface ModelInfo {\n id: string;\n name: string;\n reasoning: boolean;\n toolCall: boolean;\n modalities: {\n input: string[];\n output: string[];\n };\n limit: {\n context: number;\n output: number;\n };\n /** Cost per token in USD (from models.dev) */\n cost: {\n input: number;\n output: number;\n };\n}\n\nexport type Provider = 'anthropic' | 'openai' | 'openrouter' | 'demo';\n\nexport const MODELS: Record<Provider, Record<string, ModelInfo>> = {\n anthropic: {\n 'claude-opus-4-5': {\n id: 'claude-opus-4-5',\n name: 'Claude Opus 4.5 (latest)',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\",\"pdf\"],\n output: [\"text\"],\n },\n limit: {\n context: 200000,\n output: 64000,\n },\n cost: {\n input: 5,\n output: 25,\n },\n },\n 'claude-haiku-4-5': {\n id: 'claude-haiku-4-5',\n name: 'Claude Haiku 4.5 (latest)',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\",\"pdf\"],\n output: [\"text\"],\n },\n limit: {\n context: 200000,\n output: 64000,\n },\n cost: {\n input: 1,\n output: 5,\n },\n },\n 'claude-sonnet-4-5': {\n id: 'claude-sonnet-4-5',\n name: 'Claude Sonnet 4.5 (latest)',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\",\"pdf\"],\n output: [\"text\"],\n },\n limit: {\n context: 200000,\n output: 64000,\n },\n cost: {\n input: 3,\n output: 15,\n },\n },\n 'claude-opus-4-5-20251101': {\n id: 'claude-opus-4-5-20251101',\n name: 'Claude Opus 4.5',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\",\"pdf\"],\n output: [\"text\"],\n },\n limit: {\n context: 200000,\n output: 64000,\n },\n cost: {\n input: 5,\n output: 25,\n },\n },\n 'claude-haiku-4-5-20251001': {\n id: 'claude-haiku-4-5-20251001',\n name: 'Claude Haiku 4.5',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\",\"pdf\"],\n output: [\"text\"],\n },\n limit: {\n context: 200000,\n output: 64000,\n },\n cost: {\n input: 1,\n output: 5,\n },\n },\n 'claude-sonnet-4-5-20250929': {\n id: 'claude-sonnet-4-5-20250929',\n name: 'Claude Sonnet 4.5',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\",\"pdf\"],\n output: [\"text\"],\n },\n limit: {\n context: 200000,\n output: 64000,\n },\n cost: {\n input: 3,\n output: 15,\n },\n }\n },\n openai: {\n 'gpt-5.2': {\n id: 'gpt-5.2',\n name: 'GPT-5.2',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\"],\n output: [\"text\"],\n },\n limit: {\n context: 400000,\n output: 128000,\n },\n cost: {\n input: 1.75,\n output: 14,\n },\n },\n 'gpt-5.2-pro': {\n id: 'gpt-5.2-pro',\n name: 'GPT-5.2 Pro',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\"],\n output: [\"text\"],\n },\n limit: {\n context: 400000,\n output: 128000,\n },\n cost: {\n input: 21,\n output: 168,\n },\n },\n 'gpt-5.2-chat-latest': {\n id: 'gpt-5.2-chat-latest',\n name: 'GPT-5.2 Chat',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\"],\n output: [\"text\"],\n },\n limit: {\n context: 128000,\n output: 16384,\n },\n cost: {\n input: 1.75,\n output: 14,\n },\n },\n 'gpt-5.1': {\n id: 'gpt-5.1',\n name: 'GPT-5.1',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\"],\n output: [\"text\"],\n },\n limit: {\n context: 400000,\n output: 128000,\n },\n cost: {\n input: 1.25,\n output: 10,\n },\n },\n 'gpt-5.1-codex': {\n id: 'gpt-5.1-codex',\n name: 'GPT-5.1 Codex',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\"],\n output: [\"text\"],\n },\n limit: {\n context: 400000,\n output: 128000,\n },\n cost: {\n input: 1.25,\n output: 10,\n },\n },\n 'gpt-5.1-codex-max': {\n id: 'gpt-5.1-codex-max',\n name: 'GPT-5.1 Codex Max',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\"],\n output: [\"text\"],\n },\n limit: {\n context: 400000,\n output: 128000,\n },\n cost: {\n input: 1.25,\n output: 10,\n },\n },\n 'gpt-5.1-codex-mini': {\n id: 'gpt-5.1-codex-mini',\n name: 'GPT-5.1 Codex mini',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\"],\n output: [\"text\"],\n },\n limit: {\n context: 400000,\n output: 128000,\n },\n cost: {\n input: 0.25,\n output: 2,\n },\n },\n 'gpt-5.1-chat-latest': {\n id: 'gpt-5.1-chat-latest',\n name: 'GPT-5.1 Chat',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\"],\n output: [\"text\"],\n },\n limit: {\n context: 128000,\n output: 16384,\n },\n cost: {\n input: 1.25,\n output: 10,\n },\n },\n 'gpt-5': {\n id: 'gpt-5',\n name: 'GPT-5',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\"],\n output: [\"text\"],\n },\n limit: {\n context: 400000,\n output: 128000,\n },\n cost: {\n input: 1.25,\n output: 10,\n },\n },\n 'gpt-5-pro': {\n id: 'gpt-5-pro',\n name: 'GPT-5 Pro',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\"],\n output: [\"text\"],\n },\n limit: {\n context: 400000,\n output: 272000,\n },\n cost: {\n input: 15,\n output: 120,\n },\n },\n 'gpt-5-nano': {\n id: 'gpt-5-nano',\n name: 'GPT-5 Nano',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\"],\n output: [\"text\"],\n },\n limit: {\n context: 400000,\n output: 128000,\n },\n cost: {\n input: 0.05,\n output: 0.4,\n },\n },\n 'gpt-5-mini': {\n id: 'gpt-5-mini',\n name: 'GPT-5 Mini',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\"],\n output: [\"text\"],\n },\n limit: {\n context: 400000,\n output: 128000,\n },\n cost: {\n input: 0.25,\n output: 2,\n },\n },\n 'gpt-5-codex': {\n id: 'gpt-5-codex',\n name: 'GPT-5-Codex',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\"],\n output: [\"text\"],\n },\n limit: {\n context: 400000,\n output: 128000,\n },\n cost: {\n input: 1.25,\n output: 10,\n },\n },\n 'gpt-5-chat-latest': {\n id: 'gpt-5-chat-latest',\n name: 'GPT-5 Chat (latest)',\n reasoning: true,\n toolCall: false,\n modalities: {\n input: [\"text\",\"image\"],\n output: [\"text\"],\n },\n limit: {\n context: 400000,\n output: 128000,\n },\n cost: {\n input: 1.25,\n output: 10,\n },\n }\n },\n openrouter: {\n 'z-ai/glm-4.7': {\n id: 'z-ai/glm-4.7',\n name: 'GLM-4.7',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\"],\n output: [\"text\"],\n },\n limit: {\n context: 204800,\n output: 131072,\n },\n cost: {\n input: 0.6,\n output: 2.2,\n },\n },\n 'z-ai/glm-4.6': {\n id: 'z-ai/glm-4.6',\n name: 'GLM 4.6',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\"],\n output: [\"text\"],\n },\n limit: {\n context: 200000,\n output: 128000,\n },\n cost: {\n input: 0.6,\n output: 2.2,\n },\n },\n 'z-ai/glm-4.6:exacto': {\n id: 'z-ai/glm-4.6:exacto',\n name: 'GLM 4.6 (exacto)',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\"],\n output: [\"text\"],\n },\n limit: {\n context: 200000,\n output: 128000,\n },\n cost: {\n input: 0.6,\n output: 1.9,\n },\n },\n 'z-ai/glm-4.5': {\n id: 'z-ai/glm-4.5',\n name: 'GLM 4.5',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\"],\n output: [\"text\"],\n },\n limit: {\n context: 128000,\n output: 96000,\n },\n cost: {\n input: 0.6,\n output: 2.2,\n },\n },\n 'z-ai/glm-4.5v': {\n id: 'z-ai/glm-4.5v',\n name: 'GLM 4.5V',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\",\"image\",\"video\"],\n output: [\"text\"],\n },\n limit: {\n context: 64000,\n output: 16384,\n },\n cost: {\n input: 0.6,\n output: 1.8,\n },\n },\n 'z-ai/glm-4.5-air': {\n id: 'z-ai/glm-4.5-air',\n name: 'GLM 4.5 Air',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\"],\n output: [\"text\"],\n },\n limit: {\n context: 128000,\n output: 96000,\n },\n cost: {\n input: 0.2,\n output: 1.1,\n },\n },\n 'z-ai/glm-4.5-air:free': {\n id: 'z-ai/glm-4.5-air:free',\n name: 'GLM 4.5 Air (free)',\n reasoning: true,\n toolCall: false,\n modalities: {\n input: [\"text\"],\n output: [\"text\"],\n },\n limit: {\n context: 128000,\n output: 96000,\n },\n cost: {\n input: 0,\n output: 0,\n },\n },\n 'minimax/minimax-m2.1': {\n id: 'minimax/minimax-m2.1',\n name: 'MiniMax M2.1',\n reasoning: true,\n toolCall: true,\n modalities: {\n input: [\"text\"],\n output: [\"text\"],\n },\n limit: {\n context: 204800,\n output: 131072,\n },\n cost: {\n input: 0.3,\n output: 1.2,\n },\n }\n },\n demo: {\n 'hello': {\n id: 'hello',\n name: 'Demo Hello',\n reasoning: false,\n toolCall: false,\n modalities: {\n input: [\"text\"],\n output: [\"text\"],\n },\n limit: {\n context: 1000,\n output: 1000,\n },\n cost: {\n input: 0,\n output: 0,\n },\n },\n 'welcome': {\n id: 'welcome',\n name: 'Demo Welcome',\n reasoning: false,\n toolCall: false,\n modalities: {\n input: [\"text\"],\n output: [\"text\"],\n },\n limit: {\n context: 1000,\n output: 1000,\n },\n cost: {\n input: 0,\n output: 0,\n },\n },\n },\n};\n\n// Get all supported model IDs as flat list\nexport function getAllModelIds(): string[] {\n const ids: string[] = [];\n for (const [provider, models] of Object.entries(MODELS)) {\n for (const modelId of Object.keys(models)) {\n ids.push(`${provider}:${modelId}`);\n }\n }\n return ids;\n}\n\n// Get model info by full model string (provider:modelId)\nexport function getModelFromRegistry(modelString: string): ModelInfo | undefined {\n const parts = modelString.split(':');\n const [provider, ...modelParts] = parts;\n const modelId = modelParts.join(':'); // Handle model IDs with colons\n\n const providerModels = MODELS[provider as Provider];\n if (!providerModels) return undefined;\n\n return providerModels[modelId];\n}\n\n// Check if model is in registry\nexport function isModelInRegistry(modelString: string): boolean {\n return getModelFromRegistry(modelString) !== undefined;\n}\n\n// Get all models for a provider\nexport function getProviderModels(provider: Provider): ModelInfo[] {\n return Object.values(MODELS[provider] || {});\n}\n",
|
|
39
|
+
"import { z } from 'zod';\n\n/**\n * Skill name validation:\n * - 1-64 characters\n * - Lowercase letters, numbers, and hyphens only\n * - Cannot start or end with hyphen\n * - No consecutive hyphens\n */\nconst skillNameRegex = /^[a-z][a-z0-9-]*[a-z0-9]$|^[a-z]$/;\n\nexport const SkillFrontmatterSchema = z.object({\n name: z.string()\n .min(1, 'Name is required')\n .max(64, 'Name must be 64 characters or less')\n .regex(skillNameRegex, 'Name must be lowercase letters, numbers, and hyphens only')\n .refine(s => !s.includes('--'), 'Name cannot contain consecutive hyphens'),\n description: z.string()\n .min(1, 'Description is required')\n .max(1024, 'Description must be 1024 characters or less'),\n license: z.string().optional(),\n compatibility: z.string().max(500).optional(),\n metadata: z.record(z.string(), z.string()).optional(),\n 'allowed-tools': z.string().optional(),\n});\n\nexport type SkillFrontmatter = z.infer<typeof SkillFrontmatterSchema>;\n\n/**\n * Parsed skill information\n */\nexport interface SkillInfo {\n /** Skill identifier from frontmatter */\n name: string;\n /** Description of what the skill does and when to use it */\n description: string;\n /** Absolute path to SKILL.md file */\n location: string;\n /** Parsed allowed-tools patterns */\n allowedTools?: string[] | undefined;\n /** License information */\n license?: string | undefined;\n /** Compatibility/environment requirements */\n compatibility?: string | undefined;\n /** Additional metadata */\n metadata?: Record<string, string> | undefined;\n}\n\n/**\n * Full skill content after loading\n */\nexport interface SkillContent extends SkillInfo {\n /** Markdown body content (after frontmatter) */\n content: string;\n /** Directory containing the skill */\n directory: string;\n}\n\n/**\n * Tool validation result for allowed-tools checking\n */\nexport interface ToolValidationResult {\n pattern: string;\n satisfied: boolean;\n reason?: string | undefined;\n}\n",
|
|
40
|
+
"import matter from 'gray-matter';\nimport { readFile } from 'fs/promises';\nimport { dirname } from 'path';\nimport type { ZodError } from 'zod';\nimport { SkillFrontmatterSchema, type SkillInfo, type SkillContent } from './types.js';\nimport { logger } from '../utils/logger.js';\n\n/**\n * Format Zod error as a single sentence\n */\nfunction formatZodError(error: ZodError): string {\n return error.issues.map(i => `${i.path.join('.')}: ${i.message}`).join('; ');\n}\n\n/**\n * Parse allowed-tools string into array of patterns\n * Supports both space-separated and comma-separated formats\n */\nfunction parseAllowedTools(allowedTools: string | undefined): string[] | undefined {\n if (!allowedTools) return undefined;\n // Split by comma or whitespace, trim each, filter empty\n const tools = allowedTools\n .split(/[,\\s]+/)\n .map(t => t.trim())\n .filter(Boolean);\n return tools.length > 0 ? tools : undefined;\n}\n\n/**\n * Parse SKILL.md frontmatter only (for discovery)\n * Returns SkillInfo or null if invalid\n */\nexport async function parseSkillFrontmatter(filePath: string): Promise<SkillInfo | null> {\n try {\n const content = await readFile(filePath, 'utf-8');\n const { data } = matter(content);\n\n const parsed = SkillFrontmatterSchema.safeParse(data);\n if (!parsed.success) {\n logger.warn(`Invalid skill \"${filePath}\": ${formatZodError(parsed.error)}`);\n return null;\n }\n\n const frontmatter = parsed.data;\n\n return {\n name: frontmatter.name,\n description: frontmatter.description,\n location: filePath,\n allowedTools: parseAllowedTools(frontmatter['allowed-tools']),\n license: frontmatter.license,\n compatibility: frontmatter.compatibility,\n metadata: frontmatter.metadata,\n };\n } catch (error) {\n logger.warn(`Failed to parse skill at ${filePath}: ${error instanceof Error ? error.message : String(error)}`);\n return null;\n }\n}\n\n/**\n * Parse full SKILL.md content (for loading)\n * Returns SkillContent or throws if invalid\n */\nexport async function parseSkillContent(filePath: string): Promise<SkillContent> {\n const fileContent = await readFile(filePath, 'utf-8');\n const { data, content } = matter(fileContent);\n\n const parsed = SkillFrontmatterSchema.safeParse(data);\n if (!parsed.success) {\n throw new Error(`Invalid skill frontmatter: ${formatZodError(parsed.error)}`);\n }\n\n const frontmatter = parsed.data;\n\n return {\n name: frontmatter.name,\n description: frontmatter.description,\n location: filePath,\n allowedTools: parseAllowedTools(frontmatter['allowed-tools']),\n license: frontmatter.license,\n compatibility: frontmatter.compatibility,\n metadata: frontmatter.metadata,\n content: content.trim(),\n directory: dirname(filePath),\n };\n}\n",
|
|
41
|
+
"import { glob } from 'glob';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { access } from 'fs/promises';\nimport { parseSkillFrontmatter } from './parser.js';\nimport type { SkillInfo } from './types.js';\nimport { logger } from '../utils/logger.js';\nimport { ensurePkAgentDirs } from '../utils/pk-agent-dirs.js';\n\n/**\n * Skill discovery directories in priority order:\n * 1. .pk-agent/skills/ - Project-local\n * 2. ~/.pk-agent/skills/ - User-global\n * 3. .claude/skills/ - Claude ecosystem compatibility\n */\nfunction getDiscoveryDirectories(projectRoot: string): string[] {\n const home = homedir();\n return [\n join(projectRoot, '.pk-agent', 'skills'),\n join(projectRoot, '.agents', 'skills'),\n join(projectRoot, '.claude', 'skills'),\n join(projectRoot, '.claude', 'plugins'),\n join(home, '.pk-agent', 'skills'),\n join(home, '.claude', 'skills'),\n ];\n}\n\n/**\n * Check if a directory exists\n */\nasync function directoryExists(dir: string): Promise<boolean> {\n try {\n await access(dir);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Discover all skills from configured directories\n * Returns map of skill name to SkillInfo\n */\nexport async function discoverSkills(projectRoot: string): Promise<Map<string, SkillInfo>> {\n try {\n ensurePkAgentDirs(projectRoot);\n } catch {\n // best-effort\n }\n\n const skills = new Map<string, SkillInfo>();\n const directories = getDiscoveryDirectories(projectRoot);\n\n // Scan all directories in parallel for SKILL.md files\n const dirResults = await Promise.allSettled(\n directories.map(async (dir) => {\n if (!await directoryExists(dir)) return [];\n // glob requires forward slashes even on Windows\n const pattern = join(dir, '**/SKILL.md').replace(/\\\\/g, '/');\n return glob(pattern, { absolute: true });\n })\n );\n\n // Process results in priority order (first directory wins for duplicate names)\n for (const result of dirResults) {\n if (result.status !== 'fulfilled') continue;\n for (const match of result.value) {\n const skill = await parseSkillFrontmatter(match);\n if (!skill) continue;\n\n // Validate that skill name matches directory name\n const dirName = match.split(/[\\\\/]/).slice(-2, -1)[0];\n if (dirName !== skill.name) {\n logger.warn(`Skill name \"${skill.name}\" does not match directory \"${dirName}\" in ${match}`);\n continue;\n }\n\n // Warn on duplicate skill names\n if (skills.has(skill.name)) {\n logger.warn(`Duplicate skill name \"${skill.name}\". Using first found: ${skills.get(skill.name)!.location}`);\n continue;\n }\n\n skills.set(skill.name, skill);\n }\n }\n\n return skills;\n}\n\n/**\n * Get a specific skill by name\n */\nexport async function getSkill(\n name: string,\n projectRoot: string\n): Promise<SkillInfo | undefined> {\n const skills = await discoverSkills(projectRoot);\n return skills.get(name);\n}\n\n/**\n * Get all discovered skills as array\n */\nexport async function getAllSkills(projectRoot: string): Promise<SkillInfo[]> {\n const skills = await discoverSkills(projectRoot);\n return Array.from(skills.values());\n}\n",
|
|
42
|
+
"/**\r\n * Conversation Snapshot Manager (R3-3)\r\n *\r\n * Persists and restores conversation state for session resume.\r\n * All data stored in XDG data dir - zero project pollution.\r\n *\r\n * Storage: {xdgData}/pk-agent/project/{hash}/session/{sessionDir}/snapshot.json\r\n */\r\n\r\nimport fs from 'fs/promises';\nimport path from 'path';\nimport { writeJSON, readJSON, getStorageState } from '../storage';\nimport { logger } from '../utils/logger';\nimport { sanitizeAgentName } from '../utils/names';\n\r\n/** Minimal message shape matching ContextManager's ModelMessage */\r\ninterface SnapshotMessage {\r\n role: string;\r\n content: string | Array<unknown>;\r\n}\r\n\r\nexport interface ConversationSnapshot {\r\n /** Session ID (ULID) */\r\n sessionID: string;\r\n /** Path to .pk-agent file */\r\n agentFile: string;\r\n /** Agent name from YAML */\r\n agentName: string;\r\n /** Model string (e.g., 'anthropic:claude-sonnet-4-20250514') */\r\n model: string;\r\n /** Conversation messages at time of snapshot */\r\n messages: SnapshotMessage[];\r\n /** Number of times context was compacted */\r\n compactionCount: number;\r\n /** Token budget status at snapshot time */\r\n tokenBudget: {\r\n used: number;\r\n limit: number;\r\n };\r\n /** Total message count (including compacted) */\r\n messageCount: number;\r\n /** Unix timestamp (ms) */\r\n timestamp: number;\r\n /** pk-agent version */\r\n version: string;\r\n}\r\n\r\n/** Summary for listing sessions (lighter than full snapshot) */\r\nexport interface SessionSummary {\r\n sessionID: string;\r\n agentName: string;\r\n agentFile: string;\r\n model: string;\r\n messageCount: number;\r\n compactionCount: number;\r\n timestamp: number;\r\n age: string; // Human-readable age (e.g., \"2h ago\", \"3d ago\")\r\n}\r\n\r\nconst DEFAULT_RETENTION_DAYS = 7;\r\n\r\n/**\r\n * Save a conversation snapshot for later resume\r\n */\r\nexport async function saveSnapshot(\r\n sessionDir: string,\r\n snapshot: ConversationSnapshot\r\n): Promise<void> {\r\n try {\r\n await writeJSON(`${sessionDir}/snapshot`, snapshot);\r\n logger.debug(`[R3-3] Snapshot saved for session ${snapshot.sessionID}`);\r\n } catch (error) {\r\n // Non-fatal - don't break the agent loop for a failed save\r\n logger.debug(`[R3-3] Failed to save snapshot: ${(error as Error).message}`);\r\n }\r\n}\r\n\r\n/**\r\n * Load a conversation snapshot for resume\r\n */\r\nexport async function loadSnapshot(\r\n sessionDir: string\r\n): Promise<ConversationSnapshot | null> {\r\n return readJSON<ConversationSnapshot>(`${sessionDir}/snapshot`);\r\n}\r\n\r\n/**\r\n * List all resumable sessions for the current project, newest first\r\n */\r\nexport async function listSnapshots(): Promise<SessionSummary[]> {\r\n try {\r\n const state = await getStorageState();\r\n const baseDir = state.dir;\r\n\r\n // Read top-level session directories\r\n const entries = await fs.readdir(baseDir, { withFileTypes: true });\r\n const summaries: SessionSummary[] = [];\r\n\r\n for (const entry of entries) {\r\n if (!entry.isDirectory()) continue;\r\n\r\n // Check for snapshot.json in this session dir\r\n const snapshotPath = path.join(baseDir, entry.name, 'snapshot.json');\r\n try {\r\n const content = await fs.readFile(snapshotPath, 'utf-8');\r\n const snapshot = JSON.parse(content) as ConversationSnapshot;\r\n\r\n summaries.push({\r\n sessionID: snapshot.sessionID,\r\n agentName: snapshot.agentName,\r\n agentFile: snapshot.agentFile,\r\n model: snapshot.model,\r\n messageCount: snapshot.messageCount,\r\n compactionCount: snapshot.compactionCount,\r\n timestamp: snapshot.timestamp,\r\n age: formatAge(snapshot.timestamp),\r\n });\r\n } catch {\r\n // No snapshot or invalid - skip\r\n continue;\r\n }\r\n }\r\n\r\n // Sort newest first\r\n summaries.sort((a, b) => b.timestamp - a.timestamp);\r\n return summaries;\r\n } catch {\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Find the most recent snapshot for a specific agent file\r\n */\r\nexport async function findLatestSnapshot(\r\n agentFile: string\r\n): Promise<{ sessionDir: string; snapshot: ConversationSnapshot } | null> {\r\n const snapshots = await listSnapshots();\r\n const match = snapshots.find(s => s.agentFile === agentFile);\r\n if (!match) return null;\n\n // Reconstruct session dir name\n const sanitizedName = sanitizeAgentName(match.agentName);\n\n const sessionDir = `${match.sessionID}-${sanitizedName}`;\n const snapshot = await loadSnapshot(sessionDir);\n if (!snapshot) return null;\n\r\n return { sessionDir, snapshot };\r\n}\r\n\r\n/**\r\n * Prune snapshots older than retention period.\r\n * Fire-and-forget - non-blocking, non-fatal.\r\n */\r\nexport async function pruneSnapshots(\r\n retentionDays?: number\r\n): Promise<number> {\r\n const maxAge = (retentionDays ?? parseFloat(process.env.SESSION_RETENTION_DAYS || String(DEFAULT_RETENTION_DAYS))) * 24 * 60 * 60 * 1000;\r\n const cutoff = Date.now() - maxAge;\r\n let pruned = 0;\r\n\r\n try {\r\n const state = await getStorageState();\r\n const baseDir = state.dir;\r\n const entries = await fs.readdir(baseDir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n if (!entry.isDirectory()) continue;\r\n\r\n const snapshotPath = path.join(baseDir, entry.name, 'snapshot.json');\r\n try {\r\n const content = await fs.readFile(snapshotPath, 'utf-8');\r\n const snapshot = JSON.parse(content) as ConversationSnapshot;\r\n\r\n if (snapshot.timestamp < cutoff) {\r\n await fs.unlink(snapshotPath);\r\n pruned++;\r\n }\r\n } catch {\r\n continue;\r\n }\r\n }\r\n\r\n if (pruned > 0) {\r\n logger.debug(`[R3-3] Pruned ${pruned} expired snapshot(s)`);\r\n }\r\n } catch {\r\n // Non-fatal\r\n }\r\n\r\n return pruned;\r\n}\r\n\r\n/**\r\n * Format timestamp as human-readable age string\r\n */\r\nfunction formatAge(timestamp: number): string {\r\n const deltaMs = Date.now() - timestamp;\r\n const minutes = Math.floor(deltaMs / 60_000);\r\n const hours = Math.floor(deltaMs / 3_600_000);\r\n const days = Math.floor(deltaMs / 86_400_000);\r\n\r\n if (minutes < 1) return 'just now';\r\n if (minutes < 60) return `${minutes}m ago`;\r\n if (hours < 24) return `${hours}h ago`;\r\n if (days < 30) return `${days}d ago`;\r\n return `${Math.floor(days / 30)}mo ago`;\r\n}\r\n",
|
|
43
|
+
"/**\n * Model validation utilities with fuzzy matching suggestions\n */\n\nimport fuzzysort from 'fuzzysort';\nimport { getAllModelIds, getModelFromRegistry, type ModelInfo } from '../generated/models';\nimport { logger } from './logger';\n\nexport interface ValidationResult {\n valid: boolean;\n model?: ModelInfo;\n suggestions?: string[];\n warning?: string;\n}\n\n/**\n * Validate a model string and return suggestions if invalid\n */\nexport function validateModel(modelString: string): ValidationResult {\n // Check if model exists in registry\n const model = getModelFromRegistry(modelString);\n if (model) {\n return { valid: true, model };\n }\n\n // Model not found - find similar ones using fuzzy matching\n const allModels = getAllModelIds();\n const results = fuzzysort.go(modelString, allModels, {\n limit: 3,\n threshold: -10000, // Include even weak matches\n });\n\n const suggestions = results.map(r => r.target);\n\n return {\n valid: false,\n suggestions,\n warning: `Model '${modelString}' not found in registry`,\n };\n}\n\n/**\n * Warn if model is not in registry (non-blocking)\n * Returns the original model string to continue with\n */\nexport function warnIfModelNotInRegistry(modelString: string): string {\n const result = validateModel(modelString);\n\n if (!result.valid) {\n logger.warn(`${result.warning}`);\n if (result.suggestions && result.suggestions.length > 0) {\n logger.warn(`Did you mean: ${result.suggestions.join(', ')}?`);\n }\n logger.warn('Continuing anyway - this model may still work if supported by the provider');\n }\n\n return modelString;\n}\n\n/**\n * Get fuzzy suggestions for a model string\n */\nexport function getSuggestions(modelString: string, limit = 5): string[] {\n const allModels = getAllModelIds();\n const results = fuzzysort.go(modelString, allModels, {\n limit,\n threshold: -10000,\n });\n\n return results.map(r => r.target);\n}\n",
|
|
44
|
+
"/**\r\n * Demo Provider - A mock language model provider for zero-config trials\r\n *\r\n * This provider streams hardcoded responses without requiring any API keys,\r\n * allowing users to try PK Agent immediately with:\r\n * npx -y pk-agent@latest run https://pk-agent.io/hello.pk-agent\r\n */\r\n\r\nimport type {\r\n LanguageModelV2,\r\n LanguageModelV2CallOptions,\r\n LanguageModelV2StreamPart,\r\n} from '@ai-sdk/provider';\r\n\r\n// Demo responses for different model variants\r\nconst DEMO_RESPONSES: Record<string, string> = {\r\n hello: `# Welcome to PK Agent! \r\n\r\nPK Agent lets you build autonomous AI agents using simple Markdown files.\r\n\r\n## What You Can Do\r\n\r\n- **Write agents in Markdown** - No complex frameworks, just natural language instructions\r\n- **Use any LLM provider** - OpenAI, Anthropic, or open-source models via OpenRouter\r\n- **Trigger on events** - Run agents on schedules, webhooks, or CI/CD\r\n\r\n## Getting Started\r\n\r\n1. **Authenticate with your preferred provider:**\r\n \\`\\`\\`bash\r\n pk-agent auth login openai\r\n \\`\\`\\`\r\n\r\n2. **Create an autonomous agent** (e.g., \\`domain-check.pk-agent\\`):\r\n \\`\\`\\`yaml\r\n ---\r\n model: openai:gpt-5.2\r\n schedule: \"0 9 * * 1\" # Every Monday at 9am\r\n tools:\r\n bash:\r\n commands: [\"whois *\"]\r\n ---\r\n Check when mysite.com expires.\r\n Alert me if it's within 30 days.\r\n \\`\\`\\`\r\n\r\n3. **Start the scheduler:**\r\n \\`\\`\\`bash\r\n pk-agent serve\r\n \\`\\`\\`\r\n\r\n## Learn More\r\n\r\n- Documentation: https://docs.pk-agent.io/\r\n- GitHub: https://github.com/pk-agent/pk-agent\r\n\r\nHappy building! `,\r\n\r\n welcome: `Welcome! This is a demo response from PK Agent.\r\n\r\nPK Agent lets you build autonomous AI agents using simple Markdown files.\r\n\r\nTo get started with real AI models, run:\r\n pk-agent auth login\r\n\r\nFor more information, visit: https://docs.pk-agent.io/`,\r\n\r\n default: `This is a demo response from PK Agent.\r\n\r\nThe demo provider is used for testing and zero-config trials.\r\nTo use real AI models, run:\r\n pk-agent auth login\r\n\r\nLearn more: https://docs.pk-agent.io/`,\r\n};\r\n\r\n/**\r\n * Creates a demo language model that streams hardcoded responses\r\n */\r\nexport function createDemoModel(modelId: string): LanguageModelV2 {\r\n // Suppress AI SDK compatibility warnings for demo provider\r\n (globalThis as Record<string, unknown>).AI_SDK_LOG_WARNINGS = false;\r\n\r\n const responseKey = modelId in DEMO_RESPONSES ? modelId : 'default';\r\n const responseText = DEMO_RESPONSES[responseKey];\r\n\r\n return {\r\n specificationVersion: 'v2',\r\n provider: 'demo',\r\n modelId: `demo:${modelId}`,\r\n supportedUrls: {},\r\n\r\n async doGenerate(_options: LanguageModelV2CallOptions) {\r\n // Simulate a small delay for realism\r\n await new Promise((resolve) => setTimeout(resolve, 100));\r\n\r\n const outputTokens = responseText.split(/\\s+/).length;\r\n const inputTokens = 10;\r\n\r\n return {\r\n content: [{ type: 'text' as const, text: responseText }],\r\n finishReason: 'stop' as const,\r\n usage: {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n },\r\n warnings: [],\r\n };\r\n },\r\n\r\n async doStream(options: LanguageModelV2CallOptions) {\r\n const abortSignal = options.abortSignal;\r\n const words = responseText.split(/(\\s+)/);\r\n const outputTokens = words.filter((w) => w.trim()).length;\r\n const inputTokens = 10;\r\n const textId = 'demo-text-0';\r\n\r\n // Create a ReadableStream that yields text chunks word by word\r\n const stream = new ReadableStream<LanguageModelV2StreamPart>({\r\n async start(controller) {\r\n // Emit text-start\r\n controller.enqueue({\r\n type: 'text-start',\r\n id: textId,\r\n });\r\n\r\n for (const word of words) {\r\n // Check for abort\r\n if (abortSignal?.aborted) {\r\n controller.close();\r\n return;\r\n }\r\n\r\n // Yield each word/whitespace as a text delta\r\n controller.enqueue({\r\n type: 'text-delta',\r\n id: textId,\r\n delta: word,\r\n });\r\n\r\n // Small delay between words for streaming effect\r\n await new Promise((resolve) => setTimeout(resolve, 20));\r\n }\r\n\r\n // Emit text-end\r\n controller.enqueue({\r\n type: 'text-end',\r\n id: textId,\r\n });\r\n\r\n // Yield finish event\r\n controller.enqueue({\r\n type: 'finish',\r\n finishReason: 'stop',\r\n usage: {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n },\r\n });\r\n\r\n controller.close();\r\n },\r\n });\r\n\r\n return {\r\n stream,\r\n };\r\n },\r\n };\r\n}\r\n",
|
|
45
|
+
"import { randomUUID } from 'crypto';\r\nimport { createOpenAI } from '@ai-sdk/openai';\r\nimport { createAnthropic } from '@ai-sdk/anthropic';\r\nimport { wrapLanguageModel } from 'ai';\r\nimport { AnthropicAuth } from './auth/anthropic';\r\nimport { CodexAuth } from './auth/codex';\r\nimport { AuthStorage } from './auth/storage';\r\nimport { logger } from './utils/logger';\r\nimport { warnIfModelNotInRegistry } from './utils/model-utils';\r\nimport { createDemoModel } from './providers/demo';\r\n\r\n/**\r\n * Check if DevTools is enabled via environment variable\r\n */\r\nfunction isDevToolsEnabled(): boolean {\r\n return process.env.PK_AGENT_DEVTOOLS === 'true';\r\n}\r\n\r\n// Cache for DevTools middleware (lazy loaded)\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nlet devToolsMiddlewareCache: any = null;\r\nlet devToolsLoadAttempted = false;\r\n\r\n/**\r\n * Wrap model with DevTools middleware if enabled (dev dependency, dynamically imported)\r\n */\r\nasync function maybeWrapWithDevTools<T>(model: T): Promise<T> {\r\n if (!isDevToolsEnabled()) {\r\n return model;\r\n }\r\n\r\n // Try to load devtools (dev dependency, may not be installed in production)\r\n if (!devToolsLoadAttempted) {\r\n devToolsLoadAttempted = true;\r\n try {\r\n const { devToolsMiddleware } = await import('@ai-sdk/devtools');\r\n devToolsMiddlewareCache = devToolsMiddleware();\r\n logger.info('DevTools enabled - run `npx @ai-sdk/devtools` to inspect agent runs');\r\n } catch (error) {\r\n logger.warn('DevTools requested but @ai-sdk/devtools not installed. Run: pnpm add -D @ai-sdk/devtools');\r\n logger.debug(`DevTools import error: ${error instanceof Error ? error.message : String(error)}`);\r\n }\r\n }\r\n\r\n if (!devToolsMiddlewareCache) {\r\n return model;\r\n }\r\n\r\n // wrapLanguageModel expects LanguageModelV3, which is what providers return\r\n return wrapLanguageModel({\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n model: model as any,\r\n middleware: devToolsMiddlewareCache,\r\n }) as T;\r\n}\r\n\r\nexport class AuthenticationError extends Error {\r\n constructor(\r\n public provider: string,\r\n public envVar: string,\r\n message: string\r\n ) {\r\n super(message);\r\n this.name = 'AuthenticationError';\r\n }\r\n}\r\n\r\ninterface ModelConfig {\r\n provider: string;\r\n modelName: string;\r\n envVar?: string;\r\n envSuffix?: string;\r\n}\r\n\r\nfunction resolveBaseURL(\r\n config: ModelConfig,\r\n provider: 'openai' | 'anthropic'\r\n): string | undefined {\r\n const readEnv = (name: string | undefined) => {\r\n if (!name) return undefined;\r\n const value = process.env[name];\r\n return value && value.trim() !== '' ? value : undefined;\r\n };\r\n\r\n if (config.envVar) {\r\n const envVarBase = readEnv(`${config.envVar}_BASE_URL`);\r\n if (envVarBase) return envVarBase;\r\n }\r\n\r\n if (config.envSuffix) {\r\n const suffix = `_${config.envSuffix}`;\r\n const suffixBase = readEnv(`${provider.toUpperCase()}_BASE_URL${suffix}`);\r\n if (suffixBase) return suffixBase;\r\n }\r\n\r\n return readEnv(`${provider.toUpperCase()}_BASE_URL`);\r\n}\r\n\r\n/**\r\n * Parse model string to extract provider, model name, and optional env suffix\r\n * Format: \"provider:model[:env]\"\r\n * Examples:\r\n * - \"openai:gpt-5.2\" -> default env vars\r\n * - \"openai:gpt-5.2:dev\" -> use _DEV suffix\r\n * - \"openai:gpt-5.2:OPENAI_API_KEY_PERSONAL\" -> use specific env var\r\n */\r\nfunction parseModelConfig(modelString: string): ModelConfig {\r\n const parts = modelString.split(':');\r\n const [provider, modelName, envPart] = parts.length >= 2\r\n ? parts\r\n : ['openai', modelString, undefined];\r\n\r\n if (!envPart) {\r\n return { provider, modelName };\r\n }\r\n\r\n // Determine if envPart is a full env var or just a suffix\r\n const isFullEnvVar = envPart.includes('_KEY');\r\n return {\r\n provider,\r\n modelName,\r\n ...(isFullEnvVar\r\n ? { envVar: envPart }\r\n : { envSuffix: envPart.toUpperCase() })\r\n };\r\n}\r\n\r\n/**\r\n * Create AI model instance based on configuration\r\n */\r\nexport async function createModel(modelString: string) {\r\n // Validate model and warn if not in registry (non-blocking)\r\n warnIfModelNotInRegistry(modelString);\r\n\r\n const config = parseModelConfig(modelString);\r\n\r\n if (config.provider === 'anthropic') {\r\n const baseURL = resolveBaseURL(config, 'anthropic');\r\n // Check for OAuth token first (handles refresh automatically)\r\n const oauthToken = await AnthropicAuth.access();\r\n if (oauthToken) {\r\n logger.debug('Using Anthropic OAuth token for authentication');\r\n // For OAuth, we need to use a custom fetch to set Bearer token\r\n const anthropicOptions: Record<string, any> = {\r\n apiKey: '', // Empty API key for OAuth\r\n fetch: async (input: RequestInfo | URL, init?: RequestInit) => {\r\n const access = await AnthropicAuth.access();\r\n const headers: Record<string, string> = {\r\n ...((init?.headers || {}) as Record<string, string>),\r\n 'authorization': `Bearer ${access}`,\r\n 'anthropic-beta': 'oauth-2025-04-20',\r\n };\r\n // Remove x-api-key header since we're using Bearer auth\r\n if ('x-api-key' in headers) {\r\n delete headers['x-api-key'];\r\n }\r\n return fetch(input as RequestInfo | URL, {\r\n ...init,\r\n headers,\r\n });\r\n },\r\n };\r\n\r\n if (baseURL) {\r\n anthropicOptions.baseURL = baseURL;\r\n }\r\n\r\n const anthropic = createAnthropic(anthropicOptions);\r\n return await maybeWrapWithDevTools(anthropic.chat(config.modelName));\r\n }\r\n\r\n // Fall back to API key authentication\r\n let apiKey: string | undefined;\r\n if (config.envVar) {\r\n apiKey = process.env[config.envVar];\r\n if (!apiKey) {\r\n throw new AuthenticationError(\r\n 'anthropic',\r\n config.envVar,\r\n `No authentication found for Anthropic (missing ${config.envVar})`\r\n );\r\n }\r\n logger.debug(`Using ${config.envVar} for authentication`);\r\n } else if (config.envSuffix) {\r\n const suffix = `_${config.envSuffix}`;\r\n apiKey = process.env[`ANTHROPIC_API_KEY${suffix}`];\r\n if (!apiKey) {\r\n throw new AuthenticationError(\r\n 'anthropic',\r\n `ANTHROPIC_API_KEY${suffix}`,\r\n `No authentication found for Anthropic (missing ANTHROPIC_API_KEY${suffix})`\r\n );\r\n }\r\n logger.debug(`Using ANTHROPIC_API_KEY${suffix} for authentication`);\r\n } else {\r\n // Check environment variable first\r\n apiKey = process.env.ANTHROPIC_API_KEY;\r\n if (apiKey) {\r\n logger.debug('Using ANTHROPIC_API_KEY for authentication');\r\n }\r\n\r\n // Fall back to stored credentials from `pk-agent auth login`\r\n if (!apiKey) {\r\n const storedApiKey = await AuthStorage.getApiKey('anthropic');\r\n if (storedApiKey) {\r\n apiKey = storedApiKey.key;\r\n logger.debug('Using stored API key for Anthropic authentication');\r\n }\r\n }\r\n\r\n if (!apiKey) {\r\n throw new AuthenticationError(\r\n 'anthropic',\r\n 'ANTHROPIC_API_KEY',\r\n 'No authentication found for Anthropic. Run `pk-agent auth login anthropic` or set ANTHROPIC_API_KEY'\r\n );\r\n }\r\n }\r\n\r\n if (!apiKey) {\r\n throw new Error('Failed to obtain API key for Anthropic');\r\n }\r\n const anthropicOptions: { apiKey: string; baseURL?: string } = { apiKey };\r\n if (baseURL) {\r\n anthropicOptions.baseURL = baseURL;\r\n }\r\n const anthropic = createAnthropic(anthropicOptions);\r\n return await maybeWrapWithDevTools(anthropic.chat(config.modelName));\r\n\r\n } else if (config.provider === 'openai') {\r\n // Check for Codex OAuth token first (handles refresh automatically)\r\n const codexAccess = await CodexAuth.access();\r\n if (codexAccess && !config.envVar && !config.envSuffix) {\r\n logger.debug('Using ChatGPT OAuth for OpenAI authentication');\r\n\r\n // Warn if model is not gpt-5 - ChatGPT backend may reject other models\r\n if (config.modelName !== 'gpt-5') {\r\n logger.warn(\r\n `ChatGPT OAuth backend may only support gpt-5. ` +\r\n `Model '${config.modelName}' might return \"Unsupported model\" errors. ` +\r\n `If so, use 'openai:gpt-5' or switch to API key auth.`\r\n );\r\n }\r\n\r\n // Generate a stable session ID for this model creation\r\n const sessionId = randomUUID();\r\n\r\n // Fetch wrapper that sets all required ChatGPT backend headers\r\n // The AI SDK's openai.responses() speaks the Responses API format natively\r\n const codexFetch = async (input: RequestInfo | URL, init?: RequestInit) => {\r\n const access = await CodexAuth.access();\r\n if (!access) {\r\n throw new Error('Codex OAuth token expired');\r\n }\r\n\r\n // Build headers from init\r\n const headers = new Headers(init?.headers);\r\n\r\n // Set Bearer token (remove any existing authorization header first)\r\n headers.delete('authorization');\r\n headers.delete('Authorization');\r\n headers.set('authorization', `Bearer ${access.token}`);\r\n\r\n // Set ChatGPT-Account-Id header for organization subscriptions\r\n if (access.accountId) {\r\n headers.set('ChatGPT-Account-Id', access.accountId);\r\n }\r\n\r\n // Required headers for ChatGPT backend-api/codex endpoint\r\n headers.set('originator', 'codex_cli_rs');\r\n headers.set('session_id', sessionId);\r\n headers.set('OpenAI-Beta', 'responses=experimental');\r\n\r\n return fetch(input, { ...init, headers });\r\n };\r\n\r\n const openai = createOpenAI({\r\n apiKey: 'codex-oauth', // Placeholder, custom fetch overrides auth\r\n baseURL: 'https://chatgpt.com/backend-api/codex',\r\n fetch: codexFetch as typeof fetch,\r\n });\r\n\r\n // Use openai.responses() which speaks the Responses API format natively\r\n return await maybeWrapWithDevTools(openai.responses(config.modelName));\r\n }\r\n\r\n // Fall back to API key authentication\r\n let apiKey: string | undefined;\r\n\r\n if (config.envVar) {\r\n apiKey = process.env[config.envVar];\r\n if (!apiKey) {\r\n throw new AuthenticationError(\r\n 'openai',\r\n config.envVar,\r\n `No authentication found for OpenAI (missing ${config.envVar})`\r\n );\r\n }\r\n logger.debug(`Using ${config.envVar} for authentication`);\r\n } else if (config.envSuffix) {\r\n const suffix = `_${config.envSuffix}`;\r\n apiKey = process.env[`OPENAI_API_KEY${suffix}`];\r\n if (!apiKey) {\r\n throw new AuthenticationError(\r\n 'openai',\r\n `OPENAI_API_KEY${suffix}`,\r\n `No authentication found for OpenAI (missing OPENAI_API_KEY${suffix})`\r\n );\r\n }\r\n logger.debug(`Using OPENAI_API_KEY${suffix} for authentication`);\r\n } else {\r\n // Check environment variable first\r\n apiKey = process.env.OPENAI_API_KEY;\r\n if (apiKey) {\r\n logger.debug('Using OPENAI_API_KEY for authentication');\r\n }\r\n\r\n // Fall back to stored credentials from `pk-agent auth login`\r\n if (!apiKey) {\r\n const storedApiKey = await AuthStorage.getApiKey('openai');\r\n if (storedApiKey) {\r\n apiKey = storedApiKey.key;\r\n logger.debug('Using stored API key for OpenAI authentication');\r\n }\r\n }\r\n\r\n if (!apiKey) {\r\n throw new AuthenticationError(\r\n 'openai',\r\n 'OPENAI_API_KEY',\r\n 'No authentication found for OpenAI. Run `pk-agent auth login openai` or set OPENAI_API_KEY'\r\n );\r\n }\r\n }\r\n\r\n if (!apiKey) {\r\n throw new Error('Failed to obtain API key for OpenAI');\r\n }\r\n const baseURL = resolveBaseURL(config, 'openai');\r\n const openaiOptions: { apiKey: string; baseURL?: string } = { apiKey };\r\n if (baseURL) {\r\n openaiOptions.baseURL = baseURL;\r\n }\r\n const openai = createOpenAI(openaiOptions);\r\n return await maybeWrapWithDevTools(openai.chat(config.modelName));\r\n\r\n } else if (config.provider === 'openrouter') {\r\n let apiKey: string | undefined;\r\n\r\n if (config.envVar) {\r\n apiKey = process.env[config.envVar];\r\n if (!apiKey) {\r\n throw new AuthenticationError(\r\n 'openrouter',\r\n config.envVar,\r\n `No authentication found for OpenRouter (missing ${config.envVar})`\r\n );\r\n }\r\n logger.debug(`Using ${config.envVar} for authentication`);\r\n } else if (config.envSuffix) {\r\n const suffix = `_${config.envSuffix}`;\r\n apiKey = process.env[`OPENROUTER_API_KEY${suffix}`];\r\n if (!apiKey) {\r\n throw new AuthenticationError(\r\n 'openrouter',\r\n `OPENROUTER_API_KEY${suffix}`,\r\n `No authentication found for OpenRouter (missing OPENROUTER_API_KEY${suffix})`\r\n );\r\n }\r\n logger.debug(`Using OPENROUTER_API_KEY${suffix} for authentication`);\r\n } else {\r\n // Check environment variable first\r\n apiKey = process.env.OPENROUTER_API_KEY;\r\n if (apiKey) {\r\n logger.debug('Using OPENROUTER_API_KEY for authentication');\r\n }\r\n\r\n // Fall back to stored credentials from `pk-agent auth login`\r\n if (!apiKey) {\r\n const storedApiKey = await AuthStorage.getApiKey('openrouter');\r\n if (storedApiKey) {\r\n apiKey = storedApiKey.key;\r\n logger.debug('Using stored API key for OpenRouter authentication');\r\n }\r\n }\r\n\r\n if (!apiKey) {\r\n throw new AuthenticationError(\r\n 'openrouter',\r\n 'OPENROUTER_API_KEY',\r\n 'No authentication found for OpenRouter. Run `pk-agent auth login openrouter` or set OPENROUTER_API_KEY'\r\n );\r\n }\r\n }\r\n\r\n if (!apiKey) {\r\n throw new Error('Failed to obtain API key for OpenRouter');\r\n }\r\n\r\n // OpenRouter uses OpenAI SDK with custom baseURL\r\n const openrouter = createOpenAI({\r\n apiKey,\r\n baseURL: 'https://openrouter.ai/api/v1',\r\n });\r\n return await maybeWrapWithDevTools(openrouter.chat(config.modelName));\r\n\r\n } else if (config.provider === 'demo') {\r\n // Demo provider - no authentication required\r\n logger.debug('Using demo provider (no API key required)');\r\n return await maybeWrapWithDevTools(createDemoModel(config.modelName));\r\n\r\n } else {\r\n throw new Error(`Unsupported provider: ${config.provider}`);\r\n }\r\n}",
|
|
46
|
+
"/**\r\n * Model Fallback Chain (R3-1)\r\n *\r\n * Inspired by Gemini CLI's ModelAvailabilityService - provides automatic\r\n * model fallback when the primary model fails due to rate limits, quota\r\n * exhaustion, or server errors. Maintains a fallback chain and tracks\r\n * per-model failure counts to skip known-degraded models.\r\n *\r\n * Usage:\r\n * const chain = new ModelFallbackChain('anthropic:claude-sonnet-4-5');\r\n * const model = await chain.createModelWithFallback();\r\n */\r\n\r\nimport { createModel, AuthenticationError } from './models';\r\nimport { logger } from './utils/logger';\r\n\r\nexport interface FallbackConfig {\r\n /** Maximum consecutive failures before skipping a model (default: 3) */\r\n maxFailures?: number;\r\n /** Custom fallback chain (overrides default). Format: 'provider:model' */\r\n fallbackModels?: string[];\r\n}\r\n\r\ninterface ModelHealth {\r\n consecutiveFailures: number;\r\n lastFailure?: Date;\r\n lastError?: string;\r\n}\r\n\r\n/**\r\n * Default fallback chains per provider.\r\n * Within the same provider ecosystem first, then cross-provider.\r\n */\r\nconst DEFAULT_FALLBACK_CHAINS: Record<string, string[]> = {\r\n anthropic: [\r\n 'openai:gpt-5.2',\r\n 'openai:gpt-5.2-mini',\r\n ],\r\n openai: [\r\n 'openai:gpt-5.2-mini',\r\n 'anthropic:claude-haiku-4-5-20251001',\r\n ],\r\n openrouter: [\r\n 'openrouter:openai/gpt-5.2',\r\n 'openrouter:google/gemini-2.5-flash',\r\n ],\r\n};\r\n\r\nexport class ModelFallbackChain {\r\n private readonly primaryModel: string;\r\n private readonly chain: string[];\r\n private readonly maxFailures: number;\r\n private readonly health = new Map<string, ModelHealth>();\r\n\r\n constructor(primaryModel: string, config: FallbackConfig = {}) {\r\n this.primaryModel = primaryModel;\r\n this.maxFailures = config.maxFailures ?? 3;\r\n\r\n // Build chain: primary + custom/default fallbacks\r\n if (config.fallbackModels && config.fallbackModels.length > 0) {\r\n this.chain = [primaryModel, ...config.fallbackModels];\r\n } else {\r\n // Extract provider from model string\r\n const provider = primaryModel.split(':')[0] || 'openai';\r\n const defaults = DEFAULT_FALLBACK_CHAINS[provider] ?? [];\r\n this.chain = [primaryModel, ...defaults];\r\n }\r\n\r\n // Parse FALLBACK_MODELS env var override\r\n const envOverride = process.env.FALLBACK_MODELS;\r\n if (envOverride) {\r\n const envModels = envOverride.split(',').map(m => m.trim()).filter(Boolean);\r\n if (envModels.length > 0) {\r\n this.chain.length = 0;\r\n this.chain.push(primaryModel, ...envModels);\r\n logger.debug(`[Fallback] Using env override chain: ${this.chain.join(' -> ')}`);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Attempt to create a model, falling back through the chain on failure.\r\n * Returns the model instance and which model string was used.\r\n */\r\n async createModelWithFallback(): Promise<{ model: any; modelString: string; wasFallback: boolean }> {\r\n for (let i = 0; i < this.chain.length; i++) {\r\n const modelString = this.chain[i];\r\n const health = this.health.get(modelString);\r\n\r\n // Skip models with too many consecutive failures\r\n if (health && health.consecutiveFailures >= this.maxFailures) {\r\n logger.debug(`[Fallback] Skipping ${modelString} (${health.consecutiveFailures} consecutive failures)`);\r\n continue;\r\n }\r\n\r\n try {\r\n const model = await createModel(modelString);\r\n this.reportSuccess(modelString);\r\n\r\n if (i > 0) {\r\n logger.warn(`[Fallback] Using fallback model: ${modelString} (primary: ${this.primaryModel})`);\r\n }\r\n\r\n return {\r\n model,\r\n modelString,\r\n wasFallback: i > 0,\r\n };\r\n } catch (error) {\r\n const errorMsg = error instanceof Error ? error.message : String(error);\r\n\r\n // Don't fallback on authentication errors - they won't resolve by switching models\r\n if (error instanceof AuthenticationError) {\r\n logger.error(`[Fallback] Auth error for ${modelString}, not retryable via fallback`);\r\n throw error;\r\n }\r\n\r\n this.reportFailure(modelString, errorMsg);\r\n\r\n if (i < this.chain.length - 1) {\r\n logger.warn(`[Fallback] ${modelString} failed: ${errorMsg.slice(0, 100)}. Trying next model...`);\r\n } else {\r\n logger.error(`[Fallback] All models in chain exhausted. Last error: ${errorMsg.slice(0, 100)}`);\r\n throw error;\r\n }\r\n }\r\n }\r\n\r\n // Should never reach here, but TypeScript requires it\r\n throw new Error('[Fallback] No models available in fallback chain');\r\n }\r\n\r\n /**\r\n * Report a successful model use - resets failure count\r\n */\r\n reportSuccess(modelString: string): void {\r\n const health = this.health.get(modelString);\r\n if (health) {\r\n health.consecutiveFailures = 0;\r\n }\r\n }\r\n\r\n /**\r\n * Report a model failure - increments failure count\r\n */\r\n reportFailure(modelString: string, error: string): void {\r\n const existing = this.health.get(modelString);\r\n if (existing) {\r\n existing.consecutiveFailures++;\r\n existing.lastFailure = new Date();\r\n existing.lastError = error;\r\n } else {\r\n this.health.set(modelString, {\r\n consecutiveFailures: 1,\r\n lastFailure: new Date(),\r\n lastError: error,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Reset all failure counts (e.g., after some time has passed)\r\n */\r\n reset(): void {\r\n this.health.clear();\r\n }\r\n\r\n /**\r\n * Get the full chain for diagnostics\r\n */\r\n getChain(): readonly string[] {\r\n return this.chain;\r\n }\r\n\r\n /**\r\n * Get health status of all models\r\n */\r\n getHealthReport(): Record<string, { failures: number; lastError?: string | undefined }> {\r\n const report: Record<string, { failures: number; lastError?: string | undefined }> = {};\r\n for (const modelStr of this.chain) {\r\n const health = this.health.get(modelStr);\r\n report[modelStr] = {\r\n failures: health?.consecutiveFailures ?? 0,\r\n lastError: health?.lastError,\r\n };\r\n }\r\n return report;\r\n }\r\n}\r\n",
|
|
47
|
+
"/**\n * Model information API\n *\n * Uses the generated registry first, falls back to models.dev API for unknown models.\n */\n\nimport { getModelFromRegistry } from '../generated/models';\n\nexport interface ModelInfo {\n provider: string;\n modelId: string;\n name: string;\n contextLimit: number;\n outputLimit: number;\n}\n\n// Default context limits for unknown models\nconst DEFAULT_FALLBACK_CONTEXT_LIMIT = 32000;\nconst DEFAULT_FALLBACK_OUTPUT_LIMIT = 4000;\n\n/**\n * Get model information including context limits\n *\n * Uses the generated registry first, falls back to conservative defaults for unknown models.\n *\n * @param modelString - Model string in format \"provider:model-id\"\n * @returns ModelInfo with context and output limits\n */\nexport async function getModelInfo(modelString: string): Promise<ModelInfo> {\n // Parse model string\n const parts = modelString.split(':');\n const [provider, ...modelParts] = parts.length >= 2\n ? parts\n : ['openai', modelString];\n const modelId = modelParts.join(':'); // Handle model IDs with colons\n\n // Check generated registry first\n const registryModel = getModelFromRegistry(modelString);\n if (registryModel) {\n return {\n provider,\n modelId,\n name: registryModel.name,\n contextLimit: registryModel.limit.context,\n outputLimit: registryModel.limit.output,\n };\n }\n\n // Fallback for unknown models - use conservative estimates\n return {\n provider,\n modelId,\n name: modelId,\n contextLimit: DEFAULT_FALLBACK_CONTEXT_LIMIT,\n outputLimit: DEFAULT_FALLBACK_OUTPUT_LIMIT,\n };\n}\n",
|
|
48
|
+
"import type { LanguageModelUsage } from 'ai';\r\nimport { getModelInfo, type ModelInfo } from './utils/models-api';\r\nimport { logger } from './utils/logger';\r\n\r\n// Constants\r\nconst DEFAULT_COMPACTION_THRESHOLD = 0.7; // 70% of context limit\r\nconst DEFAULT_KEEP_RECENT_MESSAGES = 3; // Keep last 3 messages\r\nconst DEFAULT_CHARS_PER_TOKEN = 4; // Conservative estimate (research shows 3-4 chars/token)\r\n// R3-5: Proactive token budget thresholds\r\nconst TOKEN_BUDGET_WARNING = 0.80; // 80% - auto-compact\r\nconst TOKEN_BUDGET_CRITICAL = 0.95; // 95% - aggressive compact (keep only 2 messages)\r\n\r\n// Minimal message shape for context tracking (avoids coupling to AI SDK internals)\r\ninterface ModelMessage {\r\n role: string;\r\n // AI SDK message content can be a plain string or a provider-specific array of \"parts\"\r\n // (e.g., text/file/tool parts). Keep it wide so we can accept stepResult.response.messages.\r\n content: string | Array<unknown>;\r\n}\r\n\r\ninterface TrackedMessage {\r\n message: ModelMessage;\r\n estimatedTokens: number;\r\n actualTokens?: number;\r\n}\r\n\r\nexport class ContextManager {\r\n private modelInfo: ModelInfo | null = null;\r\n private messages: TrackedMessage[] = [];\r\n private totalTokensUsed = 0;\r\n private compactionThreshold: number;\r\n private keepRecentMessages: number;\r\n private isCompacting = false;\r\n /** Deduplicates concurrent compact() calls - returns in-flight result if one exists */\r\n private compactionPromise: Promise<ModelMessage[]> | null = null;\r\n /** P-7: Tracks how many times context has been compacted (\"summaries of summaries\" depth) */\r\n private compactionCount = 0;\r\n\r\n constructor(\r\n private modelString: string,\r\n private onCompact?: (messages: ModelMessage[]) => Promise<ModelMessage>\r\n ) {\r\n // Read from environment variables\r\n this.compactionThreshold = parseFloat(process.env.COMPACTION_THRESHOLD || String(DEFAULT_COMPACTION_THRESHOLD));\r\n this.keepRecentMessages = parseInt(process.env.COMPACTION_KEEP_RECENT || String(DEFAULT_KEEP_RECENT_MESSAGES));\r\n }\r\n\r\n /**\r\n * Initialize the context manager with model info\r\n */\r\n async initialize(): Promise<void> {\r\n this.modelInfo = await getModelInfo(this.modelString);\r\n logger.debug(`Context manager initialized for ${this.modelString}: limit=${this.modelInfo.contextLimit}, threshold=${this.compactionThreshold}`);\r\n }\r\n\r\n /**\r\n * Estimate tokens from text using character count\r\n */\r\n private estimateTokens(text: string): number {\r\n return Math.ceil(text.length / DEFAULT_CHARS_PER_TOKEN);\r\n }\r\n\r\n /**\r\n * Convert message to string for token estimation\r\n */\r\n private messageToString(message: ModelMessage): string {\r\n if (typeof message.content === 'string') {\r\n return message.content;\r\n }\r\n\r\n if (Array.isArray(message.content)) {\r\n return message.content\r\n .map((part: any) => {\r\n if ('text' in part) return part.text;\r\n if ('toolName' in part) return `Tool: ${part.toolName}`;\r\n return JSON.stringify(part);\r\n })\r\n .join(' ');\r\n }\r\n\r\n return JSON.stringify(message.content);\r\n }\r\n\r\n /**\r\n * Add a message and track its tokens\r\n */\r\n addMessage(message: ModelMessage): void {\r\n const text = this.messageToString(message);\r\n const estimatedTokens = this.estimateTokens(text);\r\n\r\n this.messages.push({\r\n message,\r\n estimatedTokens\r\n });\r\n\r\n this.totalTokensUsed += estimatedTokens;\r\n }\r\n\r\n /**\r\n * Update token count with actual usage from AI SDK\r\n */\r\n updateUsage(usage: LanguageModelUsage): void {\r\n if (usage.totalTokens) {\r\n // Update our total with actual tokens\r\n this.totalTokensUsed = usage.totalTokens;\r\n\r\n // Update the last message's actual tokens if available\r\n if (this.messages.length > 0 && usage.outputTokens) {\r\n this.messages[this.messages.length - 1].actualTokens = usage.outputTokens;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Check if compaction is needed\r\n */\r\n shouldCompact(): boolean {\r\n if (!this.modelInfo || this.isCompacting) return false;\r\n\r\n const threshold = this.modelInfo.contextLimit * this.compactionThreshold;\r\n return this.totalTokensUsed >= threshold;\r\n }\r\n\r\n /**\r\n * R3-5: Check proactive token budget status\r\n * Returns tier: 'ok', 'warning' (80%+), or 'critical' (95%+)\r\n */\r\n getTokenBudgetTier(): 'ok' | 'warning' | 'critical' {\r\n if (!this.modelInfo) return 'ok';\r\n const ratio = this.totalTokensUsed / this.modelInfo.contextLimit;\r\n if (ratio >= TOKEN_BUDGET_CRITICAL) return 'critical';\r\n if (ratio >= TOKEN_BUDGET_WARNING) return 'warning';\r\n return 'ok';\r\n }\r\n\r\n /**\r\n * R3-5: Proactive token budget check - call before each API request.\r\n * At 80%: triggers auto-compaction and logs warning.\r\n * At 95%: triggers aggressive compaction (minimal context).\r\n * Returns true if compaction was triggered.\r\n */\r\n async checkTokenBudget(): Promise<boolean> {\r\n if (!this.modelInfo || this.isCompacting) return false;\r\n\r\n const tier = this.getTokenBudgetTier();\r\n const pct = this.getUsagePercentage().toFixed(0);\r\n const used = this.totalTokensUsed;\r\n const limit = this.modelInfo.contextLimit;\r\n\r\n if (tier === 'critical') {\r\n logger.warn(`[R3-5] STOP ${pct}% of token budget used (${used}/${limit}), aggressive compaction`);\r\n // Aggressive mode: temporarily reduce keepRecent to 2\r\n const savedKeepRecent = this.keepRecentMessages;\r\n this.keepRecentMessages = Math.min(2, savedKeepRecent);\r\n try {\r\n await this.compact();\r\n } finally {\r\n this.keepRecentMessages = savedKeepRecent;\r\n }\r\n return true;\r\n }\r\n\r\n if (tier === 'warning') {\r\n logger.warn(`[R3-5] WARNING ${pct}% of token budget used (${used}/${limit}), auto-compacting`);\r\n await this.compact();\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * R3-5: Get full token budget status for diagnostics\r\n */\r\n getTokenBudgetStatus(): { used: number; limit: number; percentage: number; tier: string } {\r\n const limit = this.modelInfo?.contextLimit ?? 0;\r\n return {\r\n used: this.totalTokensUsed,\r\n limit,\r\n percentage: this.getUsagePercentage(),\r\n tier: this.getTokenBudgetTier(),\r\n };\r\n }\r\n\r\n /**\r\n * Get current usage percentage\r\n */\r\n getUsagePercentage(): number {\r\n if (!this.modelInfo) return 0;\r\n return (this.totalTokensUsed / this.modelInfo.contextLimit) * 100;\r\n }\r\n\r\n /**\r\n * Compact messages, keeping recent ones intact\r\n */\r\n async compact(): Promise<ModelMessage[]> {\r\n if (!this.onCompact || this.messages.length <= this.keepRecentMessages) {\r\n return this.messages.map(m => m.message);\r\n }\r\n\r\n // Dedup: if a compaction is already in-flight, return the same result\r\n if (this.compactionPromise) {\r\n return this.compactionPromise;\r\n }\r\n\r\n this.compactionPromise = this._doCompact();\r\n try {\r\n return await this.compactionPromise;\r\n } finally {\r\n this.compactionPromise = null;\r\n }\r\n }\r\n\r\n /**\r\n * Internal compaction implementation\r\n */\r\n private async _doCompact(): Promise<ModelMessage[]> {\r\n this.isCompacting = true;\r\n logger.info(`Context approaching limit (${this.getUsagePercentage().toFixed(0)}% used). Compacting agent context...`);\r\n\r\n try {\r\n // Split messages into old (to compact) and recent (to keep)\r\n const toCompact = this.messages.slice(0, -this.keepRecentMessages);\r\n const toKeep = this.messages.slice(-this.keepRecentMessages);\r\n\r\n // Get messages to compact\r\n const messagesToCompact = toCompact.map(m => m.message);\r\n\r\n // Create compacted summary message\r\n const compactedMessage = await this.onCompact!(messagesToCompact);\r\n\r\n // Rebuild message list with compacted message + recent messages\r\n const compactedTokens = this.estimateTokens(this.messageToString(compactedMessage));\r\n\r\n this.messages = [\r\n {\r\n message: compactedMessage,\r\n estimatedTokens: compactedTokens\r\n },\r\n ...toKeep\r\n ];\r\n\r\n // Recalculate total tokens\r\n const tokensBefore = this.totalTokensUsed;\r\n this.totalTokensUsed = this.messages.reduce((sum, m) => sum + m.estimatedTokens, 0);\r\n\r\n // P-7: Track compaction depth and warn on quality degradation\r\n this.compactionCount++;\r\n logger.info(`Context compacted (depth=${this.compactionCount}, tokens: ${tokensBefore}->${this.totalTokensUsed})`);\r\n\r\n if (this.compactionCount === 3) {\r\n logger.warn('WARNING Context compacted 3 times - quality may degrade (summaries of summaries)');\r\n } else if (this.compactionCount >= 5) {\r\n logger.error('STOP Context compacted 5+ times - severe quality loss likely. Consider increasing context limit or reducing task scope.');\r\n }\r\n\r\n return this.messages.map(m => m.message);\r\n } finally {\r\n this.isCompacting = false;\r\n }\r\n }\r\n\r\n /**\r\n * Get all messages\r\n */\r\n getMessages(): ModelMessage[] {\r\n return this.messages.map(m => m.message);\r\n }\r\n\r\n /**\r\n * Check if compaction is enabled\r\n */\r\n static isEnabled(): boolean {\r\n return process.env.CONTEXT_COMPACTION !== 'false';\r\n }\r\n\r\n /**\r\n * P-7: Get how many times context has been compacted\r\n */\r\n getCompactionCount(): number {\r\n return this.compactionCount;\r\n }\r\n\r\n /**\r\n * R3-3: Export state for session snapshot persistence\r\n */\r\n exportState(): {\r\n messages: Array<{ role: string; content: string | Array<unknown> }>;\r\n compactionCount: number;\r\n totalTokensUsed: number;\r\n contextLimit: number;\r\n } {\r\n return {\r\n messages: this.messages.map(m => m.message),\r\n compactionCount: this.compactionCount,\r\n totalTokensUsed: this.totalTokensUsed,\r\n contextLimit: this.modelInfo?.contextLimit ?? 0,\r\n };\r\n }\r\n\r\n /**\r\n * R3-3: Import state from a saved snapshot for session resume\r\n */\r\n importState(state: {\r\n messages: Array<{ role: string; content: string | Array<unknown> }>;\r\n compactionCount: number;\r\n }): void {\r\n this.messages = [];\r\n this.totalTokensUsed = 0;\r\n this.compactionCount = state.compactionCount;\r\n\r\n // Re-add each message to recalculate token estimates\r\n for (const msg of state.messages) {\r\n this.addMessage(msg);\r\n }\r\n logger.debug(`[R3-3] Imported ${state.messages.length} messages, compaction depth ${state.compactionCount}`);\r\n }\r\n}\r\n",
|
|
49
|
+
"import { generateText } from 'ai';\nimport { createModel } from './models';\nimport { logger } from './utils/logger';\n\n// Minimal message shape for compaction (avoids coupling to AI SDK internals)\ninterface ModelMessage {\n role: string;\n content: string | Array<unknown>;\n}\n\n// Constants\nconst MAX_SUMMARY_TOKENS = 2000;\nconst COMPACTION_SYSTEM_PROMPT = `You are a conversation summarizer. Summarize the following agent context concisely, preserving:\n1. Key decisions and outcomes\n2. Important tool results and errors\n3. Current state and progress\n4. Any critical information needed for continuation\n\nBe concise but comprehensive. Output a single summary that captures the essence of the conversation.`;\n\n/**\n * Compact messages into a summary using the agent's model\n */\nexport async function compactMessages(\n messages: ModelMessage[],\n modelString: string\n): Promise<ModelMessage> {\n try {\n // Prepare messages for summarization\n const contextToSummarize = messages.map(msg => {\n const role = msg.role;\n const content = typeof msg.content === 'string'\n ? msg.content\n : JSON.stringify(msg.content);\n return `${role}: ${content}`;\n }).join('\\n\\n');\n\n // Use the agent's model to create summary\n const model = await createModel(modelString);\n\n const { text } = await generateText({\n model,\n messages: [\n {\n role: 'system',\n content: COMPACTION_SYSTEM_PROMPT\n },\n {\n role: 'user',\n content: `Please summarize this agent context:\\n\\n${contextToSummarize}`\n }\n ],\n maxRetries: 2,\n maxOutputTokens: MAX_SUMMARY_TOKENS,\n temperature: 0.3 // Lower temperature for more consistent summaries\n });\n\n // Return as a system message with the summary\n return {\n role: 'system',\n content: `[Context Summary]\\n${text}\\n[End Summary]`\n };\n } catch (error) {\n logger.error('Failed to compact messages', error as Error);\n\n // Fallback: create a simple summary\n const toolCalls = messages.filter(m =>\n m.role === 'assistant' &&\n typeof m.content !== 'string' &&\n Array.isArray(m.content) &&\n m.content.some((c: any) => 'toolName' in c)\n ).length;\n\n const fallbackSummary = `Previous context: ${messages.length} messages exchanged, ${toolCalls} tool calls made. Key information may have been lost due to compaction error.`;\n\n return {\n role: 'system',\n content: `[Context Summary - Fallback]\\n${fallbackSummary}\\n[End Summary]`\n };\n }\n}\n",
|
|
50
|
+
"/**\r\n * Retry with Exponential Backoff and Jitter\r\n *\r\n * Generic retry utility for API calls and other fallible operations.\r\n * Uses truncated exponential backoff with optional jitter to avoid\r\n * thundering herd problems during outages.\r\n *\r\n * Formula: delay = min(baseDelay * 2^attempt + jitter, maxDelay)\r\n */\r\n\r\nimport { logger } from './logger';\r\n\r\nexport interface RetryOptions {\r\n /** Maximum number of retry attempts (default: 4) */\r\n maxRetries?: number;\r\n /** Base delay between retries in ms (default: 500) */\r\n baseDelayMs?: number;\r\n /** Maximum delay cap in ms (default: 30000) */\r\n maxDelayMs?: number;\r\n /** Add random jitter to prevent thundering herd (default: true) */\r\n jitter?: boolean;\r\n /** Function to determine if error is retryable (default: always true) */\r\n isRetryable?: (error: unknown) => boolean;\r\n /** Label for log messages (default: 'Operation') */\r\n label?: string;\r\n /** AbortSignal for cancellation */\r\n abortSignal?: AbortSignal;\r\n}\r\n\r\nexport interface RetryResult<T> {\r\n /** The successful result */\r\n result: T;\r\n /** Total number of attempts (1 = no retries needed) */\r\n attempts: number;\r\n /** Total delay spent waiting in ms */\r\n totalDelayMs: number;\r\n}\r\n\r\nconst DEFAULT_OPTIONS: Required<Omit<RetryOptions, 'isRetryable' | 'label' | 'abortSignal'>> = {\r\n maxRetries: 4,\r\n baseDelayMs: 500,\r\n maxDelayMs: 30_000,\r\n jitter: true,\r\n};\r\n\r\n/**\r\n * Calculate backoff delay for a given attempt\r\n */\r\nexport function calculateBackoff(\r\n attempt: number,\r\n baseDelayMs: number,\r\n maxDelayMs: number,\r\n jitter: boolean\r\n): number {\r\n // Exponential: baseDelay * 2^attempt\r\n const exponentialDelay = baseDelayMs * Math.pow(2, attempt);\r\n\r\n // Cap at maxDelay\r\n const cappedDelay = Math.min(exponentialDelay, maxDelayMs);\r\n\r\n // Add jitter: random value between 0 and cappedDelay * 0.3\r\n if (jitter) {\r\n const jitterAmount = Math.random() * cappedDelay * 0.3;\r\n return Math.round(cappedDelay + jitterAmount);\r\n }\r\n\r\n return Math.round(cappedDelay);\r\n}\r\n\r\n/**\r\n * Sleep for the given duration, respecting abort signals\r\n */\r\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n if (signal?.aborted) {\r\n reject(new Error('Aborted'));\r\n return;\r\n }\r\n\r\n const timer = setTimeout(resolve, ms);\r\n\r\n if (signal) {\r\n const onAbort = () => {\r\n clearTimeout(timer);\r\n reject(new Error('Aborted'));\r\n };\r\n signal.addEventListener('abort', onAbort, { once: true });\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Execute a function with exponential backoff retry logic\r\n *\r\n * @example\r\n * ```ts\r\n * const { result, attempts } = await retryWithBackoff(\r\n * () => fetchFromAPI(url),\r\n * { maxRetries: 3, label: 'API fetch' }\r\n * );\r\n * ```\r\n */\r\nexport async function retryWithBackoff<T>(\r\n fn: () => Promise<T>,\r\n options: RetryOptions = {}\r\n): Promise<RetryResult<T>> {\r\n const {\r\n maxRetries = DEFAULT_OPTIONS.maxRetries,\r\n baseDelayMs = DEFAULT_OPTIONS.baseDelayMs,\r\n maxDelayMs = DEFAULT_OPTIONS.maxDelayMs,\r\n jitter = DEFAULT_OPTIONS.jitter,\r\n isRetryable = () => true,\r\n label = 'Operation',\r\n abortSignal,\r\n } = options;\r\n\r\n let totalDelayMs = 0;\r\n\r\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\r\n try {\r\n const result = await fn();\r\n if (attempt > 0) {\r\n logger.info(`[Retry] ${label} succeeded on attempt ${attempt + 1}/${maxRetries + 1} (total delay: ${totalDelayMs}ms)`);\r\n }\r\n return { result, attempts: attempt + 1, totalDelayMs };\r\n } catch (error) {\r\n // Don't retry if aborted\r\n if (abortSignal?.aborted) {\r\n throw error;\r\n }\r\n\r\n // Don't retry if we've exhausted attempts\r\n if (attempt >= maxRetries) {\r\n logger.error(`[Retry] ${label} failed after ${attempt + 1} attempts (total delay: ${totalDelayMs}ms)`);\r\n throw error;\r\n }\r\n\r\n // Don't retry non-retryable errors\r\n if (!isRetryable(error)) {\r\n logger.warn(`[Retry] ${label} failed with non-retryable error, not retrying`);\r\n throw error;\r\n }\r\n\r\n // Calculate delay and wait\r\n const delay = calculateBackoff(attempt, baseDelayMs, maxDelayMs, jitter);\r\n totalDelayMs += delay;\r\n\r\n const errorMsg = error instanceof Error ? error.message : String(error);\r\n logger.warn(`[Retry] ${label} attempt ${attempt + 1}/${maxRetries + 1} failed: ${errorMsg.slice(0, 120)}`);\r\n logger.info(`[Retry] Waiting ${delay}ms before attempt ${attempt + 2}/${maxRetries + 1}`);\r\n\r\n await sleep(delay, abortSignal);\r\n }\r\n }\r\n\r\n // This should never be reached, but TypeScript needs it\r\n throw new Error(`[Retry] ${label} exhausted all retries`);\r\n}\r\n",
|
|
51
|
+
"import { streamText, stepCountIs, type ToolSet, type StepResult } from 'ai';\r\nimport type { ParsedAgent } from '../parser';\r\nimport { AuthenticationError } from '../models';\r\nimport { ModelFallbackChain } from '../model-fallback';\r\nimport { CodexAuth } from '../auth/codex';\r\nimport { logger } from '../utils/logger';\r\nimport { ContextManager } from '../context-manager';\r\nimport { compactMessages } from '../compactor';\r\nimport { retryWithBackoff } from '../utils/retry';\r\nimport type { AgentChunk, UserMessageContent } from './types';\r\n\r\n// Constants - increased from 3 to 4 for backoff retry strategy (R3-2)\nconst MAX_RETRIES = 4;\n\nexport function isContextLengthError(errorMessage: string): boolean {\n const msg = (errorMessage || '').toLowerCase();\n return (\n msg.includes('context_length_exceeded') ||\n msg.includes('context length') ||\n msg.includes('maximum context') ||\n msg.includes('maximum context length') ||\n msg.includes('token limit') ||\n msg.includes('context window') ||\n msg.includes('too many tokens') ||\n msg.includes('prompt is too long')\n );\n}\n\nfunction getCurrentCompactionSettingsFromEnv(): { threshold: number; keepRecent: number } {\n const thresholdRaw = process.env.COMPACTION_THRESHOLD;\n const keepRecentRaw = process.env.COMPACTION_KEEP_RECENT;\n\n const threshold = thresholdRaw !== undefined ? parseFloat(thresholdRaw) : 0.7;\n const keepRecent = keepRecentRaw !== undefined ? parseInt(keepRecentRaw) : 3;\n\n return {\n threshold: Number.isFinite(threshold) ? threshold : 0.7,\n keepRecent: Number.isFinite(keepRecent) ? keepRecent : 3,\n };\n}\n\nexport function formatContextLengthError(opts: {\n errorMessage: string;\n stepCount: number;\n isInitialFailure: boolean;\n}): string {\n const { threshold, keepRecent } = getCurrentCompactionSettingsFromEnv();\n\n if (opts.isInitialFailure) {\n return `\nWARNING INITIAL PROMPT TOO LARGE\n\nYour initial prompt exceeds the model's context limit.\n\nSuggestions:\n- Break your task into smaller sub-agents (see docs on subagents)\n- Reduce the size of your initial prompt/instructions\n- Use a model with a larger context window\n- Split your task into multiple sequential steps\n\nError: ${opts.errorMessage}`;\n }\n\n return `\nWARNING CONTEXT LIMIT EXCEEDED\n\nThe conversation history has grown too large for the model.\n\nSuggestions:\n- Break your task into smaller sub-agents (see docs on subagents)\n- Lower the compaction threshold: COMPACTION_THRESHOLD=0.6 (current: ${threshold})\n- Keep fewer recent messages: COMPACTION_KEEP_RECENT=2 (current: ${keepRecent})\n- Use a model with a larger context window\n\nCurrent step: ${opts.stepCount}\nError: ${opts.errorMessage}`;\n}\n\n/**\n * Bridge to check if an error is retryable for the backoff utility.\n * Adapts the existing classifyError/isRetryable logic.\n */\nfunction isErrorRetryable(error: unknown): boolean {\n const msg = error instanceof Error ? error.message : String(error);\r\n return isRetryable(msg);\r\n}\r\n\r\n/**\r\n * Core agent execution as an async generator\r\n */\r\nexport async function* executeAgentCore(\r\n agent: ParsedAgent,\r\n tools: ToolSet,\r\n options: {\r\n userMessage: UserMessageContent;\r\n systemMessages: Array<{ role: string, content: string }>;\r\n maxSteps: number;\r\n abortSignal?: AbortSignal;\r\n subAgentNames?: Set<string>; // Track which tools are subagents\r\n /** R3-3: Called after each step to persist conversation state */\r\n onSnapshotSave?: (state: { messages: Array<{ role: string; content: string | Array<unknown> }>; compactionCount: number; totalTokensUsed: number; contextLimit: number }) => void;\r\n /** R3-3: Saved messages from a previous session to resume from */\r\n resumeMessages?: Array<{ role: string; content: string | Array<unknown> }>;\r\n /** R3-3: Compaction depth from previous session */\r\n resumeCompactionCount?: number;\r\n }\r\n): AsyncGenerator<AgentChunk> {\r\n // R3-1: Use ModelFallbackChain instead of direct createModel\r\n const fallbackChain = new ModelFallbackChain(agent.config.model);\r\n let model;\r\n let activeModelString = agent.config.model;\r\n try {\r\n const result = await fallbackChain.createModelWithFallback();\n model = result.model;\n activeModelString = result.modelString;\n if (result.wasFallback) {\n yield { type: 'status', message: `Using fallback model: ${activeModelString}` };\n }\n } catch (error) {\n if (error instanceof AuthenticationError) {\n throw error;\n }\n throw error;\r\n }\r\n\r\n // Initialize context manager if enabled\r\n let contextManager: ContextManager | null = null;\r\n const initialMessages: any[] = options.resumeMessages ? [...options.resumeMessages] : [\r\n ...options.systemMessages,\r\n { role: 'user', content: options.userMessage }\r\n ];\r\n let messages = initialMessages;\r\n\r\n if (ContextManager.isEnabled()) {\r\n contextManager = new ContextManager(\r\n agent.config.model,\r\n async (messagesToCompact) => compactMessages(messagesToCompact, agent.config.model)\r\n );\r\n await contextManager.initialize();\r\n\r\n if (options.resumeMessages) {\n // R3-3: Resume path - import saved state (recalculates tokens)\n contextManager.importState({\n messages: options.resumeMessages,\n compactionCount: options.resumeCompactionCount ?? 0,\n });\n yield { type: 'status', message: `Resumed context: ${options.resumeMessages.length} messages` };\n } else {\n // Normal path - track initial messages\n for (const msg of messages) {\n contextManager.addMessage(msg);\n }\n }\r\n }\r\n\r\n // Function to create stream with current messages\r\n const createStream = async () => {\r\n // Check if we need to compact before creating stream\r\n if (contextManager?.shouldCompact()) {\r\n messages = await contextManager.compact();\r\n }\r\n\r\n // Extract provider options based on model provider\r\n const provider = agent.config.model.split(':')[0];\r\n\r\n // Only include provider options if they exist and match the model provider\r\n let providerOptions: any = undefined;\r\n if (provider === 'openai') {\r\n // Check if using Codex OAuth (Responses API) vs regular API key (Chat Completions API)\r\n const codexAccess = await CodexAuth.access();\r\n if (codexAccess) {\r\n // Codex OAuth uses Responses API which requires `instructions` field\r\n const systemMessage = messages.find(m => m.role === 'system');\r\n const instructions = typeof systemMessage?.content === 'string'\r\n ? systemMessage.content\r\n : 'You are a helpful assistant.';\r\n\r\n providerOptions = {\r\n openai: {\r\n instructions,\r\n store: false,\r\n ...agent.config.openai\r\n }\r\n };\r\n } else if (agent.config.openai) {\r\n // Regular OpenAI API key - only pass custom config if provided\r\n providerOptions = { openai: agent.config.openai };\r\n }\r\n }\r\n // Future: Add other providers here\r\n // if (provider === 'anthropic' && agent.config.anthropic) {\r\n // providerOptions = { anthropic: agent.config.anthropic };\r\n // }\r\n\r\n const streamConfig: any = {\r\n model,\r\n messages,\r\n // R3-2: Reduced to 1 - outer retryWithBackoff handles retry with exponential backoff\r\n maxRetries: 1,\r\n toolChoice: 'auto' as const,\r\n stopWhen: stepCountIs(options.maxSteps),\r\n prepareStep: async () => {\r\n // R3-5: Proactive token budget check (80%/95% thresholds)\r\n if (contextManager) {\r\n const budgetTriggered = await contextManager.checkTokenBudget();\r\n if (budgetTriggered) {\r\n messages = contextManager.getMessages();\r\n return { messages };\r\n }\r\n }\r\n // Original compaction check (70% threshold)\r\n if (contextManager?.shouldCompact()) {\r\n messages = await contextManager.compact();\r\n return { messages };\r\n }\r\n return undefined;\r\n },\r\n onStepFinish: (stepResult: StepResult<ToolSet>) => {\r\n stepCount++;\r\n if (contextManager) {\r\n const responseMessages = stepResult.response?.messages ?? [];\r\n if (responseMessages.length > 0) {\r\n for (const msg of responseMessages) {\r\n contextManager.addMessage(msg);\r\n }\r\n } else {\r\n if (stepResult.text?.trim()) {\r\n contextManager.addMessage({ role: 'assistant', content: stepResult.text });\r\n }\r\n if (stepResult.toolResults?.length) {\r\n for (const toolResult of stepResult.toolResults) {\r\n contextManager.addMessage({\r\n role: 'tool',\r\n content: [{\r\n type: 'tool-result',\r\n toolCallId: toolResult.toolCallId,\r\n toolName: toolResult.toolName,\r\n output: (toolResult as any).output\r\n }]\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Warn when approaching step limit\r\n if (stepCount >= options.maxSteps * 0.9 && stepCount < options.maxSteps) {\r\n logger.warn(`WARNING Approaching step limit: ${stepCount}/${options.maxSteps} steps used`);\r\n } else if (stepCount >= options.maxSteps) {\r\n logger.warn(`WARNING Step limit reached: ${stepCount}/${options.maxSteps} steps. Generation may be incomplete.`);\r\n }\r\n\r\n // R3-3: Auto-save snapshot (fire-and-forget)\r\n if (options.onSnapshotSave && contextManager) {\r\n try {\r\n options.onSnapshotSave(contextManager.exportState());\r\n } catch {\r\n // Never break agent loop for snapshot save\r\n }\r\n }\r\n },\r\n ...(options.abortSignal && { abortSignal: options.abortSignal }),\r\n ...(providerOptions && { providerOptions })\r\n };\r\n\r\n // Only add tools if there are any\r\n if (Object.keys(tools).length > 0) {\r\n streamConfig.tools = tools;\r\n }\r\n\r\n return streamText(streamConfig);\r\n };\r\n\r\n // Declare timing variables before use\r\n let accumulatedText = '';\r\n const toolStartTimes = new Map<string, number>();\r\n let llmGenerationStartTime: number | undefined;\r\n let llmFirstTokenTime: number | undefined;\r\n const currentLlmModel = agent.config.model;\r\n let stepCount = 0; // Track step count to detect when we're approaching limit\r\n let anonymousToolCallCounter = 0;\r\n const anonymousToolCalls: string[] = [];\r\n\r\n const resolveToolCallId = (chunk: any, kind: 'call' | 'result' | 'error'): string => {\r\n const explicitId = (chunk as any).toolCallId;\r\n if (explicitId) return explicitId;\r\n\r\n if (kind === 'call') {\r\n const generatedId = `toolcall_${Date.now()}_${++anonymousToolCallCounter}`;\r\n anonymousToolCalls.push(generatedId);\r\n return generatedId;\r\n }\r\n\r\n return anonymousToolCalls.shift() || `toolcall_${Date.now()}_${++anonymousToolCallCounter}`;\r\n };\r\n\r\n // R3-2: Wrap stream creation with exponential backoff for retryable errors\r\n let stream;\r\n try {\r\n const { result, attempts, totalDelayMs } = await retryWithBackoff(\r\n () => createStream(),\r\n {\r\n maxRetries: MAX_RETRIES,\r\n baseDelayMs: 500,\r\n maxDelayMs: 30_000,\r\n jitter: true,\r\n isRetryable: isErrorRetryable,\r\n label: 'Stream creation',\r\n ...(options.abortSignal && { abortSignal: options.abortSignal }),\r\n }\r\n );\r\n stream = result;\r\n if (attempts > 1) {\r\n logger.info(`[R3-2] Stream created after ${attempts} attempts (${totalDelayMs}ms total backoff)`);\r\n }\r\n } catch (error: any) {\n // Handle initial stream creation errors (after all retries exhausted)\n const errorMessage = error?.message || String(error);\n\n if (isContextLengthError(errorMessage)) {\n const isInitialFailure = stepCount === 0;\n logger.error(formatContextLengthError({\n errorMessage,\n stepCount,\n isInitialFailure,\n }));\n } else {\n logger.error('Failed to create stream after retries:', error);\n }\n\n yield { type: 'error', error };\r\n return;\r\n }\r\n\r\n try {\r\n for await (const chunk of stream.fullStream) {\r\n switch (chunk.type) {\r\n case 'tool-call': {\r\n const startTime = Date.now();\r\n const toolCallId = resolveToolCallId(chunk, 'call');\r\n toolStartTimes.set(toolCallId, startTime);\r\n\r\n yield {\r\n type: 'tool-call',\r\n toolName: chunk.toolName,\r\n toolCallId, // Add toolCallId to the chunk\r\n toolInput: (chunk as any).input || (chunk as any).args,\r\n toolStartTime: startTime,\r\n ...(options.subAgentNames?.has(chunk.toolName!) && { isSubAgent: true })\r\n };\r\n break;\r\n }\r\n\r\n case 'tool-result': {\r\n const toolCallId = resolveToolCallId(chunk, 'result');\r\n const startTime = toolStartTimes.get(toolCallId);\r\n const duration = startTime ? Date.now() - startTime : undefined;\r\n\r\n yield {\r\n type: 'tool-result',\r\n toolName: chunk.toolName,\r\n toolCallId, // Add toolCallId to the chunk\r\n toolResult: parseToolResult(chunk),\r\n toolResultRaw: (chunk as any).result || (chunk as any).output,\r\n ...(startTime && { toolStartTime: startTime }),\r\n ...(duration !== undefined && { toolDuration: duration })\r\n };\r\n\r\n // Clean up\r\n if (startTime) {\r\n toolStartTimes.delete(toolCallId);\r\n }\r\n\r\n break;\r\n }\r\n\r\n case 'tool-error': {\r\n const toolCallId = resolveToolCallId(chunk, 'error');\r\n const startTime = toolStartTimes.get(toolCallId);\r\n const duration = startTime ? Date.now() - startTime : undefined;\r\n\r\n // Pass tool errors as structured results to let AI decide on retry\r\n const errorMessage = (chunk as any).error?.message || (chunk as any).error || 'Unknown error';\r\n yield {\r\n type: 'tool-result', // Treat as result so AI sees it\r\n toolName: chunk.toolName,\r\n toolCallId,\r\n toolResult: JSON.stringify({\r\n success: false,\r\n error: {\r\n type: classifyError(errorMessage),\r\n message: errorMessage,\r\n retryable: isRetryable(errorMessage),\r\n suggestions: getSuggestions(errorMessage)\r\n }\r\n }),\r\n toolResultRaw: { error: errorMessage },\r\n ...(startTime && { toolStartTime: startTime }),\r\n ...(duration !== undefined && { toolDuration: duration })\r\n };\r\n\r\n // Clean up\r\n if (startTime) {\r\n toolStartTimes.delete(toolCallId);\r\n }\r\n break;\r\n }\r\n\r\n case 'text-delta':\r\n const textContent = (chunk as any).text || (chunk as any).textDelta || (chunk as any).delta || (chunk as any).content;\r\n if (textContent && typeof textContent === 'string') {\r\n // Track time to first token\r\n if (!llmFirstTokenTime && llmGenerationStartTime) {\r\n llmFirstTokenTime = Date.now();\r\n yield { type: 'llm-first-token', llmFirstTokenTime };\r\n }\r\n accumulatedText += textContent;\r\n yield { type: 'text', text: textContent };\r\n }\r\n break;\r\n\r\n case 'start-step':\r\n llmGenerationStartTime = Date.now();\r\n llmFirstTokenTime = undefined;\r\n yield { type: 'llm-start', llmModel: currentLlmModel, llmStartTime: llmGenerationStartTime };\r\n break;\r\n\r\n case 'finish-step':\r\n if (llmGenerationStartTime) {\r\n const llmDuration = Date.now() - llmGenerationStartTime;\r\n yield {\r\n type: 'finish',\r\n finishReason: chunk.finishReason,\r\n toolStartTime: llmGenerationStartTime,\r\n toolDuration: llmDuration\r\n };\r\n llmGenerationStartTime = undefined;\r\n llmFirstTokenTime = undefined;\r\n }\r\n break;\r\n\r\n case 'finish':\r\n accumulatedText = '';\r\n\r\n // Update usage if available\r\n const usage = (chunk as any).totalUsage || (chunk as any).usage;\r\n if (contextManager && usage) {\r\n contextManager.updateUsage(usage);\r\n }\r\n\r\n // Log finish reason for debugging and warnings (final usage only)\r\n const finishReason = chunk.finishReason;\r\n if (usage) {\r\n if (finishReason === 'length') {\r\n logger.warn(`\r\nWARNING OUTPUT LENGTH LIMIT REACHED\r\n\r\nThe model reached its maximum output token limit. The response was truncated.\r\n\r\nSuggestions:\r\n- Break your task into smaller sub-agents (see docs on subagents)\r\n- Use a model with a larger output limit\r\n- Ask the agent to be more concise in its responses\r\n\r\nCurrent step: ${stepCount}/${options.maxSteps}`);\r\n } else if (finishReason === 'content-filter') {\r\n logger.warn(`WARNING Content filter triggered. Response may be incomplete.`);\r\n } else if (finishReason === 'error') {\r\n logger.warn(`WARNING Generation stopped due to an error.`);\r\n }\r\n }\r\n // Note: We can't directly detect step limit from finishReason, as AI SDK uses 'stop'\r\n\r\n // Complete final LLM segment if exists\r\n if (llmGenerationStartTime) {\r\n const llmDuration = Date.now() - llmGenerationStartTime;\r\n yield {\r\n type: 'finish',\r\n finishReason: chunk.finishReason,\r\n usage,\r\n toolStartTime: llmGenerationStartTime,\r\n toolDuration: llmDuration\r\n };\r\n llmGenerationStartTime = undefined;\r\n llmFirstTokenTime = undefined;\r\n } else {\r\n yield {\r\n type: 'finish',\r\n finishReason: chunk.finishReason,\r\n usage\r\n };\r\n }\r\n\r\n // We can't directly detect step limit from finishReason alone\r\n // since AI SDK just reports 'stop' when stepCountIs condition is met\r\n // But we can check our step count\r\n if (stepCount >= options.maxSteps && chunk.finishReason === 'stop') {\r\n logger.warn(`\r\nWARNING Agent stopped at step limit (${options.maxSteps} steps).\r\n To increase the limit, set MAX_STEPS environment variable:\r\n MAX_STEPS=2000 pk-agent run <agent-file>`);\r\n }\r\n break;\r\n\r\n case 'error':\r\n yield { type: 'error', error: chunk.error };\r\n break;\r\n\r\n case 'abort':\r\n logger.warn(`WARNING Stream aborted - likely due to timeout or cancellation (${stepCount} steps completed)`);\r\n // Create an AbortError to properly signal timeout\r\n const abortError = new Error('Stream aborted - execution timeout or manual cancellation');\r\n abortError.name = 'AbortError';\r\n yield { type: 'error', error: abortError };\r\n return;\r\n\r\n // Handle other AI SDK chunk types that we don't need to process but shouldn't warn about\r\n case 'tool-input-start':\r\n case 'tool-input-delta':\r\n case 'tool-input-end':\r\n case 'text-start':\r\n case 'text-end':\r\n // AI SDK streaming events for text generation boundaries (not tool-related)\r\n // These indicate when the LLM starts/stops generating text content\r\n // Safe to ignore as they don't require processing\r\n break;\r\n\r\n default:\r\n logger.debug(`[STREAM] Unknown chunk type received: ${chunk.type}`);\r\n break;\r\n }\r\n }\r\n\r\n } catch (error: any) {\n const errorMessage = error?.message || String(error);\n\n if (isContextLengthError(errorMessage)) {\n logger.error(formatContextLengthError({\n errorMessage,\n stepCount,\n isInitialFailure: false,\n }));\n yield { type: 'error', error };\n return;\n }\n\r\n // Handle AI SDK errors gracefully\r\n if (error.name === 'AI_NoSuchToolError' || error.message?.includes('unavailable tool')) {\r\n // Extract tool name from the error message\r\n const toolNameMatch = error.message?.match(/tool '([^']+)'/);\r\n const toolName = toolNameMatch ? toolNameMatch[1] : 'unknown';\r\n\r\n logger.warn(`AI tried to call non-existent tool: ${toolName}`);\r\n\r\n // Return this as a tool result so the AI can adapt\r\n yield {\r\n type: 'tool-result',\r\n toolName: toolName,\r\n toolResult: JSON.stringify({\r\n success: false,\r\n error: {\r\n type: 'tool_not_found',\r\n message: `The tool '${toolName}' does not exist. Available tools: ${Object.keys(tools).join(', ')}`,\r\n retryable: false,\r\n suggestions: [\r\n 'Check the available tools list',\r\n 'Use a different tool with similar functionality',\r\n 'Proceed without this tool'\r\n ]\r\n }\r\n }),\r\n toolResultRaw: { error: error.message }\r\n };\r\n\r\n // Continue execution - don't terminate the agent\r\n // The AI will receive the error as a tool result and can adapt\r\n\r\n } else {\r\n // For other errors, still try to handle gracefully\r\n logger.error('Stream processing error:', error);\r\n yield { type: 'error', error };\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Classify error type for intelligent retry decisions\r\n */\r\nexport function classifyError(error: string): string {\r\n const errorLower = error.toLowerCase();\r\n if (errorLower.includes('no such tool') || errorLower.includes('unavailable tool') || errorLower.includes('tool not found')) {\r\n return 'tool_not_found';\r\n }\r\n if (errorLower.includes('500') || errorLower.includes('502') || errorLower.includes('503') || errorLower.includes('service unavailable')) {\r\n return 'server_error';\r\n }\r\n if (errorLower.includes('429') || errorLower.includes('rate limit')) {\r\n return 'rate_limit';\r\n }\r\n if (errorLower.includes('timeout') || errorLower.includes('timed out')) {\r\n return 'timeout';\r\n }\r\n if (errorLower.includes('401') || errorLower.includes('403') || errorLower.includes('unauthorized') || errorLower.includes('forbidden')) {\r\n return 'auth_error';\r\n }\r\n if (errorLower.includes('404') || errorLower.includes('not found')) {\r\n return 'not_found';\r\n }\r\n if (errorLower.includes('network') || errorLower.includes('connection')) {\r\n return 'network_error';\r\n }\r\n return 'unknown';\r\n}\r\n\r\n/**\r\n * Determine if error is retryable\r\n */\r\nexport function isRetryable(error: string): boolean {\r\n const type = classifyError(error);\r\n return ['server_error', 'rate_limit', 'timeout', 'network_error'].includes(type);\r\n}\r\n\r\n/**\r\n * Get recovery suggestions based on error type\r\n */\r\nexport function getSuggestions(error: string): string[] {\r\n const type = classifyError(error);\r\n switch (type) {\r\n case 'tool_not_found':\r\n return ['Check the available tools list', 'Use a different tool with similar functionality', 'Proceed without this tool'];\r\n case 'server_error':\r\n return ['Wait a moment and retry', 'Try alternative approach', 'Proceed with available information'];\r\n case 'rate_limit':\r\n return ['Wait before retrying', 'Use different tool', 'Reduce request frequency'];\r\n case 'timeout':\r\n return ['Retry with simpler request', 'Break into smaller tasks', 'Try alternative tool'];\r\n case 'auth_error':\r\n return ['Check credentials', 'Use different service', 'Proceed without this data'];\r\n case 'not_found':\r\n return ['Verify parameters', 'Try different search terms', 'Resource may not exist'];\r\n case 'network_error':\r\n return ['Check connection and retry', 'Try alternative service', 'Wait and retry'];\r\n default:\r\n return ['Review error details', 'Try alternative approach', 'Proceed with caution'];\r\n }\r\n}\r\n\r\n/**\r\n * Parse tool result from various formats\r\n */\r\nexport function parseToolResult(chunk: any): string {\r\n let output = chunk.result || chunk.output;\r\n\r\n if (typeof output === 'object' && output !== null) {\r\n if (output.output) {\r\n output = output.output;\r\n } else if (output.content) {\r\n // Handle MCP content array format\r\n if (Array.isArray(output.content)) {\r\n output = output.content\r\n .filter((item: any) => item.type === 'text')\r\n .map((item: any) => item.text)\r\n .join('\\n\\n');\r\n } else {\r\n output = output.content;\r\n }\r\n } else if (output.result) {\r\n output = output.result;\r\n } else {\r\n output = JSON.stringify(output);\r\n }\r\n }\r\n\r\n const resultStr = typeof output === 'string' ? output : JSON.stringify(output);\r\n\r\n // Detect if the result looks like an error message\r\n // Skip error detection for skill tools since skill content often contains\r\n // documentation about errors (e.g., \"not found\" troubleshooting guides)\r\n const isSkillTool = chunk.toolName === 'tools__skill_load' || chunk.toolName === 'tools__skill_read';\r\n\r\n if (resultStr && typeof resultStr === 'string' && !isSkillTool) {\r\n const errorPatterns = [\r\n /^Error:/i,\r\n /^Error executing/i,\r\n /^Failed to/i,\r\n /authentication.*failed/i,\r\n /unauthorized/i,\r\n /permission denied/i,\r\n /not found/i,\r\n /invalid.*token/i,\r\n /invalid.*api.*key/i\r\n ];\r\n\r\n for (const pattern of errorPatterns) {\r\n if (pattern.test(resultStr)) {\r\n // Extract operation from error message or use generic \"operation\"\r\n let operation = 'operation';\r\n\r\n // Try to extract operation context from error message\r\n const commandMatch = resultStr.match(/['\"`]([^'\"`]+)['\"`]/);\r\n const fileMatch = resultStr.match(/(?:file|path|directory)\\s+['\"`]?([^\\s'\"`]+)/i);\r\n const actionMatch = resultStr.match(/(?:failed to|cannot|unable to)\\s+(\\w+)/i);\r\n\r\n if (commandMatch) {\r\n operation = commandMatch[1];\r\n } else if (fileMatch) {\r\n operation = fileMatch[1];\r\n } else if (actionMatch) {\r\n operation = actionMatch[1];\r\n }\r\n\r\n logger.warnWithTool(chunk.toolName || 'unknown', operation, resultStr);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return resultStr;\r\n}\r\n",
|
|
52
|
+
"/**\n * Unescape a JSON string from environment variable\n * Handles escaped quotes and other escape sequences that might be present\n * when JSON is stored in .env files\n * \n * @param value The potentially escaped JSON string\n * @returns The unescaped string ready for JSON parsing\n */\nexport function unescapeJsonEnvVar(value: string): string {\n if (!value || typeof value !== 'string') {\n return value;\n }\n\n // Check if the value looks like it might be escaped JSON\n if (!value.includes('\\\\')) {\n return value;\n }\n\n // Common escape sequences that might appear in .env files\n // Handle double-escaped sequences first (\\\\n -> \\n in the JSON string)\n let result = value\n .replace(/\\\\\"/g, '\"'); // Unescape quotes first\n \n // Check if we have double-escaped sequences (e.g., \\\\\\\\n)\n if (result.includes('\\\\\\\\')) {\n // This means we have double escaping, handle it carefully\n result = result\n .replace(/\\\\\\\\n/g, '\\\\n') // \\\\n -> \\n (literal backslash-n in JSON)\n .replace(/\\\\\\\\r/g, '\\\\r') // \\\\r -> \\r\n .replace(/\\\\\\\\t/g, '\\\\t') // \\\\t -> \\t\n .replace(/\\\\\\\\/g, '\\\\'); // \\\\ -> \\ (do this last)\n } else {\n // Single escaping\n result = result\n .replace(/\\\\n/g, '\\n') // \\n -> newline character\n .replace(/\\\\r/g, '\\r') // \\r -> carriage return\n .replace(/\\\\t/g, '\\t') // \\t -> tab\n .replace(/\\\\\\\\/g, '\\\\'); // \\\\ -> \\\n }\n \n return result;\n}\n\n/**\n * Parse a JSON environment variable, handling escaped strings\n * \n * @param value The environment variable value\n * @returns Parsed JSON object or null if parsing fails\n */\nexport function parseJsonEnvVar<T = unknown>(value: string | undefined): T | null {\n if (!value) {\n return null;\n }\n\n try {\n // First try parsing as-is\n return JSON.parse(value) as T;\n } catch (e) {\n // If that fails, try unescaping first\n try {\n const unescaped = unescapeJsonEnvVar(value);\n return JSON.parse(unescaped) as T;\n } catch (e2) {\n // If both fail, return null\n return null;\n }\n }\n}\n\n/**\n * Get and parse a JSON environment variable\n * \n * @param name The environment variable name\n * @returns Parsed JSON object or null if not found or parsing fails\n */\nexport function getJsonEnvVar<T = unknown>(name: string): T | null {\n return parseJsonEnvVar<T>(process.env[name]);\n}",
|
|
53
|
+
"import { createHash } from 'crypto';\r\nimport { join } from 'path';\r\nimport { homedir } from 'os';\r\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\r\nimport { logger } from './utils/logger';\r\n\r\n/**\r\n * P-3: File-based cache for MCP tool schemas.\r\n *\r\n * Caches `tools/list` results per server to avoid re-fetching on subsequent runs.\r\n * Cache key = sha256(JSON.stringify(config)) truncated to 12 chars.\r\n * TTL default = 5 minutes (configurable via MCP_CACHE_TTL env, 0 = disabled).\r\n */\r\n\r\ninterface CacheEntry {\r\n tools: Record<string, unknown>; // Serialized tool schemas\r\n timestamp: number;\r\n version: string;\r\n}\r\n\r\nconst CACHE_VERSION = '1';\r\nconst DEFAULT_TTL_MS = 5 * 60 * 1000; // 5 minutes\r\n\r\nexport class MCPToolCache {\r\n private cacheDir: string;\r\n private ttlMs: number;\r\n\r\n constructor() {\r\n this.cacheDir = join(homedir(), '.pk-agent', 'cache', 'mcp-tools');\r\n\r\n // TTL from env (in seconds), 0 = disabled\r\n const envTtl = process.env.MCP_CACHE_TTL;\r\n if (envTtl !== undefined) {\r\n const ttlSec = parseInt(envTtl, 10);\r\n this.ttlMs = isNaN(ttlSec) || ttlSec <= 0 ? 0 : ttlSec * 1000;\r\n } else {\r\n this.ttlMs = DEFAULT_TTL_MS;\r\n }\r\n }\r\n\r\n /** Whether caching is enabled */\r\n get enabled(): boolean {\r\n return this.ttlMs > 0 && process.env.NO_MCP_CACHE !== 'true';\r\n }\r\n\r\n /** Generate cache key from server config */\r\n private key(serverName: string, config: unknown): string {\r\n const hash = createHash('sha256')\r\n .update(JSON.stringify(config))\r\n .digest('hex')\r\n .slice(0, 12);\r\n return `${serverName}-${hash}`;\r\n }\r\n\r\n /** Get cached tools for a server, or null if expired/missing */\r\n get(serverName: string, config: unknown): Record<string, unknown> | null {\r\n if (!this.enabled) return null;\r\n\r\n const cacheFile = join(this.cacheDir, `${this.key(serverName, config)}.json`);\r\n if (!existsSync(cacheFile)) return null;\r\n\r\n try {\r\n const entry: CacheEntry = JSON.parse(readFileSync(cacheFile, 'utf-8'));\r\n\r\n // Version mismatch -> stale\r\n if (entry.version !== CACHE_VERSION) return null;\r\n\r\n // TTL check\r\n if (Date.now() - entry.timestamp > this.ttlMs) {\r\n logger.debug(`[MCP Cache] Expired cache for ${serverName}`);\r\n return null;\r\n }\r\n\r\n logger.debug(`[MCP Cache] Hit for ${serverName} (${Object.keys(entry.tools).length} tools)`);\r\n return entry.tools;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /** Store tool schemas for a server */\r\n set(serverName: string, config: unknown, tools: Record<string, unknown>): void {\r\n if (!this.enabled) return;\r\n\r\n try {\r\n // Ensure cache directory exists\r\n if (!existsSync(this.cacheDir)) {\r\n mkdirSync(this.cacheDir, { recursive: true });\r\n }\r\n\r\n const entry: CacheEntry = {\r\n tools,\r\n timestamp: Date.now(),\r\n version: CACHE_VERSION,\r\n };\r\n\r\n const cacheFile = join(this.cacheDir, `${this.key(serverName, config)}.json`);\r\n writeFileSync(cacheFile, JSON.stringify(entry), 'utf-8');\r\n logger.debug(`[MCP Cache] Stored ${Object.keys(tools).length} tools for ${serverName}`);\r\n } catch (err) {\r\n // Cache write errors are non-fatal\r\n logger.debug(`[MCP Cache] Failed to write cache for ${serverName}: ${err instanceof Error ? err.message : String(err)}`);\r\n }\r\n }\r\n}\r\n",
|
|
54
|
+
"import { createMCPClient } from '@ai-sdk/mcp';\r\nimport type { Tool } from 'ai';\r\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js';\r\nimport { StdioClientTransport, getDefaultEnvironment } from '@modelcontextprotocol/sdk/client/stdio.js';\r\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\r\nimport {\r\n ListResourcesResultSchema,\r\n ReadResourceResultSchema,\r\n type Resource\r\n} from '@modelcontextprotocol/sdk/types.js';\r\nimport { logger } from './utils/logger';\r\nimport { parseJsonEnvVar } from './utils/env';\r\nimport { resolveToolTimeout } from './utils/config';\r\nimport { z } from 'zod';\r\nimport type { AgentConfig } from './parser';\r\nimport { resolve, isAbsolute } from 'path';\r\nimport { MCPToolCache } from './mcp-cache';\r\n\r\n// Use the actual type from the parser to avoid mismatches\r\n// Note: Using mcpServers (the normalized field after transform)\r\nexport type MCPServerConfig = NonNullable<AgentConfig['mcpServers']>[string];\r\nexport type MCPServersConfig = AgentConfig['mcpServers'];\r\n\r\nexport interface MCPConnection {\r\n name: string;\r\n client: Awaited<ReturnType<typeof createMCPClient>>;\r\n rawClient?: Client; // Raw MCP SDK client for resource access (lazily created)\r\n disallowedTools?: string[]; // List of disallowed tool names/patterns for this connection\r\n preloadedTools?: Record<string, Tool>; // Cached tools for HTTP connections (loaded immediately)\r\n config?: MCPServerConfig; // Original config for accessing toolTimeout and other settings\r\n _rawClientConfig?: { name: string; config: MCPServerConfig; debug: boolean; basePath?: string }; // Config for lazy raw client\r\n}\r\n\r\n/**\r\n * Resolve ${env:VAR_NAME} placeholders in a string\r\n * @param value The string that may contain ${env:VAR_NAME} placeholders\r\n * @returns The string with placeholders replaced by environment variable values\r\n */\r\nfunction resolveEnvVariables(value: string): string {\r\n return value.replace(/\\$\\{env:(\\w+)\\}/g, (match, varName) => {\r\n const envValue = process.env[varName];\r\n if (envValue === undefined) {\r\n logger.warn(`Environment variable '${varName}' referenced in config is not set`);\r\n return match; // Return original if not found\r\n }\r\n return envValue;\r\n });\r\n}\r\n\r\n/**\r\n * Create transport based on configuration (stdio or HTTP)\r\n */\r\nfunction createTransport(name: string, config: MCPServerConfig, debug: boolean = false, basePath?: string): any {\r\n // HTTP transport with SSE streaming\r\n if ('url' in config) {\r\n const options: any = {};\r\n\r\n if (config.sessionId) {\r\n options.sessionId = config.sessionId;\r\n }\r\n\r\n if (config.auth?.token) {\r\n const resolvedToken = resolveEnvVariables(config.auth.token);\r\n options.authProvider = {\r\n getToken: async () => resolvedToken\r\n };\r\n }\r\n\r\n if (config.headers) {\r\n options.requestInit = {\r\n headers: config.headers\r\n };\r\n }\r\n\r\n return new StreamableHTTPClientTransport(new URL(config.url), options);\r\n }\r\n\r\n // Stdio transport\r\n if ('command' in config) {\r\n // Prepare environment variables\r\n const env = getDefaultEnvironment();\r\n\r\n // Check required environment variables first (fail fast)\r\n if (config.requiredEnvVars && config.requiredEnvVars.length > 0) {\r\n const missingRequired: string[] = [];\r\n for (const varName of config.requiredEnvVars) {\r\n if (process.env[varName] === undefined) {\r\n missingRequired.push(varName);\r\n } else {\r\n const rawValue = process.env[varName];\r\n // Try to parse as JSON if it looks like JSON\r\n const parsedValue = parseJsonEnvVar(rawValue);\r\n\r\n if (parsedValue !== null && typeof parsedValue === 'object') {\r\n env[varName] = JSON.stringify(parsedValue);\r\n logger.debug(`[MCP] Adding required JSON env var ${varName} to ${name}`);\r\n } else {\r\n env[varName] = rawValue;\r\n logger.debug(`[MCP] Adding required env var ${varName} to ${name}`);\r\n }\r\n }\r\n }\r\n\r\n if (missingRequired.length > 0) {\r\n const error = new Error(\r\n `Missing required environment variables for MCP server '${name}': ${missingRequired.join(', ')}\\n` +\r\n `Please set these in your .env file or export them in your shell.`\r\n );\r\n // Mark this as a fatal error that should exit immediately\r\n (error as any).fatal = true;\r\n throw error;\r\n }\r\n }\r\n\r\n // Only include explicitly allowed environment variables\r\n if (config.allowedEnvVars && config.allowedEnvVars.length > 0) {\r\n logger.debug(`[MCP] Server ${name} allowed env vars: ${config.allowedEnvVars.join(', ')}`);\r\n for (const varName of config.allowedEnvVars) {\r\n // Skip if already added as required\r\n if (config.requiredEnvVars?.includes(varName)) {\r\n continue;\r\n }\r\n\r\n if (process.env[varName] !== undefined) {\r\n const rawValue = process.env[varName];\r\n\r\n // Try to parse as JSON if it looks like JSON\r\n const parsedValue = parseJsonEnvVar(rawValue);\r\n\r\n // If parseJsonEnvVar returns an object/array, stringify it back\r\n // because environment variables must be strings\r\n if (parsedValue !== null && typeof parsedValue === 'object') {\r\n env[varName] = JSON.stringify(parsedValue);\r\n logger.debug(`[MCP] Adding JSON env var ${varName} to ${name}`);\r\n } else {\r\n // Use the original value if not JSON or parsing failed\r\n env[varName] = rawValue;\r\n logger.debug(`[MCP] Adding env var ${varName} to ${name}`);\r\n }\r\n } else {\r\n logger.warn(`[MCP] Optional environment variable '${varName}' not set for server '${name}'`);\r\n }\r\n }\r\n }\r\n\r\n // Override with any server-specific environment variables\r\n if ('env' in config && config.env) {\r\n Object.assign(env, config.env);\r\n }\r\n\r\n // Resolve command path relative to basePath if provided and not absolute\r\n let commandPath = config.command;\r\n if (basePath && !isAbsolute(commandPath)) {\r\n // Only resolve if it looks like a path (contains / or \\)\r\n if (commandPath.includes('/') || commandPath.includes('\\\\')) {\r\n commandPath = resolve(basePath, commandPath);\r\n logger.debug(`[MCP] Resolved command path: ${config.command} -> ${commandPath}`);\r\n }\r\n }\r\n\r\n return new StdioClientTransport({\r\n command: commandPath,\r\n args: config.args || [],\r\n env: env,\r\n stderr: debug ? 'inherit' : 'ignore'\r\n });\r\n }\r\n\r\n throw new Error('MCP server must have either url or command');\r\n}\r\n\r\n/**\r\n * Connect to MCP servers using AI SDK createMCPClient\r\n * @param servers Optional server configurations\r\n * @param debug Enable debug logging\r\n * @returns Array of MCP client connections\r\n */\r\nexport async function connectMCP(servers?: MCPServersConfig, debug: boolean = false, basePath?: string): Promise<MCPConnection[]> {\r\n if (!servers) {\r\n logger.debug('[MCP] No MCP servers configured');\r\n return [];\r\n }\r\n\r\n const serverNames = Object.keys(servers);\r\n logger.info(`[MCP] Connecting to ${serverNames.length} MCP server(s): ${serverNames.join(', ')}`);\r\n\r\n // Note: Environment variables are already loaded in index.ts before this is called\r\n // The envFile parameter is kept for backwards compatibility but is no longer used here\r\n\r\n const connectStart = performance.now();\r\n\r\n // Create promises for all server connections in parallel\r\n const connectionPromises = Object.entries(servers).map(async ([name, config]) => {\r\n const serverStart = performance.now();\r\n try {\r\n logger.debug(`[MCP] Configuring server: ${name} - ${JSON.stringify(config)}`);\r\n\r\n // Create transport based on config type\r\n const transport = createTransport(name, config, debug, basePath);\r\n\r\n // Create MCP client using AI SDK's built-in method\r\n const client = await createMCPClient({\r\n name,\r\n transport: transport,\r\n });\r\n\r\n // For HTTP transports, immediately fetch tools to ensure connection is ready\r\n // This follows the official AI SDK pattern for MCP clients\r\n let preloadedTools: Record<string, Tool> | undefined = undefined;\r\n if ('url' in config) {\r\n logger.debug(`[MCP] HTTP connection detected, fetching tools immediately for: ${name}`);\r\n try {\r\n // Cast to Record<string, Tool> since McpToolSet is structurally compatible\r\n preloadedTools = await client.tools() as Record<string, Tool>;\r\n logger.debug(`[MCP] HTTP connection verified and ${Object.keys(preloadedTools).length} tools loaded for: ${name}`);\r\n } catch (error) {\r\n logger.warn(`[MCP] Failed to fetch tools immediately for ${name}: ${error instanceof Error ? error.message : String(error)}`);\r\n // Re-throw to be caught by outer try-catch\r\n throw error;\r\n }\r\n }\r\n\r\n // Store config for lazy raw client creation (only created when resources are requested)\r\n // This avoids spawning a second transport per server - most agents never use resources\r\n const rawClientConfig = { name, config, debug: !!debug, ...(basePath !== undefined && { basePath }) };\r\n\r\n const serverMs = (performance.now() - serverStart).toFixed(0);\r\n logger.info(`[MCP] Connected to ${name} in ${serverMs}ms`);\r\n\r\n return {\r\n name,\r\n client,\r\n config, // Store config for accessing toolTimeout and other settings\r\n _rawClientConfig: rawClientConfig,\r\n ...(preloadedTools && { preloadedTools }),\r\n ...(config.disallowedTools && { disallowedTools: config.disallowedTools })\r\n };\r\n } catch (error) {\r\n // Check if this is a fatal error (missing required env vars)\r\n if ((error as any).fatal) {\r\n logger.error(`[ERROR] ${error instanceof Error ? error.message : String(error)}`);\r\n // Re-throw fatal errors immediately\r\n throw error;\r\n }\r\n\r\n // Smart error detection: check if allowed env vars are missing\r\n const missingAllowed = config.allowedEnvVars?.filter(v => !process.env[v]) || [];\r\n\r\n let errorMessage = `Failed to connect to MCP server ${name}: ${error instanceof Error ? error.message : String(error)}`;\r\n\r\n if (missingAllowed.length > 0) {\r\n errorMessage += `\\n\\nNote: The following optional environment variables are not set: ${missingAllowed.join(', ')}`;\r\n errorMessage += `\\nIf this server requires these variables, please set them in your .env file or export them in your shell.`;\r\n }\r\n\r\n logger.error(errorMessage);\r\n throw new Error(errorMessage);\r\n }\r\n });\r\n\r\n // Execute all connections in parallel and wait for all to complete\r\n // Using Promise.allSettled to handle partial failures gracefully\r\n const results = await Promise.allSettled(connectionPromises);\r\n\r\n const connections: MCPConnection[] = [];\r\n const failedServers: string[] = [];\r\n\r\n for (const result of results) {\r\n if (result.status === 'fulfilled') {\r\n connections.push(result.value);\r\n } else {\r\n // Check if this is a fatal error (missing required env vars)\r\n if (result.reason?.fatal) {\r\n // Re-throw fatal errors immediately to exit the CLI\r\n throw result.reason;\r\n }\r\n\r\n // Extract server name from error message\r\n const errorMessage = result.reason?.message || '';\r\n const serverMatch = errorMessage.match(/Failed to connect to MCP server: (.+)/);\r\n const serverName = serverMatch ? serverMatch[1] : 'unknown';\r\n failedServers.push(serverName);\r\n }\r\n }\r\n\r\n // If some servers failed, log a warning but continue with successful connections\r\n if (failedServers.length > 0) {\r\n logger.warn(`Some MCP servers failed to connect: ${failedServers.join(', ')}`);\r\n }\r\n\r\n // If all servers failed, throw an error\r\n if (connections.length === 0 && serverNames.length > 0) {\r\n throw new Error('All MCP servers failed to connect');\r\n }\r\n\r\n // P-6: MCP startup telemetry summary\r\n if (connections.length > 0) {\r\n const totalMs = (performance.now() - connectStart).toFixed(0);\r\n logger.info(`[MCP] All ${connections.length} server(s) connected in ${totalMs}ms`);\r\n }\r\n\r\n return connections;\r\n}\r\n\r\n/**\r\n * Lazily create and cache the raw MCP SDK client for resource access\r\n * Only creates the client on first call - avoids spawning extra transports for servers\r\n * that never need resource access.\r\n */\r\nasync function ensureRawClient(connection: MCPConnection): Promise<Client | null> {\r\n if (connection.rawClient) return connection.rawClient;\r\n if (!connection._rawClientConfig) return null;\r\n\r\n try {\r\n const { name, config, debug, basePath } = connection._rawClientConfig;\r\n const rawTransport = createTransport(name, config, debug, basePath);\r\n\r\n const rawClient = new Client({\r\n name: `${name}-raw`,\r\n version: '1.0.0',\r\n }, {\r\n capabilities: {}\r\n });\r\n\r\n await rawClient.connect(rawTransport);\r\n connection.rawClient = rawClient; // Cache for subsequent calls\r\n logger.debug(`[MCP] Lazy-created raw client for resource access: ${name}`);\r\n return rawClient;\r\n } catch (error) {\r\n logger.debug(`[MCP] Failed to create raw client for ${connection.name}: ${error instanceof Error ? error.message : String(error)}`);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Get available resources from an MCP connection\r\n * @param connection MCP connection with raw client\r\n * @returns Array of resources\r\n */\r\nasync function getMCPResources(connection: MCPConnection): Promise<Resource[]> {\r\n const rawClient = await ensureRawClient(connection);\r\n if (!rawClient) {\r\n return [];\r\n }\r\n\r\n try {\r\n const response = await rawClient.request(\r\n { method: 'resources/list' },\r\n ListResourcesResultSchema\r\n );\r\n\r\n return response.resources || [];\r\n } catch (error) {\r\n logger.debug(`Server ${connection.name} does not support resources: ${error instanceof Error ? error.message : String(error)}`);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Create synthetic tools for resource access\r\n * @param connection MCP connection\r\n * @param resources Available resources\r\n * @returns Tools for resource operations\r\n */\r\nfunction createResourceTools(connection: MCPConnection, resources: Resource[]): Record<string, Tool> {\r\n const tools: Record<string, Tool> = {};\r\n\r\n if (resources.length === 0) {\r\n return tools;\r\n }\r\n\r\n // Create a list resources tool\r\n const listToolName = `mcp__${connection.name}__list_resources`;\r\n tools[listToolName] = {\r\n description: `List all available resources from ${connection.name}`,\r\n inputSchema: z.object({}),\r\n execute: async () => {\r\n try {\r\n const resourceList = resources.map(r => ({\r\n uri: r.uri,\r\n name: r.name,\r\n description: r.description,\r\n mimeType: r.mimeType\r\n }));\r\n\r\n const output = JSON.stringify(resourceList, null, 2);\r\n return {\r\n output\r\n };\r\n } catch (error) {\r\n return {\r\n output: `Error listing resources: ${error instanceof Error ? error.message : String(error)}`\r\n };\r\n }\r\n }\r\n };\r\n\r\n // Create a read resource tool\r\n const readToolName = `mcp__${connection.name}__read_resource`;\r\n tools[readToolName] = {\r\n description: `Read a specific resource from ${connection.name}`,\r\n inputSchema: z.object({\r\n uri: z.string().describe('The URI of the resource to read')\r\n }),\r\n execute: async ({ uri }: { uri: string }) => {\r\n const rawClient = await ensureRawClient(connection);\r\n if (!rawClient) {\r\n return {\r\n output: 'Raw client not available for resource reading'\r\n };\r\n }\r\n\r\n try {\r\n const response = await rawClient.request(\r\n {\r\n method: 'resources/read',\r\n params: { uri }\r\n },\r\n ReadResourceResultSchema\r\n );\r\n\r\n // Handle different content types\r\n const contents = response.contents || [];\r\n const outputs: string[] = [];\r\n\r\n for (const content of contents) {\r\n if (typeof content.text === 'string') {\r\n outputs.push(content.text);\r\n } else if (content.blob) {\r\n outputs.push(`[Binary data: ${content.mimeType || 'unknown type'}]`);\r\n }\r\n }\r\n\r\n return {\r\n output: outputs.join('\\n\\n')\r\n };\r\n } catch (error) {\r\n return {\r\n output: `Error reading resource ${uri}: ${error instanceof Error ? error.message : String(error)}`\r\n };\r\n }\r\n }\r\n };\r\n\r\n return tools;\r\n}\r\n\r\n/**\r\n * Check if a tool name matches any disallowed patterns\r\n * @param toolName The tool name to check\r\n * @param disallowedPatterns Array of disallowed patterns (supports wildcards)\r\n * @returns True if the tool should be disallowed\r\n */\r\nfunction isToolDisallowed(toolName: string, disallowedPatterns?: string[]): boolean {\r\n if (!disallowedPatterns || disallowedPatterns.length === 0) {\r\n return false;\r\n }\r\n\r\n for (const pattern of disallowedPatterns) {\r\n // Support wildcard patterns\r\n if (pattern.includes('*')) {\r\n // Escape regex special chars except * (wildcard)\r\n const regexPattern = pattern\r\n .split('*')\r\n .map(part => part.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&'))\r\n .join('.*');\r\n const regex = new RegExp(`^${regexPattern}$`);\r\n if (regex.test(toolName)) {\r\n return true;\r\n }\r\n } else {\r\n // Exact match\r\n if (toolName === pattern) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Get available tools from MCP connections using AI SDK approach\r\n * @param connections Array of MCP connections\r\n * @param debug Enable debug logging\r\n * @returns Tools in AI SDK format\r\n */\r\nexport async function getMCPTools(connections: MCPConnection[]): Promise<Record<string, Tool>> {\r\n // P-3: Instantiate tool schema cache\r\n const cache = new MCPToolCache();\r\n\r\n // Process all connections in parallel to fetch their tools and resources\r\n const toolPromises = connections.map(async (connection) => {\r\n const connectionTools: Record<string, Tool> = {};\r\n\r\n // First, try to get regular tools\r\n try {\r\n // If tools were preloaded during connection (HTTP), use them\r\n // Otherwise, fetch them now (stdio)\r\n // Cast to Record<string, Tool> since McpToolSet is structurally compatible\r\n const clientTools = connection.preloadedTools || await connection.client.tools() as Record<string, Tool>;\r\n\r\n // P-3: Update cache with fresh tool schemas\r\n if (cache.enabled && connection.config) {\r\n const toolSchemas: Record<string, unknown> = {};\r\n for (const [name, tool] of Object.entries(clientTools)) {\r\n toolSchemas[name] = {\r\n description: (tool as any).description,\r\n // Store only schema structure, not execute functions\r\n };\r\n }\r\n cache.set(connection.name, connection.config, toolSchemas);\r\n }\r\n\r\n // Log what tools were retrieved\r\n const toolNames = Object.keys(clientTools);\r\n const source = connection.preloadedTools ? '(preloaded)' : '(fetched)';\r\n logger.info(`[MCP] Retrieved ${toolNames.length} tools from ${connection.name} ${source}${toolNames.length > 0 ? ': ' + toolNames.join(', ') : ''}`);\r\n\r\n // Add tools with prefixed names to avoid conflicts and wrap execution (like opencode)\r\n const disallowedTools: string[] = [];\r\n for (const [toolName, tool] of Object.entries(clientTools)) {\r\n // Check if this tool is disallowed\r\n if (isToolDisallowed(toolName, connection.disallowedTools)) {\r\n disallowedTools.push(toolName);\r\n continue;\r\n }\r\n\r\n const prefixedName = `mcp__${connection.name}__${toolName}`;\r\n\r\n // Wrap the tool execution like opencode does\r\n const originalExecute = tool.execute;\r\n if (!originalExecute) {\r\n continue;\r\n }\r\n\r\n // Get timeout configuration for this server\r\n const timeoutSeconds = resolveToolTimeout(connection.config?.toolTimeout);\r\n\r\n // Create wrapped tool with proper result handling and timeout\r\n const wrappedTool = {\r\n ...tool,\r\n execute: async (args: any, opts: any) => {\r\n try {\r\n let result: any;\r\n\r\n // Apply timeout if configured (0 means no timeout)\r\n if (timeoutSeconds > 0) {\r\n const timeoutPromise = new Promise((_, reject) => {\r\n setTimeout(() => {\r\n const error = new Error(`Tool timed out after ${timeoutSeconds}s`);\r\n error.name = 'TimeoutError';\r\n reject(error);\r\n }, timeoutSeconds * 1000);\r\n });\r\n\r\n result = await Promise.race([\r\n originalExecute(args, opts),\r\n timeoutPromise\r\n ]);\r\n } else {\r\n // No timeout - execute normally\r\n result = await originalExecute(args, opts);\r\n }\r\n\r\n // Handle MCP result format (like opencode does)\r\n if (result && typeof result === 'object' && 'content' in result && Array.isArray(result.content)) {\r\n const output = result.content\r\n .filter((x: any) => x.type === \"text\")\r\n .map((x: any) => x.text)\r\n .join(\"\\n\\n\");\r\n\r\n // Check for isError flag - MCP servers return this when tool execution fails\r\n if (result.isError === true) {\r\n logger.error(`[MCP] Tool ${prefixedName} returned error (isError=true): ${output.substring(0, 200)}`);\r\n throw new Error(output || 'Tool execution failed');\r\n }\r\n\r\n // Additional check: Parse the content to detect API error responses\r\n // Some MCP servers don't set isError but return error JSON\r\n // Look for common error patterns like {\"status\": 400, \"object\": \"error\", ...}\r\n try {\r\n const parsed = JSON.parse(output);\r\n if (parsed && typeof parsed === 'object') {\r\n // Check for HTTP error status codes (4xx, 5xx)\r\n const hasErrorStatus = typeof parsed.status === 'number' && parsed.status >= 400;\r\n const hasErrorObject = parsed.object === 'error' || parsed.error;\r\n const hasErrorCode = typeof parsed.code === 'string' && parsed.code.includes('error');\r\n\r\n if (hasErrorStatus || (hasErrorObject && hasErrorCode)) {\r\n const errorMsg = parsed.message || parsed.error?.message || output;\r\n logger.error(`[MCP] Tool ${prefixedName} returned error JSON: ${errorMsg.substring(0, 200)}`);\r\n throw new Error(errorMsg);\r\n }\r\n }\r\n } catch (parseError) {\r\n // If it's a SyntaxError from JSON.parse, ignore it (content is not JSON)\r\n // Otherwise, re-throw (it's our intentional error from the error detection above)\r\n if (!(parseError instanceof SyntaxError)) {\r\n throw parseError;\r\n }\r\n }\r\n\r\n // Return as string - AI SDK handles conversion automatically\r\n return output;\r\n }\r\n\r\n // Fallback for non-standard result formats - return string directly\r\n // AI SDK v6 handles automatic conversion to provider format\r\n return typeof result === 'string' ? result : JSON.stringify(result);\r\n } catch (error) {\r\n // Log the error first\r\n const errorMessage = error instanceof Error ? error.message : String(error);\r\n logger.error(`Tool call failed: ${prefixedName} - ${errorMessage}`);\r\n\r\n // Re-throw the error so it properly triggers tool-error event\r\n throw error;\r\n }\r\n }\r\n };\r\n\r\n connectionTools[prefixedName] = wrappedTool;\r\n }\r\n if (disallowedTools.length > 0) {\r\n const toolsList = disallowedTools.map(name => `'${name}'`).join(', ');\r\n logger.info(`[MCP] Tools disallowed for server ${connection.name}: ${toolsList}`);\r\n }\r\n } catch (error) {\r\n logger.warn(`[MCP] Failed to get tools from ${connection.name}: ${error instanceof Error ? error.message : String(error)}`);\r\n logger.debug(`[MCP] Full error for ${connection.name}: ${error instanceof Error ? error.stack : String(error)}`);\r\n // Don't return yet - try to get resources\r\n }\r\n\r\n // Now try to get resources and create synthetic tools for them\r\n try {\r\n const resources = await getMCPResources(connection);\r\n if (resources.length > 0) {\r\n logger.info(`[MCP] Found ${resources.length} resources in ${connection.name}`);\r\n const resourceTools = createResourceTools(connection, resources);\r\n Object.assign(connectionTools, resourceTools);\r\n logger.info(`[MCP] Created ${Object.keys(resourceTools).length} resource tools for ${connection.name}: ${Object.keys(resourceTools).join(', ')}`);\r\n } else {\r\n logger.debug(`[MCP] No resources found in ${connection.name}`);\r\n }\r\n } catch (error) {\r\n logger.debug(`[MCP] Failed to get resources from ${connection.name}: ${error instanceof Error ? error.message : String(error)}`);\r\n }\r\n\r\n return connectionTools;\r\n });\r\n\r\n // Wait for all tools to be fetched in parallel\r\n const toolsArrays = await Promise.all(toolPromises);\r\n\r\n // Merge all tools into a single object\r\n const tools: Record<string, Tool> = {};\r\n for (const connectionTools of toolsArrays) {\r\n Object.assign(tools, connectionTools);\r\n }\r\n\r\n // Log final tool count\r\n const toolCount = Object.keys(tools).length;\r\n if (toolCount > 0) {\r\n logger.debug(`[MCP] Total tools loaded: ${toolCount}`);\r\n logger.debug(`[MCP] Tool names: ${Object.keys(tools).join(', ')}`);\r\n } else {\r\n logger.debug(`[MCP] No tools were loaded from any MCP server`);\r\n }\r\n\r\n return tools;\r\n}",
|
|
55
|
+
"import { resolve, join, dirname } from 'path';\nimport { homedir } from 'os';\nimport { existsSync, mkdirSync } from 'fs';\nimport { readFileSync, writeFileSync } from 'fs';\nimport { createHash } from 'crypto';\n\nexport function isURL(input: string): boolean {\n return input.startsWith('http://') || input.startsWith('https://');\n}\n\nexport function resolveAgentPath(basePath: string | undefined, agentPath: string): string {\n if (!basePath) {\n return agentPath;\n }\n\n if (isURL(agentPath)) {\n return agentPath;\n }\n\n if (isURL(basePath)) {\n const base = basePath.endsWith('/') ? basePath : `${basePath}/`;\n return new URL(agentPath, base).toString();\n }\n\n return resolve(basePath, agentPath);\n}\n\nexport function getRemoteAgentName(url: string): string {\n try {\n const path = new URL(url).pathname;\n const file = path.split('/').pop() || 'agent';\n return file.replace(/\\.pk-agent$/i, '');\n } catch {\n return 'agent';\n }\n}\n\nexport interface FetchRemoteAgentOptions {\n cacheDir?: string;\n noCache?: boolean;\n timeoutMs?: number;\n}\n\ninterface RemoteAgentCacheEntry {\n url: string;\n fetchedAt: number;\n etag?: string;\n lastModified?: string;\n body: string;\n}\n\nfunction ensureDir(dir: string): void {\n try {\n mkdirSync(dir, { recursive: true });\n } catch {\n // best-effort\n }\n}\n\nfunction sha256Hex(input: string): string {\n return createHash('sha256').update(input).digest('hex');\n}\n\nfunction getCacheDir(opts?: FetchRemoteAgentOptions): string {\n if (opts?.cacheDir) return opts.cacheDir;\n return join(homedir(), '.pk-agent', 'cache', 'remote-agents');\n}\n\nfunction cachePathForUrl(cacheDir: string, url: string): string {\n // Keep filenames short, predictable, and filesystem-friendly.\n return join(cacheDir, `${sha256Hex(url).slice(0, 24)}.json`);\n}\n\nfunction readCache(filePath: string): RemoteAgentCacheEntry | null {\n if (!existsSync(filePath)) return null;\n try {\n const raw = readFileSync(filePath, 'utf-8');\n const parsed = JSON.parse(raw) as RemoteAgentCacheEntry;\n if (!parsed || typeof parsed.body !== 'string') return null;\n return parsed;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(filePath: string, entry: RemoteAgentCacheEntry): void {\n ensureDir(dirname(filePath));\n try {\n writeFileSync(filePath, JSON.stringify(entry, null, 2) + '\\n', 'utf-8');\n } catch {\n // ignore\n }\n}\n\nfunction validateRemoteAgentUrl(url: string): void {\n let u: URL;\n try {\n u = new URL(url);\n } catch {\n throw new Error(`Invalid URL: ${url}`);\n }\n const proto = u.protocol.toLowerCase();\n if (proto !== 'https:' && proto !== 'http:') {\n throw new Error(`URL must use http:// or https:// (got: ${u.protocol})`);\n }\n if (!u.pathname.toLowerCase().endsWith('.pk-agent')) {\n throw new Error(`Remote agent URL must end with .pk-agent (got: ${url})`);\n }\n}\n\nfunction resolveFetchTimeoutMs(opts?: FetchRemoteAgentOptions): number {\n if (opts?.timeoutMs && Number.isFinite(opts.timeoutMs) && opts.timeoutMs > 0) {\n return Math.floor(opts.timeoutMs);\n }\n const env = Number.parseInt(String(process.env.PK_AGENT_REMOTE_FETCH_TIMEOUT_MS ?? '').trim(), 10);\n if (Number.isFinite(env) && env > 0) {\n return env;\n }\n return 30_000;\n}\n\nexport async function fetchRemoteAgent(url: string, opts?: FetchRemoteAgentOptions): Promise<string> {\n validateRemoteAgentUrl(url);\n\n const noCacheEnv = ['1', 'true', 'yes'].includes(String(process.env.PK_AGENT_REMOTE_NO_CACHE ?? '').toLowerCase());\n const noCache = opts?.noCache === true || noCacheEnv;\n\n const cacheDir = getCacheDir(opts);\n const cacheFile = cachePathForUrl(cacheDir, url);\n const cached = noCache ? null : readCache(cacheFile);\n\n const headers: Record<string, string> = {};\n if (cached?.etag) headers['If-None-Match'] = cached.etag;\n if (cached?.lastModified) headers['If-Modified-Since'] = cached.lastModified;\n\n const timeoutMs = resolveFetchTimeoutMs(opts);\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, { headers, signal: controller.signal });\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n const allowStale = ['1', 'true', 'yes'].includes(String(process.env.PK_AGENT_REMOTE_ALLOW_STALE_CACHE ?? '').toLowerCase());\n if (allowStale && cached) {\n return cached.body;\n }\n throw new Error(`Failed to fetch agent from ${url}: request timed out after ${timeoutMs}ms`);\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n\n if (response.status === 304 && cached) {\n return cached.body;\n }\n if (!response.ok) {\n const allowStale = ['1', 'true', 'yes'].includes(String(process.env.PK_AGENT_REMOTE_ALLOW_STALE_CACHE ?? '').toLowerCase());\n if (allowStale && cached) {\n return cached.body;\n }\n throw new Error(`Failed to fetch agent from ${url}: ${response.status} ${response.statusText}`);\n }\n\n const body = await response.text();\n if (!noCache) {\n ensureDir(cacheDir);\n writeCache(cacheFile, {\n url,\n fetchedAt: Date.now(),\n etag: response.headers.get('etag') ?? undefined,\n lastModified: response.headers.get('last-modified') ?? undefined,\n body,\n });\n }\n\n return body;\n}\n",
|
|
56
|
+
"/**\n * Build autonomous agent system prompt\n */\nexport function buildAutonomousAgentPrompt(todayDate: string, isSubAgent: boolean = false): string {\n const basePrompt = `You are an autonomous AI agent outputting to CLI/terminal. When given a task:\n- Break it down into clear steps\r\n- Execute each step thoroughly\r\n- Iterate until the task is fully complete\r\n- DO NOT narrate actions - never use \"Let me...\", \"I'll...\", \"I'm going to...\"\r\n- Execute tools directly without announcing them\r\n- Output only results and what changed, not process or intentions\r\n- Format for terminal: use bullets and arrows, keep lines short\r\n- When tools modify the system, explicitly state what changed:\r\n * Modified files (path and what changed)\r\n * Created/updated resources (e.g., Linear issues, GitHub PRs, Slack messages)\r\n * Executed commands and their results`;\r\n\r\n const subAgentAddition = isSubAgent ? '\\n- Provide only essential summary when complete' : '';\r\n\r\n return `${basePrompt}${subAgentAddition}\r\n\nToday's date: ${todayDate}`;\n}\n\nexport type SystemMessage = { role: 'system'; content: string };\n\n/**\n * Build system messages shared by main agents and sub-agents.\n *\n * This keeps the ordering consistent:\n * 1) Provider-specific system message (when applicable)\n * 2) Autonomous agent prompt (always)\n */\nexport function buildSystemMessages(modelString: string, isSubAgent: boolean): SystemMessage[] {\n const systemMessages: SystemMessage[] = [];\n\n // Keep behavior consistent with existing code: treat any model string containing\n // \"anthropic\" as needing the Claude Code system message (covers openrouter:anthropic/... too).\n if (modelString.includes('anthropic')) {\n systemMessages.push({\n role: 'system',\n content: \"You are Claude Code, Anthropic's official CLI for Claude.\",\n });\n }\n\n const todayDate = new Date().toLocaleDateString('en-US', {\n weekday: 'long',\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n\n systemMessages.push({\n role: 'system',\n content: buildAutonomousAgentPrompt(todayDate, isSubAgent),\n });\n\n return systemMessages;\n}\n",
|
|
57
|
+
"import type { LanguageModelUsage } from 'ai';\nimport type { ToolCallTrace } from '../plugin/types';\nimport type { DoomLoopDetector } from '../tools/index.js';\nimport type { SessionManager } from '../session';\nimport type { AgentPart } from '../types/parts';\nimport type { ToolStateCompleted, ToolStateError } from '../session/types';\nimport { logger } from '../utils/logger';\nimport type { AgentChunk } from './types';\nimport { redactForTrace, redactObjectDeep } from '../utils/redaction';\n\n/**\n * Process agent stream chunks and handle output/logging\n */\nexport async function processAgentStream(\n generator: AsyncGenerator<AgentChunk>,\n options?: {\n collectToolCalls?: boolean;\n logPrefix?: string;\n sessionManager?: SessionManager;\n sessionID?: string;\n messageID?: string;\n agentName?: string;\n doomLoopDetector?: DoomLoopDetector;\n /** Suppress console output (for serve mode) */\n quiet?: boolean;\n }\n): Promise<{\n text: string;\n usage?: LanguageModelUsage;\n toolCalls?: Array<{ tool: string; args: unknown }>;\n subAgentTokens?: number;\n toolCallTraces?: ToolCallTrace[];\n finishReason?: string;\n finishReasons?: string[];\n hasTextOutput: boolean;\n parts: AgentPart[];\n}> {\n let finalText = '';\n let usage: LanguageModelUsage | null = null;\n const toolCalls: Array<{ tool: string; args: unknown }> = [];\n let subAgentTokens = 0;\n const toolCallTraces: ToolCallTrace[] = [];\n const pendingToolCalls = new Map<string, { name: string; startTime: number; partID?: string; input?: unknown }>();\n let currentLlmCall: { model: string; startTime: number; firstTokenTime?: number } | null = null;\n let llmSegmentCount = 0;\n let hasTextOutput = false;\n const finishReasons: string[] = [];\n const parts: AgentPart[] = [];\n\n // Track current text part for streaming updates with debouncing\n let currentTextPart: { partID: string; text: string; startTime: number } | null = null;\n let creatingTextPart = false;\n let pendingTextBuffer = '';\n let createTextPartPromise: Promise<void> | null = null;\n let textUpdateTimer: NodeJS.Timeout | null = null;\n const TEXT_UPDATE_DEBOUNCE_MS = 500; // Write to disk every 500ms max\n\n // Track pending session updates to ensure they complete before returning\n // Use Set with self-cleanup to avoid holding references to resolved promises\n const pendingSessionUpdates = new Set<Promise<unknown>>();\n const trackSessionUpdate = (promise: Promise<unknown>) => {\n pendingSessionUpdates.add(promise);\n promise.finally(() => pendingSessionUpdates.delete(promise));\n };\n\n // Helper to finalize current text part\n const finalizeTextPart = async () => {\n if (createTextPartPromise) {\n try {\n await createTextPartPromise;\n } catch {\n // Ignore failures; we'll still attempt to finalize if possible\n }\n }\n\n // Clear any pending debounced update\n if (textUpdateTimer) {\n clearTimeout(textUpdateTimer);\n textUpdateTimer = null;\n }\n\n if (currentTextPart && options?.sessionManager && options?.sessionID && options?.messageID && options?.agentName) {\n try {\n await options.sessionManager.updatePart(\n options.sessionID,\n options.agentName,\n options.messageID,\n currentTextPart.partID,\n {\n text: currentTextPart.text.trimEnd(),\n time: {\n start: currentTextPart.startTime,\n end: Date.now()\n }\n }\n );\n } catch (err) {\n logger.debug(`Failed to finalize text part: ${(err as Error).message}`);\n }\n currentTextPart = null;\n } else if (pendingTextBuffer) {\n pendingTextBuffer = '';\n }\n };\n\n const finalizePendingToolCalls = async (error?: unknown) => {\n if (pendingToolCalls.size === 0) {\n return;\n }\n\n const endTime = Date.now();\n const errorMessage = error\n ? `Tool call did not complete before stream ended: ${error instanceof Error ? error.message : String(error)}`\n : 'Tool call did not complete before stream ended.';\n\n for (const pending of pendingToolCalls.values()) {\n const duration = Math.max(0, endTime - pending.startTime);\n const isSubAgent = pending.name.startsWith('subagent__');\n\n toolCallTraces.push({\n name: pending.name,\n type: isSubAgent ? 'subagent' : 'tool',\n startTime: pending.startTime,\n duration,\n success: false,\n input: pending.input\n });\n\n if (pending.partID && options?.sessionManager && options?.sessionID && options?.messageID && options?.agentName) {\n const errorState: ToolStateError = {\n status: 'error',\n input: pending.input ?? {},\n error: errorMessage,\n time: {\n start: pending.startTime,\n end: endTime\n }\n };\n\n const updatePromise = options.sessionManager.updatePart(options.sessionID, options.agentName, options.messageID, pending.partID, {\n state: errorState\n }).catch(err => logger.debug(`Failed to mark tool part as error: ${err.message}`));\n trackSessionUpdate(updatePromise);\n }\n }\n\n pendingToolCalls.clear();\n };\n\n let streamError: unknown;\n\n try {\n for await (const chunk of generator) {\n switch (chunk.type) {\n case 'text':\n parts.push({\n type: 'text',\n text: chunk.text!,\n timestamp: Date.now()\n });\n finalText += chunk.text!;\n if (chunk.text && chunk.text.trim()) {\n hasTextOutput = true;\n }\n if (!options?.quiet) {\n logger.response(chunk.text!);\n }\n\n // Log to session with debounced writes to prevent race conditions\n if (options?.sessionManager && options?.sessionID && options?.messageID && options?.agentName) {\n if (!currentTextPart) {\n if (!creatingTextPart) {\n creatingTextPart = true;\n const startTime = Date.now();\n const initialText = chunk.text!;\n const addPromise = options.sessionManager.addPart(options.sessionID, options.agentName, options.messageID, {\n type: 'text',\n text: initialText,\n time: { start: startTime }\n } as any).then(partID => {\n currentTextPart = {\n partID,\n text: initialText + pendingTextBuffer,\n startTime\n };\n pendingTextBuffer = '';\n }).catch(err => logger.debug(`Failed to create text part: ${err.message}`)).finally(() => {\n creatingTextPart = false;\n createTextPartPromise = null;\n });\n createTextPartPromise = addPromise.then(() => undefined);\n trackSessionUpdate(addPromise);\n } else {\n pendingTextBuffer += chunk.text!;\n }\n } else {\n const textPart = currentTextPart as { partID: string; text: string; startTime: number };\n textPart.text += chunk.text!;\n\n // Clear existing timer and schedule new debounced write\n if (textUpdateTimer) {\n clearTimeout(textUpdateTimer);\n }\n\n // Capture current state for the timeout callback\n const partID = textPart.partID;\n const getText = () => currentTextPart?.text || '';\n\n textUpdateTimer = setTimeout(() => {\n if (options?.sessionManager && options?.sessionID && options?.messageID && options?.agentName) {\n const updatePromise = options.sessionManager.updatePart(\n options.sessionID,\n options.agentName,\n options.messageID,\n partID,\n {\n text: getText()\n }\n ).catch(err => logger.debug(`Failed to update text part: ${err.message}`));\n trackSessionUpdate(updatePromise);\n }\n textUpdateTimer = null;\n }, TEXT_UPDATE_DEBOUNCE_MS);\n }\n }\n break;\n\n case 'status':\n parts.push({\n type: 'status',\n message: chunk.message || '',\n timestamp: Date.now()\n });\n if (!options?.quiet && chunk.message) {\n logger.info(chunk.message);\n }\n break;\n\n case 'llm-start':\n // Track the start of an LLM generation\n if (chunk.llmModel && !options?.quiet) {\n logger.llmStart(chunk.llmModel);\n }\n\n if (chunk.llmModel && chunk.llmStartTime) {\n currentLlmCall = {\n model: chunk.llmModel,\n startTime: chunk.llmStartTime\n };\n llmSegmentCount++;\n }\n break;\n\n case 'llm-first-token':\n // Track time to first token\n if (currentLlmCall && chunk.llmFirstTokenTime) {\n currentLlmCall.firstTokenTime = chunk.llmFirstTokenTime;\n if (currentLlmCall.startTime && !options?.quiet) {\n const latency = chunk.llmFirstTokenTime - currentLlmCall.startTime;\n logger.llmFirstToken(currentLlmCall.model, latency);\n }\n }\n break;\n\n case 'tool-call':\n // Finalize any pending text part before tool call\n await finalizeTextPart();\n\n // Check for doom loop (repeated identical tool calls)\n if (options?.doomLoopDetector) {\n // This will throw DoomLoopError if threshold exceeded\n options.doomLoopDetector.check(chunk.toolName!, chunk.toolInput);\n }\n\n parts.push({\n type: 'tool-call',\n tool: chunk.toolName!,\n args: chunk.toolInput,\n timestamp: Date.now()\n });\n if (!options?.quiet) {\n logger.tool(chunk.toolName!, chunk.toolInput, undefined, chunk.isSubAgent);\n }\n if (options?.collectToolCalls) {\n toolCalls.push({ tool: chunk.toolName!, args: chunk.toolInput });\n }\n // Store info for this tool call using toolCallId as key\n if (chunk.toolCallId && chunk.toolName && chunk.toolStartTime) {\n pendingToolCalls.set(chunk.toolCallId, {\n name: chunk.toolName,\n startTime: chunk.toolStartTime,\n input: chunk.toolInput // Store input for later use in completed state\n });\n }\n\n // Log to session and track partID for later update\n if (options?.sessionManager && options?.sessionID && options?.messageID && options?.agentName && chunk.toolCallId) {\n const addPromise = options.sessionManager.addPart(options.sessionID, options.agentName, options.messageID, {\n type: 'tool',\n callID: chunk.toolCallId,\n tool: chunk.toolName!,\n state: {\n status: 'running',\n input: chunk.toolInput,\n time: { start: chunk.toolStartTime || Date.now() }\n }\n } as any).then(partID => {\n // Track partID so we can update it when result comes in\n const pending = pendingToolCalls.get(chunk.toolCallId!);\n if (pending) {\n pendingToolCalls.set(chunk.toolCallId!, { ...pending, partID });\n }\n }).catch(err => logger.debug(`Failed to log tool-call part: ${err.message}`));\n trackSessionUpdate(addPromise);\n }\n break;\n\n case 'tool-result':\n // Use the new toolResult method with timing and metadata\n const toolDuration = chunk.toolDuration;\n let tokens: number | undefined;\n let isSubAgent = false;\n\n // Extract metadata and success status before logging\n let toolSuccess = true;\n let rawResult: Record<string, unknown> | null = null;\n let toolMetadata: Record<string, unknown> | null = null;\n\n // Try to get rawResult as object - handles multiple nesting levels\n // toolResultRaw can be:\n // 1. A string with JSON: '{\"success\":false,...}'\n // 2. An object with error: {error: \"message\"}\n // 3. An object with output containing JSON: {output: '{\"success\":false,...}'}\n // 4. An object with output string and metadata: {output: \"...\", metadata: {exitCode: 1}}\n if (chunk.toolResultRaw) {\n const raw = chunk.toolResultRaw;\n\n // First, extract metadata if present (for case 4)\n const rawObj = raw as Record<string, unknown>;\n if (typeof raw === 'object' && raw !== null && 'metadata' in raw && typeof rawObj.metadata === 'object') {\n toolMetadata = rawObj.metadata as Record<string, unknown>;\n }\n\n let toCheck: unknown = raw;\n\n // If it's an object with .output string, use that for parsing\n if (typeof toCheck === 'object' && toCheck !== null && 'output' in toCheck && typeof (toCheck as Record<string, unknown>).output === 'string') {\n toCheck = (toCheck as Record<string, unknown>).output;\n }\n\n // Now parse if it's a string\n if (typeof toCheck === 'string') {\n try {\n const parsed = JSON.parse(toCheck);\n if (typeof parsed === 'object' && parsed !== null) {\n rawResult = parsed;\n }\n } catch {\n // Not valid JSON, ignore\n }\n } else if (typeof toCheck === 'object' && toCheck !== null) {\n rawResult = toCheck as Record<string, unknown>;\n }\n }\n\n // Check for failure conditions\n if (rawResult) {\n // Check if tool explicitly returned success: false or has an error field\n if (rawResult.success === false || rawResult.error !== undefined) {\n toolSuccess = false;\n }\n if (rawResult.metadata && typeof rawResult.metadata === 'object') {\n const metadata = rawResult.metadata as Record<string, unknown>;\n if (typeof metadata.tokensUsed === 'number') {\n tokens = metadata.tokensUsed;\n }\n if (metadata.agent) {\n isSubAgent = true;\n }\n }\n }\n\n // Check metadata for non-zero exit code (bash tool returns this)\n if (toolMetadata) {\n if (typeof toolMetadata.exitCode === 'number' && toolMetadata.exitCode !== 0) {\n toolSuccess = false;\n }\n if (typeof toolMetadata.tokensUsed === 'number') {\n tokens = toolMetadata.tokensUsed;\n }\n if (toolMetadata.agent) {\n isSubAgent = true;\n }\n }\n\n parts.push({\n type: 'tool-result',\n tool: chunk.toolName!,\n output: chunk.toolResult || 'No result',\n duration: toolDuration || 0,\n success: toolSuccess,\n timestamp: Date.now()\n });\n\n // Log the result with timing info\n // For skill tools, show a simple message instead of the full content\n if (!options?.quiet) {\n if (chunk.toolName === 'tools__skill_load') {\n logger.toolResult('Skill loaded', {\n ...(toolDuration !== undefined && { duration: toolDuration }),\n success: toolSuccess\n });\n } else if (chunk.toolName === 'tools__skill_read') {\n logger.toolResult('File read', {\n ...(toolDuration !== undefined && { duration: toolDuration }),\n success: toolSuccess\n });\n } else {\n logger.toolResult(chunk.toolResult || 'No result', {\n ...(toolDuration !== undefined && { duration: toolDuration }),\n success: toolSuccess,\n ...(tokens && { tokens })\n });\n }\n }\n\n // Find and complete the tool call trace using toolCallId\n if (chunk.toolCallId && chunk.toolDuration !== undefined) {\n const pending = pendingToolCalls.get(chunk.toolCallId);\n if (pending) {\n // Add tokens to subagent total if applicable\n if (tokens) {\n subAgentTokens += tokens;\n }\n\n toolCallTraces.push({\n name: pending.name,\n type: isSubAgent ? 'subagent' : 'tool',\n startTime: pending.startTime,\n duration: chunk.toolDuration,\n ...(tokens && { tokens }),\n success: toolSuccess,\n input: redactObjectDeep(pending.input),\n output: redactForTrace(chunk.toolResultRaw ?? chunk.toolResult ?? ''),\n });\n\n // Update the session storage part with completed state\n if (pending.partID && options?.sessionManager && options?.sessionID && options?.messageID && options?.agentName) {\n // Build completed state with required fields\n const completedState: ToolStateCompleted = {\n status: 'completed',\n input: pending.input || {}, // Use stored input from tool-call\n output: chunk.toolResultRaw || chunk.toolResult,\n time: {\n start: pending.startTime,\n end: Date.now()\n },\n ...(tokens && { metadata: { tokens } })\n };\n\n const updatePromise = options.sessionManager.updatePart(options.sessionID, options.agentName, options.messageID, pending.partID, {\n state: completedState\n }).catch(err => logger.debug(`Failed to update tool part: ${err.message}`));\n trackSessionUpdate(updatePromise);\n }\n\n pendingToolCalls.delete(chunk.toolCallId);\n }\n }\n break;\n\n case 'tool-error':\n // Tool errors are now passed as tool-result in executeAgentCore\n // This case shouldn't occur but keep for safety\n const prefix = options?.logPrefix || '';\n const errorStr = typeof chunk.error === 'string'\n ? chunk.error\n : ((chunk.error as any)?.message || 'Unknown error');\n logger.warnWithTool(chunk.toolName || 'unknown', 'call', errorStr);\n if (prefix) logger.warn(prefix.trim()); // Show any prefix separately\n break;\n\n case 'finish':\n // Finalize any pending text part\n await finalizeTextPart();\n\n // Only update usage on final finish (not intermediate segments)\n if (chunk.usage) {\n usage = chunk.usage;\n }\n\n finishReasons.push(chunk.finishReason ?? 'unknown');\n\n // Complete the LLM call trace for this segment\n if (currentLlmCall && currentLlmCall.startTime) {\n const duration = Date.now() - currentLlmCall.startTime;\n const segmentName = llmSegmentCount > 1 ?\n `${currentLlmCall.model}_segment_${llmSegmentCount}` :\n currentLlmCall.model;\n\n const llmTrace: ToolCallTrace = {\n name: segmentName,\n type: 'llm',\n startTime: currentLlmCall.startTime,\n duration,\n // Only add tokens for final segment with usage data\n ...(chunk.usage && chunk.usage.totalTokens && {\n tokens: chunk.usage.totalTokens\n })\n };\n toolCallTraces.push(llmTrace);\n currentLlmCall = null;\n }\n\n if (finalText.trim() && !options?.quiet) {\n logger.responseComplete();\n }\n break;\n\n case 'error':\n // Finalize any pending text part before throwing error\n await finalizeTextPart();\n throw chunk.error;\n }\n }\n } catch (error) {\n streamError = error;\n throw error;\n } finally {\n // Finalize any pending text part before returning (safety fallback)\n await finalizeTextPart();\n\n // Ensure tools that never returned are marked as errored\n await finalizePendingToolCalls(streamError);\n\n // Wait for all pending session updates to complete before returning\n // This ensures tool states are persisted (e.g., \"running\" -> \"completed\")\n if (pendingSessionUpdates.size > 0) {\n await Promise.allSettled(pendingSessionUpdates);\n }\n }\n\n return {\n text: finalText,\n ...(usage && { usage }),\n ...(options?.collectToolCalls && { toolCalls }),\n ...(subAgentTokens > 0 && { subAgentTokens }),\n ...(toolCallTraces.length > 0 && { toolCallTraces }),\n ...(finishReasons.length > 0 && { finishReasons, finishReason: finishReasons[finishReasons.length - 1] }),\n hasTextOutput,\n parts\n };\n}\n\r\n\r\n",
|
|
58
|
+
"import type { ParsedAgent } from '../parser';\nimport type { MCPConnection } from '../mcp';\nimport type { SessionManager } from '../session';\nimport { logger } from '../utils/logger';\nimport { executeAgentCore } from './execution';\nimport { prepareAgentExecution } from './preparation';\nimport type { AgentChunk, PreparedAgentExecution } from './types';\n\nexport interface RunAgentStreamOptions {\n abortSignal?: AbortSignal;\n startTime?: number;\n verbose?: boolean;\n agentFilePath?: string;\n cliMaxSteps?: number;\n sessionManager?: SessionManager;\n projectContext?: { projectRoot: string; cwd: string };\n userPrompt?: string;\n preparedExecution?: PreparedAgentExecution;\n}\n\n/**\n * Stream agent execution events as AgentChunk items.\n *\n * This is a harness-friendly API for UIs and servers that want tool-call/result\n * events and text deltas instead of just the final text.\n */\nexport async function* runAgentStream(\n agent: ParsedAgent,\n mcpClients: MCPConnection[],\n options: RunAgentStreamOptions = {}\n): AsyncGenerator<AgentChunk> {\n const preparation = options.preparedExecution ?? await prepareAgentExecution({\n agent,\n mcpClients,\n agentFilePath: options.agentFilePath,\n cliMaxSteps: options.cliMaxSteps,\n sessionManager: options.sessionManager,\n projectContext: options.projectContext,\n userPrompt: options.userPrompt,\n abortSignal: options.abortSignal,\n verbose: options.verbose\n });\n\n const {\n tools,\n systemMessages,\n userMessage,\n maxSteps,\n subAgentNames,\n sessionID,\n hookRunner,\n runId\n } = preparation;\n\n const effectiveRunId = runId || sessionID || String(Date.now());\n if (hookRunner?.enabled) {\n await hookRunner.run('run:start', {\n runId: effectiveRunId,\n agent: {\n name: agent.name,\n model: agent.config.model,\n ...(options.agentFilePath && { filePath: options.agentFilePath }),\n isSubAgent: false,\n },\n project: {\n projectRoot: options.projectContext?.projectRoot ?? process.cwd(),\n cwd: process.cwd(),\n },\n } as any);\n }\n\n try {\n yield* executeAgentCore(agent, tools, {\n userMessage,\n systemMessages,\n maxSteps,\n ...(options.abortSignal && { abortSignal: options.abortSignal }),\n ...(subAgentNames && { subAgentNames }),\n });\n } catch (err) {\n yield { type: 'error', error: err };\n throw err;\n } finally {\n if (hookRunner?.enabled) {\n try {\n await hookRunner.run('run:end', {\n runId: effectiveRunId,\n agent: {\n name: agent.name,\n model: agent.config.model,\n ...(options.agentFilePath && { filePath: options.agentFilePath }),\n isSubAgent: false,\n },\n project: {\n projectRoot: options.projectContext?.projectRoot ?? process.cwd(),\n cwd: process.cwd(),\n },\n } as any);\n } catch (hookErr: any) {\n logger.debug(`run:end hook failed: ${hookErr?.message ?? String(hookErr)}`);\n }\n }\n\n // Clean up MCP clients (mirrors runAgent)\n for (const connection of mcpClients) {\n try {\n await connection.client.close();\n if (connection.rawClient) {\n await connection.rawClient.close();\n }\n } catch {\n // ignore\n }\n }\n }\n}\n\n",
|
|
59
|
+
"export { buildAutonomousAgentPrompt, buildSystemMessages } from './runner/prompt';\nexport { prepareAgentExecution } from './runner/preparation';\nexport { processAgentStream } from './runner/stream';\nexport { executeAgentCore } from './runner/execution';\nexport { runAgent } from './runner/run';\nexport { runAgentStream } from './runner/run-stream';\nexport type { PrepareAgentOptions, PreparedAgentExecution, AgentChunk, RunAgentResult } from './runner/types';\n",
|
|
60
|
+
"import { ulid } from 'ulid';\nimport { writeJSON, readJSON, sanitizeAgentName } from '../storage';\nimport type {\n SessionInfo,\n Part,\n Message,\n DeepPartial\n} from './types';\n\nexport class SessionManager {\n private sessionID: string | null = null;\n private agentName: string | null = null;\n private parentPath: string | null = null; // For subagents: \"{mainSessionID}-{mainAgentName}/subagent\"\n private fullPath: string | null = null; // Full path to this session's directory\n\n /**\n * Build full session directory path\n */\n private buildSessionPath(sessionID: string, agentName: string): string {\n const sanitizedAgentName = sanitizeAgentName(agentName);\n const sessionDir = `${sessionID}-${sanitizedAgentName}`;\n\n if (this.parentPath) {\n return `${this.parentPath}/${sessionDir}`;\n }\n return sessionDir;\n }\n\n /**\n * Create a new session\n */\n async createSession(info: Omit<SessionInfo, 'id' | 'time'>): Promise<string> {\n const id = ulid();\n const now = Date.now();\n\n const session: SessionInfo = {\n ...info,\n id,\n time: {\n created: now,\n updated: now\n }\n };\n\n const sessionPath = this.buildSessionPath(id, info.agent.name);\n await writeJSON(`${sessionPath}/session`, session);\n\n this.sessionID = id;\n this.agentName = sanitizeAgentName(info.agent.name);\n this.fullPath = sessionPath;\n\n return id;\n }\n\n /**\n * Create a message exchange (user + assistant in one)\n */\n async createMessage(\n sessionID: string,\n agentName: string,\n data: {\n user: {\n prompt: {\n task: string;\n user?: string;\n };\n };\n assistant: {\n system: string[];\n modelID: string;\n providerID: string;\n mode: string;\n path: { cwd: string; root: string };\n cost: number;\n tokens: {\n input: number;\n output: number;\n reasoning: number;\n cache: { read: number; write: number };\n };\n };\n }\n ): Promise<string> {\n const id = ulid();\n\n const message: Message = {\n id,\n sessionID,\n time: { created: Date.now() },\n ...data\n };\n\n const sessionPath = this.buildSessionPath(sessionID, agentName);\n // New path structure: {messageID}/message.json\n await writeJSON(`${sessionPath}/${id}/message`, message);\n return id;\n }\n\n /**\n * Add a part to a message\n * Accepts part data without base fields (id, sessionID, messageID) and adds them\n */\n async addPart(\n sessionID: string,\n agentName: string,\n messageID: string,\n partData: Omit<Part, 'id' | 'sessionID' | 'messageID'>\n ): Promise<string> {\n const id = ulid();\n const sessionPath = this.buildSessionPath(sessionID, agentName);\n\n // Add base fields to create complete Part\n const completePart: Part = {\n ...partData,\n id,\n sessionID,\n messageID,\n } as Part; // Type assertion needed due to discriminated union complexity\n\n // New path structure: {messageID}/part/{partID}.json\n await writeJSON(`${sessionPath}/${messageID}/part/${id}`, completePart);\n return id;\n }\n\n /**\n * Update an existing part\n */\n async updatePart(sessionID: string, agentName: string, messageID: string, partID: string, updates: Partial<Part>): Promise<void> {\n const sessionPath = this.buildSessionPath(sessionID, agentName);\n // New path structure: {messageID}/part/{partID}.json\n const key = `${sessionPath}/${messageID}/part/${partID}`;\n\n const existing = await readJSON<Part>(key);\n if (existing) {\n const updated = { ...existing, ...updates };\n await writeJSON(key, updated);\n }\n }\n\n /**\n * Update session info\n */\n async updateSession(sessionID: string, agentName: string, updates: Partial<Omit<SessionInfo, 'id'>>): Promise<void> {\n const sessionPath = this.buildSessionPath(sessionID, agentName);\n const key = `${sessionPath}/session`;\n\n const session = await readJSON<SessionInfo>(key);\n if (session) {\n Object.assign(session, updates);\n session.time.updated = Date.now();\n await writeJSON(key, session);\n }\n }\n\n /**\n * Update message (typically for updating assistant response data)\n */\n async updateMessage(\n sessionID: string,\n agentName: string,\n messageID: string,\n updates: DeepPartial<Omit<Message, 'id' | 'sessionID'>>\n ): Promise<void> {\n const sessionPath = this.buildSessionPath(sessionID, agentName);\n // New path structure: {messageID}/message.json\n const key = `${sessionPath}/${messageID}/message`;\n\n const message = await readJSON<Message>(key);\n if (message) {\n // Deep merge for nested objects (time, assistant, user)\n if (updates.time) {\n message.time = { ...message.time, ...updates.time } as Message['time'];\n }\n if (updates.assistant) {\n const assistantUpdates = updates.assistant;\n // Deep merge tokens if provided\n if (assistantUpdates.tokens) {\n message.assistant.tokens = { ...message.assistant.tokens, ...assistantUpdates.tokens } as Message['assistant']['tokens'];\n }\n // Merge other assistant fields (excluding tokens which we handled above)\n const { tokens: _, ...otherAssistantUpdates } = assistantUpdates;\n message.assistant = { ...message.assistant, ...otherAssistantUpdates } as Message['assistant'];\n }\n if (updates.user) {\n message.user = { ...message.user, ...updates.user } as Message['user'];\n }\n await writeJSON(key, message);\n }\n }\n\n /**\n * Get current session ID\n */\n getCurrentSessionID(): string | null {\n return this.sessionID;\n }\n\n /**\n * Get current agent name\n */\n getCurrentAgentName(): string | null {\n return this.agentName;\n }\n\n /**\n * Get session info\n */\n async getSession(sessionID: string, agentName: string): Promise<SessionInfo | null> {\n const sessionPath = this.buildSessionPath(sessionID, agentName);\n return readJSON<SessionInfo>(`${sessionPath}/session`);\n }\n\n /**\n * Get message\n */\n async getMessage(sessionID: string, agentName: string, messageID: string): Promise<Message | null> {\n const sessionPath = this.buildSessionPath(sessionID, agentName);\n // New path structure: {messageID}/message.json\n return readJSON<Message>(`${sessionPath}/${messageID}/message`);\n }\n\n /**\n * Get part\n */\n async getPart(sessionID: string, agentName: string, messageID: string, partID: string): Promise<Part | null> {\n const sessionPath = this.buildSessionPath(sessionID, agentName);\n // New path structure: {messageID}/part/{partID}.json\n return readJSON<Part>(`${sessionPath}/${messageID}/part/${partID}`);\n }\n\n /**\n * Set parent path for subagent sessions\n * @param parentFullPath The full path of the parent session\n */\n setParentPath(parentFullPath: string): void {\n this.parentPath = `${parentFullPath}/subagent`;\n }\n\n /**\n * Set error on session (for failures before LLM calls - auth, MCP, etc.)\n */\n async setSessionError(\n sessionID: string,\n agentName: string,\n error: { message: string; code: string }\n ): Promise<void> {\n await this.updateSession(sessionID, agentName, {\n error: {\n ...error,\n time: Date.now()\n }\n });\n }\n\n /**\n * Get the full path to this session's directory\n */\n getFullPath(): string | null {\n return this.fullPath;\n }\n}\n",
|
|
61
|
+
"import { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\n\nexport type AgentsGuidanceSource = { label: string; path: string };\n\nexport type AgentsGuidanceOptions = {\n projectRoot: string;\n homeDir: string;\n // Allow disabling injection without changing agent files.\n enabled?: boolean;\n maxChars?: number;\n};\n\nfunction truncate(text: string, maxChars: number): { text: string; truncated: boolean } {\n if (maxChars <= 0) return { text: '', truncated: text.length > 0 };\n if (text.length <= maxChars) return { text, truncated: false };\n return { text: text.slice(0, maxChars) + '\\n\\n[TRUNCATED]', truncated: true };\n}\n\nfunction safeReadText(path: string): string | null {\n try {\n if (!existsSync(path)) return null;\n return readFileSync(path, 'utf8');\n } catch {\n return null;\n }\n}\n\nexport function loadAgentsGuidance(opts: AgentsGuidanceOptions): {\n content: string | null;\n sources: AgentsGuidanceSource[];\n} {\n const enabled = opts.enabled !== false;\n if (!enabled) return { content: null, sources: [] };\n\n const maxChars = opts.maxChars ?? 40_000;\n\n const candidates: AgentsGuidanceSource[] = [\n { label: 'project', path: join(opts.projectRoot, 'AGENTS.md') },\n { label: 'project-dotdir', path: join(opts.projectRoot, '.pk-agent', 'AGENTS.md') },\n { label: 'user', path: join(opts.homeDir, '.pk-agent', 'AGENTS.md') },\n ];\n\n const blocks: string[] = [];\n const sources: AgentsGuidanceSource[] = [];\n\n for (const c of candidates) {\n const raw = safeReadText(c.path);\n if (!raw) continue;\n\n const { text, truncated } = truncate(raw.trim(), maxChars);\n if (!text) continue;\n\n sources.push(c);\n blocks.push(\n [\n `Source: ${c.label}`,\n `Path: ${c.path}`,\n truncated ? 'Note: content truncated' : '',\n '',\n text,\n ]\n .filter((s) => s !== '')\n .join('\\n')\n );\n }\n\n if (blocks.length === 0) return { content: null, sources: [] };\n\n const content = [\n 'Additional environment guidance (AGENTS.md):',\n 'These are instructions about the repo/tooling environment. Follow them as hard constraints.',\n '',\n blocks.join('\\n\\n' + '-'.repeat(60) + '\\n\\n'),\n ].join('\\n');\n\n return { content, sources };\n}\n\n",
|
|
62
|
+
"import { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { logger } from '../utils/logger';\nimport { redactForTrace, redactObjectDeep } from '../utils/redaction';\nimport type { HookCommand, HookContext, HookEvent, HookRunner, HooksConfig } from './types';\nimport { spawn } from 'child_process';\nimport { ensurePkAgentDirs } from '../utils/pk-agent-dirs';\n\nfunction safeReadJson(path: string): any | null {\n try {\n if (!existsSync(path)) return null;\n const text = readFileSync(path, 'utf8');\n return JSON.parse(text);\n } catch {\n return null;\n }\n}\n\nfunction normalizeConfig(raw: any): HooksConfig {\n if (!raw || typeof raw !== 'object') return {};\n const enabled = raw.enabled === undefined ? undefined : Boolean(raw.enabled);\n const timeoutMs =\n raw.timeoutMs === undefined ? undefined : (Number.isFinite(Number(raw.timeoutMs)) ? Number(raw.timeoutMs) : undefined);\n const events = raw.events && typeof raw.events === 'object' ? raw.events : undefined;\n const out: HooksConfig = {};\n if (enabled !== undefined) out.enabled = enabled;\n if (timeoutMs !== undefined) out.timeoutMs = timeoutMs;\n if (events !== undefined) out.events = events;\n return out;\n}\n\nfunction mergeConfigs(globalCfg: HooksConfig, projectCfg: HooksConfig): HooksConfig {\n // Project config overrides global enabled/timeout; event commands concatenate (global then project).\n const enabled = projectCfg.enabled !== undefined ? projectCfg.enabled : globalCfg.enabled;\n const timeoutMs = projectCfg.timeoutMs !== undefined ? projectCfg.timeoutMs : globalCfg.timeoutMs;\n\n const events: Partial<Record<HookEvent, HookCommand[]>> = {};\n const allEvents: HookEvent[] = ['run:start', 'run:end', 'tool:start', 'tool:end'];\n for (const ev of allEvents) {\n const g = globalCfg.events?.[ev] ?? [];\n const p = projectCfg.events?.[ev] ?? [];\n const merged = [...g, ...p].filter(Boolean) as HookCommand[];\n if (merged.length) {\n (events as any)[ev] = merged;\n }\n }\n\n const out: HooksConfig = {};\n if (enabled !== undefined) out.enabled = enabled;\n if (timeoutMs !== undefined) out.timeoutMs = timeoutMs;\n if (Object.keys(events).length > 0) out.events = events;\n return out;\n}\n\nfunction shouldRunCommand(cmd: HookCommand, ctx: HookContext): boolean {\n if (!cmd.toolNamePrefix) return true;\n if (!ctx.tool?.name) return false;\n return ctx.tool.name.startsWith(cmd.toolNamePrefix);\n}\n\nasync function runOneCommand(cmd: HookCommand, ctx: HookContext, defaultTimeoutMs: number): Promise<void> {\n const timeoutMs = cmd.timeoutMs ?? defaultTimeoutMs;\n\n const payload: HookContext = {\n ...ctx,\n // Ensure we never pass unredacted tool content.\n ...(ctx.tool ? {\n tool: {\n ...ctx.tool,\n input: redactObjectDeep(ctx.tool.input),\n output: redactForTrace(ctx.tool.output ?? ''),\n }\n } : {}),\n };\n\n const json = JSON.stringify(payload);\n\n await new Promise<void>((resolve, reject) => {\n let settled = false;\n\n const child = spawn(cmd.cmd, cmd.args ?? [], {\n shell: cmd.shell === true,\n windowsHide: true,\n stdio: ['pipe', 'pipe', 'pipe'],\n env: {\n ...process.env,\n PK_AGENT_HOOK_EVENT: payload.event,\n PK_AGENT_RUN_ID: payload.runId,\n PK_AGENT_AGENT_NAME: payload.agent.name,\n PK_AGENT_AGENT_MODEL: payload.agent.model,\n PK_AGENT_PROJECT_ROOT: payload.project.projectRoot,\n },\n });\n\n const kill = () => {\n try {\n child.kill();\n } catch {\n // ignore\n }\n };\n\n const timer = setTimeout(() => {\n if (settled) return;\n kill();\n settled = true;\n reject(new Error(`Hook timed out after ${timeoutMs}ms: ${cmd.cmd}`));\n }, timeoutMs);\n\n let stderr = '';\n child.stderr?.on('data', (d: Buffer) => {\n if (stderr.length < 16_384) stderr += d.toString();\n });\n\n child.on('error', (err) => {\n clearTimeout(timer);\n if (settled) return;\n settled = true;\n reject(err);\n });\n\n child.on('close', (code) => {\n clearTimeout(timer);\n if (settled) return;\n settled = true;\n if (code && code !== 0) {\n const msg = (stderr || '').trim();\n reject(new Error(`Hook failed (exit ${code}): ${cmd.cmd}${msg ? `\\n${msg}` : ''}`));\n } else {\n resolve();\n }\n });\n\n try {\n child.stdin?.write(json);\n child.stdin?.end();\n } catch {\n // ignore stdin failures\n }\n });\n}\n\nexport function createHookRunner(projectRoot: string, opts?: { homeDir?: string }): HookRunner {\n const home = opts?.homeDir ?? homedir();\n const globalPath = join(home, '.pk-agent', 'hooks.json');\n const projectPath = join(projectRoot, '.pk-agent', 'hooks.json');\n\n try {\n ensurePkAgentDirs(projectRoot, { homeDir: home });\n } catch {\n // best-effort\n }\n\n const globalCfg = normalizeConfig(safeReadJson(globalPath));\n const projectCfg = normalizeConfig(safeReadJson(projectPath));\n const cfg = mergeConfigs(globalCfg, projectCfg);\n\n const enabled = cfg.enabled !== false && Boolean(cfg.events && Object.keys(cfg.events).length > 0);\n const defaultTimeoutMs = cfg.timeoutMs ?? 30_000;\n\n if (enabled) {\n logger.debug(`Hooks enabled (global: ${existsSync(globalPath) ? globalPath : 'none'}, project: ${existsSync(projectPath) ? projectPath : 'none'})`);\n }\n\n return {\n enabled,\n run: async (event, ctx) => {\n if (!enabled) return;\n\n const now = new Date().toISOString();\n const fullCtx: HookContext = {\n ...ctx,\n event,\n timestampUtc: now,\n } as any;\n\n const commands = cfg.events?.[event] ?? [];\n for (const command of commands) {\n if (!shouldRunCommand(command, fullCtx)) continue;\n try {\n await runOneCommand(command, fullCtx, defaultTimeoutMs);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (command.failOnError) {\n throw err;\n }\n logger.warn(`Hook error (${event}): ${msg}`);\n }\n }\n },\n };\n}\n",
|
|
63
|
+
"import { basename, isAbsolute, resolve } from 'path';\nimport { readFile } from 'fs/promises';\n\nexport type OpenAIFileAttachmentPart = {\n type: 'file';\n mediaType: 'application/pdf';\n data: string | URL | Uint8Array;\n filename?: string;\n};\n\nexport function isHttpUrl(value: string): boolean {\n return /^https?:\\/\\//i.test(value);\n}\n\nexport function isOpenAIFileId(value: string): boolean {\n // OpenAI Files API ids are like \"file-...\" (and sometimes \"file_...\").\n return /^file[-_]/i.test(value);\n}\n\n/**\n * Resolve file attachments into OpenAI \"file\" parts.\n *\n * Supports:\n * - OpenAI file ids (passthrough)\n * - Public HTTP(S) URLs (passthrough as URL)\n * - Local PDF paths (read into bytes)\n */\nexport async function resolveFileAttachments(\n files: unknown[],\n baseDir: string | undefined,\n provider: string\n): Promise<OpenAIFileAttachmentPart[]> {\n if (provider !== 'openai') {\n throw new Error('files are only supported when using an OpenAI model');\n }\n\n return await Promise.all(files.map(async (ref, index) => {\n const value = String(ref).trim();\n if (!value) {\n throw new Error('files contains an empty entry');\n }\n\n // OpenAI file id passthrough (Files API).\n if (isOpenAIFileId(value)) {\n return { type: 'file', mediaType: 'application/pdf', data: value };\n }\n\n // URL passthrough (Responses API will fetch it). Only supports public HTTPS URLs.\n if (isHttpUrl(value)) {\n return { type: 'file', mediaType: 'application/pdf', data: new URL(value) };\n }\n\n // Local path (resolved relative to the agent file). Require baseDir to avoid\n // surprising behavior for remote agents or callers without a base directory.\n if (!baseDir) {\n throw new Error(`Local file attachments require a local agent file path. Use an http(s) URL or OpenAI file id instead (got: ${value})`);\n }\n\n const absPath = isAbsolute(value) ? value : resolve(baseDir, value);\n if (!absPath.toLowerCase().endsWith('.pdf')) {\n throw new Error(`Only PDF files are supported for files (got: ${value})`);\n }\n\n const data = await readFile(absPath);\n return {\n type: 'file',\n mediaType: 'application/pdf',\n data,\n filename: basename(absPath) ?? `part-${index}.pdf`,\n };\n }));\n}\n",
|
|
64
|
+
"import { resolveSafeVariables, type PathResolverContext } from '../tools/index.js';\n\nexport type PromptVariablesContext = PathResolverContext;\n\n/**\n * Resolve safe prompt variables.\n *\n * Supported:\n * - ${root}\n * - ${agentDir}\n * - ${tmpDir}\n *\n * Intentionally NOT supported:\n * - ${env:VAR} (prevents secret exposure)\n */\nexport function resolvePromptVariables(text: string, context: PromptVariablesContext): string {\n return resolveSafeVariables(text, context);\n}\n\n",
|
|
65
|
+
"import { glob } from 'glob';\r\nimport { homedir } from 'os';\r\nimport { join, resolve, basename } from 'path';\r\nimport { access, readFile } from 'fs/promises';\r\nimport { parseAgentContent, parseAgent } from './parser.js';\r\nimport { discoverSkills } from './skill/discovery.js';\r\nimport { parseSkillContent } from './skill/parser.js';\r\nimport { isURL, fetchRemoteAgent, getRemoteAgentName } from './utils/remote-agent.js';\nimport { logger } from './utils/logger.js';\nimport { ensurePkAgentDirs } from './utils/pk-agent-dirs.js';\n\r\n// --- Constants ---\r\n\r\n/** Triple-bracket skill references - must match FIRST to avoid double-bracket partial match */\r\nconst SKILL_REF_REGEX = /\\[\\[\\[([^\\[\\]]+)\\]\\]\\]/g;\r\n\r\n/** Double-bracket agent references - match SECOND */\r\nconst AGENT_REF_REGEX = /\\[\\[([^\\[\\]]+)\\]\\]/g;\r\n\r\n/** Default maximum nesting depth for recursive reference resolution */\r\nconst DEFAULT_MAX_DEPTH = 10;\r\n\r\n// --- Types ---\r\n\r\nexport interface ResolveOptions {\r\n /** Directory of the current agent file (for relative path resolution and sibling discovery) */\r\n agentDir?: string | undefined;\r\n /** Project root for discovery directories */\r\n projectRoot?: string | undefined;\r\n /** Names already declared in YAML subagents (to avoid double-registration) */\r\n existingSubagents?: string[] | undefined;\r\n}\r\n\r\nexport interface ResolveResult {\r\n /** Fully resolved instructions text with all references expanded */\r\n text: string;\r\n /** Agents found via [[]] that should be auto-registered as subagent tools */\r\n discoveredAgents: Array<{\r\n name: string;\r\n path: string;\r\n }>;\r\n}\r\n\r\n// --- Agent Discovery ---\r\n\r\n/**\r\n * Get agent discovery directories in priority order.\r\n * Higher-priority directories shadow lower ones for duplicate agent names.\r\n */\r\nfunction getAgentDiscoveryDirectories(projectRoot: string, agentDir?: string): string[] {\r\n const home = homedir();\r\n const dirs: string[] = [];\r\n\r\n // 1. Current agent's directory (siblings)\r\n if (agentDir) {\r\n dirs.push(agentDir);\r\n }\r\n\r\n // 2. Project .pk-agent/agents/\r\n dirs.push(join(projectRoot, '.pk-agent', 'agents'));\r\n\r\n // 3. Project .agents/agents/ (ecosystem)\r\n dirs.push(join(projectRoot, '.agents', 'agents'));\r\n\r\n // 4. Project .claude/agents/ (Claude compat)\r\n dirs.push(join(projectRoot, '.claude', 'agents'));\r\n\r\n // 5. User ~/.pk-agent/agents/\r\n dirs.push(join(home, '.pk-agent', 'agents'));\r\n\r\n // 6. User ~/.claude/agents/ (Claude compat)\r\n dirs.push(join(home, '.claude', 'agents'));\r\n\r\n return dirs;\r\n}\r\n\r\n/**\r\n * Check if a directory exists\r\n */\r\nasync function directoryExists(dir: string): Promise<boolean> {\r\n try {\r\n await access(dir);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Discover all agents from convention-based directories.\r\n * Returns Map<name, absolutePath> where name is the filename without extension.\r\n * First match wins (higher-priority directories shadow lower ones).\r\n *\r\n * @param projectRoot Project root directory\r\n * @param agentDir Optional directory of the current agent file (for sibling discovery)\r\n */\r\nexport async function discoverAgents(\n projectRoot: string,\n agentDir?: string\n): Promise<Map<string, string>> {\n try {\n ensurePkAgentDirs(projectRoot);\n } catch {\n // best-effort\n }\n\n const agents = new Map<string, string>();\n const directories = getAgentDiscoveryDirectories(projectRoot, agentDir);\n\r\n // Track which dirs are ecosystem (accept .md files too)\r\n const ecosystemDirs = new Set([\r\n join(projectRoot, '.agents', 'agents'),\r\n join(projectRoot, '.claude', 'agents'),\r\n join(homedir(), '.claude', 'agents'),\r\n ]);\r\n\r\n for (const dir of directories) {\r\n if (!await directoryExists(dir)) continue;\r\n\r\n // Always look for .pk-agent files\r\n const pkAgentPattern = join(dir, '*.pk-agent').replace(/\\\\/g, '/');\r\n const pkAgentFiles = await glob(pkAgentPattern, { absolute: true });\r\n\r\n for (const filePath of pkAgentFiles) {\r\n const name = basename(filePath).replace(/\\.pk-agent$/, '');\r\n if (!agents.has(name)) {\r\n agents.set(name, filePath);\r\n }\r\n }\r\n\r\n // Also look for .md files in ecosystem directories (cross-tool compat)\r\n if (ecosystemDirs.has(dir)) {\r\n const mdPattern = join(dir, '*.md').replace(/\\\\/g, '/');\r\n const mdFiles = await glob(mdPattern, { absolute: true });\r\n\r\n for (const filePath of mdFiles) {\r\n const name = basename(filePath).replace(/\\.md$/, '');\r\n // .pk-agent format takes priority over .md\r\n if (!agents.has(name)) {\r\n agents.set(name, filePath);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return agents;\r\n}\r\n\r\n/**\r\n * Discover agents from a single directory only (used when no projectRoot is available).\r\n */\r\nasync function discoverAgentsFromDir(dir: string): Promise<Map<string, string>> {\r\n const agents = new Map<string, string>();\r\n if (!await directoryExists(dir)) return agents;\r\n\r\n const pkAgentPattern = join(dir, '*.pk-agent').replace(/\\\\/g, '/');\r\n const pkAgentFiles = await glob(pkAgentPattern, { absolute: true });\r\n\r\n for (const filePath of pkAgentFiles) {\r\n const name = basename(filePath).replace(/\\.pk-agent$/, '');\r\n if (!agents.has(name)) {\r\n agents.set(name, filePath);\r\n }\r\n }\r\n\r\n return agents;\r\n}\r\n\r\n// --- Reference Resolution ---\r\n\r\n/**\r\n * Resolve a single agent reference [[name]].\r\n *\r\n * @returns Object with resolved text and any discovered agents for auto-registration\r\n */\r\nasync function resolveAgentRef(\r\n name: string,\r\n agentMap: Map<string, string>,\r\n options: ResolveOptions,\r\n visited: Set<string>,\r\n depth: number,\r\n discoveredAgents: Map<string, string>,\r\n existingSubagents: Set<string>\r\n): Promise<string> {\r\n const maxDepth = parseInt(process.env.MAX_REFERENCE_DEPTH || '') || DEFAULT_MAX_DEPTH;\r\n\r\n // Depth limit\r\n if (depth >= maxDepth) {\r\n logger.warn(`Reference depth limit (${maxDepth}) exceeded for [[${name}]]. Leaving as-is.`);\r\n return `[[${name}]]`;\r\n }\r\n\r\n // 1. URL reference - fetch remote agent\r\n if (isURL(name)) {\r\n try {\r\n const content = await fetchRemoteAgent(name);\r\n const agentName = getRemoteAgentName(name);\r\n const agent = parseAgentContent(content, agentName);\r\n\r\n // Recursively resolve nested references\r\n const resolved = await resolveAllReferences(\r\n agent.instructions,\r\n agentMap,\r\n options,\r\n visited,\r\n depth + 1,\r\n discoveredAgents,\r\n existingSubagents\r\n );\r\n\r\n return `<!-- BEGIN [[${name}]] -->\\n${resolved}\\n<!-- END [[${name}]] -->`;\r\n } catch (error) {\r\n logger.warn(`Failed to fetch remote agent [[${name}]]: ${error instanceof Error ? error.message : String(error)}`);\r\n return `[[${name}]]`;\r\n }\r\n }\r\n\r\n // 2. Relative path reference (contains / or \\)\r\n let agentPath: string | undefined;\r\n\r\n if (name.includes('/') || name.includes('\\\\')) {\r\n if (options.agentDir) {\r\n const relPath = resolve(options.agentDir, name);\r\n // Try with .pk-agent extension if not already present\r\n if (!relPath.endsWith('.pk-agent') && !relPath.endsWith('.md')) {\r\n const withExt = relPath + '.pk-agent';\r\n try {\r\n await access(withExt);\r\n agentPath = withExt;\r\n } catch {\r\n // Try .md fallback\r\n try {\r\n await access(relPath + '.md');\r\n agentPath = relPath + '.md';\r\n } catch {\r\n // Try as-is\r\n try {\r\n await access(relPath);\r\n agentPath = relPath;\r\n } catch {\r\n logger.warn(`Agent reference [[${name}]] not found at relative path from ${options.agentDir}`);\r\n return `[[${name}]]`;\r\n }\r\n }\r\n }\r\n } else {\r\n try {\r\n await access(relPath);\r\n agentPath = relPath;\r\n } catch {\r\n logger.warn(`Agent reference [[${name}]] not found at relative path: ${relPath}`);\r\n return `[[${name}]]`;\r\n }\r\n }\r\n } else {\r\n logger.warn(`Agent reference [[${name}]] uses relative path but no agentDir is set`);\r\n return `[[${name}]]`;\r\n }\r\n } else {\r\n // 3. Name-based lookup in discovery map\r\n agentPath = agentMap.get(name);\r\n if (!agentPath) {\r\n logger.warn(`Agent reference [[${name}]] not found in any discovery directory`);\r\n return `[[${name}]]`;\r\n }\r\n }\r\n\r\n // Cycle detection\r\n const normalizedPath = resolve(agentPath);\r\n if (visited.has(normalizedPath)) {\r\n const chain = [...visited, normalizedPath].join(' -> ');\r\n throw new Error(`Circular reference detected: ${chain}`);\r\n }\r\n\r\n // Parse the agent file\r\n try {\r\n let agent;\r\n if (agentPath.endsWith('.pk-agent')) {\r\n agent = await parseAgent(agentPath);\r\n } else {\r\n // .md ecosystem agent - read raw content as instructions\r\n const content = await readFile(agentPath, 'utf-8');\r\n const agentName = basename(agentPath).replace(/\\.md$/, '');\r\n agent = { name: agentName, instructions: content.trim(), config: {} as any };\r\n }\r\n\r\n // Track for auto-registration (only if not already declared)\r\n const agentName = agent.name || basename(agentPath).replace(/\\.(pk-agent|md)$/, '');\r\n if (!existingSubagents.has(agentName) && !discoveredAgents.has(agentName)) {\r\n discoveredAgents.set(agentName, normalizedPath);\r\n }\r\n\r\n // Recursively resolve nested references\r\n const nextVisited = new Set(visited);\r\n nextVisited.add(normalizedPath);\r\n\r\n const resolved = await resolveAllReferences(\r\n agent.instructions,\r\n agentMap,\r\n options,\r\n nextVisited,\r\n depth + 1,\r\n discoveredAgents,\r\n existingSubagents\r\n );\r\n\r\n return `<!-- BEGIN [[${name}]] -->\\n${resolved}\\n<!-- END [[${name}]] -->`;\r\n } catch (error) {\r\n if (error instanceof Error && error.message.startsWith('Circular reference')) {\r\n throw error; // Re-throw cycle errors\r\n }\r\n logger.warn(`Failed to parse agent [[${name}]]: ${error instanceof Error ? error.message : String(error)}`);\r\n return `[[${name}]]`;\r\n }\r\n}\r\n\r\n/**\r\n * Resolve a single skill reference [[[name]]].\r\n *\r\n * @returns Resolved skill content wrapped in delimiters, or null if not found\r\n */\r\nasync function resolveSkillRef(\r\n name: string,\r\n options: ResolveOptions,\r\n agentMap: Map<string, string>,\r\n visited: Set<string>,\r\n depth: number,\r\n discoveredAgents: Map<string, string>,\r\n existingSubagents: Set<string>\r\n): Promise<string> {\r\n const maxDepth = parseInt(process.env.MAX_REFERENCE_DEPTH || '') || DEFAULT_MAX_DEPTH;\r\n\r\n if (depth >= maxDepth) {\r\n logger.warn(`Reference depth limit (${maxDepth}) exceeded for [[[${name}]]]. Leaving as-is.`);\r\n return `[[[${name}]]]`;\r\n }\r\n\r\n if (!options.projectRoot) {\r\n logger.warn(`Skill reference [[[${name}]]] requires projectRoot to resolve`);\r\n return `[[[${name}]]]`;\r\n }\r\n\r\n try {\r\n // Use existing skill discovery\r\n const skills = await discoverSkills(options.projectRoot);\r\n const skill = skills.get(name);\r\n\r\n if (!skill) {\r\n logger.warn(`Skill reference [[[${name}]]] not found in any discovery directory`);\r\n return `[[[${name}]]]`;\r\n }\r\n\r\n // Parse full skill content\r\n const skillContent = await parseSkillContent(skill.location);\r\n\r\n // Substitute ${skillDir} variable\r\n let content = skillContent.content.replace(/\\$\\{skillDir\\}/g, skillContent.directory);\r\n\r\n // Recursively resolve any nested references in the skill content\r\n content = await resolveAllReferences(\r\n content,\r\n agentMap,\r\n options,\r\n visited,\r\n depth + 1,\r\n discoveredAgents,\r\n existingSubagents\r\n );\r\n\r\n return `<!-- BEGIN [[[${name}]]] -->\\n${content}\\n<!-- END [[[${name}]]] -->`;\r\n } catch (error) {\r\n if (error instanceof Error && error.message.startsWith('Circular reference')) {\r\n throw error;\r\n }\r\n logger.warn(`Failed to load skill [[[${name}]]]: ${error instanceof Error ? error.message : String(error)}`);\r\n return `[[[${name}]]]`;\r\n }\r\n}\r\n\r\n/**\r\n * Internal: resolve all [[]] and [[[]]] references in text.\r\n * Processes triple-bracket FIRST to avoid partial matches with double-bracket.\r\n */\r\nasync function resolveAllReferences(\r\n text: string,\r\n agentMap: Map<string, string>,\r\n options: ResolveOptions,\r\n visited: Set<string>,\r\n depth: number,\r\n discoveredAgents: Map<string, string>,\r\n existingSubagents: Set<string>\r\n): Promise<string> {\r\n // Phase 1: Collect all triple-bracket [[[skill]]] matches\r\n const skillMatches: Array<{ full: string; name: string; index: number }> = [];\r\n let match: RegExpExecArray | null;\r\n\r\n const skillRegex = new RegExp(SKILL_REF_REGEX.source, 'g');\r\n while ((match = skillRegex.exec(text)) !== null) {\r\n const name = match[1].trim();\r\n if (name) {\r\n skillMatches.push({ full: match[0], name, index: match.index });\r\n }\r\n }\r\n\r\n // Phase 2: Collect all double-bracket [[agent]] matches\r\n // But skip any positions that were already matched as triple-bracket\r\n const agentMatches: Array<{ full: string; name: string; index: number }> = [];\r\n const skillRanges = skillMatches.map(m => ({\r\n start: m.index,\r\n end: m.index + m.full.length,\r\n }));\r\n\r\n const agentRegex = new RegExp(AGENT_REF_REGEX.source, 'g');\r\n while ((match = agentRegex.exec(text)) !== null) {\r\n const pos = match.index;\r\n // Skip if this match falls within a triple-bracket range\r\n const insideSkillRef = skillRanges.some(r => pos >= r.start && pos < r.end);\r\n if (insideSkillRef) continue;\r\n\r\n const name = match[1].trim();\r\n if (name) {\r\n agentMatches.push({ full: match[0], name, index: pos });\r\n }\r\n }\r\n\r\n // If nothing to resolve, return as-is\r\n if (skillMatches.length === 0 && agentMatches.length === 0) {\r\n return text;\r\n }\r\n\r\n // Phase 3: Resolve all matches (skills and agents)\r\n // Build a replacement map: original string -> resolved string\r\n // Process in reverse order of position to maintain correct indices during replacement\r\n const allMatches = [\r\n ...skillMatches.map(m => ({ ...m, type: 'skill' as const })),\r\n ...agentMatches.map(m => ({ ...m, type: 'agent' as const })),\r\n ].sort((a, b) => b.index - a.index); // Reverse sort for safe replacement\r\n\r\n let result = text;\r\n\r\n for (const m of allMatches) {\r\n let replacement: string;\r\n\r\n if (m.type === 'skill') {\r\n replacement = await resolveSkillRef(\r\n m.name, options, agentMap, visited, depth,\r\n discoveredAgents, existingSubagents\r\n );\r\n } else {\r\n replacement = await resolveAgentRef(\r\n m.name, agentMap, options, visited, depth,\r\n discoveredAgents, existingSubagents\r\n );\r\n }\r\n\r\n // Replace at exact position\r\n result = result.slice(0, m.index) + replacement + result.slice(m.index + m.full.length);\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// --- Public API ---\r\n\r\n/**\r\n * Resolve all wikilink references in agent instructions text.\r\n *\r\n * - `[[Agent-Name]]` - resolves to agent's instructions wrapped in delimiters,\r\n * and collects the agent for auto-registration as a subagent tool.\r\n * - `[[[skill-name]]]` - resolves to skill's SKILL.md content wrapped in delimiters.\r\n *\r\n * @param text Instructions text potentially containing references\r\n * @param options Resolution options (agentDir, projectRoot, existingSubagents)\r\n * @returns ResolveResult with resolved text and discovered agents\r\n */\r\nexport async function resolveReferences(\r\n text: string,\r\n options: ResolveOptions\r\n): Promise<ResolveResult> {\r\n // Quick check: if no brackets at all, skip all work\r\n if (!text.includes('[[')) {\r\n return { text, discoveredAgents: [] };\r\n }\r\n\r\n // Build agent discovery map\r\n // Even without projectRoot, agentDir alone enables sibling discovery\r\n const agentMap = options.projectRoot\r\n ? await discoverAgents(options.projectRoot, options.agentDir)\r\n : options.agentDir\r\n ? await discoverAgentsFromDir(options.agentDir)\r\n : new Map<string, string>();\r\n\r\n // Track discovered agents for auto-registration\r\n const discoveredAgents = new Map<string, string>();\r\n\r\n // Build set of existing subagent names for dedup\r\n const existingSubagents = new Set(options.existingSubagents ?? []);\r\n\r\n // Resolve all references\r\n const resolved = await resolveAllReferences(\r\n text,\r\n agentMap,\r\n options,\r\n new Set<string>(), // visited set (for cycle detection)\r\n 0, // initial depth\r\n discoveredAgents,\r\n existingSubagents\r\n );\r\n\r\n return {\r\n text: resolved,\r\n discoveredAgents: Array.from(discoveredAgents.entries()).map(([name, path]) => ({\r\n name,\r\n path,\r\n })),\r\n };\r\n}\r\n",
|
|
66
|
+
"import type { Tool } from 'ai';\r\nimport { z } from 'zod';\r\nimport { parseAgent, parseAgentContent, type ParsedAgent } from './parser';\r\nimport { connectMCP, getMCPTools, type MCPServersConfig } from './mcp';\nimport { logger } from './utils/logger';\nimport { fetchRemoteAgent, getRemoteAgentName, isURL, resolveAgentPath } from './utils/remote-agent';\nimport { executeAgentCore, processAgentStream, buildSystemMessages } from './runner';\nimport { DoomLoopDetector } from './tools/index.js';\nimport { dirname, resolve } from 'path';\nimport { SessionManager } from './session/manager';\nimport { homedir } from 'os';\nimport { loadAgentsGuidance } from './utils/agents-guidance';\nimport { createHookRunner } from './hooks';\nimport { resolveFileAttachments } from './utils/file-attachments';\nimport { resolvePromptVariables } from './utils/prompt-variables';\n\r\n// Constants\r\nconst DEFAULT_MAX_SUBAGENT_DEPTH = 2;\r\n\r\n/**\r\n * Get the maximum sub-agent nesting depth from environment or use default\r\n * Exported for testing purposes\r\n */\r\nexport function getMaxSubAgentDepth(): number {\r\n const envValue = process.env.MAX_SUBAGENT_DEPTH;\r\n if (envValue) {\r\n const parsed = parseInt(envValue);\r\n if (isNaN(parsed) || parsed <= 0) {\r\n logger.warn(`Invalid MAX_SUBAGENT_DEPTH value: \"${envValue}\". Using default: ${DEFAULT_MAX_SUBAGENT_DEPTH}`);\r\n return DEFAULT_MAX_SUBAGENT_DEPTH;\r\n }\r\n return parsed;\r\n }\r\n return DEFAULT_MAX_SUBAGENT_DEPTH;\r\n}\r\n\r\n/**\r\n * Create a tool that runs another agent as a sub-agent\r\n * @param agentPath Path to the agent file (.pk-agent)\r\n * @param maxSteps Maximum steps the sub-agent can take\r\n * @param basePath Optional base path for resolving relative paths\r\n * @param modelOverride Optional model override from parent agent\r\n * @param depth Current nesting depth (0 = main agent)\r\n * @param callStack Array of agent paths in the call stack for cycle detection\r\n * @param sessionManager Optional session manager for logging\r\n * @param parentSessionID Optional parent session ID\r\n * @param parentAgentName Optional parent agent name\r\n * @param projectContext Optional project context (root, cwd)\r\n * @returns Tool that executes the sub-agent\r\n */\r\nexport async function createSubAgentTool(\n agentPath: string,\n maxSteps: number = 50,\n basePath?: string,\r\n modelOverride?: string,\r\n depth: number = 0,\r\n callStack: string[] = [],\r\n sessionManager?: SessionManager,\r\n parentSessionID?: string,\r\n parentAgentName?: string,\r\n projectContext?: { projectRoot: string; cwd: string },\n abortSignal?: AbortSignal\n): Promise<Tool> {\n // Resolve the path relative to the base path if provided\n const resolvedPath = resolveAgentPath(basePath, agentPath);\n\r\n // Guard: Check for cycles\r\n if (callStack.includes(resolvedPath)) {\r\n const cycleChain = [...callStack, resolvedPath].join(' -> ');\r\n logger.error(`[SubAgent] Cycle detected: ${cycleChain}`);\r\n throw new Error(`Circular sub-agent dependency detected: ${cycleChain}`);\r\n }\r\n\r\n // Parse the agent file\r\n let agent: ParsedAgent;\r\n if (isURL(resolvedPath)) {\r\n const pathname = new URL(resolvedPath).pathname;\r\n if (!pathname.toLowerCase().endsWith('.pk-agent')) {\r\n throw new Error(`Remote sub-agent URL must end with .pk-agent (got: ${resolvedPath})`);\r\n }\r\n const content = await fetchRemoteAgent(resolvedPath);\r\n const name = getRemoteAgentName(resolvedPath);\r\n agent = parseAgentContent(content, name);\r\n } else {\r\n agent = await parseAgent(resolvedPath);\r\n }\r\n\r\n // Apply model override if provided\r\n if (modelOverride) {\r\n agent.config.model = modelOverride;\r\n }\r\n\r\n return {\r\n description: agent.description || `Run ${agent.name} agent: ${agent.instructions.split('\\n')[0].slice(0, 100)}...`,\r\n inputSchema: z.object({\r\n task: z.string().optional().describe('Optional additional task or question for the sub-agent'),\r\n context: z.record(z.string(), z.any()).optional().describe('Additional context to pass to the sub-agent')\r\n }),\n execute: async ({ task, context }) => {\n const startTime = Date.now();\n // Declare outside try so error handlers can reference.\n let subagentSessionID: string | undefined;\n let subagentMsgID: string | undefined;\n\n try {\n logger.info(`[SubAgent:depth=${depth}] Starting ${agent.name}${task ? ` with task: ${task.slice(0, 100)}...` : ''}`);\n\r\n // Connect to any MCP servers the sub-agent needs\r\n // Use the sub-agent's directory as base path for resolving relative paths\r\n const subAgentBasePath = isURL(resolvedPath)\r\n ? new URL('.', resolvedPath).toString()\r\n : dirname(resolvedPath);\r\n const mcpConnections = agent.config.mcpServers\r\n ? await connectMCP(agent.config.mcpServers as MCPServersConfig, false, subAgentBasePath)\r\n : [];\r\n\r\n const mcpTools = await getMCPTools(mcpConnections);\r\n\r\n // Load nested sub-agents if within depth limit (will be populated after session creation)\r\n const maxDepth = getMaxSubAgentDepth();\r\n let nestedSubAgentTools: Record<string, Tool> = {};\r\n\r\n // Create NEW SessionManager instance for this subagent (eliminates shared state issues)\n let subagentSessionManager: SessionManager | undefined;\n\r\n // Check depth limit but don't create nested tools yet\r\n if (depth + 1 >= maxDepth && agent.config.subagents && agent.config.subagents.length > 0) {\r\n // At depth limit, warn that nested sub-agents are being skipped\r\n logger.warn(`[SubAgent:depth=${depth}] Max depth ${maxDepth} reached, skipping ${agent.config.subagents.length} nested sub-agent(s) for ${agent.name}`);\r\n }\r\n\r\n // Initially just MCP tools (nested subagents will be added after session creation)\r\n let tools = { ...mcpTools };\n\n try {\n const systemMessages = buildSystemMessages(agent.config.model, true);\n\n // Auto-inject AGENTS.md guidance (project + user-level) as an additional system message.\n // Disable with PK_AGENT_AGENTS_MD=0/false/no.\n const agentsMdEnabled = !['0', 'false', 'no'].includes(String(process.env.PK_AGENT_AGENTS_MD ?? '1').toLowerCase());\n if (projectContext && agentsMdEnabled) {\n const guidance = loadAgentsGuidance({\n projectRoot: projectContext.projectRoot,\n homeDir: homedir(),\n enabled: true,\n });\n if (guidance.content) {\n systemMessages.push({ role: 'system', content: guidance.content });\n }\n }\n\n // Build user message: agent instructions + optional parent task\n let userMessageText = agent.instructions;\n\r\n // Resolve [[agent]] and [[[skill]]] wikilink references in subagent instructions\r\n try {\r\n const { resolveReferences } = await import('./references.js');\r\n const { text: resolvedText } = await resolveReferences(userMessageText, {\r\n agentDir: isURL(resolvedPath) ? undefined : dirname(resolvedPath),\r\n projectRoot: projectContext?.projectRoot,\r\n existingSubagents: [],\r\n });\r\n userMessageText = resolvedText;\r\n } catch (error) {\r\n logger.warn(`[SubAgent] Failed to resolve references for ${agent.name}: ${(error as Error).message}`);\r\n }\r\n\r\n // Only append task if it's meaningful (not empty or generic)\n if (task && task.trim() && !task.match(/^(run|execute|perform|do)$/i)) {\n userMessageText = context\n ? `${agent.instructions}\\n\\nAdditional task: ${task}\\n\\nContext: ${JSON.stringify(context)}`\n : `${agent.instructions}\\n\\nAdditional task: ${task}`;\n } else if (context) {\n userMessageText = `${agent.instructions}\\n\\nContext: ${JSON.stringify(context)}`;\n }\n\n // Resolve safe prompt variables in the final subagent user message.\n userMessageText = resolvePromptVariables(userMessageText, {\n projectRoot: projectContext?.projectRoot ?? process.cwd(),\n agentDir: isURL(resolvedPath) ? undefined : dirname(resolvedPath),\n });\n\r\n let userMessage: string | Array<unknown> = userMessageText;\r\n\r\n // Optional PDF attachments for OpenAI models in sub-agents.\n if (agent.config.files && agent.config.files.length > 0) {\n const provider = agent.config.model.split(':')[0] || 'openai';\n const baseDir = isURL(resolvedPath) ? undefined : dirname(resolvedPath);\n const fileParts = await resolveFileAttachments(agent.config.files, baseDir, provider);\n\n userMessage = [...fileParts, { type: 'text', text: userMessageText }];\n }\n\r\n // Create session for this subagent if SessionManager is provided\r\n if (sessionManager && parentSessionID && parentAgentName && projectContext) {\r\n try {\r\n // Create NEW SessionManager instance for this subagent\r\n // This eliminates shared state issues with parent agent\r\n subagentSessionManager = new SessionManager();\r\n\r\n // Set parent path on the NEW instance using parent's full path\r\n const parentFullPath = sessionManager.getFullPath();\r\n if (parentFullPath) {\r\n subagentSessionManager.setParentPath(parentFullPath);\r\n }\r\n\r\n // Create subagent session using the NEW instance\r\n subagentSessionID = await subagentSessionManager.createSession({\r\n agent: {\r\n name: agent.name,\r\n ...(resolvedPath && { filePath: resolvedPath }),\r\n ...(agent.description && { description: agent.description }),\r\n isSubAgent: true\r\n },\r\n model: agent.config.model,\r\n version: process.env.npm_package_version || 'unknown',\r\n config: {\r\n ...(agent.config.timeout !== undefined && { timeout: agent.config.timeout }),\r\n ...(agent.config.maxSteps !== undefined && { maxSteps: agent.config.maxSteps }),\r\n ...(agent.config.mcpServers && { mcpServers: Object.keys(agent.config.mcpServers) }),\r\n ...(agent.config.subagents && {\r\n subagents: agent.config.subagents.map(s => ({\r\n path: s.path,\r\n ...(s.name && { name: s.name })\r\n }))\r\n })\r\n },\r\n project: {\r\n root: projectContext.projectRoot,\r\n cwd: projectContext.cwd\r\n }\r\n });\r\n\r\n // Create message exchange\r\n const taskPrompt = task && task.trim() && !task.match(/^(run|execute|perform|do)$/i)\r\n ? task\r\n : undefined;\r\n\r\n subagentMsgID = await subagentSessionManager.createMessage(subagentSessionID, agent.name, {\r\n user: {\r\n prompt: {\r\n task: agent.instructions,\r\n ...(taskPrompt && { user: taskPrompt })\r\n }\r\n },\r\n assistant: {\r\n system: systemMessages.map(m => m.content),\r\n modelID: agent.config.model,\r\n providerID: agent.config.model.split(':')[0],\r\n mode: 'build',\r\n path: { cwd: projectContext.cwd, root: projectContext.projectRoot },\r\n cost: 0,\r\n tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } }\r\n }\r\n });\r\n\r\n logger.debug(`[SubAgent] Created session ${subagentSessionID} for ${agent.name}`);\r\n } catch (error) {\r\n logger.warn(`[SubAgent] Failed to create session: ${(error as Error).message}`);\r\n }\r\n }\r\n\r\n // Now create nested sub-agent tools after this subagent's session exists\r\n // Pass the NEW subagent SessionManager instance to nested tools\r\n if (depth + 1 < maxDepth && agent.config.subagents && agent.config.subagents.length > 0) {\r\n nestedSubAgentTools = await createSubAgentTools(\r\n agent.config.subagents,\r\n subAgentBasePath,\r\n agent.config.model,\r\n depth + 1,\r\n [...callStack, resolvedPath],\r\n subagentSessionManager, // Pass NEW instance (not parent's)\r\n subagentSessionID,\r\n agent.name,\r\n projectContext,\r\n abortSignal // Pass parent's abort signal to nested subagents\r\n );\r\n\r\n // Merge nested subagent tools into tools\r\n tools = { ...mcpTools, ...nestedSubAgentTools };\r\n }\r\n\r\n // Create doom loop detector for sub-agent\n const doomLoopDetector = new DoomLoopDetector({ threshold: 3, action: 'error' });\n\n // Hooks (optional). Configured via JSON:\n // - Project: <projectRoot>/.pk-agent/hooks.json\n // - User: ~/.pk-agent/hooks.json\n const hookRunner = createHookRunner(projectContext?.projectRoot ?? process.cwd());\n const effectiveRunId = subagentSessionID || String(Date.now());\n\n const baseHookCtx = {\n runId: effectiveRunId,\n agent: {\n name: agent.name,\n model: agent.config.model,\n ...(isURL(resolvedPath) ? {} : { filePath: resolvedPath }),\n isSubAgent: true,\n },\n project: {\n projectRoot: projectContext?.projectRoot ?? process.cwd(),\n cwd: process.cwd(),\n },\n };\n\n if (hookRunner.enabled) {\n await hookRunner.run('run:start', baseHookCtx as any);\n }\n\n // Wrap tools to emit tool:start/tool:end hooks for auditing/integration.\n const wrapTool = (name: string, tool: Tool): Tool => {\n const originalExecute = tool.execute;\n if (!originalExecute) {\n return tool;\n }\n return {\n ...tool,\n execute: async (input: any, execOpts: any) => {\n const start = Date.now();\n await hookRunner.run('tool:start', { ...baseHookCtx, tool: { name, input } } as any);\n try {\n const result: any = await originalExecute(input, execOpts);\n const durationMs = Date.now() - start;\n const outputText = typeof result?.output === 'string' ? result.output : undefined;\n await hookRunner.run('tool:end', {\n ...baseHookCtx,\n tool: { name, input, output: outputText, success: true, durationMs },\n } as any);\n return result;\n } catch (err: any) {\n const durationMs = Date.now() - start;\n await hookRunner.run('tool:end', {\n ...baseHookCtx,\n tool: { name, input, success: false, durationMs },\n error: { message: err?.message ?? String(err) },\n } as any);\n throw err;\n }\n },\n };\n };\n\n const wrappedTools = Object.fromEntries(\n Object.entries(tools).map(([name, tool]) => [name, wrapTool(name, tool as Tool)])\n );\n\n // Process the agent stream using the NEW SessionManager instance\n const result = await processAgentStream(\n executeAgentCore(agent, wrappedTools as any, {\n userMessage,\n systemMessages,\n maxSteps,\n ...(abortSignal && { abortSignal }), // Pass parent's abort signal\n subAgentNames: new Set(Object.keys(nestedSubAgentTools)) // Track nested sub-agent names for logging\n }),\n subagentSessionID && subagentMsgID && subagentSessionManager ? {\r\n sessionManager: subagentSessionManager, // Use NEW instance\r\n sessionID: subagentSessionID,\r\n agentName: agent.name,\r\n messageID: subagentMsgID,\r\n collectToolCalls: true,\r\n logPrefix: '[SubAgent] ',\r\n doomLoopDetector\r\n } : {\r\n collectToolCalls: true,\r\n logPrefix: '[SubAgent] ',\r\n doomLoopDetector\r\n }\r\n );\r\n \r\n const duration = Date.now() - startTime;\n logger.info(`[SubAgent:depth=${depth}] ${agent.name} completed in ${(duration / 1000).toFixed(2)}s`);\n\n if (hookRunner.enabled) {\n await hookRunner.run('run:end', baseHookCtx as any);\n }\n\n // Log token usage\n if (result.usage?.totalTokens) {\n logger.info(`[SubAgent:depth=${depth}] ${agent.name} tokens used: ${result.usage.totalTokens}`);\n }\n\r\n // Update session message with final token usage\r\n if (subagentSessionManager && subagentSessionID && subagentMsgID && result.usage) {\r\n try {\r\n await subagentSessionManager.updateMessage(subagentSessionID, agent.name, subagentMsgID, {\r\n time: { completed: Date.now() },\r\n assistant: {\r\n tokens: {\r\n input: result.usage.inputTokens || 0,\r\n output: result.usage.outputTokens || 0\r\n }\r\n }\r\n });\r\n } catch (error) {\r\n logger.debug(`[SubAgent] Failed to update message with token usage: ${(error as Error).message}`);\r\n }\r\n }\r\n\r\n return {\r\n output: result.text || 'Sub-agent completed without text response',\r\n metadata: {\r\n agent: agent.name,\r\n toolCalls: result.toolCalls && result.toolCalls.length > 0 ? result.toolCalls : undefined,\r\n tokensUsed: result.usage?.totalTokens,\r\n duration // Add duration in ms to metadata\r\n }\r\n };\r\n } finally {\r\n // Clean up MCP connections\r\n for (const conn of mcpConnections) {\r\n try {\r\n await conn.client.close();\r\n } catch (error) {\r\n // Ignore errors when closing\r\n }\r\n }\r\n }\r\n \r\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n logger.error(`[SubAgent] ${agent.name} failed: ${errorMsg}`);\n try {\n const hookRunner = createHookRunner(projectContext?.projectRoot ?? process.cwd());\n if (hookRunner.enabled) {\n await hookRunner.run('run:end', {\n runId: subagentSessionID || String(Date.now()),\n agent: {\n name: agent.name,\n model: agent.config.model,\n ...(isURL(resolvedPath) ? {} : { filePath: resolvedPath }),\n isSubAgent: true,\n },\n project: {\n projectRoot: projectContext?.projectRoot ?? process.cwd(),\n cwd: process.cwd(),\n },\n error: { message: errorMsg },\n } as any);\n }\n } catch {\n // ignore hook failures\n }\n return {\n output: `Sub-agent ${agent.name} failed: ${errorMsg}`\n };\n }\n }\r\n };\r\n}\r\n\r\n/**\r\n * Create tools for multiple sub-agents\r\n * @param subAgents Array of sub-agent configurations\r\n * @param basePath Optional base path for resolving relative agent paths\r\n * @param modelOverride Optional model override from parent agent\r\n * @param depth Current nesting depth (0 = main agent)\r\n * @param callStack Array of agent paths in the call stack for cycle detection\r\n * @returns Map of sub-agent tools\r\n */\r\nexport async function createSubAgentTools(\r\n subAgents?: Array<{ path: string; name?: string | undefined; maxSteps?: number | undefined }>,\r\n basePath?: string,\r\n modelOverride?: string,\r\n depth: number = 0,\r\n callStack: string[] = [],\r\n sessionManager?: SessionManager,\r\n parentSessionID?: string,\r\n parentAgentName?: string,\r\n projectContext?: { projectRoot: string; cwd: string },\r\n abortSignal?: AbortSignal\r\n): Promise<Record<string, Tool>> {\r\n if (!subAgents || subAgents.length === 0) {\r\n return {};\r\n }\r\n\r\n const tools: Record<string, Tool> = {};\r\n\r\n for (const config of subAgents) {\r\n try {\r\n const tool = await createSubAgentTool(\r\n config.path,\r\n config.maxSteps,\r\n basePath,\r\n modelOverride,\r\n depth,\r\n callStack,\r\n sessionManager,\r\n parentSessionID,\r\n parentAgentName,\r\n projectContext,\r\n abortSignal\r\n );\r\n // Use custom name if provided, otherwise extract from filename\r\n let name = config.name;\r\n if (!name) {\r\n // Extract agent name from path (e.g., \"./code-reviewer.pk-agent\" -> \"code_reviewer\")\r\n const filename = config.path.split('/').pop()?.replace(/\\.pk-agent$/, '') || 'agent';\r\n // Replace all non-alphanumeric characters (except underscore and hyphen) with underscore\r\n name = filename.replace(/[^a-zA-Z0-9_-]/g, '_').replace(/-/g, '_');\r\n }\r\n \r\n // Ensure the name is valid for API requirements (only alphanumeric, underscore, hyphen)\r\n name = name.replace(/[^a-zA-Z0-9_-]/g, '_');\r\n\r\n // Add subagent__ prefix\r\n const prefixedName = `subagent__${name}`;\r\n tools[prefixedName] = tool;\r\n logger.info(`[SubAgent] Registered sub-agent: ${prefixedName}`);\r\n \r\n // Note: @ symbol is not allowed in tool names by the API\r\n // So we won't register @-prefixed versions anymore\r\n // Users can still reference them with @ in instructions, but the actual tool name won't have @\r\n } catch (error) {\r\n const errorMsg = error instanceof Error ? error.message : String(error);\r\n logger.error(`Failed to load sub-agent from ${config.path}: ${errorMsg}`);\r\n \r\n // Provide helpful error messages for common issues\r\n if (errorMsg.includes('File not found')) {\r\n const resolvedPath = basePath ? resolve(basePath, config.path) : config.path;\r\n logger.error(` Attempted to load from: ${resolvedPath}`);\r\n logger.error(` Make sure the file exists and the path is correct`);\r\n \r\n // Check for special characters that might cause issues\r\n if (config.path.includes(':')) {\r\n logger.error(` Note: The path contains ':' which may cause file system issues`);\r\n logger.error(` Consider renaming the file to use '-' or '_' instead`);\r\n }\r\n }\r\n }\r\n }\r\n \r\n return tools;\r\n}\r\n",
|
|
67
|
+
"import type { ToolsConfig } from '../tools/types.js';\r\nimport type { ToolValidationResult } from './types.js';\r\nimport { logger } from '../utils/logger.js';\r\n\r\n/**\r\n * Tool pattern aliases\r\n */\r\nconst TOOL_ALIASES: Record<string, string> = {\r\n 'Read': 'tools__filesystem_read',\r\n 'Write': 'tools__filesystem_write',\r\n 'Edit': 'tools__filesystem_edit',\r\n};\r\n\r\n/**\r\n * Parse a Bash pattern like \"Bash(git:*)\" or \"Bash(python3:*)\"\r\n * Returns the command name or null if not a bash pattern\r\n */\r\nfunction parseBashPattern(pattern: string): string | null {\r\n const match = pattern.match(/^Bash\\(([^:]+):\\*\\)$/);\r\n return match ? match[1] : null;\r\n}\r\n\r\n/**\r\n * Check if a single tool pattern is satisfied by the agent's tools config\r\n */\r\nfunction validateToolPattern(\r\n pattern: string,\r\n toolsConfig: ToolsConfig | undefined\r\n): ToolValidationResult {\r\n // Resolve aliases\r\n const resolvedPattern = TOOL_ALIASES[pattern] || pattern;\r\n\r\n // Check for plain \"Bash\" pattern (requires any bash config)\r\n if (resolvedPattern === 'Bash') {\r\n if (!toolsConfig?.bash?.commands || toolsConfig.bash.commands.length === 0) {\r\n return {\r\n pattern,\r\n satisfied: false,\r\n reason: 'Bash tool not configured for this agent',\r\n };\r\n }\r\n return { pattern, satisfied: true };\r\n }\r\n\r\n // Check for Bash patterns like \"Bash(git:*)\"\r\n const bashCommand = parseBashPattern(resolvedPattern);\r\n if (bashCommand) {\r\n if (!toolsConfig?.bash?.commands) {\r\n return {\r\n pattern,\r\n satisfied: false,\r\n reason: 'Bash tool not configured',\r\n };\r\n }\r\n\r\n const hasCommand = toolsConfig.bash.commands.some(\r\n cmd => cmd === bashCommand || cmd.startsWith(`${bashCommand} `)\r\n );\r\n\r\n if (!hasCommand) {\r\n return {\r\n pattern,\r\n satisfied: false,\r\n reason: `Bash command \"${bashCommand}\" not in allowed commands`,\r\n };\r\n }\r\n\r\n return { pattern, satisfied: true };\r\n }\r\n\r\n // Check for filesystem tools\r\n if (resolvedPattern === 'tools__filesystem_read') {\r\n const hasRead = toolsConfig?.filesystem?.some(c => c.permissions.includes('read'));\r\n return {\r\n pattern,\r\n satisfied: !!hasRead,\r\n reason: hasRead ? undefined : 'Filesystem read permission not configured',\r\n };\r\n }\r\n\r\n if (resolvedPattern === 'tools__filesystem_write') {\r\n const hasWrite = toolsConfig?.filesystem?.some(c => c.permissions.includes('write'));\r\n return {\r\n pattern,\r\n satisfied: !!hasWrite,\r\n reason: hasWrite ? undefined : 'Filesystem write permission not configured',\r\n };\r\n }\r\n\r\n if (resolvedPattern === 'tools__filesystem_edit') {\r\n const hasEdit = toolsConfig?.filesystem?.some(c => c.permissions.includes('edit'));\r\n return {\r\n pattern,\r\n satisfied: !!hasEdit,\r\n reason: hasEdit ? undefined : 'Filesystem edit permission not configured',\r\n };\r\n }\r\n\r\n // MCP tools and other tool names are accepted as documentation\r\n // Only builtin tools (Read, Write, Edit, Bash) are validated\r\n // This allows MCP tools like mcp__github, mcp__linear, etc.\r\n // Warn about unknown patterns for visibility\r\n if (!resolvedPattern.startsWith('mcp__') && !resolvedPattern.startsWith('tools__')) {\r\n logger.warn(`Unknown tool pattern \"${pattern}\" - assuming satisfied`);\r\n }\r\n return { pattern, satisfied: true };\r\n}\r\n\r\n/**\r\n * Validate all allowed-tools patterns against agent's tools config\r\n * Returns array of unsatisfied patterns with reasons\r\n */\r\nexport function validateAllowedTools(\r\n allowedTools: string[] | undefined,\r\n toolsConfig: ToolsConfig | undefined\r\n): ToolValidationResult[] {\r\n if (!allowedTools || allowedTools.length === 0) {\r\n return [];\r\n }\r\n\r\n return allowedTools\r\n .map(pattern => validateToolPattern(pattern, toolsConfig))\r\n .filter(result => !result.satisfied);\r\n}\r\n\r\n/**\r\n * Format unsatisfied tools as warning message\r\n */\r\nexport function formatToolsWarning(unsatisfied: ToolValidationResult[]): string | null {\r\n if (unsatisfied.length === 0) return null;\r\n\r\n const details = unsatisfied.map(r => `- ${r.pattern}: ${r.reason}`).join('\\n');\r\n const hasBash = unsatisfied.some(r => r.pattern === 'Bash' || r.pattern.startsWith('Bash('));\r\n\r\n const lines = [\r\n '> WARNING **WARNING: Required tools not available**',\r\n '>',\r\n '> This skill requires tools that are not configured for this agent:',\r\n details.split('\\n').map(line => `> ${line}`).join('\\n'),\r\n '>',\r\n '> The agent cannot execute these operations without the required tools.',\r\n ];\r\n\r\n if (hasBash) {\r\n lines.push(\r\n '> To enable bash, add to your agent YAML:',\r\n '> ```yaml',\r\n '> tools:',\r\n '> bash:',\r\n '> commands:',\r\n '> - \"python3 *\"',\r\n '> - \"date\"',\r\n '> ```',\r\n );\r\n }\r\n\r\n return lines.join('\\n');\r\n}\r\n",
|
|
68
|
+
"import { z } from 'zod';\r\nimport * as path from 'path';\r\nimport * as fs from 'fs/promises';\r\nimport type { Tool } from 'ai';\r\nimport { discoverSkills } from './discovery.js';\r\nimport { parseSkillContent } from './parser.js';\r\nimport { validateAllowedTools } from './validate.js';\r\nimport type { SkillInfo } from './types.js';\r\nimport type { ToolsConfig } from '../tools/types.js';\r\nimport { PathValidator, resolveRealPath } from '../tools/path-validator.js';\r\nimport { logger } from '../utils/logger.js';\r\n\r\n/**\r\n * Build the available skills XML block for tool description\r\n */\r\nfunction buildAvailableSkillsXml(skills: SkillInfo[]): string {\r\n if (skills.length === 0) {\r\n return '<available_skills>\\n (No skills available)\\n</available_skills>';\r\n }\r\n\r\n const skillEntries = skills.map(skill =>\r\n ` <skill>\\n <name>${skill.name}</name>\\n <description>${skill.description}</description>\\n </skill>`\r\n ).join('\\n');\r\n\r\n return `<available_skills>\\n${skillEntries}\\n</available_skills>`;\r\n}\r\n\r\n/**\r\n * Build the tool description with available skills\r\n */\r\nfunction buildToolDescription(skills: SkillInfo[]): string {\r\n return [\r\n 'Load a skill to get detailed instructions for a specific task.',\r\n 'Skills provide specialized knowledge and step-by-step guidance.',\r\n 'Use this when a task matches an available skill\\'s description.',\r\n '',\r\n buildAvailableSkillsXml(skills),\r\n ].join('\\n');\r\n}\r\n\r\n/**\r\n * Substitute ${skillDir} variable in skill content\r\n */\r\nfunction substituteSkillVariables(content: string, directory: string): string {\r\n return content.replace(/\\$\\{skillDir\\}/g, directory);\r\n}\r\n\r\n/**\r\n * Format the skill output with base directory and optional warnings\r\n */\r\nfunction formatSkillOutput(\r\n name: string,\r\n directory: string,\r\n content: string,\r\n warning: string | null\r\n): string {\r\n // Substitute ${skillDir} with actual directory path\r\n const resolvedContent = substituteSkillVariables(content, directory);\r\n\r\n const parts = [\r\n `## Skill: ${name}`,\r\n '',\r\n `**Base directory**: ${directory}`,\r\n ];\r\n\r\n if (warning) {\r\n parts.push('', warning);\r\n }\r\n\r\n parts.push('', resolvedContent);\r\n\r\n return parts.join('\\n');\r\n}\r\n\r\n/**\r\n * Result type for createSkillTools\r\n */\r\nexport interface SkillToolsResult {\r\n /** The main skill loading tool */\r\n skillTool: Tool;\r\n /** Tool to read files from loaded skill directories */\r\n skillReadTool: Tool;\r\n /** List of discovered skills */\r\n skills: SkillInfo[];\r\n}\r\n\r\n/**\r\n * Create the skill tool (backward compatibility wrapper)\r\n */\r\nexport async function createSkillTool(\r\n projectRoot: string,\r\n agentToolsConfig: ToolsConfig | undefined\r\n): Promise<{ tool: Tool; skills: SkillInfo[] }> {\r\n const { skillTool, skills } = await createSkillTools(projectRoot, agentToolsConfig);\r\n return { tool: skillTool, skills };\r\n}\r\n\r\n/**\r\n * Create both skill tools: skill loader and skill file reader\r\n */\r\nexport async function createSkillTools(\r\n projectRoot: string,\r\n agentToolsConfig: ToolsConfig | undefined\r\n): Promise<SkillToolsResult> {\r\n // Discover all available skills\r\n const skillsMap = await discoverSkills(projectRoot);\r\n const skills = Array.from(skillsMap.values());\r\n\r\n // Track loaded skills: name -> directory (shared between both tools)\r\n const loadedSkills = new Map<string, string>();\r\n\r\n // Main skill loading tool\r\n const skillTool: Tool = {\r\n description: buildToolDescription(skills),\r\n inputSchema: z.object({\r\n name: z.string().describe('Skill identifier from available_skills'),\r\n }),\r\n execute: async ({ name }: { name: string }) => {\r\n // Find the skill\r\n const skill = skillsMap.get(name);\r\n if (!skill) {\r\n const available = skills.map(s => s.name).join(', ') || 'none';\r\n throw new Error(`Skill \"${name}\" not found. Available skills: ${available}`);\r\n }\r\n\r\n // Load full skill content\r\n const skillContent = await parseSkillContent(skill.location);\r\n\r\n // Track loaded skill directory for skill_read tool\r\n loadedSkills.set(name, skillContent.directory);\r\n\r\n // Validate allowed-tools\r\n const unsatisfied = validateAllowedTools(skillContent.allowedTools, agentToolsConfig);\r\n\r\n // Log warning to console for user visibility\r\n if (unsatisfied.length > 0) {\r\n const toolsList = unsatisfied.map(r => r.pattern).join(', ');\r\n logger.warn(`Skill \"${name}\" requires tools not configured: ${toolsList}`);\r\n for (const r of unsatisfied) {\r\n logger.warn(` - ${r.pattern}: ${r.reason}`);\r\n }\r\n }\r\n\r\n // Format output with simple flag for LLM\r\n const warning = unsatisfied.length > 0\r\n ? `> WARNING WARNING: This skill requires tools not available: ${unsatisfied.map(r => r.pattern).join(', ')}. Do not attempt to use these tools.`\r\n : null;\r\n\r\n const output = formatSkillOutput(\r\n skillContent.name,\r\n skillContent.directory,\r\n skillContent.content,\r\n warning\r\n );\r\n\r\n return output;\r\n },\r\n };\r\n\r\n // Skill file reader tool - reads files from loaded skill directories\r\n const skillReadTool: Tool = {\r\n description: [\r\n 'Read a file from a loaded skill directory.',\r\n 'The skill must be loaded first using the skill tool.',\r\n 'Use this to access helper scripts, data files, or other resources bundled with skills.',\r\n ].join('\\n'),\r\n inputSchema: z.object({\r\n skill: z.string().describe('Name of the skill (must be already loaded)'),\r\n path: z.string().describe('Relative path to file within the skill directory'),\r\n }),\r\n execute: async ({ skill, path: filePath }: { skill: string; path: string }) => {\r\n // Check if skill is loaded\r\n const skillDir = loadedSkills.get(skill);\r\n if (!skillDir) {\r\n const loaded = Array.from(loadedSkills.keys()).join(', ') || 'none';\r\n throw new Error(`Skill \"${skill}\" has not been loaded yet. Load it first using the skill tool. Currently loaded skills: ${loaded}`);\r\n }\r\n\r\n // Reject absolute paths\r\n if (path.isAbsolute(filePath)) {\r\n throw new Error('Absolute paths are not allowed. Use a relative path within the skill directory.');\r\n }\r\n\r\n // Resolve skill directory to real path (handles macOS /var -> /private/var symlinks)\r\n const realSkillDir = resolveRealPath(skillDir);\r\n\r\n // Use PathValidator to validate the path (handles path traversal, symlinks, sensitive files)\r\n const validator = new PathValidator(\r\n [{ path: realSkillDir, permissions: ['read'] }],\r\n { projectRoot: realSkillDir }\r\n );\r\n\r\n // Resolve relative to skill directory\r\n const resolvedPath = path.resolve(realSkillDir, filePath);\r\n const validation = validator.validate(resolvedPath, 'read');\r\n\r\n if (!validation.allowed) {\r\n throw new Error(validation.error ?? 'Access denied');\r\n }\r\n\r\n // Read the file\r\n try {\r\n const content = await fs.readFile(validation.resolvedPath, 'utf-8');\r\n return {\r\n skill,\r\n path: filePath,\r\n resolvedPath: validation.resolvedPath,\r\n content,\r\n };\r\n } catch (error) {\r\n const err = error as NodeJS.ErrnoException;\r\n if (err.code === 'ENOENT') {\r\n throw new Error(`File not found: ${filePath} (in skill directory: ${skillDir})`);\r\n }\r\n if (err.code === 'EISDIR') {\r\n throw new Error(`Cannot read directory: ${filePath}. Please specify a file path.`);\r\n }\r\n throw new Error(`Failed to read file: ${err.message}`);\r\n }\r\n },\r\n };\r\n\r\n return { skillTool, skillReadTool, skills };\r\n}\r\n",
|
|
69
|
+
"// Types\nexport type {\n SkillInfo,\n SkillContent,\n SkillFrontmatter,\n ToolValidationResult,\n} from './types.js';\nexport { SkillFrontmatterSchema } from './types.js';\n\n// Discovery\nexport { discoverSkills, getSkill, getAllSkills } from './discovery.js';\n\n// Parser\nexport { parseSkillFrontmatter, parseSkillContent } from './parser.js';\n\n// Validation\nexport { validateAllowedTools, formatToolsWarning } from './validate.js';\n\n// Tool\nexport { createSkillTool, createSkillTools } from './tool.js';\nexport type { SkillToolsResult } from './tool.js';\n",
|
|
70
|
+
"import * as readline from 'readline';\r\nimport { join } from 'path';\r\nimport { existsSync } from 'fs';\r\nimport { version as packageVersion } from '../../package.json';\r\n\r\n/**\r\n * Detect if running from a linked/local development build.\r\n */\r\nexport function getVersionString(): string {\r\n const packageRoot = join(__dirname, '..');\r\n const isLocalDev = existsSync(join(packageRoot, '.git'));\r\n return isLocalDev ? `${packageVersion} (local)` : packageVersion;\r\n}\r\n\r\n/**\r\n * Helper function to prompt user via readline.\r\n */\r\nexport async function prompt(question: string): Promise<string> {\r\n const rl = readline.createInterface({\r\n input: process.stdin,\r\n output: process.stdout\r\n });\r\n\r\n return new Promise((resolve, reject) => {\r\n rl.on('SIGINT', () => {\r\n rl.close();\r\n reject(new Error('Interrupted'));\r\n });\r\n\r\n rl.question(question, (answer) => {\r\n rl.close();\r\n resolve(answer.toLowerCase().trim());\r\n });\r\n });\r\n}\r\n\r\nexport { packageVersion };\r\n",
|
|
71
|
+
"import { dirname } from 'path';\nimport { getMCPTools } from '../mcp';\nimport { createSubAgentTools } from '../subagent';\nimport {\n getTools as getConfiguredTools,\n DoomLoopDetector,\n type PathResolverContext\n} from '../tools/index.js';\nimport { logger } from '../utils/logger';\nimport { resolveMaxSteps, DEFAULT_MAX_STEPS } from '../utils/config';\nimport { createSkillTools } from '../skill/index.js';\nimport { buildSystemMessages } from './prompt';\nimport { version as packageVersion } from '../../package.json';\nimport type { PrepareAgentOptions, PreparedAgentExecution, UserMessageContent } from './types';\nimport type { Tool, ToolSet } from 'ai';\nimport { homedir } from 'os';\nimport { loadAgentsGuidance } from '../utils/agents-guidance';\nimport { createHookRunner } from '../hooks';\nimport { resolveFileAttachments } from '../utils/file-attachments';\nimport { prompt } from '../utils/cli-helpers';\nimport { redactObjectDeep } from '../utils/redaction';\nimport { resolvePromptVariables } from '../utils/prompt-variables';\n\n/**\n * Prepare agent execution - shared setup logic for both streaming and non-streaming modes\n * This extracts the common setup code to avoid duplication between runAgent and serve.ts\n */\r\nexport async function prepareAgentExecution(options: PrepareAgentOptions): Promise<PreparedAgentExecution> {\r\n const {\r\n agent,\r\n mcpClients,\r\n mcpClientsPromise,\r\n agentFilePath,\r\n cliMaxSteps,\r\n sessionManager,\r\n projectContext,\r\n userPrompt,\r\n abortSignal,\r\n verbose = false\r\n } = options;\r\n\r\n // Get configured builtin tools (filesystem, bash) - does NOT depend on MCP\n const configuredTools = agent.config.tools && projectContext\n ? await getConfiguredTools(agent.config.tools, {\n projectRoot: projectContext.projectRoot,\n agentDir: agentFilePath ? dirname(agentFilePath) : undefined,\r\n } as PathResolverContext)\r\n : {};\r\n\r\n if (Object.keys(configuredTools).length > 0) {\r\n logger.debug(`Loaded ${Object.keys(configuredTools).length} configured tool(s): ${Object.keys(configuredTools).join(', ')}`);\r\n }\r\n\r\n // Resolve safe variables in instructions (${root}, ${agentDir}, ${tmpDir} - NOT ${env:*})\n const pathContext: PathResolverContext = {\n projectRoot: projectContext?.projectRoot ?? process.cwd(),\n agentDir: agentFilePath ? dirname(agentFilePath) : undefined,\n };\n const resolvedInstructions = resolvePromptVariables(agent.instructions, pathContext);\n\r\n // Resolve [[agent]] and [[[skill]]] wikilink references\r\n const { resolveReferences } = await import('../references.js');\r\n const existingSubagentNames = (agent.config.subagents ?? []).map(sa =>\r\n sa.name ?? sa.path.split('/').pop()?.replace(/\\.pk-agent$/, '') ?? ''\r\n );\r\n const { text: finalInstructions, discoveredAgents } = await resolveReferences(resolvedInstructions, {\r\n agentDir: agentFilePath ? dirname(agentFilePath) : undefined,\r\n projectRoot: projectContext?.projectRoot,\r\n existingSubagents: existingSubagentNames,\r\n });\r\n\r\n // Precedence: CLI > Agent YAML > Default\r\n const maxSteps = resolveMaxSteps(cliMaxSteps, agent.config.maxSteps);\r\n\r\n // Create doom loop detector to catch agents stuck in repetitive tool calls\r\n const doomLoopDetector = new DoomLoopDetector({ threshold: 3, action: 'error' });\r\n\n logger.debug(`Running agent with model: ${agent.config.model}`);\n\n const systemMessages = buildSystemMessages(agent.config.model, false);\n if (agent.config.model.includes('anthropic')) {\n logger.debug(\"Using Anthropic system prompt: You are Claude Code...\");\n }\n\n // Auto-inject AGENTS.md guidance (project + user-level) as an additional system message.\n // Disable with PK_AGENT_AGENTS_MD=0/false/no.\n const agentsMdEnabled = !['0', 'false', 'no'].includes(String(process.env.PK_AGENT_AGENTS_MD ?? '1').toLowerCase());\n if (projectContext && agentsMdEnabled) {\n const guidance = loadAgentsGuidance({\n projectRoot: projectContext.projectRoot,\n homeDir: homedir(),\n enabled: true,\n });\n if (guidance.content) {\n systemMessages.push({ role: 'system', content: guidance.content });\n }\n }\n\n // Run session creation, skill loading, and sub-agent loading in parallel\n // These three tasks are independent of each other (all depend only on agent config)\n logger.debug(`Session manager available: ${!!sessionManager}, Project context available: ${!!projectContext}`);\n\r\n // Prepare sub-agent args upfront (synchronous)\r\n const subAgentBasePath = agentFilePath ? dirname(agentFilePath) : undefined;\r\n if (agentFilePath && verbose && agent.config.subagents?.length) {\r\n logger.debug(`[SubAgent] Agent file path: ${agentFilePath}`);\r\n logger.debug(`[SubAgent] Base path for sub-agents: ${subAgentBasePath}`);\r\n }\r\n\r\n const [sessionResult, skillResult, subAgentResult, mcpToolsResult] = await Promise.allSettled([\r\n // Task 1: Session creation\r\n (async (): Promise<{ sessionID?: string; assistantMsgID?: string }> => {\r\n if (!(sessionManager && projectContext)) return {};\r\n\r\n const agentConfig: {\r\n name: string;\r\n filePath?: string;\r\n description?: string;\r\n isSubAgent: boolean;\r\n } = {\r\n name: agent.name,\r\n isSubAgent: false\r\n };\r\n if (agentFilePath) agentConfig.filePath = agentFilePath;\r\n if (agent.description) agentConfig.description = agent.description;\r\n\r\n const sessionConfig: {\r\n timeout?: number;\r\n maxSteps?: number;\r\n mcpServers?: string[];\r\n subagents?: Array<{ path: string; name?: string }>;\r\n } = {};\r\n if (agent.config.timeout) sessionConfig.timeout = agent.config.timeout;\r\n if (maxSteps) sessionConfig.maxSteps = maxSteps;\r\n if (agent.config.mcpServers) sessionConfig.mcpServers = Object.keys(agent.config.mcpServers);\r\n if (agent.config.subagents) {\r\n sessionConfig.subagents = agent.config.subagents.map(sa => {\r\n const result: { path: string; name?: string } = { path: sa.path };\r\n if (sa.name) result.name = sa.name;\r\n return result;\r\n });\r\n }\r\n\r\n const sid = await sessionManager.createSession({\r\n agent: agentConfig,\r\n model: agent.config.model,\r\n version: packageVersion,\r\n config: sessionConfig,\r\n project: {\r\n root: projectContext.projectRoot,\r\n cwd: projectContext.cwd\r\n }\r\n });\r\n\r\n const msgID = await sessionManager.createMessage(sid, agent.name, {\r\n user: {\r\n prompt: {\r\n task: finalInstructions,\r\n ...(userPrompt && { user: userPrompt })\r\n }\r\n },\r\n assistant: {\r\n system: systemMessages.map(m => m.content),\r\n modelID: agent.config.model,\r\n providerID: agent.config.model.split(':')[0],\r\n mode: 'build',\r\n path: { cwd: projectContext.cwd, root: projectContext.projectRoot },\r\n cost: 0,\r\n tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } }\r\n }\r\n });\r\n\r\n logger.debug(`Session created: ${sid}`);\r\n return { sessionID: sid, assistantMsgID: msgID };\r\n })(),\r\n\r\n // Task 2: Skill tools loading\r\n (async (): Promise<Record<string, ToolSet[string]>> => {\r\n if (!projectContext) return {};\r\n const { skillTool, skillReadTool, skills } = await createSkillTools(projectContext.projectRoot, agent.config.tools);\r\n if (skills.length > 0) {\r\n logger.debug(`Loaded ${skills.length} skill(s): ${skills.map(s => s.name).join(', ')}`);\r\n return {\r\n 'tools__skill_load': skillTool,\r\n 'tools__skill_read': skillReadTool\r\n };\r\n }\r\n return {};\r\n })(),\r\n\r\n // Task 3: Sub-agent tools loading\r\n (async (): Promise<Record<string, ToolSet[string]>> => {\r\n if (!(agent.config.subagents?.length && agent.config.subagents.length > 0)) return {};\r\n const tools = await createSubAgentTools(\r\n agent.config.subagents,\r\n subAgentBasePath,\r\n agent.config.model,\r\n 0,\r\n [],\r\n sessionManager,\r\n undefined, // sessionID not yet available - sub-agents don't depend on parent session\r\n agent.name,\r\n projectContext,\r\n abortSignal\r\n );\r\n if (verbose) {\r\n logger.debug(`[SubAgent] Loaded ${Object.keys(tools).length} sub-agent tool(s)`);\r\n }\r\n return tools;\r\n })(),\r\n\r\n // Task 4: MCP tools - runs concurrently when mcpClientsPromise is provided\r\n // This overlaps MCP server process spawning with session/skill/subagent work\r\n (async (): Promise<Record<string, ToolSet[string]>> => {\r\n const clients = mcpClientsPromise ? await mcpClientsPromise : mcpClients;\r\n return getMCPTools(clients);\r\n })()\r\n ]);\r\n\r\n // Extract results with graceful fallbacks\r\n let sessionID: string | undefined;\r\n let assistantMsgID: string | undefined;\r\n if (sessionResult.status === 'fulfilled') {\r\n sessionID = sessionResult.value.sessionID;\r\n assistantMsgID = sessionResult.value.assistantMsgID;\r\n } else {\r\n logger.warn(`Failed to create session: ${sessionResult.reason?.message ?? sessionResult.reason}`);\r\n if (verbose) {\r\n logger.debug(`Session creation error stack: ${sessionResult.reason?.stack}`);\r\n }\r\n }\r\n\r\n let skillTools: Record<string, ToolSet[string]> = {};\r\n if (skillResult.status === 'fulfilled') {\r\n skillTools = skillResult.value;\r\n } else {\r\n logger.warn(`Failed to load skills: ${skillResult.reason?.message ?? skillResult.reason}`);\r\n }\r\n\r\n let subAgentTools: Record<string, ToolSet[string]> = {};\r\n if (subAgentResult.status === 'fulfilled') {\r\n subAgentTools = subAgentResult.value;\r\n } else {\r\n logger.warn(`Failed to load sub-agent tools: ${subAgentResult.reason?.message ?? subAgentResult.reason}`);\r\n }\r\n\r\n let mcpTools: Record<string, ToolSet[string]> = {};\r\n if (mcpToolsResult.status === 'fulfilled') {\r\n mcpTools = mcpToolsResult.value;\r\n } else {\r\n logger.warn(`Failed to load MCP tools: ${mcpToolsResult.reason?.message ?? mcpToolsResult.reason}`);\r\n }\r\n\r\n // Auto-register agents discovered via [[]] wikilink references\r\n if (discoveredAgents.length > 0) {\r\n try {\r\n const { createSubAgentTools } = await import('../subagent.js');\r\n const autoSubagents = discoveredAgents.map(a => ({ path: a.path, name: a.name }));\r\n const autoTools = await createSubAgentTools(\r\n autoSubagents,\r\n subAgentBasePath,\r\n agent.config.model,\r\n 0,\r\n [],\r\n sessionManager,\r\n undefined,\r\n agent.name,\r\n projectContext,\r\n abortSignal\r\n );\r\n subAgentTools = { ...subAgentTools, ...autoTools };\r\n } catch (error) {\r\n logger.warn(`Failed to auto-register discovered agents: ${(error as Error).message}`);\r\n }\r\n }\r\n\r\n // Merge all tools\n const mergedTools = { ...mcpTools, ...configuredTools, ...skillTools, ...subAgentTools } as Record<string, Tool>;\n\n // Hooks are configured via JSON:\n // - Project: <projectRoot>/.pk-agent/hooks.json\n // - User: ~/.pk-agent/hooks.json\n // Hook runner is always created; it is a no-op unless hooks are configured.\n const hookRunner = createHookRunner(projectContext?.projectRoot ?? process.cwd());\n\n const approvalsEnabled = ['1', 'true', 'yes'].includes(String(process.env.PK_AGENT_APPROVALS ?? '').toLowerCase());\n let approvalMode: 'prompt' | 'allow-all' | 'deny-all' = 'prompt';\n\n const isInteractive = (): boolean => {\n if (process.env.NO_TTY === 'true' || process.env.NO_TTY === '1') return false;\n return Boolean(process.stdin.isTTY && process.stdout.isTTY);\n };\n\n const gatedToolNames = new Set<string>([\n 'tools__bash',\n 'tools__filesystem_write',\n 'tools__filesystem_edit',\n 'tools__fullstack_backend_test',\n 'tools__fullstack_frontend_test',\n 'tools__fullstack_frontend_debug',\n 'tools__fullstack_api_smoke',\n 'tools__fullstack_backend_debug',\n 'tools__fullstack_replace',\n 'tools__fullstack_sqlite_snapshot',\n ]);\n\n const shouldGateTool = (name: string): boolean => gatedToolNames.has(name);\n\n const requestApproval = async (name: string, input: unknown): Promise<boolean> => {\n if (!approvalsEnabled) return true;\n if (!shouldGateTool(name)) return true;\n if (!isInteractive()) {\n return false;\n }\n if (approvalMode === 'allow-all') return true;\n if (approvalMode === 'deny-all') return false;\n\n const redacted = redactObjectDeep(input);\n const preview = (() => {\n try {\n const s = JSON.stringify(redacted, null, 2);\n return s.length > 2000 ? s.slice(0, 2000) + '\\n...(truncated)' : s;\n } catch {\n return String(redacted);\n }\n })();\n\n logger.warn(`\\nTOOL APPROVAL REQUIRED\\nTool: ${name}\\nInput (redacted):\\n${preview}\\n`);\n const answer = await prompt('[y]es / [n]o / [a]llow all / [d]eny all: ');\n if (answer === 'a' || answer === 'all' || answer === 'allow all') {\n approvalMode = 'allow-all';\n return true;\n }\n if (answer === 'd' || answer === 'deny' || answer === 'deny all') {\n approvalMode = 'deny-all';\n return false;\n }\n if (answer === 'y' || answer === 'yes') return true;\n return false;\n };\n\n // Wrap tools to emit tool:start/tool:end hooks (context is redacted).\n const wrapTool = (name: string, tool: Tool): Tool => {\n const originalExecute = tool.execute;\n if (!originalExecute) {\n return tool;\n }\n return {\n ...tool,\n execute: async (input: any, execOpts: any) => {\n const runId = sessionID || String(Date.now());\n const baseCtx = {\n runId,\n agent: {\n name: agent.name,\n model: agent.config.model,\n ...(agentFilePath && { filePath: agentFilePath }),\n isSubAgent: false,\n },\n project: {\n projectRoot: projectContext?.projectRoot ?? process.cwd(),\n cwd: process.cwd(),\n },\n };\n\n const start = Date.now();\n await hookRunner.run('tool:start', {\n ...baseCtx,\n tool: { name, input },\n } as any);\n\n try {\n const allowed = await requestApproval(name, input);\n if (!allowed) {\n const denied = JSON.stringify({\n success: false,\n error: {\n type: 'approval_denied',\n message: `Tool execution denied by user: ${name}`,\n retryable: false,\n }\n });\n const durationMs = Date.now() - start;\n await hookRunner.run('tool:end', {\n ...baseCtx,\n tool: { name, input, output: denied, success: false, durationMs },\n error: { message: 'approval denied' },\n } as any);\n return { output: denied, metadata: { denied: true } } as any;\n }\n\n const result: any = await originalExecute(input, execOpts);\n const durationMs = Date.now() - start;\n const outputText = typeof result?.output === 'string' ? result.output : undefined;\n await hookRunner.run('tool:end', {\n ...baseCtx,\n tool: { name, input, output: outputText, success: true, durationMs },\n } as any);\n return result;\n } catch (err: any) {\n const durationMs = Date.now() - start;\n await hookRunner.run('tool:end', {\n ...baseCtx,\n tool: { name, input, success: false, durationMs },\n error: { message: err?.message ?? String(err) },\n } as any);\n throw err;\n }\n },\n };\n };\n\n const tools = Object.fromEntries(\n Object.entries(mergedTools).map(([name, tool]) => [name, wrapTool(name, tool)])\n ) as ToolSet;\n\r\n if (Object.keys(tools).length > 0) {\r\n logger.debug(`Available tools: ${Object.keys(tools).join(', ')}`);\r\n }\r\n\r\n // Log step limit if it's non-default or in verbose mode\r\n if (maxSteps !== DEFAULT_MAX_STEPS || verbose) {\r\n logger.debug(`Max steps: ${maxSteps} (override via MAX_STEPS env var)`);\r\n }\r\n\r\n // Track subagent names for logging\r\n const subAgentNames = new Set(Object.keys(subAgentTools));\r\n\r\n // Build user message by concatenating task and user prompts\r\n const userMessageTextRaw = userPrompt\n ? `${finalInstructions}\\n\\n${userPrompt}`\n : finalInstructions;\n const userMessageText = resolvePromptVariables(userMessageTextRaw, pathContext);\n\r\n let userMessage: UserMessageContent = userMessageText;\r\n\r\n // Optional PDF attachments for OpenAI models (supports local paths, URLs, and OpenAI file IDs).\n if (agent.config.files && agent.config.files.length > 0) {\n const provider = agent.config.model.split(':')[0] || 'openai';\n const baseDir = agentFilePath ? dirname(agentFilePath) : undefined;\n const fileParts = await resolveFileAttachments(agent.config.files, baseDir, provider);\n\n // Place file(s) before the text prompt, mirroring OpenAI examples (file then question).\n userMessage = [...fileParts, { type: 'text', text: userMessageText }];\n }\n\r\n return {\n tools,\n systemMessages,\n userMessage,\n maxSteps,\n subAgentNames,\n sessionID,\n assistantMsgID,\n doomLoopDetector,\n hookRunner,\n runId: sessionID\n };\n}\n",
|
|
72
|
+
"import type { ParsedAgent } from '../parser';\nimport type { MCPConnection } from '../mcp';\nimport type { SessionManager } from '../session';\nimport { saveSnapshot, pruneSnapshots } from '../session/conversation-snapshot';\nimport type { ConversationSnapshot } from '../session/conversation-snapshot';\nimport { AuthenticationError } from '../models';\nimport { logger } from '../utils/logger';\nimport { sanitizeAgentName } from '../utils/names';\nimport { executeAgentCore } from './execution';\nimport { prepareAgentExecution } from './preparation';\nimport { processAgentStream } from './stream';\nimport type { PreparedAgentExecution, RunAgentResult } from './types';\n\n/**\n * Run an agent with AI and MCP tools\n * @param agent Parsed agent configuration\n * @param mcpClients Connected MCP clients\n * @param debug Enable debug logging\n * @param abortSignal Optional abort signal for cancellation\n * @param startTime Optional start time for timing\n * @param verbose Enable verbose logging\n * @param agentFilePath Optional path to the agent file for resolving sub-agent paths\n * @param cliMaxSteps Optional CLI override for max steps\n */\nexport async function runAgent(\n agent: ParsedAgent,\n mcpClients: MCPConnection[],\n _debug: boolean = false,\n abortSignal?: AbortSignal,\n startTime?: number,\n verbose: boolean = false,\n agentFilePath?: string,\n cliMaxSteps?: number,\n sessionManager?: SessionManager,\n projectContext?: { projectRoot: string; cwd: string },\n userPrompt?: string,\n /**\n * Optional pre-computed execution context to avoid duplicate preparation work.\n *\n * **When to provide this:**\n * - CLI flows that need to display metadata (tool count, session ID) before running\n * - Contexts where agent setup needs inspection before execution\n *\n * **When to omit this:**\n * - Direct API usage where metadata inspection isn't needed\n * - Test contexts where simpler call signatures are preferred\n * - Any scenario where duplicate preparation overhead is acceptable\n *\n * **Performance benefit:**\n * Preparation involves MCP tool discovery, plugin loading, and session setup.\n * Pre-computing allows the caller to inspect this context (e.g., for UI display)\n * and then reuse it for execution, avoiding duplicate expensive operations.\n */\n preparedExecution?: PreparedAgentExecution,\n /** Suppress console output (for serve mode) */\n quiet: boolean = false,\n /** R3-3: Resume snapshot to restore conversation state */\n resumeSnapshot?: ConversationSnapshot\n): Promise<RunAgentResult> {\n // Track session info for error logging (set during preparation)\n let sessionID: string | undefined;\n let agentName: string | undefined;\n\n try {\n // Log initialization time if verbose\n if (verbose && startTime) {\n const initTime = Date.now() - startTime;\n logger.info(`Initialization completed in ${initTime}ms`);\n }\n\n // Use shared preparation logic (allow caller to precompute to avoid duplicate work)\n // If preparedExecution is provided, use it directly (CLI path).\n // If not provided, compute it fresh (API/test path).\n const preparation = preparedExecution ?? await prepareAgentExecution({\n agent,\n mcpClients,\n agentFilePath,\n cliMaxSteps,\n sessionManager,\n projectContext,\n userPrompt,\n abortSignal,\n verbose\n });\n\n const {\n tools,\n systemMessages,\n userMessage,\n maxSteps,\n subAgentNames,\n sessionID: prepSessionID,\n assistantMsgID,\n doomLoopDetector,\n hookRunner,\n runId\n } = preparation;\n\n // Set outer scope variables for error logging\n sessionID = prepSessionID;\n agentName = agent.name;\n\n const effectiveRunId = runId || prepSessionID || String(Date.now());\n if (hookRunner?.enabled) {\n await hookRunner.run('run:start', {\n runId: effectiveRunId,\n agent: {\n name: agent.name,\n model: agent.config.model,\n ...(agentFilePath && { filePath: agentFilePath }),\n isSubAgent: false,\n },\n project: {\n projectRoot: projectContext?.projectRoot ?? process.cwd(),\n cwd: process.cwd(),\n },\n } as any);\n }\n\n // R3-3: Fire-and-forget prune of old snapshots on startup\n if (sessionManager) {\n pruneSnapshots().catch(() => { });\n }\n\n // R3-3: Build session dir for snapshot storage\n const sanitizedName = sanitizeAgentName(agent.name);\n const sessionDir = prepSessionID ? `${prepSessionID}-${sanitizedName}` : undefined;\n\n // R3-3: Snapshot save callback for auto-save after each step\n const onSnapshotSave = sessionDir ? (state: ReturnType<import('../context-manager').ContextManager['exportState']>) => {\n const snapshot: ConversationSnapshot = {\n sessionID: prepSessionID!,\n agentFile: agentFilePath || '',\n agentName: agent.name,\n model: agent.config.model,\n messages: state.messages,\n compactionCount: state.compactionCount,\n tokenBudget: { used: state.totalTokensUsed, limit: state.contextLimit },\n messageCount: state.messages.length,\n timestamp: Date.now(),\n version: '0.0.0', // Will be replaced with actual version\n };\n saveSnapshot(sessionDir!, snapshot).catch(() => { });\n } : undefined;\n\n // Execute using the core generator\n const coreOptions = {\n userMessage,\n systemMessages,\n maxSteps,\n subAgentNames,\n ...(abortSignal && { abortSignal }),\n ...(onSnapshotSave && { onSnapshotSave }),\n ...(resumeSnapshot && {\n resumeMessages: resumeSnapshot.messages,\n resumeCompactionCount: resumeSnapshot.compactionCount,\n }),\n };\n\n const result = await processAgentStream(\n executeAgentCore(agent, tools, coreOptions),\n sessionManager && prepSessionID && assistantMsgID ? {\n collectToolCalls: true,\n sessionManager,\n sessionID: prepSessionID,\n messageID: assistantMsgID,\n agentName: agent.name,\n doomLoopDetector,\n quiet\n } : {\n collectToolCalls: true,\n doomLoopDetector,\n quiet\n }\n );\n\n logger.debug(`Agent finish reasons: ${result.finishReasons?.join(', ') ?? 'none'}`);\n logger.debug(`Agent produced text output: ${result.hasTextOutput}`);\n\n // Display execution summary\n const mainTokens = result.usage?.totalTokens || 0;\n const subTokens = result.subAgentTokens || 0;\n const totalTokens = mainTokens + subTokens;\n const durationMs = startTime ? Date.now() - startTime : 0;\n const toolCallCount = result.toolCalls?.length || 0;\n\n if (!quiet) {\n logger.separator();\n logger.summary({\n success: true,\n durationMs,\n ...(totalTokens > 0 && { tokensUsed: totalTokens }),\n ...(toolCallCount > 0 && { toolCallCount }),\n });\n }\n\n // Update session message with final token usage\n if (sessionManager && prepSessionID && assistantMsgID && result.usage) {\n try {\n await sessionManager.updateMessage(prepSessionID, agent.name, assistantMsgID, {\n time: { completed: Date.now() },\n assistant: {\n tokens: {\n input: result.usage.inputTokens || 0,\n output: result.usage.outputTokens || 0\n }\n }\n });\n } catch (error) {\n logger.debug(`Failed to update message with token usage: ${(error as Error).message}`);\n }\n }\n\n // Return metrics for plugin system\n const finalResult: RunAgentResult = {\n text: result.text,\n ...(result.usage && { usage: result.usage }),\n toolCallCount: result.toolCalls?.length || 0,\n ...(result.toolCallTraces && { toolCallTraces: result.toolCallTraces }),\n ...(result.finishReason && { finishReason: result.finishReason }),\n ...(result.finishReasons && { finishReasons: result.finishReasons }),\n hasTextOutput: result.hasTextOutput\n };\n\n if (hookRunner?.enabled) {\n await hookRunner.run('run:end', {\n runId: effectiveRunId,\n agent: {\n name: agent.name,\n model: agent.config.model,\n ...(agentFilePath && { filePath: agentFilePath }),\n isSubAgent: false,\n },\n project: {\n projectRoot: projectContext?.projectRoot ?? process.cwd(),\n cwd: process.cwd(),\n },\n } as any);\n }\n\n return finalResult;\n } catch (error: unknown) {\n // Best-effort: emit run:end hook on failure.\n try {\n const preparation = preparedExecution;\n const hookRunner = preparation?.hookRunner;\n const effectiveRunId = preparation?.runId || sessionID || String(Date.now());\n if (hookRunner?.enabled) {\n await hookRunner.run('run:end', {\n runId: effectiveRunId,\n agent: {\n name: agent.name,\n model: agent.config.model,\n ...(agentFilePath && { filePath: agentFilePath }),\n isSubAgent: false,\n },\n project: {\n projectRoot: projectContext?.projectRoot ?? process.cwd(),\n cwd: process.cwd(),\n },\n error: { message: error instanceof Error ? error.message : String(error) },\n } as any);\n }\n } catch {\n // ignore hook failures\n }\n\n // Log error to session if available (for visibility in `pk-agent sessions`)\n if (sessionManager && sessionID && agentName) {\n try {\n const errorCode = error instanceof AuthenticationError ? 'AUTH_ERROR' :\n (error instanceof Error && error.name === 'AbortError') ? 'TIMEOUT' :\n 'EXECUTION_ERROR';\n const errorMessage = error instanceof Error ? error.message : String(error);\n await sessionManager.setSessionError(sessionID, agentName, {\n code: errorCode,\n message: errorMessage\n });\n } catch {\n // Ignore error logging failures\n }\n }\n\n // Check if it's an abort error from timeout\n if ((error instanceof Error && error.name === 'AbortError') || (abortSignal && abortSignal.aborted)) {\n // Timeout already handled by caller\n throw error;\n }\n logger.error('Agent execution failed', error as Error);\n throw error;\n } finally {\n // Clean up MCP clients (like opencode does)\n for (const connection of mcpClients) {\n try {\n await connection.client.close();\n if (connection.rawClient) {\n await connection.rawClient.close();\n }\n logger.debug(`Closed MCP client: ${connection.name}`);\n } catch (error) {\n // Ignore errors when closing MCP clients\n }\n }\n }\n}\n",
|
|
73
|
+
"export { SessionManager } from './manager';\nexport type * from './types';\nexport { saveSnapshot, loadSnapshot, listSnapshots, findLatestSnapshot, pruneSnapshots } from './conversation-snapshot';\nexport type { ConversationSnapshot, SessionSummary } from './conversation-snapshot';\n",
|
|
74
|
+
"#!/usr/bin/env bun\r\nimport { Command } from 'commander';\r\nimport chalk from 'chalk';\r\nimport { createAuthCommand } from './cli/auth';\r\nimport { createSessionsCommand } from './cli/sessions';\r\nimport { createServeCommand } from './cli/serve';\r\nimport { createModelsCommand } from './cli/models';\r\nimport { createSkillsCommand } from './cli/skills';\r\nimport { createBenchmarkCommand } from './cli/benchmark';\nimport { createAgentsCommand } from './cli/agents';\nimport { createAddCommand } from './cli/add';\nimport { createCreateCommand } from './cli/create';\nimport { createRunCommand } from './cli/run';\nimport { createLintCommand } from './cli/lint';\nimport { createConfigCommand } from './cli/config';\nimport { createTestCommand } from './cli/test';\nimport { runInternalWorker } from './cli/worker';\nimport { getVersionString } from './utils/cli-helpers';\nimport { ensurePkAgentProjectDirs, ensurePkAgentUserDirs } from './utils/pk-agent-dirs';\n\r\nconst version = getVersionString();\r\n\r\nconst program = new Command();\n\n// Ensure pk-agent's expected config directories exist (USER first, PROJECT second).\n// Best-effort: avoid blocking the CLI if a directory cannot be created.\ntry {\n ensurePkAgentUserDirs();\n // \"Project\" is the directory pk-agent is run from (cwd).\n ensurePkAgentProjectDirs(process.cwd());\n} catch {\n // ignore\n}\n\nprogram\n .name('pk-agent')\n .description('Run AI agents from natural language markdown files')\n .version(version)\r\n .showHelpAfterError('(add --help for additional information)')\r\n .addHelpText('beforeAll', () => {\r\n const title = chalk.cyanBright.bold('PK-AGENT') + chalk.gray(` v${version}`);\r\n const divider = chalk.yellowBright('='.repeat(44));\r\n return `\\n${divider}\\n${title}\\n${chalk.gray('Autonomous agents from markdown')}\\n${divider}\\n`;\r\n })\r\n .addHelpText('afterAll', () => {\r\n return [\r\n '',\r\n 'Examples:',\r\n ' pk-agent run agents/example.pk-agent',\r\n ' pk-agent run --audit agents/example.pk-agent',\r\n ' pk-agent auth login openai',\r\n ' pk-agent skills list',\r\n '',\r\n 'Tip: Use --audit (or PK_AGENT_AUDIT=1) to stream tool I/O for real-time auditing.',\r\n '',\r\n ].join('\\n');\r\n })\r\n .configureOutput({\r\n outputError: (str, write) => {\r\n // For missing required arguments, show help instead of just error\r\n if (str.includes('missing required argument')) {\r\n program.outputHelp();\r\n write('\\n' + str);\r\n } else {\r\n write(str);\r\n }\r\n }\r\n });\r\n\r\n// Add all commands\r\nprogram.addCommand(createAuthCommand());\r\nprogram.addCommand(createSessionsCommand());\r\nprogram.addCommand(createServeCommand());\r\nprogram.addCommand(createModelsCommand());\r\nprogram.addCommand(createSkillsCommand());\r\nprogram.addCommand(createAgentsCommand());\r\nprogram.addCommand(createAddCommand());\nprogram.addCommand(createCreateCommand());\nprogram.addCommand(createRunCommand());\nprogram.addCommand(createLintCommand());\nprogram.addCommand(createConfigCommand());\nprogram.addCommand(createTestCommand());\nprogram.addCommand(createBenchmarkCommand(), { hidden: true });\n\r\n// Handle internal worker mode (used by serve command)\r\n// This must be checked before program.parse() to avoid Commander processing\r\nif (process.argv[2] === '--internal-worker') {\r\n runInternalWorker();\r\n} else {\r\n // Parse command line arguments\r\n program.parse(process.argv);\r\n\r\n // Show help if no command provided\r\n if (!process.argv.slice(2).length) {\r\n program.outputHelp();\r\n }\r\n}\r\n",
|
|
75
|
+
"import { Command } from \"commander\";\r\nimport { AnthropicAuth, AuthStorage, CodexAuth } from \"../auth/index.js\";\r\nimport readline from \"readline\";\r\nimport { logger } from \"../utils/logger\";\r\nimport { openUrl } from \"../utils/open-url.js\";\r\n\r\nfunction createReadlineInterface() {\r\n return readline.createInterface({\r\n input: process.stdin,\r\n output: process.stdout,\r\n });\r\n}\r\n\r\nasync function promptInput(question: string): Promise<string> {\r\n const rl = createReadlineInterface();\r\n return new Promise((resolve, reject) => {\r\n rl.on('SIGINT', () => {\r\n rl.close();\r\n reject(new Error('Interrupted'));\r\n });\r\n\r\n rl.question(question, (answer) => {\r\n rl.close();\r\n resolve(answer.trim());\r\n });\r\n });\r\n}\r\n\r\n\r\nexport function createAuthCommand(): Command {\r\n const authCmd = new Command(\"auth\")\r\n .description(\"Manage authentication credentials\");\r\n\r\n authCmd\r\n .command(\"help\")\r\n .description(\"Show authentication help and configuration options\")\r\n .action(() => {\r\n process.stdout.write(\" PK Agent Authentication Help\\n\");\r\n process.stdout.write(`${\"=\".repeat(60)}\\n\\n`);\r\n\r\n process.stdout.write(\"AUTHENTICATION METHODS:\\n\");\r\n process.stdout.write(\"-\".repeat(40) + \"\\n\");\r\n process.stdout.write(\"1. Login Command (Recommended):\\n\");\r\n process.stdout.write(\" pk-agent auth login\\n\\n\");\r\n\r\n process.stdout.write(\"2. Environment Variables:\\n\");\r\n process.stdout.write(\" Set API keys directly in your environment:\\n\");\r\n process.stdout.write(\" * ANTHROPIC_API_KEY - For Anthropic Claude models\\n\");\r\n process.stdout.write(\" * OPENAI_API_KEY - For OpenAI GPT models\\n\");\r\n process.stdout.write(\" * OPENROUTER_API_KEY - For OpenRouter (multiple models)\\n\\n\");\r\n\r\n process.stdout.write(\"ENVIRONMENT VARIABLE SETUP:\\n\");\r\n process.stdout.write(\"-\".repeat(40) + \"\\n\");\r\n process.stdout.write(\"Bash/Zsh (~/.bashrc or ~/.zshrc):\\n\");\r\n process.stdout.write(\" export ANTHROPIC_API_KEY=\\\"your-api-key\\\"\\n\");\r\n process.stdout.write(\" export OPENAI_API_KEY=\\\"your-api-key\\\"\\n\");\r\n process.stdout.write(\" export OPENROUTER_API_KEY=\\\"your-api-key\\\"\\n\\n\");\r\n\r\n process.stdout.write(\"Fish (~/.config/fish/config.fish):\\n\");\r\n process.stdout.write(\" set -x ANTHROPIC_API_KEY \\\"your-api-key\\\"\\n\");\r\n process.stdout.write(\" set -x OPENAI_API_KEY \\\"your-api-key\\\"\\n\");\r\n process.stdout.write(\" set -x OPENROUTER_API_KEY \\\"your-api-key\\\"\\n\\n\");\r\n\r\n process.stdout.write(\"Windows (PowerShell):\\n\");\r\n process.stdout.write(\" $env:ANTHROPIC_API_KEY=\\\"your-api-key\\\"\\n\");\r\n process.stdout.write(\" $env:OPENAI_API_KEY=\\\"your-api-key\\\"\\n\");\r\n process.stdout.write(\" $env:OPENROUTER_API_KEY=\\\"your-api-key\\\"\\n\\n\");\r\n\r\n process.stdout.write(\"Windows (Command Prompt):\\n\");\r\n process.stdout.write(\" set ANTHROPIC_API_KEY=your-api-key\\n\");\r\n process.stdout.write(\" set OPENAI_API_KEY=your-api-key\\n\");\r\n process.stdout.write(\" set OPENROUTER_API_KEY=your-api-key\\n\\n\");\r\n\r\n process.stdout.write(\"PRIORITY ORDER:\\n\");\r\n process.stdout.write(\"-\".repeat(40) + \"\\n\");\r\n process.stdout.write(\"1. OAuth tokens (Anthropic OAuth or OpenAI Codex OAuth)\\n\");\r\n process.stdout.write(\"2. Stored API keys (via auth login)\\n\");\r\n process.stdout.write(\"3. Environment variables\\n\\n\");\r\n\r\n process.stdout.write(\"COMMANDS:\\n\");\r\n process.stdout.write(\"-\".repeat(40) + \"\\n\");\r\n process.stdout.write(\" auth login [provider] - Store API credentials\\n\");\r\n process.stdout.write(\" auth logout [provider] - Remove stored credentials\\n\");\r\n process.stdout.write(\" auth list - Show stored credentials\\n\");\r\n process.stdout.write(\" auth help - Show this help message\\n\\n\");\r\n\r\n process.stdout.write(\"GETTING API KEYS:\\n\");\r\n process.stdout.write(\"-\".repeat(40) + \"\\n\");\r\n process.stdout.write(\"* Anthropic: https://console.anthropic.com/account/keys\\n\");\r\n process.stdout.write(\"* OpenAI: https://platform.openai.com/api-keys\\n\");\r\n process.stdout.write(\"* OpenRouter: https://openrouter.ai/keys\\n\");\r\n });\r\n\r\n authCmd\r\n .command(\"login\")\r\n .description(\"Login to a provider\")\r\n .argument(\"[provider]\", \"Provider to login to\")\r\n .action(async (provider?: string) => {\r\n try {\r\n process.stdout.write(\" PK Agent Authentication\\n\\n\");\r\n\r\n if (!provider) {\r\n process.stdout.write(\"Available providers:\\n\");\r\n process.stdout.write(\" 1. anthropic - Anthropic Claude (supports OAuth for Claude Max)\\n\");\r\n process.stdout.write(\" 2. openai - OpenAI GPT models\\n\");\r\n process.stdout.write(\" 3. openrouter - OpenRouter (access to multiple models)\\n\");\r\n process.stdout.write(\"\\n\");\r\n\r\n const selection = await promptInput(\"Select provider (1-3 or name): \");\r\n\r\n // Handle numbered selection\r\n switch (selection) {\r\n case \"1\":\r\n provider = \"anthropic\";\r\n break;\r\n case \"2\":\r\n provider = \"openai\";\r\n break;\r\n case \"3\":\r\n provider = \"openrouter\";\r\n break;\r\n default:\r\n provider = selection;\r\n }\r\n }\r\n\r\n switch (provider.toLowerCase()) {\r\n case \"anthropic\":\r\n await handleAnthropicLogin();\r\n break;\r\n case \"openai\":\r\n await handleOpenAILogin();\r\n break;\r\n case \"openrouter\":\r\n await handleGenericLogin(\"openrouter\", \"OpenRouter API Key\");\r\n break;\r\n default:\r\n logger.warn(`Unknown provider: ${provider}`);\r\n process.exit(1);\r\n }\r\n } catch (error) {\r\n logger.error(\"Login failed\", error as Error);\r\n process.exit(1);\r\n }\r\n });\r\n\r\n authCmd\r\n .command(\"logout\")\r\n .description(\"Logout from a provider\")\r\n .argument(\"[provider]\", \"Provider to logout from\")\r\n .option(\"--oauth\", \"Remove only OAuth credentials\")\r\n .option(\"--api\", \"Remove only API key credentials\")\r\n .action(async (provider?: string, options?: { oauth?: boolean; api?: boolean }) => {\r\n const knownProviders = [\"anthropic\", \"openai\", \"openrouter\"];\r\n\r\n // Build list of stored credentials\r\n const storedList: { provider: string; type: string; key: string }[] = [];\r\n for (const p of knownProviders) {\r\n const providerAuth = await AuthStorage.getProviderAuth(p);\r\n if (providerAuth.oauth) {\r\n storedList.push({\r\n provider: p,\r\n type: providerAuth.oauth.type === \"codex-oauth\" ? \"ChatGPT OAuth\" : \"OAuth\",\r\n key: `${p}:oauth`,\r\n });\r\n }\r\n if (providerAuth.api) {\r\n storedList.push({\r\n provider: p,\r\n type: \"API key\",\r\n key: `${p}:api`,\r\n });\r\n }\r\n }\r\n\r\n if (storedList.length === 0) {\r\n logger.warn(\"No stored credentials found\");\r\n return;\r\n }\r\n\r\n if (!provider) {\r\n process.stdout.write(\"Stored credentials:\\n\");\r\n storedList.forEach((item, i) => {\r\n process.stdout.write(` ${i + 1}. ${item.provider} (${item.type})\\n`);\r\n });\r\n process.stdout.write(\"\\n\");\r\n\r\n const selection = await promptInput(\"Select credential to remove: \");\r\n const index = parseInt(selection) - 1;\r\n\r\n if (index >= 0 && index < storedList.length) {\r\n const item = storedList[index];\r\n if (item.key.endsWith(\":oauth\")) {\r\n await AuthStorage.removeOAuth(item.provider);\r\n } else {\r\n await AuthStorage.removeApiKey(item.provider);\r\n }\r\n process.stdout.write(`[OK] Removed ${item.type} from ${item.provider}\\n`);\r\n return;\r\n } else {\r\n provider = selection;\r\n }\r\n }\r\n\r\n // Handle provider-specific logout\r\n const providerAuth = await AuthStorage.getProviderAuth(provider);\r\n const hasOAuth = !!providerAuth.oauth;\r\n const hasApiKey = !!providerAuth.api;\r\n\r\n if (!hasOAuth && !hasApiKey) {\r\n logger.warn(`No credentials found for ${provider}`);\r\n return;\r\n }\r\n\r\n // If specific flag is set, remove only that type\r\n if (options?.oauth) {\r\n if (hasOAuth) {\r\n await AuthStorage.removeOAuth(provider);\r\n process.stdout.write(`[OK] Removed OAuth from ${provider}\\n`);\r\n } else {\r\n logger.warn(`No OAuth credentials found for ${provider}`);\r\n }\r\n return;\r\n }\r\n\r\n if (options?.api) {\r\n if (hasApiKey) {\r\n await AuthStorage.removeApiKey(provider);\r\n process.stdout.write(`[OK] Removed API key from ${provider}\\n`);\r\n } else {\r\n logger.warn(`No API key found for ${provider}`);\r\n }\r\n return;\r\n }\r\n\r\n // If both exist, ask which to remove\r\n if (hasOAuth && hasApiKey) {\r\n process.stdout.write(`${provider} has both OAuth and API key configured:\\n`);\r\n process.stdout.write(\" 1. OAuth\\n\");\r\n process.stdout.write(\" 2. API key\\n\");\r\n process.stdout.write(\" 3. Both\\n\\n\");\r\n\r\n const selection = await promptInput(\"Select what to remove (1-3): \");\r\n\r\n switch (selection) {\r\n case \"1\":\r\n await AuthStorage.removeOAuth(provider);\r\n process.stdout.write(`[OK] Removed OAuth from ${provider}\\n`);\r\n break;\r\n case \"2\":\r\n await AuthStorage.removeApiKey(provider);\r\n process.stdout.write(`[OK] Removed API key from ${provider}\\n`);\r\n break;\r\n case \"3\":\r\n await AuthStorage.removeOAuth(provider);\r\n await AuthStorage.removeApiKey(provider);\r\n process.stdout.write(`[OK] Removed all credentials from ${provider}\\n`);\r\n break;\r\n default:\r\n logger.warn(\"Invalid selection\");\r\n }\r\n } else {\r\n // Only one type exists, remove it\r\n if (hasOAuth) {\r\n await AuthStorage.removeOAuth(provider);\r\n process.stdout.write(`[OK] Removed OAuth from ${provider}\\n`);\r\n } else {\r\n await AuthStorage.removeApiKey(provider);\r\n process.stdout.write(`[OK] Removed API key from ${provider}\\n`);\r\n }\r\n }\r\n });\r\n\r\n authCmd\r\n .command(\"list\")\r\n .alias(\"ls\")\r\n .description(\"List stored credentials\")\r\n .action(async () => {\r\n const authPath = AuthStorage.getFilePath();\r\n const homedir = process.env.HOME || process.env.USERPROFILE || \"\";\r\n const displayPath = authPath.startsWith(homedir)\r\n ? authPath.replace(homedir, \"~\")\r\n : authPath;\r\n\r\n process.stdout.write(` Credentials stored in: ${displayPath}\\n\\n`);\r\n\r\n // Define providers and their auth sources in priority order\r\n const providers = [\r\n {\r\n name: \"anthropic\",\r\n display: \"Anthropic\",\r\n envVars: [\"CLAUDE_CODE_OAUTH_TOKEN\", \"ANTHROPIC_API_KEY\"],\r\n },\r\n {\r\n name: \"openai\",\r\n display: \"OpenAI\",\r\n envVars: [\"OPENAI_API_KEY\"],\r\n },\r\n {\r\n name: \"openrouter\",\r\n display: \"OpenRouter\",\r\n envVars: [\"OPENROUTER_API_KEY\"],\r\n },\r\n ];\r\n\r\n process.stdout.write(\"Authentication (in priority order):\\n\");\r\n process.stdout.write(\"-\".repeat(50) + \"\\n\\n\");\r\n\r\n for (const provider of providers) {\r\n // Use new getProviderAuth to get both OAuth and API key\r\n const providerAuth = await AuthStorage.getProviderAuth(provider.name);\r\n const sources: { priority: number; source: string; type: string; active: boolean }[] = [];\r\n\r\n // Priority 1: OAuth tokens (stored)\r\n if (providerAuth.oauth) {\r\n sources.push({\r\n priority: 1,\r\n source: providerAuth.oauth.type === \"codex-oauth\" ? \"ChatGPT OAuth\" : \"OAuth\",\r\n type: providerAuth.oauth.type,\r\n active: true,\r\n });\r\n }\r\n\r\n // Priority 1 (Anthropic only): CLAUDE_CODE_OAUTH_TOKEN\r\n if (provider.name === \"anthropic\" && process.env.CLAUDE_CODE_OAUTH_TOKEN) {\r\n // If no stored OAuth, this takes priority\r\n if (!providerAuth.oauth) {\r\n sources.push({\r\n priority: 1,\r\n source: \"CLAUDE_CODE_OAUTH_TOKEN\",\r\n type: \"env\",\r\n active: true,\r\n });\r\n }\r\n }\r\n\r\n // Priority 2: Stored API keys\r\n if (providerAuth.api) {\r\n sources.push({\r\n priority: 2,\r\n source: \"Stored API key\",\r\n type: \"api\",\r\n active: !sources.some(s => s.priority === 1),\r\n });\r\n }\r\n\r\n // Priority 3: Environment variables\r\n for (const envVar of provider.envVars) {\r\n if (envVar === \"CLAUDE_CODE_OAUTH_TOKEN\") continue; // Already handled\r\n if (process.env[envVar]) {\r\n sources.push({\r\n priority: 3,\r\n source: envVar,\r\n type: \"env\",\r\n active: sources.length === 0,\r\n });\r\n }\r\n }\r\n\r\n // Display provider section\r\n if (sources.length > 0) {\r\n process.stdout.write(`${provider.display}:\\n`);\r\n for (const source of sources.sort((a, b) => a.priority - b.priority)) {\r\n const icon = source.type === \"oauth\" || source.type === \"codex-oauth\" ? \"\" : source.type === \"api\" ? \"\" : \"\";\r\n const activeMarker = source.active ? \" <- active\" : \"\";\r\n const priorityLabel = `[${source.priority}]`;\r\n process.stdout.write(` ${priorityLabel} ${icon} ${source.source}${activeMarker}\\n`);\r\n }\r\n process.stdout.write(\"\\n\");\r\n }\r\n }\r\n\r\n // Show providers with no auth configured\r\n const unconfiguredProviders: typeof providers = [];\r\n for (const p of providers) {\r\n const providerAuth = await AuthStorage.getProviderAuth(p.name);\r\n const hasEnv = p.envVars.some(e => process.env[e]);\r\n if (!providerAuth.oauth && !providerAuth.api && !hasEnv) {\r\n unconfiguredProviders.push(p);\r\n }\r\n }\r\n\r\n if (unconfiguredProviders.length > 0) {\r\n process.stdout.write(\"Not configured:\\n\");\r\n for (const p of unconfiguredProviders) {\r\n process.stdout.write(` WARNING ${p.display} - run \\`pk-agent auth login ${p.name}\\`\\n`);\r\n }\r\n process.stdout.write(\"\\n\");\r\n }\r\n\r\n process.stdout.write(\"Priority: [1] OAuth -> [2] Stored API key -> [3] Environment variable\\n\");\r\n });\r\n\r\n authCmd\r\n .command(\"setup-github\")\r\n .description(\"Set up long-lived OAuth token for GitHub Actions (1 year validity)\")\r\n .option(\"--repo <repo>\", \"GitHub repository (owner/repo) - auto-detected from git if not specified\")\r\n .action(async (options: { repo?: string }) => {\r\n const { execSync } = await import(\"child_process\");\r\n\r\n // Auto-detect repo from git remote if not specified\r\n if (!options.repo) {\r\n try {\r\n const remoteUrl = execSync(\"git remote get-url origin\", { encoding: \"utf-8\", stdio: [\"pipe\", \"pipe\", \"ignore\"] }).trim();\r\n // Parse GitHub URL: git@github.com:owner/repo.git or https://github.com/owner/repo.git\r\n const match = remoteUrl.match(/github\\.com[:/]([^/]+\\/[^/.]+)/);\r\n if (match) {\r\n options.repo = match[1];\r\n process.stdout.write(` Auto-detected repository: ${options.repo}\\n\\n`);\r\n }\r\n } catch {\r\n // Not a git repo or no remote\r\n }\r\n }\r\n\r\n if (!options.repo) {\r\n logger.error(\"Could not detect repository. Specify --repo owner/repo\");\r\n process.stdout.write(\"\\nUsage:\\n\");\r\n process.stdout.write(\" pk-agent auth setup-github # Auto-detect from git\\n\");\r\n process.stdout.write(\" pk-agent auth setup-github --repo owner/repo # Specify repo\\n\");\r\n process.exit(1);\r\n }\r\n\r\n // Check prerequisites\r\n try {\r\n execSync(\"gh --version\", { stdio: \"ignore\" });\r\n } catch {\r\n logger.error(\"GitHub CLI (gh) is not installed. Run: brew install gh\");\r\n process.exit(1);\r\n }\r\n\r\n try {\r\n execSync(\"gh auth status\", { stdio: \"ignore\" });\r\n } catch {\r\n logger.error(\"Not authenticated with gh. Run: gh auth login\");\r\n process.exit(1);\r\n }\r\n\r\n // Check if we have secrets:write permission by trying to list secrets\r\n try {\r\n execSync(`gh secret list --repo ${options.repo}`, { stdio: \"ignore\" });\r\n } catch {\r\n logger.error(`Cannot access secrets for ${options.repo}`);\r\n process.stdout.write(\"\\nYou need a PAT with 'secrets:write' permission.\\n\");\r\n process.stdout.write(\"Set it with: export GH_TOKEN=your_pat_here\\n\");\r\n process.stdout.write(\"\\nOr create one at:\\n\");\r\n process.stdout.write(\" GitHub -> Settings -> Developer settings -> Personal access tokens -> Fine-grained tokens\\n\");\r\n process.stdout.write(\" Permissions: Secrets (Read and write)\\n\");\r\n process.exit(1);\r\n }\r\n\r\n process.stdout.write(\" Setting up OAuth for GitHub Actions\\n\\n\");\r\n process.stdout.write(`Repository: ${options.repo}\\n\\n`);\r\n process.stdout.write(\"This uses a long-lived token (1 year) - no refresh needed!\\n\\n\");\r\n\r\n process.stdout.write(`${\"=\".repeat(60)}\\n`);\r\n process.stdout.write(\" Step 1: Generate a long-lived token\\n\");\r\n process.stdout.write(`${\"=\".repeat(60)}\\n\\n`);\r\n process.stdout.write(\"Run this command in Claude Code CLI:\\n\\n\");\r\n process.stdout.write(\" claude setup-token\\n\\n\");\r\n process.stdout.write(\"This will give you an OAuth token valid for 1 year.\\n\\n\");\r\n\r\n const token = await promptInput(\" Paste the OAuth token here: \");\r\n\r\n if (!token || token.length === 0) {\r\n logger.warn(\"No token provided\");\r\n return;\r\n }\r\n\r\n // Basic validation - Claude tokens typically start with specific patterns\r\n if (token.length < 20) {\r\n logger.warn(\"Token seems too short. Make sure you copied the full token.\");\r\n return;\r\n }\r\n\r\n // Upload to GitHub secrets\r\n process.stdout.write(\"\\n Uploading token to GitHub secrets...\\n\");\r\n\r\n try {\r\n execSync(`echo \"${token}\" | gh secret set CLAUDE_CODE_OAUTH_TOKEN --repo ${options.repo}`, {\r\n stdio: \"pipe\",\r\n });\r\n\r\n process.stdout.write(\"\\n[OK] GitHub Actions setup complete!\\n\\n\");\r\n process.stdout.write(\"Secret created:\\n\");\r\n process.stdout.write(\" * CLAUDE_CODE_OAUTH_TOKEN (valid for 1 year)\\n\\n\");\r\n process.stdout.write(\"No SECRETS_ADMIN_PAT needed - this token doesn't require refresh!\\n\");\r\n } catch {\r\n logger.error(\"Failed to upload secret\");\r\n process.exit(1);\r\n }\r\n });\r\n\r\n authCmd\r\n .command(\"import-codex\")\r\n .description(\"Import credentials from an existing OpenAI Codex CLI installation\")\r\n .action(async () => {\r\n process.stdout.write(\" Importing credentials from Codex CLI...\\n\\n\");\r\n\r\n const result = await CodexAuth.importFromCodexCli();\r\n\r\n if (result.success) {\r\n process.stdout.write(\"[OK] Successfully imported Codex CLI credentials!\\n\");\r\n if (result.accountId) {\r\n process.stdout.write(` Account ID: ${result.accountId}\\n`);\r\n }\r\n process.stdout.write(\"\\nYou can now use ChatGPT OAuth with pk-agent.\\n\");\r\n } else {\r\n logger.error(result.error || \"Import failed\");\r\n process.stdout.write(\"\\nTo install Codex CLI and login:\\n\");\r\n process.stdout.write(\" npm install -g @openai/codex\\n\");\r\n process.stdout.write(\" codex\\n\");\r\n process.stdout.write(\"\\nThen re-run: pk-agent auth import-codex\\n\");\r\n }\r\n });\r\n\r\n return authCmd;\r\n}\r\n\r\nasync function handleAnthropicLogin() {\r\n process.stdout.write(\"Anthropic login methods:\\n\");\r\n process.stdout.write(\" 1. Claude Pro/Max Plan (OAuth) (Experimental)\\n\");\r\n process.stdout.write(\" 2. Anthropic Console (OAuth)\\n\");\r\n process.stdout.write(\" 3. Manual API Key\\n\");\r\n process.stdout.write(\"\\n\");\r\n\r\n const method = await promptInput(\"Select method (1-3): \");\r\n\r\n switch (method) {\r\n case \"1\":\r\n await handleAnthropicOAuth(\"max\");\r\n break;\r\n case \"2\":\r\n await handleAnthropicOAuth(\"console\");\r\n break;\r\n case \"3\":\r\n await handleGenericLogin(\"anthropic\", \"Anthropic API Key\");\r\n break;\r\n default:\r\n logger.warn(\"Invalid selection\");\r\n }\r\n}\r\n\r\nasync function handleOpenAILogin() {\r\n process.stdout.write(\"OpenAI login methods:\\n\");\r\n process.stdout.write(\" 1. ChatGPT Pro/Plus (OAuth) - Uses your ChatGPT subscription\\n\");\r\n process.stdout.write(\" 2. Manual API Key\\n\");\r\n process.stdout.write(\"\\n\");\r\n\r\n const method = await promptInput(\"Select method (1-2): \");\r\n\r\n switch (method) {\r\n case \"1\":\r\n await handleCodexOAuth();\r\n break;\r\n case \"2\":\r\n await handleGenericLogin(\"openai\", \"OpenAI API Key\");\r\n break;\r\n default:\r\n logger.warn(\"Invalid selection\");\r\n }\r\n}\r\n\r\nasync function handleCodexOAuth() {\r\n // Some weird bug where program exits without this delay (from OpenCode)\r\n await new Promise((resolve) => setTimeout(resolve, 10));\r\n\r\n process.stdout.write(\"\\n Starting ChatGPT OAuth flow...\\n\\n\");\r\n\r\n try {\r\n const { url, pkce } = await CodexAuth.authorize();\r\n\r\n // Always show the URL so users can copy/paste if auto-open fails on Windows.\r\n process.stdout.write(`${\"=\".repeat(80)}\\n`);\r\n process.stdout.write(` AUTHORIZATION URL (open this if your browser doesn't pop up):\\n`);\r\n process.stdout.write(`${url}\\n`);\r\n process.stdout.write(`${\"=\".repeat(80)}\\n\\n`);\r\n\r\n // Try automatic flow with local callback server first\r\n let autoCode: string | undefined;\r\n // Callback server is only needed to capture the code, so we close it as soon as we have it.\r\n let serverPromise: ReturnType<typeof CodexAuth.startCallbackServer> | undefined;\r\n\r\n try {\r\n serverPromise = CodexAuth.startCallbackServer(5 * 60 * 1000, {\r\n expectedState: pkce.verifier,\r\n });\r\n\r\n // Open browser automatically (best-effort). If it fails, keep the callback server running\r\n // and let the user open the URL manually.\r\n try {\r\n await openUrl(url);\r\n } catch {\r\n process.stdout.write(\"Warning: Could not open your browser automatically.\\n\");\r\n process.stdout.write(\" Please copy/paste the authorization URL into your browser.\\n\\n\");\r\n }\r\n\r\n process.stdout.write(\" Attempting to open your browser for authentication...\\n\");\r\n process.stdout.write(\" Waiting for callback (timeout: 5 minutes)...\\n\\n\");\r\n\r\n const result = await serverPromise;\r\n autoCode = result.code;\r\n result.close();\r\n } catch {\r\n serverPromise?.stop();\r\n // Server failed (port in use, browser can't open, timeout, etc.)\r\n // Fall back to manual flow\r\n process.stdout.write(\"Warning: Auto-redirect unavailable. Using manual flow.\\n\\n\");\r\n }\r\n\r\n let code: string | null = null;\r\n\r\n if (autoCode) {\r\n code = autoCode;\r\n process.stdout.write(\"[OK] Authorization code received automatically!\\n\");\r\n } else {\r\n // Manual fallback\r\n process.stdout.write(`${\"=\".repeat(80)}\\n`);\r\n process.stdout.write(` AUTHORIZATION URL:\\n`);\r\n process.stdout.write(`${url}\\n`);\r\n process.stdout.write(`${\"=\".repeat(80)}\\n\\n`);\r\n\r\n process.stdout.write(\" Steps:\\n\");\r\n process.stdout.write(\" 1. Visit the URL above in your browser\\n\");\r\n process.stdout.write(\" 2. Sign in to ChatGPT and authorize the application\\n\");\r\n process.stdout.write(\" 3. You'll be redirected to a page (it may show an error - that's OK)\\n\");\r\n process.stdout.write(\" 4. Copy the FULL URL from your browser's address bar\\n\");\r\n process.stdout.write(\" 5. Paste it below\\n\\n\");\r\n\r\n const callbackUrl = await promptInput(\" Paste the callback URL here: \");\r\n\r\n if (!callbackUrl || callbackUrl.length === 0) {\r\n logger.warn(\"No URL provided\");\r\n return;\r\n }\r\n\r\n try {\r\n const parsed = new URL(callbackUrl);\r\n code = parsed.searchParams.get(\"code\");\r\n } catch {\r\n code = callbackUrl.trim();\r\n }\r\n }\r\n\r\n if (!code) {\r\n logger.warn(\"Could not extract authorization code\");\r\n return;\r\n }\r\n\r\n process.stdout.write(\" Exchanging code for tokens...\\n\");\r\n\r\n try {\r\n const credentials = await CodexAuth.exchange(code, pkce);\r\n await AuthStorage.setOAuth(\"openai\", {\r\n type: \"codex-oauth\",\r\n refresh: credentials.refresh,\r\n access: credentials.access,\r\n expires: credentials.expires,\r\n accountId: credentials.accountId,\r\n });\r\n\r\n process.stdout.write(\"[OK] Successfully authenticated with ChatGPT!\\n\");\r\n if (credentials.accountId) {\r\n process.stdout.write(` Account ID: ${credentials.accountId}\\n`);\r\n }\r\n } catch {\r\n logger.warn(\"Invalid code or authorization failed\");\r\n }\r\n\r\n } catch (error) {\r\n logger.error(\"Authentication failed\", error as Error);\r\n }\r\n}\r\n\r\nasync function handleAnthropicOAuth(mode: \"max\" | \"console\") {\r\n // Some weird bug where program exits without this delay (from OpenCode)\r\n await new Promise((resolve) => setTimeout(resolve, 10));\r\n\r\n process.stdout.write(`\\n Starting ${mode === \"max\" ? \"Claude Pro/Max\" : \"Console\"} OAuth flow...\\n\\n`);\r\n\r\n try {\r\n const { url, verifier } = await AnthropicAuth.authorize(mode);\r\n\r\n // Always show the URL prominently \r\n process.stdout.write(`\\n${\"=\".repeat(80)}\\n`);\r\n process.stdout.write(` AUTHORIZATION URL:\\n`);\r\n process.stdout.write(`${url}\\n`);\r\n process.stdout.write(`${\"=\".repeat(80)}\\n\\n`);\r\n\r\n process.stdout.write(\" Steps:\\n\");\r\n process.stdout.write(\" 1. Visit the URL above in your browser\\n\");\r\n process.stdout.write(\" 2. Sign in to Claude and authorize the application\\n\");\r\n process.stdout.write(\" 3. Copy the authorization code you receive\\n\");\r\n process.stdout.write(\" 4. Paste it below\\n\\n\");\r\n\r\n const code = await promptInput(\" Paste the authorization code here: \");\r\n\r\n if (!code || code.length === 0) {\r\n logger.warn(\"No code provided\");\r\n return;\r\n }\r\n\r\n process.stdout.write(\" Exchanging code for tokens...\\n\");\r\n\r\n try {\r\n const credentials = await AnthropicAuth.exchange(code, verifier);\r\n await AuthStorage.setOAuth(\"anthropic\", {\r\n type: \"oauth\",\r\n refresh: credentials.refresh,\r\n access: credentials.access,\r\n expires: credentials.expires,\r\n });\r\n process.stdout.write(\"[OK] Login successful\\n\");\r\n\r\n if (mode === \"max\") {\r\n process.stdout.write(\" Successfully authenticated with Claude Max!\\n\");\r\n }\r\n } catch {\r\n logger.warn(\"Invalid code\");\r\n }\r\n\r\n } catch (error) {\r\n logger.error(\"Authentication failed\", error as Error);\r\n }\r\n}\r\n\r\nasync function handleGenericLogin(provider: string, keyName: string) {\r\n process.stdout.write(`\\n Please enter your ${keyName}:\\n`);\r\n\r\n // Use simple input instead of password masking for easier debugging\r\n const key = await promptInput(\"API Key: \");\r\n\r\n if (!key || key.length === 0) {\r\n logger.warn(\"No API key provided\");\r\n return;\r\n }\r\n\r\n try {\r\n await AuthStorage.setApiKey(provider, {\r\n type: \"api\",\r\n key,\r\n });\r\n\r\n process.stdout.write(`[OK] Successfully stored ${keyName}!\\n`);\r\n } catch (error) {\r\n logger.error(\"Failed to store API key\", error as Error);\r\n }\r\n}\r\n",
|
|
76
|
+
"import { z } from \"zod\";\n\nexport const OAuthTokens = z.object({\n type: z.literal(\"oauth\"),\n refresh: z.string(),\n access: z.string(),\n expires: z.number(),\n});\n\nexport const CodexOAuthTokens = z.object({\n type: z.literal(\"codex-oauth\"),\n refresh: z.string(),\n access: z.string(),\n expires: z.number(),\n accountId: z.string().optional(),\n});\n\nexport const ApiKeyAuth = z.object({\n type: z.literal(\"api\"),\n key: z.string(),\n});\n\nexport const WellKnownAuth = z.object({\n type: z.literal(\"wellknown\"),\n key: z.string(),\n token: z.string(),\n});\n\nexport const AuthInfo = z.discriminatedUnion(\"type\", [\n OAuthTokens,\n CodexOAuthTokens,\n ApiKeyAuth,\n WellKnownAuth,\n]);\n\nexport type AuthInfo = z.infer<typeof AuthInfo>;\nexport type OAuthTokens = z.infer<typeof OAuthTokens>;\nexport type CodexOAuthTokens = z.infer<typeof CodexOAuthTokens>;\nexport type ApiKeyAuth = z.infer<typeof ApiKeyAuth>;\nexport type WellKnownAuth = z.infer<typeof WellKnownAuth>;\n\n// Combined provider auth supporting both OAuth and API key\nexport interface ProviderAuth {\n oauth?: OAuthTokens | CodexOAuthTokens;\n api?: ApiKeyAuth;\n}",
|
|
77
|
+
"export * from \"./types.js\";\nexport * from \"./storage.js\";\nexport * from \"./anthropic.js\";\nexport * from \"./codex.js\";",
|
|
78
|
+
"import { spawn } from \"child_process\";\r\n\r\nfunction quotePwshSingle(s: string): string {\r\n // PowerShell single-quoted strings escape ' by doubling it.\r\n return `'${s.replace(/'/g, \"''\")}'`;\r\n}\r\n\r\nasync function runDetached(command: string, args: string[]): Promise<void> {\r\n await new Promise<void>((resolve, reject) => {\r\n const child = spawn(command, args, { stdio: \"ignore\", detached: true });\r\n child.on(\"error\", reject);\r\n child.unref();\r\n // If we spawned successfully, treat it as \"opened\".\r\n resolve();\r\n });\r\n}\r\n\r\n/**\r\n * Best-effort open of a URL in the user's default browser.\r\n * This should never throw unless all strategies fail.\r\n */\r\nexport async function openUrl(url: string): Promise<void> {\r\n const platform = process.platform;\r\n\r\n if (platform === \"win32\") {\r\n // Prefer PowerShell Start-Process. It's more reliable than `cmd start` when\r\n // URLs contain characters `cmd.exe` treats specially.\r\n try {\r\n await runDetached(\"powershell.exe\", [\r\n \"-NoProfile\",\r\n \"-Command\",\r\n `Start-Process -FilePath ${quotePwshSingle(url)}`,\r\n ]);\r\n return;\r\n } catch {\r\n // Fall back to cmd.exe builtin.\r\n }\r\n\r\n await runDetached(\"cmd.exe\", [\"/d\", \"/s\", \"/c\", \"start\", '\"\"', url]);\r\n return;\r\n }\r\n\r\n if (platform === \"darwin\") {\r\n await runDetached(\"open\", [url]);\r\n return;\r\n }\r\n\r\n // Linux / other\r\n await runDetached(\"xdg-open\", [url]);\r\n}\r\n\r\n",
|
|
79
|
+
"import { Command } from \"commander\";\r\nimport fs from \"fs/promises\";\r\nimport path from \"path\";\r\nimport { getSessionStorageDir, getProjectDir } from \"../storage/paths\";\r\nimport type { SessionInfo, Message, Part } from \"../session/types\";\r\nimport { resolveProjectContext } from \"../utils/project\";\r\n\r\ninterface SessionSummary {\r\n id: string;\r\n agentName: string;\r\n model: string;\r\n created: Date;\r\n isSubAgent: boolean;\r\n dirPath: string;\r\n}\r\n\r\n/**\r\n * Parse session directory name to extract ID and agent name\r\n * Format: {sessionID}-{agentName}\r\n */\r\nfunction parseSessionDirName(dirName: string): { id: string; agentName: string } | null {\r\n // ULID is 26 characters\r\n const ulidLength = 26;\r\n if (dirName.length < ulidLength + 2) {\r\n return null;\r\n }\r\n\r\n const id = dirName.substring(0, ulidLength);\r\n const agentName = dirName.substring(ulidLength + 1); // Skip the hyphen\r\n\r\n // Validate ULID format (basic check)\r\n if (!/^[0-9A-Z]{26}$/i.test(id)) {\r\n return null;\r\n }\r\n\r\n return { id, agentName };\r\n}\r\n\r\n/**\r\n * List all sessions from storage\r\n */\r\nasync function listSessions(projectRoot: string): Promise<SessionSummary[]> {\r\n const sessionDir = await getSessionStorageDir(projectRoot);\r\n const sessions: SessionSummary[] = [];\r\n\r\n try {\r\n const entries = await fs.readdir(sessionDir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n if (!entry.isDirectory()) continue;\r\n\r\n const parsed = parseSessionDirName(entry.name);\r\n if (!parsed) continue;\r\n\r\n // Try to read session.json for more details\r\n const sessionJsonPath = path.join(sessionDir, entry.name, \"session.json\");\r\n try {\r\n const content = await fs.readFile(sessionJsonPath, \"utf-8\");\r\n const sessionInfo = JSON.parse(content) as SessionInfo;\r\n\r\n sessions.push({\r\n id: sessionInfo.id,\r\n agentName: sessionInfo.agent.name,\r\n model: sessionInfo.model,\r\n created: new Date(sessionInfo.time.created),\r\n isSubAgent: sessionInfo.agent.isSubAgent,\r\n dirPath: path.join(sessionDir, entry.name),\r\n });\r\n } catch {\r\n // If session.json is missing or invalid, use parsed info\r\n sessions.push({\r\n id: parsed.id,\r\n agentName: parsed.agentName,\r\n model: \"unknown\",\r\n created: new Date(0),\r\n isSubAgent: false,\r\n dirPath: path.join(sessionDir, entry.name),\r\n });\r\n }\r\n }\r\n } catch {\r\n // Directory doesn't exist or can't be read\r\n return [];\r\n }\r\n\r\n // Sort by created date (newest first)\r\n sessions.sort((a, b) => b.created.getTime() - a.created.getTime());\r\n\r\n return sessions;\r\n}\r\n\r\n/**\r\n * Get session details including messages and parts\r\n */\r\nasync function getSessionDetails(\r\n sessionDir: string\r\n): Promise<{\r\n session: SessionInfo | null;\r\n messages: Array<{ message: Message; parts: Part[] }>;\r\n}> {\r\n const result: {\r\n session: SessionInfo | null;\r\n messages: Array<{ message: Message; parts: Part[] }>;\r\n } = {\r\n session: null,\r\n messages: [],\r\n };\r\n\r\n // Read session.json\r\n try {\r\n const sessionContent = await fs.readFile(\r\n path.join(sessionDir, \"session.json\"),\r\n \"utf-8\"\r\n );\r\n result.session = JSON.parse(sessionContent) as SessionInfo;\r\n } catch {\r\n return result;\r\n }\r\n\r\n // List message directories (ULIDs)\r\n const entries = await fs.readdir(sessionDir, { withFileTypes: true });\r\n const messageDirs = entries.filter(\r\n (e) => e.isDirectory() && /^[0-9A-Z]{26}$/i.test(e.name)\r\n );\r\n\r\n for (const msgDir of messageDirs) {\r\n const msgPath = path.join(sessionDir, msgDir.name);\r\n\r\n // Read message.json\r\n let message: Message | null = null;\r\n try {\r\n const msgContent = await fs.readFile(\r\n path.join(msgPath, \"message.json\"),\r\n \"utf-8\"\r\n );\r\n message = JSON.parse(msgContent) as Message;\r\n } catch {\r\n continue;\r\n }\r\n\r\n // Read parts\r\n const parts: Part[] = [];\r\n const partDir = path.join(msgPath, \"part\");\r\n try {\r\n const partFiles = await fs.readdir(partDir);\r\n for (const partFile of partFiles) {\r\n if (!partFile.endsWith(\".json\")) continue;\r\n try {\r\n const partContent = await fs.readFile(\r\n path.join(partDir, partFile),\r\n \"utf-8\"\r\n );\r\n parts.push(JSON.parse(partContent) as Part);\r\n } catch {\r\n // Skip invalid part files\r\n }\r\n }\r\n } catch {\r\n // No parts directory\r\n }\r\n\r\n result.messages.push({ message, parts });\r\n }\r\n\r\n // Sort messages by created time\r\n result.messages.sort(\r\n (a, b) => a.message.time.created - b.message.time.created\r\n );\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Format date for display\r\n */\r\nfunction formatDate(date: Date): string {\r\n if (date.getTime() === 0) return \"unknown\";\r\n const now = new Date();\r\n const diff = now.getTime() - date.getTime();\r\n const days = Math.floor(diff / (1000 * 60 * 60 * 24));\r\n\r\n if (days === 0) {\r\n return date.toLocaleTimeString(\"en-US\", {\r\n hour: \"2-digit\",\r\n minute: \"2-digit\",\r\n });\r\n } else if (days < 7) {\r\n return date.toLocaleDateString(\"en-US\", {\r\n weekday: \"short\",\r\n hour: \"2-digit\",\r\n minute: \"2-digit\",\r\n });\r\n } else {\r\n return date.toLocaleDateString(\"en-US\", {\r\n month: \"short\",\r\n day: \"numeric\",\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Truncate string with ellipsis\r\n */\r\nfunction truncate(str: string, len: number): string {\r\n if (str.length <= len) return str;\r\n return str.substring(0, len - 1) + \"...\";\r\n}\r\n\r\n/**\r\n * Format value for full display (multi-line, indented)\r\n */\r\nfunction formatValueFull(value: unknown, indent: string = \" \"): string {\r\n if (value === null || value === undefined) {\r\n return `${indent}${String(value)}`;\r\n }\r\n\r\n let str: string;\r\n if (typeof value === \"string\") {\r\n str = value;\r\n } else if (typeof value === \"object\") {\r\n try {\r\n str = JSON.stringify(value, null, 2);\r\n } catch {\r\n str = String(value);\r\n }\r\n } else {\r\n str = String(value);\r\n }\r\n\r\n // Indent each line\r\n return str\r\n .split(\"\\n\")\r\n .map((line) => `${indent}${line}`)\r\n .join(\"\\n\");\r\n}\r\n\r\n/**\r\n * Format tool name for cleaner display\r\n * mcp__bash__run_bash -> Bash{run_bash}\r\n * mcp__notion__API-post-page -> Notion{API-post-page}\r\n */\r\nfunction formatToolName(toolName: string): string {\r\n // Handle MCP tools: mcp__<server>__<method>\r\n if (toolName.startsWith(\"mcp__\")) {\r\n const parts = toolName.substring(5).split(\"__\");\r\n if (parts.length >= 2) {\r\n const server = parts[0].charAt(0).toUpperCase() + parts[0].slice(1);\r\n const method = parts.slice(1).join(\"__\");\r\n return `${server}{${method}}`;\r\n }\r\n }\r\n return toolName;\r\n}\r\n\r\n/**\r\n * Extract main input value for inline display\r\n */\r\nfunction extractMainInput(input: unknown): string | null {\r\n if (!input || typeof input !== \"object\") return null;\r\n\r\n const obj = input as Record<string, unknown>;\r\n\r\n // Priority order for common input fields\r\n const priorityFields = [\"command\", \"query\", \"url\", \"path\", \"file_path\", \"pattern\", \"text\", \"content\"];\r\n\r\n for (const field of priorityFields) {\r\n if (obj[field] && typeof obj[field] === \"string\") {\r\n return obj[field] as string;\r\n }\r\n }\r\n\r\n // Fallback: use first string value\r\n for (const value of Object.values(obj)) {\r\n if (typeof value === \"string\" && value.length < 200) {\r\n return value;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Extract output value for display (unwrap common wrapper patterns)\r\n */\r\nfunction extractOutputValue(output: unknown): string {\r\n if (output === null || output === undefined) return String(output);\r\n\r\n if (typeof output === \"string\") return output;\r\n\r\n if (typeof output === \"object\") {\r\n const obj = output as Record<string, unknown>;\r\n\r\n // Common wrapper patterns\r\n if (obj.output && typeof obj.output === \"string\") {\r\n return obj.output;\r\n }\r\n if (obj.result && typeof obj.result === \"string\") {\r\n return obj.result;\r\n }\r\n if (obj.content && typeof obj.content === \"string\") {\r\n return obj.content;\r\n }\r\n\r\n // Fallback to JSON\r\n try {\r\n return JSON.stringify(output);\r\n } catch {\r\n return String(output);\r\n }\r\n }\r\n\r\n return String(output);\r\n}\r\n\r\n/**\r\n * Format tool output with truncation and line limits\r\n */\r\nfunction formatToolOutput(output: string, maxLen: number = 200, maxLines: number = 5): string {\r\n const lines = output.split(\"\\n\");\r\n const result: string[] = [];\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n let line = lines[i];\r\n if (line.length > maxLen) {\r\n line = line.substring(0, maxLen) + `... [${output.length} chars]`;\r\n }\r\n result.push(line);\r\n\r\n // Limit lines in non-full mode\r\n if (i >= maxLines - 1 && lines.length > maxLines) {\r\n result.push(`... (${lines.length - maxLines} more lines)`);\r\n break;\r\n }\r\n }\r\n\r\n return result.join(\"\\n\");\r\n}\r\n\r\n/**\r\n * Format model name for display (shorter)\r\n */\r\nfunction formatModel(model: string): string {\r\n // anthropic:claude-sonnet-4-0 -> claude-sonnet-4\r\n const parts = model.split(\":\");\r\n if (parts.length < 2) return model;\r\n\r\n let modelName = parts[1];\r\n\r\n // Remove trailing version numbers like -0, -1\r\n modelName = modelName.replace(/-\\d+$/, \"\");\r\n\r\n return truncate(modelName, 20);\r\n}\r\n\r\nexport function createSessionsCommand(): Command {\r\n const sessionsCmd = new Command(\"sessions\")\r\n .description(\"View session logs\")\r\n .argument(\"[id]\", \"Session ID to show details (supports partial match)\")\r\n .option(\"-s, --subagents\", \"Include subagent sessions\")\r\n .option(\"-n, --limit <n>\", \"Limit number of sessions to show\", \"10\")\r\n .option(\"-j, --json\", \"Output as JSON\")\r\n .option(\"-f, --full\", \"Show full tool input/output (not truncated)\")\r\n .action(async (sessionId?: string, options?: { subagents?: boolean; limit?: string; json?: boolean; full?: boolean }) => {\r\n const projectContext = resolveProjectContext(process.cwd());\r\n\r\n if (sessionId) {\r\n // Show specific session\r\n const showOptions: { json?: boolean; full?: boolean } = {};\r\n if (options?.json) showOptions.json = options.json;\r\n if (options?.full) showOptions.full = options.full;\r\n await showSession(projectContext.projectRoot, sessionId, showOptions);\r\n } else {\r\n // List sessions\r\n await listSessionsCommand(projectContext.projectRoot, options);\r\n }\r\n });\r\n\r\n // Add explicit list subcommand for clarity\r\n sessionsCmd\r\n .command(\"list\")\r\n .alias(\"ls\")\r\n .description(\"List all sessions\")\r\n .option(\"-s, --subagents\", \"Include subagent sessions\")\r\n .option(\"-n, --limit <n>\", \"Limit number of sessions to show\", \"10\")\r\n .option(\"-j, --json\", \"Output as JSON\")\r\n .action(async (options: { subagents?: boolean; limit?: string; json?: boolean }) => {\r\n const projectContext = resolveProjectContext(process.cwd());\r\n await listSessionsCommand(projectContext.projectRoot, options);\r\n });\r\n\r\n // Add show subcommand\r\n sessionsCmd\r\n .command(\"show <id>\")\r\n .description(\"Show session details\")\r\n .option(\"-j, --json\", \"Output as JSON\")\r\n .option(\"-f, --full\", \"Show full tool input/output (not truncated)\")\r\n .action(async (id: string, options: { json?: boolean; full?: boolean }) => {\r\n const projectContext = resolveProjectContext(process.cwd());\r\n await showSession(projectContext.projectRoot, id, options);\r\n });\r\n\r\n // Add path subcommand to show storage location\r\n sessionsCmd\r\n .command(\"path\")\r\n .description(\"Show session storage path\")\r\n .action(async () => {\r\n const projectContext = resolveProjectContext(process.cwd());\r\n const projectDir = await getProjectDir(projectContext.projectRoot);\r\n const sessionDir = await getSessionStorageDir(projectContext.projectRoot);\r\n\r\n process.stdout.write(`Project dir: ${projectDir}\\n`);\r\n process.stdout.write(`Sessions: ${sessionDir}\\n`);\r\n });\r\n\r\n return sessionsCmd;\r\n}\r\n\r\nasync function listSessionsCommand(\r\n projectRoot: string,\r\n options?: { subagents?: boolean; limit?: string; json?: boolean }\r\n): Promise<void> {\r\n let sessions = await listSessions(projectRoot);\r\n\r\n // Filter out subagents unless --subagents is specified\r\n if (!options?.subagents) {\r\n sessions = sessions.filter((s) => !s.isSubAgent);\r\n }\r\n\r\n // Apply limit\r\n const limit = parseInt(options?.limit || \"10\");\r\n if (limit > 0 && sessions.length > limit) {\r\n sessions = sessions.slice(0, limit);\r\n }\r\n\r\n if (sessions.length === 0) {\r\n process.stdout.write(\"No sessions found\\n\");\r\n return;\r\n }\r\n\r\n if (options?.json) {\r\n process.stdout.write(JSON.stringify(sessions, null, 2) + \"\\n\");\r\n return;\r\n }\r\n\r\n // Calculate column widths\r\n const idWidth = 12; // First 12 chars of ULID\r\n const agentWidth = Math.min(\r\n 20,\r\n Math.max(...sessions.map((s) => s.agentName.length))\r\n );\r\n const modelWidth = 20;\r\n\r\n // Header\r\n process.stdout.write(\r\n `${\"ID\".padEnd(idWidth)} ${\"AGENT\".padEnd(agentWidth)} ${\"MODEL\".padEnd(modelWidth)} DATE\\n`\r\n );\r\n process.stdout.write(`${\"-\".repeat(idWidth + agentWidth + modelWidth + 20)}\\n`);\r\n\r\n // Rows\r\n for (const session of sessions) {\r\n const shortId = session.id.substring(0, idWidth);\r\n const agent = truncate(session.agentName, agentWidth).padEnd(agentWidth);\r\n const model = formatModel(session.model).padEnd(modelWidth);\r\n const date = formatDate(session.created);\r\n\r\n process.stdout.write(`${shortId} ${agent} ${model} ${date}\\n`);\r\n }\r\n\r\n // Footer\r\n if (sessions.length > 0) {\r\n process.stdout.write(\r\n `\\nShowing ${sessions.length} session(s). Use 'pk-agent sessions <id>' for details.\\n`\r\n );\r\n }\r\n}\r\n\r\nasync function showSession(\r\n projectRoot: string,\r\n sessionId: string,\r\n options?: { json?: boolean; full?: boolean }\r\n): Promise<void> {\r\n // Find session by partial ID match\r\n const sessions = await listSessions(projectRoot);\r\n const matches = sessions.filter((s) =>\r\n s.id.toLowerCase().startsWith(sessionId.toLowerCase())\r\n );\r\n\r\n if (matches.length === 0) {\r\n process.stderr.write(`No session found matching: ${sessionId}\\n`);\r\n process.exit(1);\r\n }\r\n\r\n if (matches.length > 1) {\r\n process.stderr.write(`Multiple sessions match '${sessionId}':\\n`);\r\n for (const m of matches) {\r\n process.stderr.write(` ${m.id.substring(0, 12)} ${m.agentName}\\n`);\r\n }\r\n process.stderr.write(`\\nPlease use a more specific ID.\\n`);\r\n process.exit(1);\r\n }\r\n\r\n const session = matches[0];\r\n const details = await getSessionDetails(session.dirPath);\r\n\r\n if (!details.session) {\r\n process.stderr.write(`Failed to read session: ${sessionId}\\n`);\r\n process.exit(1);\r\n }\r\n\r\n if (options?.json) {\r\n process.stdout.write(JSON.stringify(details, null, 2) + \"\\n\");\r\n return;\r\n }\r\n\r\n const showFull = options?.full ?? false;\r\n\r\n // Display session info\r\n const s = details.session;\r\n\r\n process.stdout.write(`\\n${\"=\".repeat(60)}\\n`);\r\n process.stdout.write(`SESSION: ${s.id}\\n`);\r\n process.stdout.write(`${\"=\".repeat(60)}\\n\\n`);\r\n\r\n process.stdout.write(`Agent: ${s.agent.name}\\n`);\r\n if (s.agent.description) {\r\n process.stdout.write(`Description: ${s.agent.description}\\n`);\r\n }\r\n if (s.agent.filePath) {\r\n process.stdout.write(`File: ${s.agent.filePath}\\n`);\r\n }\r\n process.stdout.write(`Model: ${s.model}\\n`);\r\n process.stdout.write(`Started: ${new Date(s.time.created).toLocaleString()}\\n`);\r\n\r\n if (s.config.mcpServers && s.config.mcpServers.length > 0) {\r\n process.stdout.write(`MCP Servers: ${s.config.mcpServers.join(\", \")}\\n`);\r\n }\r\n\r\n process.stdout.write(`\\nProject: ${s.project.root}\\n`);\r\n process.stdout.write(`Working Dir: ${s.project.cwd}\\n`);\r\n\r\n // Display session-level error (failures before LLM calls - auth, MCP, etc.)\r\n if (s.error) {\r\n process.stdout.write(`\\n${\"-\".repeat(60)}\\n`);\r\n process.stdout.write(`[X] ERROR: ${s.error.code}\\n`);\r\n process.stdout.write(` ${s.error.message}\\n`);\r\n process.stdout.write(` Time: ${new Date(s.error.time).toLocaleString()}\\n`);\r\n }\r\n\r\n // Display messages\r\n if (details.messages.length > 0) {\r\n process.stdout.write(`\\n${\"-\".repeat(60)}\\n`);\r\n\r\n for (const { message, parts } of details.messages) {\r\n // Show message header only if multiple messages\r\n if (details.messages.length > 1) {\r\n process.stdout.write(`[Message ${message.id.substring(0, 8)}]\\n`);\r\n }\r\n\r\n // Show user prompt (first line only for task, full for user input)\r\n const taskFirstLine = message.user.prompt.task.split(\"\\n\")[0];\r\n process.stdout.write(`Task: ${truncate(taskFirstLine, 80)}\\n`);\r\n if (message.user.prompt.user) {\r\n process.stdout.write(`User: ${message.user.prompt.user}\\n`);\r\n }\r\n\r\n // Show token usage and duration\r\n const tokens = message.assistant.tokens;\r\n const totalTokens = tokens.input + tokens.output;\r\n let statsLine = `Tokens: ${totalTokens} (in: ${tokens.input}, out: ${tokens.output})`;\r\n\r\n // Add duration if completed timestamp exists\r\n if (message.time.completed) {\r\n const durationMs = message.time.completed - message.time.created;\r\n const durationSec = (durationMs / 1000).toFixed(1);\r\n statsLine += ` Duration: ${durationSec}s`;\r\n }\r\n process.stdout.write(statsLine + \"\\n\");\r\n\r\n // Show error if session failed\r\n if (message.assistant.error) {\r\n process.stdout.write(`\\n[X] Error: ${message.assistant.error.message}\\n`);\r\n if (message.assistant.error.type) {\r\n process.stdout.write(` Type: ${message.assistant.error.type}\\n`);\r\n }\r\n }\r\n\r\n // Count parts by type\r\n const partCounts: Record<string, number> = {};\r\n for (const part of parts) {\r\n partCounts[part.type] = (partCounts[part.type] || 0) + 1;\r\n }\r\n\r\n if (Object.keys(partCounts).length > 0) {\r\n const partSummary = Object.entries(partCounts)\r\n .map(([type, count]) => `${type}: ${count}`)\r\n .join(\", \");\r\n process.stdout.write(`Parts: ${partSummary}\\n`);\r\n }\r\n\r\n // Show tools summary\r\n const toolParts = parts.filter((p) => p.type === \"tool\") as Array<\r\n Part & {\r\n type: \"tool\";\r\n tool: string;\r\n state: {\r\n status: string;\r\n input?: unknown;\r\n output?: unknown;\r\n error?: string;\r\n time?: { start: number; end?: number };\r\n }\r\n }\r\n >;\r\n if (toolParts.length > 0) {\r\n // Count tools by name for summary\r\n const toolCounts: Record<string, number> = {};\r\n for (const tool of toolParts) {\r\n toolCounts[tool.tool] = (toolCounts[tool.tool] || 0) + 1;\r\n }\r\n const toolSummary = Object.entries(toolCounts)\r\n .map(([name, count]) => count > 1 ? `${name} x${count}` : name)\r\n .join(\", \");\r\n process.stdout.write(`Tools: ${toolParts.length} calls (${truncate(toolSummary, 60)})\\n`);\r\n }\r\n\r\n // Show interleaved output (text and tool parts in chronological order)\r\n // Sort parts by ULID id (which is chronologically sortable)\r\n const displayParts = parts\r\n .filter((p) => p.type === \"text\" || p.type === \"tool\")\r\n .sort((a, b) => a.id.localeCompare(b.id));\r\n\r\n if (displayParts.length > 0) {\r\n process.stdout.write(`\\nOutput:\\n`);\r\n\r\n for (const part of displayParts) {\r\n if (part.type === \"text\") {\r\n const textPart = part as Part & { type: \"text\"; text: string };\r\n if (textPart.text.trim()) {\r\n // Plain text output, no prefix\r\n process.stdout.write(`${textPart.text.trim()}\\n`);\r\n }\r\n } else if (part.type === \"tool\") {\r\n const tool = part as Part & {\r\n type: \"tool\";\r\n tool: string;\r\n state: {\r\n status: string;\r\n input?: unknown;\r\n output?: unknown;\r\n error?: string;\r\n time?: { start: number; end?: number };\r\n }\r\n };\r\n\r\n const status =\r\n tool.state.status === \"completed\"\r\n ? \"[OK]\"\r\n : tool.state.status === \"error\"\r\n ? \"[X]\"\r\n : \"...\";\r\n\r\n // Format tool name: mcp__bash__run_bash -> Bash{run_bash}\r\n const toolName = formatToolName(tool.tool);\r\n\r\n // Extract main input for inline display\r\n const mainInput = extractMainInput(tool.state.input);\r\n const inputDisplay = mainInput ? ` (${truncate(mainInput, 60)})` : \"\";\r\n\r\n // Show duration if available\r\n let durationStr = \"\";\r\n if (tool.state.time?.start && tool.state.time?.end) {\r\n const durationMs = tool.state.time.end - tool.state.time.start;\r\n durationStr = durationMs < 1000\r\n ? ` ${durationMs}ms`\r\n : ` ${(durationMs / 1000).toFixed(1)}s`;\r\n }\r\n\r\n // Visual indicator for tool call\r\n const header = `--- ${status} ${toolName}${inputDisplay}${durationStr} `;\r\n const padding = Math.max(0, 60 - header.length);\r\n process.stdout.write(`\\n${header}${\"-\".repeat(padding)}\\n`);\r\n\r\n // Show full input in --full mode\r\n if (showFull && tool.state.input !== undefined) {\r\n process.stdout.write(`Input:\\n`);\r\n process.stdout.write(formatValueFull(tool.state.input, \" \") + \"\\n\");\r\n }\r\n\r\n // Show output or error\r\n if (tool.state.status === \"error\" && tool.state.error) {\r\n if (showFull) {\r\n process.stdout.write(`Error:\\n`);\r\n process.stdout.write(formatValueFull(tool.state.error, \" \") + \"\\n\");\r\n } else {\r\n const errorOutput = formatToolOutput(tool.state.error, 150);\r\n process.stdout.write(`${errorOutput}\\n`);\r\n }\r\n } else if (tool.state.status === \"completed\" && tool.state.output !== undefined) {\r\n if (showFull) {\r\n process.stdout.write(`Result:\\n`);\r\n process.stdout.write(formatValueFull(tool.state.output, \" \") + \"\\n\");\r\n } else {\r\n const outputValue = extractOutputValue(tool.state.output);\r\n const formattedOutput = formatToolOutput(outputValue, 150);\r\n process.stdout.write(`${formattedOutput}\\n`);\r\n }\r\n }\r\n\r\n // Closing separator\r\n process.stdout.write(`${\"-\".repeat(60)}\\n`);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n process.stdout.write(`\\n`);\r\n}\r\n",
|
|
80
|
+
"import { existsSync, statSync } from 'fs';\nimport { dirname, parse, resolve } from 'path';\nimport { homedir } from 'os';\nimport { logger } from './logger';\nimport { ensurePkAgentProjectDirs, ensurePkAgentUserDirs } from './pk-agent-dirs';\n\n/**\n * Find project root by searching upward from a starting directory.\n * Looks for common project markers in order of specificity.\n *\n * @param startPath - Starting directory or file path\n * @returns Project root directory path\n */\nexport function findProjectRoot(startPath: string): string {\n // If startPath exists and is a file (not a directory), start from its directory\n let currentDir = startPath;\n if (existsSync(startPath)) {\n const stats = statSync(startPath);\n if (stats.isFile()) {\n currentDir = dirname(startPath);\n }\n }\n\n // For URLs or non-existent paths, use current working directory\n if (!existsSync(currentDir) || currentDir.startsWith('http')) {\n return process.cwd();\n }\n\n currentDir = resolve(currentDir);\n const startDir = currentDir;\n const root = parse(currentDir).root;\n\n logger.debug(`Searching for project root starting from: ${currentDir}`);\n\n // Search upward for project markers\n while (currentDir !== root) {\n // Check for project markers in priority order\n const markers = [\n '.pk-agent', // Agentuse plugins directory (if using plugins)\n '.git', // Git repository root (most common)\n 'package.json', // Node.js project\n ];\n\n for (const marker of markers) {\n const markerPath = resolve(currentDir, marker);\n logger.debug(`Checking for ${marker} at ${markerPath}`);\n if (existsSync(markerPath)) {\n logger.debug(`Found project root marker '${marker}' at: ${currentDir}`);\n return currentDir;\n }\n }\n\n // Move up one directory\n const parentDir = dirname(currentDir);\n if (parentDir === currentDir) {\n // Reached filesystem root\n break;\n }\n currentDir = parentDir;\n }\n\n // No project root found, use the starting directory\n logger.debug(`No project root markers found, using: ${startDir}`);\n return startDir;\n}\n\n/**\n * Resolve project context based on current directory and CLI options\n *\n * @param currentDir - Current working directory\n * @param options - CLI options\n * @returns Project context with resolved paths\n */\nexport function resolveProjectContext(\n currentDir: string,\n options: { envFile?: string } = {}\n): {\n projectRoot: string;\n envFile: string;\n pluginDirs: string[];\n} {\n // Ensure expected directory layout exists (best-effort).\n // This is intentionally done early so skills/agents/hooks/plugins can rely on it.\n const absCwd = resolve(currentDir);\n try {\n ensurePkAgentUserDirs();\n // \"Project\" scope is the directory pk-agent was run from (currentDir).\n ensurePkAgentProjectDirs(absCwd);\n } catch (err) {\n logger.debug(`Failed to ensure .pk-agent directories: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n // Find project root from current directory\n const projectRoot = findProjectRoot(absCwd);\n\n // Also ensure the discovered project root so marker-based resolution keeps working.\n try {\n ensurePkAgentProjectDirs(projectRoot);\n } catch {\n // best-effort\n }\n\n // Resolve env file path\n let envFile: string;\n if (options.envFile) {\n // Explicit env file override\n envFile = resolve(options.envFile);\n } else {\n // Look for env files in project root\n const candidates = [\n resolve(projectRoot, '.env.local'),\n resolve(projectRoot, '.env'),\n ];\n\n envFile = candidates.find(f => existsSync(f)) || resolve(projectRoot, '.env');\n }\n\n // Resolve plugin directories\n const pluginDirs = [\n resolve(projectRoot, '.pk-agent', 'plugins'),\n resolve(homedir(), '.pk-agent', 'plugins'),\n ].filter(dir => existsSync(dir));\n\n return {\n projectRoot,\n envFile,\n pluginDirs,\n };\n}\n",
|
|
81
|
+
"import { Command } from \"commander\";\r\nimport { createServer, IncomingMessage, ServerResponse } from \"http\";\r\nimport { timingSafeEqual } from \"crypto\";\r\nimport { spawn, type ChildProcess } from \"child_process\";\r\nimport { resolve, relative, isAbsolute } from \"path\";\nimport { existsSync } from \"fs\";\r\nimport { glob } from \"glob\";\r\nimport { createInterface, type Interface as ReadlineInterface } from \"readline\";\r\nimport chalk from \"chalk\";\nimport { parseAgent } from \"../parser\";\nimport { resolveProjectContext } from \"../utils/project\";\nimport { logger, LogLevel, executionLog } from \"../utils/logger\";\nimport { printLogo } from \"../utils/branding\";\nimport { initStorage } from \"../storage/index.js\";\nimport { Scheduler, type Schedule } from \"../scheduler\";\nimport { FileWatcher } from \"../watcher\";\r\nimport { telemetry, parseModel } from \"../telemetry\";\r\nimport { version as packageVersion } from \"../../package.json\";\r\nimport { validateAgentEnvVars, formatEnvValidationError } from \"../utils/env-validation\";\r\nimport { registerServer, unregisterServer, updateServer, listServers, formatUptime, type ServerEntry } from \"../utils/server-registry\";\r\nimport { homedir } from \"os\";\nimport * as dotenv from \"dotenv\";\nimport { ensurePkAgentDirs } from \"../utils/pk-agent-dirs\";\nimport { resolveAppConfig, applyAppConfigDefaultsToAgentConfig } from \"../config/app-config\";\n\r\nfunction readRawBody(req: IncomingMessage, maxBytes: number = 10 * 1024 * 1024): Promise<Buffer> {\r\n return new Promise((resolve, reject) => {\r\n const chunks: Buffer[] = [];\r\n let total = 0;\r\n\r\n req.on(\"data\", (chunk) => {\r\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\r\n total += buf.length;\r\n if (total > maxBytes) {\r\n reject(new Error(`Request body too large (>${maxBytes} bytes)`));\r\n try {\r\n req.destroy();\r\n } catch {\r\n // ignore\r\n }\r\n return;\r\n }\r\n chunks.push(buf);\r\n });\r\n\r\n req.on(\"end\", () => resolve(Buffer.concat(chunks)));\r\n req.on(\"error\", reject);\r\n });\r\n}\r\n\r\ninterface RunRequest {\r\n agent: string;\r\n prompt?: string;\r\n model?: string;\r\n timeout?: number;\r\n maxSteps?: number;\r\n}\r\n\r\ninterface RunResponse {\r\n success: true;\r\n sessionId?: string;\r\n result: {\r\n text: string;\r\n finishReason?: string;\r\n duration: number;\r\n tokens?: { input: number; output: number };\r\n toolCalls: number;\r\n };\r\n}\r\n\r\ninterface RunErrorResponse {\r\n success: false;\r\n error: {\r\n code: string;\r\n message: string;\r\n };\r\n}\r\n\r\ninterface WorkerExecuteOptions {\r\n agentPath: string;\r\n projectRoot: string;\r\n prompt?: string | undefined;\r\n model?: string | undefined;\r\n timeout?: number | undefined;\r\n maxSteps?: number | undefined;\r\n debug?: boolean | undefined;\r\n}\r\n\r\ninterface WorkerExecuteResult {\r\n success: true;\r\n result: {\r\n text: string;\r\n finishReason?: string;\r\n duration: number;\r\n tokens?: { input: number; output: number };\r\n toolCalls: number;\r\n };\r\n}\r\n\r\ninterface WorkerExecuteError {\r\n success: false;\r\n error: {\r\n code: string;\r\n message: string;\r\n };\r\n}\r\n\r\n/**\r\n * Agent Worker Manager\r\n *\r\n * Spawns and manages a worker process for agent execution.\r\n * The worker is spawned at serve startup (sync context) where spawn works,\r\n * and stays alive to handle execution requests via stdin/stdout IPC.\r\n *\r\n * This works around the EBADF issue where spawn() fails in async callback\r\n * contexts (HTTP handlers, scheduler callbacks) in bundled Node.js code.\r\n */\r\nclass AgentWorker {\n private process: ChildProcess | null = null;\n private readline: ReadlineInterface | null = null;\n private pendingRequests: Map<string, {\n resolve: (value: WorkerExecuteResult | WorkerExecuteError) => void;\n timeoutId?: NodeJS.Timeout;\n onEvent?: (event: any) => void;\n }> = new Map();\n private requestCounter = 0;\n private ready = false;\n private readyPromise: Promise<void> | null = null;\n private readyResolve: (() => void) | null = null;\n\r\n /**\r\n * Spawn the worker process. Must be called during server startup (sync context).\r\n */\r\n spawn(): Promise<void> {\r\n // Fork the same CLI with --internal-worker flag\r\n // This avoids needing a separate worker bundle - more elegant for npm package\r\n const cliPath = process.argv[1];\r\n\r\n this.readyPromise = new Promise((resolve, reject) => {\r\n this.readyResolve = resolve;\r\n\r\n // Timeout if worker doesn't become ready within 10 seconds\r\n const startupTimeout = setTimeout(() => {\r\n if (!this.ready) {\r\n reject(new Error(\"Worker failed to start within 10 seconds\"));\r\n this.shutdown();\r\n }\r\n }, 10000);\r\n\r\n // Clear timeout when ready\r\n const originalResolve = this.readyResolve;\r\n this.readyResolve = () => {\r\n clearTimeout(startupTimeout);\r\n originalResolve?.();\r\n };\r\n });\r\n\r\n this.process = spawn(process.execPath, [cliPath, \"--internal-worker\"], {\r\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\r\n env: process.env,\r\n });\r\n\r\n this.readline = createInterface({\r\n input: this.process.stdout!,\r\n terminal: false,\r\n });\r\n\r\n this.readline.on(\"line\", (line) => {\r\n this.handleWorkerMessage(line);\r\n });\r\n\r\n this.process.stderr?.on(\"data\", (data) => {\r\n logger.debug(`[Worker stderr] ${data.toString().trim()}`);\r\n });\r\n\r\n this.process.on(\"error\", (err) => {\r\n logger.error(`Worker process error: ${err.message}`);\r\n this.handleWorkerDeath();\r\n });\r\n\r\n this.process.on(\"exit\", (code) => {\r\n logger.warn(`Worker process exited with code ${code}`);\r\n this.handleWorkerDeath();\r\n });\r\n\r\n return this.readyPromise;\r\n }\r\n\r\n private handleWorkerMessage(line: string) {\n if (!line.trim()) return;\n\n try {\n const message = JSON.parse(line);\n\n // Handle ready signal\n if (message.type === \"ready\") {\n this.ready = true;\n if (this.readyResolve) {\n this.readyResolve();\n this.readyResolve = null;\n }\n return;\n }\n\n // Handle streaming event\n if (message.type === \"event\" && message.id) {\n const pending = this.pendingRequests.get(message.id);\n if (pending?.onEvent) {\n try {\n pending.onEvent(message.event);\n } catch {\n // ignore handler errors\n }\n }\n return;\n }\n\n // Handle done response\n if (message.type === \"done\" && message.id) {\n const pending = this.pendingRequests.get(message.id);\n if (pending) {\n if (pending.timeoutId) {\n clearTimeout(pending.timeoutId);\n }\n this.pendingRequests.delete(message.id);\n pending.resolve(message);\n }\n return;\n }\n\n // Backwards compatibility: handle legacy {id, success,...} shape.\n const pending = this.pendingRequests.get(message.id);\n if (pending) {\n if (pending.timeoutId) {\n clearTimeout(pending.timeoutId);\n }\n this.pendingRequests.delete(message.id);\n pending.resolve(message);\n }\n } catch (err) {\n logger.debug(`Failed to parse worker message: ${line}`);\n }\n }\n\r\n private handleWorkerDeath() {\r\n this.ready = false;\r\n this.process = null;\r\n this.readline = null;\r\n\r\n // Reject all pending requests\r\n for (const pending of this.pendingRequests.values()) {\r\n if (pending.timeoutId) {\r\n clearTimeout(pending.timeoutId);\r\n }\r\n pending.resolve({\r\n success: false,\r\n error: { code: \"WORKER_DIED\", message: \"Worker process died unexpectedly\" },\r\n });\r\n }\r\n this.pendingRequests.clear();\r\n }\r\n\r\n /**\r\n * Execute an agent via the worker process.\r\n */\r\n execute(options: WorkerExecuteOptions): Promise<WorkerExecuteResult | WorkerExecuteError> {\n return new Promise((resolve) => {\n if (!this.process || !this.ready) {\n resolve({\n success: false,\n error: { code: \"WORKER_NOT_READY\", message: \"Worker process not ready\" },\n });\n return;\n }\n\n const id = `req-${++this.requestCounter}`;\n const timeoutMs = (options.timeout ?? 300) * 1000 + 5000; // Add 5s buffer\n\r\n const timeoutId = setTimeout(() => {\r\n const pending = this.pendingRequests.get(id);\r\n if (pending) {\r\n this.pendingRequests.delete(id);\r\n pending.resolve({\r\n success: false,\r\n error: { code: \"TIMEOUT\", message: `Request timed out after ${options.timeout ?? 300}s` },\r\n });\r\n }\r\n }, timeoutMs);\r\n\r\n this.pendingRequests.set(id, { resolve, timeoutId });\n\n const request = {\n id,\n type: \"execute\",\n agentPath: options.agentPath,\n projectRoot: options.projectRoot,\n prompt: options.prompt,\n model: options.model,\n timeout: options.timeout,\n maxSteps: options.maxSteps,\n debug: options.debug,\n stream: false,\n };\n\n this.process.stdin!.write(JSON.stringify(request) + \"\\n\");\n });\n }\n\n /**\n * Execute an agent via the worker process, emitting streaming events.\n */\n executeWithEvents(\n options: WorkerExecuteOptions,\n onEvent: (event: any) => void\n ): Promise<WorkerExecuteResult | WorkerExecuteError> {\n return new Promise((resolve) => {\n if (!this.process || !this.ready) {\n resolve({\n success: false,\n error: { code: \"WORKER_NOT_READY\", message: \"Worker process not ready\" },\n });\n return;\n }\n\n const id = `req-${++this.requestCounter}`;\n const timeoutMs = (options.timeout ?? 300) * 1000 + 5000; // Add 5s buffer\n\n const timeoutId = setTimeout(() => {\n const pending = this.pendingRequests.get(id);\n if (pending) {\n this.pendingRequests.delete(id);\n pending.resolve({\n success: false,\n error: { code: \"TIMEOUT\", message: `Request timed out after ${options.timeout ?? 300}s` },\n });\n }\n }, timeoutMs);\n\n this.pendingRequests.set(id, { resolve, timeoutId, onEvent });\n\n const request = {\n id,\n type: \"execute\",\n agentPath: options.agentPath,\n projectRoot: options.projectRoot,\n prompt: options.prompt,\n model: options.model,\n timeout: options.timeout,\n maxSteps: options.maxSteps,\n debug: options.debug,\n stream: true,\n };\n\n this.process.stdin!.write(JSON.stringify(request) + \"\\n\");\n });\n }\n\r\n /**\r\n * Shutdown the worker process.\r\n */\r\n shutdown() {\r\n if (this.process) {\r\n this.process.kill(\"SIGTERM\");\r\n this.process = null;\r\n }\r\n if (this.readline) {\r\n this.readline.close();\r\n this.readline = null;\r\n }\r\n this.ready = false;\r\n }\r\n\r\n isReady(): boolean {\r\n return this.ready;\r\n }\r\n}\r\n\r\nfunction parseRequestBody(req: IncomingMessage): Promise<RunRequest> {\n return readRawBody(req, 1024 * 1024).then((raw) => {\n let parsed: any;\n try {\n parsed = JSON.parse(raw.toString(\"utf8\"));\n } catch {\n throw new Error(\"Invalid JSON body\");\n }\n\n if (!parsed.agent || typeof parsed.agent !== \"string\") {\n throw new Error(\"Missing required field: agent\");\n }\n\n return parsed as RunRequest;\n });\n}\n\nfunction isPathWithinRoot(candidatePath: string, rootPath: string): boolean {\n const rel = relative(rootPath, candidatePath);\n return rel === \"\" || (!rel.startsWith(\"..\") && !isAbsolute(rel));\n}\n\r\nfunction sendJSON(res: ServerResponse, status: number, data: RunResponse | RunErrorResponse) {\r\n res.writeHead(status, { \"Content-Type\": \"application/json\" });\r\n res.end(JSON.stringify(data));\r\n}\r\n\r\nfunction sendError(res: ServerResponse, status: number, code: string, message: string) {\r\n sendJSON(res, status, { success: false, error: { code, message } });\r\n}\r\n\r\nfunction isExposedHost(host: string): boolean {\r\n return host !== \"127.0.0.1\" && host !== \"localhost\";\r\n}\r\n\r\nfunction validateApiKey(req: IncomingMessage, expectedKey: string | undefined): boolean {\r\n if (!expectedKey) return true;\r\n\r\n const authHeader = req.headers.authorization;\r\n if (!authHeader?.startsWith(\"Bearer \")) return false;\r\n\r\n const providedKey = authHeader.slice(7);\r\n if (!providedKey) return false;\r\n\r\n // Constant-time comparison to prevent timing attacks\r\n try {\r\n const expected = Buffer.from(expectedKey);\r\n const provided = Buffer.from(providedKey);\r\n return expected.length === provided.length && timingSafeEqual(expected, provided);\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nfunction getHeaderValue(headers: IncomingMessage[\"headers\"], name: string): string | undefined {\r\n const raw = headers[name.toLowerCase() as keyof typeof headers];\r\n if (Array.isArray(raw)) return raw[0];\r\n return typeof raw === \"string\" ? raw : undefined;\r\n}\r\n\r\n// Very small in-memory dedupe to avoid double-processing rare duplicate deliveries.\r\nconst openaiWebhookSeenIds = new Set<string>();\r\n\r\nasync function handleOpenAIWebhook(req: IncomingMessage, res: ServerResponse) {\r\n const secret = process.env.OPENAI_WEBHOOK_SECRET;\r\n if (!secret) {\r\n sendError(res, 500, \"OPENAI_WEBHOOK_SECRET_MISSING\", \"OPENAI_WEBHOOK_SECRET is not set\");\r\n return;\r\n }\r\n\r\n const rawBody = await readRawBody(req);\r\n\r\n let OpenAI: any;\r\n try {\r\n OpenAI = (await import(\"openai\")).default;\r\n } catch {\r\n sendError(res, 500, \"OPENAI_SDK_MISSING\", \"Missing dependency: openai. Install it with: pnpm add openai\");\r\n return;\r\n }\r\n\r\n const client = new OpenAI({\r\n webhookSecret: secret,\r\n // apiKey is optional for unwrap(), but required if we want to retrieve resources later.\r\n ...(process.env.OPENAI_API_KEY ? { apiKey: process.env.OPENAI_API_KEY } : {}),\r\n });\r\n\r\n let event: any;\r\n try {\r\n // Signature verification must use the raw request body (not JSON-parsed).\r\n event = await client.webhooks.unwrap(rawBody.toString(\"utf8\"), req.headers);\r\n } catch (error: any) {\r\n if (error instanceof OpenAI.InvalidWebhookSignatureError) {\r\n res.writeHead(400, { \"Content-Type\": \"text/plain\" });\r\n res.end(\"Invalid signature\");\r\n return;\r\n }\r\n sendError(res, 400, \"OPENAI_WEBHOOK_INVALID\", error?.message || \"Invalid webhook\");\r\n return;\r\n }\r\n\r\n const webhookId = getHeaderValue(req.headers, \"webhook-id\");\r\n if (webhookId) {\r\n if (openaiWebhookSeenIds.has(webhookId)) {\r\n // Ack duplicates.\r\n res.writeHead(200);\r\n res.end();\r\n return;\r\n }\r\n openaiWebhookSeenIds.add(webhookId);\r\n if (openaiWebhookSeenIds.size > 10_000) {\r\n openaiWebhookSeenIds.clear();\r\n }\r\n }\r\n\r\n // Ack fast (non-trivial processing happens async).\r\n res.writeHead(200);\r\n res.end();\r\n\r\n // Background processing (don't block delivery acks).\r\n void (async () => {\r\n try {\r\n logger.info(`[OpenAI webhook] ${event.type} (${event.id})`);\r\n\r\n if (event.type === \"response.completed\") {\r\n const responseId = event.data?.id;\r\n if (!responseId) return;\r\n if (!process.env.OPENAI_API_KEY) {\r\n logger.debug(\"[OpenAI webhook] OPENAI_API_KEY not set; skipping response retrieval\");\r\n return;\r\n }\r\n\r\n const response = await client.responses.retrieve(responseId);\r\n const outputText =\r\n typeof response.output_text === \"string\"\r\n ? response.output_text\r\n : (response.output || [])\r\n .filter((item: any) => item.type === \"message\")\r\n .flatMap((item: any) => item.content || [])\r\n .filter((c: any) => c.type === \"output_text\")\r\n .map((c: any) => c.text)\r\n .join(\"\");\r\n\r\n if (outputText) {\r\n logger.info(`[OpenAI webhook] response.completed: ${responseId}`);\r\n logger.info(outputText);\r\n } else {\r\n logger.debug(`[OpenAI webhook] response.completed: ${responseId} (no output_text)`);\r\n }\r\n }\r\n } catch (err: any) {\r\n logger.warn(`[OpenAI webhook] processing failed: ${err?.message || String(err)}`);\r\n }\r\n })();\r\n}\r\n\r\nexport function createServeCommand(): Command {\r\n const openaiWebhookPath = process.env.PK_AGENT_OPENAI_WEBHOOK_PATH ?? \"/webhook/openai\";\r\n\r\n const serveCmd = new Command(\"serve\")\r\n .description(\"Start an HTTP server to run agents via API\")\r\n .option(\"-p, --port <number>\", \"Port to listen on\", \"12233\")\r\n .option(\"-H, --host <string>\", \"Host to bind to\", \"127.0.0.1\")\r\n .option(\"-C, --directory <path>\", \"Working directory for agent resolution\")\r\n .option(\"-d, --debug\", \"Enable debug mode\")\r\n .option(\"--no-auth\", \"Disable API key requirement for exposed hosts (dangerous)\")\r\n .action(async (options: { port: string; host: string; directory?: string; debug?: boolean; auth: boolean }) => {\r\n const port = parseInt(options.port, 10);\r\n if (isNaN(port) || port <= 0 || port > 65535) {\r\n console.error(\"Invalid port number\");\r\n process.exit(1);\r\n }\r\n\r\n // Check API key requirement for exposed hosts\r\n const apiKey = process.env.PK_AGENT_API_KEY;\r\n const authDisabled = options.auth === false;\r\n\r\n if (isExposedHost(options.host) && !apiKey && !authDisabled) {\r\n console.error(chalk.red(\"Error: API key required when binding to exposed host\"));\r\n console.error(chalk.dim(\"Set PK_AGENT_API_KEY environment variable or use --no-auth to bypass (dangerous)\"));\r\n process.exit(1);\r\n }\r\n\r\n // Configure logging\r\n if (options.debug) {\r\n logger.configure({ level: LogLevel.DEBUG, enableDebug: true });\r\n process.env.PK_AGENT_DEBUG = \"true\";\r\n }\r\n\r\n // Resolve working directory.\n // Precedence: CLI -C/--directory > PK_AGENT_DEFAULT_DIRECTORY env > config defaultDirectory.\n const defaultDir = (() => {\n if (options.directory) return options.directory;\n const envDir = process.env.PK_AGENT_DEFAULT_DIRECTORY;\n if (envDir && envDir.trim()) return envDir.trim();\n return resolveAppConfig(process.cwd()).effective.defaultDirectory;\n })();\n const workDir = defaultDir ? resolve(defaultDir) : process.cwd();\n if (!existsSync(workDir)) {\n console.error(`Directory not found: ${workDir}`);\n process.exit(1);\n }\n\r\n // Resolve project context\r\n // If --directory is explicitly specified, use it directly as project root\r\n // Otherwise, search upward for project markers\r\n const projectContext = options.directory\n ? {\n projectRoot: workDir,\n envFile: existsSync(resolve(workDir, '.env.local'))\n ? resolve(workDir, '.env.local')\n : resolve(workDir, '.env'),\n pluginDirs: [\n resolve(workDir, '.pk-agent', 'plugins'),\n resolve(homedir(), '.pk-agent', 'plugins'),\n ],\n }\n : resolveProjectContext(workDir);\n logger.info(`Project root: ${projectContext.projectRoot}`);\n\n // Ensure expected directory layout exists (USER first, PROJECT second).\n // Best-effort: keep serving even if directories cannot be created.\n try {\n ensurePkAgentDirs(projectContext.projectRoot);\n } catch (err) {\n logger.debug(`Failed to ensure .pk-agent directories: ${err instanceof Error ? err.message : String(err)}`);\n }\n\r\n // Check if a server is already running for this project\r\n const existingServers = listServers();\r\n const existingServer = existingServers.find(s => s.projectRoot === projectContext.projectRoot);\r\n if (existingServer) {\r\n console.error(chalk.red(`\\nError: A server is already running for this project.`));\r\n console.error(chalk.dim(`\\n PID: ${existingServer.pid}`));\r\n console.error(chalk.dim(` Port: ${existingServer.port}`));\r\n console.error(chalk.dim(`\\nTo see all running servers: pk-agent serve ps`));\r\n process.exit(1);\r\n }\r\n\r\n // Load environment\n if (existsSync(projectContext.envFile)) {\n dotenv.config({ path: projectContext.envFile, quiet: true });\n logger.debug(`Loaded env from: ${projectContext.envFile}`);\n }\n\n // Resolve app-level defaults once per server process (env > project config > user config > built-in defaults).\n const appCfg = resolveAppConfig(projectContext.projectRoot);\n const parseAgentWithDefaults = async (agentPath: string) => {\n const agent = await parseAgent(agentPath);\n applyAppConfigDefaultsToAgentConfig(agent.config, appCfg);\n return agent;\n };\n\n // Initialize storage\n try {\n await initStorage(projectContext.projectRoot);\n logger.debug(\"Session storage initialized\");\n } catch (err) {\n logger.warn(`Failed to initialize session storage: ${(err as Error).message}`);\r\n }\r\n\r\n // Initialize telemetry\r\n await telemetry.init(packageVersion);\r\n\r\n // Spawn agent worker at startup (sync context where spawn works)\r\n // This worker handles agent execution to work around EBADF in async callbacks\r\n const worker = new AgentWorker();\r\n try {\r\n await worker.spawn();\r\n logger.debug(\"Agent worker spawned successfully\");\r\n } catch (err) {\r\n console.error(chalk.red(`Failed to spawn agent worker: ${(err as Error).message}`));\r\n process.exit(1);\r\n }\r\n\r\n // Execution stats tracking\r\n const serverStartTime = Date.now();\r\n let totalExecutions = 0;\r\n let successfulExecutions = 0;\r\n let failedExecutions = 0;\r\n\r\n // Helper function to execute an agent (used by scheduler)\r\n // Uses subprocess to work around EBADF issue when spawning from async callbacks\r\n const executeScheduledAgent = async (\r\n schedule: Schedule\r\n ): Promise<{ success: boolean; duration: number; error?: string; sessionId?: string }> => {\r\n const startTime = Date.now();\r\n const agentPath = resolve(projectContext.projectRoot, schedule.agentPath);\r\n\r\n // Parse agent for telemetry and validation\r\n let agent: Awaited<ReturnType<typeof parseAgent>> | undefined;\r\n try {\r\n agent = await parseAgentWithDefaults(agentPath);\n\r\n // Pre-flight environment variable validation\r\n const envValidation = validateAgentEnvVars(agent.config);\r\n if (!envValidation.valid) {\r\n throw new Error(formatEnvValidationError(envValidation));\r\n }\r\n } catch (parseError) {\r\n const duration = Date.now() - startTime;\r\n totalExecutions++;\r\n failedExecutions++;\r\n return {\r\n success: false,\r\n duration,\r\n error: (parseError as Error).message,\r\n };\r\n }\r\n\r\n // Execute via worker process to work around EBADF issue in async callbacks\r\n const spawnResult = await worker.execute({\r\n agentPath: schedule.agentPath, // Use relative path\r\n projectRoot: projectContext.projectRoot,\r\n timeout: agent.config.timeout,\r\n maxSteps: agent.config.maxSteps,\r\n debug: options.debug,\r\n });\r\n\r\n const duration = Date.now() - startTime;\r\n\r\n if (spawnResult.success) {\r\n totalExecutions++;\r\n successfulExecutions++;\r\n\r\n // Capture telemetry for scheduled execution\r\n telemetry.captureExecution({\r\n ...parseModel(agent.config.model),\r\n durationMs: duration,\r\n inputTokens: spawnResult.result.tokens?.input ?? 0,\r\n outputTokens: spawnResult.result.tokens?.output ?? 0,\r\n success: true,\r\n features: {\r\n mcpServersCount: Object.keys(agent.config.mcpServers || {}).length,\r\n subagentsConfigured: agent.config.subagents?.length ?? 0,\r\n skillsUsed: false,\r\n mode: 'schedule',\r\n },\r\n config: {\r\n timeoutCustom: agent.config.timeout !== undefined,\r\n maxStepsCustom: agent.config.maxSteps !== undefined,\r\n quietMode: true,\r\n debugMode: options.debug ?? false,\r\n },\r\n });\r\n\r\n return {\r\n success: true,\r\n duration,\r\n };\r\n } else {\r\n totalExecutions++;\r\n failedExecutions++;\r\n\r\n // Capture telemetry for failed scheduled execution\r\n telemetry.captureExecution({\r\n ...parseModel(agent.config.model),\r\n durationMs: duration,\r\n inputTokens: 0,\r\n outputTokens: 0,\r\n success: false,\r\n errorType: spawnResult.error.code === 'TIMEOUT' ? 'timeout' : 'unknown',\r\n features: {\r\n mcpServersCount: Object.keys(agent.config.mcpServers || {}).length,\r\n subagentsConfigured: agent.config.subagents?.length ?? 0,\r\n skillsUsed: false,\r\n mode: 'schedule',\r\n },\r\n });\r\n\r\n return {\r\n success: false,\r\n duration,\r\n error: spawnResult.error.message,\r\n };\r\n }\r\n };\r\n\r\n // Initialize scheduler\r\n const scheduler = new Scheduler({\r\n onExecute: executeScheduledAgent,\r\n });\r\n\r\n // Scan for agents with schedule config\r\n const agentFiles = await glob(\"**/*.pk-agent\", {\r\n cwd: projectContext.projectRoot,\r\n ignore: [\"node_modules/**\", \"tmp/**\", \".git/**\"],\r\n });\r\n\r\n // Track agent count for registry updates (mutable for hot reload)\r\n let currentAgentCount = agentFiles.length;\r\n\r\n // Helper to update the server registry after hot reload changes\r\n const updateRegistryCounts = () => {\r\n updateServer({\r\n agentCount: currentAgentCount,\r\n scheduleCount: scheduler.list().length,\r\n });\r\n };\r\n\r\n for (const agentFile of agentFiles) {\r\n try {\r\n const agentPath = resolve(projectContext.projectRoot, agentFile);\r\n const agent = await parseAgentWithDefaults(agentPath);\n\r\n if (agent.config.schedule) {\r\n scheduler.add(agentFile, agent.config.schedule);\r\n logger.debug(`Loaded schedule for: ${agentFile}`);\r\n }\r\n } catch (err) {\r\n logger.warn(`Failed to load agent ${agentFile}: ${(err as Error).message}`);\r\n }\r\n }\r\n\r\n // Helper to print hot reload messages\r\n const printHotReload = (action: \"added\" | \"changed\" | \"removed\", path: string, schedule?: Schedule) => {\r\n const actionColor = action === \"added\" ? chalk.green : action === \"removed\" ? chalk.red : chalk.yellow;\r\n console.log(` ${chalk.cyan(\"Hot reload\")} Agent ${actionColor(action)}: ${chalk.dim(path)}`);\r\n if (schedule) {\r\n const nextRun = schedule.nextRun?.toLocaleString(\"en-US\", {\r\n month: \"short\",\r\n day: \"2-digit\",\r\n hour: \"2-digit\",\r\n minute: \"2-digit\",\r\n hour12: false,\r\n }) || \"N/A\";\r\n console.log(` Schedule: ${chalk.dim(schedule.expression)} ${chalk.dim(`(next: ${nextRun})`)}`);\r\n }\r\n };\r\n\r\n // Initialize file watcher for hot reload\r\n const fileWatcher = new FileWatcher({\r\n projectRoot: projectContext.projectRoot,\r\n envFile: projectContext.envFile,\r\n\r\n onAgentAdded: async (relativePath: string) => {\r\n try {\r\n const agentPath = resolve(projectContext.projectRoot, relativePath);\r\n const agent = await parseAgentWithDefaults(agentPath);\n\r\n const schedule = agent.config.schedule ? scheduler.add(relativePath, agent.config.schedule) : undefined;\r\n printHotReload(\"added\", relativePath, schedule);\r\n\r\n // Update registry\r\n currentAgentCount++;\r\n updateRegistryCounts();\r\n } catch (err) {\r\n logger.warn(`Hot reload: Failed to parse new agent ${relativePath}: ${(err as Error).message}`);\r\n }\r\n },\r\n\r\n onAgentChanged: async (relativePath: string) => {\r\n try {\r\n const agentPath = resolve(projectContext.projectRoot, relativePath);\r\n const agent = await parseAgentWithDefaults(agentPath);\n\r\n const schedule = scheduler.update(relativePath, agent.config.schedule);\r\n printHotReload(\"changed\", relativePath, schedule);\r\n\r\n // Update registry (schedule count may have changed)\r\n updateRegistryCounts();\r\n } catch (err) {\r\n logger.warn(`Hot reload: Failed to parse changed agent ${relativePath}: ${(err as Error).message}`);\r\n }\r\n },\r\n\r\n onAgentRemoved: (relativePath: string) => {\r\n const hadSchedule = scheduler.removeByAgentPath(relativePath);\r\n printHotReload(\"removed\", relativePath);\r\n if (hadSchedule) {\r\n logger.debug(`Hot reload: Unregistered schedule for ${relativePath}`);\r\n }\r\n\r\n // Update registry\r\n currentAgentCount--;\r\n updateRegistryCounts();\r\n },\r\n\r\n onEnvReloaded: () => {\r\n // Environment variables are reloaded in process.env\r\n // New requests will pick up the changes automatically\r\n },\r\n });\r\n\r\n // Start watching for file changes\r\n fileWatcher.start();\r\n\r\n const server = createServer(async (req, res) => {\r\n // CORS headers\r\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\r\n res.setHeader(\"Access-Control-Allow-Methods\", \"POST, OPTIONS\");\r\n res.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type, Accept, Authorization\");\r\n\r\n if (req.method === \"OPTIONS\") {\r\n res.writeHead(204);\r\n res.end();\r\n return;\r\n }\r\n\r\n // OpenAI webhooks (signature-verified). Deliberately bypasses PK_AGENT_API_KEY auth.\r\n if (req.method === \"POST\" && req.url === openaiWebhookPath) {\r\n await handleOpenAIWebhook(req, res);\r\n return;\r\n }\r\n\r\n // Auth check\r\n if (apiKey && !validateApiKey(req, apiKey)) {\r\n sendError(res, 401, \"UNAUTHORIZED\", \"Invalid or missing Authorization header. Use: Authorization: Bearer <key>\");\r\n return;\r\n }\r\n\r\n if (req.method !== \"POST\" || req.url !== \"/run\") {\r\n sendError(res, 404, \"NOT_FOUND\", \"Endpoint not found. Use POST /run\");\r\n return;\r\n }\r\n\r\n const startTime = Date.now();\r\n\r\n try {\r\n // Parse request\r\n const body = await parseRequestBody(req);\r\n const wantsStream = req.headers.accept?.includes(\"application/x-ndjson\");\r\n\r\n // Resolve agent path\r\n const agentPath = resolve(projectContext.projectRoot, body.agent);\r\n if (!existsSync(agentPath)) {\r\n sendError(res, 404, \"AGENT_NOT_FOUND\", `Agent file not found: ${body.agent}`);\r\n return;\r\n }\r\n\r\n // Security: ensure agent is within project root\r\n if (!isPathWithinRoot(agentPath, projectContext.projectRoot)) {\n sendError(res, 400, \"INVALID_PATH\", \"Agent path must be within project root\");\n return;\n }\n\r\n executionLog.start(body.agent);\r\n\r\n // Parse agent for validation and telemetry\r\n const agent = await parseAgentWithDefaults(agentPath);\n\r\n // Pre-flight environment variable validation\r\n const envValidation = validateAgentEnvVars(agent.config);\r\n if (!envValidation.valid) {\r\n sendError(res, 500, \"ENV_MISSING\", formatEnvValidationError(envValidation));\r\n return;\r\n }\r\n\r\n // Create abort controller for timeout\n const timeoutSeconds = body.timeout ?? agent.config.timeout ?? 300;\n const abortController = new AbortController();\n const timeoutId = setTimeout(() => abortController.abort(), timeoutSeconds * 1000);\n\r\n // Handle client disconnect\r\n req.on(\"close\", () => {\r\n abortController.abort();\r\n });\r\n\r\n // Execute via worker process to work around EBADF issue in async callbacks.\n // When streaming, forward the worker's event stream to the client as NDJSON.\n let spawnResult: WorkerExecuteResult | WorkerExecuteError;\n if (wantsStream) {\n res.writeHead(200, {\n \"Content-Type\": \"application/x-ndjson\",\n \"Transfer-Encoding\": \"chunked\",\n \"Cache-Control\": \"no-cache\",\n \"Connection\": \"keep-alive\",\n });\n\n const safeWrite = (obj: any) => {\n if (res.writableEnded) return;\n try {\n res.write(JSON.stringify(obj) + \"\\n\");\n } catch {\n // ignore serialization failures\n }\n };\n\n spawnResult = await worker.executeWithEvents({\n agentPath: body.agent, // Use relative path, worker resolves from projectRoot\n projectRoot: projectContext.projectRoot,\n prompt: body.prompt,\n model: body.model,\n timeout: timeoutSeconds,\n maxSteps: body.maxSteps,\n debug: options.debug,\n }, (event) => {\n safeWrite(event);\n });\n\n // Always end the NDJSON stream with a done marker.\n safeWrite({ type: \"done\", ...spawnResult });\n res.end();\n } else {\n // Non-stream JSON response.\n spawnResult = await worker.execute({\n agentPath: body.agent, // Use relative path, worker resolves from projectRoot\n projectRoot: projectContext.projectRoot,\n prompt: body.prompt,\n model: body.model,\n timeout: timeoutSeconds,\n maxSteps: body.maxSteps,\n debug: options.debug,\n });\n }\n\n clearTimeout(timeoutId);\n const duration = Date.now() - startTime;\n\n if (spawnResult.success) {\n totalExecutions++;\r\n successfulExecutions++;\r\n\r\n // Capture telemetry\r\n telemetry.captureExecution({\r\n ...parseModel(body.model || agent.config.model),\r\n durationMs: duration,\r\n inputTokens: spawnResult.result.tokens?.input ?? 0,\r\n outputTokens: spawnResult.result.tokens?.output ?? 0,\r\n success: true,\r\n features: {\r\n mcpServersCount: Object.keys(agent.config.mcpServers || {}).length,\r\n subagentsConfigured: agent.config.subagents?.length ?? 0,\r\n skillsUsed: false,\r\n mode: 'webhook',\r\n },\r\n config: {\r\n timeoutCustom: body.timeout !== undefined || agent.config.timeout !== undefined,\r\n maxStepsCustom: body.maxSteps !== undefined || agent.config.maxSteps !== undefined,\r\n quietMode: true,\r\n debugMode: options.debug ?? false,\r\n },\r\n });\r\n\r\n executionLog.complete(body.agent, duration);\r\n\r\n if (!wantsStream) {\n // JSON response\n const response: RunResponse = {\n success: true,\n result: {\n text: spawnResult.result.text,\n ...(spawnResult.result.finishReason && { finishReason: spawnResult.result.finishReason }),\r\n duration,\r\n ...(spawnResult.result.tokens && { tokens: spawnResult.result.tokens }),\r\n toolCalls: spawnResult.result.toolCalls,\r\n },\r\n };\r\n sendJSON(res, 200, response);\n }\n } else {\n totalExecutions++;\n failedExecutions++;\n\r\n const errorCode = spawnResult.error.code;\r\n const errorMessage = spawnResult.error.message;\r\n\r\n // Capture telemetry\r\n telemetry.captureExecution({\r\n ...parseModel(body.model || agent.config.model),\r\n durationMs: duration,\r\n inputTokens: 0,\r\n outputTokens: 0,\r\n success: false,\r\n errorType: errorCode === 'TIMEOUT' ? 'timeout' : 'unknown',\r\n features: {\r\n mcpServersCount: Object.keys(agent.config.mcpServers || {}).length,\r\n subagentsConfigured: agent.config.subagents?.length ?? 0,\r\n skillsUsed: false,\r\n mode: 'webhook',\r\n },\r\n });\r\n\r\n if (errorCode === 'TIMEOUT') {\r\n executionLog.timeout(body.agent, duration);\r\n } else {\r\n executionLog.failed(body.agent, duration, errorMessage);\r\n }\r\n\r\n if (!wantsStream) {\n // JSON error response\n const httpStatus = errorCode === 'TIMEOUT' ? 504 : 500;\n sendError(res, httpStatus, errorCode, errorMessage);\n }\n }\n } catch (err) {\r\n const message = (err as Error).message;\r\n\r\n if (message.includes(\"Request body too large\")) {\n sendError(res, 413, \"PAYLOAD_TOO_LARGE\", message);\n } else if (message.includes(\"Invalid JSON\")) {\n sendError(res, 400, \"INVALID_REQUEST\", message);\n } else if (message.includes(\"Missing required\")) {\n sendError(res, 400, \"MISSING_FIELD\", message);\n } else if (message.includes(\"not found\")) {\r\n sendError(res, 404, \"AGENT_NOT_FOUND\", message);\r\n } else {\r\n sendError(res, 500, \"INTERNAL_ERROR\", message);\r\n }\r\n }\r\n });\r\n\r\n // Graceful shutdown\r\n const shutdown = async () => {\r\n console.log(\"\\nShutting down...\");\r\n\r\n // Unregister from process registry\r\n unregisterServer();\r\n\r\n scheduler.shutdown();\r\n worker.shutdown();\r\n\r\n // Capture server shutdown telemetry\r\n telemetry.captureServerShutdown({\r\n uptimeMs: Date.now() - serverStartTime,\r\n totalExecutions,\r\n successfulExecutions,\r\n failedExecutions,\r\n });\r\n await telemetry.shutdown();\r\n\r\n server.close(() => {\r\n console.log(\"Server closed\");\r\n process.exit(0);\r\n });\r\n };\r\n\r\n process.on(\"SIGINT\", shutdown);\r\n process.on(\"SIGTERM\", shutdown);\r\n\r\n // Handle server errors (e.g., port already in use)\r\n server.on(\"error\", (err: NodeJS.ErrnoException) => {\r\n if (err.code === \"EADDRINUSE\") {\r\n console.error(chalk.red(`\\nError: Port ${port} is already in use.`));\r\n console.error(chalk.dim(`\\nTry one of these:`));\r\n console.error(chalk.dim(` * Use a different port: pk-agent serve --port ${port + 1}`));\r\n console.error(chalk.dim(` * See running servers: pk-agent serve ps`));\r\n process.exit(1);\r\n }\r\n // Re-throw other errors\r\n throw err;\r\n });\r\n\r\n server.listen(port, options.host, () => {\r\n const serverUrl = `http://${options.host}:${port}`;\r\n const firstAgent = agentFiles[0] || \"path/to/agent.pk-agent\";\r\n const schedules = scheduler.list();\r\n\r\n // Register server in the process registry\r\n registerServer({\r\n port,\r\n host: options.host,\r\n projectRoot: projectContext.projectRoot,\r\n startTime: serverStartTime,\r\n agentCount: agentFiles.length,\r\n scheduleCount: schedules.length,\r\n version: packageVersion,\r\n });\r\n\r\n printLogo();\r\n\r\n // Server info\r\n console.log(` ${chalk.dim(\"Server\")} ${chalk.cyan(serverUrl)}`);\r\n console.log(` ${chalk.dim(\"Directory\")} ${projectContext.projectRoot}`);\r\n if (apiKey) {\r\n console.log(` ${chalk.dim(\"Auth\")} ${chalk.green(\"API key required\")}`);\r\n } else if (isExposedHost(options.host)) {\r\n console.log(` ${chalk.dim(\"Auth\")} ${chalk.yellow(\"No API key (--no-auth)\")}`);\r\n } else {\r\n console.log(` ${chalk.dim(\"Auth\")} ${chalk.dim(\"None (localhost)\")}`);\r\n }\r\n console.log(` ${chalk.dim(\"Hot reload\")} ${chalk.green(\"enabled\")}`);\r\n\r\n // Webhooks\r\n console.log(`\\n ${chalk.dim(\"Webhooks\")}`);\r\n const authHeader = apiKey ? ` -H \"Authorization: Bearer $PK_AGENT_API_KEY\"` : \"\";\r\n console.log(` curl -X POST ${serverUrl}/run${authHeader} -H \"Content-Type: application/json\" -d '{\"agent\": \"${firstAgent}\"}'`);\r\n console.log(` ${chalk.dim(`curl -N ... -H \"Accept: application/x-ndjson\" -d '{\"agent\": \"...\"}' (streaming)`)}`);\r\n\r\n // OpenAI webhooks (optional)\r\n if (process.env.OPENAI_WEBHOOK_SECRET) {\r\n console.log(`\\n ${chalk.dim(\"OpenAI Webhooks\")}`);\r\n console.log(` POST ${serverUrl}${openaiWebhookPath}`);\r\n console.log(` ${chalk.dim(\"Set OPENAI_WEBHOOK_SECRET to enable signature verification\")}`);\r\n }\r\n\r\n // Available agents for webhooks\r\n if (agentFiles.length > 0) {\r\n console.log(`\\n ${chalk.dim(`Agents (${agentFiles.length})`)}`);\r\n for (const agent of agentFiles) {\r\n console.log(` ${agent}`);\r\n }\r\n }\r\n // Scheduled agents\r\n if (schedules.length > 0) {\r\n console.log(`\\n ${chalk.dim(`Scheduled (${schedules.length})`)}`);\r\n console.log(scheduler.formatScheduleTable());\r\n }\r\n\r\n console.log();\r\n\r\n // Capture server start telemetry\r\n telemetry.captureServerStart({\r\n port,\r\n host: options.host,\r\n scheduledAgents: schedules.length,\r\n totalAgents: agentFiles.length,\r\n authEnabled: !!apiKey,\r\n });\r\n });\r\n });\r\n\r\n // Add ps subcommand\r\n serveCmd.addCommand(createPsSubcommand());\r\n\r\n return serveCmd;\r\n}\r\n\r\n// Helper functions for ps subcommand\r\nfunction truncatePath(path: string, maxLen: number): string {\r\n const homeDir = homedir();\r\n let displayPath = path.startsWith(homeDir) ? \"~\" + path.slice(homeDir.length) : path;\r\n if (displayPath.length <= maxLen) {\r\n return displayPath;\r\n }\r\n return \"...\" + displayPath.slice(-(maxLen - 3));\r\n}\r\n\r\nfunction formatPsTable(servers: ServerEntry[]): string {\r\n if (servers.length === 0) return \"\";\r\n\r\n const headers = [\"PID\", \"PORT\", \"PROJECT\", \"AGENTS\", \"SCHEDULES\", \"UPTIME\"];\r\n const widths = [7, 7, 40, 7, 10, 10];\r\n\r\n const headerRow = headers.map((h, i) => h.padEnd(widths[i])).join(\" \");\r\n const separator = widths.map((w) => \"-\".repeat(w)).join(\"--\");\r\n\r\n const rows = servers.map((s) => [\r\n String(s.pid).padEnd(widths[0]),\r\n String(s.port).padEnd(widths[1]),\r\n truncatePath(s.projectRoot, widths[2]).padEnd(widths[2]),\r\n String(s.agentCount).padEnd(widths[3]),\r\n String(s.scheduleCount).padEnd(widths[4]),\r\n formatUptime(s.startTime).padEnd(widths[5]),\r\n ].join(\" \"));\r\n\r\n return [chalk.dim(headerRow), chalk.dim(separator), ...rows].join(\"\\n\");\r\n}\r\n\r\nfunction createPsSubcommand(): Command {\r\n return new Command(\"ps\")\r\n .description(\"List running pk-agent serve instances\")\r\n .option(\"--json\", \"Output as JSON\")\r\n .action((options: { json?: boolean }) => {\r\n const servers = listServers();\r\n\r\n if (options.json) {\r\n console.log(JSON.stringify(servers, null, 2));\r\n return;\r\n }\r\n\r\n if (servers.length === 0) {\r\n console.log(chalk.dim(\"No running pk-agent serve instances found.\"));\r\n console.log(chalk.dim(\"\\nStart a server with: pk-agent serve\"));\r\n return;\r\n }\r\n\r\n console.log(formatPsTable(servers));\r\n console.log();\r\n console.log(chalk.dim(`${servers.length} server${servers.length === 1 ? \"\" : \"s\"} running`));\r\n });\r\n}\r\n",
|
|
82
|
+
"import chalk from 'chalk';\r\nimport { version } from '../../package.json';\r\n\r\nexport type BrandingStyle = 'full' | 'compact';\r\n\r\nexport function printLogo(style: BrandingStyle = 'full'): void {\r\n const name = chalk.cyanBright.bold('PK-AGENT');\r\n const ver = chalk.gray(`v${version}`);\r\n\r\n if (style === 'compact') {\r\n console.error(`${name} ${ver}`);\r\n return;\r\n }\r\n\r\n const divider = chalk.yellowBright('='.repeat(44));\r\n console.error(`${divider}\\n${name} ${ver}\\n${chalk.gray('Autonomous agents from markdown')}\\n${divider}`);\r\n}\r\n\r\n",
|
|
83
|
+
"import chokidar, { type FSWatcher } from \"chokidar\";\nimport { resolve, relative } from \"path\";\nimport { logger } from \"../utils/logger\";\nimport * as dotenv from \"dotenv\";\n\nexport interface FileWatcherOptions {\n projectRoot: string;\n envFile: string;\n onAgentAdded: (relativePath: string) => Promise<void>;\n onAgentChanged: (relativePath: string) => Promise<void>;\n onAgentRemoved: (relativePath: string) => void;\n onEnvReloaded: () => void;\n}\n\n/**\n * FileWatcher monitors .pk-agent files and environment files for changes,\n * enabling hot reload functionality for the serve command.\n */\nexport class FileWatcher {\n private agentWatcher: FSWatcher | null = null;\n private envWatcher: FSWatcher | null = null;\n private options: FileWatcherOptions;\n private closed = false;\n\n constructor(options: FileWatcherOptions) {\n this.options = options;\n }\n\n /**\n * Start watching for file changes\n */\n start(): void {\n if (this.closed) {\n throw new Error(\"FileWatcher has been closed and cannot be restarted\");\n }\n\n this.startAgentWatcher();\n this.startEnvWatcher();\n\n logger.debug(\"FileWatcher: Hot reload enabled\");\n }\n\n private isAgentFile(path: string): boolean {\n return path.endsWith(\".pk-agent\");\n }\n\n private shouldIgnore(path: string): boolean {\n const normalized = path.replace(/\\\\/g, \"/\");\n return (\n normalized.includes(\"node_modules\") ||\n normalized.includes(\"/tmp/\") ||\n normalized.includes(\"/.git/\") ||\n normalized.startsWith(\"tmp/\")\n );\n }\n\n private startAgentWatcher(): void {\n const { projectRoot, onAgentAdded, onAgentChanged, onAgentRemoved } = this.options;\n\n // Watch the project root directory for all changes\n // and filter for .pk-agent files manually\n this.agentWatcher = chokidar.watch(projectRoot, {\n ignored: [\n \"**/node_modules/**\",\n \"**/tmp/**\",\n \"**/.git/**\",\n ],\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 50,\n },\n });\n\n this.agentWatcher\n .on(\"add\", async (absolutePath) => {\n if (this.closed) return;\n if (!this.isAgentFile(absolutePath)) return;\n\n const relativePath = relative(projectRoot, absolutePath);\n if (this.shouldIgnore(relativePath)) return;\n\n try {\n await onAgentAdded(relativePath);\n } catch (err) {\n logger.warn(`Hot reload: Failed to add agent ${relativePath}: ${(err as Error).message}`);\n }\n })\n .on(\"change\", async (absolutePath) => {\n if (this.closed) return;\n if (!this.isAgentFile(absolutePath)) return;\n\n const relativePath = relative(projectRoot, absolutePath);\n if (this.shouldIgnore(relativePath)) return;\n\n try {\n await onAgentChanged(relativePath);\n } catch (err) {\n logger.warn(`Hot reload: Failed to reload agent ${relativePath}: ${(err as Error).message}`);\n }\n })\n .on(\"unlink\", (absolutePath) => {\n if (this.closed) return;\n if (!this.isAgentFile(absolutePath)) return;\n\n const relativePath = relative(projectRoot, absolutePath);\n if (this.shouldIgnore(relativePath)) return;\n\n try {\n onAgentRemoved(relativePath);\n } catch (err) {\n logger.warn(`Hot reload: Failed to remove agent ${relativePath}: ${(err as Error).message}`);\n }\n })\n .on(\"error\", (error: unknown) => {\n logger.warn(`Hot reload: Watcher error: ${(error as Error).message}`);\n });\n }\n\n private startEnvWatcher(): void {\n const { projectRoot, envFile, onEnvReloaded } = this.options;\n\n // Watch for env files\n const envPath = resolve(projectRoot, \".env\");\n const envLocalPath = resolve(projectRoot, \".env.local\");\n\n this.envWatcher = chokidar.watch([envPath, envLocalPath], {\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 100,\n pollInterval: 50,\n },\n });\n\n this.envWatcher\n .on(\"add\", (path) => {\n if (this.closed) return;\n this.reloadEnv(path, envFile, onEnvReloaded);\n })\n .on(\"change\", (path) => {\n if (this.closed) return;\n this.reloadEnv(path, envFile, onEnvReloaded);\n })\n .on(\"error\", (error: unknown) => {\n logger.warn(`Hot reload: Env watcher error: ${(error as Error).message}`);\n });\n }\n\n private reloadEnv(changedFile: string, envFile: string, callback: () => void): void {\n // Reload environment variables with override to update existing vars\n dotenv.config({ path: envFile, override: true });\n\n const fileName = changedFile.split(\"/\").pop() || changedFile;\n console.log(` Hot reload: Environment reloaded from ${fileName}`);\n\n callback();\n }\n\n /**\n * Stop watching and clean up resources\n */\n async close(): Promise<void> {\n this.closed = true;\n\n const closeWithTimeout = (watcher: FSWatcher | null): Promise<void> => {\n if (!watcher) return Promise.resolve();\n return Promise.race([\n watcher.close(),\n new Promise<void>((resolve) => setTimeout(resolve, 1000)),\n ]);\n };\n\n await Promise.all([\n closeWithTimeout(this.agentWatcher),\n closeWithTimeout(this.envWatcher),\n ]);\n\n this.agentWatcher = null;\n this.envWatcher = null;\n logger.debug(\"FileWatcher: Stopped\");\n }\n}\n",
|
|
84
|
+
"/**\n * Telemetry module for anonymous usage tracking\n *\n * Collects anonymous usage data to help improve pk-agent.\n * No personal information, prompts, code, or file paths are ever collected.\n *\n * Opt-out: Set PK_AGENT_TELEMETRY_DISABLED=true\n */\n\nimport { PostHog } from 'posthog-node';\nimport { getOrCreateAnonymousId, isFirstRun, markFirstRunComplete } from './id';\nimport type { ExecutionResult, ToolCallMetrics, StartupError, ServerStartConfig, ServerShutdownStats, AddCommandResult } from './types';\nimport type { ToolCallTrace } from '../plugin/types';\n\n// PostHog configuration\n// This is a public write-only key - safe to commit\nconst POSTHOG_API_KEY = 'phc_aOtJsTJ38N4bdZVt8B2YeuwbQjsMtlTPQvyM7NtaZap';\nconst POSTHOG_HOST = 'https://us.i.posthog.com';\n\n// Package version - imported dynamically to avoid circular deps\nlet VERSION = 'unknown';\n\n/**\n * Check if telemetry is disabled via environment variable\n */\nfunction isDisabled(): boolean {\n const value = process.env.PK_AGENT_TELEMETRY_DISABLED;\n return value === 'true' || value === '1';\n}\n\n/**\n * Check if running in CI environment\n */\nfunction isCI(): boolean {\n return !!(\n process.env.CI ||\n process.env.GITHUB_ACTIONS ||\n process.env.GITLAB_CI ||\n process.env.CIRCLECI ||\n process.env.TRAVIS ||\n process.env.JENKINS_URL ||\n process.env.BUILDKITE\n );\n}\n\n/**\n * Check if running in Docker container\n */\nfunction isDocker(): boolean {\n try {\n const fs = require('fs');\n // Check for .dockerenv file or cgroup\n return fs.existsSync('/.dockerenv') ||\n (fs.existsSync('/proc/1/cgroup') &&\n fs.readFileSync('/proc/1/cgroup', 'utf8').includes('docker'));\n } catch {\n return false;\n }\n}\n\n/**\n * Check if running via npx (not globally/locally installed)\n * npx runs from a cache directory like:\n * - ~/.npm/_npx/...\n * - node_modules/.npx-cache/...\n */\nfunction isNpx(): boolean {\n try {\n const scriptPath = process.argv[1] || '';\n return (\n scriptPath.includes('/_npx/') ||\n scriptPath.includes('\\\\_npx\\\\') ||\n scriptPath.includes('/.npx-cache/') ||\n scriptPath.includes('\\\\.npx-cache\\\\')\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Check if running from a local development build\n * Local dev builds have a .git folder in the package root\n */\nfunction isLocalDev(): boolean {\n try {\n const fs = require('fs');\n const path = require('path');\n const packageRoot = path.join(__dirname, '..');\n return fs.existsSync(path.join(packageRoot, '.git'));\n } catch {\n return false;\n }\n}\n\n/**\n * Parse model identifier into provider and model name\n * e.g., \"anthropic:claude-sonnet-4-5\" -> { provider: \"anthropic\", modelName: \"claude-sonnet-4-5\" }\n */\nexport function parseModel(modelId: string): { provider: string; modelName: string } {\n const colonIndex = modelId.indexOf(':');\n if (colonIndex === -1) {\n // No provider prefix, assume it's just the model name\n return { provider: 'unknown', modelName: modelId };\n }\n return {\n provider: modelId.slice(0, colonIndex),\n modelName: modelId.slice(colonIndex + 1),\n };\n}\n\n/**\n * Aggregate tool call traces into metrics by type\n * MCP tools are prefixed with \"mcp__\"\n */\nexport function aggregateToolCalls(traces: ToolCallTrace[] | undefined): ToolCallMetrics {\n const metrics: ToolCallMetrics = {\n total: 0,\n builtin: 0,\n mcp: 0,\n subagent: 0,\n };\n\n if (!traces) return metrics;\n\n for (const trace of traces) {\n // Skip LLM calls - we only count tool calls\n if (trace.type === 'llm') continue;\n\n metrics.total++;\n\n if (trace.type === 'subagent') {\n metrics.subagent++;\n } else if (trace.name.startsWith('mcp__')) {\n metrics.mcp++;\n } else {\n metrics.builtin++;\n }\n }\n\n return metrics;\n}\n\n/**\n * Count LLM steps from traces\n */\nexport function countSteps(traces: ToolCallTrace[] | undefined): number {\n if (!traces) return 0;\n return traces.filter(t => t.type === 'llm').length;\n}\n\n/**\n * Extract time to first token from the first LLM trace\n * Returns undefined if not available\n */\nexport function getTimeToFirstToken(traces: ToolCallTrace[] | undefined): number | undefined {\n if (!traces) return undefined;\n\n // Find the first LLM trace with timing info\n const firstLlm = traces.find(t => t.type === 'llm');\n if (!firstLlm) return undefined;\n\n // TTFT would be the difference between promptTokens processing and first output\n // For now, we'll estimate from the trace timing if available\n // This is approximate - the trace records duration but not TTFT specifically\n return undefined; // Will be passed explicitly from the stream if needed\n}\n\n/**\n * Categorize error into a type for telemetry\n */\nexport function categorizeError(error: unknown): ExecutionResult['errorType'] {\n if (!error) return undefined;\n\n const message = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();\n\n if (message.includes('timeout') || message.includes('timed out')) {\n return 'timeout';\n }\n if (message.includes('abort') || message.includes('cancel') || message.includes('interrupt')) {\n return 'user_abort';\n }\n if (message.includes('api') || message.includes('rate limit') || message.includes('401') || message.includes('403')) {\n return 'api_error';\n }\n if (message.includes('tool') || message.includes('function')) {\n return 'tool_error';\n }\n\n return 'unknown';\n}\n\n/**\n * TelemetryManager handles anonymous usage tracking\n */\nclass TelemetryManager {\n private client: PostHog | null = null;\n private anonymousId: string | null = null;\n private enabled: boolean;\n private initialized: boolean = false;\n private initPromise: Promise<void> | null = null;\n\n constructor() {\n this.enabled = !isDisabled();\n }\n\n /**\n * Initialize the telemetry client\n * Must be called before capturing events\n */\n async init(version: string): Promise<void> {\n if (this.initPromise) {\n return this.initPromise;\n }\n\n this.initPromise = this._init(version);\n return this.initPromise;\n }\n\n private async _init(version: string): Promise<void> {\n VERSION = version;\n\n if (!this.enabled) {\n this.initialized = true;\n return;\n }\n\n try {\n this.anonymousId = await getOrCreateAnonymousId();\n\n this.client = new PostHog(POSTHOG_API_KEY, {\n host: POSTHOG_HOST,\n // CLI: send events immediately, don't batch\n flushAt: 1,\n flushInterval: 0,\n });\n\n this.initialized = true;\n } catch {\n // Telemetry init failed - continue without it\n this.enabled = false;\n this.initialized = true;\n }\n }\n\n /**\n * Check if this is the first run (for showing telemetry notice)\n */\n async isFirstRun(): Promise<boolean> {\n if (!this.enabled) return false;\n return isFirstRun();\n }\n\n /**\n * Mark first run as complete (telemetry notice shown)\n */\n async markFirstRunComplete(): Promise<void> {\n if (!this.enabled) return;\n await markFirstRunComplete();\n }\n\n /**\n * Capture an agent execution event\n */\n captureExecution(result: ExecutionResult): void {\n if (!this.enabled || !this.initialized || !this.client || !this.anonymousId) {\n return;\n }\n\n try {\n this.client.capture({\n distinctId: this.anonymousId,\n event: 'agent_execution',\n properties: {\n // Ensure truly anonymous - no person profile\n $process_person_profile: false,\n\n // Version and environment\n version: VERSION,\n os: process.platform,\n arch: process.arch,\n node_version: process.version,\n is_ci: isCI(),\n is_docker: isDocker(),\n is_npx: isNpx(),\n is_local_dev: isLocalDev(),\n\n // Execution metrics (no sensitive data)\n provider: result.provider,\n model_name: result.modelName,\n duration_ms: result.durationMs,\n tokens_input: result.inputTokens,\n tokens_output: result.outputTokens,\n success: result.success,\n error_type: result.errorType,\n\n // Tool call metrics\n ...(result.toolCalls && {\n tool_calls_total: result.toolCalls.total,\n tool_calls_builtin: result.toolCalls.builtin,\n tool_calls_mcp: result.toolCalls.mcp,\n tool_calls_subagent: result.toolCalls.subagent,\n }),\n\n // LLM steps\n ...(result.steps !== undefined && { steps: result.steps }),\n\n // Performance & Reliability\n ...(result.finishReason && { finish_reason: result.finishReason }),\n ...(result.hasTextOutput !== undefined && { has_text_output: result.hasTextOutput }),\n ...(result.timeToFirstTokenMs !== undefined && { time_to_first_token_ms: result.timeToFirstTokenMs }),\n\n // Feature Adoption\n ...(result.features && {\n mcp_servers_count: result.features.mcpServersCount,\n subagents_configured: result.features.subagentsConfigured,\n skills_used: result.features.skillsUsed,\n mode: result.features.mode,\n }),\n\n // Configuration Patterns\n ...(result.config && {\n timeout_custom: result.config.timeoutCustom,\n max_steps_custom: result.config.maxStepsCustom,\n quiet_mode: result.config.quietMode,\n debug_mode: result.config.debugMode,\n }),\n\n // Error Patterns\n ...(result.errors && {\n doom_loop_triggered: result.errors.doomLoopTriggered,\n mcp_connection_failures: result.errors.mcpConnectionFailures,\n }),\n },\n });\n } catch {\n // Silently ignore capture errors\n }\n }\n\n /**\n * Capture a startup error event (auth or config errors before execution)\n */\n captureStartupError(error: StartupError): void {\n if (!this.enabled || !this.initialized || !this.client || !this.anonymousId) {\n return;\n }\n\n try {\n this.client.capture({\n distinctId: this.anonymousId,\n event: 'startup_error',\n properties: {\n $process_person_profile: false,\n\n // Version and environment\n version: VERSION,\n os: process.platform,\n arch: process.arch,\n node_version: process.version,\n is_ci: isCI(),\n is_docker: isDocker(),\n is_npx: isNpx(),\n is_local_dev: isLocalDev(),\n\n // Error details (anonymous)\n error_type: error.type,\n ...(error.provider && { provider: error.provider }),\n ...(error.field && { config_field: error.field }),\n ...(error.issue && { config_issue: error.issue }),\n },\n });\n } catch {\n // Silently ignore capture errors\n }\n }\n\n /**\n * Capture a server start event (for serve mode)\n */\n captureServerStart(config: ServerStartConfig): void {\n if (!this.enabled || !this.initialized || !this.client || !this.anonymousId) {\n return;\n }\n\n try {\n this.client.capture({\n distinctId: this.anonymousId,\n event: 'server_start',\n properties: {\n $process_person_profile: false,\n\n // Version and environment\n version: VERSION,\n os: process.platform,\n arch: process.arch,\n node_version: process.version,\n is_ci: isCI(),\n is_docker: isDocker(),\n is_npx: isNpx(),\n is_local_dev: isLocalDev(),\n\n // Server configuration\n port: config.port,\n host: config.host,\n scheduled_agents: config.scheduledAgents,\n total_agents: config.totalAgents,\n auth_enabled: config.authEnabled,\n },\n });\n } catch {\n // Silently ignore capture errors\n }\n }\n\n /**\n * Capture a server shutdown event (for serve mode)\n */\n captureServerShutdown(stats: ServerShutdownStats): void {\n if (!this.enabled || !this.initialized || !this.client || !this.anonymousId) {\n return;\n }\n\n try {\n this.client.capture({\n distinctId: this.anonymousId,\n event: 'server_shutdown',\n properties: {\n $process_person_profile: false,\n\n // Version and environment\n version: VERSION,\n os: process.platform,\n arch: process.arch,\n node_version: process.version,\n is_ci: isCI(),\n is_docker: isDocker(),\n is_npx: isNpx(),\n is_local_dev: isLocalDev(),\n\n // Server stats\n uptime_ms: stats.uptimeMs,\n total_executions: stats.totalExecutions,\n successful_executions: stats.successfulExecutions,\n failed_executions: stats.failedExecutions,\n },\n });\n } catch {\n // Silently ignore capture errors\n }\n }\n\n /**\n * Capture an add command event (for pk-agent add)\n */\n captureAddCommand(result: AddCommandResult): void {\n if (!this.enabled || !this.initialized || !this.client || !this.anonymousId) {\n return;\n }\n\n try {\n this.client.capture({\n distinctId: this.anonymousId,\n event: 'add_command',\n properties: {\n $process_person_profile: false,\n\n // Version and environment\n version: VERSION,\n os: process.platform,\n arch: process.arch,\n node_version: process.version,\n is_ci: isCI(),\n is_docker: isDocker(),\n is_npx: isNpx(),\n is_local_dev: isLocalDev(),\n\n // Add command metrics\n source_type: result.sourceType,\n ...(result.source && { source: result.source }),\n ...(result.skillsInstalled?.length && { skills_installed: result.skillsInstalled }),\n ...(result.agentsInstalled?.length && { agents_installed: result.agentsInstalled }),\n mode: result.mode,\n force: result.force,\n duration_ms: result.durationMs,\n success: result.success,\n ...(result.errorType && { error_type: result.errorType }),\n },\n });\n } catch {\n // Silently ignore capture errors\n }\n }\n\n /**\n * Shutdown the telemetry client\n * Should be called before process exit to flush pending events\n */\n async shutdown(): Promise<void> {\n if (!this.client) return;\n\n try {\n await this.client.shutdown();\n } catch {\n // Ignore shutdown errors\n }\n }\n\n /**\n * Check if telemetry is enabled\n */\n isEnabled(): boolean {\n return this.enabled;\n }\n}\n\n// Singleton instance\nexport const telemetry = new TelemetryManager();\n\n// Re-export types\nexport type { ExecutionResult, StartupError, ServerStartConfig, ServerShutdownStats, AddCommandResult } from './types';\n",
|
|
85
|
+
"/**\n * Anonymous ID generation and persistence for telemetry\n *\n * Stores telemetry config in ~/.local/share/pk-agent/telemetry.json\n * This ID is never tied to user identity - it's purely for counting unique installations\n */\n\nimport fs from 'fs/promises';\nimport path from 'path';\nimport crypto from 'crypto';\nimport { getXdgDataDir } from '../storage/paths';\n\nconst TELEMETRY_FILE = 'telemetry.json';\n\ninterface TelemetryConfig {\n id: string;\n alertedAt?: string;\n}\n\nfunction getTelemetryDir(): string {\n return path.join(getXdgDataDir(), 'pk-agent');\n}\n\nfunction getConfigPath(): string {\n return path.join(getTelemetryDir(), TELEMETRY_FILE);\n}\n\nasync function readConfig(): Promise<TelemetryConfig | null> {\n try {\n const content = await fs.readFile(getConfigPath(), 'utf-8');\n return JSON.parse(content) as TelemetryConfig;\n } catch {\n return null;\n }\n}\n\nasync function writeConfig(config: TelemetryConfig): Promise<void> {\n const dir = getTelemetryDir();\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(getConfigPath(), JSON.stringify(config, null, 2), 'utf-8');\n}\n\nexport async function getOrCreateAnonymousId(): Promise<string> {\n const config = await readConfig();\n if (config?.id) return config.id;\n\n const newId = crypto.randomUUID();\n try {\n await writeConfig({ id: newId });\n } catch {\n // If we can't persist, still return the ID for this session\n }\n return newId;\n}\n\nexport async function isFirstRun(): Promise<boolean> {\n const config = await readConfig();\n return !config?.alertedAt;\n}\n\nexport async function markFirstRunComplete(): Promise<void> {\n try {\n const config = await readConfig() ?? { id: crypto.randomUUID() };\n config.alertedAt = new Date().toISOString();\n await writeConfig(config);\n } catch {\n // Ignore errors - non-critical\n }\n}\n",
|
|
86
|
+
"import type { AgentConfig } from '../parser';\n\n/**\n * Represents an environment variable reference found in the agent config\n */\nexport interface EnvVarReference {\n name: string; // e.g., \"API_TOKEN\"\n source: string; // e.g., \"mcpServers.api_server\"\n type: 'inline' | 'required' | 'allowed';\n required: boolean;\n}\n\n/**\n * Result of environment variable validation\n */\nexport interface EnvValidationResult {\n valid: boolean;\n missingRequired: EnvVarReference[];\n missingOptional: EnvVarReference[];\n}\n\n/**\n * Regex to match ${env:VAR_NAME} syntax\n */\nconst ENV_VAR_PATTERN = /\\$\\{env:(\\w+)\\}/g;\n\n/**\n * Deep scan an object for ${env:VAR_NAME} patterns\n */\nfunction extractInlineEnvVars(obj: unknown, path: string, refs: EnvVarReference[]): void {\n if (typeof obj === 'string') {\n let match;\n while ((match = ENV_VAR_PATTERN.exec(obj)) !== null) {\n refs.push({\n name: match[1],\n source: path,\n type: 'inline',\n required: true // inline references are treated as required\n });\n }\n // Reset regex lastIndex for next string\n ENV_VAR_PATTERN.lastIndex = 0;\n } else if (Array.isArray(obj)) {\n obj.forEach((item, index) => {\n extractInlineEnvVars(item, `${path}[${index}]`, refs);\n });\n } else if (obj !== null && typeof obj === 'object') {\n for (const [key, value] of Object.entries(obj)) {\n extractInlineEnvVars(value, path ? `${path}.${key}` : key, refs);\n }\n }\n}\n\n/**\n * Extract all environment variable references from an agent config\n */\nexport function extractEnvVarReferences(config: AgentConfig): EnvVarReference[] {\n const refs: EnvVarReference[] = [];\n\n // Extract from MCP servers\n if (config.mcpServers) {\n for (const [serverName, serverConfig] of Object.entries(config.mcpServers)) {\n const source = `mcpServers.${serverName}`;\n\n // Extract inline ${env:VAR_NAME} references\n extractInlineEnvVars(serverConfig, source, refs);\n\n // Extract requiredEnvVars\n if ('requiredEnvVars' in serverConfig && serverConfig.requiredEnvVars) {\n for (const varName of serverConfig.requiredEnvVars) {\n refs.push({\n name: varName,\n source,\n type: 'required',\n required: true\n });\n }\n }\n\n // Extract allowedEnvVars\n if ('allowedEnvVars' in serverConfig && serverConfig.allowedEnvVars) {\n for (const varName of serverConfig.allowedEnvVars) {\n refs.push({\n name: varName,\n source,\n type: 'allowed',\n required: false\n });\n }\n }\n }\n }\n\n return refs;\n}\n\n/**\n * Validate environment variables against current process.env\n */\nexport function validateEnvVars(refs: EnvVarReference[]): EnvValidationResult {\n const missingRequired: EnvVarReference[] = [];\n const missingOptional: EnvVarReference[] = [];\n const seen = new Set<string>();\n\n for (const ref of refs) {\n // Deduplicate by name (same var might be referenced multiple times)\n const key = `${ref.name}:${ref.required}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n if (process.env[ref.name] === undefined) {\n if (ref.required) {\n missingRequired.push(ref);\n } else {\n missingOptional.push(ref);\n }\n }\n }\n\n return {\n valid: missingRequired.length === 0,\n missingRequired,\n missingOptional\n };\n}\n\n/**\n * Format validation result as a user-friendly message\n */\nexport function formatEnvValidationError(result: EnvValidationResult): string {\n const lines: string[] = [];\n\n if (result.missingRequired.length > 0) {\n lines.push('Missing required environment variables:');\n lines.push('');\n\n // Group by source (MCP server)\n const bySource = new Map<string, EnvVarReference[]>();\n for (const ref of result.missingRequired) {\n const existing = bySource.get(ref.source) || [];\n existing.push(ref);\n bySource.set(ref.source, existing);\n }\n\n for (const [source, refs] of bySource) {\n lines.push(` ${source}:`);\n for (const ref of refs) {\n const typeLabel = ref.type === 'inline' ? 'in config value' : `in ${ref.type}EnvVars`;\n lines.push(` - ${ref.name} (${typeLabel})`);\n }\n }\n\n lines.push('');\n lines.push('Please set these in your .env file or export them in your shell.');\n }\n\n if (result.missingOptional.length > 0) {\n if (lines.length > 0) lines.push('');\n lines.push('Optional environment variables not set:');\n lines.push('');\n\n // Group by source\n const bySource = new Map<string, EnvVarReference[]>();\n for (const ref of result.missingOptional) {\n const existing = bySource.get(ref.source) || [];\n existing.push(ref);\n bySource.set(ref.source, existing);\n }\n\n for (const [source, refs] of bySource) {\n lines.push(` ${source}:`);\n for (const ref of refs) {\n lines.push(` - ${ref.name}`);\n }\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Validate all environment variables for an agent config\n * Returns validation result with all missing variables\n */\nexport function validateAgentEnvVars(config: AgentConfig): EnvValidationResult {\n const refs = extractEnvVarReferences(config);\n return validateEnvVars(refs);\n}\n",
|
|
87
|
+
"/**\n * Server Registry\n *\n * Tracks running `pk-agent serve` instances using PID files.\n * Each server writes a JSON file to {XDG_DATA_HOME}/pk-agent/servers/<pid>.json on startup,\n * which is removed on graceful shutdown. Stale entries (where PID no longer exists)\n * are cleaned up automatically.\n */\n\nimport { existsSync, mkdirSync, readdirSync, rmSync, writeFileSync, readFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { getXdgDataDir } from \"../storage/paths\";\n\nexport interface ServerEntry {\n pid: number;\n port: number;\n host: string;\n projectRoot: string;\n startTime: number;\n agentCount: number;\n scheduleCount: number;\n version: string;\n}\n\nconst REGISTRY_DIR = join(getXdgDataDir(), \"pk-agent\", \"servers\");\n\n/**\n * Ensure the registry directory exists.\n */\nfunction ensureRegistryDir(): void {\n if (!existsSync(REGISTRY_DIR)) {\n mkdirSync(REGISTRY_DIR, { recursive: true });\n }\n}\n\n/**\n * Check if a process with the given PID is running.\n */\nfunction isProcessRunning(pid: number): boolean {\n try {\n // Sending signal 0 doesn't kill the process, just checks if it exists\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the file path for a server entry.\n */\nfunction getEntryPath(pid: number): string {\n return join(REGISTRY_DIR, `${pid}.json`);\n}\n\n/**\n * Register a running server.\n */\nexport function registerServer(entry: Omit<ServerEntry, \"pid\">): void {\n ensureRegistryDir();\n const fullEntry: ServerEntry = {\n ...entry,\n pid: process.pid,\n };\n writeFileSync(getEntryPath(process.pid), JSON.stringify(fullEntry, null, 2));\n}\n\n/**\n * Update an existing server entry (e.g., when agent count changes due to hot reload).\n */\nexport function updateServer(updates: Partial<Omit<ServerEntry, \"pid\" | \"startTime\">>): void {\n const entryPath = getEntryPath(process.pid);\n if (!existsSync(entryPath)) {\n return;\n }\n\n try {\n const existing = JSON.parse(readFileSync(entryPath, \"utf-8\")) as ServerEntry;\n const updated: ServerEntry = { ...existing, ...updates };\n writeFileSync(entryPath, JSON.stringify(updated, null, 2));\n } catch {\n // Ignore errors - registry is best-effort\n }\n}\n\n/**\n * Unregister the current server.\n */\nexport function unregisterServer(): void {\n const entryPath = getEntryPath(process.pid);\n if (existsSync(entryPath)) {\n try {\n rmSync(entryPath);\n } catch {\n // Ignore errors - file might already be gone\n }\n }\n}\n\n/**\n * List all running servers, cleaning up stale entries.\n */\nexport function listServers(): ServerEntry[] {\n ensureRegistryDir();\n\n const entries: ServerEntry[] = [];\n const files = readdirSync(REGISTRY_DIR).filter((f) => f.endsWith(\".json\"));\n\n for (const file of files) {\n const filePath = join(REGISTRY_DIR, file);\n try {\n const entry = JSON.parse(readFileSync(filePath, \"utf-8\")) as ServerEntry;\n\n if (isProcessRunning(entry.pid)) {\n entries.push(entry);\n } else {\n // Clean up stale entry\n try {\n rmSync(filePath);\n } catch {\n // Ignore cleanup errors\n }\n }\n } catch {\n // Invalid JSON or read error - try to clean up\n try {\n rmSync(filePath);\n } catch {\n // Ignore\n }\n }\n }\n\n // Sort by start time (oldest first)\n return entries.sort((a, b) => a.startTime - b.startTime);\n}\n\n/**\n * Format uptime from milliseconds to human-readable string.\n */\nexport function formatUptime(startTime: number): string {\n const ms = Date.now() - startTime;\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) {\n return `${days}d ${hours % 24}h`;\n } else if (hours > 0) {\n return `${hours}h ${minutes % 60}m`;\n } else if (minutes > 0) {\n return `${minutes}m ${seconds % 60}s`;\n } else {\n return `${seconds}s`;\n }\n}\n",
|
|
88
|
+
"import { existsSync } from 'fs';\nimport { readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { homedir } from 'os';\nimport { join, dirname, resolve } from 'path';\nimport { z } from 'zod';\nimport { findSecretMatches } from '../utils/redaction';\nimport { DEFAULT_MAX_STEPS, DEFAULT_TIMEOUT } from '../utils/config';\n\nconst AppConfigSchema = z.object({\n defaultModel: z.string().min(1).optional(),\n defaultTimeoutSeconds: z.number().int().positive().optional(),\n defaultMaxSteps: z.number().int().positive().optional(),\n defaultAudit: z.boolean().optional(),\n defaultTrace: z.boolean().optional(),\n defaultApprovals: z.boolean().optional(),\n defaultDirectory: z.string().min(1).optional(),\n}).strict();\n\nexport type AppConfig = z.infer<typeof AppConfigSchema>;\n\nexport type AppConfigKey = keyof AppConfig;\n\nexport type AppConfigSourceScope = 'env' | 'project' | 'user' | 'default';\n\nexport interface AppConfigKeySource {\n scope: AppConfigSourceScope;\n envVar?: string;\n path?: string;\n}\n\nexport interface ResolvedAppConfig {\n effective: Required<Pick<AppConfig, 'defaultAudit' | 'defaultTrace' | 'defaultApprovals'>> &\n Pick<AppConfig, 'defaultModel' | 'defaultTimeoutSeconds' | 'defaultMaxSteps' | 'defaultDirectory'>;\n sources: Record<AppConfigKey, AppConfigKeySource>;\n paths: { user: string; project: string };\n}\n\nexport const APP_CONFIG_KEYS: AppConfigKey[] = [\n 'defaultModel',\n 'defaultTimeoutSeconds',\n 'defaultMaxSteps',\n 'defaultAudit',\n 'defaultTrace',\n 'defaultApprovals',\n 'defaultDirectory',\n];\n\nfunction parseBool(value: string | undefined): boolean | undefined {\n if (value === undefined) return undefined;\n const v = String(value).trim().toLowerCase();\n if (v === '1' || v === 'true' || v === 'yes') return true;\n if (v === '0' || v === 'false' || v === 'no') return false;\n return undefined;\n}\n\nfunction parseIntPositive(value: string | undefined): number | undefined {\n if (value === undefined) return undefined;\n const n = Number.parseInt(String(value).trim(), 10);\n if (!Number.isFinite(n) || n <= 0) return undefined;\n return n;\n}\n\nfunction ensureParentDir(filePath: string): void {\n try {\n mkdirSync(dirname(filePath), { recursive: true });\n } catch {\n // Best-effort; callers handle write errors.\n }\n}\n\nexport function getUserConfigPath(home: string = homedir()): string {\n return join(home, '.pk-agent', 'config.json');\n}\n\nexport function getProjectConfigPath(projectRoot: string): string {\n return join(projectRoot, '.pk-agent', 'config.json');\n}\n\nexport function readConfigFile(path: string): AppConfig {\n if (!existsSync(path)) return {};\n try {\n const raw = readFileSync(path, 'utf-8');\n const parsed = JSON.parse(raw);\n return AppConfigSchema.parse(parsed);\n } catch {\n // Treat invalid config as empty; do not hard-fail the CLI.\n return {};\n }\n}\n\nexport function writeConfigFile(path: string, config: AppConfig): void {\n ensureParentDir(path);\n const data = AppConfigSchema.parse(config);\n writeFileSync(path, JSON.stringify(data, null, 2) + '\\n', 'utf-8');\n}\n\nexport function looksSecretKey(key: string): boolean {\n const k = String(key).toLowerCase();\n return (\n k.includes('token') ||\n k.includes('secret') ||\n k.includes('password') ||\n k.includes('authorization') ||\n k.includes('webhook') ||\n k.includes('apikey') ||\n k.includes('api_key') ||\n k.endsWith('key')\n );\n}\n\nexport function looksSecretValue(value: string): boolean {\n return findSecretMatches(String(value)).length > 0;\n}\n\nexport function parseConfigKey(key: string): AppConfigKey | null {\n const k = String(key).trim();\n return (APP_CONFIG_KEYS as string[]).includes(k) ? (k as AppConfigKey) : null;\n}\n\nexport function parseConfigValue(key: AppConfigKey, raw: string): AppConfig[AppConfigKey] {\n const s = String(raw).trim();\n if (key === 'defaultAudit' || key === 'defaultTrace' || key === 'defaultApprovals') {\n const b = parseBool(s);\n if (b === undefined) {\n throw new Error(`Invalid boolean for ${key}: ${raw}`);\n }\n return b as any;\n }\n if (key === 'defaultTimeoutSeconds' || key === 'defaultMaxSteps') {\n const n = parseIntPositive(s);\n if (n === undefined) {\n throw new Error(`Invalid positive integer for ${key}: ${raw}`);\n }\n return n as any;\n }\n if (key === 'defaultModel' || key === 'defaultDirectory') {\n if (!s) throw new Error(`Invalid string for ${key}: ${raw}`);\n return s as any;\n }\n // Exhaustiveness guard.\n throw new Error(`Unsupported config key: ${key}`);\n}\n\nexport function configDefaults(): ResolvedAppConfig['effective'] {\n return {\n defaultModel: undefined,\n defaultTimeoutSeconds: DEFAULT_TIMEOUT,\n defaultMaxSteps: DEFAULT_MAX_STEPS,\n defaultAudit: false,\n defaultTrace: false,\n defaultApprovals: false,\n defaultDirectory: undefined,\n };\n}\n\nfunction envConfig(env: NodeJS.ProcessEnv): { cfg: Partial<AppConfig>; sources: Partial<Record<AppConfigKey, AppConfigKeySource>> } {\n const cfg: Partial<AppConfig> = {};\n const sources: Partial<Record<AppConfigKey, AppConfigKeySource>> = {};\n\n const map: Array<[AppConfigKey, string]> = [\n ['defaultModel', 'PK_AGENT_DEFAULT_MODEL'],\n ['defaultTimeoutSeconds', 'PK_AGENT_DEFAULT_TIMEOUT_SECONDS'],\n ['defaultMaxSteps', 'PK_AGENT_DEFAULT_MAX_STEPS'],\n ['defaultAudit', 'PK_AGENT_DEFAULT_AUDIT'],\n ['defaultTrace', 'PK_AGENT_DEFAULT_TRACE'],\n ['defaultApprovals', 'PK_AGENT_DEFAULT_APPROVALS'],\n ['defaultDirectory', 'PK_AGENT_DEFAULT_DIRECTORY'],\n ];\n\n for (const [key, envVar] of map) {\n const v = env[envVar];\n if (v === undefined) continue;\n try {\n // Parse per key type.\n if (key === 'defaultAudit' || key === 'defaultTrace' || key === 'defaultApprovals') {\n const b = parseBool(v);\n if (b === undefined) continue;\n (cfg as any)[key] = b;\n } else if (key === 'defaultTimeoutSeconds' || key === 'defaultMaxSteps') {\n const n = parseIntPositive(v);\n if (n === undefined) continue;\n (cfg as any)[key] = n;\n } else {\n const s = String(v).trim();\n if (!s) continue;\n (cfg as any)[key] = s;\n }\n (sources as any)[key] = { scope: 'env', envVar };\n } catch {\n // ignore invalid env values\n }\n }\n\n return { cfg, sources };\n}\n\nexport function resolveAppConfig(projectRoot: string, env: NodeJS.ProcessEnv = process.env, home: string = homedir()): ResolvedAppConfig {\n const userPath = getUserConfigPath(home);\n const projectPath = getProjectConfigPath(projectRoot);\n\n const user = readConfigFile(userPath);\n const project = readConfigFile(projectPath);\n const { cfg: envCfg, sources: envSources } = envConfig(env);\n\n const defaults = configDefaults();\n\n const sources: Record<AppConfigKey, AppConfigKeySource> = {\n defaultModel: { scope: 'default' },\n defaultTimeoutSeconds: { scope: 'default' },\n defaultMaxSteps: { scope: 'default' },\n defaultAudit: { scope: 'default' },\n defaultTrace: { scope: 'default' },\n defaultApprovals: { scope: 'default' },\n defaultDirectory: { scope: 'default' },\n };\n\n const effective: any = { ...defaults };\n\n const apply = (cfg: Partial<AppConfig>, src: (k: AppConfigKey) => AppConfigKeySource) => {\n for (const key of APP_CONFIG_KEYS) {\n const val = (cfg as any)[key];\n if (val === undefined) continue;\n effective[key] = val;\n sources[key] = src(key);\n }\n };\n\n apply(user, (k) => ({ scope: 'user', path: userPath }));\n apply(project, (k) => ({ scope: 'project', path: projectPath }));\n apply(envCfg, (k) => (envSources[k] ? envSources[k]! : { scope: 'env' }));\n\n // Normalize defaultDirectory to absolute path if set.\n if (typeof effective.defaultDirectory === 'string' && effective.defaultDirectory.trim()) {\n effective.defaultDirectory = resolve(effective.defaultDirectory.trim());\n }\n\n return {\n effective,\n sources,\n paths: { user: userPath, project: projectPath },\n };\n}\n\nexport function applyAppConfigDefaultsToAgentConfig(agentConfig: { timeout?: number; maxSteps?: number }, resolved: ResolvedAppConfig): void {\n if (agentConfig.timeout === undefined && resolved.effective.defaultTimeoutSeconds !== undefined) {\n agentConfig.timeout = resolved.effective.defaultTimeoutSeconds;\n }\n if (agentConfig.maxSteps === undefined && resolved.effective.defaultMaxSteps !== undefined) {\n agentConfig.maxSteps = resolved.effective.defaultMaxSteps;\n }\n}\n\n",
|
|
89
|
+
"import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { MODELS, type Provider, type ModelInfo } from '../generated/models';\n\nexport function createModelsCommand(): Command {\n const modelsCommand = new Command('models')\n .description('List recommended AI models')\n .argument('[provider]', 'Filter by provider (anthropic, openai, openrouter)')\n .option('-v, --verbose', 'Show detailed model information')\n .action(async (provider: string | undefined, options: { verbose?: boolean }) => {\n const providers: Provider[] = provider\n ? [provider as Provider]\n : ['anthropic', 'openai', 'openrouter'];\n\n // Validate provider\n if (provider && !['anthropic', 'openai', 'openrouter'].includes(provider)) {\n console.error(chalk.red(`Unknown provider: ${provider}`));\n console.log(chalk.gray('Available providers: anthropic, openai, openrouter'));\n process.exit(1);\n }\n\n console.log(chalk.bold('\\nRecommended Models\\n'));\n console.log(chalk.gray('Note: Other models from these providers may also work.\\n'));\n\n for (const p of providers) {\n const models = MODELS[p];\n if (!models || Object.keys(models).length === 0) continue;\n\n console.log(chalk.cyan.bold(`${p.charAt(0).toUpperCase() + p.slice(1)}`));\n\n for (const [modelId, model] of Object.entries(models)) {\n const fullId = `${p}:${modelId}`;\n\n if (options.verbose) {\n printVerboseModel(fullId, model);\n } else {\n printCompactModel(fullId, model);\n }\n }\n\n console.log();\n }\n\n // Show legend\n console.log(chalk.gray('Legend: [R] Reasoning, [V] Vision, [T] Tool Use\\n'));\n\n // Show usage hint\n console.log(chalk.gray('Usage: pk-agent run agent.pk-agent -m <model>'));\n console.log(chalk.gray('Example: pk-agent run agent.pk-agent -m anthropic:claude-sonnet-4-5\\n'));\n });\n\n return modelsCommand;\n}\n\nfunction printCompactModel(fullId: string, model: ModelInfo): void {\n const capabilities: string[] = [];\n if (model.reasoning) capabilities.push('R');\n if (model.modalities.input.includes('image')) capabilities.push('V');\n if (model.toolCall) capabilities.push('T');\n\n const capStr = capabilities.length > 0 ? chalk.gray(` [${capabilities.join(',')}]`) : '';\n\n console.log(` ${chalk.white(fullId)}${capStr}`);\n}\n\nfunction printVerboseModel(fullId: string, model: ModelInfo): void {\n console.log(` ${chalk.white(fullId)}`);\n console.log(chalk.gray(` Name: ${model.name}`));\n console.log(chalk.gray(` Context: ${model.limit.context.toLocaleString()} tokens`));\n console.log(chalk.gray(` Output: ${model.limit.output.toLocaleString()} tokens`));\n\n const caps: string[] = [];\n if (model.reasoning) caps.push('Reasoning');\n if (model.modalities.input.includes('image')) caps.push('Vision');\n if (model.modalities.input.includes('video')) caps.push('Video');\n if (model.toolCall) caps.push('Tool Use');\n\n if (caps.length > 0) {\n console.log(chalk.gray(` Capabilities: ${caps.join(', ')}`));\n }\n\n console.log();\n}\n",
|
|
90
|
+
"import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { discoverSkills } from '../skill/discovery.js';\nimport { resolveProjectContext } from '../utils/project.js';\nimport type { SkillInfo } from '../skill/types.js';\n\n/**\n * Get the source directory label for a skill\n */\nfunction getSourceDir(location: string, projectRoot: string): string {\n const home = homedir();\n const dirs = [\n { path: join(projectRoot, '.pk-agent', 'skills'), label: '.pk-agent/skills' },\n { path: join(home, '.pk-agent', 'skills'), label: '~/.pk-agent/skills' },\n { path: join(projectRoot, '.claude', 'skills'), label: '.claude/skills' },\n { path: join(home, '.claude', 'skills'), label: '~/.claude/skills' },\n ];\n\n for (const dir of dirs) {\n if (location.startsWith(dir.path)) {\n return dir.label;\n }\n }\n return 'unknown';\n}\n\nexport function createSkillsCommand(): Command {\n const skillsCommand = new Command('skills')\n .description('List available skills')\n .option('-v, --verbose', 'Show skill file paths')\n .action(async (options: { verbose?: boolean }) => {\n const projectContext = resolveProjectContext(process.cwd());\n const skills = await discoverSkills(projectContext.projectRoot);\n\n if (skills.size === 0) {\n console.log(chalk.gray('No skills found.'));\n console.log(chalk.gray('\\nSkill directories searched:'));\n console.log(chalk.gray(' .pk-agent/skills/'));\n console.log(chalk.gray(' ~/.pk-agent/skills/'));\n console.log(chalk.gray(' .claude/skills/'));\n console.log(chalk.gray(' ~/.claude/skills/'));\n return;\n }\n\n // Group skills by source directory\n const grouped = new Map<string, SkillInfo[]>();\n for (const skill of skills.values()) {\n const source = getSourceDir(skill.location, projectContext.projectRoot);\n if (!grouped.has(source)) {\n grouped.set(source, []);\n }\n grouped.get(source)!.push(skill);\n }\n\n console.log(chalk.bold(`\\nFound ${skills.size} skill(s):\\n`));\n\n for (const [source, sourceSkills] of grouped) {\n console.log(chalk.yellow(source));\n for (const skill of sourceSkills) {\n console.log(` ${chalk.cyan(skill.name)}`);\n console.log(chalk.gray(` ${skill.description}`));\n if (options.verbose) {\n console.log(chalk.gray(` ${skill.location}`));\n }\n if (skill.allowedTools?.length) {\n console.log(chalk.gray(` tools: ${skill.allowedTools.join(', ')}`));\n }\n }\n console.log();\n }\n });\n\n return skillsCommand;\n}\n",
|
|
91
|
+
"import { Command } from 'commander';\r\nimport chalk from 'chalk';\r\nimport { resolve } from 'path';\r\nimport { loadSuite, getTotalScenarios, resolveSuitePath, BENCHMARK_DIRS } from '../benchmark/loader.js';\r\nimport { runBenchmarkSuite } from '../benchmark/runner.js';\r\nimport { saveReports, generateMarkdownReport, generateHtmlReport, isRawBenchmarkResult, type ReportFormat } from '../benchmark/reporter/index.js';\r\nimport { calculateMetrics } from '../benchmark/calculator.js';\r\nimport type { BenchmarkRunConfig, SuiteResult } from '../benchmark/types.js';\r\n\r\nexport function createBenchmarkCommand(): Command {\r\n const benchmarkCommand = new Command('benchmark')\r\n .description('Run LLM benchmarks to evaluate agent performance');\r\n\r\n // Run benchmark\r\n benchmarkCommand\r\n .command('run')\r\n .description('Execute a benchmark suite')\r\n .argument('<suite>', 'Path to suite YAML file')\r\n .option('-m, --models <models...>', 'Override models to evaluate')\r\n .option('-r, --runs <number>', 'Number of runs (trials) per scenario', parseInt)\r\n .option('--timeout <seconds>', 'Timeout per scenario in seconds', parseInt)\r\n .option('--max-steps <number>', 'Max steps per scenario', parseInt)\r\n .option('--budget <usd>', 'Cost budget in USD (stops if exceeded)', parseFloat)\r\n .option('-o, --output <dir>', 'Output directory for reports', './.pk-agent/benchmark/results')\r\n .option('--format <formats...>', 'Output formats: json, markdown, html')\r\n .option('-v, --verbose', 'Enable verbose logging')\r\n .action(async (suitePath: string, options: {\r\n models?: string[];\r\n runs?: number;\r\n timeout?: number;\r\n maxSteps?: number;\r\n budget?: number;\r\n output?: string;\r\n format?: string[];\r\n verbose?: boolean;\r\n }) => {\r\n try {\r\n console.log(chalk.bold('\\n PK Agent Benchmark\\n'));\r\n\r\n // Resolve suite path (supports name, relative path, or absolute path)\r\n const absoluteSuitePath = await resolveSuitePath(suitePath);\r\n console.log(chalk.gray(`Suite: ${absoluteSuitePath}`));\r\n\r\n // Load suite\r\n console.log(chalk.gray('Loading suite...'));\r\n const loadedSuite = await loadSuite(absoluteSuitePath);\r\n\r\n // Show suite info\r\n const totalScenarios = getTotalScenarios(loadedSuite.suite);\r\n const models = options.models ?? loadedSuite.suite.config.models;\r\n const runs = options.runs ?? loadedSuite.suite.config.runs;\r\n const totalTrials = totalScenarios * models.length * runs;\r\n\r\n console.log(chalk.cyan(`\\n ${loadedSuite.suite.name}`));\r\n console.log(chalk.gray(` Models: ${models.join(', ')}`));\r\n console.log(chalk.gray(` Scenarios: ${totalScenarios}`));\r\n console.log(chalk.gray(` Runs per scenario: ${runs}`));\r\n console.log(chalk.gray(` Total trials: ${totalTrials}`));\r\n\r\n if (options.budget) {\r\n console.log(chalk.yellow(` Budget: $${options.budget}`));\r\n }\r\n\r\n console.log('');\r\n\r\n // Build config\r\n const config: BenchmarkRunConfig = {\r\n suitePath: absoluteSuitePath,\r\n ...(options.models && { models: options.models }),\r\n ...(options.runs !== undefined && { runs: options.runs }),\r\n ...(options.timeout !== undefined && { timeout: options.timeout }),\r\n ...(options.maxSteps !== undefined && { maxSteps: options.maxSteps }),\r\n ...(options.budget !== undefined && { budgetUsd: options.budget }),\r\n ...(options.output && { outputDir: options.output }),\r\n formats: (options.format as ReportFormat[]) ?? ['json', 'markdown', 'html'],\r\n ...(options.verbose !== undefined && { verbose: options.verbose }),\r\n };\r\n\r\n // Run benchmark\r\n console.log(chalk.bold('Running benchmark...\\n'));\r\n const result = await runBenchmarkSuite(loadedSuite, config);\r\n\r\n // Print results summary\r\n console.log(chalk.bold('\\n Results\\n'));\r\n\r\n console.log(chalk.bold('Model Ranking:'));\r\n for (const entry of result.ranking) {\r\n const medal = entry.rank === 1 ? '#1' : entry.rank === 2 ? '#2' : entry.rank === 3 ? '#3' : ' ';\r\n const modelName = entry.model.split(':')[1] || entry.model;\r\n const costDisplay = entry.costUsd !== undefined\r\n ? chalk.gray('$' + entry.costUsd.toFixed(3))\r\n : chalk.gray('-');\r\n console.log(\r\n `${medal} ${chalk.bold(entry.rank + '.')} ${chalk.white(modelName)} - ` +\r\n `Score: ${chalk.cyan(entry.score.toFixed(1))} | ` +\r\n `Completion: ${chalk.green((entry.completionRate * 100).toFixed(0) + '%')} | ` +\r\n `Pass^k: ${chalk.yellow((entry.passK * 100).toFixed(0) + '%')} | ` +\r\n `Avg Tools: ${chalk.magenta(entry.meanToolCalls.toFixed(1))} | ` +\r\n `Cost: ${costDisplay}`\r\n );\r\n }\r\n\r\n // Save reports\r\n console.log(chalk.gray('\\nSaving reports...'));\r\n const outputDir = options.output ?? './.pk-agent/benchmark/results';\r\n const formats = (options.format as ReportFormat[]) ?? ['json', 'markdown', 'html'];\r\n const savedFiles = await saveReports(result, outputDir, formats);\r\n\r\n console.log(chalk.green('\\n[OK] Reports saved:'));\r\n for (const file of savedFiles) {\r\n console.log(chalk.gray(` ${file}`));\r\n }\r\n\r\n console.log(chalk.bold(`\\n Benchmark completed in ${(result.durationMs / 1000).toFixed(1)}s\\n`));\r\n\r\n } catch (error) {\r\n console.error(chalk.red(`\\n[X] Benchmark failed: ${error instanceof Error ? error.message : String(error)}\\n`));\r\n if (options.verbose && error instanceof Error) {\r\n console.error(chalk.gray(error.stack));\r\n }\r\n process.exit(1);\r\n }\r\n });\r\n\r\n // List available suites\r\n benchmarkCommand\r\n .command('list')\r\n .description('List available benchmark suites')\r\n .option('-d, --dir <directory>', 'Directory to search (overrides default locations)')\r\n .action(async (options: { dir?: string }) => {\r\n const { readdir } = await import('fs/promises');\r\n const { existsSync } = await import('fs');\r\n const { join, basename } = await import('path');\r\n\r\n interface SuiteEntry {\r\n name: string;\r\n path: string;\r\n source: 'local' | 'builtin';\r\n }\r\n\r\n const suites: SuiteEntry[] = [];\r\n\r\n try {\r\n // If custom dir provided, only search there\r\n if (options.dir) {\r\n const dir = resolve(options.dir);\r\n if (!existsSync(dir)) {\r\n console.log(chalk.yellow(`Directory not found: ${dir}`));\r\n return;\r\n }\r\n const files = await readdir(dir);\r\n for (const file of files) {\r\n if (file.endsWith('.suite.yaml') || file.endsWith('.suite.yml')) {\r\n suites.push({\r\n name: basename(file, file.endsWith('.suite.yaml') ? '.suite.yaml' : '.suite.yml'),\r\n path: join(dir, file),\r\n source: 'builtin',\r\n });\r\n }\r\n }\r\n } else {\r\n // Search both directories\r\n const dirs = [\r\n { path: resolve(BENCHMARK_DIRS.local), source: 'local' as const },\r\n { path: resolve(BENCHMARK_DIRS.builtin), source: 'builtin' as const },\r\n ];\r\n\r\n for (const { path: dir, source } of dirs) {\r\n if (!existsSync(dir)) continue;\r\n try {\r\n const files = await readdir(dir);\r\n for (const file of files) {\r\n if (file.endsWith('.suite.yaml') || file.endsWith('.suite.yml')) {\r\n suites.push({\r\n name: basename(file, file.endsWith('.suite.yaml') ? '.suite.yaml' : '.suite.yml'),\r\n path: join(dir, file),\r\n source,\r\n });\r\n }\r\n }\r\n } catch {\r\n // Directory doesn't exist or not readable, skip\r\n }\r\n }\r\n }\r\n\r\n if (suites.length === 0) {\r\n console.log(chalk.yellow('No benchmark suites found'));\r\n console.log(chalk.gray(`\\nSearched in:\\n - ${BENCHMARK_DIRS.local}\\n - ${BENCHMARK_DIRS.builtin}`));\r\n return;\r\n }\r\n\r\n console.log(chalk.bold('\\nAvailable Benchmark Suites:\\n'));\r\n for (const suite of suites) {\r\n const tag = suite.source === 'local' ? chalk.cyan('[local]') : chalk.gray('[builtin]');\r\n console.log(` ${tag} ${chalk.white(suite.name)}`);\r\n console.log(chalk.gray(` ${suite.path}`));\r\n }\r\n console.log(chalk.gray('\\nRun with: pk-agent benchmark run <name>\\n'));\r\n } catch (error) {\r\n console.error(chalk.red(`Failed to list suites: ${error instanceof Error ? error.message : String(error)}`));\r\n process.exit(1);\r\n }\r\n });\r\n\r\n // View results\r\n benchmarkCommand\r\n .command('results')\r\n .description('View benchmark results')\r\n .argument('[runId]', 'Run ID (hash) to view specific result')\r\n .option('--latest', 'Show the latest run')\r\n .option('--markdown', 'Output as markdown')\r\n .option('--web', 'Open HTML report in browser')\r\n .option('--dir <directory>', 'Results directory', './.pk-agent/benchmark/results')\r\n .action(async (runId: string | undefined, options: { latest?: boolean; markdown?: boolean; web?: boolean; dir?: string }) => {\r\n const { readdir, readFile } = await import('fs/promises');\r\n const { join } = await import('path');\r\n\r\n try {\r\n const dir = resolve(options.dir ?? './.pk-agent/benchmark/results');\r\n const files = await readdir(dir);\r\n const jsonFiles = files.filter(f => f.endsWith('.json'));\r\n\r\n if (jsonFiles.length === 0) {\r\n console.log(chalk.yellow(`No benchmark results found in ${dir}`));\r\n return;\r\n }\r\n\r\n // Load all results with full data\r\n interface ResultEntry {\r\n file: string;\r\n data: SuiteResult;\r\n }\r\n\r\n const results: ResultEntry[] = [];\r\n\r\n for (const file of jsonFiles) {\r\n try {\r\n const content = await readFile(join(dir, file), 'utf-8');\r\n const parsed = JSON.parse(content);\r\n\r\n // Must be raw format (version 2)\r\n if (!isRawBenchmarkResult(parsed)) {\r\n console.log(chalk.yellow(`Skipping ${file}: incompatible format (re-run benchmark to generate new format)`));\r\n continue;\r\n }\r\n\r\n const suiteResult = calculateMetrics(parsed);\r\n results.push({ file, data: suiteResult });\r\n } catch {\r\n // Skip invalid files\r\n }\r\n }\r\n\r\n // Sort by timestamp descending\r\n results.sort((a, b) => b.data.timestamp - a.data.timestamp);\r\n\r\n if (results.length === 0) {\r\n console.log(chalk.yellow(`No valid benchmark results found in ${dir}`));\r\n return;\r\n }\r\n\r\n // Formatting helpers\r\n const pct = (v: number) => `${(v * 100).toFixed(1)}%`;\r\n const cost = (v: number | undefined) => v === undefined ? '-' : v < 0.01 ? `$${v.toFixed(4)}` : v < 1 ? `$${v.toFixed(3)}` : `$${v.toFixed(2)}`;\r\n const dur = (ms: number) => ms < 1000 ? `${ms.toFixed(0)}ms` : `${(ms / 1000).toFixed(1)}s`;\r\n const getModelName = (m: string) => m.split(':')[1] || m;\r\n\r\n // Helper to display a single result\r\n const displayResult = async (entry: ResultEntry) => {\r\n const result = entry.data;\r\n\r\n // Handle --markdown option\r\n if (options.markdown) {\r\n const { writeFile: writeFileAsync, mkdir: mkdirAsync } = await import('fs/promises');\r\n\r\n const markdown = generateMarkdownReport(result);\r\n const outputDir = resolve('.pk-agent/benchmark/results');\r\n await mkdirAsync(outputDir, { recursive: true });\r\n const mdPath = join(outputDir, `${result.suiteId}-${result.runId}.md`);\r\n await writeFileAsync(mdPath, markdown, 'utf-8');\r\n\r\n console.log(markdown);\r\n console.log(chalk.green(`\\nSaved to: ${mdPath}`));\r\n return;\r\n }\r\n\r\n // Handle --web option\r\n if (options.web) {\r\n const { writeFile: writeFileAsync, mkdir: mkdirAsync } = await import('fs/promises');\r\n const { exec } = await import('child_process');\r\n\r\n const html = generateHtmlReport(result);\r\n const outputDir = resolve('.pk-agent/benchmark/results');\r\n await mkdirAsync(outputDir, { recursive: true });\r\n const htmlPath = join(outputDir, `${result.suiteId}-${result.runId}.html`);\r\n await writeFileAsync(htmlPath, html, 'utf-8');\r\n\r\n // Open in browser\r\n const openCmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';\r\n exec(`${openCmd} \"${htmlPath}\"`, (err) => {\r\n if (err) {\r\n console.log(chalk.yellow(`Could not open browser. HTML saved to: ${htmlPath}`));\r\n } else {\r\n console.log(chalk.green(`Opened in browser: ${htmlPath}`));\r\n }\r\n });\r\n return;\r\n }\r\n\r\n // Default: show in terminal\r\n console.log(chalk.bold(`\\n ${result.suiteName}\\n`));\r\n console.log(chalk.gray(`Run ID: ${result.runId}`));\r\n console.log(chalk.gray(`Date: ${new Date(result.timestamp).toISOString()}`));\r\n console.log(chalk.gray(`Duration: ${dur(result.durationMs)}`));\r\n console.log(chalk.gray(`Models: ${result.config.models.length}`));\r\n console.log(chalk.gray(`Scenarios: ${result.config.totalScenarios}`));\r\n console.log(chalk.gray(`Runs/scenario: ${result.config.runs}`));\r\n\r\n // Model comparison table\r\n console.log(chalk.bold('\\n-- Model Comparison --\\n'));\r\n\r\n const models = Object.keys(result.modelResults);\r\n const nameWidth = Math.max(12, ...models.map(m => getModelName(m).length));\r\n\r\n // Header\r\n const headers = ['Model', 'Score', 'Completion', 'Pass^k', 'Consistency', 'Efficiency', 'Latency', 'Cost'];\r\n const widths = [nameWidth, 7, 10, 8, 11, 10, 9, 10];\r\n console.log(chalk.gray(headers.map((h, i) => h.padEnd(widths[i])).join(' ')));\r\n console.log(chalk.gray('-'.repeat(widths.reduce((a, b) => a + b + 1, 0))));\r\n\r\n // Sort by rank\r\n const sortedModels = [...models].sort((a, b) => {\r\n const rankA = result.ranking.find(r => r.model === a)?.rank ?? 999;\r\n const rankB = result.ranking.find(r => r.model === b)?.rank ?? 999;\r\n return rankA - rankB;\r\n });\r\n\r\n for (const model of sortedModels) {\r\n const agg = result.modelResults[model].aggregate;\r\n const scoreColor = agg.overallScore >= 80 ? chalk.green : agg.overallScore >= 60 ? chalk.yellow : chalk.red;\r\n\r\n const row = [\r\n getModelName(model).padEnd(widths[0]),\r\n scoreColor(agg.overallScore.toFixed(1).padStart(widths[1] - 1) + ' '),\r\n pct(agg.completionRate).padStart(widths[2]),\r\n pct(agg.passK).padStart(widths[3]),\r\n pct(agg.consistency).padStart(widths[4]),\r\n pct(agg.efficiency).padStart(widths[5]),\r\n dur(agg.latencyMeanMs).padStart(widths[6]),\r\n cost(agg.totalCostUsd).padStart(widths[7]),\r\n ];\r\n console.log(row.join(' '));\r\n }\r\n\r\n // Show errors if any\r\n let hasErrors = false;\r\n for (const model of models) {\r\n const errors = result.modelResults[model].aggregate.errorCounts;\r\n if (errors && Object.values(errors).some(v => v > 0)) {\r\n if (!hasErrors) {\r\n console.log(chalk.bold('\\n-- Errors --\\n'));\r\n hasErrors = true;\r\n }\r\n const errorList = Object.entries(errors)\r\n .filter(([, v]) => v > 0)\r\n .map(([k, v]) => `${k}: ${v}`)\r\n .join(', ');\r\n console.log(chalk.red(` ${getModelName(model)}: ${errorList}`));\r\n }\r\n }\r\n\r\n // Scenario breakdown per model\r\n console.log(chalk.bold('\\n-- Scenario Breakdown --'));\r\n\r\n for (const model of sortedModels) {\r\n const mr = result.modelResults[model];\r\n console.log(chalk.cyan(`\\n ${getModelName(model)}`));\r\n\r\n // Collect all scenarios\r\n const scenarios = mr.agents.flatMap(a => a.scenarios);\r\n if (scenarios.length === 0) {\r\n console.log(chalk.gray(' No scenarios'));\r\n continue;\r\n }\r\n\r\n // Check if any scenario has goals\r\n const hasGoals = scenarios.some(s => s.metrics.goals);\r\n\r\n // Calculate column widths for scenario table\r\n const scenarioNameWidth = Math.max(20, ...scenarios.map(s => s.scenarioName.length));\r\n\r\n if (hasGoals) {\r\n // Header with goals\r\n const sHeaders = ['Scenario', 'Status', 'Goals', 'Recovery', 'Tools', 'Time', 'Cost'];\r\n const sWidths = [scenarioNameWidth, 8, 8, 10, 7, 8, 10];\r\n console.log(chalk.gray(' ' + sHeaders.map((h, i) => h.padEnd(sWidths[i])).join(' ')));\r\n console.log(chalk.gray(' ' + '-'.repeat(sWidths.reduce((a, b) => a + b + 1, 0))));\r\n\r\n for (const scenario of scenarios) {\r\n const m = scenario.metrics;\r\n const statusIcon = m.completionRate === 1 ? chalk.green('[OK]') : m.completionRate > 0 ? chalk.yellow('*') : chalk.red('[X]');\r\n const statusText = m.completionRate === 1 ? 'Pass' : m.completionRate > 0 ? 'Partial' : 'Fail';\r\n const goalsStr = m.goals ? `${m.goals.completedGoals}/${m.goals.totalGoals}` : '-';\r\n const recoveryStr = m.goals ? pct(m.goals.recoveryRate) : '-';\r\n const toolsStr = m.goals ? m.goals.avgAttemptsPerGoal.toFixed(1) : '-';\r\n\r\n const row = [\r\n scenario.scenarioName.slice(0, scenarioNameWidth).padEnd(scenarioNameWidth),\r\n `${statusIcon} ${statusText}`.padEnd(sWidths[1] + 2), // +2 for icon\r\n goalsStr.padStart(sWidths[2]),\r\n recoveryStr.padStart(sWidths[3]),\r\n toolsStr.padStart(sWidths[4]),\r\n dur(m.latency.meanMs).padStart(sWidths[5]),\r\n cost(m.cost.totalUsd).padStart(sWidths[6]),\r\n ];\r\n console.log(' ' + row.join(' '));\r\n }\r\n } else {\r\n // Header without goals\r\n const sHeaders = ['Scenario', 'Status', 'Pass^k', 'Consistency', 'Time', 'Cost'];\r\n const sWidths = [scenarioNameWidth, 8, 8, 11, 8, 10];\r\n console.log(chalk.gray(' ' + sHeaders.map((h, i) => h.padEnd(sWidths[i])).join(' ')));\r\n console.log(chalk.gray(' ' + '-'.repeat(sWidths.reduce((a, b) => a + b + 1, 0))));\r\n\r\n for (const scenario of scenarios) {\r\n const m = scenario.metrics;\r\n const statusIcon = m.completionRate === 1 ? chalk.green('[OK]') : m.completionRate > 0 ? chalk.yellow('*') : chalk.red('[X]');\r\n const statusText = m.completionRate === 1 ? 'Pass' : m.completionRate > 0 ? 'Partial' : 'Fail';\r\n\r\n const row = [\r\n scenario.scenarioName.slice(0, scenarioNameWidth).padEnd(scenarioNameWidth),\r\n `${statusIcon} ${statusText}`.padEnd(sWidths[1] + 2),\r\n pct(m.passK).padStart(sWidths[2]),\r\n pct(m.consistency).padStart(sWidths[3]),\r\n dur(m.latency.meanMs).padStart(sWidths[4]),\r\n cost(m.cost.totalUsd).padStart(sWidths[5]),\r\n ];\r\n console.log(' ' + row.join(' '));\r\n }\r\n }\r\n }\r\n\r\n console.log('');\r\n };\r\n\r\n // Find by runId if provided\r\n if (runId) {\r\n const match = results.find(r => r.data.runId.startsWith(runId) || r.data.runId === runId);\r\n if (!match) {\r\n console.log(chalk.yellow(`No result found matching run ID: ${runId}`));\r\n return;\r\n }\r\n await displayResult(match);\r\n return;\r\n }\r\n\r\n if (options.latest) {\r\n await displayResult(results[0]);\r\n } else {\r\n // Display as table\r\n console.log(chalk.bold('\\n Benchmark Results\\n'));\r\n\r\n // Calculate column widths\r\n const suiteWidth = Math.max(10, ...results.map(r => r.data.suiteName.length));\r\n const hashWidth = 8;\r\n const dateWidth = 19;\r\n\r\n // Header\r\n const header = [\r\n 'Suite'.padEnd(suiteWidth),\r\n 'Hash'.padEnd(hashWidth),\r\n 'Timestamp'.padEnd(dateWidth),\r\n ].join(' ');\r\n console.log(chalk.gray(header));\r\n console.log(chalk.gray('-'.repeat(header.length)));\r\n\r\n // Rows\r\n for (const entry of results.slice(0, 20)) {\r\n const date = new Date(entry.data.timestamp);\r\n const dateStr = date.toISOString().slice(0, 19).replace('T', ' ');\r\n const row = [\r\n entry.data.suiteName.padEnd(suiteWidth),\r\n entry.data.runId.slice(0, hashWidth).padEnd(hashWidth),\r\n dateStr,\r\n ].join(' ');\r\n console.log(row);\r\n }\r\n\r\n if (results.length > 20) {\r\n console.log(chalk.gray(`\\n... and ${results.length - 20} more`));\r\n }\r\n console.log(chalk.gray('\\nUse --latest to view the most recent result\\n'));\r\n }\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\r\n console.log(chalk.yellow('No benchmark results found'));\r\n } else {\r\n console.error(chalk.red(`Failed to read results: ${error instanceof Error ? error.message : String(error)}`));\r\n }\r\n process.exit(1);\r\n }\r\n });\r\n\r\n return benchmarkCommand;\r\n}\r\n",
|
|
92
|
+
"import { readFile } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { resolve, dirname, join } from 'path';\nimport { parse as parseYaml } from 'yaml';\nimport { z } from 'zod';\nimport { randomBytes } from 'crypto';\nimport { parseAgent, type ParsedAgent } from '../parser.js';\nimport {\n BenchmarkSuiteSchema,\n type BenchmarkSuite,\n type Scenario,\n} from './types.js';\n\n/**\n * Directory paths for benchmark suites\n */\nexport const BENCHMARK_DIRS = {\n /** User's local suites (gitignored) */\n local: '.pk-agent/benchmark/suites',\n /** Shipped example suites (committed) */\n builtin: 'benchmarks/suites',\n} as const;\n\n/**\n * Resolve a suite path from name or path.\n * Searches in order: exact path, local (.pk-agent/benchmark/suites), builtin (benchmarks/suites)\n * @param input Suite name (e.g., \"quick-test\") or full path\n * @returns Resolved absolute path to the suite file\n */\nexport async function resolveSuitePath(input: string): Promise<string> {\n // If it's already an absolute path or exists as-is, use it\n const asProvided = resolve(input);\n if (existsSync(asProvided)) {\n return asProvided;\n }\n\n // Try adding .suite.yaml extension if not present\n const withExt = input.endsWith('.suite.yaml') || input.endsWith('.suite.yml')\n ? input\n : `${input}.suite.yaml`;\n\n // Search locations in order: local first (user preference), then builtin\n const candidates = [\n resolve(BENCHMARK_DIRS.local, withExt),\n resolve(BENCHMARK_DIRS.builtin, withExt),\n ];\n\n for (const candidate of candidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n\n throw new SuiteConfigError(\n `Suite not found: ${input}. Searched in:\\n - ${candidates.join('\\n - ')}`,\n 'suitePath',\n 'not_found'\n );\n}\n\n/**\n * Error thrown when suite configuration is invalid\n */\nexport class SuiteConfigError extends Error {\n constructor(\n message: string,\n public field: string,\n public issue: string\n ) {\n super(message);\n this.name = 'SuiteConfigError';\n }\n}\n\n/**\n * Loaded test with resolved agent\n */\nexport interface LoadedTest {\n agent: ParsedAgent;\n agentPath: string;\n scenarios: Scenario[];\n}\n\n/**\n * Fully loaded benchmark suite with resolved agents\n */\nexport interface LoadedSuite {\n suite: BenchmarkSuite;\n suitePath: string;\n tests: LoadedTest[];\n}\n\n/**\n * Parse and validate a benchmark suite YAML file\n * @param suitePath Path to the suite YAML file\n * @returns Parsed and validated suite configuration\n */\nexport async function parseSuite(suitePath: string): Promise<BenchmarkSuite> {\n try {\n // Resolve to absolute path\n const absolutePath = resolve(suitePath);\n\n // Read file content\n const content = await readFile(absolutePath, 'utf-8');\n\n // Parse YAML\n const data = parseYaml(content);\n\n // Validate with Zod schema\n const suite = BenchmarkSuiteSchema.parse(data);\n\n return suite;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new SuiteConfigError(\n `Suite file not found: ${suitePath}`,\n 'suitePath',\n 'not_found'\n );\n }\n\n if (error instanceof z.ZodError) {\n // Zod v4 uses `issues`; Zod v3 used `errors`. Support both.\n const issues: any[] = (error as any).issues ?? (error as any).errors ?? [];\n const firstError = issues[0];\n const message = issues\n .map((e) => `${(e.path ?? []).join('.')}: ${e.message}`)\n .join(', ');\n const topLevelField = String(firstError?.path?.[0] ?? 'root');\n throw new SuiteConfigError(\n `Invalid suite configuration: ${message}`,\n topLevelField,\n String(firstError?.code ?? 'invalid')\n );\n }\n\n throw error;\n }\n}\n\n/**\n * Load a benchmark suite with all agents resolved\n * @param suitePath Path to the suite YAML file\n * @returns Loaded suite with parsed agents\n */\nexport async function loadSuite(suitePath: string): Promise<LoadedSuite> {\n // Parse the suite file\n const suite = await parseSuite(suitePath);\n\n // Resolve agent paths relative to suite file\n const suiteDir = dirname(resolve(suitePath));\n\n // Load all agents\n const tests: LoadedTest[] = [];\n\n for (const test of suite.tests) {\n // Resolve agent path relative to suite directory\n const agentPath = join(suiteDir, test.agent);\n\n try {\n const agent = await parseAgent(agentPath);\n\n tests.push({\n agent,\n agentPath, // Use absolute path for skill discovery\n scenarios: test.scenarios,\n });\n } catch (error) {\n throw new SuiteConfigError(\n `Failed to load agent \"${test.agent}\": ${error instanceof Error ? error.message : String(error)}`,\n `tests.${test.agent}`,\n 'agent_load_error'\n );\n }\n }\n\n return {\n suite,\n suitePath: resolve(suitePath),\n tests,\n };\n}\n\n/**\n * Get total number of scenarios in a suite\n */\nexport function getTotalScenarios(suite: BenchmarkSuite): number {\n return suite.tests.reduce((total, test) => total + test.scenarios.length, 0);\n}\n\n/**\n * Get total number of trials for a suite run\n * (scenarios * models * runs)\n */\nexport function getTotalTrials(suite: BenchmarkSuite): number {\n const scenarios = getTotalScenarios(suite);\n const models = suite.config.models.length;\n const runs = suite.config.runs;\n return scenarios * models * runs;\n}\n\n/**\n * Substitute model placeholder in agent config\n * Agents use ${model} placeholder which gets replaced at runtime\n */\nexport function substituteModel(\n agent: ParsedAgent,\n model: string\n): ParsedAgent {\n return {\n ...agent,\n config: {\n ...agent.config,\n model: agent.config.model === '${model}' ? model : agent.config.model,\n },\n };\n}\n\n/**\n * Built-in dynamic variables for benchmark suite YAML files.\n * Uses {{$variable}} syntax (Postman-style) to differentiate from\n * agent config substitution which uses ${variable} syntax.\n */\nconst dynamicVariables: Record<string, () => string> = {\n uuid: () => crypto.randomUUID(),\n timestamp: () => new Date().toISOString(),\n randomHex: () => randomBytes(4).toString('hex'), // 8 chars\n};\n\n/**\n * Substitute dynamic variables in scenario input text.\n * Supports {{$uuid}}, {{$timestamp}}, {{$randomHex}} syntax.\n * Called at runtime before each trial to ensure unique values.\n */\nexport function substituteTemplateVariables(input: string): string {\n return input.replace(/\\{\\{\\$(\\w+)\\}\\}/g, (match, varName: string) => {\n const generator = dynamicVariables[varName];\n if (generator) {\n return generator();\n }\n // Return original if unknown variable\n return match;\n });\n}\n",
|
|
93
|
+
"import { z } from 'zod';\nimport { getModelFromRegistry } from '../generated/models';\n\n// ============ Expected Output Validation ============\n\nexport const ContainsValidationSchema = z.object({\n type: z.literal('contains'),\n values: z.array(z.string()),\n});\n\nexport const RegexValidationSchema = z.object({\n type: z.literal('regex'),\n pattern: z.string(),\n});\n\nexport const LLMJudgeValidationSchema = z.object({\n type: z.literal('llm-judge'),\n criteria: z.string(),\n model: z.string().optional(), // defaults to gpt-5.2-mini\n});\n\nexport const OutputValidationSchema = z.discriminatedUnion('type', [\n ContainsValidationSchema,\n RegexValidationSchema,\n LLMJudgeValidationSchema,\n]);\n\nexport type OutputValidation = z.infer<typeof OutputValidationSchema>;\n\n// ============ Artifact Validation ============\n\nexport const ArtifactExpectationSchema = z.object({\n path: z.string(),\n exists: z.boolean().default(true),\n contains: z.array(z.string()).optional(),\n});\n\nexport type ArtifactExpectation = z.infer<typeof ArtifactExpectationSchema>;\n\n// ============ Scenario (embedded in suite) ============\n\nexport const ScenarioSchema = z.object({\n id: z.string(),\n name: z.string(),\n difficulty: z.enum(['easy', 'medium', 'hard']).optional(),\n input: z.string(), // Goal/problem given to agent\n expected: z.object({\n artifacts: z.array(ArtifactExpectationSchema).optional(),\n output: OutputValidationSchema.optional(),\n }),\n});\n\nexport type Scenario = z.infer<typeof ScenarioSchema>;\n\n// ============ Test (agent + scenarios) ============\n\nexport const TestSchema = z.object({\n agent: z.string(), // path to .pk-agent file\n scenarios: z.array(ScenarioSchema),\n});\n\nexport type Test = z.infer<typeof TestSchema>;\n\n// ============ Suite Configuration ============\n\nexport const SuiteConfigSchema = z.object({\n models: z.array(z.string()),\n runs: z.number().int().positive().default(3), // number of trials per scenario\n timeout: z.number().positive().default(300), // seconds\n maxSteps: z.number().int().positive().default(30),\n});\n\nexport type SuiteConfig = z.infer<typeof SuiteConfigSchema>;\n\n// ============ Benchmark Suite ============\n\nexport const BenchmarkSuiteSchema = z.object({\n id: z.string(),\n name: z.string(),\n description: z.string().optional(),\n config: SuiteConfigSchema,\n tests: z.array(TestSchema),\n});\n\nexport type BenchmarkSuite = z.infer<typeof BenchmarkSuiteSchema>;\n\n// ============ Tool Call Trace (from existing types) ============\n\nexport interface ToolCallTrace {\n name: string;\n type: 'tool' | 'subagent' | 'llm';\n startTime: number;\n duration: number;\n tokens?: number;\n success?: boolean;\n input?: unknown;\n}\n\n// ============ Goal Tracking ============\n\n/**\n * A tracked goal declared by the agent during execution\n */\nexport interface TrackedGoal {\n id: string;\n name: string;\n description?: string;\n startTime: number;\n endTime?: number;\n status: 'active' | 'completed' | 'failed' | 'abandoned';\n toolCalls: Array<{\n name: string;\n success: boolean;\n duration: number;\n }>;\n}\n\n/**\n * Aggregated metrics for goal tracking\n */\nexport interface GoalMetrics {\n totalGoals: number;\n completedGoals: number;\n failedGoals: number;\n abandonedGoals: number;\n goalCompletionRate: number; // completed / total (0-1)\n avgAttemptsPerGoal: number; // tool calls per goal\n toolCallSuccessRate: number; // successful calls / total calls (0-1)\n toolCallFailureRate: number; // failed calls / total calls (0-1)\n toolCallEfficiency?: number; // relative efficiency vs best performer (0-1), calculated post-run\n recoveryRate: number; // goals completed after a failure (0-1)\n}\n\n// ============ Token Efficiency ============\n\n/**\n * Token efficiency metrics - tokens per successful completion\n */\nexport interface TokenEfficiency {\n inputPerSuccess: number;\n outputPerSuccess: number;\n totalPerSuccess: number;\n}\n\n// ============ Tool Metrics ============\n\n/**\n * Per-tool success rate metrics\n */\nexport interface ToolMetrics {\n name: string;\n totalCalls: number;\n successfulCalls: number;\n failedCalls: number;\n successRate: number; // 0-1\n avgDurationMs: number;\n}\n\n// ============ Error Categorization ============\n\nexport type ErrorCategory =\n | 'timeout'\n | 'runtime_error'\n | 'validation_failure'\n | 'tool_error'\n | 'unknown';\n\nexport interface ErrorCounts {\n timeout: number;\n runtime_error: number;\n validation_failure: number;\n tool_error: number;\n unknown: number;\n}\n\n// ============ Trial Result ============\n\nexport interface TrialResult {\n trialNumber: number;\n seed?: number;\n\n execution: {\n success: boolean;\n durationMs: number;\n timeToFirstTokenMs?: number;\n finishReason: string;\n error?: {\n type: string;\n message: string;\n category: ErrorCategory;\n };\n };\n\n usage: {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n estimatedCostUsd?: number; // undefined if model pricing not available\n };\n\n toolCalls: {\n total: number;\n names: string[];\n traces: ToolCallTrace[];\n };\n\n output: {\n text: string;\n valid: boolean;\n validationDetails?: string;\n };\n\n artifacts: {\n checked: number;\n passed: number;\n details: Array<{\n path: string;\n exists: boolean;\n containsMatch: boolean;\n }>;\n };\n\n goals?: {\n tracked: TrackedGoal[];\n metrics: GoalMetrics;\n };\n}\n\n// ============ Scenario Result (aggregated across trials) ============\n\nexport interface ScenarioResult {\n scenarioId: string;\n scenarioName: string;\n agentPath: string;\n model: string;\n difficulty?: 'easy' | 'medium' | 'hard';\n\n trials: TrialResult[];\n\n metrics: {\n completionRate: number; // 0-1, proportion of successful trials\n passK: number; // 0-1, probability of at least one success in k trials\n consistency: number; // 0-1, low variance = high consistency\n efficiency?: number; // 0-1, relative efficiency vs best performer (calculated post-run)\n\n latency: {\n meanMs: number;\n medianMs: number;\n p95Ms: number;\n stdDevMs: number;\n };\n\n cost: {\n meanUsd?: number; // undefined if model pricing not available\n totalUsd?: number; // undefined if model pricing not available\n perSuccessUsd?: number; // cost per successful completion\n };\n\n toolCalls: {\n meanCount: number;\n uniqueTools: string[];\n perToolMetrics?: ToolMetrics[];\n };\n\n tokenEfficiency?: TokenEfficiency;\n errorCounts?: ErrorCounts;\n goals?: GoalMetrics;\n };\n}\n\n// ============ Agent Result (all scenarios for one agent) ============\n\nexport interface AgentResult {\n agentPath: string;\n agentName: string;\n model: string;\n scenarios: ScenarioResult[];\n\n aggregate: {\n completionRate: number;\n passK: number;\n consistency: number; // 0-1, average consistency across scenarios\n efficiency: number; // 0-1, fewer tool calls = higher efficiency (only successful trials)\n meanToolCalls: number; // Raw average tool calls (successful trials only)\n latencyMeanMs: number;\n totalCostUsd?: number; // undefined if model pricing not available\n costPerSuccessUsd?: number;\n tokenEfficiency?: TokenEfficiency;\n errorCounts?: ErrorCounts;\n goals?: GoalMetrics;\n weightedScore?: number; // Difficulty-weighted score (0-100), undefined if no difficulties set\n };\n}\n\n// ============ Suite Result (full benchmark run) ============\n\nexport interface SuiteResult {\n suiteId: string;\n suiteName: string;\n\n runId: string; // ULID\n timestamp: number;\n durationMs: number;\n\n config: {\n models: string[];\n runs: number;\n totalScenarios: number;\n totalTrials: number;\n };\n\n // Results per model\n modelResults: Record<string, {\n agents: AgentResult[];\n aggregate: {\n completionRate: number;\n passK: number;\n consistency: number; // 0-1, average consistency across all scenarios\n efficiency: number; // 0-1, fewer tool calls = higher efficiency\n meanToolCalls: number; // Raw average tool calls (successful trials only)\n latencyMeanMs: number;\n totalCostUsd?: number; // undefined if model pricing not available\n costPerSuccessUsd?: number;\n tokenEfficiency?: TokenEfficiency;\n errorCounts?: ErrorCounts;\n overallScore: number; // 0-100\n weightedScore?: number; // Difficulty-weighted score (0-100), undefined if no difficulties set\n goals?: GoalMetrics;\n };\n }>;\n\n // Comparative ranking\n ranking: Array<{\n model: string;\n rank: number;\n score: number;\n weightedScore?: number; // Difficulty-weighted score, undefined if no difficulties set\n completionRate: number;\n passK: number;\n consistency: number;\n efficiency: number;\n meanToolCalls: number; // Raw figure for display\n costUsd?: number; // undefined if model pricing not available\n costPerSuccessUsd?: number;\n goals?: {\n completionRate: number;\n avgAttempts: number;\n toolCallSuccessRate: number;\n toolCallFailureRate: number;\n toolCallEfficiency?: number;\n recoveryRate: number;\n };\n }>;\n}\n\n// ============ Raw Benchmark Result (for JSON storage) ============\n\n/**\n * Raw trial entry - minimal data needed to reconstruct metrics\n */\nexport interface RawTrialEntry {\n model: string;\n agentPath: string;\n agentName: string;\n scenarioId: string;\n scenarioName: string;\n difficulty?: 'easy' | 'medium' | 'hard';\n trial: TrialResult;\n}\n\n/**\n * Raw benchmark result - stored in JSON\n * All metrics are computed from this data when loading\n */\nexport interface RawBenchmarkResult {\n version: 2;\n\n // Metadata\n suiteId: string;\n suiteName: string;\n runId: string;\n timestamp: number;\n durationMs: number;\n\n // Config\n config: {\n models: string[];\n runs: number;\n };\n\n // Raw trial data - flat array\n trials: RawTrialEntry[];\n}\n\n// ============ Model Pricing ============\n\n/**\n * Calculate cost for a model based on token usage.\n * Pricing is fetched from the models.dev registry (see src/generated/models.ts).\n * Returns undefined if model is not in registry (no pricing available).\n * Note: models.dev provides cost in USD per million tokens.\n */\nexport function calculateCost(\n model: string,\n inputTokens: number,\n outputTokens: number\n): number | undefined {\n const modelInfo = getModelFromRegistry(model);\n if (!modelInfo?.cost || (modelInfo.cost.input === 0 && modelInfo.cost.output === 0)) {\n return undefined;\n }\n\n // models.dev provides cost in USD per million tokens\n return (inputTokens * modelInfo.cost.input + outputTokens * modelInfo.cost.output) / 1_000_000;\n}\n\n// ============ Benchmark Run Configuration ============\n\nexport interface BenchmarkRunConfig {\n suitePath: string;\n models?: string[]; // Override suite config\n runs?: number; // Override trials per scenario\n timeout?: number;\n maxSteps?: number;\n budgetUsd?: number; // Stop if exceeded\n outputDir?: string;\n formats?: Array<'json' | 'markdown' | 'html'>;\n verbose?: boolean;\n}\n",
|
|
94
|
+
"import { ulid } from 'ulid';\nimport { mkdir, rm } from 'fs/promises';\nimport { join, dirname } from 'path';\nimport { runAgent } from '../runner/run.js';\nimport { prepareAgentExecution } from '../runner/preparation.js';\nimport { connectMCP } from '../mcp.js';\nimport { substituteModel, substituteTemplateVariables, type LoadedSuite, type LoadedTest } from './loader.js';\nimport {\n type BenchmarkRunConfig,\n type TrialResult,\n type ScenarioResult,\n type AgentResult,\n type SuiteResult,\n type Scenario,\n type GoalMetrics,\n type ToolMetrics,\n type ErrorCategory,\n type ErrorCounts,\n type TokenEfficiency,\n type ToolCallTrace,\n} from './types.js';\nimport { evaluateCompletion } from './evaluator/completion.js';\nimport { evaluateArtifacts } from './evaluator/artifacts.js';\nimport type { ParsedAgent } from '../parser.js';\nimport { logger } from '../utils/logger.js';\nimport { GoalTracker } from './goal-tracker.js';\nimport { createGoalTools, GOAL_TRACKING_PROMPT } from './goal-tools.js';\n\n/**\n * Run a single trial of a scenario\n */\nasync function runTrial(\n agent: ParsedAgent,\n scenario: Scenario,\n trialNumber: number,\n config: BenchmarkRunConfig,\n agentFilePath: string\n): Promise<TrialResult> {\n const startTime = Date.now();\n let timeToFirstToken: number | undefined;\n\n // Substitute dynamic variables ({{$uuid}}, {{$timestamp}}, etc.) for this trial\n const scenarioInput = substituteTemplateVariables(scenario.input);\n\n // Create a temp directory for this trial's artifacts\n const trialDir = join(\n config.outputDir ?? '.pk-agent/benchmark',\n 'trials',\n `${scenario.id}-${trialNumber}`\n );\n await mkdir(trialDir, { recursive: true });\n\n // Set up abort controller with timeout\n const abortController = new AbortController();\n const timeout = config.timeout ?? 300;\n const timeoutId = setTimeout(() => abortController.abort(), timeout * 1000);\n\n try {\n // Connect MCP servers from agent config\n const mcpClients = await connectMCP(\n agent.config.mcpServers,\n false,\n dirname(config.suitePath)\n );\n\n try {\n // Use agent directory as projectRoot for skill discovery and cwd for bash commands\n const projectRoot = dirname(agentFilePath);\n const projectContext = { projectRoot, cwd: projectRoot };\n\n // Create goal tracker for this trial\n const goalTracker = new GoalTracker();\n const goalTools = createGoalTools(goalTracker);\n\n // Use the core preparation logic to get skills, tools, etc.\n const preparedExecution = await prepareAgentExecution({\n agent,\n mcpClients,\n agentFilePath,\n cliMaxSteps: config.maxSteps,\n projectContext,\n userPrompt: scenarioInput,\n abortSignal: abortController.signal,\n verbose: config.verbose ?? false,\n });\n\n // Inject goal tracking tools and prompt\n preparedExecution.tools = { ...preparedExecution.tools, ...goalTools };\n preparedExecution.systemMessages.push({\n role: 'system',\n content: GOAL_TRACKING_PROMPT,\n });\n\n // Run the agent with pre-computed execution context\n const result = await runAgent(\n agent,\n mcpClients,\n false, // debug\n abortController.signal,\n startTime,\n config.verbose ?? false,\n agentFilePath,\n config.maxSteps,\n undefined, // sessionManager\n projectContext,\n scenarioInput, // userPrompt - this is the scenario goal (with substituted variables)\n preparedExecution\n );\n\n clearTimeout(timeoutId);\n\n const durationMs = Date.now() - startTime;\n\n // Extract tool names from traces\n const toolNames = result.toolCallTraces?.map((t) => t.name) ?? [];\n\n // Evaluate output if validation is specified\n let outputValid = true;\n let validationDetails = '';\n\n if (scenario.expected.output) {\n const evalResult = await evaluateCompletion(\n result.text,\n scenario.expected.output\n );\n outputValid = evalResult.valid;\n validationDetails = evalResult.details;\n }\n\n // Evaluate artifacts if expectations are specified\n let artifactResult = {\n checked: 0,\n passed: 0,\n details: [] as Array<{ path: string; exists: boolean; containsMatch: boolean }>,\n };\n\n if (scenario.expected.artifacts && scenario.expected.artifacts.length > 0) {\n const evalResult = await evaluateArtifacts(\n scenario.expected.artifacts,\n projectRoot // Use agent's project root for artifact paths\n );\n artifactResult = {\n checked: evalResult.checked,\n passed: evalResult.passed,\n details: evalResult.details.map((d) => ({\n path: d.path,\n exists: d.exists,\n containsMatch: d.containsMatch,\n })),\n };\n }\n\n // Process goal tracking\n if (result.toolCallTraces) {\n goalTracker.processTraces(result.toolCallTraces);\n }\n const trackedGoals = goalTracker.getGoals();\n const goalMetrics = goalTracker.getMetrics();\n\n return {\n trialNumber,\n execution: {\n success: true,\n durationMs,\n ...(timeToFirstToken !== undefined && { timeToFirstTokenMs: timeToFirstToken }),\n finishReason: result.finishReason ?? 'unknown',\n },\n usage: {\n inputTokens: result.usage?.inputTokens ?? 0,\n outputTokens: result.usage?.outputTokens ?? 0,\n totalTokens: result.usage?.totalTokens ?? 0,\n // Note: estimatedCostUsd is calculated at display time from current model registry\n // to avoid stale pricing in stored results\n },\n toolCalls: {\n total: result.toolCallCount,\n names: toolNames,\n traces: result.toolCallTraces ?? [],\n },\n output: {\n text: result.text,\n valid: outputValid,\n ...(validationDetails && { validationDetails }),\n },\n artifacts: artifactResult,\n goals: {\n tracked: trackedGoals,\n metrics: goalMetrics,\n },\n };\n } finally {\n // Clean up MCP clients\n for (const connection of mcpClients) {\n try {\n await connection.client.close();\n } catch {\n // Ignore cleanup errors\n }\n }\n }\n } catch (error) {\n clearTimeout(timeoutId);\n const durationMs = Date.now() - startTime;\n\n const isAbort =\n error instanceof Error &&\n (error.name === 'AbortError' || abortController.signal.aborted);\n\n const errorInfo = {\n type: error instanceof Error ? error.name : 'unknown',\n message: error instanceof Error ? error.message : String(error),\n category: isAbort ? 'timeout' as ErrorCategory : 'runtime_error' as ErrorCategory,\n };\n\n return {\n trialNumber,\n execution: {\n success: false,\n durationMs,\n finishReason: isAbort ? 'timeout' : 'error',\n error: errorInfo,\n },\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n estimatedCostUsd: 0,\n },\n toolCalls: {\n total: 0,\n names: [],\n traces: [],\n },\n output: {\n text: '',\n valid: false,\n validationDetails: isAbort\n ? `Timeout after ${timeout}s`\n : `Error: ${error instanceof Error ? error.message : String(error)}`,\n },\n artifacts: {\n checked: 0,\n passed: 0,\n details: [],\n },\n };\n } finally {\n // Clean up trial directory\n try {\n await rm(trialDir, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Calculate statistics for an array of numbers\n */\nfunction calculateStats(values: number[]): {\n mean: number;\n median: number;\n p95: number;\n stdDev: number;\n} {\n if (values.length === 0) {\n return { mean: 0, median: 0, p95: 0, stdDev: 0 };\n }\n\n const sorted = [...values].sort((a, b) => a - b);\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\n const median = sorted[Math.floor(sorted.length / 2)];\n const p95Index = Math.ceil(sorted.length * 0.95) - 1;\n const p95 = sorted[Math.max(0, p95Index)];\n\n const variance =\n values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) /\n values.length;\n const stdDev = Math.sqrt(variance);\n\n return { mean, median, p95, stdDev };\n}\n\n/**\n * Calculate pass@k metric\n * pass@k = probability of at least one success in k trials\n * pass@k = 1 - (1 - p)^k where p is single-trial success rate\n */\nfunction calculatePassK(trials: TrialResult[], runs: number): number {\n const successRate =\n trials.filter((t) => t.execution.success && t.output.valid).length /\n trials.length;\n return 1 - Math.pow(1 - successRate, runs);\n}\n\n/**\n * Aggregate per-tool metrics from tool call traces\n */\nfunction aggregateToolMetrics(traces: ToolCallTrace[]): ToolMetrics[] {\n const toolMap = new Map<\n string,\n { total: number; success: number; durations: number[] }\n >();\n\n for (const trace of traces) {\n if (trace.type !== 'tool') continue;\n\n if (!toolMap.has(trace.name)) {\n toolMap.set(trace.name, { total: 0, success: 0, durations: [] });\n }\n\n const entry = toolMap.get(trace.name)!;\n entry.total++;\n if (trace.success !== false) entry.success++;\n entry.durations.push(trace.duration);\n }\n\n return Array.from(toolMap.entries()).map(([name, data]) => ({\n name,\n totalCalls: data.total,\n successfulCalls: data.success,\n failedCalls: data.total - data.success,\n successRate: data.total > 0 ? data.success / data.total : 1,\n avgDurationMs:\n data.durations.length > 0\n ? data.durations.reduce((a, b) => a + b, 0) / data.durations.length\n : 0,\n }));\n}\n\n/**\n * Aggregate error counts from trials\n */\nfunction aggregateErrorCounts(trials: TrialResult[]): ErrorCounts {\n const counts: ErrorCounts = {\n timeout: 0,\n runtime_error: 0,\n validation_failure: 0,\n tool_error: 0,\n unknown: 0,\n };\n\n for (const trial of trials) {\n if (!trial.execution.success || !trial.output.valid) {\n const category =\n trial.execution.error?.category ??\n (trial.output.valid ? 'unknown' : 'validation_failure');\n counts[category]++;\n }\n }\n\n return counts;\n}\n\n/**\n * Merge error counts from multiple sources\n */\nfunction mergeErrorCounts(allCounts: ErrorCounts[]): ErrorCounts {\n const merged: ErrorCounts = {\n timeout: 0,\n runtime_error: 0,\n validation_failure: 0,\n tool_error: 0,\n unknown: 0,\n };\n\n for (const counts of allCounts) {\n merged.timeout += counts.timeout;\n merged.runtime_error += counts.runtime_error;\n merged.validation_failure += counts.validation_failure;\n merged.tool_error += counts.tool_error;\n merged.unknown += counts.unknown;\n }\n\n return merged;\n}\n\n/**\n * Calculate token efficiency from successful trials\n */\nfunction calculateTokenEfficiency(\n trials: TrialResult[]\n): TokenEfficiency | undefined {\n const successfulTrials = trials.filter(\n (t) => t.execution.success && t.output.valid\n );\n if (successfulTrials.length === 0) return undefined;\n\n return {\n inputPerSuccess:\n successfulTrials.reduce((sum, t) => sum + t.usage.inputTokens, 0) /\n successfulTrials.length,\n outputPerSuccess:\n successfulTrials.reduce((sum, t) => sum + t.usage.outputTokens, 0) /\n successfulTrials.length,\n totalPerSuccess:\n successfulTrials.reduce((sum, t) => sum + t.usage.totalTokens, 0) /\n successfulTrials.length,\n };\n}\n\n/**\n * Average token efficiency across multiple sources\n */\nfunction averageTokenEfficiency(\n efficiencies: (TokenEfficiency | undefined)[]\n): TokenEfficiency | undefined {\n const valid = efficiencies.filter((e): e is TokenEfficiency => e !== undefined);\n if (valid.length === 0) return undefined;\n\n return {\n inputPerSuccess:\n valid.reduce((sum, e) => sum + e.inputPerSuccess, 0) / valid.length,\n outputPerSuccess:\n valid.reduce((sum, e) => sum + e.outputPerSuccess, 0) / valid.length,\n totalPerSuccess:\n valid.reduce((sum, e) => sum + e.totalPerSuccess, 0) / valid.length,\n };\n}\n\n/**\n * Aggregate goal metrics across multiple trials\n */\nfunction aggregateGoalMetrics(trials: TrialResult[]): GoalMetrics | undefined {\n const trialsWithGoals = trials.filter((t) => t.goals && t.goals.tracked.length > 0);\n if (trialsWithGoals.length === 0) {\n return undefined;\n }\n\n const allMetrics = trialsWithGoals.map((t) => t.goals!.metrics);\n\n // Average all metrics\n const totalGoals = allMetrics.reduce((sum, m) => sum + m.totalGoals, 0);\n const completedGoals = allMetrics.reduce((sum, m) => sum + m.completedGoals, 0);\n const failedGoals = allMetrics.reduce((sum, m) => sum + m.failedGoals, 0);\n const abandonedGoals = allMetrics.reduce((sum, m) => sum + m.abandonedGoals, 0);\n\n // Weighted averages for rates (handle undefined for backwards compatibility)\n const avgGoalCompletionRate =\n allMetrics.reduce((sum, m) => sum + m.goalCompletionRate, 0) / allMetrics.length;\n const avgAttemptsPerGoal =\n allMetrics.reduce((sum, m) => sum + m.avgAttemptsPerGoal, 0) / allMetrics.length;\n const avgToolCallSuccessRate =\n allMetrics.reduce((sum, m) => sum + m.toolCallSuccessRate, 0) / allMetrics.length;\n // toolCallFailureRate = 1 - toolCallSuccessRate (derive if missing for backwards compat)\n const avgToolCallFailureRate =\n allMetrics.reduce((sum, m) => sum + (m.toolCallFailureRate ?? (1 - m.toolCallSuccessRate)), 0) / allMetrics.length;\n const avgRecoveryRate =\n allMetrics.reduce((sum, m) => sum + m.recoveryRate, 0) / allMetrics.length;\n\n return {\n totalGoals,\n completedGoals,\n failedGoals,\n abandonedGoals,\n goalCompletionRate: avgGoalCompletionRate,\n avgAttemptsPerGoal,\n toolCallSuccessRate: avgToolCallSuccessRate,\n toolCallFailureRate: avgToolCallFailureRate,\n // toolCallEfficiency is calculated at cross-model comparison stage\n recoveryRate: avgRecoveryRate,\n };\n}\n\n/**\n * Run all trials for a scenario and aggregate results\n */\nasync function runScenario(\n agent: ParsedAgent,\n scenario: Scenario,\n model: string,\n runs: number,\n config: BenchmarkRunConfig,\n agentFilePath: string\n): Promise<ScenarioResult> {\n logger.info(` Scenario: ${scenario.name} (${runs} runs)`);\n\n const trials: TrialResult[] = [];\n\n for (let i = 0; i < runs; i++) {\n logger.info(` Trial ${i + 1}/${runs}...`);\n const trial = await runTrial(agent, scenario, i + 1, config, agentFilePath);\n trials.push(trial);\n\n // Check cost budget\n if (config.budgetUsd) {\n const totalCost = trials.reduce(\n (sum, t) => sum + (t.usage.estimatedCostUsd ?? 0),\n 0\n );\n if (totalCost > config.budgetUsd) {\n logger.warn(`Cost budget exceeded ($${totalCost.toFixed(2)} > $${config.budgetUsd})`);\n break;\n }\n }\n }\n\n // Calculate metrics\n const durations = trials.map((t) => t.execution.durationMs);\n const validCosts = trials\n .map((t) => t.usage.estimatedCostUsd)\n .filter((c): c is number => c !== undefined);\n const toolCounts = trials.map((t) => t.toolCalls.total);\n\n // Get unique tools used across all trials\n const uniqueTools = [\n ...new Set(trials.flatMap((t) => t.toolCalls.names)),\n ];\n\n const latencyStats = calculateStats(durations);\n const successfulTrials = trials.filter(\n (t) => t.execution.success && t.output.valid\n );\n const completionRate = successfulTrials.length / trials.length;\n const passK = calculatePassK(trials, runs);\n\n // Consistency: low variance = high consistency\n const outcomes = trials.map((t) =>\n t.execution.success && t.output.valid ? 1 : 0\n );\n const consistency = 1 - calculateStats(outcomes).stdDev;\n\n // Aggregate goal metrics across trials\n const goalMetrics = aggregateGoalMetrics(trials);\n\n // Calculate new metrics\n const allTraces = trials.flatMap((t) => t.toolCalls.traces);\n const perToolMetrics = aggregateToolMetrics(allTraces);\n const tokenEfficiency = calculateTokenEfficiency(trials);\n const errorCounts = aggregateErrorCounts(trials);\n\n // Cost per success\n const validSuccessCosts = successfulTrials\n .map((t) => t.usage.estimatedCostUsd)\n .filter((c): c is number => c !== undefined);\n const costPerSuccess =\n validSuccessCosts.length > 0\n ? validSuccessCosts.reduce((sum, c) => sum + c, 0) / validSuccessCosts.length\n : undefined;\n\n return {\n scenarioId: scenario.id,\n scenarioName: scenario.name,\n agentPath: '', // Will be set by caller\n model,\n ...(scenario.difficulty && { difficulty: scenario.difficulty }),\n trials,\n metrics: {\n completionRate,\n passK,\n consistency,\n latency: {\n meanMs: latencyStats.mean,\n medianMs: latencyStats.median,\n p95Ms: latencyStats.p95,\n stdDevMs: latencyStats.stdDev,\n },\n cost: {\n ...(validCosts.length > 0 && {\n meanUsd: validCosts.reduce((a, b) => a + b, 0) / validCosts.length,\n totalUsd: validCosts.reduce((a, b) => a + b, 0),\n }),\n ...(costPerSuccess !== undefined && { perSuccessUsd: costPerSuccess }),\n },\n toolCalls: {\n meanCount: toolCounts.reduce((a, b) => a + b, 0) / toolCounts.length,\n uniqueTools,\n perToolMetrics,\n },\n ...(tokenEfficiency && { tokenEfficiency }),\n errorCounts,\n ...(goalMetrics && { goals: goalMetrics }),\n },\n };\n}\n\n/**\n * Run all scenarios for an agent with a specific model\n */\nasync function runAgentBenchmark(\n test: LoadedTest,\n model: string,\n runs: number,\n config: BenchmarkRunConfig\n): Promise<AgentResult> {\n logger.info(`Agent: ${test.agent.name} (model: ${model})`);\n\n // Substitute model placeholder in agent config\n const agent = substituteModel(test.agent, model);\n\n const scenarios: ScenarioResult[] = [];\n\n for (const scenario of test.scenarios) {\n const result = await runScenario(agent, scenario, model, runs, config, test.agentPath);\n result.agentPath = test.agentPath;\n scenarios.push(result);\n }\n\n // Calculate aggregate metrics\n const completionRates = scenarios.map((s) => s.metrics.completionRate);\n const passKs = scenarios.map((s) => s.metrics.passK);\n const consistencies = scenarios.map((s) => s.metrics.consistency);\n const latencies = scenarios.map((s) => s.metrics.latency.meanMs);\n const validCosts = scenarios\n .map((s) => s.metrics.cost.totalUsd)\n .filter((c): c is number => c !== undefined);\n\n // Calculate mean tool calls for successful trials (efficiency calculated later via relative comparison)\n const successfulTrials = scenarios.flatMap((s) =>\n s.trials.filter((t) => t.execution.success && t.output.valid)\n );\n const meanToolCalls =\n successfulTrials.length > 0\n ? successfulTrials.reduce((sum, t) => sum + t.toolCalls.total, 0) /\n successfulTrials.length\n : 0;\n // Efficiency will be calculated after all models complete (relative to best performer per scenario)\n const efficiency = 0;\n\n // Aggregate goal metrics across all trials in all scenarios\n const allTrials = scenarios.flatMap((s) => s.trials);\n const agentGoalMetrics = aggregateGoalMetrics(allTrials);\n\n // Aggregate new metrics\n const agentTokenEfficiency = averageTokenEfficiency(\n scenarios.map((s) => s.metrics.tokenEfficiency)\n );\n const agentErrorCounts = mergeErrorCounts(\n scenarios.map((s) => s.metrics.errorCounts).filter((e): e is ErrorCounts => e !== undefined)\n );\n\n // Cost per success aggregated across all successful trials\n const validSuccessCosts = successfulTrials\n .map((t) => t.usage.estimatedCostUsd)\n .filter((c): c is number => c !== undefined);\n const costPerSuccess =\n validSuccessCosts.length > 0\n ? validSuccessCosts.reduce((sum, c) => sum + c, 0) / validSuccessCosts.length\n : undefined;\n\n return {\n agentPath: test.agentPath,\n agentName: test.agent.name,\n model,\n scenarios,\n aggregate: {\n completionRate:\n completionRates.reduce((a, b) => a + b, 0) / completionRates.length,\n passK: passKs.reduce((a, b) => a + b, 0) / passKs.length,\n consistency:\n consistencies.reduce((a, b) => a + b, 0) / consistencies.length,\n efficiency,\n meanToolCalls,\n latencyMeanMs: latencies.reduce((a, b) => a + b, 0) / latencies.length,\n ...(validCosts.length > 0 && { totalCostUsd: validCosts.reduce((a, b) => a + b, 0) }),\n ...(costPerSuccess !== undefined && { costPerSuccessUsd: costPerSuccess }),\n ...(agentTokenEfficiency && { tokenEfficiency: agentTokenEfficiency }),\n errorCounts: agentErrorCounts,\n ...(agentGoalMetrics && { goals: agentGoalMetrics }),\n },\n };\n}\n\n/**\n * Calculate relative efficiency for all models based on per-scenario comparison.\n * Efficiency = minToolCalls / meanToolCalls (best performer per scenario = 1.0)\n */\nfunction calculateRelativeEfficiency(\n modelResults: SuiteResult['modelResults']\n): void {\n // Collect all scenario results grouped by scenarioId\n const scenariosByModel: Map<\n string, // scenarioId\n Array<{ model: string; agentIdx: number; scenarioIdx: number; meanToolCalls: number }>\n > = new Map();\n\n for (const [model, result] of Object.entries(modelResults)) {\n for (let agentIdx = 0; agentIdx < result.agents.length; agentIdx++) {\n const agent = result.agents[agentIdx];\n for (let scenarioIdx = 0; scenarioIdx < agent.scenarios.length; scenarioIdx++) {\n const scenario = agent.scenarios[scenarioIdx];\n const scenarioId = scenario.scenarioId;\n\n // Calculate mean tool calls for successful trials in this scenario\n const successfulTrials = scenario.trials.filter(\n (t) => t.execution.success && t.output.valid\n );\n const meanToolCalls =\n successfulTrials.length > 0\n ? successfulTrials.reduce((sum, t) => sum + t.toolCalls.total, 0) /\n successfulTrials.length\n : 0;\n\n if (!scenariosByModel.has(scenarioId)) {\n scenariosByModel.set(scenarioId, []);\n }\n scenariosByModel.get(scenarioId)!.push({\n model,\n agentIdx,\n scenarioIdx,\n meanToolCalls,\n });\n }\n }\n }\n\n // For each scenario, find minimum tool calls and calculate relative efficiency\n for (const [, entries] of scenariosByModel) {\n // Only consider entries with successful completions (meanToolCalls > 0)\n const successfulEntries = entries.filter((e) => e.meanToolCalls > 0);\n if (successfulEntries.length === 0) continue;\n\n const minToolCalls = Math.min(...successfulEntries.map((e) => e.meanToolCalls));\n\n // Update efficiency for each entry (relative to best performer)\n for (const entry of entries) {\n const efficiency =\n entry.meanToolCalls > 0 ? minToolCalls / entry.meanToolCalls : 0;\n\n // Update the scenario's metrics\n const agent = modelResults[entry.model].agents[entry.agentIdx];\n const scenario = agent.scenarios[entry.scenarioIdx];\n scenario.metrics.efficiency = efficiency;\n }\n }\n\n // Calculate scenario-level goal toolCallEfficiency\n // Compare avgAttemptsPerGoal across models for each scenario\n const scenarioGoalsByModel: Map<\n string, // scenarioId\n Array<{ model: string; agentIdx: number; scenarioIdx: number; avgAttemptsPerGoal: number }>\n > = new Map();\n\n for (const [model, result] of Object.entries(modelResults)) {\n for (let agentIdx = 0; agentIdx < result.agents.length; agentIdx++) {\n const agent = result.agents[agentIdx];\n for (let scenarioIdx = 0; scenarioIdx < agent.scenarios.length; scenarioIdx++) {\n const scenario = agent.scenarios[scenarioIdx];\n const goals = scenario.metrics.goals;\n if (!goals || goals.avgAttemptsPerGoal <= 0) continue;\n\n const scenarioId = scenario.scenarioId;\n if (!scenarioGoalsByModel.has(scenarioId)) {\n scenarioGoalsByModel.set(scenarioId, []);\n }\n scenarioGoalsByModel.get(scenarioId)!.push({\n model,\n agentIdx,\n scenarioIdx,\n avgAttemptsPerGoal: goals.avgAttemptsPerGoal,\n });\n }\n }\n }\n\n // For each scenario, find minimum avgAttemptsPerGoal and calculate relative efficiency\n for (const [, entries] of scenarioGoalsByModel) {\n if (entries.length === 0) continue;\n\n const minAttempts = Math.min(...entries.map((e) => e.avgAttemptsPerGoal));\n\n for (const entry of entries) {\n const goalEfficiency = minAttempts / entry.avgAttemptsPerGoal;\n\n // Update the scenario's goal metrics\n const agent = modelResults[entry.model].agents[entry.agentIdx];\n const scenario = agent.scenarios[entry.scenarioIdx];\n if (scenario.metrics.goals) {\n scenario.metrics.goals.toolCallEfficiency = goalEfficiency;\n }\n }\n }\n\n // Now recalculate agent-level and model-level efficiency aggregates\n for (const [_model, result] of Object.entries(modelResults)) {\n for (const agent of result.agents) {\n // Average efficiency across scenarios for this agent\n const scenarioEfficiencies = agent.scenarios\n .map((s) => s.metrics.efficiency ?? 0);\n agent.aggregate.efficiency =\n scenarioEfficiencies.length > 0\n ? scenarioEfficiencies.reduce((a, b) => a + b, 0) / scenarioEfficiencies.length\n : 0;\n }\n\n // Recalculate model-level efficiency\n const agentEfficiencies = result.agents.map((a) => a.aggregate.efficiency);\n result.aggregate.efficiency =\n agentEfficiencies.length > 0\n ? agentEfficiencies.reduce((a, b) => a + b, 0) / agentEfficiencies.length\n : 0;\n\n // Recalculate overall score with new efficiency\n result.aggregate.overallScore =\n result.aggregate.passK * 60 +\n result.aggregate.efficiency * 40;\n }\n\n // Calculate goal toolCallEfficiency (relative efficiency based on avgAttemptsPerGoal)\n // Lower avgAttemptsPerGoal = better efficiency\n const modelsWithGoals = Object.entries(modelResults)\n .filter(([, result]) => result.aggregate.goals && result.aggregate.goals.avgAttemptsPerGoal > 0)\n .map(([model, result]) => ({\n model,\n avgAttemptsPerGoal: result.aggregate.goals!.avgAttemptsPerGoal,\n }));\n\n if (modelsWithGoals.length > 0) {\n const minAttempts = Math.min(...modelsWithGoals.map((m) => m.avgAttemptsPerGoal));\n\n for (const { model, avgAttemptsPerGoal } of modelsWithGoals) {\n const goalEfficiency = minAttempts / avgAttemptsPerGoal;\n if (modelResults[model].aggregate.goals) {\n modelResults[model].aggregate.goals.toolCallEfficiency = goalEfficiency;\n }\n }\n }\n}\n\n/**\n * Run the full benchmark suite\n */\nexport async function runBenchmarkSuite(\n loadedSuite: LoadedSuite,\n config: BenchmarkRunConfig\n): Promise<SuiteResult> {\n const { suite, tests } = loadedSuite;\n const runId = ulid();\n const startTime = Date.now();\n\n // Use config overrides or suite defaults\n const models = config.models ?? suite.config.models;\n const runs = config.runs ?? suite.config.runs;\n\n logger.info(`\\nBenchmark: ${suite.name}`);\n logger.info(`Models: ${models.join(', ')}`);\n logger.info(`Runs per scenario: ${runs}`);\n logger.info(`Total scenarios: ${tests.reduce((sum, t) => sum + t.scenarios.length, 0)}`);\n logger.separator();\n\n const modelResults: SuiteResult['modelResults'] = {};\n\n for (const model of models) {\n logger.info(`\\n=== Model: ${model} ===\\n`);\n\n const agents: AgentResult[] = [];\n\n for (const test of tests) {\n const agentResult = await runAgentBenchmark(test, model, runs, config);\n agents.push(agentResult);\n }\n\n // Calculate model aggregate\n const completionRates = agents.map((a) => a.aggregate.completionRate);\n const passKs = agents.map((a) => a.aggregate.passK);\n const consistencies = agents.map((a) => a.aggregate.consistency);\n const efficiencies = agents.map((a) => a.aggregate.efficiency);\n const toolCalls = agents.map((a) => a.aggregate.meanToolCalls);\n const latencies = agents.map((a) => a.aggregate.latencyMeanMs);\n const validCosts = agents\n .map((a) => a.aggregate.totalCostUsd)\n .filter((c): c is number => c !== undefined);\n\n const avgCompletionRate =\n completionRates.reduce((a, b) => a + b, 0) / completionRates.length;\n const avgPassK = passKs.reduce((a, b) => a + b, 0) / passKs.length;\n const avgConsistency =\n consistencies.reduce((a, b) => a + b, 0) / consistencies.length;\n const avgEfficiency =\n efficiencies.reduce((a, b) => a + b, 0) / efficiencies.length;\n const avgMeanToolCalls =\n toolCalls.reduce((a, b) => a + b, 0) / toolCalls.length;\n\n // Aggregate goal metrics across all agents\n const allModelTrials = agents.flatMap((a) =>\n a.scenarios.flatMap((s) => s.trials)\n );\n const modelGoalMetrics = aggregateGoalMetrics(allModelTrials);\n\n // Aggregate new metrics\n const modelTokenEfficiency = averageTokenEfficiency(\n agents.map((a) => a.aggregate.tokenEfficiency)\n );\n const modelErrorCounts = mergeErrorCounts(\n agents.map((a) => a.aggregate.errorCounts).filter((e): e is ErrorCounts => e !== undefined)\n );\n\n // Cost per success aggregated across all successful trials\n const successfulTrials = allModelTrials.filter(\n (t) => t.execution.success && t.output.valid\n );\n const validSuccessCosts = successfulTrials\n .map((t) => t.usage.estimatedCostUsd)\n .filter((c): c is number => c !== undefined);\n const modelCostPerSuccess =\n validSuccessCosts.length > 0\n ? validSuccessCosts.reduce((sum, c) => sum + c, 0) / validSuccessCosts.length\n : undefined;\n\n // Overall score: weighted combination (agentic capability focus)\n // 60% passK (reliability - probability of at least one success in k trials)\n // 40% efficiency (fewer tool calls = higher efficiency)\n // Note: Speed excluded intentionally - this is a capability benchmark, not infrastructure\n const overallScore =\n avgPassK * 60 + avgEfficiency * 40;\n\n modelResults[model] = {\n agents,\n aggregate: {\n completionRate: avgCompletionRate,\n passK: avgPassK,\n consistency: avgConsistency,\n efficiency: avgEfficiency,\n meanToolCalls: avgMeanToolCalls,\n latencyMeanMs: latencies.reduce((a, b) => a + b, 0) / latencies.length,\n ...(validCosts.length > 0 && { totalCostUsd: validCosts.reduce((a, b) => a + b, 0) }),\n ...(modelCostPerSuccess !== undefined && { costPerSuccessUsd: modelCostPerSuccess }),\n ...(modelTokenEfficiency && { tokenEfficiency: modelTokenEfficiency }),\n errorCounts: modelErrorCounts,\n overallScore,\n ...(modelGoalMetrics && { goals: modelGoalMetrics }),\n },\n };\n }\n\n // Calculate relative efficiency across all models for each scenario\n // This updates efficiency values based on best performer per scenario\n calculateRelativeEfficiency(modelResults);\n\n // Create ranking\n const ranking = Object.entries(modelResults)\n .map(([model, result]) => ({\n model,\n score: result.aggregate.overallScore,\n completionRate: result.aggregate.completionRate,\n passK: result.aggregate.passK,\n consistency: result.aggregate.consistency,\n efficiency: result.aggregate.efficiency,\n meanToolCalls: result.aggregate.meanToolCalls,\n ...(result.aggregate.totalCostUsd !== undefined && {\n costUsd: result.aggregate.totalCostUsd,\n }),\n ...(result.aggregate.costPerSuccessUsd !== undefined && {\n costPerSuccessUsd: result.aggregate.costPerSuccessUsd,\n }),\n ...(result.aggregate.goals && {\n goals: {\n completionRate: result.aggregate.goals.goalCompletionRate,\n avgAttempts: result.aggregate.goals.avgAttemptsPerGoal,\n toolCallSuccessRate: result.aggregate.goals.toolCallSuccessRate,\n toolCallFailureRate: result.aggregate.goals.toolCallFailureRate,\n ...(result.aggregate.goals.toolCallEfficiency !== undefined && {\n toolCallEfficiency: result.aggregate.goals.toolCallEfficiency,\n }),\n recoveryRate: result.aggregate.goals.recoveryRate,\n },\n }),\n }))\n .sort((a, b) => b.score - a.score)\n .map((entry, index) => ({\n ...entry,\n rank: index + 1,\n }));\n\n const totalScenarios = tests.reduce(\n (sum, t) => sum + t.scenarios.length,\n 0\n );\n\n return {\n suiteId: suite.id,\n suiteName: suite.name,\n runId,\n timestamp: startTime,\n durationMs: Date.now() - startTime,\n config: {\n models,\n runs,\n totalScenarios,\n totalTrials: totalScenarios * models.length * runs,\n },\n modelResults,\n ranking,\n };\n}\n",
|
|
95
|
+
"import { generateText } from 'ai';\nimport { createModel } from '../../models.js';\nimport type { OutputValidation } from '../types.js';\n\nexport interface CompletionEvalResult {\n valid: boolean;\n details: string;\n}\n\n/**\n * Evaluate output with \"contains\" validation\n * Checks if output contains all required values\n */\nfunction evaluateContains(\n output: string,\n values: string[]\n): CompletionEvalResult {\n const lowerOutput = output.toLowerCase();\n const missing = values.filter(\n (v) => !lowerOutput.includes(v.toLowerCase())\n );\n\n if (missing.length === 0) {\n return {\n valid: true,\n details: `Output contains all ${values.length} required values`,\n };\n }\n\n return {\n valid: false,\n details: `Missing values: ${missing.join(', ')}`,\n };\n}\n\n/**\n * Evaluate output with regex pattern\n */\nfunction evaluateRegex(\n output: string,\n pattern: string\n): CompletionEvalResult {\n try {\n const regex = new RegExp(pattern, 'is'); // case-insensitive, dotall\n const match = regex.test(output);\n\n return {\n valid: match,\n details: match\n ? `Output matches pattern: ${pattern}`\n : `Output does not match pattern: ${pattern}`,\n };\n } catch (error) {\n return {\n valid: false,\n details: `Invalid regex pattern: ${pattern}`,\n };\n }\n}\n\n/**\n * Evaluate output using LLM as judge\n * Uses a fast model to evaluate against criteria\n */\nasync function evaluateLLMJudge(\n output: string,\n criteria: string,\n model?: string\n): Promise<CompletionEvalResult> {\n // Default to a fast model; support provider:model format\n const judgeModelString = model ?? 'openai:gpt-5.2-mini';\n\n const userPrompt = `You are evaluating an AI agent's output against specific criteria.\n\n## Agent Output:\n${output}\n\n## Evaluation Criteria:\n${criteria}\n\n## Instructions:\nEvaluate whether the agent's output satisfies ALL the criteria listed above.\nRespond with a JSON object containing:\n- \"pass\": boolean (true if ALL criteria are met, false otherwise)\n- \"reasoning\": string (brief explanation of your evaluation)\n\nRespond ONLY with the JSON object, no other text.`;\n\n try {\n const judgeModel = await createModel(judgeModelString);\n\n // For Anthropic models, we need the Claude Code system prompt for OAuth credentials\n const isAnthropic = judgeModelString.includes('anthropic');\n\n const result = await generateText({\n model: judgeModel,\n ...(isAnthropic && {\n system: \"You are Claude Code, Anthropic's official CLI for Claude.\",\n }),\n prompt: userPrompt,\n temperature: 0,\n maxOutputTokens: 500,\n });\n\n // Parse the JSON response\n const jsonMatch = result.text.match(/\\{[\\s\\S]*\\}/);\n if (!jsonMatch) {\n return {\n valid: false,\n details: 'LLM judge returned invalid response format',\n };\n }\n\n const evaluation = JSON.parse(jsonMatch[0]) as {\n pass: boolean;\n reasoning: string;\n };\n\n return {\n valid: evaluation.pass,\n details: evaluation.reasoning,\n };\n } catch (error) {\n return {\n valid: false,\n details: `LLM judge error: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n}\n\n/**\n * Evaluate output against validation rules\n */\nexport async function evaluateCompletion(\n output: string,\n validation: OutputValidation\n): Promise<CompletionEvalResult> {\n switch (validation.type) {\n case 'contains':\n return evaluateContains(output, validation.values);\n\n case 'regex':\n return evaluateRegex(output, validation.pattern);\n\n case 'llm-judge':\n return evaluateLLMJudge(output, validation.criteria, validation.model);\n\n default:\n return {\n valid: false,\n details: `Unknown validation type: ${(validation as { type: string }).type}`,\n };\n }\n}\n",
|
|
96
|
+
"import { access, readFile } from 'fs/promises';\nimport { join } from 'path';\nimport type { ArtifactExpectation } from '../types.js';\n\nexport interface ArtifactCheckResult {\n path: string;\n exists: boolean;\n containsMatch: boolean;\n details?: string;\n}\n\nexport interface ArtifactsEvalResult {\n valid: boolean;\n checked: number;\n passed: number;\n details: ArtifactCheckResult[];\n}\n\n/**\n * Check if a file exists\n */\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Check if file contains all required strings\n */\nasync function fileContains(\n path: string,\n values: string[]\n): Promise<{ match: boolean; missing: string[] }> {\n try {\n const content = await readFile(path, 'utf-8');\n const lowerContent = content.toLowerCase();\n const missing = values.filter(\n (v) => !lowerContent.includes(v.toLowerCase())\n );\n return { match: missing.length === 0, missing };\n } catch {\n return { match: false, missing: values };\n }\n}\n\n/**\n * Evaluate a single artifact expectation\n */\nasync function evaluateArtifact(\n expectation: ArtifactExpectation,\n baseDir: string\n): Promise<ArtifactCheckResult> {\n const fullPath = join(baseDir, expectation.path);\n\n // Check existence\n const exists = await fileExists(fullPath);\n\n // If we expect it to not exist\n if (!expectation.exists) {\n return {\n path: expectation.path,\n exists,\n containsMatch: !exists, // Pass if it doesn't exist\n details: exists\n ? 'File exists but should not'\n : 'File correctly does not exist',\n };\n }\n\n // If we expect it to exist but it doesn't\n if (!exists) {\n return {\n path: expectation.path,\n exists: false,\n containsMatch: false,\n details: 'File does not exist',\n };\n }\n\n // Check contains if specified\n if (expectation.contains && expectation.contains.length > 0) {\n const { match, missing } = await fileContains(\n fullPath,\n expectation.contains\n );\n\n return {\n path: expectation.path,\n exists: true,\n containsMatch: match,\n details: match\n ? `File contains all ${expectation.contains.length} required values`\n : `File missing values: ${missing.join(', ')}`,\n };\n }\n\n // File exists and no content check required\n return {\n path: expectation.path,\n exists: true,\n containsMatch: true,\n details: 'File exists',\n };\n}\n\n/**\n * Evaluate all artifact expectations\n */\nexport async function evaluateArtifacts(\n expectations: ArtifactExpectation[],\n baseDir: string\n): Promise<ArtifactsEvalResult> {\n if (expectations.length === 0) {\n return {\n valid: true,\n checked: 0,\n passed: 0,\n details: [],\n };\n }\n\n const results: ArtifactCheckResult[] = [];\n\n for (const expectation of expectations) {\n const result = await evaluateArtifact(expectation, baseDir);\n results.push(result);\n }\n\n const passed = results.filter((r) => r.containsMatch).length;\n\n return {\n valid: passed === results.length,\n checked: results.length,\n passed,\n details: results,\n };\n}\n",
|
|
97
|
+
"/**\n * Goal tracking for benchmark runs\n * Enables measuring efficiency, capability, and resilience\n */\n\nimport type { ToolCallTrace } from '../plugin/types.js';\nimport type { GoalMetrics, TrackedGoal } from './types.js';\n\nexport type { GoalMetrics, TrackedGoal };\n\n/**\n * Goal tracker for benchmark runs\n * Tracks goals declared by agents and associates tool calls with them\n */\nexport class GoalTracker {\n private goals: Map<string, TrackedGoal> = new Map();\n private activeGoalName: string | null = null;\n private goalCounter = 0;\n\n /**\n * Declare a new goal\n */\n declareGoal(name: string, description?: string): void {\n // If there's an active goal, mark it as abandoned\n if (this.activeGoalName) {\n const activeGoal = this.goals.get(this.activeGoalName);\n if (activeGoal && activeGoal.status === 'active') {\n activeGoal.status = 'abandoned';\n activeGoal.endTime = Date.now();\n }\n }\n\n const id = `goal_${++this.goalCounter}`;\n const goal: TrackedGoal = {\n id,\n name,\n ...(description !== undefined && { description }),\n startTime: Date.now(),\n status: 'active',\n toolCalls: [],\n };\n\n this.goals.set(name, goal);\n this.activeGoalName = name;\n }\n\n /**\n * Complete a goal\n */\n completeGoal(name: string, success: boolean): void {\n const goal = this.goals.get(name);\n if (!goal) {\n // Goal wasn't declared, create it retroactively\n this.declareGoal(name);\n const newGoal = this.goals.get(name)!;\n newGoal.status = success ? 'completed' : 'failed';\n newGoal.endTime = Date.now();\n } else {\n goal.status = success ? 'completed' : 'failed';\n goal.endTime = Date.now();\n }\n\n // Clear active goal if this was the active one\n if (this.activeGoalName === name) {\n this.activeGoalName = null;\n }\n }\n\n /**\n * Record a tool call (called after each tool execution)\n */\n recordToolCall(name: string, success: boolean, duration: number): void {\n if (this.activeGoalName) {\n const goal = this.goals.get(this.activeGoalName);\n if (goal && goal.status === 'active') {\n goal.toolCalls.push({ name, success, duration });\n }\n }\n }\n\n /**\n * Process tool call traces to associate them with goals\n * This is called after the agent run completes\n */\n processTraces(traces: ToolCallTrace[]): void {\n let currentGoalName: string | null = null;\n\n for (const trace of traces) {\n // Skip LLM traces\n if (trace.type === 'llm') continue;\n\n // Check for goal declaration/completion\n if (trace.name === 'benchmark__declare_goal') {\n const input = trace.input as { name: string; description?: string } | undefined;\n if (input?.name) {\n currentGoalName = input.name;\n // Goal should already be declared by the tool execution\n }\n } else if (trace.name === 'benchmark__complete_goal') {\n const input = trace.input as { name: string; success: boolean } | undefined;\n if (input?.name) {\n currentGoalName = null;\n }\n } else if (currentGoalName) {\n // Associate this tool call with the current goal\n const goal = this.goals.get(currentGoalName);\n if (goal) {\n goal.toolCalls.push({\n name: trace.name,\n success: trace.success ?? true,\n duration: trace.duration,\n });\n }\n }\n }\n\n // Mark any still-active goals as abandoned\n for (const goal of this.goals.values()) {\n if (goal.status === 'active') {\n goal.status = 'abandoned';\n goal.endTime = Date.now();\n }\n }\n }\n\n /**\n * Get all tracked goals\n */\n getGoals(): TrackedGoal[] {\n return Array.from(this.goals.values());\n }\n\n /**\n * Calculate goal metrics\n */\n getMetrics(): GoalMetrics {\n const goals = this.getGoals();\n\n if (goals.length === 0) {\n return {\n totalGoals: 0,\n completedGoals: 0,\n failedGoals: 0,\n abandonedGoals: 0,\n goalCompletionRate: 0,\n avgAttemptsPerGoal: 0,\n toolCallSuccessRate: 1,\n toolCallFailureRate: 0,\n recoveryRate: 1,\n };\n }\n\n const completedGoals = goals.filter(g => g.status === 'completed').length;\n const failedGoals = goals.filter(g => g.status === 'failed').length;\n const abandonedGoals = goals.filter(g => g.status === 'abandoned').length;\n\n // Calculate tool call stats\n const allToolCalls = goals.flatMap(g => g.toolCalls);\n const totalToolCalls = allToolCalls.length;\n const successfulToolCalls = allToolCalls.filter(t => t.success).length;\n\n // Calculate recovery rate: goals that had failures but still completed\n const goalsWithFailures = goals.filter(g =>\n g.toolCalls.some(t => !t.success)\n );\n const recoveredGoals = goalsWithFailures.filter(g => g.status === 'completed');\n\n const failedToolCalls = totalToolCalls - successfulToolCalls;\n\n return {\n totalGoals: goals.length,\n completedGoals,\n failedGoals,\n abandonedGoals,\n goalCompletionRate: completedGoals / goals.length,\n avgAttemptsPerGoal: totalToolCalls / goals.length,\n toolCallSuccessRate: totalToolCalls > 0 ? successfulToolCalls / totalToolCalls : 1,\n toolCallFailureRate: totalToolCalls > 0 ? failedToolCalls / totalToolCalls : 0,\n recoveryRate: goalsWithFailures.length > 0\n ? recoveredGoals.length / goalsWithFailures.length\n : 1, // No failures = perfect recovery\n };\n }\n\n /**\n * Reset the tracker for a new run\n */\n reset(): void {\n this.goals.clear();\n this.activeGoalName = null;\n this.goalCounter = 0;\n }\n}\n",
|
|
98
|
+
"/**\n * Goal tracking tools for benchmark runs\n * These tools are auto-injected during benchmarks to enable explicit goal tracking\n */\n\nimport type { Tool } from 'ai';\nimport { z } from 'zod';\nimport type { GoalTracker } from './goal-tracker.js';\n\n/**\n * Create goal tracking tools bound to a GoalTracker instance\n */\nexport function createGoalTools(tracker: GoalTracker): Record<string, Tool> {\n return {\n benchmark__declare_goal: {\n description: `Declare a new goal or sub-task you're working on. Use this when starting work on a distinct objective.\nThis helps benchmark your problem-solving approach by tracking:\n- How many goals you set\n- How many tool calls you make per goal\n- Whether you recover from failures\n\nExample: declare_goal({ name: \"Find database schema\", description: \"Locate and understand the database structure\" })`,\n inputSchema: z.object({\n name: z.string().describe('A short, descriptive name for this goal'),\n description: z.string().optional().describe('Optional longer description of what you\\'re trying to accomplish'),\n }),\n execute: async ({ name, description }: { name: string; description?: string }): Promise<string> => {\n tracker.declareGoal(name, description);\n return JSON.stringify({\n success: true,\n message: `Goal \"${name}\" declared. Tool calls will now be tracked against this goal.`,\n });\n },\n },\n\n benchmark__complete_goal: {\n description: `Mark a goal as completed or failed. Use this when you've finished working on a goal, whether successfully or not.\n\nExample successful: complete_goal({ name: \"Find database schema\", success: true })\nExample failed: complete_goal({ name: \"Find database schema\", success: false })`,\n inputSchema: z.object({\n name: z.string().describe('The name of the goal to complete (must match a declared goal)'),\n success: z.boolean().describe('Whether the goal was achieved successfully'),\n }),\n execute: async ({ name, success }: { name: string; success: boolean }): Promise<string> => {\n tracker.completeGoal(name, success);\n return JSON.stringify({\n success: true,\n message: `Goal \"${name}\" marked as ${success ? 'completed' : 'failed'}.`,\n });\n },\n },\n };\n}\n\n/**\n * System prompt addition for goal tracking\n */\nexport const GOAL_TRACKING_PROMPT = `\n## Goal Tracking (Benchmark Mode) - REQUIRED\n\n**IMPORTANT: You MUST use goal tracking tools for this benchmark.**\n\nBefore making ANY tool calls to accomplish the task, you MUST first call:\n- **benchmark__declare_goal**: Declare what you're about to work on\n\nWhen you finish a goal (successfully or not), you MUST call:\n- **benchmark__complete_goal**: Mark the goal as done\n\n**This is mandatory.** Your first action after reading the task should be to declare a goal.\n\nExample workflow (you MUST follow this pattern):\n1. benchmark__declare_goal({ name: \"Get database schema\", description: \"Retrieve the schema\" })\n2. [Make tool calls to accomplish the goal]\n3. benchmark__complete_goal({ name: \"Get database schema\", success: true })\n\nIf the task has multiple steps, declare and complete goals for each step.\n`;\n",
|
|
99
|
+
"import { writeFile, mkdir } from 'fs/promises';\nimport { join } from 'path';\nimport type { SuiteResult, RawBenchmarkResult } from '../types.js';\nimport { extractRawData } from '../calculator.js';\n\n/**\n * Generate JSON report from suite results\n * Saves only raw trial data - metrics are computed on load\n */\nexport function generateJsonReport(result: SuiteResult): string {\n const rawData = extractRawData(result);\n return JSON.stringify(rawData, null, 2);\n}\n\n/**\n * Save JSON report to file\n */\nexport async function saveJsonReport(\n result: SuiteResult,\n outputDir: string\n): Promise<string> {\n await mkdir(outputDir, { recursive: true });\n\n const filename = `${result.suiteId}-${result.runId}.json`;\n const filepath = join(outputDir, filename);\n\n await writeFile(filepath, generateJsonReport(result), 'utf-8');\n\n return filepath;\n}\n\n/**\n * Type guard to check if loaded JSON is raw format\n */\nexport function isRawBenchmarkResult(data: unknown): data is RawBenchmarkResult {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'version' in data &&\n (data as RawBenchmarkResult).version === 2 &&\n 'trials' in data &&\n Array.isArray((data as RawBenchmarkResult).trials)\n );\n}\n",
|
|
100
|
+
"/**\r\n * Benchmark metrics calculator\r\n * Computes all derived metrics from raw trial data\r\n */\r\n\r\nimport {\r\n type RawBenchmarkResult,\r\n type RawTrialEntry,\r\n type SuiteResult,\r\n type ScenarioResult,\r\n type AgentResult,\r\n type TrialResult,\r\n type GoalMetrics,\r\n type ToolMetrics,\r\n type ErrorCounts,\r\n type TokenEfficiency,\r\n type ToolCallTrace,\r\n calculateCost,\r\n} from './types.js';\r\n\r\n// ============ Difficulty Weights ============\r\n\r\n/**\r\n * Weights for difficulty levels when calculating weighted scores\r\n * Higher difficulty = higher weight in the final score\r\n */\r\nconst DIFFICULTY_WEIGHTS: Record<'easy' | 'medium' | 'hard', number> = {\r\n easy: 1,\r\n medium: 2,\r\n hard: 3,\r\n};\r\n\r\n// ============ Stats Helpers ============\r\n\r\ninterface Stats {\r\n mean: number;\r\n median: number;\r\n p95: number;\r\n stdDev: number;\r\n}\r\n\r\nfunction calculateStats(values: number[]): Stats {\r\n if (values.length === 0) {\r\n return { mean: 0, median: 0, p95: 0, stdDev: 0 };\r\n }\r\n\r\n const sorted = [...values].sort((a, b) => a - b);\r\n const mean = values.reduce((a, b) => a + b, 0) / values.length;\r\n const median = sorted[Math.floor(sorted.length / 2)];\r\n const p95Index = Math.ceil(sorted.length * 0.95) - 1;\r\n const p95 = sorted[Math.max(0, p95Index)];\r\n\r\n const variance =\r\n values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) /\r\n values.length;\r\n const stdDev = Math.sqrt(variance);\r\n\r\n return { mean, median, p95, stdDev };\r\n}\r\n\r\n/**\r\n * Calculate pass@k metric\r\n * pass@k = probability of at least one success in k trials\r\n * pass@k = 1 - (1 - p)^k where p is single-trial success rate\r\n */\r\nfunction calculatePassK(trials: TrialResult[], runs: number): number {\r\n if (trials.length === 0) return 0;\r\n const successRate =\r\n trials.filter((t) => t.execution.success && t.output.valid).length /\r\n trials.length;\r\n return 1 - Math.pow(1 - successRate, runs);\r\n}\r\n\r\n/**\r\n * Calculate difficulty-weighted score for scenarios\r\n * Returns undefined if no scenarios have difficulty set\r\n *\r\n * @param scenarios - Array of scenario results\r\n * @returns Weighted score 0-100 or undefined if no difficulties\r\n */\r\nfunction calculateWeightedScore(\r\n scenarios: Array<{\r\n passK: number;\r\n efficiency: number;\r\n toolSuccessRate: number;\r\n difficulty: 'easy' | 'medium' | 'hard' | undefined;\r\n }>\r\n): number | undefined {\r\n const scenariosWithDifficulty = scenarios.filter(s => s.difficulty !== undefined);\r\n\r\n // Only calculate weighted score if at least one scenario has difficulty set\r\n if (scenariosWithDifficulty.length === 0) {\r\n return undefined;\r\n }\r\n\r\n let weightedPassK = 0;\r\n let weightedEfficiency = 0;\r\n let weightedToolSuccessRate = 0;\r\n let totalWeight = 0;\r\n\r\n for (const scenario of scenarios) {\r\n // Use weight 1 for scenarios without difficulty (treat as easy)\r\n const weight = scenario.difficulty ? DIFFICULTY_WEIGHTS[scenario.difficulty] : 1;\r\n weightedPassK += scenario.passK * weight;\r\n weightedEfficiency += scenario.efficiency * weight;\r\n weightedToolSuccessRate += scenario.toolSuccessRate * weight;\r\n totalWeight += weight;\r\n }\r\n\r\n if (totalWeight === 0) return undefined;\r\n\r\n const avgWeightedPassK = weightedPassK / totalWeight;\r\n const avgWeightedEfficiency = weightedEfficiency / totalWeight;\r\n const avgWeightedToolSuccessRate = weightedToolSuccessRate / totalWeight;\r\n\r\n // Formula: passK x 50 + efficiency x 30 + toolSuccessRate x 20\r\n return avgWeightedPassK * 50 + avgWeightedEfficiency * 30 + avgWeightedToolSuccessRate * 20;\r\n}\r\n\r\n// ============ Aggregation Helpers ============\r\n\r\nfunction aggregateToolMetrics(traces: ToolCallTrace[]): ToolMetrics[] {\r\n const toolMap = new Map<\r\n string,\r\n { total: number; success: number; durations: number[] }\r\n >();\r\n\r\n for (const trace of traces) {\r\n if (trace.type !== 'tool') continue;\r\n\r\n if (!toolMap.has(trace.name)) {\r\n toolMap.set(trace.name, { total: 0, success: 0, durations: [] });\r\n }\r\n\r\n const entry = toolMap.get(trace.name)!;\r\n entry.total++;\r\n if (trace.success !== false) entry.success++;\r\n entry.durations.push(trace.duration);\r\n }\r\n\r\n return Array.from(toolMap.entries()).map(([name, data]) => ({\r\n name,\r\n totalCalls: data.total,\r\n successfulCalls: data.success,\r\n failedCalls: data.total - data.success,\r\n successRate: data.total > 0 ? data.success / data.total : 1,\r\n avgDurationMs:\r\n data.durations.length > 0\r\n ? data.durations.reduce((a, b) => a + b, 0) / data.durations.length\r\n : 0,\r\n }));\r\n}\r\n\r\nfunction aggregateErrorCounts(trials: TrialResult[]): ErrorCounts {\r\n const counts: ErrorCounts = {\r\n timeout: 0,\r\n runtime_error: 0,\r\n validation_failure: 0,\r\n tool_error: 0,\r\n unknown: 0,\r\n };\r\n\r\n for (const trial of trials) {\r\n if (!trial.execution.success || !trial.output.valid) {\r\n const category =\r\n trial.execution.error?.category ??\r\n (trial.output.valid ? 'unknown' : 'validation_failure');\r\n counts[category]++;\r\n }\r\n }\r\n\r\n return counts;\r\n}\r\n\r\nfunction mergeErrorCounts(allCounts: ErrorCounts[]): ErrorCounts {\r\n const merged: ErrorCounts = {\r\n timeout: 0,\r\n runtime_error: 0,\r\n validation_failure: 0,\r\n tool_error: 0,\r\n unknown: 0,\r\n };\r\n\r\n for (const counts of allCounts) {\r\n merged.timeout += counts.timeout;\r\n merged.runtime_error += counts.runtime_error;\r\n merged.validation_failure += counts.validation_failure;\r\n merged.tool_error += counts.tool_error;\r\n merged.unknown += counts.unknown;\r\n }\r\n\r\n return merged;\r\n}\r\n\r\nfunction calculateTokenEfficiency(\r\n trials: TrialResult[]\r\n): TokenEfficiency | undefined {\r\n const successfulTrials = trials.filter(\r\n (t) => t.execution.success && t.output.valid\r\n );\r\n if (successfulTrials.length === 0) return undefined;\r\n\r\n return {\r\n inputPerSuccess:\r\n successfulTrials.reduce((sum, t) => sum + t.usage.inputTokens, 0) /\r\n successfulTrials.length,\r\n outputPerSuccess:\r\n successfulTrials.reduce((sum, t) => sum + t.usage.outputTokens, 0) /\r\n successfulTrials.length,\r\n totalPerSuccess:\r\n successfulTrials.reduce((sum, t) => sum + t.usage.totalTokens, 0) /\r\n successfulTrials.length,\r\n };\r\n}\r\n\r\nfunction averageTokenEfficiency(\r\n efficiencies: (TokenEfficiency | undefined)[]\r\n): TokenEfficiency | undefined {\r\n const valid = efficiencies.filter((e): e is TokenEfficiency => e !== undefined);\r\n if (valid.length === 0) return undefined;\r\n\r\n return {\r\n inputPerSuccess:\r\n valid.reduce((sum, e) => sum + e.inputPerSuccess, 0) / valid.length,\r\n outputPerSuccess:\r\n valid.reduce((sum, e) => sum + e.outputPerSuccess, 0) / valid.length,\r\n totalPerSuccess:\r\n valid.reduce((sum, e) => sum + e.totalPerSuccess, 0) / valid.length,\r\n };\r\n}\r\n\r\nfunction aggregateGoalMetrics(trials: TrialResult[]): GoalMetrics | undefined {\r\n const trialsWithGoals = trials.filter((t) => t.goals && t.goals.tracked.length > 0);\r\n if (trialsWithGoals.length === 0) {\r\n return undefined;\r\n }\r\n\r\n const allMetrics = trialsWithGoals.map((t) => t.goals!.metrics);\r\n\r\n const totalGoals = allMetrics.reduce((sum, m) => sum + m.totalGoals, 0);\r\n const completedGoals = allMetrics.reduce((sum, m) => sum + m.completedGoals, 0);\r\n const failedGoals = allMetrics.reduce((sum, m) => sum + m.failedGoals, 0);\r\n const abandonedGoals = allMetrics.reduce((sum, m) => sum + m.abandonedGoals, 0);\r\n\r\n const avgGoalCompletionRate =\r\n allMetrics.reduce((sum, m) => sum + m.goalCompletionRate, 0) / allMetrics.length;\r\n const avgAttemptsPerGoal =\r\n allMetrics.reduce((sum, m) => sum + m.avgAttemptsPerGoal, 0) / allMetrics.length;\r\n const avgToolCallSuccessRate =\r\n allMetrics.reduce((sum, m) => sum + m.toolCallSuccessRate, 0) / allMetrics.length;\r\n const avgToolCallFailureRate =\r\n allMetrics.reduce((sum, m) => sum + (m.toolCallFailureRate ?? (1 - m.toolCallSuccessRate)), 0) / allMetrics.length;\r\n const avgRecoveryRate =\r\n allMetrics.reduce((sum, m) => sum + m.recoveryRate, 0) / allMetrics.length;\r\n\r\n return {\r\n totalGoals,\r\n completedGoals,\r\n failedGoals,\r\n abandonedGoals,\r\n goalCompletionRate: avgGoalCompletionRate,\r\n avgAttemptsPerGoal,\r\n toolCallSuccessRate: avgToolCallSuccessRate,\r\n toolCallFailureRate: avgToolCallFailureRate,\r\n recoveryRate: avgRecoveryRate,\r\n };\r\n}\r\n\r\n// ============ Scenario Metrics ============\r\n\r\nfunction calculateScenarioMetrics(\r\n trials: TrialResult[],\r\n scenarioId: string,\r\n scenarioName: string,\r\n agentPath: string,\r\n model: string,\r\n runs: number,\r\n difficulty?: 'easy' | 'medium' | 'hard'\r\n): ScenarioResult {\r\n const successfulTrials = trials.filter(\r\n (t) => t.execution.success && t.output.valid\r\n );\r\n const completionRate = trials.length > 0 ? successfulTrials.length / trials.length : 0;\r\n const passK = calculatePassK(trials, runs);\r\n\r\n // Consistency: low variance = high consistency\r\n const outcomes = trials.map((t) =>\r\n t.execution.success && t.output.valid ? 1 : 0\r\n );\r\n const consistency = 1 - calculateStats(outcomes).stdDev;\r\n\r\n // Latency stats\r\n const latencies = trials.map((t) => t.execution.durationMs);\r\n const latencyStats = calculateStats(latencies);\r\n\r\n // Cost stats - filter out undefined costs\r\n const validCosts = trials\r\n .map((t) => t.usage.estimatedCostUsd)\r\n .filter((c): c is number => c !== undefined);\r\n const validSuccessCosts = successfulTrials\r\n .map((t) => t.usage.estimatedCostUsd)\r\n .filter((c): c is number => c !== undefined);\r\n const costPerSuccess =\r\n validSuccessCosts.length > 0\r\n ? validSuccessCosts.reduce((sum, c) => sum + c, 0) / validSuccessCosts.length\r\n : undefined;\r\n\r\n // Tool call stats (from successful trials only)\r\n const toolCounts = successfulTrials.map((t) => t.toolCalls.total);\r\n const uniqueTools = [...new Set(trials.flatMap((t) => t.toolCalls.names))];\r\n const allTraces = trials.flatMap((t) => t.toolCalls.traces);\r\n const perToolMetrics = aggregateToolMetrics(allTraces);\r\n\r\n // Goal metrics\r\n const goalMetrics = aggregateGoalMetrics(trials);\r\n\r\n // Token efficiency and errors\r\n const tokenEfficiency = calculateTokenEfficiency(trials);\r\n const errorCounts = aggregateErrorCounts(trials);\r\n\r\n return {\r\n scenarioId,\r\n scenarioName,\r\n agentPath,\r\n model,\r\n ...(difficulty && { difficulty }),\r\n trials,\r\n metrics: {\r\n completionRate,\r\n passK,\r\n consistency,\r\n // efficiency is calculated later in cross-model comparison\r\n latency: {\r\n meanMs: latencyStats.mean,\r\n medianMs: latencyStats.median,\r\n p95Ms: latencyStats.p95,\r\n stdDevMs: latencyStats.stdDev,\r\n },\r\n cost: {\r\n ...(validCosts.length > 0 && {\r\n meanUsd: validCosts.reduce((a, b) => a + b, 0) / validCosts.length,\r\n totalUsd: validCosts.reduce((a, b) => a + b, 0),\r\n }),\r\n ...(costPerSuccess !== undefined && { perSuccessUsd: costPerSuccess }),\r\n },\r\n toolCalls: {\r\n meanCount: toolCounts.length > 0 ? toolCounts.reduce((a, b) => a + b, 0) / toolCounts.length : 0,\r\n uniqueTools,\r\n perToolMetrics,\r\n },\r\n ...(tokenEfficiency && { tokenEfficiency }),\r\n errorCounts,\r\n ...(goalMetrics && { goals: goalMetrics }),\r\n },\r\n };\r\n}\r\n\r\n// ============ Relative Efficiency ============\r\n\r\nfunction calculateRelativeEfficiency(\r\n modelResults: SuiteResult['modelResults']\r\n): void {\r\n // Collect all scenario results grouped by scenarioId\r\n const scenariosByModel: Map<\r\n string,\r\n Array<{ model: string; agentIdx: number; scenarioIdx: number; meanToolCalls: number }>\r\n > = new Map();\r\n\r\n for (const [model, result] of Object.entries(modelResults)) {\r\n for (let agentIdx = 0; agentIdx < result.agents.length; agentIdx++) {\r\n const agent = result.agents[agentIdx];\r\n for (let scenarioIdx = 0; scenarioIdx < agent.scenarios.length; scenarioIdx++) {\r\n const scenario = agent.scenarios[scenarioIdx];\r\n const scenarioId = scenario.scenarioId;\r\n\r\n const successfulTrials = scenario.trials.filter(\r\n (t) => t.execution.success && t.output.valid\r\n );\r\n const meanToolCalls =\r\n successfulTrials.length > 0\r\n ? successfulTrials.reduce((sum, t) => sum + t.toolCalls.total, 0) /\r\n successfulTrials.length\r\n : 0;\r\n\r\n if (!scenariosByModel.has(scenarioId)) {\r\n scenariosByModel.set(scenarioId, []);\r\n }\r\n scenariosByModel.get(scenarioId)!.push({\r\n model,\r\n agentIdx,\r\n scenarioIdx,\r\n meanToolCalls,\r\n });\r\n }\r\n }\r\n }\r\n\r\n // Calculate tool call efficiency per scenario\r\n for (const [, entries] of scenariosByModel) {\r\n const successfulEntries = entries.filter((e) => e.meanToolCalls > 0);\r\n if (successfulEntries.length === 0) continue;\r\n\r\n const minToolCalls = Math.min(...successfulEntries.map((e) => e.meanToolCalls));\r\n\r\n for (const entry of entries) {\r\n const efficiency =\r\n entry.meanToolCalls > 0 ? minToolCalls / entry.meanToolCalls : 0;\r\n\r\n const agent = modelResults[entry.model].agents[entry.agentIdx];\r\n const scenario = agent.scenarios[entry.scenarioIdx];\r\n scenario.metrics.efficiency = efficiency;\r\n }\r\n }\r\n\r\n // Calculate scenario-level goal toolCallEfficiency\r\n const scenarioGoalsByModel: Map<\r\n string,\r\n Array<{ model: string; agentIdx: number; scenarioIdx: number; avgAttemptsPerGoal: number }>\r\n > = new Map();\r\n\r\n for (const [model, result] of Object.entries(modelResults)) {\r\n for (let agentIdx = 0; agentIdx < result.agents.length; agentIdx++) {\r\n const agent = result.agents[agentIdx];\r\n for (let scenarioIdx = 0; scenarioIdx < agent.scenarios.length; scenarioIdx++) {\r\n const scenario = agent.scenarios[scenarioIdx];\r\n const goals = scenario.metrics.goals;\r\n if (!goals || goals.avgAttemptsPerGoal <= 0) continue;\r\n\r\n const scenarioId = scenario.scenarioId;\r\n if (!scenarioGoalsByModel.has(scenarioId)) {\r\n scenarioGoalsByModel.set(scenarioId, []);\r\n }\r\n scenarioGoalsByModel.get(scenarioId)!.push({\r\n model,\r\n agentIdx,\r\n scenarioIdx,\r\n avgAttemptsPerGoal: goals.avgAttemptsPerGoal,\r\n });\r\n }\r\n }\r\n }\r\n\r\n for (const [, entries] of scenarioGoalsByModel) {\r\n if (entries.length === 0) continue;\r\n\r\n const minAttempts = Math.min(...entries.map((e) => e.avgAttemptsPerGoal));\r\n\r\n for (const entry of entries) {\r\n const goalEfficiency = minAttempts / entry.avgAttemptsPerGoal;\r\n\r\n const agent = modelResults[entry.model].agents[entry.agentIdx];\r\n const scenario = agent.scenarios[entry.scenarioIdx];\r\n if (scenario.metrics.goals) {\r\n scenario.metrics.goals.toolCallEfficiency = goalEfficiency;\r\n }\r\n }\r\n }\r\n\r\n // Recalculate agent-level and model-level efficiency aggregates\r\n for (const [_model, result] of Object.entries(modelResults)) {\r\n for (const agent of result.agents) {\r\n const scenarioEfficiencies = agent.scenarios\r\n .map((s) => s.metrics.efficiency ?? 0);\r\n agent.aggregate.efficiency =\r\n scenarioEfficiencies.length > 0\r\n ? scenarioEfficiencies.reduce((a, b) => a + b, 0) / scenarioEfficiencies.length\r\n : 0;\r\n\r\n // Calculate agent-level weighted score\r\n const agentScenarioData = agent.scenarios.map(s => ({\r\n passK: s.metrics.passK,\r\n efficiency: s.metrics.efficiency ?? 0,\r\n toolSuccessRate: s.metrics.goals?.toolCallSuccessRate ?? 1,\r\n difficulty: s.difficulty,\r\n }));\r\n const agentWeightedScore = calculateWeightedScore(agentScenarioData);\r\n if (agentWeightedScore !== undefined) {\r\n agent.aggregate.weightedScore = agentWeightedScore;\r\n }\r\n }\r\n\r\n const agentEfficiencies = result.agents.map((a) => a.aggregate.efficiency);\r\n result.aggregate.efficiency =\r\n agentEfficiencies.length > 0\r\n ? agentEfficiencies.reduce((a, b) => a + b, 0) / agentEfficiencies.length\r\n : 0;\r\n\r\n // Recalculate overall score\r\n // Formula: passK x 50 + efficiency x 30 + toolSuccessRate x 20\r\n const toolSuccessRate = result.aggregate.goals?.toolCallSuccessRate ?? 1;\r\n result.aggregate.overallScore =\r\n result.aggregate.passK * 50 +\r\n result.aggregate.efficiency * 30 +\r\n toolSuccessRate * 20;\r\n\r\n // Calculate model-level weighted score from all scenarios\r\n const allScenarioData = result.agents.flatMap(a =>\r\n a.scenarios.map(s => ({\r\n passK: s.metrics.passK,\r\n efficiency: s.metrics.efficiency ?? 0,\r\n toolSuccessRate: s.metrics.goals?.toolCallSuccessRate ?? 1,\r\n difficulty: s.difficulty,\r\n }))\r\n );\r\n const modelWeightedScore = calculateWeightedScore(allScenarioData);\r\n if (modelWeightedScore !== undefined) {\r\n result.aggregate.weightedScore = modelWeightedScore;\r\n }\r\n }\r\n\r\n // Calculate model-level goal toolCallEfficiency\r\n const modelsWithGoals = Object.entries(modelResults)\r\n .filter(([, result]) => result.aggregate.goals && result.aggregate.goals.avgAttemptsPerGoal > 0)\r\n .map(([model, result]) => ({\r\n model,\r\n avgAttemptsPerGoal: result.aggregate.goals!.avgAttemptsPerGoal,\r\n }));\r\n\r\n if (modelsWithGoals.length > 0) {\r\n const minAttempts = Math.min(...modelsWithGoals.map((m) => m.avgAttemptsPerGoal));\r\n\r\n for (const { model, avgAttemptsPerGoal } of modelsWithGoals) {\r\n const goalEfficiency = minAttempts / avgAttemptsPerGoal;\r\n if (modelResults[model].aggregate.goals) {\r\n modelResults[model].aggregate.goals.toolCallEfficiency = goalEfficiency;\r\n }\r\n }\r\n }\r\n}\r\n\r\n// ============ Main Calculator ============\r\n\r\n/**\r\n * Calculate all metrics from raw benchmark data\r\n * This is the main entry point for computing SuiteResult from RawBenchmarkResult\r\n */\r\nexport function calculateMetrics(raw: RawBenchmarkResult): SuiteResult {\r\n const { suiteId, suiteName, runId, timestamp, durationMs, config, trials } = raw;\r\n // Support legacy 'k' field for backward compatibility with older JSON files\r\n const runs = config.runs ?? (config as { k?: number }).k ?? 1;\r\n\r\n // Recalculate costs using current model registry pricing\r\n // This ensures pricing updates are reflected when viewing old results\r\n for (const entry of trials) {\r\n const { inputTokens, outputTokens } = entry.trial.usage;\r\n const cost = calculateCost(entry.model, inputTokens, outputTokens);\r\n if (cost !== undefined) {\r\n entry.trial.usage.estimatedCostUsd = cost;\r\n }\r\n }\r\n\r\n // Group trials by model -> agent -> scenario\r\n const modelMap = new Map<string, Map<string, Map<string, RawTrialEntry[]>>>();\r\n\r\n for (const entry of trials) {\r\n if (!modelMap.has(entry.model)) {\r\n modelMap.set(entry.model, new Map());\r\n }\r\n const agentMap = modelMap.get(entry.model)!;\r\n\r\n if (!agentMap.has(entry.agentPath)) {\r\n agentMap.set(entry.agentPath, new Map());\r\n }\r\n const scenarioMap = agentMap.get(entry.agentPath)!;\r\n\r\n if (!scenarioMap.has(entry.scenarioId)) {\r\n scenarioMap.set(entry.scenarioId, []);\r\n }\r\n scenarioMap.get(entry.scenarioId)!.push(entry);\r\n }\r\n\r\n // Build model results\r\n const modelResults: SuiteResult['modelResults'] = {};\r\n\r\n for (const [model, agentMap] of modelMap) {\r\n const agents: AgentResult[] = [];\r\n\r\n for (const [agentPath, scenarioMap] of agentMap) {\r\n const scenarios: ScenarioResult[] = [];\r\n let agentName = '';\r\n\r\n for (const [scenarioId, entries] of scenarioMap) {\r\n const firstEntry = entries[0];\r\n agentName = firstEntry.agentName;\r\n\r\n const trialResults = entries.map((e) => e.trial);\r\n const scenarioResult = calculateScenarioMetrics(\r\n trialResults,\r\n scenarioId,\r\n firstEntry.scenarioName,\r\n agentPath,\r\n model,\r\n runs,\r\n firstEntry.difficulty\r\n );\r\n scenarios.push(scenarioResult);\r\n }\r\n\r\n // Calculate agent aggregate\r\n const completionRates = scenarios.map((s) => s.metrics.completionRate);\r\n const passKs = scenarios.map((s) => s.metrics.passK);\r\n const consistencies = scenarios.map((s) => s.metrics.consistency);\r\n const latencies = scenarios.map((s) => s.metrics.latency.meanMs);\r\n const validCosts = scenarios\r\n .map((s) => s.metrics.cost.totalUsd)\r\n .filter((c): c is number => c !== undefined);\r\n\r\n const allTrials = scenarios.flatMap((s) => s.trials);\r\n const successfulTrials = allTrials.filter(\r\n (t) => t.execution.success && t.output.valid\r\n );\r\n const toolCounts = successfulTrials.map((t) => t.toolCalls.total);\r\n\r\n const agentGoalMetrics = aggregateGoalMetrics(allTrials);\r\n const agentTokenEfficiency = averageTokenEfficiency(\r\n scenarios.map((s) => s.metrics.tokenEfficiency)\r\n );\r\n const agentErrorCounts = mergeErrorCounts(\r\n scenarios.map((s) => s.metrics.errorCounts).filter((e): e is ErrorCounts => e !== undefined)\r\n );\r\n const validSuccessCosts = successfulTrials\r\n .map((t) => t.usage.estimatedCostUsd)\r\n .filter((c): c is number => c !== undefined);\r\n const agentCostPerSuccess =\r\n validSuccessCosts.length > 0\r\n ? validSuccessCosts.reduce((sum, c) => sum + c, 0) / validSuccessCosts.length\r\n : undefined;\r\n\r\n agents.push({\r\n agentPath,\r\n agentName,\r\n model,\r\n scenarios,\r\n aggregate: {\r\n completionRate: completionRates.reduce((a, b) => a + b, 0) / completionRates.length,\r\n passK: passKs.reduce((a, b) => a + b, 0) / passKs.length,\r\n consistency: consistencies.reduce((a, b) => a + b, 0) / consistencies.length,\r\n efficiency: 0, // Calculated later\r\n meanToolCalls: toolCounts.length > 0 ? toolCounts.reduce((a, b) => a + b, 0) / toolCounts.length : 0,\r\n latencyMeanMs: latencies.reduce((a, b) => a + b, 0) / latencies.length,\r\n ...(validCosts.length > 0 && { totalCostUsd: validCosts.reduce((a, b) => a + b, 0) }),\r\n ...(agentCostPerSuccess !== undefined && { costPerSuccessUsd: agentCostPerSuccess }),\r\n ...(agentTokenEfficiency && { tokenEfficiency: agentTokenEfficiency }),\r\n errorCounts: agentErrorCounts,\r\n ...(agentGoalMetrics && { goals: agentGoalMetrics }),\r\n },\r\n });\r\n }\r\n\r\n // Calculate model aggregate\r\n const completionRates = agents.map((a) => a.aggregate.completionRate);\r\n const passKs = agents.map((a) => a.aggregate.passK);\r\n const consistencies = agents.map((a) => a.aggregate.consistency);\r\n const toolCalls = agents.map((a) => a.aggregate.meanToolCalls);\r\n const latencies = agents.map((a) => a.aggregate.latencyMeanMs);\r\n const validCosts = agents\r\n .map((a) => a.aggregate.totalCostUsd)\r\n .filter((c): c is number => c !== undefined);\r\n\r\n const avgCompletionRate = completionRates.reduce((a, b) => a + b, 0) / completionRates.length;\r\n const avgPassK = passKs.reduce((a, b) => a + b, 0) / passKs.length;\r\n const avgConsistency = consistencies.reduce((a, b) => a + b, 0) / consistencies.length;\r\n const avgMeanToolCalls = toolCalls.reduce((a, b) => a + b, 0) / toolCalls.length;\r\n\r\n const allModelTrials = agents.flatMap((a) => a.scenarios.flatMap((s) => s.trials));\r\n const modelGoalMetrics = aggregateGoalMetrics(allModelTrials);\r\n const modelTokenEfficiency = averageTokenEfficiency(\r\n agents.map((a) => a.aggregate.tokenEfficiency)\r\n );\r\n const modelErrorCounts = mergeErrorCounts(\r\n agents.map((a) => a.aggregate.errorCounts).filter((e): e is ErrorCounts => e !== undefined)\r\n );\r\n\r\n const successfulTrials = allModelTrials.filter(\r\n (t) => t.execution.success && t.output.valid\r\n );\r\n const validSuccessCosts = successfulTrials\r\n .map((t) => t.usage.estimatedCostUsd)\r\n .filter((c): c is number => c !== undefined);\r\n const modelCostPerSuccess =\r\n validSuccessCosts.length > 0\r\n ? validSuccessCosts.reduce((sum, c) => sum + c, 0) / validSuccessCosts.length\r\n : undefined;\r\n\r\n // Initial overall score (will be recalculated after efficiency and toolSuccessRate)\r\n const overallScore = avgPassK * 50; // efficiency and toolSuccessRate added later\r\n\r\n modelResults[model] = {\r\n agents,\r\n aggregate: {\r\n completionRate: avgCompletionRate,\r\n passK: avgPassK,\r\n consistency: avgConsistency,\r\n efficiency: 0, // Calculated later\r\n meanToolCalls: avgMeanToolCalls,\r\n latencyMeanMs: latencies.reduce((a, b) => a + b, 0) / latencies.length,\r\n ...(validCosts.length > 0 && { totalCostUsd: validCosts.reduce((a, b) => a + b, 0) }),\r\n ...(modelCostPerSuccess !== undefined && { costPerSuccessUsd: modelCostPerSuccess }),\r\n ...(modelTokenEfficiency && { tokenEfficiency: modelTokenEfficiency }),\r\n errorCounts: modelErrorCounts,\r\n overallScore,\r\n ...(modelGoalMetrics && { goals: modelGoalMetrics }),\r\n },\r\n };\r\n }\r\n\r\n // Calculate relative efficiency across all models\r\n calculateRelativeEfficiency(modelResults);\r\n\r\n // Build ranking\r\n const ranking = Object.entries(modelResults)\r\n .map(([model, result]) => ({\r\n model,\r\n score: result.aggregate.overallScore,\r\n ...(result.aggregate.weightedScore !== undefined && {\r\n weightedScore: result.aggregate.weightedScore,\r\n }),\r\n completionRate: result.aggregate.completionRate,\r\n passK: result.aggregate.passK,\r\n consistency: result.aggregate.consistency,\r\n efficiency: result.aggregate.efficiency,\r\n meanToolCalls: result.aggregate.meanToolCalls,\r\n ...(result.aggregate.totalCostUsd !== undefined && {\r\n costUsd: result.aggregate.totalCostUsd,\r\n }),\r\n ...(result.aggregate.costPerSuccessUsd !== undefined && {\r\n costPerSuccessUsd: result.aggregate.costPerSuccessUsd,\r\n }),\r\n ...(result.aggregate.goals && {\r\n goals: {\r\n completionRate: result.aggregate.goals.goalCompletionRate,\r\n avgAttempts: result.aggregate.goals.avgAttemptsPerGoal,\r\n toolCallSuccessRate: result.aggregate.goals.toolCallSuccessRate,\r\n toolCallFailureRate: result.aggregate.goals.toolCallFailureRate,\r\n ...(result.aggregate.goals.toolCallEfficiency !== undefined && {\r\n toolCallEfficiency: result.aggregate.goals.toolCallEfficiency,\r\n }),\r\n recoveryRate: result.aggregate.goals.recoveryRate,\r\n },\r\n }),\r\n }))\r\n // Sort by weighted score if available, otherwise by regular score\r\n .sort((a, b) => (b.weightedScore ?? b.score) - (a.weightedScore ?? a.score))\r\n .map((entry, index) => ({\r\n ...entry,\r\n rank: index + 1,\r\n }));\r\n\r\n const totalScenarios = Object.values(modelResults).reduce(\r\n (sum, mr) => sum + mr.agents.reduce((s, a) => s + a.scenarios.length, 0),\r\n 0\r\n ) / config.models.length;\r\n\r\n return {\r\n suiteId,\r\n suiteName,\r\n runId,\r\n timestamp,\r\n durationMs,\r\n config: {\r\n models: config.models,\r\n runs,\r\n totalScenarios,\r\n totalTrials: trials.length,\r\n },\r\n modelResults,\r\n ranking,\r\n };\r\n}\r\n\r\n/**\r\n * Extract raw data from a SuiteResult for storage\r\n * This is the inverse of calculateMetrics\r\n */\r\nexport function extractRawData(result: SuiteResult): RawBenchmarkResult {\r\n const trials: RawTrialEntry[] = [];\r\n\r\n for (const [model, mr] of Object.entries(result.modelResults)) {\r\n for (const agent of mr.agents) {\r\n for (const scenario of agent.scenarios) {\r\n for (const trial of scenario.trials) {\r\n trials.push({\r\n model,\r\n agentPath: agent.agentPath,\r\n agentName: agent.agentName,\r\n scenarioId: scenario.scenarioId,\r\n scenarioName: scenario.scenarioName,\r\n ...(scenario.difficulty && { difficulty: scenario.difficulty }),\r\n trial,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n version: 2,\r\n suiteId: result.suiteId,\r\n suiteName: result.suiteName,\r\n runId: result.runId,\r\n timestamp: result.timestamp,\r\n durationMs: result.durationMs,\r\n config: {\r\n models: result.config.models,\r\n runs: result.config.runs,\r\n },\r\n trials,\r\n };\r\n}\r\n",
|
|
101
|
+
"import { writeFile, mkdir } from 'fs/promises';\r\nimport { join } from 'path';\r\nimport type { SuiteResult } from '../types.js';\r\nimport {\r\n generateReportData,\r\n formatDuration,\r\n formatCost,\r\n formatPercent,\r\n formatTokens,\r\n GLOSSARY_ITEMS,\r\n} from './shared.js';\r\n\r\n/**\r\n * Generate Markdown report from suite results\r\n */\r\nexport function generateMarkdownReport(result: SuiteResult): string {\r\n const data = generateReportData(result);\r\n const lines: string[] = [];\r\n const showConsistency = data.runs > 1; // Hide consistency when runs=1 (always 100%)\r\n\r\n // Check if any model has goals\r\n const hasGoals = data.models.some((m) => m.goals);\r\n // Check if weighted scores are available (must be non-null number)\r\n const hasWeightedScores = data.models.some((m) => m.scores.weighted != null);\r\n\r\n // Header\r\n lines.push(`# ${data.summary.suiteName}`);\r\n lines.push('');\r\n lines.push(`**Run ID:** \\`${data.summary.runId}\\``);\r\n lines.push(`**Date:** ${new Date(data.generatedAt).toISOString()}`);\r\n lines.push(`**Duration:** ${formatDuration(data.summary.runDurationMs)}`);\r\n lines.push('');\r\n\r\n // Summary\r\n lines.push('## Summary');\r\n lines.push('');\r\n lines.push('| Metric | Value |');\r\n lines.push('|--------|-------|');\r\n lines.push(`| Models | ${data.summary.totalModels} |`);\r\n lines.push(`| Scenarios | ${data.summary.totalScenarios} |`);\r\n lines.push(`| Trials | ${data.summary.totalTrials} |`);\r\n lines.push(`| Total Cost | ${formatCost(data.summary.totalCostUsd)} |`);\r\n lines.push('');\r\n\r\n // Model Ranking\r\n lines.push('## Model Ranking');\r\n lines.push('');\r\n\r\n // Build header dynamically based on available metrics\r\n if (hasGoals) {\r\n const headers = ['Rank', 'Model', 'Score'];\r\n if (hasWeightedScores) headers.push('Unweighted');\r\n headers.push('Pass^k', 'Efficiency', 'Tools/Goal', 'Tool Failure', 'Tool Efficiency', 'P95 Latency', 'Avg Cost');\r\n lines.push(`| ${headers.join(' | ')} |`);\r\n lines.push(`|${headers.map(() => '------').join('|')}|`);\r\n } else {\r\n const headers = ['Rank', 'Model', 'Score'];\r\n if (hasWeightedScores) headers.push('Unweighted');\r\n headers.push('Completion', 'Pass^k');\r\n if (showConsistency) headers.push('Consistency');\r\n headers.push('P95 Latency', 'Avg Cost');\r\n lines.push(`| ${headers.join(' | ')} |`);\r\n lines.push(`|${headers.map(() => '------').join('|')}|`);\r\n }\r\n\r\n for (const entry of data.ranking) {\r\n const model = data.models.find((m) => m.id === entry.model);\r\n if (!model) continue;\r\n\r\n // When weighted scores exist: Score = weighted (bold), Unweighted = raw\r\n // When no weighted scores: Score = raw (bold)\r\n const primaryScore = entry.weighted != null ? entry.weighted : entry.score;\r\n const scoreStr = `**${primaryScore.toFixed(1)}**`;\r\n const unweightedStr = hasWeightedScores ? (entry.score?.toFixed(1) ?? '-') : '';\r\n\r\n if (hasGoals) {\r\n const failureRate = model.goals?.toolCallFailureRate;\r\n const failureRateStr = failureRate != null && !isNaN(failureRate) ? formatPercent(failureRate) : '-';\r\n const toolEfficiency = model.goals?.toolCallEfficiency;\r\n const toolEfficiencyStr = toolEfficiency != null && !isNaN(toolEfficiency) ? formatPercent(toolEfficiency) : '-';\r\n\r\n const cells = [\r\n entry.rank.toString(),\r\n model.name,\r\n scoreStr,\r\n ];\r\n if (hasWeightedScores) cells.push(unweightedStr);\r\n cells.push(\r\n formatPercent(model.scores.passK),\r\n formatPercent(model.scores.efficiency),\r\n model.goals ? model.goals.avgAttempts.toFixed(1) : '-',\r\n failureRateStr,\r\n toolEfficiencyStr,\r\n formatDuration(model.latency.p95Ms),\r\n formatCost(model.cost.perFullRun)\r\n );\r\n lines.push(`| ${cells.join(' | ')} |`);\r\n } else {\r\n const cells = [\r\n entry.rank.toString(),\r\n model.name,\r\n scoreStr,\r\n ];\r\n if (hasWeightedScores) cells.push(unweightedStr);\r\n cells.push(\r\n formatPercent(model.scores.completion),\r\n formatPercent(model.scores.passK)\r\n );\r\n if (showConsistency) cells.push(formatPercent(model.scores.consistency));\r\n cells.push(\r\n formatDuration(model.latency.p95Ms),\r\n formatCost(model.cost.perFullRun)\r\n );\r\n lines.push(`| ${cells.join(' | ')} |`);\r\n }\r\n }\r\n lines.push('');\r\n\r\n // Model Details\r\n lines.push('## Model Details');\r\n lines.push('');\r\n\r\n for (const model of data.models) {\r\n lines.push(`### ${model.name}`);\r\n lines.push('');\r\n lines.push(`*Provider: ${model.provider}*`);\r\n lines.push('');\r\n\r\n // Primary score (weighted if exists)\r\n const primaryScore = model.scores.weighted != null ? model.scores.weighted : model.scores.overall;\r\n lines.push(`- **Score:** ${primaryScore.toFixed(1)}`);\r\n if (model.scores.weighted != null) {\r\n lines.push(`- **Unweighted Score:** ${model.scores.overall.toFixed(1)}`);\r\n }\r\n lines.push(`- **Completion:** ${formatPercent(model.scores.completion)}`);\r\n lines.push(`- **Pass^k:** ${formatPercent(model.scores.passK)}`);\r\n if (showConsistency) {\r\n lines.push(`- **Consistency:** ${formatPercent(model.scores.consistency)}`);\r\n }\r\n lines.push(`- **Efficiency:** ${formatPercent(model.scores.efficiency)}`);\r\n lines.push(`- **Mean Latency:** ${formatDuration(model.latency.meanMs)}`);\r\n lines.push(`- **P95 Latency:** ${formatDuration(model.latency.p95Ms)}`);\r\n lines.push(`- **Avg Cost:** ${formatCost(model.cost.perFullRun)}`);\r\n if (model.cost.perSuccess !== undefined) {\r\n lines.push(`- **Cost/Success:** ${formatCost(model.cost.perSuccess)}`);\r\n }\r\n\r\n // Goals metrics\r\n if (model.goals) {\r\n lines.push('');\r\n lines.push('#### Goal Metrics');\r\n lines.push('');\r\n lines.push('| Metric | Value |');\r\n lines.push('|--------|-------|');\r\n lines.push(`| Goal Completion | ${formatPercent(model.goals.completionRate)} |`);\r\n lines.push(`| Tools/Goal | ${model.goals.avgAttempts.toFixed(1)} |`);\r\n lines.push(`| Tool Failure Rate | ${formatPercent(model.goals.toolCallFailureRate)} |`);\r\n if (model.goals.toolCallEfficiency !== undefined) {\r\n lines.push(`| Tool Efficiency | ${formatPercent(model.goals.toolCallEfficiency)} |`);\r\n }\r\n }\r\n\r\n // Errors\r\n if (model.errors) {\r\n const totalErrors = Object.values(model.errors).reduce((sum, v) => sum + v, 0);\r\n if (totalErrors > 0) {\r\n lines.push('');\r\n lines.push('#### Errors');\r\n lines.push('');\r\n lines.push('| Type | Count |');\r\n lines.push('|------|-------|');\r\n if (model.errors.timeout) lines.push(`| Timeout | ${model.errors.timeout} |`);\r\n if (model.errors.runtime_error) lines.push(`| Runtime | ${model.errors.runtime_error} |`);\r\n if (model.errors.validation_failure) lines.push(`| Validation | ${model.errors.validation_failure} |`);\r\n if (model.errors.tool_error) lines.push(`| Tool | ${model.errors.tool_error} |`);\r\n if (model.errors.unknown) lines.push(`| Unknown | ${model.errors.unknown} |`);\r\n\r\n // Error details\r\n if (model.errorDetails && model.errorDetails.length > 0) {\r\n lines.push('');\r\n lines.push('**Error Details:**');\r\n lines.push('');\r\n for (const err of model.errorDetails.slice(0, 10)) {\r\n lines.push(`- **${err.scenario}** #${err.trial}: \\`${err.type}\\` - ${err.message}`);\r\n }\r\n if (model.errorDetails.length > 10) {\r\n lines.push(`- ... and ${model.errorDetails.length - 10} more errors`);\r\n }\r\n }\r\n }\r\n }\r\n lines.push('');\r\n }\r\n\r\n // Scenarios Breakdown\r\n lines.push('## Scenarios Breakdown');\r\n lines.push('');\r\n\r\n // Build scenario headers\r\n if (hasGoals) {\r\n const headers = ['Scenario', 'Model', 'Status', 'Goals', 'Tools/Goal', 'Tool Failure', 'Tool Efficiency', 'Recovery', 'In Tokens', 'Out Tokens', 'Latency', 'Avg Cost'];\r\n lines.push(`| ${headers.join(' | ')} |`);\r\n lines.push(`|${headers.map(() => '------').join('|')}|`);\r\n } else {\r\n const headers = ['Scenario', 'Model', 'Status', 'Completion', 'Pass^k'];\r\n if (showConsistency) headers.push('Consistency');\r\n headers.push('In Tokens', 'Out Tokens', 'Latency', 'Avg Cost');\r\n lines.push(`| ${headers.join(' | ')} |`);\r\n lines.push(`|${headers.map(() => '------').join('|')}|`);\r\n }\r\n\r\n for (const scenario of data.scenarios) {\r\n const difficultyBadge = scenario.difficulty ? ` [${scenario.difficulty}]` : '';\r\n\r\n for (const model of data.models) {\r\n const r = scenario.results[model.id];\r\n if (!r) continue;\r\n\r\n // Status\r\n const status = r.completionRate === 1 ? 'pass' : r.completionRate > 0 ? 'partial' : 'fail';\r\n\r\n if (hasGoals && r.goals) {\r\n const failureRate = r.goals.toolCallFailureRate;\r\n const failureRateStr = failureRate != null && !isNaN(failureRate) ? formatPercent(failureRate) : '-';\r\n const efficiencyStr = r.goals.toolCallEfficiency != null && !isNaN(r.goals.toolCallEfficiency) ? formatPercent(r.goals.toolCallEfficiency) : '-';\r\n\r\n lines.push(`| ${scenario.name}${difficultyBadge} | ${model.name} | ${status} | ${r.goals.completed}/${r.goals.total} | ${r.goals.avgAttempts.toFixed(1)} | ${failureRateStr} | ${efficiencyStr} | ${formatPercent(r.goals.recoveryRate)} | ${formatTokens(r.inputTokens)} | ${formatTokens(r.outputTokens)} | ${formatDuration(r.latencyMs)} | ${formatCost(r.costUsd)} |`);\r\n } else if (hasGoals) {\r\n lines.push(`| ${scenario.name}${difficultyBadge} | ${model.name} | ${status} | - | - | - | - | - | ${formatTokens(r.inputTokens)} | ${formatTokens(r.outputTokens)} | ${formatDuration(r.latencyMs)} | ${formatCost(r.costUsd)} |`);\r\n } else {\r\n const cells = [\r\n scenario.name + difficultyBadge,\r\n model.name,\r\n status,\r\n formatPercent(r.completionRate),\r\n formatPercent(r.passK),\r\n ];\r\n if (showConsistency) cells.push(formatPercent(r.consistency));\r\n cells.push(\r\n formatTokens(r.inputTokens),\r\n formatTokens(r.outputTokens),\r\n formatDuration(r.latencyMs),\r\n formatCost(r.costUsd)\r\n );\r\n lines.push(`| ${cells.join(' | ')} |`);\r\n }\r\n }\r\n }\r\n lines.push('');\r\n\r\n // Glossary\r\n lines.push('## Glossary');\r\n lines.push('');\r\n lines.push('| Term | Definition |');\r\n lines.push('|------|------------|');\r\n for (const item of GLOSSARY_ITEMS) {\r\n lines.push(`| **${item.term}** | ${item.definition} |`);\r\n }\r\n lines.push('');\r\n\r\n // Footer\r\n lines.push('---');\r\n lines.push('');\r\n lines.push('*Generated by PK Agent Benchmark*');\r\n\r\n return lines.join('\\n');\r\n}\r\n\r\n/**\r\n * Save Markdown report to file\r\n */\r\nexport async function saveMarkdownReport(\r\n result: SuiteResult,\r\n outputDir: string\r\n): Promise<string> {\r\n await mkdir(outputDir, { recursive: true });\r\n\r\n const filename = `${result.suiteId}-${result.runId}.md`;\r\n const filepath = join(outputDir, filename);\r\n\r\n await writeFile(filepath, generateMarkdownReport(result), 'utf-8');\r\n\r\n return filepath;\r\n}\r\n",
|
|
102
|
+
"import type { SuiteResult, ErrorCounts } from '../types.js';\r\n\r\n/**\r\n * Shared data structure for benchmark reports.\r\n * Used by both HTML and Markdown reporters to ensure consistent output.\r\n */\r\nexport interface ReportData {\r\n version: string;\r\n generatedAt: number;\r\n runs: number; // trials per scenario - used to hide consistency when runs=1\r\n summary: {\r\n suiteId: string;\r\n suiteName: string;\r\n runId: string;\r\n totalScenarios: number;\r\n totalTrials: number;\r\n totalModels: number;\r\n totalCostUsd: number;\r\n runDurationMs: number;\r\n };\r\n models: Array<{\r\n id: string;\r\n name: string;\r\n provider: string;\r\n scores: {\r\n overall: number;\r\n weighted?: number; // Difficulty-weighted score\r\n completion: number;\r\n passK: number;\r\n consistency: number;\r\n efficiency: number;\r\n };\r\n latency: {\r\n meanMs: number;\r\n p95Ms: number;\r\n };\r\n cost: {\r\n total?: number; // undefined if model pricing not available\r\n perFullRun?: number; // avg cost to run all scenarios once\r\n perScenario?: number;\r\n perSuccess?: number;\r\n };\r\n goals?: {\r\n completionRate: number;\r\n avgAttempts: number;\r\n toolCallFailureRate: number;\r\n toolCallEfficiency?: number;\r\n };\r\n tokenEfficiency?: {\r\n inputPerSuccess: number;\r\n outputPerSuccess: number;\r\n totalPerSuccess: number;\r\n };\r\n errors?: ErrorCounts;\r\n errorDetails?: Array<{\r\n scenario: string;\r\n trial: number;\r\n type: string;\r\n message: string;\r\n }>;\r\n }>;\r\n scenarios: Array<{\r\n id: string;\r\n name: string;\r\n agentPath: string;\r\n difficulty?: string;\r\n results: Record<\r\n string,\r\n {\r\n completionRate: number;\r\n passK: number;\r\n consistency: number;\r\n latencyMs: number;\r\n costUsd?: number | undefined; // undefined if model pricing not available\r\n inputTokens: number;\r\n outputTokens: number;\r\n goals?: {\r\n completed: number;\r\n total: number;\r\n recoveryRate: number;\r\n avgAttempts: number;\r\n toolCallFailureRate: number;\r\n toolCallEfficiency?: number;\r\n };\r\n }\r\n >;\r\n }>;\r\n ranking: Array<{\r\n model: string;\r\n rank: number;\r\n score: number;\r\n weighted?: number; // Difficulty-weighted score\r\n consistency: number;\r\n }>;\r\n}\r\n\r\n/**\r\n * Calculate P95 from an array of values\r\n */\r\nexport function calculateP95(values: number[]): number {\r\n if (values.length === 0) return 0;\r\n const sorted = [...values].sort((a, b) => a - b);\r\n const idx = Math.ceil(sorted.length * 0.95) - 1;\r\n return sorted[Math.max(0, idx)];\r\n}\r\n\r\n/**\r\n * Format duration in human-readable format\r\n */\r\nexport function formatDuration(ms: number): string {\r\n if (ms < 1000) return `${ms}ms`;\r\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\r\n const minutes = Math.floor(ms / 60000);\r\n const seconds = ((ms % 60000) / 1000).toFixed(0);\r\n return `${minutes}m ${seconds}s`;\r\n}\r\n\r\n/**\r\n * Format cost in USD (returns '-' if undefined)\r\n */\r\nexport function formatCost(usd: number | undefined): string {\r\n if (usd === undefined) return '-';\r\n if (usd < 0.01) return `$${usd.toFixed(4)}`;\r\n if (usd < 1) return `$${usd.toFixed(3)}`;\r\n return `$${usd.toFixed(2)}`;\r\n}\r\n\r\n/**\r\n * Format percentage\r\n */\r\nexport function formatPercent(value: number): string {\r\n return `${(value * 100).toFixed(1)}%`;\r\n}\r\n\r\n/**\r\n * Format token count (K/M suffixes)\r\n */\r\nexport function formatTokens(count: number): string {\r\n if (count >= 1000000) return `${(count / 1000000).toFixed(1)}M`;\r\n if (count >= 1000) return `${(count / 1000).toFixed(1)}K`;\r\n return count.toString();\r\n}\r\n\r\n/**\r\n * Generate shared data structure for benchmark reports\r\n */\r\nexport function generateReportData(result: SuiteResult): ReportData {\r\n const getProvider = (model: string): string => {\r\n const [provider] = model.split(':');\r\n return provider || 'unknown';\r\n };\r\n\r\n const getDisplayName = (model: string): string => {\r\n const parts = model.split(':');\r\n return parts[1] || model;\r\n };\r\n\r\n return {\r\n version: '1.0',\r\n generatedAt: Date.now(),\r\n runs: result.config.runs,\r\n\r\n summary: {\r\n suiteId: result.suiteId,\r\n suiteName: result.suiteName,\r\n runId: result.runId,\r\n totalScenarios: result.config.totalScenarios,\r\n totalTrials: result.config.totalTrials,\r\n totalModels: result.config.models.length,\r\n totalCostUsd: Object.values(result.modelResults).reduce(\r\n (sum, mr) => sum + (mr.aggregate.totalCostUsd ?? 0),\r\n 0\r\n ),\r\n runDurationMs: result.durationMs,\r\n },\r\n\r\n models: Object.entries(result.modelResults).map(([model, mr]) => {\r\n const allTrialDurations = mr.agents.flatMap((a) =>\r\n a.scenarios.flatMap((s) => s.trials.map((t) => t.execution.durationMs))\r\n );\r\n const scenarioCount = mr.agents.reduce(\r\n (sum, a) => sum + a.scenarios.length,\r\n 0\r\n );\r\n\r\n // Extract detailed error information from failed trials\r\n const errorDetails: Array<{\r\n scenario: string;\r\n trial: number;\r\n type: string;\r\n message: string;\r\n }> = [];\r\n for (const agent of mr.agents) {\r\n for (const scenario of agent.scenarios) {\r\n for (const trial of scenario.trials) {\r\n if (!trial.execution.success || !trial.output.valid) {\r\n errorDetails.push({\r\n scenario: scenario.scenarioName,\r\n trial: trial.trialNumber,\r\n type: trial.execution.error?.category ?? 'validation_failure',\r\n message:\r\n trial.execution.error?.message ??\r\n trial.output.validationDetails ??\r\n 'Unknown error',\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n id: model,\r\n name: getDisplayName(model),\r\n provider: getProvider(model),\r\n scores: {\r\n overall: mr.aggregate.overallScore,\r\n ...(mr.aggregate.weightedScore !== undefined && {\r\n weighted: mr.aggregate.weightedScore,\r\n }),\r\n completion: mr.aggregate.completionRate,\r\n passK: mr.aggregate.passK,\r\n consistency: mr.aggregate.consistency,\r\n efficiency: mr.aggregate.efficiency,\r\n },\r\n latency: {\r\n meanMs: mr.aggregate.latencyMeanMs,\r\n p95Ms: calculateP95(allTrialDurations),\r\n },\r\n cost: {\r\n ...(mr.aggregate.totalCostUsd !== undefined && {\r\n total: mr.aggregate.totalCostUsd,\r\n perFullRun: mr.aggregate.totalCostUsd / (result.config.runs || 1),\r\n perScenario: mr.aggregate.totalCostUsd / (scenarioCount || 1),\r\n }),\r\n ...(mr.aggregate.costPerSuccessUsd !== undefined && {\r\n perSuccess: mr.aggregate.costPerSuccessUsd,\r\n }),\r\n },\r\n ...(mr.aggregate.goals && {\r\n goals: {\r\n completionRate: mr.aggregate.goals.goalCompletionRate,\r\n avgAttempts: mr.aggregate.goals.avgAttemptsPerGoal,\r\n toolCallFailureRate: mr.aggregate.goals.toolCallFailureRate ?? (1 - mr.aggregate.goals.toolCallSuccessRate),\r\n ...(mr.aggregate.goals.toolCallEfficiency !== undefined && {\r\n toolCallEfficiency: mr.aggregate.goals.toolCallEfficiency,\r\n }),\r\n },\r\n }),\r\n ...(mr.aggregate.tokenEfficiency && {\r\n tokenEfficiency: mr.aggregate.tokenEfficiency,\r\n }),\r\n ...(mr.aggregate.errorCounts && {\r\n errors: mr.aggregate.errorCounts,\r\n }),\r\n ...(errorDetails.length > 0 && { errorDetails }),\r\n };\r\n }),\r\n\r\n scenarios: (() => {\r\n const scenarioMap = new Map<\r\n string,\r\n {\r\n id: string;\r\n name: string;\r\n agentPath: string;\r\n difficulty?: string;\r\n results: Record<\r\n string,\r\n {\r\n completionRate: number;\r\n passK: number;\r\n consistency: number;\r\n latencyMs: number;\r\n costUsd?: number; // undefined if model pricing not available\r\n inputTokens: number;\r\n outputTokens: number;\r\n goals?: {\r\n completed: number;\r\n total: number;\r\n recoveryRate: number;\r\n avgAttempts: number;\r\n toolCallFailureRate: number;\r\n toolCallEfficiency?: number;\r\n };\r\n }\r\n >;\r\n }\r\n >();\r\n\r\n for (const [model, mr] of Object.entries(result.modelResults)) {\r\n for (const agent of mr.agents) {\r\n for (const scenario of agent.scenarios) {\r\n if (!scenarioMap.has(scenario.scenarioId)) {\r\n scenarioMap.set(scenario.scenarioId, {\r\n id: scenario.scenarioId,\r\n name: scenario.scenarioName,\r\n agentPath: scenario.agentPath,\r\n ...(scenario.difficulty && { difficulty: scenario.difficulty }),\r\n results: {},\r\n });\r\n }\r\n\r\n const entry = scenarioMap.get(scenario.scenarioId)!;\r\n const goals = scenario.metrics.goals;\r\n // Calculate total input/output tokens from all trials\r\n const inputTokens = scenario.trials.reduce((sum, t) => sum + t.usage.inputTokens, 0);\r\n const outputTokens = scenario.trials.reduce((sum, t) => sum + t.usage.outputTokens, 0);\r\n entry.results[model] = {\r\n completionRate: scenario.metrics.completionRate,\r\n passK: scenario.metrics.passK,\r\n consistency: scenario.metrics.consistency,\r\n latencyMs: scenario.metrics.latency.meanMs,\r\n ...(scenario.metrics.cost.meanUsd !== undefined && {\r\n costUsd: scenario.metrics.cost.meanUsd,\r\n }),\r\n inputTokens,\r\n outputTokens,\r\n ...(goals && {\r\n goals: {\r\n completed: goals.completedGoals,\r\n total: goals.totalGoals,\r\n recoveryRate: goals.recoveryRate,\r\n avgAttempts: goals.avgAttemptsPerGoal,\r\n // Derive toolCallFailureRate if missing (backwards compat)\r\n toolCallFailureRate: goals.toolCallFailureRate ?? (1 - goals.toolCallSuccessRate),\r\n ...(goals.toolCallEfficiency !== undefined && {\r\n toolCallEfficiency: goals.toolCallEfficiency,\r\n }),\r\n },\r\n }),\r\n };\r\n }\r\n }\r\n }\r\n\r\n return Array.from(scenarioMap.values());\r\n })(),\r\n\r\n ranking: result.ranking.map((r) => ({\r\n model: r.model,\r\n rank: r.rank,\r\n score: r.score,\r\n ...(r.weightedScore !== undefined && { weighted: r.weightedScore }),\r\n consistency: r.consistency,\r\n })),\r\n };\r\n}\r\n\r\n/**\r\n * Glossary definitions for report metrics\r\n */\r\nexport const GLOSSARY_ITEMS = [\r\n {\r\n term: 'Score',\r\n definition: 'Composite performance score (0-100): Pass@k x 50 + Efficiency x 30 + Tool Success Rate x 20. When difficulties are set, harder scenarios contribute more (easy=1x, medium=2x, hard=3x).',\r\n },\r\n {\r\n term: 'Unweighted',\r\n definition: 'Raw score treating all scenarios equally, regardless of difficulty. Shown for comparison when difficulty weighting is applied.',\r\n },\r\n {\r\n term: 'Completion',\r\n definition: 'Percentage of trials where the agent successfully completed the task with valid output.',\r\n },\r\n {\r\n term: 'Pass^k',\r\n definition: 'Pass@k metric: probability that at least one of k trials succeeds. Higher is better.',\r\n },\r\n {\r\n term: 'Consistency',\r\n definition: 'How reliably the model produces the same result across multiple trials (only shown when k > 1).',\r\n },\r\n {\r\n term: 'Efficiency',\r\n definition: 'Relative efficiency score comparing cost-performance ratio against the best model (0-100%).',\r\n },\r\n {\r\n term: 'Tools/Goal',\r\n definition: 'Average number of tool calls needed to complete each goal. Lower indicates more efficient tool usage.',\r\n },\r\n {\r\n term: 'Tool Failure',\r\n definition: 'Percentage of tool calls that failed (errors, invalid params). Lower is better.',\r\n },\r\n {\r\n term: 'Tool Efficiency',\r\n definition: 'Ratio of goals achieved to total tool calls made. Higher means fewer wasted calls per goal.',\r\n },\r\n {\r\n term: 'Recovery',\r\n definition: 'Percentage of failed tool calls that were successfully retried and recovered.',\r\n },\r\n {\r\n term: 'P95 Latency',\r\n definition: '95th percentile response time-95% of trials complete faster than this duration.',\r\n },\r\n {\r\n term: 'Avg Cost',\r\n definition: 'Average cost per run. In Model Ranking, this is the cost to run all scenarios once. In Scenarios Breakdown, this is the cost per trial.',\r\n },\r\n {\r\n term: 'Cost/Success',\r\n definition: 'Average cost per successful trial. Accounts for failed attempts, so lower is more cost-effective.',\r\n },\r\n];\r\n",
|
|
103
|
+
"import { writeFile, mkdir } from 'fs/promises';\r\nimport { join } from 'path';\r\nimport type { SuiteResult } from '../types.js';\r\nimport {\r\n generateReportData,\r\n formatDuration,\r\n formatCost,\r\n GLOSSARY_ITEMS,\r\n} from './shared.js';\r\n\r\n/**\r\n * Generate HTML report from suite results\r\n */\r\nexport function generateHtmlReport(result: SuiteResult): string {\r\n const data = generateReportData(result);\r\n const dataJson = JSON.stringify(data, null, 2);\r\n\r\n return `<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n <meta charset=\"UTF-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n <title>${escapeHtml(result.suiteName)} - Benchmark Results</title>\r\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\r\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\r\n <link href=\"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=IBM+Plex+Sans:wght@400;500;600&display=swap\" rel=\"stylesheet\">\r\n <script src=\"https://cdn.jsdelivr.net/npm/chart.js\"></script>\r\n <style>\r\n :root {\r\n --bg-primary: #0d0d0d;\r\n --bg-secondary: #161616;\r\n --bg-tertiary: #1a1a1a;\r\n --bg-hover: #222222;\r\n --border: #2a2a2a;\r\n --border-light: #333333;\r\n --text-primary: #e5e5e5;\r\n --text-secondary: #a3a3a3;\r\n --text-muted: #6b6b6b;\r\n --accent: #00d4aa;\r\n --accent-dim: rgba(0, 212, 170, 0.15);\r\n --success: #22c55e;\r\n --warning: #eab308;\r\n --error: #ef4444;\r\n --chart-1: #00d4aa;\r\n --chart-2: #3b82f6;\r\n --chart-3: #a855f7;\r\n --chart-4: #f97316;\r\n --chart-5: #ec4899;\r\n --chart-6: #06b6d4;\r\n }\r\n\r\n * { box-sizing: border-box; margin: 0; padding: 0; }\r\n\r\n body {\r\n font-family: 'IBM Plex Sans', -apple-system, sans-serif;\r\n background: var(--bg-primary);\r\n color: var(--text-primary);\r\n line-height: 1.5;\r\n min-height: 100vh;\r\n }\r\n\r\n .mono {\r\n font-family: 'JetBrains Mono', 'SF Mono', monospace;\r\n }\r\n\r\n .container {\r\n max-width: 1400px;\r\n margin: 0 auto;\r\n padding: 0 24px;\r\n }\r\n\r\n /* Header */\r\n header {\r\n border-bottom: 1px solid var(--border);\r\n padding: 32px 0;\r\n }\r\n\r\n .header-content {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: flex-start;\r\n gap: 24px;\r\n flex-wrap: wrap;\r\n }\r\n\r\n .header-title {\r\n font-family: 'JetBrains Mono', monospace;\r\n font-size: 20px;\r\n font-weight: 600;\r\n color: var(--text-primary);\r\n letter-spacing: -0.02em;\r\n }\r\n\r\n .header-meta {\r\n display: flex;\r\n gap: 24px;\r\n font-size: 13px;\r\n color: var(--text-muted);\r\n font-family: 'JetBrains Mono', monospace;\r\n }\r\n\r\n .header-meta span {\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n }\r\n\r\n .run-id {\r\n color: var(--accent);\r\n background: var(--accent-dim);\r\n padding: 2px 8px;\r\n border-radius: 3px;\r\n }\r\n\r\n /* Summary Stats */\r\n .stats-grid {\r\n display: grid;\r\n grid-template-columns: repeat(4, 1fr);\r\n gap: 1px;\r\n background: var(--border);\r\n border: 1px solid var(--border);\r\n margin: 32px 0;\r\n }\r\n\r\n @media (max-width: 768px) {\r\n .stats-grid { grid-template-columns: repeat(2, 1fr); }\r\n }\r\n\r\n .stat-card {\r\n background: var(--bg-secondary);\r\n padding: 20px 24px;\r\n }\r\n\r\n .stat-label {\r\n font-size: 11px;\r\n text-transform: uppercase;\r\n letter-spacing: 0.08em;\r\n color: var(--text-muted);\r\n margin-bottom: 8px;\r\n }\r\n\r\n .stat-value {\r\n font-family: 'JetBrains Mono', monospace;\r\n font-size: 28px;\r\n font-weight: 600;\r\n color: var(--text-primary);\r\n }\r\n\r\n /* Section */\r\n .section {\r\n margin: 40px 0;\r\n }\r\n\r\n .section-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 16px;\r\n padding-bottom: 12px;\r\n border-bottom: 1px solid var(--border);\r\n }\r\n\r\n .section-title {\r\n font-family: 'JetBrains Mono', monospace;\r\n font-size: 14px;\r\n font-weight: 600;\r\n text-transform: uppercase;\r\n letter-spacing: 0.05em;\r\n color: var(--text-secondary);\r\n }\r\n\r\n /* Table */\r\n .table-wrapper {\r\n border: 1px solid var(--border);\r\n overflow-x: auto;\r\n }\r\n\r\n table {\r\n width: 100%;\r\n border-collapse: collapse;\r\n font-size: 13px;\r\n }\r\n\r\n thead {\r\n background: var(--bg-tertiary);\r\n }\r\n\r\n th {\r\n padding: 12px 16px;\r\n text-align: left;\r\n font-size: 11px;\r\n font-weight: 500;\r\n text-transform: uppercase;\r\n letter-spacing: 0.06em;\r\n color: var(--text-muted);\r\n border-bottom: 1px solid var(--border);\r\n white-space: nowrap;\r\n }\r\n\r\n th.sortable {\r\n cursor: pointer;\r\n user-select: none;\r\n transition: color 0.15s;\r\n }\r\n\r\n th.sortable:hover {\r\n color: var(--text-secondary);\r\n }\r\n\r\n th.sort-asc::after { content: ' ^'; color: var(--accent); }\r\n th.sort-desc::after { content: ' v'; color: var(--accent); }\r\n\r\n td {\r\n padding: 14px 16px;\r\n border-bottom: 1px solid var(--border);\r\n color: var(--text-secondary);\r\n }\r\n\r\n tr:hover td {\r\n background: var(--bg-hover);\r\n }\r\n\r\n tr:last-child td {\r\n border-bottom: none;\r\n }\r\n\r\n .cell-rank {\r\n font-family: 'JetBrains Mono', monospace;\r\n font-weight: 600;\r\n color: var(--text-muted);\r\n width: 60px;\r\n }\r\n\r\n .cell-model {\r\n min-width: 180px;\r\n }\r\n\r\n .model-name {\r\n font-weight: 500;\r\n color: var(--text-primary);\r\n }\r\n\r\n .model-provider {\r\n font-size: 11px;\r\n color: var(--text-muted);\r\n margin-top: 2px;\r\n }\r\n\r\n .cell-score {\r\n font-family: 'JetBrains Mono', monospace;\r\n font-weight: 600;\r\n }\r\n\r\n .cell-metric {\r\n font-family: 'JetBrains Mono', monospace;\r\n text-align: right;\r\n }\r\n\r\n .score-badge {\r\n display: inline-block;\r\n padding: 4px 10px;\r\n border-radius: 3px;\r\n font-size: 13px;\r\n font-weight: 600;\r\n }\r\n\r\n .score-high { color: var(--success); background: rgba(34, 197, 94, 0.12); }\r\n .score-mid { color: var(--warning); background: rgba(234, 179, 8, 0.12); }\r\n .score-low { color: var(--error); background: rgba(239, 68, 68, 0.12); }\r\n\r\n /* Status indicators */\r\n .status {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 6px;\r\n font-size: 12px;\r\n font-weight: 500;\r\n }\r\n\r\n .status-dot {\r\n width: 6px;\r\n height: 6px;\r\n border-radius: 50%;\r\n }\r\n\r\n .status-pass { color: var(--success); }\r\n .status-pass .status-dot { background: var(--success); }\r\n .status-partial { color: var(--warning); }\r\n .status-partial .status-dot { background: var(--warning); }\r\n .status-fail { color: var(--error); }\r\n .status-fail .status-dot { background: var(--error); }\r\n\r\n /* Charts */\r\n .charts-grid {\r\n display: grid;\r\n grid-template-columns: repeat(2, 1fr);\r\n gap: 24px;\r\n }\r\n\r\n @media (max-width: 900px) {\r\n .charts-grid { grid-template-columns: 1fr; }\r\n }\r\n\r\n .chart-card {\r\n background: var(--bg-secondary);\r\n border: 1px solid var(--border);\r\n padding: 24px;\r\n }\r\n\r\n .chart-title {\r\n font-size: 12px;\r\n font-weight: 500;\r\n text-transform: uppercase;\r\n letter-spacing: 0.05em;\r\n color: var(--text-muted);\r\n margin-bottom: 20px;\r\n }\r\n\r\n .chart-container {\r\n position: relative;\r\n height: 220px;\r\n }\r\n\r\n /* Model Details */\r\n .model-card {\r\n border: 1px solid var(--border);\r\n margin-bottom: 8px;\r\n }\r\n\r\n .model-card-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 16px 20px;\r\n background: var(--bg-secondary);\r\n cursor: pointer;\r\n transition: background 0.15s;\r\n }\r\n\r\n .model-card-header:hover {\r\n background: var(--bg-hover);\r\n }\r\n\r\n .model-card-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 16px;\r\n }\r\n\r\n .model-card-name {\r\n font-weight: 500;\r\n color: var(--text-primary);\r\n }\r\n\r\n .model-card-provider {\r\n font-size: 12px;\r\n color: var(--text-muted);\r\n }\r\n\r\n .chevron {\r\n width: 16px;\r\n height: 16px;\r\n color: var(--text-muted);\r\n transition: transform 0.2s;\r\n }\r\n\r\n .model-card.expanded .chevron {\r\n transform: rotate(180deg);\r\n }\r\n\r\n .model-card-content {\r\n display: none;\r\n padding: 20px;\r\n background: var(--bg-tertiary);\r\n border-top: 1px solid var(--border);\r\n }\r\n\r\n .model-card.expanded .model-card-content {\r\n display: block;\r\n }\r\n\r\n .metrics-grid {\r\n display: grid;\r\n grid-template-columns: repeat(4, 1fr);\r\n gap: 20px;\r\n }\r\n\r\n @media (max-width: 768px) {\r\n .metrics-grid { grid-template-columns: repeat(2, 1fr); }\r\n }\r\n\r\n .metric-item {\r\n padding: 12px 0;\r\n }\r\n\r\n .metric-label {\r\n font-size: 11px;\r\n text-transform: uppercase;\r\n letter-spacing: 0.06em;\r\n color: var(--text-muted);\r\n margin-bottom: 6px;\r\n }\r\n\r\n .metric-value {\r\n font-family: 'JetBrains Mono', monospace;\r\n font-size: 18px;\r\n font-weight: 600;\r\n color: var(--text-primary);\r\n }\r\n\r\n .errors-panel {\r\n margin-top: 20px;\r\n padding: 16px;\r\n background: rgba(239, 68, 68, 0.08);\r\n border: 1px solid rgba(239, 68, 68, 0.2);\r\n }\r\n\r\n .errors-title {\r\n font-size: 12px;\r\n font-weight: 500;\r\n color: var(--error);\r\n margin-bottom: 12px;\r\n }\r\n\r\n .error-tags {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 8px;\r\n }\r\n\r\n .error-tag {\r\n font-family: 'JetBrains Mono', monospace;\r\n font-size: 11px;\r\n padding: 4px 8px;\r\n background: rgba(239, 68, 68, 0.12);\r\n color: var(--error);\r\n }\r\n\r\n .error-details-list {\r\n margin-top: 12px;\r\n border-top: 1px solid rgba(239, 68, 68, 0.15);\r\n padding-top: 12px;\r\n }\r\n\r\n .error-detail-item {\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 8px;\r\n padding: 8px 0;\r\n border-bottom: 1px solid rgba(239, 68, 68, 0.1);\r\n font-size: 11px;\r\n }\r\n\r\n .error-detail-item:last-child {\r\n border-bottom: none;\r\n }\r\n\r\n .error-detail-scenario {\r\n font-family: 'JetBrains Mono', monospace;\r\n color: var(--text-secondary);\r\n white-space: nowrap;\r\n flex-shrink: 0;\r\n }\r\n\r\n .error-detail-type {\r\n font-family: 'JetBrains Mono', monospace;\r\n padding: 2px 6px;\r\n background: rgba(239, 68, 68, 0.12);\r\n color: var(--error);\r\n font-size: 10px;\r\n flex-shrink: 0;\r\n }\r\n\r\n .error-detail-message {\r\n font-family: 'JetBrains Mono', monospace;\r\n color: var(--text-muted);\r\n flex: 1;\r\n min-width: 0;\r\n word-break: break-word;\r\n }\r\n\r\n /* Difficulty badges */\r\n .difficulty {\r\n font-family: 'JetBrains Mono', monospace;\r\n font-size: 10px;\r\n font-weight: 500;\r\n text-transform: uppercase;\r\n letter-spacing: 0.05em;\r\n padding: 3px 8px;\r\n margin-top: 4px;\r\n display: inline-block;\r\n }\r\n\r\n .difficulty-easy { color: var(--success); background: rgba(34, 197, 94, 0.1); }\r\n .difficulty-medium { color: var(--warning); background: rgba(234, 179, 8, 0.1); }\r\n .difficulty-hard { color: var(--error); background: rgba(239, 68, 68, 0.1); }\r\n\r\n /* Footer */\r\n footer {\r\n margin-top: 60px;\r\n padding: 24px 0;\r\n border-top: 1px solid var(--border);\r\n }\r\n\r\n .footer-text {\r\n font-family: 'JetBrains Mono', monospace;\r\n font-size: 11px;\r\n color: var(--text-muted);\r\n text-align: center;\r\n }\r\n\r\n .footer-text strong {\r\n color: var(--text-secondary);\r\n }\r\n\r\n /* Glossary */\r\n .glossary {\r\n background: var(--bg-secondary);\r\n border: 1px solid var(--border);\r\n padding: 24px 28px;\r\n }\r\n\r\n .glossary-grid {\r\n display: grid;\r\n grid-template-columns: repeat(2, 1fr);\r\n gap: 16px 32px;\r\n }\r\n\r\n @media (max-width: 768px) {\r\n .glossary-grid { grid-template-columns: 1fr; }\r\n }\r\n\r\n .glossary-item {\r\n display: flex;\r\n gap: 12px;\r\n padding: 8px 0;\r\n border-bottom: 1px solid var(--border);\r\n }\r\n\r\n .glossary-item:last-child {\r\n border-bottom: none;\r\n }\r\n\r\n .glossary-term {\r\n font-family: 'JetBrains Mono', monospace;\r\n font-size: 12px;\r\n font-weight: 600;\r\n color: var(--accent);\r\n white-space: nowrap;\r\n min-width: 120px;\r\n flex-shrink: 0;\r\n }\r\n\r\n .glossary-def {\r\n font-size: 12px;\r\n color: var(--text-secondary);\r\n line-height: 1.5;\r\n }\r\n </style>\r\n</head>\r\n<body>\r\n <script>\r\n const DATA = ${dataJson};\r\n </script>\r\n\r\n <header>\r\n <div class=\"container\">\r\n <div class=\"header-content\">\r\n <h1 class=\"header-title\">${escapeHtml(result.suiteName)}</h1>\r\n <div class=\"header-meta\">\r\n <span><span class=\"run-id\">${escapeHtml(result.runId)}</span></span>\r\n <span>${new Date(result.timestamp).toISOString().slice(0, 19).replace('T', ' ')}</span>\r\n <span>${formatDuration(result.durationMs)}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </header>\r\n\r\n <main class=\"container\">\r\n <!-- Summary Stats -->\r\n <div class=\"stats-grid\">\r\n <div class=\"stat-card\">\r\n <div class=\"stat-label\">Models</div>\r\n <div class=\"stat-value\">${data.summary.totalModels}</div>\r\n </div>\r\n <div class=\"stat-card\">\r\n <div class=\"stat-label\">Scenarios</div>\r\n <div class=\"stat-value\">${data.summary.totalScenarios}</div>\r\n </div>\r\n <div class=\"stat-card\">\r\n <div class=\"stat-label\">Trials</div>\r\n <div class=\"stat-value\">${data.summary.totalTrials}</div>\r\n </div>\r\n <div class=\"stat-card\">\r\n <div class=\"stat-label\">Total Cost</div>\r\n <div class=\"stat-value\">${formatCost(data.summary.totalCostUsd)}</div>\r\n </div>\r\n </div>\r\n\r\n <!-- Model Ranking -->\r\n <section class=\"section\">\r\n <div class=\"section-header\">\r\n <h2 class=\"section-title\">Model Ranking</h2>\r\n </div>\r\n <div class=\"table-wrapper\">\r\n <table id=\"ranking-table\">\r\n <thead id=\"ranking-header\"></thead>\r\n <tbody id=\"ranking-body\"></tbody>\r\n </table>\r\n </div>\r\n </section>\r\n\r\n <!-- Charts -->\r\n <section class=\"section\">\r\n <div class=\"section-header\">\r\n <h2 class=\"section-title\">Performance Overview</h2>\r\n </div>\r\n <div class=\"charts-grid\">\r\n <div class=\"chart-card\">\r\n <h3 class=\"chart-title\">Overall Scores</h3>\r\n <div class=\"chart-container\">\r\n <canvas id=\"scores-chart\"></canvas>\r\n </div>\r\n </div>\r\n <div class=\"chart-card\">\r\n <h3 class=\"chart-title\">Multi-Metric Comparison</h3>\r\n <div class=\"chart-container\">\r\n <canvas id=\"radar-chart\"></canvas>\r\n </div>\r\n </div>\r\n </div>\r\n </section>\r\n\r\n <!-- Model Details -->\r\n <section class=\"section\">\r\n <div class=\"section-header\">\r\n <h2 class=\"section-title\">Model Details</h2>\r\n </div>\r\n <div id=\"model-details\"></div>\r\n </section>\r\n\r\n <!-- Scenarios -->\r\n <section class=\"section\">\r\n <div class=\"section-header\">\r\n <h2 class=\"section-title\">Scenarios Breakdown</h2>\r\n </div>\r\n <div class=\"table-wrapper\">\r\n <table>\r\n <thead id=\"scenarios-header\"></thead>\r\n <tbody id=\"scenarios-body\"></tbody>\r\n </table>\r\n </div>\r\n </section>\r\n\r\n <!-- Glossary -->\r\n <section class=\"section\">\r\n <div class=\"section-header\">\r\n <h2 class=\"section-title\">Glossary</h2>\r\n </div>\r\n <div class=\"glossary\">\r\n <div class=\"glossary-grid\">\r\n ${GLOSSARY_ITEMS.map(item => `\r\n <div class=\"glossary-item\">\r\n <span class=\"glossary-term\">${escapeHtml(item.term)}</span>\r\n <span class=\"glossary-def\">${escapeHtml(item.definition)}</span>\r\n </div>`).join('')}\r\n </div>\r\n </div>\r\n </section>\r\n </main>\r\n\r\n <footer>\r\n <div class=\"container\">\r\n <p class=\"footer-text\">Generated by <strong>PK Agent Benchmark</strong> - ${new Date().toISOString()}</p>\r\n </div>\r\n </footer>\r\n\r\n <script>\r\n function formatPercent(value) {\r\n return (value * 100).toFixed(1) + '%';\r\n }\r\n\r\n function formatDuration(ms) {\r\n if (ms < 1000) return ms + 'ms';\r\n if (ms < 60000) return (ms / 1000).toFixed(1) + 's';\r\n const minutes = Math.floor(ms / 60000);\r\n const seconds = ((ms % 60000) / 1000).toFixed(0);\r\n return minutes + 'm ' + seconds + 's';\r\n }\r\n\r\n function formatCost(usd) {\r\n if (usd === undefined || usd === null) return '-';\r\n if (usd < 0.01) return '$' + usd.toFixed(4);\r\n if (usd < 1) return '$' + usd.toFixed(3);\r\n return '$' + usd.toFixed(2);\r\n }\r\n\r\n function formatTokens(count) {\r\n if (count === undefined || count === null) return '-';\r\n if (count >= 1000000) return (count / 1000000).toFixed(1) + 'M';\r\n if (count >= 1000) return (count / 1000).toFixed(1) + 'K';\r\n return count.toString();\r\n }\r\n\r\n function getScoreClass(score) {\r\n if (score >= 90) return 'score-high'; // Green: excellent\r\n if (score >= 80) return 'score-mid'; // Yellow: good\r\n return 'score-low'; // Red: needs improvement\r\n }\r\n\r\n // Check if any model has goals\r\n const hasGoals = DATA.models.some(m => m.goals);\r\n // Check if weighted scores are available (must be non-null number)\r\n const hasWeightedScores = DATA.models.some(m => m.scores.weighted != null);\r\n // Hide consistency when runs=1 (always 100%)\r\n const showConsistency = DATA.runs > 1;\r\n\r\n // Ranking table\r\n function renderRankingHeader() {\r\n const thead = document.getElementById('ranking-header');\r\n if (hasGoals) {\r\n let headers = '<tr>';\r\n headers += '<th class=\"sortable\" data-sort=\"rank\">Rank</th>';\r\n headers += '<th class=\"sortable\" data-sort=\"name\">Model</th>';\r\n headers += '<th class=\"sortable\" data-sort=\"score\">Score</th>';\r\n if (hasWeightedScores) headers += '<th class=\"sortable\" data-sort=\"unweighted\">Unweighted</th>';\r\n headers += '<th class=\"sortable cell-metric\" data-sort=\"passK\">Pass^k</th>';\r\n headers += '<th class=\"sortable cell-metric\" data-sort=\"efficiency\">Efficiency</th>';\r\n headers += '<th class=\"sortable cell-metric\" data-sort=\"avgAttempts\">Tools/Goal</th>';\r\n headers += '<th class=\"sortable cell-metric\" data-sort=\"toolFailure\">Tool Failure</th>';\r\n headers += '<th class=\"sortable cell-metric\" data-sort=\"toolEfficiency\">Tool Efficiency</th>';\r\n headers += '<th class=\"sortable cell-metric\" data-sort=\"latency\">P95 Latency</th>';\r\n headers += '<th class=\"sortable cell-metric\" data-sort=\"cost\">Avg Cost</th>';\r\n headers += '</tr>';\r\n thead.innerHTML = headers;\r\n } else {\r\n let headers = '<tr>';\r\n headers += '<th class=\"sortable\" data-sort=\"rank\">Rank</th>';\r\n headers += '<th class=\"sortable\" data-sort=\"name\">Model</th>';\r\n headers += '<th class=\"sortable\" data-sort=\"score\">Score</th>';\r\n if (hasWeightedScores) headers += '<th class=\"sortable\" data-sort=\"unweighted\">Unweighted</th>';\r\n headers += '<th class=\"sortable cell-metric\" data-sort=\"completion\">Completion</th>';\r\n headers += '<th class=\"sortable cell-metric\" data-sort=\"passK\">Pass^k</th>';\r\n if (showConsistency) headers += '<th class=\"sortable cell-metric\" data-sort=\"consistency\">Consistency</th>';\r\n headers += '<th class=\"sortable cell-metric\" data-sort=\"latency\">P95 Latency</th>';\r\n headers += '<th class=\"sortable cell-metric\" data-sort=\"cost\">Avg Cost</th>';\r\n headers += '</tr>';\r\n thead.innerHTML = headers;\r\n }\r\n }\r\n\r\n function renderRankingTable(sortKey = 'rank', sortDir = 'asc') {\r\n const tbody = document.getElementById('ranking-body');\r\n const models = [...DATA.models];\r\n\r\n models.sort((a, b) => {\r\n let valA, valB;\r\n switch (sortKey) {\r\n case 'rank':\r\n valA = DATA.ranking.find(r => r.model === a.id)?.rank || 999;\r\n valB = DATA.ranking.find(r => r.model === b.id)?.rank || 999;\r\n break;\r\n case 'name': valA = a.name; valB = b.name; break;\r\n // Score = weighted if available and valid, else overall (unweighted)\r\n case 'score': valA = (a.scores.weighted != null) ? a.scores.weighted : (a.scores.overall ?? 0); valB = (b.scores.weighted != null) ? b.scores.weighted : (b.scores.overall ?? 0); break;\r\n case 'unweighted': valA = a.scores.overall; valB = b.scores.overall; break;\r\n case 'completion': valA = a.scores.completion; valB = b.scores.completion; break;\r\n case 'passK': valA = a.scores.passK; valB = b.scores.passK; break;\r\n case 'consistency': valA = a.scores.consistency; valB = b.scores.consistency; break;\r\n case 'efficiency': valA = a.scores.efficiency; valB = b.scores.efficiency; break;\r\n case 'avgAttempts': valA = a.goals?.avgAttempts || 999; valB = b.goals?.avgAttempts || 999; break;\r\n case 'toolFailure': valA = a.goals?.toolCallFailureRate || 0; valB = b.goals?.toolCallFailureRate || 0; break;\r\n case 'toolEfficiency': valA = a.goals?.toolCallEfficiency || 0; valB = b.goals?.toolCallEfficiency || 0; break;\r\n case 'latency': valA = a.latency.p95Ms; valB = b.latency.p95Ms; break;\r\n case 'cost': valA = a.cost.perFullRun; valB = b.cost.perFullRun; break;\r\n default: valA = a.scores.overall; valB = b.scores.overall;\r\n }\r\n return sortDir === 'asc' ? (valA > valB ? 1 : -1) : (valA < valB ? 1 : -1);\r\n });\r\n\r\n tbody.innerHTML = models.map(m => {\r\n const rank = DATA.ranking.find(r => r.model === m.id)?.rank || '-';\r\n // Score = weighted if available and valid, else overall (unweighted)\r\n const primaryScore = (m.scores.weighted != null) ? m.scores.weighted : (m.scores.overall ?? 0);\r\n // Unweighted cell only shown when weighted scores exist\r\n const unweightedCell = hasWeightedScores\r\n ? '<td class=\"cell-metric mono\">' + (m.scores.overall?.toFixed(1) ?? '-') + '</td>'\r\n : '';\r\n\r\n if (hasGoals) {\r\n const failureRate = m.goals?.toolCallFailureRate;\r\n const failureRateStr = (failureRate != null && !isNaN(failureRate)) ? formatPercent(failureRate) : '-';\r\n const toolEfficiency = m.goals?.toolCallEfficiency;\r\n const toolEfficiencyStr = (toolEfficiency != null && !isNaN(toolEfficiency)) ? formatPercent(toolEfficiency) : '-';\r\n return \\`\r\n <tr>\r\n <td class=\"cell-rank\">#\\${rank}</td>\r\n <td class=\"cell-model\">\r\n <div class=\"model-name\">\\${m.name}</div>\r\n <div class=\"model-provider\">\\${m.provider}</div>\r\n </td>\r\n <td class=\"cell-score\">\r\n <span class=\"score-badge \\${getScoreClass(primaryScore)}\">\\${primaryScore.toFixed(1)}</span>\r\n </td>\r\n \\${unweightedCell}\r\n <td class=\"cell-metric mono\">\\${formatPercent(m.scores.passK)}</td>\r\n <td class=\"cell-metric mono\">\\${formatPercent(m.scores.efficiency)}</td>\r\n <td class=\"cell-metric mono\">\\${m.goals ? m.goals.avgAttempts.toFixed(1) : '-'}</td>\r\n <td class=\"cell-metric mono\">\\${failureRateStr}</td>\r\n <td class=\"cell-metric mono\">\\${toolEfficiencyStr}</td>\r\n <td class=\"cell-metric mono\">\\${formatDuration(m.latency.p95Ms)}</td>\r\n <td class=\"cell-metric mono\">\\${formatCost(m.cost.perFullRun)}</td>\r\n </tr>\r\n \\`;\r\n } else {\r\n const consistencyCell = showConsistency\r\n ? '<td class=\"cell-metric mono\">' + formatPercent(m.scores.consistency) + '</td>'\r\n : '';\r\n return \\`\r\n <tr>\r\n <td class=\"cell-rank\">#\\${rank}</td>\r\n <td class=\"cell-model\">\r\n <div class=\"model-name\">\\${m.name}</div>\r\n <div class=\"model-provider\">\\${m.provider}</div>\r\n </td>\r\n <td class=\"cell-score\">\r\n <span class=\"score-badge \\${getScoreClass(primaryScore)}\">\\${primaryScore.toFixed(1)}</span>\r\n </td>\r\n \\${unweightedCell}\r\n <td class=\"cell-metric mono\">\\${formatPercent(m.scores.completion)}</td>\r\n <td class=\"cell-metric mono\">\\${formatPercent(m.scores.passK)}</td>\r\n \\${consistencyCell}\r\n <td class=\"cell-metric mono\">\\${formatDuration(m.latency.p95Ms)}</td>\r\n <td class=\"cell-metric mono\">\\${formatCost(m.cost.perFullRun)}</td>\r\n </tr>\r\n \\`;\r\n }\r\n }).join('');\r\n }\r\n\r\n // Sortable headers\r\n let currentSort = { key: 'rank', dir: 'asc' };\r\n function initSortableHeaders() {\r\n document.querySelectorAll('.sortable').forEach(header => {\r\n header.addEventListener('click', () => {\r\n const sortKey = header.dataset.sort;\r\n if (currentSort.key === sortKey) {\r\n currentSort.dir = currentSort.dir === 'asc' ? 'desc' : 'asc';\r\n } else {\r\n currentSort.key = sortKey;\r\n currentSort.dir = (sortKey === 'latency' || sortKey === 'cost' || sortKey === 'avgAttempts' || sortKey === 'toolFailure') ? 'asc' : 'desc';\r\n }\r\n document.querySelectorAll('.sortable').forEach(h => h.classList.remove('sort-asc', 'sort-desc'));\r\n header.classList.add(currentSort.dir === 'asc' ? 'sort-asc' : 'sort-desc');\r\n renderRankingTable(currentSort.key, currentSort.dir);\r\n });\r\n });\r\n }\r\n\r\n // Model details\r\n function renderModelDetails() {\r\n const container = document.getElementById('model-details');\r\n container.innerHTML = DATA.models.map((m, idx) => {\r\n const errors = m.errors || {};\r\n const totalErrors = Object.values(errors).reduce((sum, v) => sum + v, 0);\r\n // When weighted exists and is valid, show primary score (weighted)\r\n const primaryDetailScore = (m.scores.weighted != null) ? m.scores.weighted : (m.scores.overall ?? 0);\r\n const consistencyItem = showConsistency ? \\`\r\n <div class=\"metric-item\">\r\n <div class=\"metric-label\">Consistency</div>\r\n <div class=\"metric-value\">\\${formatPercent(m.scores.consistency)}</div>\r\n </div>\\` : '';\r\n const unweightedScoreItem = (m.scores.weighted != null) ? \\`\r\n <div class=\"metric-item\">\r\n <div class=\"metric-label\">Unweighted Score</div>\r\n <div class=\"metric-value\">\\${m.scores.overall?.toFixed(1) ?? '-'}</div>\r\n </div>\\` : '';\r\n\r\n return \\`\r\n <div class=\"model-card\" id=\"model-card-\\${idx}\">\r\n <div class=\"model-card-header\" onclick=\"toggleModel(\\${idx})\">\r\n <div class=\"model-card-left\">\r\n <span class=\"model-card-name\">\\${m.name}</span>\r\n <span class=\"model-card-provider\">\\${m.provider}</span>\r\n <span class=\"score-badge \\${getScoreClass(primaryDetailScore)}\">\\${primaryDetailScore.toFixed(1)}</span>\r\n </div>\r\n <svg class=\"chevron\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\"/>\r\n </svg>\r\n </div>\r\n <div class=\"model-card-content\">\r\n <div class=\"metrics-grid\">\r\n <div class=\"metric-item\">\r\n <div class=\"metric-label\">Completion</div>\r\n <div class=\"metric-value\">\\${formatPercent(m.scores.completion)}</div>\r\n </div>\r\n <div class=\"metric-item\">\r\n <div class=\"metric-label\">Pass^k</div>\r\n <div class=\"metric-value\">\\${formatPercent(m.scores.passK)}</div>\r\n </div>\r\n \\${consistencyItem}\r\n <div class=\"metric-item\">\r\n <div class=\"metric-label\">Efficiency</div>\r\n <div class=\"metric-value\">\\${formatPercent(m.scores.efficiency)}</div>\r\n </div>\r\n \\${unweightedScoreItem}\r\n <div class=\"metric-item\">\r\n <div class=\"metric-label\">Mean Latency</div>\r\n <div class=\"metric-value\">\\${formatDuration(m.latency.meanMs)}</div>\r\n </div>\r\n <div class=\"metric-item\">\r\n <div class=\"metric-label\">P95 Latency</div>\r\n <div class=\"metric-value\">\\${formatDuration(m.latency.p95Ms)}</div>\r\n </div>\r\n <div class=\"metric-item\">\r\n <div class=\"metric-label\">Avg Cost</div>\r\n <div class=\"metric-value\">\\${formatCost(m.cost.perFullRun)}</div>\r\n </div>\r\n <div class=\"metric-item\">\r\n <div class=\"metric-label\">Cost/Success</div>\r\n <div class=\"metric-value\">\\${m.cost.perSuccess ? formatCost(m.cost.perSuccess) : '-'}</div>\r\n </div>\r\n </div>\r\n \\${totalErrors > 0 ? \\`\r\n <div class=\"errors-panel\">\r\n <div class=\"errors-title\">\\${totalErrors} Error\\${totalErrors > 1 ? 's' : ''}</div>\r\n <div class=\"error-tags\">\r\n \\${errors.timeout ? \\`<span class=\"error-tag\">timeout: \\${errors.timeout}</span>\\` : ''}\r\n \\${errors.runtime_error ? \\`<span class=\"error-tag\">runtime: \\${errors.runtime_error}</span>\\` : ''}\r\n \\${errors.validation_failure ? \\`<span class=\"error-tag\">validation: \\${errors.validation_failure}</span>\\` : ''}\r\n \\${errors.tool_error ? \\`<span class=\"error-tag\">tool: \\${errors.tool_error}</span>\\` : ''}\r\n \\${errors.unknown ? \\`<span class=\"error-tag\">unknown: \\${errors.unknown}</span>\\` : ''}\r\n </div>\r\n \\${m.errorDetails && m.errorDetails.length > 0 ? \\`\r\n <div class=\"error-details-list\">\r\n \\${m.errorDetails.map(e => \\`\r\n <div class=\"error-detail-item\">\r\n <span class=\"error-detail-scenario\">\\${e.scenario} #\\${e.trial}</span>\r\n <span class=\"error-detail-type\">\\${e.type}</span>\r\n <span class=\"error-detail-message\">\\${e.message}</span>\r\n </div>\r\n \\`).join('')}\r\n </div>\r\n \\` : ''}\r\n </div>\r\n \\` : ''}\r\n </div>\r\n </div>\r\n \\`;\r\n }).join('');\r\n }\r\n\r\n function toggleModel(idx) {\r\n document.getElementById('model-card-' + idx).classList.toggle('expanded');\r\n }\r\n\r\n // Scenarios table\r\n function renderScenariosTable() {\r\n const thead = document.getElementById('scenarios-header');\r\n const tbody = document.getElementById('scenarios-body');\r\n const hasGoals = DATA.scenarios.some(s => Object.values(s.results).some(r => r.goals));\r\n\r\n const thBase = 'padding: 12px 16px; text-align: left; font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); border-bottom: 1px solid var(--border);';\r\n\r\n if (hasGoals) {\r\n thead.innerHTML = \\`<tr>\r\n <th style=\"\\${thBase}\">Scenario</th>\r\n <th style=\"\\${thBase}\">Model</th>\r\n <th style=\"\\${thBase} text-align: center;\">Status</th>\r\n <th style=\"\\${thBase} text-align: right;\">Goals</th>\r\n <th style=\"\\${thBase} text-align: right;\">Tools/Goal</th>\r\n <th style=\"\\${thBase} text-align: right;\">Tool Failure</th>\r\n <th style=\"\\${thBase} text-align: right;\">Tool Efficiency</th>\r\n <th style=\"\\${thBase} text-align: right;\">Recovery</th>\r\n <th style=\"\\${thBase} text-align: right;\">Input Tokens</th>\r\n <th style=\"\\${thBase} text-align: right;\">Output Tokens</th>\r\n <th style=\"\\${thBase} text-align: right;\">Latency</th>\r\n <th style=\"\\${thBase} text-align: right;\">Avg Cost</th>\r\n </tr>\\`;\r\n } else {\r\n thead.innerHTML = \\`<tr>\r\n <th style=\"\\${thBase}\">Scenario</th>\r\n <th style=\"\\${thBase}\">Model</th>\r\n <th style=\"\\${thBase} text-align: center;\">Status</th>\r\n <th style=\"\\${thBase} text-align: right;\">Completion</th>\r\n <th style=\"\\${thBase} text-align: right;\">Pass^k</th>\r\n <th style=\"\\${thBase} text-align: right;\">Consistency</th>\r\n <th style=\"\\${thBase} text-align: right;\">Input Tokens</th>\r\n <th style=\"\\${thBase} text-align: right;\">Output Tokens</th>\r\n <th style=\"\\${thBase} text-align: right;\">Latency</th>\r\n <th style=\"\\${thBase} text-align: right;\">Avg Cost</th>\r\n </tr>\\`;\r\n }\r\n\r\n const rows = [];\r\n for (const scenario of DATA.scenarios) {\r\n const diffClass = {\r\n easy: 'difficulty-easy',\r\n medium: 'difficulty-medium',\r\n hard: 'difficulty-hard'\r\n }[scenario.difficulty] || '';\r\n\r\n let isFirst = true;\r\n for (const model of DATA.models) {\r\n const result = scenario.results[model.id];\r\n if (!result) continue;\r\n\r\n const statusClass = result.completionRate === 1 ? 'status-pass' : result.completionRate > 0 ? 'status-partial' : 'status-fail';\r\n const statusText = result.completionRate === 1 ? 'pass' : result.completionRate > 0 ? 'partial' : 'fail';\r\n\r\n let metricCells = '';\r\n if (hasGoals && result.goals) {\r\n const failureRate = result.goals.toolCallFailureRate;\r\n const failureRateStr = (failureRate != null && !isNaN(failureRate)) ? formatPercent(failureRate) : '-';\r\n const efficiencyStr = (result.goals.toolCallEfficiency != null && !isNaN(result.goals.toolCallEfficiency)) ? formatPercent(result.goals.toolCallEfficiency) : '-';\r\n metricCells = \\`\r\n <td class=\"cell-metric mono\">\\${result.goals.completed}/\\${result.goals.total}</td>\r\n <td class=\"cell-metric mono\">\\${result.goals.avgAttempts.toFixed(1)}</td>\r\n <td class=\"cell-metric mono\">\\${failureRateStr}</td>\r\n <td class=\"cell-metric mono\">\\${efficiencyStr}</td>\r\n <td class=\"cell-metric mono\">\\${formatPercent(result.goals.recoveryRate)}</td>\r\n <td class=\"cell-metric mono\">\\${formatTokens(result.inputTokens)}</td>\r\n <td class=\"cell-metric mono\">\\${formatTokens(result.outputTokens)}</td>\r\n \\`;\r\n } else if (hasGoals) {\r\n metricCells = \\`<td class=\"cell-metric\">-</td><td class=\"cell-metric\">-</td><td class=\"cell-metric\">-</td><td class=\"cell-metric\">-</td><td class=\"cell-metric\">-</td><td class=\"cell-metric\">-</td><td class=\"cell-metric\">-</td>\\`;\r\n } else {\r\n metricCells = \\`\r\n <td class=\"cell-metric mono\">\\${formatPercent(result.completionRate)}</td>\r\n <td class=\"cell-metric mono\">\\${formatPercent(result.passK)}</td>\r\n <td class=\"cell-metric mono\">\\${formatPercent(result.consistency)}</td>\r\n <td class=\"cell-metric mono\">\\${formatTokens(result.inputTokens)}</td>\r\n <td class=\"cell-metric mono\">\\${formatTokens(result.outputTokens)}</td>\r\n \\`;\r\n }\r\n\r\n rows.push(\\`\r\n <tr>\r\n \\${isFirst ? \\`\r\n <td rowspan=\"\\${DATA.models.length}\" style=\"vertical-align: top; padding: 14px 16px; border-bottom: 1px solid var(--border);\">\r\n <div class=\"model-name\">\\${scenario.name}</div>\r\n \\${scenario.difficulty ? \\`<span class=\"difficulty \\${diffClass}\">\\${scenario.difficulty}</span>\\` : ''}\r\n </td>\r\n \\` : ''}\r\n <td class=\"cell-model\">\r\n <div class=\"model-name\">\\${model.name}</div>\r\n <div class=\"model-provider\">\\${model.provider}</div>\r\n </td>\r\n <td style=\"text-align: center;\">\r\n <span class=\"status \\${statusClass}\">\r\n <span class=\"status-dot\"></span>\r\n \\${statusText}\r\n </span>\r\n </td>\r\n \\${metricCells}\r\n <td class=\"cell-metric mono\">\\${formatDuration(result.latencyMs)}</td>\r\n <td class=\"cell-metric mono\">\\${formatCost(result.costUsd)}</td>\r\n </tr>\r\n \\`);\r\n isFirst = false;\r\n }\r\n }\r\n tbody.innerHTML = rows.join('');\r\n }\r\n\r\n // Charts\r\n function initCharts() {\r\n const colors = ['#00d4aa', '#3b82f6', '#a855f7', '#f97316', '#ec4899', '#06b6d4'];\r\n\r\n Chart.defaults.color = '#6b6b6b';\r\n Chart.defaults.borderColor = '#2a2a2a';\r\n Chart.defaults.font.family = \"'JetBrains Mono', monospace\";\r\n\r\n new Chart(document.getElementById('scores-chart').getContext('2d'), {\r\n type: 'bar',\r\n data: {\r\n labels: DATA.models.map(m => m.name),\r\n datasets: [{\r\n label: 'Score',\r\n data: DATA.models.map(m => m.scores.overall),\r\n backgroundColor: DATA.models.map((_, i) => colors[i % colors.length]),\r\n borderRadius: 2,\r\n borderSkipped: false\r\n }]\r\n },\r\n options: {\r\n responsive: true,\r\n maintainAspectRatio: false,\r\n plugins: { legend: { display: false } },\r\n scales: {\r\n y: { beginAtZero: true, max: 100, grid: { color: '#1a1a1a' } },\r\n x: { grid: { display: false } }\r\n }\r\n }\r\n });\r\n\r\n // Build radar chart labels and data based on whether consistency should be shown\r\n const radarLabels = showConsistency\r\n ? ['Completion', 'Pass^k', 'Consistency', 'Efficiency']\r\n : ['Completion', 'Pass^k', 'Efficiency'];\r\n\r\n new Chart(document.getElementById('radar-chart').getContext('2d'), {\r\n type: 'radar',\r\n data: {\r\n labels: radarLabels,\r\n datasets: DATA.models.map((m, i) => ({\r\n label: m.name,\r\n data: showConsistency\r\n ? [m.scores.completion * 100, m.scores.passK * 100, m.scores.consistency * 100, m.scores.efficiency * 100]\r\n : [m.scores.completion * 100, m.scores.passK * 100, m.scores.efficiency * 100],\r\n backgroundColor: colors[i % colors.length] + '20',\r\n borderColor: colors[i % colors.length],\r\n pointBackgroundColor: colors[i % colors.length],\r\n pointRadius: 3,\r\n borderWidth: 2\r\n }))\r\n },\r\n options: {\r\n responsive: true,\r\n maintainAspectRatio: false,\r\n plugins: { legend: { position: 'bottom', labels: { boxWidth: 12, padding: 16 } } },\r\n scales: {\r\n r: {\r\n beginAtZero: true,\r\n max: 100,\r\n grid: { color: '#2a2a2a' },\r\n angleLines: { color: '#2a2a2a' },\r\n pointLabels: { color: '#a3a3a3', font: { size: 11 } }\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n // Initialize\r\n document.addEventListener('DOMContentLoaded', () => {\r\n renderRankingHeader();\r\n renderRankingTable();\r\n initSortableHeaders();\r\n renderModelDetails();\r\n renderScenariosTable();\r\n initCharts();\r\n document.querySelector('[data-sort=\"rank\"]').classList.add('sort-asc');\r\n });\r\n </script>\r\n</body>\r\n</html>`;\r\n}\r\n\r\n/**\r\n * Escape HTML special characters\r\n */\r\nfunction escapeHtml(str: string): string {\r\n return str\r\n .replace(/&/g, '&')\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/\"/g, '"')\r\n .replace(/'/g, ''');\r\n}\r\n\r\n/**\r\n * Save HTML report to file\r\n */\r\nexport async function saveHtmlReport(\r\n result: SuiteResult,\r\n outputDir: string\r\n): Promise<string> {\r\n await mkdir(outputDir, { recursive: true });\r\n\r\n const filename = `${result.suiteId}-${result.runId}.html`;\r\n const filepath = join(outputDir, filename);\r\n\r\n await writeFile(filepath, generateHtmlReport(result), 'utf-8');\r\n\r\n return filepath;\r\n}\r\n",
|
|
104
|
+
"import { generateJsonReport, saveJsonReport, isRawBenchmarkResult } from './json.js';\nimport { generateMarkdownReport, saveMarkdownReport } from './markdown.js';\nimport { generateHtmlReport, saveHtmlReport } from './html.js';\nimport type { SuiteResult } from '../types.js';\n\n// Re-export shared utilities for external consumers\nexport {\n type ReportData,\n generateReportData,\n formatDuration,\n formatCost,\n formatPercent,\n formatTokens,\n GLOSSARY_ITEMS,\n} from './shared.js';\n\nexport {\n generateJsonReport,\n saveJsonReport,\n isRawBenchmarkResult,\n generateMarkdownReport,\n saveMarkdownReport,\n generateHtmlReport,\n saveHtmlReport,\n};\n\nexport type ReportFormat = 'json' | 'markdown' | 'html';\n\n/**\n * Save reports in specified formats\n */\nexport async function saveReports(\n result: SuiteResult,\n outputDir: string,\n formats: ReportFormat[] = ['json', 'markdown', 'html']\n): Promise<string[]> {\n const savedFiles: string[] = [];\n\n for (const format of formats) {\n switch (format) {\n case 'json':\n savedFiles.push(await saveJsonReport(result, outputDir));\n break;\n case 'markdown':\n savedFiles.push(await saveMarkdownReport(result, outputDir));\n break;\n case 'html':\n savedFiles.push(await saveHtmlReport(result, outputDir));\n break;\n }\n }\n\n return savedFiles;\n}\n",
|
|
105
|
+
"import { Command } from 'commander';\r\nimport chalk from 'chalk';\r\nimport { relative, dirname } from 'path';\r\nimport { glob } from 'glob';\r\nimport { resolveProjectContext } from '../utils/project.js';\r\nimport { parseAgent } from '../parser.js';\r\nimport { formatScheduleHuman } from '../scheduler/parser.js';\r\n\r\ninterface AgentInfo {\r\n name: string;\r\n path: string;\r\n relativePath: string;\r\n dir: string;\r\n description: string | undefined;\r\n model: string;\r\n schedule: string | undefined;\r\n}\r\n\r\n/**\r\n * Discover all agent files in the project\r\n */\r\nasync function discoverAgents(projectRoot: string): Promise<AgentInfo[]> {\r\n const agents: AgentInfo[] = [];\r\n\r\n try {\r\n const files = await glob('**/*.pk-agent', {\r\n cwd: projectRoot,\r\n absolute: true,\r\n ignore: ['**/node_modules/**', '**/dist/**', '**/.git/**'],\r\n });\r\n\r\n for (const file of files) {\r\n try {\r\n const parsed = await parseAgent(file);\r\n const relativePath = relative(projectRoot, file);\r\n agents.push({\r\n name: parsed.name,\r\n path: file,\r\n relativePath,\r\n dir: dirname(relativePath) || '.',\r\n description: parsed.description,\r\n model: parsed.config.model,\r\n schedule: parsed.config.schedule,\r\n });\r\n } catch {\r\n // Skip files that fail to parse\r\n }\r\n }\r\n } catch {\r\n // Directory not readable, skip\r\n }\r\n\r\n return agents;\r\n}\r\n\r\nexport function createAgentsCommand(): Command {\r\n const agentsCommand = new Command('agents')\r\n .description('List available agents in the project')\r\n .option('-v, --verbose', 'Show model information')\r\n .option('-j, --json', 'Output as JSON')\r\n .action(async (options: { verbose?: boolean; json?: boolean }) => {\r\n const projectContext = resolveProjectContext(process.cwd());\r\n const agents = await discoverAgents(projectContext.projectRoot);\r\n\r\n // JSON output\r\n if (options.json) {\r\n const output = {\r\n project: projectContext.projectRoot,\r\n count: agents.length,\r\n agents: agents.map((a) => ({\r\n name: a.name,\r\n path: a.relativePath,\r\n description: a.description ?? null,\r\n model: a.model,\r\n schedule: a.schedule ?? null,\r\n })),\r\n };\r\n console.log(JSON.stringify(output, null, 2));\r\n return;\r\n }\r\n\r\n // Header\r\n console.log();\r\n console.log(chalk.bold.blue('* Agents'));\r\n console.log(chalk.gray(` ${projectContext.projectRoot}`));\r\n console.log();\r\n\r\n if (agents.length === 0) {\r\n console.log(chalk.gray(' No agents found.'));\r\n console.log();\r\n return;\r\n }\r\n\r\n // Group by directory\r\n const grouped = new Map<string, AgentInfo[]>();\r\n for (const agent of agents) {\r\n if (!grouped.has(agent.dir)) {\r\n grouped.set(agent.dir, []);\r\n }\r\n grouped.get(agent.dir)!.push(agent);\r\n }\r\n\r\n // Sort directories, then sort agents by name within each directory\r\n const sortedDirs = [...grouped.keys()].sort();\r\n\r\n console.log(chalk.gray(` ${agents.length} agents found`));\r\n console.log();\r\n\r\n for (const dir of sortedDirs) {\r\n const dirAgents = grouped.get(dir)!;\r\n dirAgents.sort((a, b) => a.name.localeCompare(b.name));\r\n\r\n for (const agent of dirAgents) {\r\n const path = chalk.cyan(agent.relativePath);\r\n const schedule = agent.schedule ? chalk.yellow(` ${formatScheduleHuman(agent.schedule)}`) : '';\r\n const desc = agent.description ? chalk.gray(` - ${agent.description}`) : '';\r\n console.log(` ${path}${schedule}${desc}`);\r\n if (options.verbose) {\r\n console.log(chalk.gray(` model: ${agent.model}`));\r\n }\r\n }\r\n console.log();\r\n }\r\n });\r\n\r\n return agentsCommand;\r\n}\r\n",
|
|
106
|
+
"import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { execSync } from 'child_process';\nimport { existsSync, rmSync, mkdirSync, cpSync, statSync, readFileSync } from 'fs';\nimport { glob } from 'glob';\nimport { join, basename, dirname, resolve } from 'path';\nimport { tmpdir, homedir } from 'os';\nimport * as readline from 'readline';\nimport * as p from '@clack/prompts';\nimport { resolveProjectContext } from '../utils/project.js';\nimport { telemetry, type AddCommandResult } from '../telemetry/index.js';\n\ntype SourceType = 'github' | 'git' | 'local' | 'skill';\n\n/**\n * Extract a privacy-safe source identifier for telemetry\n * - GitHub: user/repo format\n * - Git URLs: extracts user/repo from common formats\n * - Local paths: returns undefined (privacy)\n */\nfunction sanitizeSourceForTelemetry(source: string, type: SourceType): string | undefined {\n if (type === 'local' || type === 'skill') {\n // Don't track local paths for privacy\n return undefined;\n }\n\n if (type === 'github') {\n // GitHub shorthand: user/repo or user/repo#ref\n return source.split('#')[0];\n }\n\n if (type === 'git') {\n // Extract user/repo from git URLs\n // https://github.com/user/repo.git -> user/repo\n // git@github.com:user/repo.git -> user/repo\n const httpsMatch = source.match(/github\\.com\\/([^/]+\\/[^/.]+)/);\n if (httpsMatch) return httpsMatch[1];\n\n const sshMatch = source.match(/github\\.com:([^/]+\\/[^/.]+)/);\n if (sshMatch) return sshMatch[1];\n\n // For other git hosts, just return the hostname\n try {\n const url = new URL(source);\n return url.hostname;\n } catch {\n return undefined;\n }\n }\n\n return undefined;\n}\n\ninterface ResolvedSource {\n type: SourceType;\n path: string;\n ref?: string;\n needsClone: boolean;\n}\n\ninterface SkillInfo {\n name: string;\n description: string;\n path: string;\n}\n\ninterface AgentInfo {\n path: string;\n name: string;\n}\n\ninterface CopyResult {\n skills: { name: string; action: 'added' | 'skipped' | 'overwritten' }[];\n agents: { path: string; action: 'added' | 'skipped' | 'overwritten' }[];\n}\n\ntype ConflictMode = 'prompt' | 'skip-all' | 'overwrite-all';\n\n/**\n * Resolve the source to a normalized format\n */\nexport function resolveSource(source: string): ResolvedSource {\n // Direct skill path (contains SKILL.md)\n if (existsSync(source) && existsSync(join(source, 'SKILL.md'))) {\n return { type: 'skill', path: resolve(source), needsClone: false };\n }\n\n // Local directory (starts with ./ or / or is an existing directory)\n if (source.startsWith('./') || source.startsWith('/') || (existsSync(source) && statSync(source).isDirectory())) {\n return { type: 'local', path: resolve(source), needsClone: false };\n }\n\n // Git URL (https:// or git@)\n if (source.startsWith('https://') || source.startsWith('git@')) {\n return { type: 'git', path: source, needsClone: true };\n }\n\n // GitHub shorthand (user/repo or user/repo#ref)\n const [repo, ref] = source.split('#');\n return { type: 'github', path: `https://github.com/${repo}.git`, ref, needsClone: true };\n}\n\n/**\n * Parse skill description from SKILL.md frontmatter\n */\nfunction parseSkillDescription(skillMdPath: string): string {\n try {\n const content = readFileSync(skillMdPath, 'utf-8');\n const match = content.match(/^---\\s*\\n([\\s\\S]*?)\\n---/);\n if (match) {\n const frontmatter = match[1];\n const descMatch = frontmatter.match(/description:\\s*(.+)/);\n if (descMatch) {\n return descMatch[1].trim().replace(/^[\"']|[\"']$/g, '');\n }\n }\n } catch {\n // Ignore parse errors\n }\n return '';\n}\n\n/**\n * Discover available skills and agents in a directory\n */\nexport async function discoverItems(workDir: string): Promise<{ skills: SkillInfo[]; agents: AgentInfo[] }> {\n const skills: SkillInfo[] = [];\n const agents: AgentInfo[] = [];\n\n // Find skills\n const skillFiles = await glob('**/SKILL.md', {\n cwd: workDir,\n ignore: ['node_modules/**', '.git/**', 'docs/**', 'tests/**'],\n });\n\n for (const skillMd of skillFiles) {\n const skillDir = dirname(skillMd);\n const skillName = basename(skillDir);\n const description = parseSkillDescription(join(workDir, skillMd));\n skills.push({ name: skillName, description, path: skillDir });\n }\n\n // Find agents\n const agentFiles = await glob('**/*.pk-agent', {\n cwd: workDir,\n ignore: ['node_modules/**', '.git/**', 'docs/**', 'tests/**'],\n });\n\n for (const agent of agentFiles) {\n // Normalize to forward slashes for consistent cross-platform paths\n const normalizedPath = agent.replace(/\\\\/g, '/');\n agents.push({ path: normalizedPath, name: basename(agent, '.pk-agent') });\n }\n\n return { skills, agents };\n}\n\n/**\n * Prompt user for conflict resolution\n */\nasync function promptConflict(\n type: 'skill' | 'agent',\n name: string\n): Promise<'skip' | 'overwrite' | 'skip-all' | 'overwrite-all'> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n console.log(chalk.yellow(`\\n${type === 'skill' ? 'Skill' : 'Agent'} \"${name}\" already exists.`));\n rl.question(chalk.gray(' [s] Skip [o] Overwrite [a] Skip all [O] Overwrite all: '), (answer) => {\n rl.close();\n switch (answer.trim()) {\n case 'o':\n resolve('overwrite');\n break;\n case 'a':\n resolve('skip-all');\n break;\n case 'O':\n resolve('overwrite-all');\n break;\n case 's':\n default:\n resolve('skip');\n break;\n }\n });\n });\n}\n\n/**\n * Copy a skill or agent, prompting on conflict\n */\nasync function copyWithConflictHandling(\n src: string,\n dest: string,\n type: 'skill' | 'agent',\n name: string,\n mode: ConflictMode\n): Promise<{ action: 'added' | 'skipped' | 'overwritten'; newMode?: ConflictMode }> {\n const exists = existsSync(dest);\n\n if (exists) {\n if (mode === 'skip-all') {\n return { action: 'skipped' };\n }\n if (mode === 'overwrite-all') {\n rmSync(dest, { recursive: true, force: true });\n mkdirSync(dirname(dest), { recursive: true });\n cpSync(src, dest, { recursive: true });\n return { action: 'overwritten' };\n }\n\n // Prompt user\n const answer = await promptConflict(type, name);\n\n if (answer === 'skip-all') {\n return { action: 'skipped', newMode: 'skip-all' };\n }\n if (answer === 'overwrite-all') {\n rmSync(dest, { recursive: true, force: true });\n mkdirSync(dirname(dest), { recursive: true });\n cpSync(src, dest, { recursive: true });\n return { action: 'overwritten', newMode: 'overwrite-all' };\n }\n if (answer === 'overwrite') {\n rmSync(dest, { recursive: true, force: true });\n mkdirSync(dirname(dest), { recursive: true });\n cpSync(src, dest, { recursive: true });\n return { action: 'overwritten' };\n }\n return { action: 'skipped' };\n }\n\n // No conflict - just copy\n mkdirSync(dirname(dest), { recursive: true });\n cpSync(src, dest, { recursive: true });\n return { action: 'added' };\n}\n\ninterface AddOptions {\n force?: boolean;\n selectedSkills?: string[] | undefined;\n selectedAgents?: string[] | undefined;\n /** Override destination root for skills (e.g., ~/.pk-agent/skills/ for user scope) */\n skillDestRoot?: string | undefined;\n /** Override destination root for agents (e.g., ~/.pk-agent/agents/ for user scope) */\n agentDestRoot?: string | undefined;\n}\n\n/**\n * Main add function\n */\nexport async function add(\n source: string,\n projectRoot: string,\n options: AddOptions = {}\n): Promise<CopyResult> {\n const resolved = resolveSource(source);\n let workDir: string;\n let shouldCleanup = false;\n const result: CopyResult = { skills: [], agents: [] };\n let conflictMode: ConflictMode = options.force ? 'overwrite-all' : 'prompt';\n\n // 1. Get working directory\n if (resolved.needsClone) {\n workDir = join(tmpdir(), `pk-agent-add-${Date.now()}`);\n const cloneCmd = resolved.ref\n ? `git clone --depth 1 --branch ${resolved.ref} \"${resolved.path}\" \"${workDir}\"`\n : `git clone --depth 1 \"${resolved.path}\" \"${workDir}\"`;\n\n console.log(chalk.gray(`Cloning ${resolved.path}...`));\n try {\n execSync(cloneCmd, { stdio: 'pipe' });\n } catch (error) {\n throw new Error(`Failed to clone repository: ${(error as Error).message}`);\n }\n shouldCleanup = true;\n } else {\n workDir = resolved.path;\n }\n\n try {\n // 2. Handle direct skill path\n if (resolved.type === 'skill') {\n const skillName = basename(workDir);\n const dest = options.skillDestRoot\n ? join(options.skillDestRoot, skillName)\n : join(projectRoot, '.pk-agent', 'skills', skillName);\n const { action } = await copyWithConflictHandling(workDir, dest, 'skill', skillName, conflictMode);\n result.skills.push({ name: skillName, action });\n return result;\n }\n\n // 3. Find available items\n const { skills, agents } = await discoverItems(workDir);\n\n // 4. Filter by selection if provided\n const selectedSkills = options.selectedSkills;\n const selectedAgents = options.selectedAgents;\n\n // Copy skills\n for (const skill of skills) {\n if (selectedSkills && !selectedSkills.includes(skill.name)) {\n continue;\n }\n\n const src = join(workDir, skill.path);\n const dest = options.skillDestRoot\n ? join(options.skillDestRoot, skill.name)\n : join(projectRoot, '.pk-agent', 'skills', skill.name);\n\n const { action, newMode } = await copyWithConflictHandling(src, dest, 'skill', skill.name, conflictMode);\n if (newMode) conflictMode = newMode;\n result.skills.push({ name: skill.name, action });\n }\n\n // Copy agents\n for (const agent of agents) {\n if (selectedAgents && !selectedAgents.includes(agent.path)) {\n continue;\n }\n\n const src = join(workDir, agent.path);\n const agentFileName = basename(agent.path);\n const dest = options.agentDestRoot\n ? join(options.agentDestRoot, agentFileName)\n : join(projectRoot, agent.path);\n\n const { action, newMode } = await copyWithConflictHandling(src, dest, 'agent', agent.path, conflictMode);\n if (newMode) conflictMode = newMode;\n result.agents.push({ path: agent.path, action });\n }\n\n return result;\n } finally {\n // 5. Cleanup\n if (shouldCleanup) {\n rmSync(workDir, { recursive: true, force: true });\n }\n }\n}\n\n/**\n * Print summary of what was added\n */\nfunction printSummary(result: CopyResult): void {\n const skillsAdded = result.skills.filter((s) => s.action === 'added').length;\n const skillsOverwritten = result.skills.filter((s) => s.action === 'overwritten').length;\n const skillsSkipped = result.skills.filter((s) => s.action === 'skipped').length;\n\n const agentsAdded = result.agents.filter((a) => a.action === 'added').length;\n const agentsOverwritten = result.agents.filter((a) => a.action === 'overwritten').length;\n const agentsSkipped = result.agents.filter((a) => a.action === 'skipped').length;\n\n const lines: string[] = [];\n\n if (result.skills.length > 0) {\n const parts: string[] = [];\n if (skillsAdded > 0) parts.push(chalk.green(`${skillsAdded} added`));\n if (skillsOverwritten > 0) parts.push(chalk.yellow(`${skillsOverwritten} overwritten`));\n if (skillsSkipped > 0) parts.push(chalk.gray(`${skillsSkipped} skipped`));\n lines.push(`Skills: ${parts.join(', ')}`);\n\n for (const skill of result.skills) {\n const icon =\n skill.action === 'added' ? chalk.green('+') : skill.action === 'overwritten' ? chalk.yellow('~') : chalk.gray('-');\n lines.push(` ${icon} ${skill.name}`);\n }\n }\n\n if (result.agents.length > 0) {\n const parts: string[] = [];\n if (agentsAdded > 0) parts.push(chalk.green(`${agentsAdded} added`));\n if (agentsOverwritten > 0) parts.push(chalk.yellow(`${agentsOverwritten} overwritten`));\n if (agentsSkipped > 0) parts.push(chalk.gray(`${agentsSkipped} skipped`));\n lines.push(`Agents: ${parts.join(', ')}`);\n\n for (const agent of result.agents) {\n const icon =\n agent.action === 'added' ? chalk.green('+') : agent.action === 'overwritten' ? chalk.yellow('~') : chalk.gray('-');\n lines.push(` ${icon} ${agent.path}`);\n }\n }\n\n if (result.skills.length === 0 && result.agents.length === 0) {\n lines.push(chalk.gray('No skills or agents found in the source.'));\n }\n\n if (lines.length > 0) {\n p.log.success(lines.join('\\n'));\n }\n}\n\n/**\n * Interactive selection prompt - combined skills and agents\n */\nasync function promptSelection(\n skills: SkillInfo[],\n agents: AgentInfo[],\n projectRoot: string\n): Promise<{ selectedSkills: string[]; selectedAgents: string[] } | null> {\n // Build combined options with type prefixes\n const options: { value: string; label: string }[] = [];\n\n for (const s of skills) {\n const exists = existsSync(join(projectRoot, '.pk-agent', 'skills', s.name));\n const marker = exists ? chalk.yellow(' (exists)') : '';\n options.push({ value: `skill:${s.name}`, label: `${chalk.blue('[skill]')} ${s.name}${marker}` });\n }\n\n for (const a of agents) {\n const exists = existsSync(join(projectRoot, a.path));\n const marker = exists ? chalk.yellow(' (exists)') : '';\n options.push({ value: `agent:${a.path}`, label: `${chalk.magenta('[agent]')} ${a.path}${marker}` });\n }\n\n if (options.length === 0) {\n return { selectedSkills: [], selectedAgents: [] };\n }\n\n const selection = await p.multiselect({\n message: 'Select items to install (use --list to see descriptions)',\n options,\n initialValues: options.map((o) => o.value),\n required: false,\n });\n\n if (p.isCancel(selection)) {\n return null;\n }\n\n const selected = selection as string[];\n const selectedSkills = selected.filter((v) => v.startsWith('skill:')).map((v) => v.slice(6));\n const selectedAgents = selected.filter((v) => v.startsWith('agent:')).map((v) => v.slice(6));\n\n return { selectedSkills, selectedAgents };\n}\n\ninterface CliOptions {\n force?: boolean;\n all?: boolean;\n list?: boolean;\n skill?: string[];\n agent?: string[];\n urlpath?: string;\n}\n\nexport function createAddCommand(): Command {\n const addCommand = new Command('add')\n .description('Add skills and agents from a GitHub repo, git URL, or local path')\n .argument('<source>', 'Source to add (user/repo, git URL, or local path)')\n .option('--force', 'Overwrite existing skills/agents without prompting')\n .option('--all', 'Install all skills and agents without prompting')\n .option('--list', 'List available skills and agents without installing')\n .option('-s, --skill <name...>', 'Install specific skill(s) by name')\n .option('-a, --agent <path...>', 'Install specific agent(s) by path')\n .option('-u, --urlpath <path>', 'Install into .pk-agent/ at this filepath instead of auto-detected project root')\n .action(async (source: string, options: CliOptions) => {\n const projectContext = resolveProjectContext(process.cwd());\n const startTime = Date.now();\n\n // Resolve --urlpath: override the effective project root\n const effectiveRoot = options.urlpath ? resolve(options.urlpath) : projectContext.projectRoot;\n if (options.urlpath) {\n mkdirSync(join(effectiveRoot, '.pk-agent', 'skills'), { recursive: true });\n mkdirSync(join(effectiveRoot, '.pk-agent', 'agents'), { recursive: true });\n }\n\n // Telemetry state - will be updated as we progress\n let telemetryData: Partial<AddCommandResult> = {\n sourceType: 'github', // Will be updated after resolving\n mode: options.list ? 'list' : options.all ? 'all' : options.skill || options.agent ? 'explicit' : 'interactive',\n force: options.force ?? false,\n success: false,\n };\n // Track if source is trackable (non-local)\n let isTrackableSource = false;\n\n p.intro(chalk.bold.blue('PK Agent Add'));\n p.log.info(chalk.gray(`Target: ${effectiveRoot}${options.urlpath ? ' (--urlpath)' : ''}`));\n\n try {\n // 1. Resolve and clone/access source\n const resolved = resolveSource(source);\n telemetryData.sourceType = resolved.type;\n const sanitizedSource = sanitizeSourceForTelemetry(source, resolved.type);\n if (sanitizedSource) {\n telemetryData.source = sanitizedSource;\n isTrackableSource = true;\n }\n\n let workDir: string;\n let shouldCleanup = false;\n\n if (resolved.needsClone) {\n workDir = join(tmpdir(), `pk-agent-add-${Date.now()}`);\n const cloneCmd = resolved.ref\n ? `git clone --depth 1 --branch ${resolved.ref} \"${resolved.path}\" \"${workDir}\"`\n : `git clone --depth 1 \"${resolved.path}\" \"${workDir}\"`;\n\n const spinner = p.spinner();\n spinner.start(`Cloning ${resolved.path}`);\n try {\n execSync(cloneCmd, { stdio: 'pipe' });\n spinner.stop('Repository cloned');\n } catch (error) {\n spinner.stop('Clone failed');\n telemetryData.errorType = 'clone_failed';\n throw new Error(`Failed to clone repository: ${(error as Error).message}`);\n }\n shouldCleanup = true;\n } else {\n workDir = resolved.path;\n }\n\n try {\n // Handle direct skill path\n if (resolved.type === 'skill') {\n let skillDestRoot: string;\n\n if (options.urlpath) {\n // --urlpath overrides: install directly at the specified path\n skillDestRoot = join(effectiveRoot, '.pk-agent', 'skills');\n } else {\n const storageOptions = [\n { value: 'project', label: 'Project', hint: `.pk-agent/skills/ in project root` },\n { value: 'user', label: 'User', hint: `~/.pk-agent/skills/ (available globally)` },\n { value: 'cancel', label: 'Cancel' },\n ];\n\n const location = await p.select({\n message: 'Where should skills be stored?',\n options: storageOptions,\n });\n\n if (p.isCancel(location) || location === 'cancel') {\n telemetryData.errorType = 'cancelled';\n telemetryData.success = false;\n p.outro('Cancelled');\n return;\n }\n\n skillDestRoot = location === 'user'\n ? join(homedir(), '.pk-agent', 'skills')\n : join(effectiveRoot, '.pk-agent', 'skills');\n }\n\n const result = await add(source, effectiveRoot, {\n force: options.force ?? false,\n skillDestRoot,\n });\n // Track installed skills (only for non-local sources)\n if (isTrackableSource) {\n const installed = result.skills.filter((s) => s.action === 'added' || s.action === 'overwritten');\n if (installed.length > 0) {\n telemetryData.skillsInstalled = installed.map((s) => s.name);\n }\n }\n telemetryData.success = true;\n printSummary(result);\n p.outro('Done');\n return;\n }\n\n // 2. Discover available items\n const { skills, agents } = await discoverItems(workDir);\n\n if (skills.length === 0 && agents.length === 0) {\n telemetryData.success = true;\n p.outro(chalk.gray('No skills or agents found in the source.'));\n return;\n }\n\n p.log.info(chalk.gray(`Found ${skills.length} skill(s), ${agents.length} agent(s)`));\n\n // 3. Handle --list mode\n if (options.list) {\n if (skills.length > 0) {\n const skillLines = skills.map((skill) => {\n const exists = existsSync(join(effectiveRoot, '.pk-agent', 'skills', skill.name));\n const marker = exists ? chalk.yellow(' (exists)') : '';\n const desc = skill.description ? `\\n ${chalk.gray(skill.description)}` : '';\n return ` ${chalk.cyan(skill.name)}${marker}${desc}`;\n });\n p.log.message(`${chalk.bold('Skills:')}\\n${skillLines.join('\\n')}`);\n }\n\n if (agents.length > 0) {\n const agentLines = agents.map((agent) => {\n const exists = existsSync(join(effectiveRoot, agent.path));\n const marker = exists ? chalk.yellow(' (exists)') : '';\n return ` ${chalk.cyan(agent.path)}${marker}`;\n });\n p.log.message(`${chalk.bold('Agents:')}\\n${agentLines.join('\\n')}`);\n }\n\n telemetryData.success = true;\n p.outro('Use --skill or --agent to install specific items');\n return;\n }\n\n // 4. Determine what to install\n let selectedSkills: string[] | undefined;\n let selectedAgents: string[] | undefined;\n\n if (options.skill || options.agent) {\n // Explicit selection via flags\n selectedSkills = options.skill;\n selectedAgents = options.agent;\n\n // Validate selections\n if (selectedSkills) {\n const availableSkillNames = skills.map((s) => s.name);\n for (const name of selectedSkills) {\n if (!availableSkillNames.includes(name)) {\n telemetryData.errorType = 'validation_failed';\n throw new Error(`Skill \"${name}\" not found. Available: ${availableSkillNames.join(', ')}`);\n }\n }\n }\n if (selectedAgents) {\n const availableAgentPaths = agents.map((a) => a.path);\n for (const path of selectedAgents) {\n if (!availableAgentPaths.includes(path)) {\n telemetryData.errorType = 'validation_failed';\n throw new Error(`Agent \"${path}\" not found. Available: ${availableAgentPaths.join(', ')}`);\n }\n }\n }\n } else if (!options.all) {\n // Interactive selection\n const selection = await promptSelection(skills, agents, effectiveRoot);\n if (!selection) {\n telemetryData.errorType = 'cancelled';\n telemetryData.success = false;\n p.outro('Cancelled');\n return;\n }\n selectedSkills = selection.selectedSkills;\n selectedAgents = selection.selectedAgents;\n\n if (selectedSkills.length === 0 && selectedAgents.length === 0) {\n telemetryData.success = true;\n p.outro('Nothing selected');\n return;\n }\n }\n // If --all, selectedSkills and selectedAgents remain undefined (install all)\n\n // 5. Determine storage location for skills and agents\n let skillDestRoot: string | undefined;\n let agentDestRoot: string | undefined;\n const hasSkillsToInstall = selectedSkills\n ? selectedSkills.length > 0\n : skills.length > 0;\n const hasAgentsToInstall = selectedAgents\n ? selectedAgents.length > 0\n : agents.length > 0;\n\n if (options.urlpath) {\n // --urlpath: skip prompts, install directly at specified path\n if (hasSkillsToInstall) {\n skillDestRoot = join(effectiveRoot, '.pk-agent', 'skills');\n }\n if (hasAgentsToInstall) {\n agentDestRoot = join(effectiveRoot, '.pk-agent', 'agents');\n }\n } else {\n // Interactive: prompt for storage location\n if (hasSkillsToInstall) {\n const storageOptions = [\n { value: 'project', label: 'Project', hint: `.pk-agent/skills/ in project root` },\n { value: 'user', label: 'User', hint: `~/.pk-agent/skills/ (available globally)` },\n { value: 'cancel', label: 'Cancel' },\n ];\n\n const location = await p.select({\n message: 'Where should skills be stored?',\n options: storageOptions,\n });\n\n if (p.isCancel(location) || location === 'cancel') {\n telemetryData.errorType = 'cancelled';\n telemetryData.success = false;\n p.outro('Cancelled');\n return;\n }\n\n if (location === 'project') {\n skillDestRoot = join(effectiveRoot, '.pk-agent', 'skills');\n } else if (location === 'user') {\n skillDestRoot = join(homedir(), '.pk-agent', 'skills');\n }\n }\n\n if (hasAgentsToInstall) {\n const storageOptions = [\n { value: 'project', label: 'Project', hint: `.pk-agent/agents/ in project root` },\n ...(effectiveRoot\n ? [{ value: 'user', label: 'User', hint: `~/.pk-agent/agents/ (available globally)` }]\n : []),\n { value: 'cancel', label: 'Cancel' },\n ];\n\n const location = await p.select({\n message: 'Where should agents be stored?',\n options: storageOptions,\n });\n\n if (p.isCancel(location) || location === 'cancel') {\n telemetryData.errorType = 'cancelled';\n telemetryData.success = false;\n p.outro('Cancelled');\n return;\n }\n\n if (location === 'project') {\n agentDestRoot = join(effectiveRoot, '.pk-agent', 'agents');\n } else if (location === 'user') {\n agentDestRoot = join(homedir(), '.pk-agent', 'agents');\n }\n }\n }\n\n // Install selected items\n const result = await add(source, effectiveRoot, {\n force: options.force ?? false,\n selectedSkills,\n selectedAgents,\n skillDestRoot,\n agentDestRoot,\n });\n\n // Update telemetry with results (only for non-local sources)\n if (isTrackableSource) {\n const installedSkills = result.skills\n .filter((s) => s.action === 'added' || s.action === 'overwritten')\n .map((s) => s.name);\n const installedAgents = result.agents\n .filter((a) => a.action === 'added' || a.action === 'overwritten')\n .map((a) => basename(a.path, '.pk-agent'));\n if (installedSkills.length > 0) {\n telemetryData.skillsInstalled = installedSkills;\n }\n if (installedAgents.length > 0) {\n telemetryData.agentsInstalled = installedAgents;\n }\n }\n telemetryData.success = true;\n\n printSummary(result);\n p.outro('Done');\n } finally {\n if (shouldCleanup) {\n rmSync(workDir, { recursive: true, force: true });\n }\n }\n } catch (error) {\n if (!telemetryData.errorType) {\n telemetryData.errorType = 'unknown';\n }\n p.outro(chalk.red(`Error: ${(error as Error).message}`));\n process.exit(1);\n } finally {\n // Capture telemetry\n telemetryData.durationMs = Date.now() - startTime;\n telemetry.captureAddCommand(telemetryData as AddCommandResult);\n }\n });\n\n return addCommand;\n}\n",
|
|
107
|
+
"import { Command } from 'commander';\r\nimport chalk from 'chalk';\r\nimport * as p from '@clack/prompts';\r\nimport matter from 'gray-matter';\r\nimport { writeFileSync, mkdirSync, existsSync } from 'fs';\r\nimport { join, resolve } from 'path';\r\nimport { homedir } from 'os';\r\nimport { MODELS } from '../generated/models.js';\nimport { parseAgentContent } from '../parser.js';\nimport { findProjectRoot } from '../utils/project.js';\nimport { ensurePkAgentDirs } from '../utils/pk-agent-dirs.js';\n\r\nconst DEFAULTS = {\n model: 'anthropic:claude-sonnet-4-5',\n version: '0.1.0',\n timeout: 300,\n maxSteps: 100,\n} as const;\n\r\ninterface CreateOptions {\r\n description: string;\r\n name: string;\r\n model: string;\r\n timeout: number;\r\n maxSteps: number;\r\n}\r\n\r\n/**\r\n * Derive a kebab-case agent filename from a free-text description.\r\n */\r\nexport function deriveAgentName(description: string): string {\r\n return description\r\n .toLowerCase()\r\n .slice(0, 60)\r\n .replace(/[^a-z0-9\\s-]/g, '')\r\n .trim()\r\n .replace(/\\s+/g, '-')\r\n .replace(/-+/g, '-')\r\n .replace(/^-|-$/g, '')\r\n .slice(0, 40)\r\n || 'my-agent';\r\n}\r\n\r\n/**\r\n * Build the YAML frontmatter object. Omits fields that match defaults.\r\n */\r\nexport function buildFrontmatter(opts: CreateOptions): Record<string, unknown> {\n const fm: Record<string, unknown> = {\n model: opts.model,\n description: opts.description,\n version: DEFAULTS.version,\n };\n if (opts.timeout !== DEFAULTS.timeout) fm.timeout = opts.timeout;\n if (opts.maxSteps !== DEFAULTS.maxSteps) fm.maxSteps = opts.maxSteps;\n return fm;\n}\n\r\n/**\r\n * Serialize frontmatter + instructions into the .pk-agent file format.\r\n */\r\nexport function serializeAgent(\r\n frontmatter: Record<string, unknown>,\r\n instructions: string,\r\n): string {\r\n const body = instructions.trim() ? `\\n${instructions.trim()}\\n` : '\\n';\r\n return matter.stringify(body, frontmatter);\r\n}\r\n\r\n/**\r\n * Build model selection options grouped by provider for the interactive prompt.\r\n */\r\nexport function buildModelOptions() {\r\n const providers: { value: string; label: string; hint: string }[] = [\r\n { value: 'anthropic', label: 'Anthropic', hint: 'Claude models' },\r\n { value: 'openai', label: 'OpenAI', hint: 'GPT models' },\r\n { value: 'openrouter', label: 'OpenRouter', hint: 'GLM, MiniMax, and more' },\r\n ];\r\n\r\n const modelsByProvider: Record<string, { value: string; label: string; hint: string }[]> = {};\r\n\r\n for (const [providerKey, models] of Object.entries(MODELS)) {\r\n if (providerKey === 'demo') continue;\r\n modelsByProvider[providerKey] = Object.entries(models).map(([modelId, info]) => {\r\n const caps: string[] = [];\r\n if (info.reasoning) caps.push('Reasoning');\r\n if (info.modalities.input.includes('image')) caps.push('Vision');\r\n if (info.toolCall) caps.push('Tools');\r\n const cost = info.cost.input === 0 ? 'Free'\r\n : info.cost.input < 1 ? '$'\r\n : info.cost.input < 5 ? '$$'\r\n : '$$$';\r\n return {\r\n value: `${providerKey}:${modelId}`,\r\n label: modelId,\r\n hint: `${info.name} [${caps.join(', ')}] ${cost}`,\r\n };\r\n });\r\n }\r\n\r\n return { providers, modelsByProvider };\r\n}\r\n\r\nexport function createCreateCommand(): Command {\r\n return new Command('create')\r\n .description('Create a new agent interactively')\r\n .option('--name <name>', 'Agent name (skips name prompt)')\r\n .option('--model <model>', 'Model override (skips model prompt)')\r\n .option('-y, --yes', 'Accept all defaults (only asks for description)')\r\n .action(async (flags: { name?: string; model?: string; yes?: boolean }) => {\n const projectRoot = findProjectRoot(process.cwd());\n ensurePkAgentDirs(projectRoot);\n\n p.intro(chalk.bold.blue('Create Agent'));\n\r\n // 1. Description\r\n const descResult = await p.text({\r\n message: 'What should this agent do?',\r\n placeholder: 'e.g., Search for AI news and post a digest to Slack',\r\n validate: (v) => {\r\n if (!v || v.trim().length === 0) return 'Description is required';\r\n if (v.trim().length < 5) return 'Please provide a more detailed description';\r\n return;\r\n },\r\n });\r\n if (p.isCancel(descResult)) { p.outro('Cancelled.'); return; }\r\n const description = (descResult as string).trim();\r\n\r\n // 2. Defaults shortcut\r\n let useDefaults = flags.yes === true;\r\n if (!useDefaults) {\r\n const confirmResult = await p.confirm({\r\n message: `Use defaults? (model: ${DEFAULTS.model}, timeout: ${DEFAULTS.timeout}s, maxSteps: ${DEFAULTS.maxSteps})`,\r\n initialValue: true,\r\n });\r\n if (p.isCancel(confirmResult)) { p.outro('Cancelled.'); return; }\r\n useDefaults = confirmResult as boolean;\r\n }\r\n\r\n const opts: CreateOptions = {\r\n description,\r\n name: flags.name || deriveAgentName(description),\r\n model: flags.model || DEFAULTS.model,\r\n timeout: DEFAULTS.timeout,\r\n maxSteps: DEFAULTS.maxSteps,\r\n };\r\n\r\n let instructionsBody = description;\r\n\r\n if (!useDefaults) {\r\n // 3. Name\r\n const nameResult = await p.text({\r\n message: 'Agent name (used as filename)',\r\n defaultValue: opts.name,\r\n placeholder: opts.name,\r\n validate: (v) => {\r\n if (!v || v.trim().length === 0) return 'Name is required';\r\n if (!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(v.trim())) {\r\n return 'Use lowercase letters, numbers, and hyphens (must start/end with alphanumeric)';\r\n }\r\n return;\r\n },\r\n });\r\n if (p.isCancel(nameResult)) { p.outro('Cancelled.'); return; }\r\n opts.name = (nameResult as string).trim();\r\n\r\n // 4. Model (provider -> model)\r\n if (!flags.model) {\r\n const modelOpts = buildModelOptions();\r\n\r\n const provResult = await p.select({\r\n message: 'Model provider',\r\n options: modelOpts.providers,\r\n initialValue: 'anthropic',\r\n });\r\n if (p.isCancel(provResult)) { p.outro('Cancelled.'); return; }\r\n const provider = provResult as string;\r\n\r\n const providerModels = modelOpts.modelsByProvider[provider];\r\n const defaultModel = provider === 'anthropic'\r\n ? 'anthropic:claude-sonnet-4-5'\r\n : providerModels[0]?.value;\r\n\r\n const modelResult = await p.select({\r\n message: 'Model',\r\n options: providerModels,\r\n initialValue: defaultModel,\r\n });\r\n if (p.isCancel(modelResult)) { p.outro('Cancelled.'); return; }\r\n opts.model = modelResult as string;\r\n }\r\n\r\n // 5. Timeout\r\n const timeoutResult = await p.text({\r\n message: 'Timeout (seconds)',\r\n defaultValue: String(DEFAULTS.timeout),\r\n placeholder: String(DEFAULTS.timeout),\r\n validate: (v) => {\r\n const n = parseInt(v);\r\n if (isNaN(n) || n <= 0) return 'Must be a positive number';\r\n return;\r\n },\r\n });\r\n if (p.isCancel(timeoutResult)) { p.outro('Cancelled.'); return; }\r\n opts.timeout = parseInt(timeoutResult as string);\r\n\r\n // 6. Max steps\r\n const stepsResult = await p.text({\r\n message: 'Max steps (tool calls)',\r\n defaultValue: String(DEFAULTS.maxSteps),\r\n placeholder: String(DEFAULTS.maxSteps),\r\n validate: (v) => {\r\n const n = parseInt(v);\r\n if (isNaN(n) || n <= 0) return 'Must be a positive integer';\r\n return;\r\n },\r\n });\r\n if (p.isCancel(stepsResult)) { p.outro('Cancelled.'); return; }\r\n opts.maxSteps = parseInt(stepsResult as string);\r\n\r\n // 7. Instructions body\r\n const instrResult = await p.select({\r\n message: 'Agent instructions (markdown body)',\r\n options: [\r\n { value: 'description', label: 'Use description as instructions', hint: 'Quick start' },\r\n { value: 'custom', label: 'Write custom instructions' },\r\n { value: 'empty', label: 'Leave empty (edit later)' },\r\n ],\r\n });\r\n if (p.isCancel(instrResult)) { p.outro('Cancelled.'); return; }\r\n\r\n if (instrResult === 'custom') {\r\n const customResult = await p.text({\r\n message: 'Instructions (markdown)',\r\n placeholder: 'You are an agent that...',\r\n });\r\n if (p.isCancel(customResult)) { p.outro('Cancelled.'); return; }\r\n instructionsBody = (customResult as string).trim();\r\n } else if (instrResult === 'empty') {\r\n instructionsBody = '';\r\n }\r\n }\r\n\r\n // 8. Storage location\r\n const locResult = await p.select({\r\n message: 'Where should the agent be saved?',\r\n options: [\r\n { value: 'project', label: 'Project', hint: `${projectRoot}/.pk-agent/agents/` },\r\n { value: 'user', label: 'User (global)', hint: '~/.pk-agent/agents/' },\r\n { value: 'custom', label: 'Custom path' },\r\n { value: 'cancel', label: 'Cancel' },\r\n ],\r\n });\r\n if (p.isCancel(locResult) || locResult === 'cancel') { p.outro('Cancelled.'); return; }\r\n\r\n let destDir: string;\r\n if (locResult === 'project') {\r\n destDir = join(projectRoot, '.pk-agent', 'agents');\r\n } else if (locResult === 'user') {\r\n destDir = join(homedir(), '.pk-agent', 'agents');\r\n } else {\r\n const pathResult = await p.text({\r\n message: 'Directory path',\r\n placeholder: './agents',\r\n validate: (v) => {\r\n if (!v || v.trim().length === 0) return 'Path is required';\r\n return;\r\n },\r\n });\r\n if (p.isCancel(pathResult)) { p.outro('Cancelled.'); return; }\r\n destDir = resolve((pathResult as string).trim());\r\n }\r\n\r\n // 9. Build and write\r\n const frontmatter = buildFrontmatter(opts);\r\n const fileContent = serializeAgent(frontmatter, instructionsBody);\r\n\r\n // Round-trip validation\r\n try {\r\n parseAgentContent(fileContent, opts.name);\r\n } catch (err) {\r\n p.log.error(`Generated file is invalid: ${(err as Error).message}`);\r\n p.outro(chalk.red('Failed.'));\r\n return;\r\n }\r\n\r\n const filePath = join(destDir, `${opts.name}.pk-agent`);\r\n\r\n if (existsSync(filePath)) {\r\n const overwrite = await p.confirm({\r\n message: `${filePath} already exists. Overwrite?`,\r\n initialValue: false,\r\n });\r\n if (p.isCancel(overwrite) || !overwrite) { p.outro('Cancelled.'); return; }\r\n }\r\n\r\n mkdirSync(destDir, { recursive: true });\r\n writeFileSync(filePath, fileContent, 'utf-8');\r\n\r\n p.log.success(`Created ${chalk.cyan(filePath)}`);\r\n p.log.info(chalk.gray(`Run it: pk-agent run ${filePath}`));\r\n p.log.info(chalk.gray('Add MCP servers, subagents, tools, or schedule by editing the file.'));\r\n p.outro(chalk.green('Done.'));\r\n });\r\n}\r\n",
|
|
108
|
+
"import { parseAgent, parseAgentContent, ConfigError } from '../parser';\r\nimport { connectMCP } from '../mcp';\r\nimport { runAgent, prepareAgentExecution, type PreparedAgentExecution } from '../runner';\r\nimport { Command } from 'commander';\r\nimport { logger, LogLevel } from '../utils/logger';\r\nimport { fetchRemoteAgent, isURL } from '../utils/remote-agent';\r\nimport { basename, resolve, dirname } from 'path';\r\nimport { PluginManager } from '../plugin';\r\nimport { existsSync } from 'fs';\r\nimport * as dotenv from 'dotenv';\r\nimport { resolveProjectContext } from '../utils/project';\nimport { resolveTimeout } from '../utils/config';\nimport { printLogo, type BrandingStyle } from '../utils/branding';\nimport { validateAgentEnvVars, formatEnvValidationError } from '../utils/env-validation';\nimport { telemetry, categorizeError, aggregateToolCalls, countSteps, parseModel } from '../telemetry';\nimport { AuthenticationError } from '../models';\nimport { prompt, packageVersion } from '../utils/cli-helpers';\nimport { writeTraceFile } from '../utils/trace';\nimport { ensurePkAgentProjectDirs, ensurePkAgentUserDirs } from '../utils/pk-agent-dirs';\nimport { sanitizeAgentName } from '../utils/names';\nimport { resolveAppConfig, applyAppConfigDefaultsToAgentConfig } from '../config/app-config';\n\r\nexport function createRunCommand(): Command {\r\n const cmd = new Command('run');\r\n\r\n cmd\r\n .argument('<file>', 'Agent file path or URL')\n .argument('[prompt...]', 'Optional prompt to append')\n .description('Run an AI agent from a local file or URL, optionally appending a prompt')\n .option('-q, --quiet', 'Suppress info messages (only show warnings and errors)')\r\n .option('-d, --debug', 'Enable debug mode with detailed logging and full error messages')\n .option('--audit', 'Show tool inputs/outputs live for auditing (disables spinners)')\n .option('--trace', 'Write an execution trace artifact to .pk-agent/runs/<timestamp>/trace.json (ASCII-only)')\n .option('--approve', 'Require approval before running risky tools (bash and filesystem write/edit)')\n .option('--bash-timeout-ms <ms>', 'Override bash tool timeout in milliseconds (also supports PK_AGENT_BASH_TIMEOUT_MS env var)')\n .option('--no-tty', 'Disable TUI output (spinners, badges) for non-interactive use')\n .option('--compact', 'Use compact single-line header instead of ASCII logo')\n .option('--timeout <seconds>', 'Maximum execution time in seconds (default: 300)', '300')\n .option('-C, --directory <path>', 'Run as if pk-agent was started in <path> instead of the current directory')\n .option('--env-file <path>', 'Path to custom .env file')\n .option('-m, --model <model>', 'Override the model specified in the agent file')\n .option('--json', 'Output result as JSON (implies --quiet --no-tty)')\n .option('--resume [sessionId]', 'Resume a previous session (optionally specify session ID)')\n .addHelpText('afterAll', () => {\n return [\n '',\n 'Examples:',\n ' pk-agent run agents/example.pk-agent',\n ' pk-agent run --audit --trace agents/example.pk-agent',\n ' PK_AGENT_AUDIT=1 pk-agent run agents/example.pk-agent',\n ' PowerShell: $env:PK_AGENT_AUDIT=1; pk-agent run agents/example.pk-agent',\n '',\n 'Notes:',\n ' --audit prints tool inputs/outputs live (redacted) and disables spinners.',\n ' --trace writes .pk-agent/runs/<timestamp>/trace.json (ASCII-only, redacted).',\n ' Use --bash-timeout-ms (or PK_AGENT_BASH_TIMEOUT_MS) to cap long bash commands.',\n '',\n ].join('\\n');\n })\n .action(async (file: string, promptArgs: string[], options: { quiet: boolean, debug: boolean, audit?: boolean, trace?: boolean, bashTimeoutMs?: string, tty?: boolean, noTty?: boolean, compact: boolean, timeout: string, directory?: string, envFile?: string, model?: string, json?: boolean, resume?: boolean | string }) => {\n const startTime = Date.now();\n let originalCwd: string | undefined;\n\r\n try {\r\n if (options.audit) {\n process.env.PK_AGENT_AUDIT = 'true';\n }\n if ((options as any).approve === true) {\n process.env.PK_AGENT_APPROVALS = 'true';\n }\n if (options.bashTimeoutMs) {\n const ms = parseInt(options.bashTimeoutMs, 10);\n if (isNaN(ms) || ms <= 0) {\n throw new Error('Invalid --bash-timeout-ms value. Must be a positive integer in milliseconds.');\n }\n process.env.PK_AGENT_BASH_TIMEOUT_MS = String(ms);\n }\n\r\n // Configure logger based on flags\r\n // --json implies --quiet and --no-tty\r\n const jsonMode = options.json === true;\r\n const effectiveQuiet = options.quiet || jsonMode;\r\n\r\n if (effectiveQuiet && options.debug) {\r\n throw new Error('Cannot use --quiet/--json and --debug together');\r\n }\r\n\r\n process.env.PK_AGENT_DEBUG = options.debug ? 'true' : 'false';\r\n\r\n const loggerConfig: { level?: LogLevel; enableDebug?: boolean; disableTUI?: boolean; audit?: boolean } = {};\r\n let quietMode = false;\r\n\r\n // Commander maps --no-tty to options.tty === false (noTty isn't guaranteed), so check both\n const disableTUI = options.audit === true || options.tty === false || options.noTty === true || (options as any)['no-tty'] === true || jsonMode;\n const approvalsEnabled = process.env.PK_AGENT_APPROVALS === 'true' || process.env.PK_AGENT_APPROVALS === '1';\n\n if (effectiveQuiet) {\n loggerConfig.level = LogLevel.WARN;\n quietMode = true;\n } else if (options.debug) {\n loggerConfig.level = LogLevel.DEBUG;\r\n loggerConfig.enableDebug = true;\r\n }\r\n if (options.audit) {\r\n loggerConfig.audit = true;\r\n }\r\n if (disableTUI) {\n process.env.NO_TTY = 'true';\n loggerConfig.disableTUI = true;\n // Switch to plain mode immediately so no spinner can start before configure()\n logger.forcePlainOutput();\n }\n if (approvalsEnabled) {\n // Avoid conflicting with interactive prompts.\n process.env.NO_TTY = 'true';\n loggerConfig.disableTUI = true;\n logger.forcePlainOutput();\n }\n logger.configure({ ...loggerConfig, ...(quietMode ? { quiet: true } : {}) });\n\r\n // Initialize telemetry (skip entirely if disabled to avoid async overhead)\r\n if (telemetry.isEnabled()) {\r\n await telemetry.init(packageVersion);\r\n }\r\n\r\n // Show ASCII logo (unless in quiet/json mode)\r\n if (!effectiveQuiet) {\r\n const brandingStyle: BrandingStyle = options.compact ? 'compact' : 'full';\r\n printLogo(brandingStyle);\r\n\r\n // Show first-run telemetry notice\r\n if (await telemetry.isFirstRun()) {\r\n logger.info('pk-agent collects anonymous usage data to improve the product.');\r\n logger.info('Set PK_AGENT_TELEMETRY_DISABLED=true to opt out.\\n');\r\n await telemetry.markFirstRunComplete();\r\n }\r\n }\r\n\r\n // Log startup time if debug\r\n if (options.debug) {\r\n logger.info(`Starting PK Agent at ${new Date().toISOString()}`);\r\n }\r\n\r\n // Parse CLI timeout value (will be used as override later)\r\n const timeoutWasExplicit = process.argv.includes('--timeout');\r\n const cliTimeoutSeconds = parseInt(options.timeout);\r\n if (isNaN(cliTimeoutSeconds) || cliTimeoutSeconds <= 0) {\r\n throw new Error('Invalid timeout value. Must be a positive number of seconds.');\r\n }\r\n\r\n // Parse MAX_STEPS env var if present (CLI override)\r\n const cliMaxSteps = process.env.MAX_STEPS ? parseInt(process.env.MAX_STEPS) : undefined;\r\n if (cliMaxSteps !== undefined && (isNaN(cliMaxSteps) || cliMaxSteps <= 0)) {\r\n throw new Error('Invalid MAX_STEPS value. Must be a positive integer.');\r\n }\r\n\r\n // Change working directory before resolving project context.\n // Precedence: CLI -C/--directory > PK_AGENT_DEFAULT_DIRECTORY env > config defaultDirectory.\n originalCwd = process.cwd();\n if (options.directory) {\n const targetDir = resolve(options.directory);\n if (!existsSync(targetDir)) {\n throw new Error(`Directory not found: ${options.directory}`);\n }\n logger.debug(`Changing working directory from ${originalCwd} to ${targetDir}`);\n process.chdir(targetDir);\n } else {\n const envDefaultDir = process.env.PK_AGENT_DEFAULT_DIRECTORY;\n const cfgDefaultDir = resolveAppConfig(process.cwd()).effective.defaultDirectory;\n const target = (envDefaultDir && envDefaultDir.trim()) ? envDefaultDir.trim() : cfgDefaultDir;\n if (target && target.trim()) {\n const abs = resolve(target.trim());\n if (existsSync(abs)) {\n logger.debug(`Changing working directory from ${originalCwd} to ${abs} (defaultDirectory)`);\n process.chdir(abs);\n }\n }\n }\n\n // Ensure expected directory layout exists for the effective working directory.\n // This also guarantees project root resolution prefers the run-from directory.\n ensurePkAgentUserDirs();\n ensurePkAgentProjectDirs(process.cwd());\n\n // Now detect project root from current directory (after potential cd)\n const projectContext = resolveProjectContext(process.cwd(), {\n ...(options.envFile && { envFile: options.envFile }),\n });\n logger.debug(`Using project root: ${projectContext.projectRoot}`);\n\r\n // Initialize storage and session manager (skip in JSON/headless mode - not needed)\r\n let sessionManager;\r\n if (!jsonMode) {\r\n try {\r\n const [{ initStorage }, { SessionManager }] = await Promise.all([\r\n import('../storage/index.js'),\r\n import('../session/index.js')\r\n ]);\r\n\r\n await initStorage(projectContext.projectRoot);\r\n sessionManager = new SessionManager();\r\n\r\n logger.debug('Session storage initialized');\r\n } catch (storageError) {\r\n logger.warn(`Failed to initialize session storage: ${(storageError as Error).message}`);\r\n }\r\n } else {\r\n logger.debug('Session storage skipped (JSON mode)');\r\n }\r\n\r\n // Load environment variables from resolved env file\n if (existsSync(projectContext.envFile)) {\n logger.debug(`Loading environment from: ${projectContext.envFile}`);\n dotenv.config({ path: projectContext.envFile, quiet: true });\n } else if (options.envFile) {\n // If explicitly specified but not found, error\r\n throw new Error(`Environment file not found: ${options.envFile}`);\r\n } else {\r\n logger.debug(`No .env file found at ${projectContext.envFile}, using system environment variables`);\r\n }\r\n\r\n // Join additional prompt arguments if provided\n const additionalPrompt = promptArgs.length > 0 ? promptArgs.join(' ') : null;\n\n // Resolve app-level defaults (env > project config > user config > built-in defaults).\n const appCfg = resolveAppConfig(projectContext.projectRoot);\n\n // Apply app defaults for CLI behavior when flags are not present.\n if (!options.audit && appCfg.effective.defaultAudit) {\n options.audit = true;\n process.env.PK_AGENT_AUDIT = 'true';\n }\n if ((options as any).approve !== true && appCfg.effective.defaultApprovals) {\n process.env.PK_AGENT_APPROVALS = 'true';\n }\n if (!options.trace && appCfg.effective.defaultTrace) {\n options.trace = true;\n }\n\n // If defaults enabled audit/approvals, ensure we do not start spinners.\n if (options.audit === true || process.env.PK_AGENT_APPROVALS === 'true' || process.env.PK_AGENT_APPROVALS === '1') {\n process.env.NO_TTY = 'true';\n logger.forcePlainOutput();\n logger.configure({\n audit: options.audit === true,\n disableTUI: true,\n });\n }\n\n let agent;\n\r\n // Check if input is a URL\r\n if (isURL(file)) {\r\n // Validate HTTPS only\r\n if (!file.startsWith('https://')) {\r\n throw new Error('Only HTTPS URLs are allowed for security reasons');\r\n }\r\n\r\n // Validate .pk-agent extension\r\n if (!file.endsWith('.pk-agent')) {\r\n throw new Error('Remote agents must have .pk-agent extension');\r\n }\r\n\r\n // Trusted domains that skip the security prompt\r\n const trustedDomains = ['pk-agent.io', 'www.pk-agent.io'];\n const urlHost = new URL(file).hostname;\n const isTrustedDomain = trustedDomains.includes(urlHost);\n const interactivePromptAvailable =\n jsonMode !== true &&\n options.tty !== false &&\n options.noTty !== true &&\n (options as any)['no-tty'] !== true &&\n process.stdin.isTTY === true &&\n process.stdout.isTTY === true;\n\n let content: string;\n\n if (isTrustedDomain) {\n // Trusted domain - fetch directly without prompt\n logger.info('Fetching agent from trusted source...');\n content = await fetchRemoteAgent(file);\n } else {\n if (!interactivePromptAvailable) {\n throw new Error(\n 'Untrusted remote agents require interactive confirmation. Run without --json/--no-tty and respond to the prompt, or use a trusted domain.'\n );\n }\n\n // Show warning and prompt for untrusted domains\n console.log('\\nWARNING: You are about to execute an agent from:');\n console.log(file);\n console.log('\\nOnly continue if you trust the source and have audited the agent.');\n\r\n const answer = await prompt('[p]review / [y]es / [N]o: ');\r\n\r\n if (answer === 'p' || answer === 'preview') {\r\n // Fetch and show content\r\n logger.info('Fetching agent for preview...');\r\n content = await fetchRemoteAgent(file);\r\n console.log('\\n--- Agent Content ---');\r\n console.log(content);\r\n console.log('--- End of Content ---\\n');\r\n\r\n // Ask again after preview\r\n const confirmAnswer = await prompt('Execute this agent? [y]es / [N]o: ');\r\n if (confirmAnswer !== 'y' && confirmAnswer !== 'yes') {\r\n console.log('Aborted.');\r\n process.exit(0);\r\n }\r\n } else if (answer === 'y' || answer === 'yes') {\r\n // Fetch content\r\n logger.info('Fetching remote agent...');\r\n content = await fetchRemoteAgent(file);\r\n } else {\r\n // Default to No\r\n console.log('Aborted.');\r\n process.exit(0);\r\n }\r\n }\r\n\r\n // Parse agent from content\r\n const agentName = basename(file).replace(/\\.pk-agent$/, '');\r\n agent = parseAgentContent(content!, agentName);\r\n } else {\n // Parse agent specification from a local file.\n // Auto-append .pk-agent extension if not specified\n let agentFile = file;\n if (!file.endsWith('.pk-agent') && !existsSync(file)) {\n const withExt = `${file}.pk-agent`;\r\n if (existsSync(withExt)) {\r\n agentFile = withExt;\r\n }\r\n }\n agent = await parseAgent(agentFile);\n }\n\n // Apply app defaults to agent config if fields are missing.\n // This keeps precedence intuitive: agent YAML remains authoritative when set.\n applyAppConfigDefaultsToAgentConfig(agent.config, appCfg);\n\n // Keep additional prompt separate (don't concatenate)\n if (additionalPrompt && options.debug) {\n logger.info(`Additional user prompt: ${additionalPrompt}`);\n }\n\r\n // Override model if specified via CLI\r\n if (options.model) {\r\n // Validate model format (provider:model or provider:model:env)\r\n const modelParts = options.model.split(':');\r\n if (modelParts.length < 2) {\r\n throw new Error(`Invalid model format '${options.model}'. Expected format: provider:model or provider:model:env (e.g., openai:gpt-5, anthropic:claude-sonnet-4-0:dev)`);\r\n }\r\n\r\n const [provider] = modelParts;\r\n const validProviders = ['anthropic', 'openai', 'openrouter', 'demo'];\r\n if (!validProviders.includes(provider)) {\r\n throw new Error(`Invalid model provider '${provider}'. Supported providers: ${validProviders.join(', ')}`);\r\n }\r\n\r\n const originalModel = agent.config.model;\r\n agent.config.model = options.model;\r\n logger.info(`Model override: ${originalModel} -> ${options.model}`);\r\n\r\n // Warn if provider-specific options don't match the new provider\r\n if (agent.config.openai && provider !== 'openai') {\r\n logger.warn(`Warning: OpenAI-specific options in config will be ignored with ${provider} model`);\r\n }\r\n }\r\n\r\n // Pre-flight environment variable validation\r\n const envValidation = validateAgentEnvVars(agent.config);\r\n if (!envValidation.valid) {\r\n logger.error(formatEnvValidationError(envValidation));\r\n process.exit(1);\r\n }\r\n if (envValidation.missingOptional.length > 0) {\r\n logger.warn(formatEnvValidationError(envValidation));\r\n }\r\n\r\n // Determine effective timeout (precedence: CLI > agent YAML > default)\r\n const effectiveTimeoutSeconds = resolveTimeout(\r\n cliTimeoutSeconds,\r\n timeoutWasExplicit,\r\n agent.config.timeout\r\n );\r\n const timeoutMs = effectiveTimeoutSeconds * 1000;\r\n\r\n // Connect to MCP servers if configured\r\n // Pass the agent file's directory as base path for resolving relative paths\r\n // Since we've already changed directory, resolve the file path from the new CWD\r\n const agentFilePath = !isURL(file) ? resolve(file) : undefined;\r\n const mcpBasePath = agentFilePath ? dirname(agentFilePath) : undefined;\r\n\r\n // R3-3: Handle --resume flag (after agentFilePath is resolved)\r\n let resumeSnapshot: import('../session/conversation-snapshot').ConversationSnapshot | undefined;\r\n if (options.resume) {\r\n try {\r\n const { findLatestSnapshot, loadSnapshot } = await import('../session/conversation-snapshot.js');\r\n\r\n if (typeof options.resume === 'string') {\n // Resume specific session ID\n const sanitizedName = sanitizeAgentName(agent.name);\n const sessionDir = `${options.resume}-${sanitizedName}`;\n const snapshot = await loadSnapshot(sessionDir);\n if (snapshot) {\n resumeSnapshot = snapshot;\n } else {\n logger.warn(`No snapshot found for session ${options.resume}. Run 'pk-agent sessions' to see available sessions.`);\r\n }\r\n } else {\r\n // Resume most recent session for this agent\r\n const agentFile = agentFilePath || resolve(file);\r\n const result = await findLatestSnapshot(agentFile);\r\n if (result) {\r\n resumeSnapshot = result.snapshot;\r\n } else {\r\n logger.warn(\"No previous session found to resume. Run 'pk-agent sessions' to see available sessions.\");\r\n }\r\n }\r\n\r\n if (resumeSnapshot && !effectiveQuiet) {\r\n const age = new Date(resumeSnapshot.timestamp).toLocaleString();\r\n logger.info(` Resuming session ${resumeSnapshot.sessionID} from ${age}`);\r\n logger.info(` ${resumeSnapshot.messageCount} messages, ${resumeSnapshot.compactionCount} compactions`);\r\n }\r\n } catch (error) {\r\n logger.warn(`Failed to load resume session: ${(error as Error).message}`);\r\n }\r\n }\r\n // Start MCP connection without awaiting - let it run concurrently with preparation\r\n // Fatal errors (missing required env vars) are caught when we await below\r\n const mcpPromise = connectMCP(agent.config.mcpServers, options.debug, mcpBasePath);\r\n let mcp: Awaited<ReturnType<typeof connectMCP>>;\r\n\r\n // Create abort controller for timeout\r\n const abortController = new AbortController();\r\n let wasInterrupted = false; // Track if abort was from user interrupt vs timeout\r\n const timeoutId = setTimeout(() => {\r\n abortController.abort();\r\n }, timeoutMs);\r\n\r\n // Handle Ctrl-C gracefully\r\n let sigintCount = 0;\r\n const sigintHandler = () => {\r\n sigintCount++;\r\n\r\n if (sigintCount === 1) {\r\n console.log('\\nInterrupting...');\r\n wasInterrupted = true; // Mark as user interrupt\r\n abortController.abort(); // Trigger existing abort mechanism\r\n\r\n // Give cleanup 2 seconds, then force exit if still hanging\r\n setTimeout(() => {\r\n console.log('\\nForce exiting...');\r\n process.exit(130);\r\n }, 2000);\r\n } else {\r\n // Second Ctrl-C - immediate exit (if cleanup is taking too long)\r\n console.log('\\nForce exiting...');\r\n process.exit(130);\r\n }\r\n };\r\n process.on('SIGINT', sigintHandler);\r\n\r\n // Initialize plugin manager only when plugin directories exist AND not in JSON mode\r\n // (plugins are for interactive lifecycle events, not headless runs)\r\n let pluginManager: PluginManager | null = null;\r\n if (!jsonMode && projectContext.pluginDirs.length > 0) {\r\n try {\r\n pluginManager = new PluginManager();\r\n await pluginManager.loadPlugins(projectContext.pluginDirs);\r\n logger.debug(`Loading plugins from: ${projectContext.pluginDirs.join(', ')}`);\r\n } catch (pluginError) {\r\n logger.warn(`Failed to initialize plugins: ${(pluginError as Error).message}`);\r\n }\r\n }\r\n\r\n // Emit agent:start event for plugins\r\n if (pluginManager) {\r\n await pluginManager.emitAgentStart({\r\n agent: {\r\n name: agent.name,\r\n model: agent.config.model,\r\n ...(agent.config.description && { description: agent.config.description }),\r\n filePath: file,\r\n },\r\n isSubAgent: false,\r\n });\r\n }\r\n\r\n // Start capturing console output for plugins\r\n logger.startCapture();\r\n\r\n /**\r\n * Prepare execution context BEFORE running the agent.\r\n *\r\n * This serves two purposes:\r\n * 1. Display metadata (tool count, session ID) to the user before execution starts\r\n * 2. Avoid duplicate preparation work by passing the prepared context to runAgent\r\n *\r\n * The preparation includes expensive operations:\r\n * - MCP tool discovery and validation\r\n * - Plugin loading and initialization\r\n * - Session management setup\r\n *\r\n * By preparing once and reusing, we avoid doing this work twice.\r\n */\r\n const preparedExecution: PreparedAgentExecution = await prepareAgentExecution({\r\n agent,\r\n mcpClients: [], // Empty - actual clients come via mcpClientsPromise\r\n mcpClientsPromise: mcpPromise,\r\n agentFilePath,\r\n cliMaxSteps,\r\n sessionManager,\r\n projectContext: { projectRoot: projectContext.projectRoot, cwd: process.cwd() },\r\n userPrompt: additionalPrompt || undefined,\r\n abortSignal: abortController.signal,\r\n verbose: options.debug\r\n });\r\n\r\n // Resolve MCP connections (already completed inside prepareAgentExecution,\r\n // but we need the reference for runAgent's signature and cleanup)\r\n try {\r\n mcp = await mcpPromise;\r\n } catch (mcpError: any) {\r\n if (mcpError.fatal || mcpError.message?.includes('Missing required environment variables')) {\r\n process.exit(1);\r\n }\r\n throw mcpError;\r\n }\r\n\r\n // Display agent metadata in clean format\r\n if (!effectiveQuiet) {\r\n logger.separator();\r\n const metadataLines = [\r\n `Agent: ${agent.name}`,\r\n `Model: ${agent.config.model}`,\r\n ];\r\n if (agent.description) {\r\n metadataLines.push(`Description: ${agent.description}`);\r\n }\r\n // Count available tools from prepared execution (this is why we prepare early)\r\n const toolCount = Object.keys(preparedExecution.tools).length;\r\n metadataLines.push(`Tools: ${toolCount} available`);\r\n logger.metadata(metadataLines);\r\n logger.separator();\r\n }\r\n\r\n // Run the agent with timeout\r\n let result: any;\r\n try {\r\n if (agentFilePath && options.debug) {\r\n logger.debug(`[Main] Passing agent file path to runner: ${agentFilePath}`);\r\n }\r\n result = await runAgent(\n agent,\n mcp,\n options.debug,\n abortController.signal,\n startTime,\n options.debug,\n agentFilePath,\n cliMaxSteps,\n sessionManager,\n { projectRoot: projectContext.projectRoot, cwd: process.cwd() },\n additionalPrompt || undefined,\n preparedExecution,\n effectiveQuiet,\n resumeSnapshot\n );\n\n if (options.trace || options.audit) {\n // Do not include any LLM content in the trace artifact.\n writeTraceFile(projectContext.projectRoot, result.toolCallTraces ?? []);\n }\n\n if (!result.hasTextOutput) {\n logger.warn('Agent completed without producing a final response.');\n }\n\r\n if (result.finishReason && result.finishReason !== 'stop') {\r\n if (result.finishReason === 'unknown') {\r\n logger.warn('Agent finished without reporting a reason; output may be incomplete.');\r\n } else {\r\n logger.warn(`Agent stopped with finish reason: ${result.finishReason}. Output may be incomplete.`);\r\n }\r\n }\r\n } catch (error: unknown) {\r\n if (abortController.signal.aborted || (error as Error).name === 'AbortError') {\r\n if (wasInterrupted) {\r\n // User pressed Ctrl-C - clean exit with standard interrupt code\r\n if (!jsonMode) {\r\n logger.info('Agent execution interrupted by user.');\r\n }\r\n // Capture telemetry for user abort\r\n telemetry.captureExecution({\r\n ...parseModel(agent.config.model),\r\n durationMs: Date.now() - startTime,\r\n inputTokens: 0,\r\n outputTokens: 0,\r\n success: false,\r\n errorType: 'user_abort',\r\n });\r\n await telemetry.shutdown();\r\n if (jsonMode) {\r\n console.log(JSON.stringify({\r\n success: false,\r\n error: { code: 'USER_ABORT', message: 'Agent execution interrupted by user' },\r\n }));\r\n }\r\n process.exit(130);\r\n } else {\r\n // Actual timeout\r\n if (!jsonMode) {\r\n logger.error(`\r\nEXECUTION TIMEOUT\r\n\r\nAgent execution timed out after ${effectiveTimeoutSeconds} seconds (${Math.floor(effectiveTimeoutSeconds / 60)} minutes).\r\n\r\nThe task may require more time to complete. Try one of these solutions:\r\n\r\n1. Add timeout to your agent YAML file:\r\n timeout: 600 # 10 minutes\r\n timeout: 1200 # 20 minutes\r\n\r\n2. Or increase timeout using --timeout flag:\r\n pk-agent run --timeout 600 ${file} (10 minutes)\r\n pk-agent run --timeout 1200 ${file} (20 minutes)\r\n\r\n3. Break your task into smaller sub-agents (see docs on subagents)\r\n\r\n4. Optimize your agent to use fewer tool calls\r\n\r\nNote: Individual tool calls have their own timeouts (e.g., bash defaults to 120000ms).\r\nIf you see \"bash tool terminated command after exceeding timeout ...\", increase it via:\r\n tools:\r\n bash:\r\n timeout: 600000\r\nOr run with:\r\n pk-agent run --bash-timeout-ms 600000 ${file}\r\n\r\nCurrent timeout: ${effectiveTimeoutSeconds}s`);\r\n }\r\n // Capture telemetry for timeout\r\n telemetry.captureExecution({\r\n ...parseModel(agent.config.model),\r\n durationMs: Date.now() - startTime,\r\n inputTokens: 0,\r\n outputTokens: 0,\r\n success: false,\r\n errorType: 'timeout',\r\n });\r\n await telemetry.shutdown();\r\n if (jsonMode) {\r\n console.log(JSON.stringify({\r\n success: false,\r\n error: { code: 'TIMEOUT', message: `Agent execution timed out after ${effectiveTimeoutSeconds}s` },\r\n }));\r\n }\r\n process.exit(1);\r\n }\r\n }\r\n throw error;\r\n } finally {\r\n clearTimeout(timeoutId);\r\n process.off('SIGINT', sigintHandler);\r\n }\r\n\r\n // Stop capturing and get console output\r\n const consoleOutput = logger.stopCapture();\r\n\r\n // Emit plugin event for agent completion\r\n if (pluginManager) {\r\n try {\r\n const duration = startTime ? (Date.now() - startTime) / 1000 : 0;\r\n // agentFilePath already resolved before directory change\r\n\r\n await pluginManager.emitAgentComplete({\r\n agent: {\r\n name: agent.name,\r\n model: agent.config.model,\r\n ...(agent.description && { description: agent.description }),\r\n ...(agentFilePath && { filePath: agentFilePath })\r\n },\r\n result: {\r\n text: result.text || '',\r\n duration,\r\n tokens: result.usage?.totalTokens,\r\n toolCalls: result.toolCallCount || 0,\r\n ...(result.toolCallTraces && { toolCallTraces: result.toolCallTraces }),\r\n ...(result.finishReason && { finishReason: result.finishReason }),\r\n ...(result.finishReasons && { finishReasons: result.finishReasons }),\r\n hasTextOutput: result.hasTextOutput\r\n },\r\n isSubAgent: false,\r\n consoleOutput\r\n });\r\n } catch (pluginError) {\r\n // Don't fail the agent execution if plugins fail\r\n logger.warn(`Plugin event error: ${(pluginError as Error).message}`);\r\n }\r\n }\r\n\r\n // Capture telemetry for successful execution\r\n telemetry.captureExecution({\r\n ...parseModel(agent.config.model),\r\n durationMs: Date.now() - startTime,\r\n inputTokens: result.usage?.inputTokens ?? 0,\r\n outputTokens: result.usage?.outputTokens ?? 0,\r\n success: true,\r\n toolCalls: aggregateToolCalls(result.toolCallTraces),\r\n steps: countSteps(result.toolCallTraces),\r\n\r\n // Performance & Reliability\r\n finishReason: result.finishReason,\r\n hasTextOutput: result.hasTextOutput,\r\n\r\n // Feature Adoption\r\n features: {\r\n mcpServersCount: Object.keys(agent.config.mcpServers || {}).length,\r\n subagentsConfigured: agent.config.subagents?.length ?? 0,\r\n skillsUsed: result.toolCallTraces?.some((t: { name: string }) => t.name.startsWith('tools__skill')) ?? false,\r\n mode: 'cli' as const,\r\n },\r\n\r\n // Configuration Patterns\r\n config: {\r\n timeoutCustom: timeoutWasExplicit || (agent.config.timeout !== undefined),\r\n maxStepsCustom: cliMaxSteps !== undefined || (agent.config.maxSteps !== undefined),\r\n quietMode: options.quiet,\r\n debugMode: options.debug,\r\n },\r\n });\r\n\r\n // Restore original working directory if changed.\n if (originalCwd && originalCwd !== process.cwd()) {\n process.chdir(originalCwd);\n logger.debug(`Restored working directory to ${originalCwd}`);\n }\n\r\n // Shutdown telemetry before exit\r\n await telemetry.shutdown();\r\n\r\n // Output JSON result if --json mode\r\n if (jsonMode) {\r\n const duration = Date.now() - startTime;\r\n const jsonOutput = {\r\n success: true,\r\n result: {\r\n text: result.text || '',\r\n ...(result.finishReason && { finishReason: result.finishReason }),\r\n duration,\r\n ...(result.usage && { tokens: { input: result.usage.inputTokens || 0, output: result.usage.outputTokens || 0 } }),\r\n toolCalls: result.toolCallCount || 0,\r\n },\r\n };\r\n console.log(JSON.stringify(jsonOutput));\r\n }\r\n\r\n // Exit successfully after agent completes\r\n process.exit(0);\r\n } catch (error) {\r\n // Restore original working directory if changed.\n if (originalCwd && originalCwd !== process.cwd()) {\n process.chdir(originalCwd);\n }\n\r\n // Helper to output JSON error and exit\r\n const outputJsonError = (code: string, message: string) => {\r\n if (options.json) {\r\n console.log(JSON.stringify({\r\n success: false,\r\n error: { code, message },\r\n }));\r\n }\r\n };\r\n\r\n // Capture telemetry for startup errors (auth, config) or execution errors\r\n if (error instanceof AuthenticationError) {\r\n telemetry.captureStartupError({\r\n type: 'auth',\r\n provider: error.provider,\r\n });\r\n await telemetry.shutdown();\r\n\r\n if (options.json) {\r\n outputJsonError('AUTH_ERROR', error.message);\r\n } else {\r\n console.error(`\\n[ERROR] ${error.message}`);\r\n console.error('');\r\n console.error('To authenticate, run:');\r\n console.error(' pk-agent auth login');\r\n console.error('');\r\n console.error('Or set your API key:');\r\n console.error(` export ${error.envVar}='your-key-here'`);\r\n console.error('');\r\n console.error('For more options: pk-agent auth --help');\r\n }\r\n process.exit(1);\r\n }\r\n\r\n if (error instanceof ConfigError) {\r\n telemetry.captureStartupError({\r\n type: 'config',\r\n field: error.field,\r\n issue: error.issue,\r\n });\r\n await telemetry.shutdown();\r\n\r\n if (options.json) {\r\n outputJsonError('CONFIG_ERROR', error.message);\r\n } else {\r\n logger.error('Error', error);\r\n }\r\n process.exit(1);\r\n }\r\n\r\n // For other errors, use the execution event\r\n const errorType = categorizeError(error);\r\n telemetry.captureExecution({\r\n provider: 'unknown',\r\n modelName: 'unknown',\r\n durationMs: Date.now() - startTime,\r\n inputTokens: 0,\r\n outputTokens: 0,\r\n success: false,\r\n ...(errorType && { errorType }),\r\n });\r\n await telemetry.shutdown();\r\n\r\n if (options.json) {\r\n outputJsonError(errorType ?? 'EXECUTION_ERROR', (error as Error).message);\r\n } else {\r\n logger.error('Error', error as Error);\r\n }\r\n process.exit(1);\r\n }\r\n });\r\n\r\n return cmd;\r\n}\r\n",
|
|
109
|
+
"import { glob } from 'glob';\nimport { homedir, tmpdir } from 'os';\nimport { join, dirname, extname } from 'path';\nimport { pathToFileURL } from 'url';\nimport { stat, writeFile, rm } from 'fs/promises';\nimport * as esbuild from 'esbuild-wasm';\nimport { createHash } from 'crypto';\nimport type { AgentCompleteEvent, AgentStartEvent, PluginHandlers } from './types';\nimport { logger } from '../utils/logger';\n\n// Global initialization state for esbuild-wasm (shared across all instances)\nlet esbuildInitialized = false;\n\nasync function initializeEsbuild(): Promise<void> {\n if (!esbuildInitialized) {\n // In Node.js, esbuild-wasm will automatically find the WASM binary\n // from the installed package when an empty object is provided\n await esbuild.initialize({});\n esbuildInitialized = true;\n }\n}\n\nexport class PluginManager {\n private plugins: Array<{ path: string; handlers: PluginHandlers }> = [];\n\n async loadPlugins(customDirs?: string[]): Promise<void> {\n // Define plugin search paths\n // Use forward slashes for glob compatibility on Windows (path.join uses backslashes)\n const pluginPaths = customDirs && customDirs.length > 0\n ? customDirs.map(dir => join(dir, '*.{ts,js}').replace(/\\\\/g, '/'))\n : [\n './.pk-agent/plugins/*.{ts,js}',\n join(homedir(), '.pk-agent/plugins/*.{ts,js}').replace(/\\\\/g, '/')\n ];\n\n for (const pattern of pluginPaths) {\n try {\n const files = await glob(pattern, { absolute: true });\n\n for (const file of files) {\n try {\n let module: any;\n const ext = extname(file);\n\n if (ext === '.ts') {\n // Initialize esbuild-wasm if needed\n await initializeEsbuild();\n\n // TypeScript: Bundle with esbuild-wasm and write to temp file\n const result = await esbuild.build({\n entryPoints: [file],\n bundle: true,\n platform: 'node',\n format: 'esm',\n target: 'node18',\n sourcemap: 'inline',\n absWorkingDir: dirname(file),\n write: false,\n external: ['node:*']\n });\n\n const code = result.outputFiles[0].text;\n // Create a unique temp file name based on the original file path\n const hash = createHash('md5').update(file).digest('hex').substring(0, 8);\n const tempFile = join(tmpdir(), `pk-agent-plugin-${hash}.mjs`);\n\n // Write the compiled code to temp file\n await writeFile(tempFile, code);\n\n try {\n // Import from the temp file\n const tempUrl = pathToFileURL(tempFile).href + '?t=' + Date.now();\n module = await import(tempUrl);\n } finally {\n // Clean up temp file\n await rm(tempFile, { force: true }).catch(() => { });\n }\n } else {\n // JavaScript: Dynamic import with cache busting\n const fileStat = await stat(file);\n const url = pathToFileURL(file).href + '?v=' + fileStat.mtimeMs;\n module = await import(url);\n }\n\n const plugin = module.default;\n\n // Validate it's an object with handler functions\n if (plugin && typeof plugin === 'object') {\n this.plugins.push({ path: file, handlers: plugin });\n logger.debug(`Loaded plugin: ${file}`);\n } else {\n logger.warn(`Invalid plugin format in ${file}: must export default object with event handlers`);\n }\n } catch (error) {\n logger.warn(`Failed to load plugin ${file}: ${(error as Error).message}`);\n }\n }\n } catch (error) {\n // Glob pattern might not match anything, that's okay\n if ((error as any).code !== 'ENOENT') {\n logger.debug(`Plugin search path ${pattern} not found or inaccessible`);\n }\n }\n }\n\n if (this.plugins.length > 0) {\n logger.info(`Loaded ${this.plugins.length} plugin(s)`);\n }\n }\n\n async emitAgentComplete(event: AgentCompleteEvent): Promise<void> {\n for (const { path, handlers } of this.plugins) {\n if (handlers['agent:complete']) {\n const pluginName = path.split('/').pop() || path;\n try {\n await handlers['agent:complete'](event);\n logger.info(`Plugin '${pluginName}' executed successfully`);\n } catch (error) {\n logger.info(`Plugin '${pluginName}' failed: ${(error as Error).message}`);\n logger.warn(`Plugin error in ${path}: ${(error as Error).message}`);\n }\n }\n }\n }\n async emitAgentStart(event: AgentStartEvent): Promise<void> {\n for (const { path, handlers } of this.plugins) {\n if (handlers['agent:start']) {\n const pluginName = path.split('/').pop() || path;\n try {\n await handlers['agent:start'](event);\n } catch (error) {\n logger.warn(`Plugin '${pluginName}' agent:start failed: ${(error as Error).message}`);\n }\n }\n }\n }\n}\n\n// Export types for plugin authors\nexport type { AgentCompleteEvent, AgentStartEvent, PluginHandlers, Plugin } from './types';",
|
|
110
|
+
"import { mkdirSync, writeFileSync } from 'fs';\nimport { join } from 'path';\nimport type { ToolCallTrace } from '../plugin/types';\nimport { redactForTrace } from './redaction';\n\nexport interface PersistedTraceEntry {\n name: string;\n type: 'tool' | 'subagent';\n startTimeUtc: string;\n durationMs: number;\n success: boolean;\n input: string;\n output: string;\n}\n\nfunction defaultRunId(now: Date): string {\n // Example: 2026-02-10-03-55-12Z\n return now\n .toISOString()\n .replace(/\\..+Z$/, 'Z')\n .replace(/:/g, '-')\n .replace('T', '-');\n}\n\nexport function writeTraceFile(projectRoot: string, traces: ToolCallTrace[], runId?: string): string | null {\n const filtered = (traces ?? []).filter((t): t is ToolCallTrace & { type: 'tool' | 'subagent' } => t.type === 'tool' || t.type === 'subagent');\n if (filtered.length === 0) return null;\n\n const dirName = runId && runId.trim() ? runId.trim() : defaultRunId(new Date());\n const runsDir = join(projectRoot, '.pk-agent', 'runs', dirName);\n mkdirSync(runsDir, { recursive: true });\n\n const entries: PersistedTraceEntry[] = filtered.map((t) => {\n const output = (t as any).output;\n return {\n name: t.name,\n type: t.type,\n startTimeUtc: new Date(t.startTime).toISOString(),\n durationMs: t.duration,\n success: t.success !== false,\n input: redactForTrace(t.input),\n output: redactForTrace(output),\n };\n });\n\n const tracePath = join(runsDir, 'trace.json');\n writeFileSync(tracePath, JSON.stringify(entries, null, 2), 'utf8');\n return tracePath;\n}\n",
|
|
111
|
+
"import { Command } from 'commander';\nimport { glob } from 'glob';\nimport { readFileSync } from 'fs';\nimport { resolve } from 'path';\nimport { findSecretMatches, maskSecret } from '../utils/redaction';\n\nfunction computeLineCol(text: string, index: number): { line: number; col: number } {\n let line = 1;\n let col = 1;\n for (let i = 0; i < text.length && i < index; i++) {\n if (text[i] === '\\n') {\n line++;\n col = 1;\n } else {\n col++;\n }\n }\n return { line, col };\n}\n\nexport function createLintCommand(): Command {\n const cmd = new Command('lint')\n .description('Scan .pk-agent files for hardcoded secrets and other hazards')\n .argument('[path]', 'File or directory to lint', '.')\n .option('--fail-on-warn', 'Exit non-zero if any warnings are found', true)\n .action(async (pathArg: string, options: { failOnWarn: boolean }) => {\n const absolute = resolve(pathArg);\n const isFile = absolute.toLowerCase().endsWith('.pk-agent');\n const files = isFile\n ? [absolute]\n : await glob('**/*.pk-agent', {\n cwd: absolute,\n absolute: true,\n ignore: ['**/node_modules/**', '**/dist/**', '**/.git/**'],\n });\n if (!files.length) {\n process.stderr.write('No .pk-agent files found.\\n');\n process.exit(0);\n }\n\n let warnings = 0;\n for (const file of files) {\n let text = '';\n try {\n text = readFileSync(file, 'utf8');\n } catch (e: any) {\n process.stderr.write(`[X] Failed to read ${file}: ${e?.message ?? String(e)}\\n`);\n continue;\n }\n\n const matches = findSecretMatches(text);\n if (!matches.length) continue;\n\n warnings += matches.length;\n process.stderr.write(`\\nWARNING: ${file}\\n`);\n for (const m of matches.slice(0, 25)) {\n const lc = computeLineCol(text, m.index);\n process.stderr.write(` - ${m.kind} at ${lc.line}:${lc.col}: ${maskSecret(m.value)}\\n`);\n }\n if (matches.length > 25) {\n process.stderr.write(` - ... (${matches.length - 25} more)\\n`);\n }\n }\n\n if (warnings > 0) {\n process.stderr.write(`\\nSummary: ${warnings} warning(s)\\n`);\n process.exit(options.failOnWarn ? 1 : 0);\n }\n\n process.stderr.write('[OK] No issues found.\\n');\n process.exit(0);\n });\n\n return cmd;\n}\n",
|
|
112
|
+
"import { Command } from 'commander';\nimport { existsSync } from 'fs';\nimport { resolve } from 'path';\nimport {\n resolveAppConfig,\n getUserConfigPath,\n getProjectConfigPath,\n parseConfigKey,\n parseConfigValue,\n readConfigFile,\n writeConfigFile,\n looksSecretKey,\n looksSecretValue,\n APP_CONFIG_KEYS,\n type AppConfig,\n type AppConfigKey,\n} from '../config/app-config';\nimport { ensurePkAgentProjectDirs, ensurePkAgentUserDirs } from '../utils/pk-agent-dirs';\n\nfunction formatValueForDisplay(value: unknown): string {\n if (value === undefined) return '(unset)';\n if (typeof value === 'string') {\n if (looksSecretValue(value)) return '[REDACTED]';\n return value;\n }\n return String(value);\n}\n\nfunction resolveProjectRootFromFlags(dir?: string): string {\n if (!dir) return process.cwd();\n const target = resolve(dir);\n if (!existsSync(target)) {\n throw new Error(`Directory not found: ${dir}`);\n }\n return target;\n}\n\nfunction readScoped(scope: 'user' | 'project', projectRoot: string): { path: string; config: AppConfig } {\n if (scope === 'user') {\n const p = getUserConfigPath();\n return { path: p, config: readConfigFile(p) };\n }\n const p = getProjectConfigPath(projectRoot);\n return { path: p, config: readConfigFile(p) };\n}\n\nfunction writeScoped(scope: 'user' | 'project', projectRoot: string, cfg: AppConfig): string {\n const path = scope === 'user' ? getUserConfigPath() : getProjectConfigPath(projectRoot);\n writeConfigFile(path, cfg);\n return path;\n}\n\nexport function createConfigCommand(): Command {\n const cmd = new Command('config')\n .description('Manage non-secret pk-agent defaults (user and project scope)')\n .option('-C, --directory <path>', 'Project scope directory (defaults to current working directory)');\n\n cmd.addCommand(\n new Command('path')\n .description('Show config file paths for user and project scope')\n .option('--json', 'Output as JSON')\n .action((opts: { json?: boolean }, parent: { directory?: string }) => {\n const projectRoot = resolveProjectRootFromFlags(parent.directory);\n const paths = { user: getUserConfigPath(), project: getProjectConfigPath(projectRoot) };\n if (opts.json) {\n console.log(JSON.stringify({ success: true, paths }));\n return;\n }\n console.log(`User: ${paths.user}`);\n console.log(`Project: ${paths.project}`);\n })\n );\n\n cmd.addCommand(\n new Command('show')\n .description('Show effective config and sources')\n .option('--json', 'Output as JSON')\n .action((opts: { json?: boolean }, parent: { directory?: string }) => {\n const projectRoot = resolveProjectRootFromFlags(parent.directory);\n const resolved = resolveAppConfig(projectRoot);\n if (opts.json) {\n console.log(JSON.stringify({ success: true, ...resolved }, null, 2));\n return;\n }\n for (const key of APP_CONFIG_KEYS) {\n const value = (resolved.effective as any)[key];\n const src = resolved.sources[key];\n const srcLabel =\n src.scope === 'env' ? `env:${src.envVar}` :\n src.scope === 'project' ? `project:${src.path}` :\n src.scope === 'user' ? `user:${src.path}` :\n 'default';\n console.log(`${key} = ${formatValueForDisplay(value)} (${srcLabel})`);\n }\n })\n );\n\n cmd.addCommand(\n new Command('get')\n .description('Get a single effective config key')\n .argument('<key>', `Config key (${APP_CONFIG_KEYS.join(', ')})`)\n .action((keyRaw: string, parent: { directory?: string }) => {\n const key = parseConfigKey(keyRaw);\n if (!key) throw new Error(`Unknown config key: ${keyRaw}`);\n const projectRoot = resolveProjectRootFromFlags(parent.directory);\n const resolved = resolveAppConfig(projectRoot);\n console.log(formatValueForDisplay((resolved.effective as any)[key]));\n })\n );\n\n cmd.addCommand(\n new Command('set')\n .description('Set a config key in user or project scope')\n .argument('<key>', `Config key (${APP_CONFIG_KEYS.join(', ')})`)\n .argument('<value>', 'Value (typed based on key)')\n .option('--scope <scope>', 'Scope to write (user|project)', 'project')\n .action((keyRaw: string, valueRaw: string, opts: { scope: string }, parent: { directory?: string }) => {\n const key = parseConfigKey(keyRaw);\n if (!key) throw new Error(`Unknown config key: ${keyRaw}`);\n\n if (looksSecretKey(keyRaw)) {\n throw new Error(`Refusing to set secret-like key: ${keyRaw}`);\n }\n if (looksSecretValue(valueRaw)) {\n throw new Error('Refusing to set secret-like value. Use environment variables for secrets.');\n }\n\n const scope = opts.scope === 'user' ? 'user' : 'project';\n const projectRoot = resolveProjectRootFromFlags(parent.directory);\n\n ensurePkAgentUserDirs();\n ensurePkAgentProjectDirs(projectRoot);\n\n const parsed = parseConfigValue(key, valueRaw);\n const { config } = readScoped(scope, projectRoot);\n const next: AppConfig = { ...config, [key]: parsed } as any;\n const path = writeScoped(scope, projectRoot, next);\n console.log(`[OK] Set ${key} in ${scope} config (${path})`);\n })\n );\n\n cmd.addCommand(\n new Command('unset')\n .description('Unset a config key in user or project scope')\n .argument('<key>', `Config key (${APP_CONFIG_KEYS.join(', ')})`)\n .option('--scope <scope>', 'Scope to write (user|project)', 'project')\n .action((keyRaw: string, opts: { scope: string }, parent: { directory?: string }) => {\n const key = parseConfigKey(keyRaw);\n if (!key) throw new Error(`Unknown config key: ${keyRaw}`);\n\n const scope = opts.scope === 'user' ? 'user' : 'project';\n const projectRoot = resolveProjectRootFromFlags(parent.directory);\n\n ensurePkAgentUserDirs();\n ensurePkAgentProjectDirs(projectRoot);\n\n const { config } = readScoped(scope, projectRoot);\n if ((config as any)[key] === undefined) {\n console.log(`[OK] ${key} already unset in ${scope} config`);\n return;\n }\n const next: AppConfig = { ...config };\n delete (next as any)[key];\n const path = writeScoped(scope, projectRoot, next);\n console.log(`[OK] Unset ${key} in ${scope} config (${path})`);\n })\n );\n\n return cmd;\n}\n\n",
|
|
113
|
+
"import { Command } from 'commander';\nimport { existsSync } from 'fs';\nimport { resolve } from 'path';\nimport * as dotenv from 'dotenv';\nimport { resolveProjectContext } from '../utils/project';\nimport { ensurePkAgentProjectDirs, ensurePkAgentUserDirs } from '../utils/pk-agent-dirs';\nimport { resolveAppConfig } from '../config/app-config';\nimport { testAgent } from '../validator/agent-validator';\n\nfunction formatIssueList(title: string, items: Array<{ code: string; message: string }>): string {\n const lines: string[] = [];\n lines.push(title);\n for (const it of items) {\n lines.push(`- ${it.code}: ${it.message}`);\n }\n return lines.join('\\n');\n}\n\nfunction applyWorkingDirectory(options: { directory?: string }): { originalCwd: string } {\n const originalCwd = process.cwd();\n\n // Precedence: CLI -C/--directory > PK_AGENT_DEFAULT_DIRECTORY env > config defaultDirectory.\n let targetDir: string | undefined;\n if (options.directory) {\n targetDir = resolve(options.directory);\n if (!existsSync(targetDir)) {\n throw new Error(`Directory not found: ${options.directory}`);\n }\n } else {\n const envDefaultDir = process.env.PK_AGENT_DEFAULT_DIRECTORY;\n const cfgDefaultDir = resolveAppConfig(process.cwd()).effective.defaultDirectory;\n const chosen = (envDefaultDir && envDefaultDir.trim()) ? envDefaultDir.trim() : cfgDefaultDir;\n if (chosen && chosen.trim()) {\n const abs = resolve(chosen.trim());\n if (existsSync(abs)) targetDir = abs;\n }\n }\n\n if (targetDir && targetDir !== originalCwd) {\n process.chdir(targetDir);\n }\n\n return { originalCwd };\n}\n\nexport function createTestCommand(): Command {\n const cmd = new Command('test')\n .description('Validate an agent file or URL without executing it')\n .argument('<target>', 'Agent .pk-agent file path (or URL)')\n .option('--json', 'Output as JSON')\n .option('--strict', 'Treat warnings as failures')\n .option('--mcp', 'Attempt MCP connect + tool discovery (no tool execution)')\n .option('-C, --directory <path>', 'Run as if started in <path> instead of the current directory')\n .action(async (target: string, options: { json?: boolean; strict?: boolean; mcp?: boolean; directory?: string }) => {\n let originalCwd: string | undefined;\n\n try {\n ({ originalCwd } = applyWorkingDirectory(options));\n\n // Ensure expected directory layout exists.\n ensurePkAgentUserDirs();\n ensurePkAgentProjectDirs(process.cwd());\n\n // Resolve project context and load env file.\n const projectContext = resolveProjectContext(process.cwd());\n if (existsSync(projectContext.envFile)) {\n dotenv.config({ path: projectContext.envFile, quiet: true });\n }\n\n const result = await testAgent(target, {\n mcp: options.mcp === true,\n mcpTimeoutMs: process.env.PK_AGENT_TEST_MCP_TIMEOUT_MS\n ? Number.parseInt(process.env.PK_AGENT_TEST_MCP_TIMEOUT_MS, 10)\n : undefined,\n });\n\n const warningsCount = result.warnings.length;\n const errorsCount = result.errors.length;\n const strictFail = options.strict === true && warningsCount > 0;\n const success = result.success && !strictFail;\n\n if (options.json) {\n console.log(JSON.stringify({\n success,\n strict: options.strict === true,\n ...result,\n }, null, 2));\n } else {\n if (result.agent) {\n const rp = result.agent.resolvedPath ? ` (${result.agent.resolvedPath})` : '';\n process.stdout.write(`[${success ? 'OK' : 'X'}] ${result.agent.name} - ${result.agent.model}${rp}\\n`);\n } else {\n process.stdout.write(`[${success ? 'OK' : 'X'}] Agent validation\\n`);\n }\n\n if (result.mcp?.attempted) {\n const srv = result.mcp.servers.length;\n const tools = result.mcp.totalTools;\n process.stdout.write(`MCP: ${srv} server(s), ${tools} tool(s)\\n`);\n }\n\n if (errorsCount > 0) {\n process.stderr.write('\\n' + formatIssueList('Errors:', result.errors) + '\\n');\n }\n if (warningsCount > 0) {\n process.stderr.write('\\n' + formatIssueList('Warnings:', result.warnings) + '\\n');\n }\n\n if (strictFail) {\n process.stderr.write('\\n[X] --strict: failing due to warnings\\n');\n }\n }\n\n process.exit(success ? 0 : 1);\n } catch (err: any) {\n const msg = err instanceof Error ? err.message : String(err);\n if (options.json) {\n console.log(JSON.stringify({\n success: false,\n error: { code: 'TEST_ERROR', message: msg },\n }));\n } else {\n process.stderr.write(`[X] ${msg}\\n`);\n }\n process.exit(1);\n } finally {\n if (originalCwd && originalCwd !== process.cwd()) {\n process.chdir(originalCwd);\n }\n }\n });\n\n return cmd;\n}\n\n",
|
|
114
|
+
"import { basename, dirname, resolve } from 'path';\nimport { existsSync } from 'fs';\nimport { parseAgent, parseAgentContent, ConfigError, type ParsedAgent } from '../parser';\nimport { isURL, fetchRemoteAgent, getRemoteAgentName } from '../utils/remote-agent';\nimport { validateAgentEnvVars, type EnvVarReference } from '../utils/env-validation';\nimport { connectMCP } from '../mcp';\n\nexport type ValidationIssueCode =\n | 'INVALID_TARGET'\n | 'INVALID_URL'\n | 'FETCH_FAILED'\n | 'FILE_NOT_FOUND'\n | 'YAML_SYNTAX'\n | 'CONFIG_INVALID'\n | 'ENV_MISSING_REQUIRED'\n | 'ENV_MISSING_OPTIONAL'\n | 'MCP_NOT_CONFIGURED'\n | 'MCP_CONNECT_FAILED'\n | 'MCP_TIMEOUT';\n\nexport interface ValidationIssue {\n code: ValidationIssueCode;\n message: string;\n file?: string;\n line?: number;\n column?: number;\n}\n\nexport interface ValidationWarning {\n code: ValidationIssueCode;\n message: string;\n}\n\nexport interface McpServerSummary {\n name: string;\n toolCount: number;\n error?: string;\n}\n\nexport interface AgentTestResult {\n success: boolean;\n errors: ValidationIssue[];\n warnings: ValidationWarning[];\n agent?: {\n name: string;\n model: string;\n target: { type: 'file' | 'url'; value: string };\n resolvedPath?: string;\n };\n mcp?: {\n attempted: boolean;\n servers: McpServerSummary[];\n totalTools: number;\n };\n}\n\nexport interface AgentTestOptions {\n mcp?: boolean;\n mcpTimeoutMs?: number;\n}\n\nfunction parseYamlLineCol(msg: string): { line?: number; column?: number } {\n const m = msg.match(/line\\s+(\\d+),\\s*column\\s+(\\d+)/i);\n if (!m) return {};\n return { line: Number(m[1]), column: Number(m[2]) };\n}\n\nfunction formatEnvRef(refs: EnvVarReference[]): string {\n // Keep message stable and non-verbose: show variable names only.\n const names = Array.from(new Set(refs.map(r => r.name))).sort();\n return names.join(', ');\n}\n\nexport function validateUrlTarget(url: string): ValidationIssue | null {\n try {\n const u = new URL(url);\n const proto = u.protocol.toLowerCase();\n if (proto !== 'https:' && proto !== 'http:') {\n return { code: 'INVALID_URL', message: `URL must use http:// or https:// (got: ${u.protocol})` };\n }\n if (!u.pathname.toLowerCase().endsWith('.pk-agent')) {\n return { code: 'INVALID_URL', message: 'Remote agents must have .pk-agent extension' };\n }\n return null;\n } catch {\n return { code: 'INVALID_URL', message: `Invalid URL: ${url}` };\n }\n}\n\nasync function loadAgentFromTarget(target: string): Promise<{ agent: ParsedAgent; kind: 'file' | 'url'; resolvedPath?: string }> {\n if (isURL(target)) {\n const urlIssue = validateUrlTarget(target);\n if (urlIssue) {\n const e = new Error(urlIssue.message);\n (e as any).__pk_agent_issue = urlIssue;\n throw e;\n }\n\n const content = await fetchRemoteAgent(target);\n const name = getRemoteAgentName(target);\n return { agent: parseAgentContent(content, name), kind: 'url' };\n }\n\n // Local file path. Support omitting .pk-agent extension.\n let filePath = target;\n if (!filePath.endsWith('.pk-agent') && !existsSync(filePath)) {\n const withExt = `${filePath}.pk-agent`;\n if (existsSync(withExt)) filePath = withExt;\n }\n if (!existsSync(filePath)) {\n const e = new Error(`File not found: ${filePath}`);\n (e as any).__pk_agent_issue = { code: 'FILE_NOT_FOUND', message: `File not found: ${filePath}`, file: filePath } satisfies ValidationIssue;\n throw e;\n }\n\n const abs = resolve(filePath);\n const agent = await parseAgent(abs);\n return { agent, kind: 'file', resolvedPath: abs };\n}\n\nexport async function testAgent(target: string, opts: AgentTestOptions = {}): Promise<AgentTestResult> {\n const errors: ValidationIssue[] = [];\n const warnings: ValidationWarning[] = [];\n\n const wantMcp = opts.mcp === true;\n const mcpTimeoutMs = Number.isFinite(opts.mcpTimeoutMs) ? Number(opts.mcpTimeoutMs) : 30_000;\n\n let loaded: { agent: ParsedAgent; kind: 'file' | 'url'; resolvedPath?: string } | undefined;\n\n try {\n if (!target || !String(target).trim()) {\n return {\n success: false,\n errors: [{ code: 'INVALID_TARGET', message: 'Missing target' }],\n warnings,\n };\n }\n\n loaded = await loadAgentFromTarget(target);\n } catch (err: any) {\n const injected: ValidationIssue | undefined = err?.__pk_agent_issue;\n if (injected) {\n errors.push(injected);\n return { success: false, errors, warnings };\n }\n\n if (err instanceof ConfigError) {\n if (err.field === 'yaml' && err.issue === 'syntax_error') {\n const lc = parseYamlLineCol(err.message);\n errors.push({ code: 'YAML_SYNTAX', message: err.message, ...lc });\n } else {\n errors.push({ code: 'CONFIG_INVALID', message: err.message });\n }\n return { success: false, errors, warnings };\n }\n\n const msg = err instanceof Error ? err.message : String(err);\n if (isURL(target)) {\n errors.push({ code: 'FETCH_FAILED', message: msg });\n } else {\n errors.push({ code: 'CONFIG_INVALID', message: msg });\n }\n return { success: false, errors, warnings };\n }\n\n const agent = loaded.agent;\n\n // Env var validation (safe: never prints values).\n const envValidation = validateAgentEnvVars(agent.config);\n if (!envValidation.valid) {\n errors.push({\n code: 'ENV_MISSING_REQUIRED',\n message: `Missing required environment variables: ${formatEnvRef(envValidation.missingRequired)}`,\n });\n }\n if (envValidation.missingOptional.length > 0) {\n warnings.push({\n code: 'ENV_MISSING_OPTIONAL',\n message: `Optional environment variables not set: ${formatEnvRef(envValidation.missingOptional)}`,\n });\n }\n\n const result: AgentTestResult = {\n success: errors.length === 0,\n errors,\n warnings,\n agent: {\n name: agent.name,\n model: agent.config.model,\n target: { type: loaded.kind, value: target },\n ...(loaded.resolvedPath ? { resolvedPath: loaded.resolvedPath } : {}),\n },\n };\n\n if (!wantMcp) return result;\n\n // MCP discovery (spawn/connect and list tools; no tool execution).\n if (!agent.config.mcpServers || Object.keys(agent.config.mcpServers).length === 0) {\n result.mcp = { attempted: true, servers: [], totalTools: 0 };\n warnings.push({ code: 'MCP_NOT_CONFIGURED', message: 'No MCP servers configured' });\n result.success = errors.length === 0;\n return result;\n }\n\n const basePath = loaded.kind === 'file' && loaded.resolvedPath ? dirname(loaded.resolvedPath) : undefined;\n\n const servers: McpServerSummary[] = [];\n let totalTools = 0;\n let connections: Awaited<ReturnType<typeof connectMCP>> = [];\n\n try {\n const connectPromise = connectMCP(agent.config.mcpServers, false, basePath);\n const timed = await Promise.race([\n connectPromise,\n new Promise<never>((_, reject) => setTimeout(() => reject(new Error('MCP_TIMEOUT')), mcpTimeoutMs)),\n ]);\n connections = timed as any;\n\n for (const conn of connections) {\n const toolCount = Object.keys(conn.tools || {}).length;\n totalTools += toolCount;\n servers.push({ name: conn.name, toolCount });\n }\n } catch (err: any) {\n if (String(err?.message || err) === 'MCP_TIMEOUT') {\n errors.push({ code: 'MCP_TIMEOUT', message: `MCP discovery timed out after ${mcpTimeoutMs}ms` });\n } else {\n errors.push({ code: 'MCP_CONNECT_FAILED', message: err?.message ? String(err.message) : String(err) });\n }\n } finally {\n for (const conn of connections) {\n try {\n await conn.client.close();\n } catch {\n // ignore\n }\n }\n }\n\n result.mcp = { attempted: true, servers, totalTools };\n result.success = errors.length === 0;\n return result;\n}\n\nexport function guessAgentNameFromTarget(target: string): string {\n if (isURL(target)) return getRemoteAgentName(target);\n return basename(target).replace(/\\.pk-agent$/i, '');\n}\n\n",
|
|
115
|
+
"import { parseAgent } from '../parser';\nimport { connectMCP } from '../mcp';\nimport { executeAgentCore, prepareAgentExecution } from '../runner';\nimport { logger, LogLevel } from '../utils/logger';\nimport { validateAgentEnvVars, formatEnvValidationError } from '../utils/env-validation';\nimport { resolve, dirname } from 'path';\nimport { existsSync } from 'fs';\nimport * as dotenv from 'dotenv';\nimport { redactObjectDeep, redactForTrace } from '../utils/redaction';\nimport type { AgentChunk } from '../runner/types';\nimport { resolveAppConfig, applyAppConfigDefaultsToAgentConfig } from '../config/app-config';\n\ninterface ExecuteRequest {\n id: string;\n type: 'execute';\n agentPath: string;\n projectRoot: string;\n prompt?: string;\n model?: string;\n timeout?: number;\n maxSteps?: number;\n debug?: boolean;\n stream?: boolean;\n}\n\ntype WorkerEventMessage = { id: string; type: 'event'; event: any };\n\ninterface WorkerExecuteResult {\n success: true;\n result: {\n text: string;\n finishReason?: string;\n duration: number;\n tokens?: { input: number; output: number };\n toolCalls: number;\n };\n}\n\ninterface WorkerExecuteError {\n success: false;\n error: {\n code: string;\n message: string;\n };\n}\n\ntype WorkerDoneMessage =\n | { id: string; type: 'done' } & WorkerExecuteResult\n | { id: string; type: 'done' } & WorkerExecuteError;\n\nfunction toSafeChunk(chunk: AgentChunk): any {\n // Ensure message is JSON serializable and redacted.\n if (chunk.type === 'tool-call') {\n return {\n ...chunk,\n ...(chunk.toolInput !== undefined ? { toolInput: redactObjectDeep(chunk.toolInput) } : {}),\n };\n }\n if (chunk.type === 'tool-result') {\n return {\n ...chunk,\n // Do not include raw output; it may contain large/binary data.\n toolResultRaw: undefined,\n ...(chunk.toolResult !== undefined ? { toolResult: redactForTrace(chunk.toolResult) } : {}),\n };\n }\n if (chunk.type === 'text') {\n return { ...chunk };\n }\n if (chunk.type === 'status') {\n return { ...chunk };\n }\n if (chunk.type === 'error') {\n const err = chunk.error;\n const msg = err instanceof Error ? err.message : String(err);\n return { type: 'error', error: { message: redactForTrace(msg) } };\n }\n return { ...chunk };\n}\n\nasync function executeAgent(req: ExecuteRequest, emit?: (msg: WorkerEventMessage) => void): Promise<WorkerDoneMessage> {\n const startTime = Date.now();\n let mcp: Awaited<ReturnType<typeof connectMCP>> = [];\n\n try {\n const agentPath = resolve(req.projectRoot, req.agentPath);\n if (!existsSync(agentPath)) {\n return {\n id: req.id,\n type: 'done',\n success: false,\n error: { code: 'AGENT_NOT_FOUND', message: `Agent file not found: ${req.agentPath}` },\n };\n }\n\r\n // Load environment from project root\r\n const envFile = resolve(req.projectRoot, '.env');\r\n const envLocalFile = resolve(req.projectRoot, '.env.local');\r\n if (existsSync(envLocalFile)) {\r\n dotenv.config({ path: envLocalFile });\r\n } else if (existsSync(envFile)) {\r\n dotenv.config({ path: envFile });\r\n }\r\n\r\n try {\r\n const { initStorage } = await import('../storage/index.js');\r\n await initStorage(req.projectRoot);\r\n } catch {\r\n // Ignore storage init errors\r\n }\r\n\r\n const agent = await parseAgent(agentPath);\n\n // Apply app defaults to agent config if fields are missing.\n // Env is loaded above; resolveAppConfig() will pick up env overrides.\n const appCfg = resolveAppConfig(req.projectRoot);\n applyAppConfigDefaultsToAgentConfig(agent.config, appCfg);\n\n const envValidation = validateAgentEnvVars(agent.config);\n if (!envValidation.valid) {\n return {\n id: req.id,\n type: 'done',\n success: false,\n error: { code: 'ENV_MISSING', message: formatEnvValidationError(envValidation) },\n };\n }\n\n if (req.model) {\n agent.config.model = req.model;\n }\n\n const mcpBasePath = dirname(agentPath);\n mcp = await connectMCP(agent.config.mcpServers, req.debug ?? false, mcpBasePath);\n\n const timeoutSeconds = req.timeout ?? agent.config.timeout ?? 300;\n const abortController = new AbortController();\n const timeoutId = setTimeout(() => abortController.abort(), timeoutSeconds * 1000);\n\n const { SessionManager } = await import('../session/index.js');\n const sessionManager = new SessionManager();\n\n try {\n const prepared = await prepareAgentExecution({\n agent,\n mcpClients: mcp,\n agentFilePath: agentPath,\n cliMaxSteps: req.maxSteps,\n sessionManager,\n projectContext: { projectRoot: req.projectRoot, cwd: req.projectRoot },\n userPrompt: req.prompt,\n abortSignal: abortController.signal,\n verbose: req.debug ?? false,\n });\n\n let text = '';\n let toolCalls = 0;\n let finishReason: string | undefined;\n let usageTokens: { input: number; output: number } | undefined;\n\n const hookRunner = prepared.hookRunner;\n const effectiveRunId = prepared.runId || prepared.sessionID || String(Date.now());\n if (hookRunner?.enabled) {\n await hookRunner.run('run:start', {\n runId: effectiveRunId,\n agent: {\n name: agent.name,\n model: agent.config.model,\n filePath: agentPath,\n isSubAgent: false,\n },\n project: {\n projectRoot: req.projectRoot,\n cwd: req.projectRoot,\n },\n } as any);\n }\n\n let loopError: unknown;\n try {\n const gen = executeAgentCore(agent, prepared.tools, {\n userMessage: prepared.userMessage,\n systemMessages: prepared.systemMessages,\n maxSteps: prepared.maxSteps,\n abortSignal: abortController.signal,\n subAgentNames: prepared.subAgentNames,\n });\n\n for await (const chunk of gen) {\n if (req.stream && emit) {\n emit({ id: req.id, type: 'event', event: toSafeChunk(chunk) });\n }\n\n if (chunk.type === 'text' && typeof chunk.text === 'string') {\n text += chunk.text;\n } else if (chunk.type === 'tool-call') {\n toolCalls++;\n } else if (chunk.type === 'finish') {\n finishReason = chunk.finishReason;\n const u: any = (chunk as any).usage;\n if (u && typeof u === 'object') {\n usageTokens = {\n input: Number(u.inputTokens ?? 0),\n output: Number(u.outputTokens ?? 0),\n };\n }\n }\n }\n } catch (err) {\n loopError = err;\n throw err;\n } finally {\n if (hookRunner?.enabled) {\n await hookRunner.run('run:end', {\n runId: effectiveRunId,\n agent: {\n name: agent.name,\n model: agent.config.model,\n filePath: agentPath,\n isSubAgent: false,\n },\n project: {\n projectRoot: req.projectRoot,\n cwd: req.projectRoot,\n },\n ...(loopError ? { error: { message: loopError instanceof Error ? loopError.message : String(loopError) } } : {}),\n } as any);\n }\n }\n\n clearTimeout(timeoutId);\n const duration = Date.now() - startTime;\n\n return {\n id: req.id,\n type: 'done',\n success: true,\n result: {\n text: text || '',\n ...(finishReason && { finishReason }),\n duration,\n ...(usageTokens && { tokens: usageTokens }),\n toolCalls,\n },\n };\n } catch (err) {\n clearTimeout(timeoutId);\n if (abortController.signal.aborted) {\n return {\n id: req.id,\n type: 'done',\n success: false,\n error: { code: 'TIMEOUT', message: `Agent execution timed out after ${timeoutSeconds}s` },\n };\n }\n return {\n id: req.id,\n type: 'done',\n success: false,\n error: { code: 'EXECUTION_ERROR', message: (err as Error).message },\n };\n }\n } catch (err) {\n return {\n id: req.id,\n type: 'done',\n success: false,\n error: { code: 'INTERNAL_ERROR', message: (err as Error).message },\n };\n } finally {\n for (const conn of mcp) {\n try {\n await conn.client.close();\n } catch {\n // Ignore cleanup errors\n }\n }\n }\n}\n\r\n/**\r\n * Internal worker mode for serve command.\r\n * Listens for JSON requests on stdin, executes agents, returns JSON on stdout.\r\n * This works around EBADF issues when spawning from async callbacks.\r\n */\r\nexport async function runInternalWorker() {\n const { createInterface } = await import('readline');\n\n // Configure logger to be quiet\n logger.configure({ level: LogLevel.ERROR, quiet: true, disableTUI: true });\n\r\n const rl = createInterface({\r\n input: process.stdin,\r\n output: process.stdout,\r\n terminal: false,\r\n });\r\n\r\n // Signal ready\r\n console.log(JSON.stringify({ type: 'ready' }));\r\n\r\n for await (const line of rl) {\n if (!line.trim()) continue;\n\n try {\n const request = JSON.parse(line) as ExecuteRequest;\n if (request.type === 'execute') {\n // Don't await - handle requests concurrently\n // Each request runs in parallel, response sent when complete\n const emit = (msg: WorkerEventMessage) => {\n try {\n console.log(JSON.stringify(msg));\n } catch {\n // ignore\n }\n };\n\n executeAgent(request, emit).then((response) => {\n console.log(JSON.stringify(response));\n });\n } else {\n console.log(JSON.stringify({\n id: (request as any).id || 'unknown',\n type: 'done',\n success: false,\n error: { code: 'UNKNOWN_REQUEST', message: 'Unknown request type' },\n }));\n }\n } catch (err) {\n console.log(JSON.stringify({\n id: 'unknown',\n type: 'done',\n success: false,\n error: { code: 'PARSE_ERROR', message: (err as Error).message },\n }));\n }\n }\n}\n"
|
|
116
|
+
],
|
|
117
|
+
"mappings": "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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBA4hBnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mCAMgB,WAAW,OAAO,SAAS;AAAA;AAAA,uCAEvB,WAAW,OAAO,KAAK;AAAA,kBAC5C,IAAI,KAAK,OAAO,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE,EAAE,QAAQ,KAAK,GAAG;AAAA,kBACtE,eAAe,OAAO,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kCAWhB,KAAK,QAAQ;AAAA;AAAA;AAAA;AAAA,kCAIb,KAAK,QAAQ;AAAA;AAAA;AAAA;AAAA,kCAIb,KAAK,QAAQ;AAAA;AAAA;AAAA;AAAA,kCAIb,WAAW,KAAK,QAAQ,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAkE1D,eAAe,IAAI,UAAQ;AAAA;AAAA,0CAEG,WAAW,KAAK,IAAI;AAAA,yCACrB,WAAW,KAAK,UAAU;AAAA,iBAClD,EAAE,KAAK,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kFAQwD,IAAI,KAAK,EAAE,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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",
|
|
118
|
+
"debugId": "AFD17A95F558824E64756E2164756E21",
|
|
119
|
+
"names": []
|
|
120
|
+
}
|