@hasna/testers 0.0.34 → 0.0.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mcp/index.js CHANGED
@@ -52,7 +52,7 @@ var package_default;
52
52
  var init_package = __esm(() => {
53
53
  package_default = {
54
54
  name: "@hasna/testers",
55
- version: "0.0.33",
55
+ version: "0.0.36",
56
56
  description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
57
57
  type: "module",
58
58
  main: "dist/index.js",
@@ -76,10 +76,10 @@ var init_package = __esm(() => {
76
76
  ],
77
77
  scripts: {
78
78
  build: "bun run build:dashboard && bun run build:cli && bun run build:mcp && bun run build:server && bun run build:lib && bun run build:types",
79
- "build:cli": "bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external @anthropic-ai/sdk --external playwright --external @hasna/browser",
80
- "build:mcp": "bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external @anthropic-ai/sdk --external playwright --external @hasna/browser",
81
- "build:server": "bun build src/server/index.ts --outdir dist/server --target bun --external @anthropic-ai/sdk --external playwright --external @hasna/browser",
82
- "build:lib": "bun build src/index.ts --outdir dist --target bun --external playwright --external @anthropic-ai/sdk --external @modelcontextprotocol/sdk --external @hasna/browser",
79
+ "build:cli": "bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external @anthropic-ai/sdk --external playwright --external @hasna/browser --external @hasna/sandboxes",
80
+ "build:mcp": "bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external @anthropic-ai/sdk --external playwright --external @hasna/browser --external @hasna/sandboxes",
81
+ "build:server": "bun build src/server/index.ts --outdir dist/server --target bun --external @anthropic-ai/sdk --external playwright --external @hasna/browser --external @hasna/sandboxes",
82
+ "build:lib": "bun build src/index.ts --outdir dist --target bun --external playwright --external @anthropic-ai/sdk --external @modelcontextprotocol/sdk --external @hasna/browser --external @hasna/sandboxes",
83
83
  "build:types": "NODE_OPTIONS='--max-old-space-size=8192' tsc --emitDeclarationOnly --outDir dist --skipLibCheck || true",
84
84
  "build:dashboard": "cd dashboard && bun run build",
85
85
  "build:ext": "cd extension && bun run build",
@@ -93,10 +93,11 @@ var init_package = __esm(() => {
93
93
  },
94
94
  dependencies: {
95
95
  "@anthropic-ai/sdk": "^0.52.0",
96
- "@hasna/browser": "^0.4.5",
96
+ "@hasna/browser": "^0.4.12",
97
97
  "@hasna/cloud": "^0.1.24",
98
98
  "@hasna/contacts": "^0.6.8",
99
99
  "@hasna/projects": "^0.1.42",
100
+ "@hasna/sandboxes": "^0.1.27",
100
101
  "@modelcontextprotocol/sdk": "^1.12.1",
101
102
  ai: "^6.0.175",
102
103
  chalk: "^5.4.1",
@@ -5399,9 +5400,9 @@ async function syncTransfer(source, target, options, _direction) {
5399
5400
  const batch = rows.slice(offset, offset + batchSize);
5400
5401
  try {
5401
5402
  if (isAsyncAdapter(target)) {
5402
- await batchUpsertPg(target, table, columns, updateCols, pkColumns, batch, columns.includes(conflictColumn) ? conflictColumn : undefined);
5403
+ await batchUpsertPg(target, table, columns, updateCols, pkColumns, batch);
5403
5404
  } else {
5404
- batchUpsertSqlite(target, table, columns, updateCols, pkColumns, batch, columns.includes(conflictColumn) ? conflictColumn : undefined);
5405
+ batchUpsertSqlite(target, table, columns, updateCols, pkColumns, batch);
5405
5406
  }
5406
5407
  result.rowsWritten += batch.length;
5407
5408
  } catch (err) {
@@ -5448,7 +5449,7 @@ async function syncTransfer(source, target, options, _direction) {
5448
5449
  }
5449
5450
  return results;
5450
5451
  }
5451
- async function batchUpsertPg(target, table, columns, updateCols, primaryKeys, batch, conflictColumn) {
5452
+ async function batchUpsertPg(target, table, columns, updateCols, primaryKeys, batch) {
5452
5453
  if (batch.length === 0)
5453
5454
  return;
5454
5455
  const colList = columns.map((c) => `"${c}"`).join(", ");
@@ -5458,22 +5459,20 @@ async function batchUpsertPg(target, table, columns, updateCols, primaryKeys, ba
5458
5459
  }).join(", ");
5459
5460
  const pkList = primaryKeys.map((c) => `"${c}"`).join(", ");
5460
5461
  const setClause = updateCols.length > 0 ? updateCols.map((c) => `"${c}" = EXCLUDED."${c}"`).join(", ") : `"${primaryKeys[0]}" = EXCLUDED."${primaryKeys[0]}"`;
5461
- const whereClause = conflictColumn && updateCols.includes(conflictColumn) ? ` WHERE "${table}"."${conflictColumn}" IS NULL OR EXCLUDED."${conflictColumn}" >= "${table}"."${conflictColumn}"` : "";
5462
5462
  const sql = `INSERT INTO "${table}" (${colList}) VALUES ${valuePlaceholders}
5463
- ON CONFLICT (${pkList}) DO UPDATE SET ${setClause}${whereClause}`;
5463
+ ON CONFLICT (${pkList}) DO UPDATE SET ${setClause}`;
5464
5464
  const params = batch.flatMap((row) => columns.map((c) => row[c] ?? null));
5465
5465
  await target.run(sql, ...params);
5466
5466
  }
5467
- function batchUpsertSqlite(target, table, columns, updateCols, primaryKeys, batch, conflictColumn) {
5467
+ function batchUpsertSqlite(target, table, columns, updateCols, primaryKeys, batch) {
5468
5468
  if (batch.length === 0)
5469
5469
  return;
5470
5470
  const colList = columns.map((c) => `"${c}"`).join(", ");
5471
5471
  const valuePlaceholders = batch.map(() => `(${columns.map(() => "?").join(", ")})`).join(", ");
5472
5472
  const pkList = primaryKeys.map((c) => `"${c}"`).join(", ");
5473
5473
  const setClause = updateCols.length > 0 ? updateCols.map((c) => `"${c}" = EXCLUDED."${c}"`).join(", ") : `"${primaryKeys[0]}" = EXCLUDED."${primaryKeys[0]}"`;
5474
- const whereClause = conflictColumn && updateCols.includes(conflictColumn) ? ` WHERE "${table}"."${conflictColumn}" IS NULL OR EXCLUDED."${conflictColumn}" >= "${table}"."${conflictColumn}"` : "";
5475
5474
  const sql = `INSERT INTO "${table}" (${colList}) VALUES ${valuePlaceholders}
5476
- ON CONFLICT (${pkList}) DO UPDATE SET ${setClause}${whereClause}`;
5475
+ ON CONFLICT (${pkList}) DO UPDATE SET ${setClause}`;
5477
5476
  const params = batch.flatMap((row) => columns.map((c) => coerceForSqlite(row[c])));
5478
5477
  target.run(sql, ...params);
5479
5478
  }
@@ -5698,7 +5697,7 @@ class SyncProgressTracker {
5698
5697
  }
5699
5698
  }
5700
5699
  }
5701
- function registerCloudTools(server, serviceName, opts = {}) {
5700
+ function registerCloudTools(server, serviceName) {
5702
5701
  server.tool(`${serviceName}_cloud_status`, "Show cloud configuration and connection health", {}, async () => {
5703
5702
  const config = getCloudConfig();
5704
5703
  const lines = [
@@ -5731,13 +5730,8 @@ function registerCloudTools(server, serviceName, opts = {}) {
5731
5730
  isError: true
5732
5731
  };
5733
5732
  }
5734
- const local = new SqliteAdapter(opts.dbPath ?? getDbPath(serviceName));
5733
+ const local = new SqliteAdapter(getDbPath(serviceName));
5735
5734
  const cloud = new PgAdapterAsync(getConnectionString(serviceName));
5736
- if (opts.migrations?.length) {
5737
- for (const sql of opts.migrations) {
5738
- await cloud.run(sql);
5739
- }
5740
- }
5741
5735
  const tableList = tablesStr ? tablesStr.split(",").map((t) => t.trim()) : listSqliteTables(local);
5742
5736
  const results = await syncPush(local, cloud, { tables: tableList });
5743
5737
  local.close();
@@ -5759,7 +5753,7 @@ function registerCloudTools(server, serviceName, opts = {}) {
5759
5753
  isError: true
5760
5754
  };
5761
5755
  }
5762
- const local = new SqliteAdapter(opts.dbPath ?? getDbPath(serviceName));
5756
+ const local = new SqliteAdapter(getDbPath(serviceName));
5763
5757
  const cloud = new PgAdapterAsync(getConnectionString(serviceName));
5764
5758
  let tableList;
5765
5759
  if (tablesStr) {
@@ -14141,6 +14135,56 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
14141
14135
  });
14142
14136
 
14143
14137
  // src/types/index.ts
14138
+ function isRecord(value) {
14139
+ return typeof value === "object" && value !== null && !Array.isArray(value);
14140
+ }
14141
+ function stringValue(value) {
14142
+ return typeof value === "string" && value.trim() ? value : undefined;
14143
+ }
14144
+ function numberValue(value) {
14145
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
14146
+ }
14147
+ function stringMap(value) {
14148
+ if (!isRecord(value))
14149
+ return;
14150
+ const entries = Object.entries(value).filter((entry) => typeof entry[1] === "string");
14151
+ return entries.length > 0 ? Object.fromEntries(entries) : undefined;
14152
+ }
14153
+ function cleanupValue(value) {
14154
+ if (value === "delete" || value === "stop" || value === "keep")
14155
+ return value;
14156
+ return;
14157
+ }
14158
+ function workflowExecutionFromValue(value) {
14159
+ const input = isRecord(value) ? value : {};
14160
+ const rawTarget = stringValue(input["target"]) ?? "local";
14161
+ if (rawTarget === "local") {
14162
+ const timeoutMs2 = numberValue(input["timeoutMs"]);
14163
+ return timeoutMs2 === undefined ? { target: "local" } : { target: "local", timeoutMs: timeoutMs2 };
14164
+ }
14165
+ if (rawTarget !== "sandbox" && rawTarget !== "connector:e2b") {
14166
+ throw new Error(`Unsupported workflow execution target: ${rawTarget}`);
14167
+ }
14168
+ const provider = rawTarget === "connector:e2b" ? "e2b" : stringValue(input["provider"]) ?? stringValue(input["connector"]);
14169
+ const sandboxImage = stringValue(input["sandboxImage"]) ?? stringValue(input["sandboxTemplate"]);
14170
+ const sandboxRemoteDir = stringValue(input["sandboxRemoteDir"]);
14171
+ const sandboxCleanup = cleanupValue(input["sandboxCleanup"]);
14172
+ const setupCommand = stringValue(input["setupCommand"]);
14173
+ const packageSpec = stringValue(input["packageSpec"]);
14174
+ const timeoutMs = numberValue(input["timeoutMs"]);
14175
+ const env = stringMap(input["env"]);
14176
+ return {
14177
+ target: "sandbox",
14178
+ ...provider ? { provider } : {},
14179
+ ...sandboxImage ? { sandboxImage } : {},
14180
+ ...sandboxRemoteDir ? { sandboxRemoteDir } : {},
14181
+ ...sandboxCleanup ? { sandboxCleanup } : {},
14182
+ ...setupCommand ? { setupCommand } : {},
14183
+ ...packageSpec ? { packageSpec } : {},
14184
+ ...timeoutMs !== undefined ? { timeoutMs } : {},
14185
+ ...env ? { env } : {}
14186
+ };
14187
+ }
14144
14188
  function workflowFromRow(row) {
14145
14189
  return {
14146
14190
  id: row.id,
@@ -14150,7 +14194,7 @@ function workflowFromRow(row) {
14150
14194
  scenarioFilter: JSON.parse(row.scenario_filter || "{}"),
14151
14195
  personaIds: JSON.parse(row.persona_ids || "[]"),
14152
14196
  goal: row.goal ? JSON.parse(row.goal) : null,
14153
- execution: JSON.parse(row.execution || '{"target":"local"}'),
14197
+ execution: workflowExecutionFromValue(JSON.parse(row.execution || '{"target":"local"}')),
14154
14198
  settings: JSON.parse(row.settings || "{}"),
14155
14199
  enabled: row.enabled === 1,
14156
14200
  createdAt: row.created_at,
@@ -16556,6 +16600,10 @@ function loadConfig() {
16556
16600
  if (envApiKey) {
16557
16601
  config.anthropicApiKey = envApiKey;
16558
16602
  }
16603
+ const envSelfHeal = process.env["TESTERS_SELF_HEAL"];
16604
+ if (envSelfHeal !== undefined) {
16605
+ config.selfHeal = ["1", "true", "yes", "on"].includes(envSelfHeal.toLowerCase());
16606
+ }
16559
16607
  return config;
16560
16608
  }
16561
16609
  function resolveModel(nameOrId) {
@@ -16598,12 +16646,11 @@ Original selector that failed: "${request.failedSelector}"
16598
16646
  Please identify the correct selector from the screenshot.`;
16599
16647
  let rawResponse = "";
16600
16648
  try {
16601
- if (provider === "openai" || provider === "google") {
16602
- const baseUrl = provider === "openai" ? "https://api.openai.com/v1" : "https://generativelanguage.googleapis.com/v1beta/openai";
16603
- const apiKey = provider === "openai" ? process.env["OPENAI_API_KEY"] ?? "" : process.env["GOOGLE_API_KEY"] ?? "";
16649
+ if (provider !== "anthropic") {
16650
+ const compat = createOpenAICompatibleConfig(provider);
16604
16651
  const resp = await callOpenAICompatible({
16605
- baseUrl,
16606
- apiKey,
16652
+ baseUrl: compat.baseUrl,
16653
+ apiKey: compat.apiKey,
16607
16654
  model,
16608
16655
  system: HEAL_SYSTEM,
16609
16656
  messages: [{ role: "user", content: userMessage }],
@@ -16697,12 +16744,15 @@ var init_healer = __esm(() => {
16697
16744
  var exports_ai_client = {};
16698
16745
  __export(exports_ai_client, {
16699
16746
  runAgentLoop: () => runAgentLoop,
16747
+ resolveProviderApiKeyForModel: () => resolveProviderApiKeyForModel,
16700
16748
  resolveModel: () => resolveModel2,
16701
16749
  executeTool: () => executeTool,
16702
16750
  detectProvider: () => detectProvider,
16751
+ createOpenAICompatibleConfig: () => createOpenAICompatibleConfig,
16703
16752
  createClientForModel: () => createClientForModel,
16704
16753
  createClient: () => createClient,
16705
16754
  callOpenAICompatible: () => callOpenAICompatible,
16755
+ buildScenarioUserMessage: () => buildScenarioUserMessage,
16706
16756
  BROWSER_TOOLS: () => BROWSER_TOOLS
16707
16757
  });
16708
16758
  import Anthropic2 from "@anthropic-ai/sdk";
@@ -17115,7 +17165,6 @@ async function executeTool(page, screenshotter, toolName, toolInput, context) {
17115
17165
  const assertionType = toolInput.assertion_type;
17116
17166
  const selector = toolInput.selector;
17117
17167
  const expected = toolInput.expected;
17118
- const sessionId = context.sessionId ?? "default";
17119
17168
  switch (assertionType) {
17120
17169
  case "element_exists": {
17121
17170
  if (!selector)
@@ -17180,7 +17229,6 @@ async function executeTool(page, screenshotter, toolName, toolInput, context) {
17180
17229
  case "browser_intercept": {
17181
17230
  const action = toolInput.action;
17182
17231
  const pattern = toolInput.pattern;
17183
- const interceptAction = toolInput.intercept_action;
17184
17232
  const statusCode = toolInput.status_code;
17185
17233
  const body = toolInput.body;
17186
17234
  const sessionId = context.sessionId ?? "default";
@@ -17257,7 +17305,28 @@ ${JSON.stringify(har, null, 2)}` };
17257
17305
  }
17258
17306
  case "browser_a11y": {
17259
17307
  const level = toolInput.level ?? "AA";
17260
- const snapshot = await page.accessibility.snapshot();
17308
+ const snapshot = await page.evaluate(() => {
17309
+ function readRole(el) {
17310
+ return el.getAttribute("role") ?? el.tagName.toLowerCase();
17311
+ }
17312
+ function readName(el) {
17313
+ const labelledBy = el.getAttribute("aria-labelledby");
17314
+ if (labelledBy) {
17315
+ const labelledText = labelledBy.split(/\s+/).map((id) => document.getElementById(id)?.textContent?.trim()).filter(Boolean).join(" ");
17316
+ if (labelledText)
17317
+ return labelledText;
17318
+ }
17319
+ return el.getAttribute("aria-label") ?? el.getAttribute("alt") ?? el.textContent?.trim() ?? "";
17320
+ }
17321
+ function walk(el) {
17322
+ return {
17323
+ role: readRole(el),
17324
+ name: readName(el),
17325
+ children: Array.from(el.children).map((child) => walk(child))
17326
+ };
17327
+ }
17328
+ return document.body ? walk(document.body) : null;
17329
+ });
17261
17330
  if (!snapshot)
17262
17331
  return { result: "Error: could not capture accessibility tree" };
17263
17332
  const issues = [];
@@ -17299,6 +17368,38 @@ ${filtered.join(`
17299
17368
  return { result: `Error executing ${toolName}: ${message}` };
17300
17369
  }
17301
17370
  }
17371
+ function resolveStartUrl(baseUrl, targetPath) {
17372
+ try {
17373
+ return new URL(targetPath, baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`).toString();
17374
+ } catch {
17375
+ return `${baseUrl.replace(/\/+$/, "")}/${targetPath.replace(/^\/+/, "")}`;
17376
+ }
17377
+ }
17378
+ function buildScenarioUserMessage(scenario, baseUrl) {
17379
+ const userParts = [
17380
+ `**Scenario:** ${scenario.name}`,
17381
+ `**Description:** ${scenario.description}`
17382
+ ];
17383
+ if (baseUrl) {
17384
+ const normalizedBaseUrl = baseUrl.replace(/\/+$/, "");
17385
+ userParts.push(`**Base URL:** ${normalizedBaseUrl}`);
17386
+ if (scenario.targetPath) {
17387
+ userParts.push(`**Start URL:** ${resolveStartUrl(normalizedBaseUrl, scenario.targetPath)}`);
17388
+ }
17389
+ userParts.push("**Navigation Boundary:** Treat the Base URL as the application under test. Resolve relative paths and in-app navigation against this origin. Do not navigate to another host unless a step explicitly includes an absolute external URL.");
17390
+ }
17391
+ if (scenario.targetPath) {
17392
+ userParts.push(`**Target Path:** ${scenario.targetPath}`);
17393
+ }
17394
+ if (scenario.steps.length > 0) {
17395
+ userParts.push("**Steps:**");
17396
+ for (let i = 0;i < scenario.steps.length; i++) {
17397
+ userParts.push(`${i + 1}. ${scenario.steps[i]}`);
17398
+ }
17399
+ }
17400
+ return userParts.join(`
17401
+ `);
17402
+ }
17302
17403
  async function runAgentLoop(options) {
17303
17404
  const {
17304
17405
  client,
@@ -17308,6 +17409,7 @@ async function runAgentLoop(options) {
17308
17409
  model,
17309
17410
  runId,
17310
17411
  sessionId,
17412
+ baseUrl,
17311
17413
  maxTurns = 30,
17312
17414
  onStep,
17313
17415
  persona,
@@ -17355,21 +17457,7 @@ Instructions: ${persona.instructions}` : "",
17355
17457
  "- Verify both positive and negative states"
17356
17458
  ].join(`
17357
17459
  `) + personaSection;
17358
- const userParts = [
17359
- `**Scenario:** ${scenario.name}`,
17360
- `**Description:** ${scenario.description}`
17361
- ];
17362
- if (scenario.targetPath) {
17363
- userParts.push(`**Target Path:** ${scenario.targetPath}`);
17364
- }
17365
- if (scenario.steps.length > 0) {
17366
- userParts.push("**Steps:**");
17367
- for (let i = 0;i < scenario.steps.length; i++) {
17368
- userParts.push(`${i + 1}. ${scenario.steps[i]}`);
17369
- }
17370
- }
17371
- const userMessage = userParts.join(`
17372
- `);
17460
+ const userMessage = buildScenarioUserMessage(scenario, baseUrl);
17373
17461
  const screenshots = [];
17374
17462
  let tokensUsed = 0;
17375
17463
  let stepNumber = 0;
@@ -17432,7 +17520,7 @@ Instructions: ${persona.instructions}` : "",
17432
17520
  if (onStep) {
17433
17521
  onStep({ type: "tool_call", toolName: toolBlock.name, toolInput, stepNumber });
17434
17522
  }
17435
- const execResult = await executeTool(page, screenshotter, toolBlock.name, toolInput, { runId, scenarioSlug, stepNumber, sessionId, a11y });
17523
+ const execResult = await executeTool(page, screenshotter, toolBlock.name, toolInput, { runId, scenarioSlug, stepNumber, sessionId: sessionId ?? runId, a11y });
17436
17524
  if (onStep) {
17437
17525
  onStep({ type: "tool_result", toolName: toolBlock.name, toolResult: execResult.result, stepNumber });
17438
17526
  }
@@ -17483,10 +17571,17 @@ function detectProvider(model) {
17483
17571
  return "openai";
17484
17572
  if (model.startsWith("gemini-"))
17485
17573
  return "google";
17574
+ if (model.startsWith("glm-") || model.startsWith("zai/") || model.startsWith("zai-"))
17575
+ return "zai";
17486
17576
  if (model.startsWith("llama-") || model.startsWith("qwen-") || model.includes("cerebras"))
17487
17577
  return "cerebras";
17488
17578
  return "anthropic";
17489
17579
  }
17580
+ function resolveProviderApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey) {
17581
+ if (explicitApiKey)
17582
+ return explicitApiKey;
17583
+ return detectProvider(model) === "anthropic" ? configuredAnthropicApiKey : undefined;
17584
+ }
17490
17585
  function createClient(apiKey) {
17491
17586
  const key = apiKey ?? process.env["ANTHROPIC_API_KEY"];
17492
17587
  if (!key) {
@@ -17564,26 +17659,34 @@ async function callOpenAICompatible(options) {
17564
17659
  const usage = { input_tokens: data.usage?.prompt_tokens ?? 0, output_tokens: data.usage?.completion_tokens ?? 0 };
17565
17660
  return { content, stop_reason: stopReason, usage };
17566
17661
  }
17567
- function createClientForModel(model, apiKey) {
17568
- const provider = detectProvider(model);
17662
+ function createOpenAICompatibleConfig(provider, apiKey) {
17569
17663
  if (provider === "openai") {
17570
- const key = apiKey ?? process.env["OPENAI_API_KEY"];
17571
- if (!key)
17664
+ const key2 = apiKey ?? process.env["OPENAI_API_KEY"];
17665
+ if (!key2)
17572
17666
  throw new AIClientError("No OpenAI API key. Set OPENAI_API_KEY or pass it explicitly.");
17573
- return { provider: "openai", baseUrl: "https://api.openai.com/v1", apiKey: key };
17667
+ return { provider: "openai", baseUrl: "https://api.openai.com/v1", apiKey: key2 };
17574
17668
  }
17575
17669
  if (provider === "google") {
17576
- const key = apiKey ?? process.env["GOOGLE_API_KEY"];
17577
- if (!key)
17670
+ const key2 = apiKey ?? process.env["GOOGLE_API_KEY"];
17671
+ if (!key2)
17578
17672
  throw new AIClientError("No Google API key. Set GOOGLE_API_KEY or pass it explicitly.");
17579
- return { provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai", apiKey: key };
17673
+ return { provider: "google", baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai", apiKey: key2 };
17580
17674
  }
17581
17675
  if (provider === "cerebras") {
17582
- const key = apiKey ?? process.env["CEREBRAS_API_KEY"];
17583
- if (!key)
17676
+ const key2 = apiKey ?? process.env["CEREBRAS_API_KEY"];
17677
+ if (!key2)
17584
17678
  throw new AIClientError("No Cerebras API key. Set CEREBRAS_API_KEY or pass it explicitly.");
17585
- return { provider: "cerebras", baseUrl: "https://api.cerebras.ai/v1", apiKey: key };
17679
+ return { provider: "cerebras", baseUrl: "https://api.cerebras.ai/v1", apiKey: key2 };
17586
17680
  }
17681
+ const key = apiKey ?? process.env["ZAI_API_KEY"];
17682
+ if (!key)
17683
+ throw new AIClientError("No Z.AI API key. Set ZAI_API_KEY or pass it explicitly.");
17684
+ return { provider: "zai", baseUrl: "https://api.z.ai/api/paas/v4", apiKey: key };
17685
+ }
17686
+ function createClientForModel(model, apiKey) {
17687
+ const provider = detectProvider(model);
17688
+ if (provider !== "anthropic")
17689
+ return createOpenAICompatibleConfig(provider, apiKey);
17587
17690
  return createClient(apiKey);
17588
17691
  }
17589
17692
  var activeHARs, activeCoverage, BROWSER_TOOLS;
@@ -18160,22 +18263,22 @@ function resolveJudgeModel(config) {
18160
18263
  apiKey = process.env["GOOGLE_API_KEY"];
18161
18264
  else if (provider === "cerebras")
18162
18265
  apiKey = process.env["CEREBRAS_API_KEY"];
18266
+ else if (provider === "zai")
18267
+ apiKey = process.env["ZAI_API_KEY"];
18163
18268
  }
18164
18269
  if (!apiKey) {
18165
- apiKey = process.env["ANTHROPIC_API_KEY"] ?? process.env["CEREBRAS_API_KEY"] ?? process.env["OPENAI_API_KEY"] ?? process.env["GOOGLE_API_KEY"] ?? globalConfig.anthropicApiKey;
18166
- if (!apiKey)
18167
- throw new AIClientError("No API key found for judge. Set ANTHROPIC_API_KEY, CEREBRAS_API_KEY, OPENAI_API_KEY, or GOOGLE_API_KEY.");
18270
+ throw new AIClientError(`No API key found for ${provider} judge provider.`);
18168
18271
  }
18169
18272
  return { model, provider, apiKey };
18170
18273
  }
18171
18274
  async function callJudge(prompt, config) {
18172
18275
  const { model, provider, apiKey } = resolveJudgeModel(config);
18173
18276
  const threshold = 0.7;
18174
- if (provider === "openai" || provider === "google" || provider === "cerebras") {
18175
- const baseUrl = provider === "openai" ? "https://api.openai.com/v1" : provider === "cerebras" ? "https://api.cerebras.ai/v1" : "https://generativelanguage.googleapis.com/v1beta/openai";
18277
+ if (provider !== "anthropic") {
18278
+ const compat = createOpenAICompatibleConfig(provider, apiKey);
18176
18279
  const resp2 = await callOpenAICompatible({
18177
- baseUrl,
18178
- apiKey,
18280
+ baseUrl: compat.baseUrl,
18281
+ apiKey: compat.apiKey,
18179
18282
  model,
18180
18283
  system: LLM_SYSTEM,
18181
18284
  messages: [{ role: "user", content: prompt }],
@@ -20631,6 +20734,292 @@ var init_failure_pipeline = __esm(() => {
20631
20734
  init_todos_connector();
20632
20735
  });
20633
20736
 
20737
+ // src/lib/a11y-audit.ts
20738
+ async function runA11yAudit(page, options = {}) {
20739
+ const { level = "AA", rules, exclude = [] } = options;
20740
+ await page.addScriptTag({ url: "https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.9.1/axe.min.js" });
20741
+ const config = {
20742
+ runOnly: {
20743
+ type: level === "AAA" ? "standard" : "tag",
20744
+ values: level === "AAA" ? undefined : [level, "best-practice"]
20745
+ }
20746
+ };
20747
+ if (rules && rules.length > 0) {
20748
+ config.rules = Object.fromEntries(rules.map((r) => [r, { enabled: true }]));
20749
+ }
20750
+ if (exclude.length > 0) {
20751
+ config.exclude = exclude;
20752
+ }
20753
+ const result = await page.evaluate(async (auditConfig) => {
20754
+ const axeResult = await window.axe.run(auditConfig);
20755
+ return axeResult;
20756
+ }, config);
20757
+ const violations = (result.violations ?? []).map((v) => ({
20758
+ id: v.id,
20759
+ impact: v.impact,
20760
+ description: v.description,
20761
+ help: v.help,
20762
+ helpUrl: v.helpUrl,
20763
+ nodes: (v.nodes ?? []).map((n) => ({
20764
+ html: n.html,
20765
+ target: n.target,
20766
+ failureSummary: n.failureSummary
20767
+ }))
20768
+ }));
20769
+ const passes = (result.passes ?? []).map((p) => ({
20770
+ id: p.id,
20771
+ description: p.description
20772
+ }));
20773
+ const incomplete = (result.incomplete ?? []).map((i) => ({
20774
+ id: i.id,
20775
+ description: i.description,
20776
+ impact: i.impact
20777
+ }));
20778
+ const criticalCount = violations.filter((v) => v.impact === "critical").length;
20779
+ const seriousCount = violations.filter((v) => v.impact === "serious").length;
20780
+ const moderateCount = violations.filter((v) => v.impact === "moderate").length;
20781
+ const minorCount = violations.filter((v) => v.impact === "minor").length;
20782
+ return {
20783
+ violations,
20784
+ passes,
20785
+ incomplete,
20786
+ url: page.url(),
20787
+ timestamp: new Date().toISOString(),
20788
+ totalViolations: violations.length,
20789
+ criticalCount,
20790
+ seriousCount,
20791
+ moderateCount,
20792
+ minorCount
20793
+ };
20794
+ }
20795
+
20796
+ // src/lib/assertions.ts
20797
+ async function evaluateAssertions(page, assertions, context = {}) {
20798
+ const results = [];
20799
+ for (const assertion of assertions) {
20800
+ try {
20801
+ const result = await evaluateOne(page, assertion, context);
20802
+ results.push(result);
20803
+ } catch (err) {
20804
+ results.push({
20805
+ assertion,
20806
+ passed: false,
20807
+ actual: "",
20808
+ error: err instanceof Error ? err.message : String(err)
20809
+ });
20810
+ }
20811
+ }
20812
+ return results;
20813
+ }
20814
+ async function evaluateOne(page, assertion, context) {
20815
+ switch (assertion.type) {
20816
+ case "visible": {
20817
+ const visible = await page.locator(assertion.selector).isVisible();
20818
+ return {
20819
+ assertion,
20820
+ passed: visible,
20821
+ actual: String(visible)
20822
+ };
20823
+ }
20824
+ case "not_visible": {
20825
+ const visible = await page.locator(assertion.selector).isVisible();
20826
+ return {
20827
+ assertion,
20828
+ passed: !visible,
20829
+ actual: String(visible)
20830
+ };
20831
+ }
20832
+ case "text_contains": {
20833
+ const text = await page.locator(assertion.selector).textContent() ?? "";
20834
+ const expected = String(assertion.expected ?? "");
20835
+ return {
20836
+ assertion,
20837
+ passed: text.includes(expected),
20838
+ actual: text
20839
+ };
20840
+ }
20841
+ case "text_equals": {
20842
+ const text = await page.locator(assertion.selector).textContent() ?? "";
20843
+ const expected = String(assertion.expected ?? "");
20844
+ return {
20845
+ assertion,
20846
+ passed: text.trim() === expected.trim(),
20847
+ actual: text
20848
+ };
20849
+ }
20850
+ case "element_count": {
20851
+ const count = await page.locator(assertion.selector).count();
20852
+ const expected = Number(assertion.expected ?? 0);
20853
+ return {
20854
+ assertion,
20855
+ passed: count === expected,
20856
+ actual: String(count)
20857
+ };
20858
+ }
20859
+ case "no_console_errors": {
20860
+ if (context.consoleErrors !== undefined) {
20861
+ const errors2 = context.consoleErrors.filter(Boolean);
20862
+ return {
20863
+ assertion,
20864
+ passed: errors2.length === 0,
20865
+ actual: errors2.length === 0 ? "No console errors captured" : errors2.slice(0, 3).join(" | ")
20866
+ };
20867
+ }
20868
+ const errorElements = await page.locator('[role="alert"], .error, .error-message, [data-testid="error"]').count();
20869
+ return {
20870
+ assertion,
20871
+ passed: errorElements === 0,
20872
+ actual: `${errorElements} error element(s) found`
20873
+ };
20874
+ }
20875
+ case "no_a11y_violations": {
20876
+ try {
20877
+ const auditResult = await runA11yAudit(page);
20878
+ const hasIssues = auditResult.violations.length > 0;
20879
+ return {
20880
+ assertion,
20881
+ passed: !hasIssues,
20882
+ actual: hasIssues ? `${auditResult.totalViolations} violation(s): ${auditResult.violations.map((v) => v.id).join(", ")}` : "No accessibility violations found"
20883
+ };
20884
+ } catch (err) {
20885
+ return {
20886
+ assertion,
20887
+ passed: false,
20888
+ actual: "",
20889
+ error: err instanceof Error ? err.message : String(err)
20890
+ };
20891
+ }
20892
+ }
20893
+ case "url_contains": {
20894
+ const url = page.url();
20895
+ const expected = String(assertion.expected ?? "");
20896
+ return {
20897
+ assertion,
20898
+ passed: url.includes(expected),
20899
+ actual: url
20900
+ };
20901
+ }
20902
+ case "title_contains": {
20903
+ const title = await page.title();
20904
+ const expected = String(assertion.expected ?? "");
20905
+ return {
20906
+ assertion,
20907
+ passed: title.includes(expected),
20908
+ actual: title
20909
+ };
20910
+ }
20911
+ case "cookie_exists": {
20912
+ const cookieName = assertion.expected;
20913
+ const cookies = await page.context().cookies();
20914
+ const found = cookies.some((c) => c.name === cookieName);
20915
+ return {
20916
+ assertion,
20917
+ passed: found,
20918
+ actual: found ? `Cookie "${cookieName}" exists` : `Cookie "${cookieName}" not found`
20919
+ };
20920
+ }
20921
+ case "cookie_not_exists": {
20922
+ const cookieName = assertion.expected;
20923
+ const cookies = await page.context().cookies();
20924
+ const found = cookies.some((c) => c.name === cookieName);
20925
+ return {
20926
+ assertion,
20927
+ passed: !found,
20928
+ actual: found ? `Cookie "${cookieName}" found (unexpected)` : `Cookie "${cookieName}" does not exist`
20929
+ };
20930
+ }
20931
+ case "cookie_value": {
20932
+ const [cookieName, expectedValue] = assertion.expected.split("=", 2);
20933
+ const cookies = await page.context().cookies();
20934
+ const cookie = cookies.find((c) => c.name === cookieName);
20935
+ const actualValue = cookie?.value ?? "";
20936
+ return {
20937
+ assertion,
20938
+ passed: actualValue === expectedValue,
20939
+ actual: cookie ? `${cookieName}=${actualValue}` : `Cookie "${cookieName}" not found`
20940
+ };
20941
+ }
20942
+ case "local_storage_exists": {
20943
+ const key = assertion.expected;
20944
+ const value = await page.evaluate((k) => localStorage.getItem(k), key);
20945
+ return {
20946
+ assertion,
20947
+ passed: value !== null,
20948
+ actual: value !== null ? `Key "${key}" exists with value "${value}"` : `Key "${key}" not found in localStorage`
20949
+ };
20950
+ }
20951
+ case "local_storage_not_exists": {
20952
+ const key = assertion.expected;
20953
+ const value = await page.evaluate((k) => localStorage.getItem(k), key);
20954
+ return {
20955
+ assertion,
20956
+ passed: value === null,
20957
+ actual: value !== null ? `Key "${key}" exists (unexpected)` : `Key "${key}" does not exist in localStorage`
20958
+ };
20959
+ }
20960
+ case "local_storage_value": {
20961
+ const [lsKey, expectedValue] = assertion.expected.split("=", 2);
20962
+ const value = await page.evaluate((k) => localStorage.getItem(k), lsKey ?? "");
20963
+ return {
20964
+ assertion,
20965
+ passed: value === expectedValue,
20966
+ actual: value !== null ? `${lsKey}=${value}` : `Key "${lsKey}" not found in localStorage`
20967
+ };
20968
+ }
20969
+ case "session_storage_value": {
20970
+ const [ssKey, expectedValue] = assertion.expected.split("=", 2);
20971
+ const value = await page.evaluate((k) => sessionStorage.getItem(k), ssKey ?? "");
20972
+ return {
20973
+ assertion,
20974
+ passed: value === expectedValue,
20975
+ actual: value !== null ? `${ssKey}=${value}` : `Key "${ssKey}" not found in sessionStorage`
20976
+ };
20977
+ }
20978
+ case "session_storage_not_exists": {
20979
+ const key = assertion.expected;
20980
+ const value = await page.evaluate((k) => sessionStorage.getItem(k), key);
20981
+ return {
20982
+ assertion,
20983
+ passed: value === null,
20984
+ actual: value !== null ? `Key "${key}" exists (unexpected)` : `Key "${key}" does not exist in sessionStorage`
20985
+ };
20986
+ }
20987
+ default: {
20988
+ return {
20989
+ assertion,
20990
+ passed: false,
20991
+ actual: "",
20992
+ error: `Unknown assertion type: ${assertion.type}`
20993
+ };
20994
+ }
20995
+ }
20996
+ }
20997
+ function allAssertionsPassed(results) {
20998
+ return results.every((r) => r.passed);
20999
+ }
21000
+ function formatAssertionResults(results) {
21001
+ if (results.length === 0)
21002
+ return "No assertions.";
21003
+ const lines = [];
21004
+ for (const r of results) {
21005
+ const icon = r.passed ? "PASS" : "FAIL";
21006
+ const desc = r.assertion.description || `${r.assertion.type}${r.assertion.selector ? ` ${r.assertion.selector}` : ""}`;
21007
+ let line = ` [${icon}] ${desc}`;
21008
+ if (!r.passed) {
21009
+ line += ` (actual: ${r.actual})`;
21010
+ if (r.error)
21011
+ line += ` \u2014 ${r.error}`;
21012
+ }
21013
+ lines.push(line);
21014
+ }
21015
+ const passed = results.filter((r) => r.passed).length;
21016
+ lines.push(`
21017
+ ${passed}/${results.length} assertions passed.`);
21018
+ return lines.join(`
21019
+ `);
21020
+ }
21021
+ var init_assertions = () => {};
21022
+
20634
21023
  // src/db/flows.ts
20635
21024
  var exports_flows = {};
20636
21025
  __export(exports_flows, {
@@ -20789,7 +21178,10 @@ __export(exports_runner, {
20789
21178
  runSingleScenario: () => runSingleScenario,
20790
21179
  runByFilter: () => runByFilter,
20791
21180
  runBatch: () => runBatch,
20792
- onRunEvent: () => onRunEvent
21181
+ resolveScenariosForRun: () => resolveScenariosForRun,
21182
+ resolveAgentApiKeyForModel: () => resolveAgentApiKeyForModel,
21183
+ onRunEvent: () => onRunEvent,
21184
+ applyStructuredAssertionsToResult: () => applyStructuredAssertionsToResult
20793
21185
  });
20794
21186
  import { mkdirSync as mkdirSync8 } from "fs";
20795
21187
  import { join as join13 } from "path";
@@ -20801,6 +21193,57 @@ function emit(event) {
20801
21193
  if (eventHandler)
20802
21194
  eventHandler(event);
20803
21195
  }
21196
+ function resolveAgentApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey) {
21197
+ return resolveProviderApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey);
21198
+ }
21199
+ function assertionDescription(result) {
21200
+ return result.assertion.description || `${result.assertion.type}${result.assertion.selector ? ` ${result.assertion.selector}` : ""}`;
21201
+ }
21202
+ function summarizeAssertionResult(result) {
21203
+ const description = assertionDescription(result);
21204
+ if (result.passed)
21205
+ return description;
21206
+ const suffix = result.error ? `; ${result.error}` : "";
21207
+ return `${description} (actual: ${result.actual}${suffix})`;
21208
+ }
21209
+ async function applyStructuredAssertionsToResult(input) {
21210
+ const assertions = input.scenario.assertions ?? [];
21211
+ if (assertions.length === 0) {
21212
+ return {
21213
+ status: input.status,
21214
+ reasoning: input.reasoning,
21215
+ assertionsPassed: [],
21216
+ assertionsFailed: [],
21217
+ assertionResults: []
21218
+ };
21219
+ }
21220
+ const results = await evaluateAssertions(input.page, assertions, {
21221
+ consoleErrors: input.consoleErrors
21222
+ });
21223
+ const assertionsPassed = results.filter((r) => r.passed).map(summarizeAssertionResult);
21224
+ const assertionsFailed = results.filter((r) => !r.passed).map(summarizeAssertionResult);
21225
+ const assertionResults = results.map((result) => ({
21226
+ type: result.assertion.type,
21227
+ description: assertionDescription(result),
21228
+ passed: result.passed,
21229
+ actual: result.actual,
21230
+ ...result.error ? { error: result.error } : {}
21231
+ }));
21232
+ const assertionsOk = allAssertionsPassed(results);
21233
+ const status = assertionsOk || input.status !== "passed" ? input.status : "failed";
21234
+ const assertionHeading = assertionsOk ? "Structured assertions passed:" : "Structured assertions failed:";
21235
+ const reasoningParts = [input.reasoning, `${assertionHeading}
21236
+ ${formatAssertionResults(results)}`].map((part) => part.trim()).filter(Boolean);
21237
+ return {
21238
+ status,
21239
+ reasoning: reasoningParts.join(`
21240
+
21241
+ `),
21242
+ assertionsPassed,
21243
+ assertionsFailed,
21244
+ assertionResults
21245
+ };
21246
+ }
20804
21247
  function withTimeout(promise, ms, label) {
20805
21248
  return new Promise((resolve, reject) => {
20806
21249
  const warningAt = Math.floor(ms * 0.8);
@@ -20861,7 +21304,7 @@ async function runSingleScenario(scenario, runId, options) {
20861
21304
  });
20862
21305
  }
20863
21306
  }
20864
- const client = createClientForModel(model, effectiveOptions.apiKey ?? config.anthropicApiKey);
21307
+ const client = createClientForModel(model, resolveAgentApiKeyForModel(model, effectiveOptions.apiKey, config.anthropicApiKey));
20865
21308
  const screenshotter = new Screenshotter({
20866
21309
  baseDir: effectiveOptions.screenshotDir ?? config.screenshots.dir
20867
21310
  });
@@ -20971,6 +21414,7 @@ async function runSingleScenario(scenario, runId, options) {
20971
21414
  model,
20972
21415
  runId,
20973
21416
  sessionId: result.id,
21417
+ baseUrl: options.url,
20974
21418
  maxTurns: effectiveOptions.minimal ? 10 : 30,
20975
21419
  a11y: effectiveOptions.a11y,
20976
21420
  persona: persona ? {
@@ -21053,27 +21497,46 @@ async function runSingleScenario(scenario, runId, options) {
21053
21497
  closeSession(result.id);
21054
21498
  const lightpandaNote = options.engine === "lightpanda" ? " (Running with Lightpanda \u2014 no screenshots)" : options.engine === "bun" ? " (Running with Bun.WebView \u2014 native, ~11x faster)" : "";
21055
21499
  const networkMeta = networkErrors.length > 0 ? { networkErrors: networkErrors.slice(0, 20) } : {};
21056
- let updatedResult = updateResult(result.id, {
21500
+ const baseReasoning = agentResult.reasoning ? agentResult.reasoning + lightpandaNote : lightpandaNote || "";
21501
+ const assertionOutcome = await applyStructuredAssertionsToResult({
21502
+ page,
21503
+ scenario,
21504
+ consoleErrors,
21057
21505
  status: agentResult.status,
21058
- reasoning: agentResult.reasoning ? agentResult.reasoning + lightpandaNote : lightpandaNote || undefined,
21506
+ reasoning: baseReasoning
21507
+ });
21508
+ const structuredAssertionMeta = assertionOutcome.assertionResults.length > 0 ? {
21509
+ structuredAssertions: {
21510
+ passed: assertionOutcome.assertionsPassed,
21511
+ failed: assertionOutcome.assertionsFailed,
21512
+ results: assertionOutcome.assertionResults
21513
+ }
21514
+ } : {};
21515
+ let updatedResult = updateResult(result.id, {
21516
+ status: assertionOutcome.status,
21517
+ reasoning: assertionOutcome.reasoning || undefined,
21059
21518
  stepsCompleted: agentResult.stepsCompleted,
21060
21519
  durationMs: Date.now() - new Date(result.createdAt).getTime(),
21061
21520
  tokensUsed: agentResult.tokensUsed,
21062
21521
  costCents: estimateCost(model, agentResult.tokensUsed),
21063
- metadata: { consoleLogs, ...networkErrors.length > 0 ? networkMeta : {} }
21522
+ metadata: {
21523
+ consoleLogs,
21524
+ ...networkErrors.length > 0 ? networkMeta : {},
21525
+ ...structuredAssertionMeta
21526
+ }
21064
21527
  });
21065
- if (agentResult.status === "failed" || agentResult.status === "error") {
21066
- const failureAnalysis = analyzeFailure(null, agentResult.reasoning ?? null);
21528
+ if (assertionOutcome.status === "failed" || assertionOutcome.status === "error") {
21529
+ const failureAnalysis = analyzeFailure(null, assertionOutcome.reasoning ?? null);
21067
21530
  if (failureAnalysis) {
21068
21531
  updatedResult = updateResult(result.id, { failureAnalysis });
21069
21532
  }
21070
21533
  }
21071
- if (agentResult.status === "passed") {
21534
+ if (assertionOutcome.status === "passed") {
21072
21535
  try {
21073
21536
  updateScenarioPassedCache(scenario.id, options.url);
21074
21537
  } catch {}
21075
21538
  }
21076
- const eventType = agentResult.status === "passed" ? "scenario:pass" : "scenario:fail";
21539
+ const eventType = assertionOutcome.status === "passed" ? "scenario:pass" : "scenario:fail";
21077
21540
  emit({ type: eventType, scenarioId: scenario.id, scenarioName: scenario.name, resultId: result.id, runId });
21078
21541
  return updatedResult;
21079
21542
  } catch (error) {
@@ -21098,7 +21561,8 @@ async function runSingleScenario(scenario, runId, options) {
21098
21561
  } finally {
21099
21562
  if (harPath) {
21100
21563
  try {
21101
- updateResult(result.id, { metadata: { harPath } });
21564
+ const existing = getResult(result.id);
21565
+ updateResult(result.id, { metadata: { ...existing?.metadata ?? {}, harPath } });
21102
21566
  } catch {}
21103
21567
  }
21104
21568
  if (browser) {
@@ -21270,22 +21734,31 @@ async function runBatch(scenarios, options) {
21270
21734
  }
21271
21735
  return { run: finalRun, results };
21272
21736
  }
21273
- async function runByFilter(options) {
21274
- let scenarios;
21737
+ function findScenarioInList(scenarios, id) {
21738
+ return scenarios.find((scenario) => scenario.id === id || scenario.shortId === id || scenario.id.startsWith(id)) ?? null;
21739
+ }
21740
+ function resolveScenariosForRun(options) {
21275
21741
  if (options.scenarioIds && options.scenarioIds.length > 0) {
21276
- const all = listScenarios({ projectId: options.projectId });
21277
- scenarios = all.filter((s) => options.scenarioIds.includes(s.id) || options.scenarioIds.includes(s.shortId));
21278
- if (scenarios.length === 0 && options.projectId) {
21279
- const global2 = listScenarios({});
21280
- scenarios = global2.filter((s) => options.scenarioIds.includes(s.id) || options.scenarioIds.includes(s.shortId));
21742
+ const scoped = listScenarios({ projectId: options.projectId });
21743
+ const resolved = [];
21744
+ const seen = new Set;
21745
+ for (const id of options.scenarioIds) {
21746
+ const scenario = findScenarioInList(scoped, id) ?? getScenario(id);
21747
+ if (scenario && !seen.has(scenario.id)) {
21748
+ resolved.push(scenario);
21749
+ seen.add(scenario.id);
21750
+ }
21281
21751
  }
21282
- } else {
21283
- scenarios = listScenarios({
21284
- projectId: options.projectId,
21285
- tags: options.tags,
21286
- priority: options.priority
21287
- });
21752
+ return resolved;
21288
21753
  }
21754
+ return listScenarios({
21755
+ projectId: options.projectId,
21756
+ tags: options.tags,
21757
+ priority: options.priority
21758
+ });
21759
+ }
21760
+ async function runByFilter(options) {
21761
+ const scenarios = resolveScenariosForRun(options);
21289
21762
  if (scenarios.length === 0) {
21290
21763
  const config = loadConfig();
21291
21764
  const model = resolveModel2(options.model ?? config.defaultModel);
@@ -21298,17 +21771,7 @@ async function runByFilter(options) {
21298
21771
  function startRunAsync(options) {
21299
21772
  const config = loadConfig();
21300
21773
  const model = resolveModel2(options.model ?? config.defaultModel);
21301
- let scenarios;
21302
- if (options.scenarioIds && options.scenarioIds.length > 0) {
21303
- const all = listScenarios({ projectId: options.projectId });
21304
- scenarios = all.filter((s) => options.scenarioIds.includes(s.id) || options.scenarioIds.includes(s.shortId));
21305
- } else {
21306
- scenarios = listScenarios({
21307
- projectId: options.projectId,
21308
- tags: options.tags,
21309
- priority: options.priority
21310
- });
21311
- }
21774
+ const scenarios = resolveScenariosForRun(options);
21312
21775
  if (!options.skipBudgetCheck) {
21313
21776
  const cap = options.maxCostCents ?? config.defaultMaxCostCents;
21314
21777
  if (cap !== undefined && cap > 0 && scenarios.length > 0) {
@@ -21412,6 +21875,7 @@ var init_runner = __esm(() => {
21412
21875
  init_session_tracker();
21413
21876
  init_webhooks();
21414
21877
  init_failure_pipeline();
21878
+ init_assertions();
21415
21879
  });
21416
21880
 
21417
21881
  // src/lib/affected.ts
@@ -22886,18 +23350,7 @@ function normalizeFilter(input) {
22886
23350
  };
22887
23351
  }
22888
23352
  function normalizeExecution(input) {
22889
- const target = input?.target ?? "local";
22890
- if (target === "connector:e2b") {
22891
- return {
22892
- target,
22893
- connector: input?.connector ?? "e2b",
22894
- operation: input?.operation ?? "run",
22895
- sandboxTemplate: input?.sandboxTemplate,
22896
- timeoutMs: input?.timeoutMs,
22897
- env: input?.env
22898
- };
22899
- }
22900
- return { ...DEFAULT_EXECUTION, timeoutMs: input?.timeoutMs };
23353
+ return input ? workflowExecutionFromValue(input) : DEFAULT_EXECUTION;
22901
23354
  }
22902
23355
  function createTestingWorkflow(input) {
22903
23356
  const db2 = getDatabase();
@@ -22948,6 +23401,9 @@ var init_workflows = __esm(() => {
22948
23401
  });
22949
23402
 
22950
23403
  // src/lib/workflow-runner.ts
23404
+ import { mkdtempSync, rmSync, writeFileSync as writeFileSync3 } from "fs";
23405
+ import { tmpdir } from "os";
23406
+ import { join as join14 } from "path";
22951
23407
  function buildWorkflowRunPlan(workflow, options) {
22952
23408
  const runOptions = {
22953
23409
  url: options.url,
@@ -22964,10 +23420,10 @@ function buildWorkflowRunPlan(workflow, options) {
22964
23420
  return {
22965
23421
  workflow,
22966
23422
  runOptions,
22967
- connectorCommand: workflow.execution.target === "connector:e2b" ? buildConnectorCommand(workflow.execution, runOptions) : null
23423
+ sandbox: workflow.execution.target === "sandbox" ? buildSandboxPlan(workflow, workflow.execution, runOptions) : null
22968
23424
  };
22969
23425
  }
22970
- async function runTestingWorkflow(workflowId, options) {
23426
+ async function runTestingWorkflow(workflowId, options, dependencies = {}) {
22971
23427
  const workflow = getTestingWorkflow(workflowId);
22972
23428
  if (!workflow)
22973
23429
  throw new Error(`Testing workflow not found: ${workflowId}`);
@@ -22977,13 +23433,25 @@ async function runTestingWorkflow(workflowId, options) {
22977
23433
  const plan = buildWorkflowRunPlan(workflow, options);
22978
23434
  if (options.dryRun)
22979
23435
  return { run: null, results: [], plan };
22980
- if (workflow.execution.target === "connector:e2b") {
22981
- const connectorResult = await runViaConnector(plan);
22982
- return { run: null, results: [], plan, connectorResult };
23436
+ if (workflow.execution.target === "sandbox") {
23437
+ const sandboxResult = await runViaSandbox(plan, dependencies);
23438
+ return { run: null, results: [], plan, sandboxResult };
22983
23439
  }
22984
- const { run, results } = await runByFilter(plan.runOptions);
23440
+ const runLocal = dependencies.runByFilter ?? runByFilter;
23441
+ const { run, results } = await runLocal(plan.runOptions);
22985
23442
  return { run, results, plan };
22986
23443
  }
23444
+ function createWorkflowDatabaseBundle(workflow, plan) {
23445
+ if (!plan.sandbox)
23446
+ throw new Error(`Workflow is not configured for sandbox execution: ${workflow.name}`);
23447
+ const localDir = mkdtempSync(join14(tmpdir(), `testers-workflow-${workflow.id.slice(0, 8)}-`));
23448
+ writeFileSync3(join14(localDir, "testers.db"), getDatabase().serialize());
23449
+ return {
23450
+ localDir,
23451
+ remoteDir: plan.sandbox.stateRemoteDir,
23452
+ cleanup: () => rmSync(localDir, { recursive: true, force: true })
23453
+ };
23454
+ }
22987
23455
  function validatePersonaIds(workflow) {
22988
23456
  for (const personaId of workflow.personaIds) {
22989
23457
  if (!getPersona(personaId)) {
@@ -22991,48 +23459,112 @@ function validatePersonaIds(workflow) {
22991
23459
  }
22992
23460
  }
22993
23461
  }
22994
- function buildConnectorCommand(execution, runOptions) {
22995
- const connector = execution.connector ?? "e2b";
22996
- const operation = execution.operation ?? "run";
22997
- const payload = JSON.stringify({
22998
- operation,
22999
- template: execution.sandboxTemplate,
23462
+ function buildSandboxPlan(workflow, execution, runOptions) {
23463
+ const remoteDir = execution.sandboxRemoteDir ?? `/tmp/testers-workflow-${workflow.id.slice(0, 8)}`;
23464
+ const stateRemoteDir = `${remoteDir.replace(/\/+$/, "")}/.testers-state`;
23465
+ return {
23466
+ provider: execution.provider,
23467
+ image: execution.sandboxImage,
23468
+ name: `testers-${workflow.id.slice(0, 8)}`,
23469
+ remoteDir,
23470
+ stateRemoteDir,
23471
+ cleanup: execution.sandboxCleanup ?? "delete",
23000
23472
  timeoutMs: execution.timeoutMs,
23001
- env: execution.env ?? {},
23002
- command: [
23003
- "bunx",
23004
- "@hasna/testers",
23005
- "run",
23006
- runOptions.url,
23007
- ...runOptions.scenarioIds?.length ? ["--scenario", runOptions.scenarioIds.join(",")] : [],
23008
- ...runOptions.tags?.length ? runOptions.tags.flatMap((tag) => ["--tag", tag]) : [],
23009
- ...runOptions.priority ? ["--priority", runOptions.priority] : [],
23010
- ...runOptions.projectId ? ["--project", runOptions.projectId] : [],
23011
- ...runOptions.model ? ["--model", runOptions.model] : [],
23012
- "--json"
23013
- ]
23014
- });
23015
- return ["connectors", "run", connector, operation, payload];
23473
+ env: execution.env,
23474
+ command: buildSandboxCommand({
23475
+ runOptions,
23476
+ remoteDir,
23477
+ dbPath: `${stateRemoteDir}/testers.db`,
23478
+ setupCommand: execution.setupCommand,
23479
+ packageSpec: execution.packageSpec ?? "@hasna/testers"
23480
+ })
23481
+ };
23016
23482
  }
23017
- async function runViaConnector(plan) {
23018
- if (!plan.connectorCommand)
23019
- throw new Error("Workflow does not have a connector command");
23020
- const proc = Bun.spawn(plan.connectorCommand, {
23021
- stdout: "pipe",
23022
- stderr: "pipe",
23023
- env: process.env
23024
- });
23025
- const [stdout, stderr, exitCode] = await Promise.all([
23026
- new Response(proc.stdout).text(),
23027
- new Response(proc.stderr).text(),
23028
- proc.exited
23029
- ]);
23030
- if (exitCode !== 0) {
23031
- throw new Error(`Connector execution failed (${exitCode}): ${stderr || stdout}`);
23483
+ function buildSandboxCommand(input) {
23484
+ const args = [
23485
+ "bunx",
23486
+ input.packageSpec,
23487
+ "run",
23488
+ input.runOptions.url,
23489
+ ...input.runOptions.scenarioIds?.length ? ["--scenario", input.runOptions.scenarioIds.join(",")] : [],
23490
+ ...input.runOptions.tags?.length ? input.runOptions.tags.flatMap((tag) => ["--tag", tag]) : [],
23491
+ ...input.runOptions.priority ? ["--priority", input.runOptions.priority] : [],
23492
+ ...input.runOptions.projectId ? ["--project", input.runOptions.projectId] : [],
23493
+ ...input.runOptions.model ? ["--model", input.runOptions.model] : [],
23494
+ ...input.runOptions.headed ? ["--headed"] : [],
23495
+ ...input.runOptions.parallel ? ["--parallel", String(input.runOptions.parallel)] : [],
23496
+ ...input.runOptions.timeout ? ["--timeout", String(input.runOptions.timeout)] : [],
23497
+ ...input.runOptions.personaIds?.length ? ["--persona", input.runOptions.personaIds.join(",")] : [],
23498
+ "--no-auto-generate",
23499
+ "--json"
23500
+ ];
23501
+ return [
23502
+ "set -euo pipefail",
23503
+ `mkdir -p ${shellQuote(input.remoteDir)}`,
23504
+ `cd ${shellQuote(input.remoteDir)}`,
23505
+ input.setupCommand,
23506
+ `HASNA_TESTERS_DB_PATH=${shellQuote(input.dbPath)} ${args.map(shellQuote).join(" ")}`
23507
+ ].filter(Boolean).join(`
23508
+ `);
23509
+ }
23510
+ async function runViaSandbox(plan, dependencies) {
23511
+ if (!plan.sandbox)
23512
+ throw new Error("Workflow does not have a sandbox plan");
23513
+ const sandboxes = await resolveSandboxesRuntime(dependencies);
23514
+ const createBundle = dependencies.createDatabaseBundle ?? createWorkflowDatabaseBundle;
23515
+ const bundle = createBundle(plan.workflow, plan);
23516
+ try {
23517
+ const raw = await sandboxes.runCommandInSandbox({
23518
+ command: plan.sandbox.command,
23519
+ provider: plan.sandbox.provider,
23520
+ name: plan.sandbox.name,
23521
+ image: plan.sandbox.image,
23522
+ sandboxTimeout: plan.sandbox.timeoutMs,
23523
+ commandTimeoutMs: plan.sandbox.timeoutMs,
23524
+ projectId: plan.workflow.projectId ?? undefined,
23525
+ config: {
23526
+ source: "testers",
23527
+ workflowId: plan.workflow.id,
23528
+ workflowName: plan.workflow.name
23529
+ },
23530
+ sandboxEnvVars: plan.sandbox.env,
23531
+ cleanup: plan.sandbox.cleanup,
23532
+ upload: {
23533
+ localDir: bundle.localDir,
23534
+ remoteDir: bundle.remoteDir
23535
+ }
23536
+ });
23537
+ const exitCode = raw.result.exit_code ?? raw.result.exitCode ?? 0;
23538
+ const stdout = raw.result.stdout ?? "";
23539
+ const stderr = raw.result.stderr ?? "";
23540
+ if (exitCode !== 0) {
23541
+ throw new Error(`Sandbox workflow execution failed (${exitCode}): ${stderr || stdout}`);
23542
+ }
23543
+ return {
23544
+ sandboxId: raw.sandbox.id,
23545
+ sessionId: raw.session.id,
23546
+ exitCode,
23547
+ stdout,
23548
+ stderr,
23549
+ cleanup: raw.cleanup
23550
+ };
23551
+ } finally {
23552
+ bundle.cleanup?.();
23032
23553
  }
23033
- return stdout.trim();
23554
+ }
23555
+ async function resolveSandboxesRuntime(dependencies) {
23556
+ if (dependencies.sandboxes)
23557
+ return dependencies.sandboxes;
23558
+ if (dependencies.createSandboxesSDK)
23559
+ return dependencies.createSandboxesSDK();
23560
+ const mod = await import("@hasna/sandboxes");
23561
+ return mod.createSandboxesSDK();
23562
+ }
23563
+ function shellQuote(value) {
23564
+ return `'${value.replaceAll("'", `'"'"'`)}'`;
23034
23565
  }
23035
23566
  var init_workflow_runner = __esm(() => {
23567
+ init_database();
23036
23568
  init_workflows();
23037
23569
  init_personas();
23038
23570
  init_runner();
@@ -34705,34 +35237,27 @@ var init_v3 = __esm(() => {
34705
35237
 
34706
35238
  // node_modules/@ai-sdk/provider-utils/node_modules/eventsource-parser/dist/index.js
34707
35239
  function noop(_arg) {}
34708
- function createParser(config2) {
34709
- if (typeof config2 == "function")
34710
- throw new TypeError("`config` must be an object, got a function instead. Did you mean `createParser({onEvent: fn})`?");
34711
- const { onEvent = noop, onError = noop, onRetry = noop, onComment, maxBufferSize } = config2, pendingFragments = [];
34712
- let pendingFragmentsLength = 0, isFirstChunk = true, id, data = "", dataLines = 0, eventType, terminated = false;
35240
+ function createParser(callbacks) {
35241
+ if (typeof callbacks == "function")
35242
+ throw new TypeError("`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?");
35243
+ const { onEvent = noop, onError = noop, onRetry = noop, onComment } = callbacks, pendingFragments = [];
35244
+ let isFirstChunk = true, id, data = "", dataLines = 0, eventType;
34713
35245
  function feed(chunk) {
34714
- if (terminated)
34715
- throw new Error("Cannot feed parser: it was terminated after exceeding the configured max buffer size. Call `reset()` to resume parsing.");
34716
35246
  if (isFirstChunk && (isFirstChunk = false, chunk.charCodeAt(0) === 239 && chunk.charCodeAt(1) === 187 && chunk.charCodeAt(2) === 191 && (chunk = chunk.slice(3))), pendingFragments.length === 0) {
34717
35247
  const trailing2 = processLines(chunk);
34718
- trailing2 !== "" && (pendingFragments.push(trailing2), pendingFragmentsLength = trailing2.length), checkBufferSize();
35248
+ trailing2 !== "" && pendingFragments.push(trailing2);
34719
35249
  return;
34720
35250
  }
34721
35251
  if (chunk.indexOf(`
34722
35252
  `) === -1 && chunk.indexOf("\r") === -1) {
34723
- pendingFragments.push(chunk), pendingFragmentsLength += chunk.length, checkBufferSize();
35253
+ pendingFragments.push(chunk);
34724
35254
  return;
34725
35255
  }
34726
35256
  pendingFragments.push(chunk);
34727
35257
  const input = pendingFragments.join("");
34728
- pendingFragments.length = 0, pendingFragmentsLength = 0;
35258
+ pendingFragments.length = 0;
34729
35259
  const trailing = processLines(input);
34730
- trailing !== "" && (pendingFragments.push(trailing), pendingFragmentsLength = trailing.length), checkBufferSize();
34731
- }
34732
- function checkBufferSize() {
34733
- maxBufferSize !== undefined && (pendingFragmentsLength + data.length <= maxBufferSize || (terminated = true, pendingFragments.length = 0, pendingFragmentsLength = 0, id = undefined, data = "", dataLines = 0, eventType = undefined, onError(new ParseError(`Buffered data exceeded max buffer size of ${maxBufferSize} characters`, {
34734
- type: "max-buffer-size-exceeded"
34735
- }))));
35260
+ trailing !== "" && pendingFragments.push(trailing);
34736
35261
  }
34737
35262
  function processLines(chunk) {
34738
35263
  let searchIndex = 0;
@@ -34844,7 +35369,7 @@ ${value}`, dataLines++;
34844
35369
  const incompleteLine = pendingFragments.join("");
34845
35370
  parseLine(incompleteLine, 0, incompleteLine.length);
34846
35371
  }
34847
- isFirstChunk = true, id = undefined, data = "", dataLines = 0, eventType = undefined, pendingFragments.length = 0, pendingFragmentsLength = 0, terminated = false;
35372
+ isFirstChunk = true, id = undefined, data = "", dataLines = 0, eventType = undefined, pendingFragments.length = 0;
34848
35373
  }
34849
35374
  return { feed, reset };
34850
35375
  }
@@ -34868,7 +35393,7 @@ var EventSourceParserStream;
34868
35393
  var init_stream = __esm(() => {
34869
35394
  init_dist3();
34870
35395
  EventSourceParserStream = class EventSourceParserStream extends TransformStream {
34871
- constructor({ onError, onRetry, onComment, maxBufferSize } = {}) {
35396
+ constructor({ onError, onRetry, onComment } = {}) {
34872
35397
  let parser;
34873
35398
  super({
34874
35399
  start(controller) {
@@ -34877,11 +35402,10 @@ var init_stream = __esm(() => {
34877
35402
  controller.enqueue(event);
34878
35403
  },
34879
35404
  onError(error40) {
34880
- typeof onError == "function" && onError(error40), (onError === "terminate" || error40.type === "max-buffer-size-exceeded") && controller.error(error40);
35405
+ onError === "terminate" ? controller.error(error40) : typeof onError == "function" && onError(error40);
34881
35406
  },
34882
35407
  onRetry,
34883
- onComment,
34884
- maxBufferSize
35408
+ onComment
34885
35409
  });
34886
35410
  },
34887
35411
  transform(chunk) {
@@ -36320,7 +36844,7 @@ var DelayedPromise = class {
36320
36844
  });
36321
36845
  }
36322
36846
  return () => `${prefix}${separator}${generator()}`;
36323
- }, generateId, FETCH_FAILED_ERROR_MESSAGES, BUN_ERROR_CODES, VERSION = "4.0.27", getOriginalFetch = () => globalThis.fetch, getFromApi = async ({
36847
+ }, generateId, FETCH_FAILED_ERROR_MESSAGES, BUN_ERROR_CODES, VERSION = "4.0.26", getOriginalFetch = () => globalThis.fetch, getFromApi = async ({
36324
36848
  url: url2,
36325
36849
  headers = {},
36326
36850
  successfulResponseHandler,
@@ -38459,7 +38983,7 @@ var import_oidc, import_oidc2, marker17 = "vercel.ai.gateway.error", symbol18, _
38459
38983
  "ai-model-id": this.modelId
38460
38984
  };
38461
38985
  }
38462
- }, gatewayRerankingResponseSchema, parallelSearchInputSchema, parallelSearchOutputSchema, parallelSearchToolFactory, parallelSearch = (config2 = {}) => parallelSearchToolFactory(config2), perplexitySearchInputSchema, perplexitySearchOutputSchema, perplexitySearchToolFactory, perplexitySearch = (config2 = {}) => perplexitySearchToolFactory(config2), gatewayTools, VERSION2 = "3.0.120", AI_GATEWAY_PROTOCOL_VERSION = "0.0.1", gateway;
38986
+ }, gatewayRerankingResponseSchema, parallelSearchInputSchema, parallelSearchOutputSchema, parallelSearchToolFactory, parallelSearch = (config2 = {}) => parallelSearchToolFactory(config2), perplexitySearchInputSchema, perplexitySearchOutputSchema, perplexitySearchToolFactory, perplexitySearch = (config2 = {}) => perplexitySearchToolFactory(config2), gatewayTools, VERSION2 = "3.0.110", AI_GATEWAY_PROTOCOL_VERSION = "0.0.1", gateway;
38463
38987
  var init_dist5 = __esm(() => {
38464
38988
  init_dist4();
38465
38989
  init_dist2();
@@ -38498,15 +39022,13 @@ var init_dist5 = __esm(() => {
38498
39022
  message,
38499
39023
  statusCode = 500,
38500
39024
  cause,
38501
- generationId,
38502
- isRetryable = statusCode != null && (statusCode === 408 || statusCode === 409 || statusCode === 429 || statusCode >= 500)
39025
+ generationId
38503
39026
  }) {
38504
39027
  super(generationId ? `${message} [${generationId}]` : message);
38505
39028
  this[_a17] = true;
38506
39029
  this.statusCode = statusCode;
38507
39030
  this.cause = cause;
38508
39031
  this.generationId = generationId;
38509
- this.isRetryable = isRetryable;
38510
39032
  }
38511
39033
  static isInstance(error40) {
38512
39034
  return _GatewayError.hasMarker(error40);
@@ -39029,11 +39551,62 @@ Run 'npx vercel link' to link your project, then 'vc env pull' to fetch the toke
39029
39551
  gateway = createGatewayProvider();
39030
39552
  });
39031
39553
 
39554
+ // node_modules/@opentelemetry/api/build/src/platform/node/globalThis.js
39555
+ var require_globalThis = __commonJS((exports) => {
39556
+ Object.defineProperty(exports, "__esModule", { value: true });
39557
+ exports._globalThis = undefined;
39558
+ exports._globalThis = typeof globalThis === "object" ? globalThis : global;
39559
+ });
39560
+
39561
+ // node_modules/@opentelemetry/api/build/src/platform/node/index.js
39562
+ var require_node = __commonJS((exports) => {
39563
+ var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
39564
+ if (k2 === undefined)
39565
+ k2 = k;
39566
+ Object.defineProperty(o, k2, { enumerable: true, get: function() {
39567
+ return m[k];
39568
+ } });
39569
+ } : function(o, m, k, k2) {
39570
+ if (k2 === undefined)
39571
+ k2 = k;
39572
+ o[k2] = m[k];
39573
+ });
39574
+ var __exportStar = exports && exports.__exportStar || function(m, exports2) {
39575
+ for (var p in m)
39576
+ if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p))
39577
+ __createBinding(exports2, m, p);
39578
+ };
39579
+ Object.defineProperty(exports, "__esModule", { value: true });
39580
+ __exportStar(require_globalThis(), exports);
39581
+ });
39582
+
39583
+ // node_modules/@opentelemetry/api/build/src/platform/index.js
39584
+ var require_platform = __commonJS((exports) => {
39585
+ var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
39586
+ if (k2 === undefined)
39587
+ k2 = k;
39588
+ Object.defineProperty(o, k2, { enumerable: true, get: function() {
39589
+ return m[k];
39590
+ } });
39591
+ } : function(o, m, k, k2) {
39592
+ if (k2 === undefined)
39593
+ k2 = k;
39594
+ o[k2] = m[k];
39595
+ });
39596
+ var __exportStar = exports && exports.__exportStar || function(m, exports2) {
39597
+ for (var p in m)
39598
+ if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p))
39599
+ __createBinding(exports2, m, p);
39600
+ };
39601
+ Object.defineProperty(exports, "__esModule", { value: true });
39602
+ __exportStar(require_node(), exports);
39603
+ });
39604
+
39032
39605
  // node_modules/@opentelemetry/api/build/src/version.js
39033
39606
  var require_version = __commonJS((exports) => {
39034
39607
  Object.defineProperty(exports, "__esModule", { value: true });
39035
39608
  exports.VERSION = undefined;
39036
- exports.VERSION = "1.9.1";
39609
+ exports.VERSION = "1.9.0";
39037
39610
  });
39038
39611
 
39039
39612
  // node_modules/@opentelemetry/api/build/src/internal/semver.js
@@ -39111,11 +39684,12 @@ var require_semver = __commonJS((exports) => {
39111
39684
  var require_global_utils = __commonJS((exports) => {
39112
39685
  Object.defineProperty(exports, "__esModule", { value: true });
39113
39686
  exports.unregisterGlobal = exports.getGlobal = exports.registerGlobal = undefined;
39687
+ var platform_1 = require_platform();
39114
39688
  var version_1 = require_version();
39115
39689
  var semver_1 = require_semver();
39116
39690
  var major = version_1.VERSION.split(".")[0];
39117
39691
  var GLOBAL_OPENTELEMETRY_API_KEY = Symbol.for(`opentelemetry.js.api.${major}`);
39118
- var _global = typeof globalThis === "object" ? globalThis : typeof self === "object" ? self : typeof window === "object" ? window : typeof global === "object" ? global : {};
39692
+ var _global = platform_1._globalThis;
39119
39693
  function registerGlobal(type, instance, diag, allowOverride = false) {
39120
39694
  var _a16;
39121
39695
  const api2 = _global[GLOBAL_OPENTELEMETRY_API_KEY] = (_a16 = _global[GLOBAL_OPENTELEMETRY_API_KEY]) !== null && _a16 !== undefined ? _a16 : {
@@ -39187,7 +39761,8 @@ var require_ComponentLogger = __commonJS((exports) => {
39187
39761
  if (!logger) {
39188
39762
  return;
39189
39763
  }
39190
- return logger[funcName](namespace, ...args);
39764
+ args.unshift(namespace);
39765
+ return logger[funcName](...args);
39191
39766
  }
39192
39767
  });
39193
39768
 
@@ -39248,12 +39823,6 @@ var require_diag = __commonJS((exports) => {
39248
39823
  var API_NAME = "diag";
39249
39824
 
39250
39825
  class DiagAPI {
39251
- static instance() {
39252
- if (!this._instance) {
39253
- this._instance = new DiagAPI;
39254
- }
39255
- return this._instance;
39256
- }
39257
39826
  constructor() {
39258
39827
  function _logProxy(funcName) {
39259
39828
  return function(...args) {
@@ -39298,6 +39867,12 @@ var require_diag = __commonJS((exports) => {
39298
39867
  self2.warn = _logProxy("warn");
39299
39868
  self2.error = _logProxy("error");
39300
39869
  }
39870
+ static instance() {
39871
+ if (!this._instance) {
39872
+ this._instance = new DiagAPI;
39873
+ }
39874
+ return this._instance;
39875
+ }
39301
39876
  }
39302
39877
  exports.DiagAPI = DiagAPI;
39303
39878
  });
@@ -39319,7 +39894,7 @@ var require_baggage_impl = __commonJS((exports) => {
39319
39894
  return Object.assign({}, entry);
39320
39895
  }
39321
39896
  getAllEntries() {
39322
- return Array.from(this._entries.entries());
39897
+ return Array.from(this._entries.entries()).map(([k, v]) => [k, v]);
39323
39898
  }
39324
39899
  setEntry(key, entry) {
39325
39900
  const newBaggage = new BaggageImpl(this._entries);
@@ -39411,7 +39986,7 @@ var require_context = __commonJS((exports) => {
39411
39986
  // node_modules/@opentelemetry/api/build/src/diag/consoleLogger.js
39412
39987
  var require_consoleLogger = __commonJS((exports) => {
39413
39988
  Object.defineProperty(exports, "__esModule", { value: true });
39414
- exports.DiagConsoleLogger = exports._originalConsoleMethods = undefined;
39989
+ exports.DiagConsoleLogger = undefined;
39415
39990
  var consoleMap = [
39416
39991
  { n: "error", c: "error" },
39417
39992
  { n: "warn", c: "warn" },
@@ -39419,39 +39994,19 @@ var require_consoleLogger = __commonJS((exports) => {
39419
39994
  { n: "debug", c: "debug" },
39420
39995
  { n: "verbose", c: "trace" }
39421
39996
  ];
39422
- exports._originalConsoleMethods = {};
39423
- if (typeof console !== "undefined") {
39424
- const keys = [
39425
- "error",
39426
- "warn",
39427
- "info",
39428
- "debug",
39429
- "trace",
39430
- "log"
39431
- ];
39432
- for (const key of keys) {
39433
- if (typeof console[key] === "function") {
39434
- exports._originalConsoleMethods[key] = console[key];
39435
- }
39436
- }
39437
- }
39438
39997
 
39439
39998
  class DiagConsoleLogger {
39440
39999
  constructor() {
39441
40000
  function _consoleFunc(funcName) {
39442
40001
  return function(...args) {
39443
- let theFunc = exports._originalConsoleMethods[funcName];
39444
- if (typeof theFunc !== "function") {
39445
- theFunc = exports._originalConsoleMethods["log"];
39446
- }
39447
- if (typeof theFunc !== "function" && console) {
39448
- theFunc = console[funcName];
40002
+ if (console) {
40003
+ let theFunc = console[funcName];
39449
40004
  if (typeof theFunc !== "function") {
39450
40005
  theFunc = console.log;
39451
40006
  }
39452
- }
39453
- if (typeof theFunc === "function") {
39454
- return theFunc.apply(console, args);
40007
+ if (typeof theFunc === "function") {
40008
+ return theFunc.apply(console, args);
40009
+ }
39455
40010
  }
39456
40011
  };
39457
40012
  }
@@ -39689,8 +40244,8 @@ var require_NonRecordingSpan = __commonJS((exports) => {
39689
40244
  var invalid_span_constants_1 = require_invalid_span_constants();
39690
40245
 
39691
40246
  class NonRecordingSpan {
39692
- constructor(spanContext = invalid_span_constants_1.INVALID_SPAN_CONTEXT) {
39693
- this._spanContext = spanContext;
40247
+ constructor(_spanContext = invalid_span_constants_1.INVALID_SPAN_CONTEXT) {
40248
+ this._spanContext = _spanContext;
39694
40249
  }
39695
40250
  spanContext() {
39696
40251
  return this._spanContext;
@@ -39766,126 +40321,14 @@ var require_spancontext_utils = __commonJS((exports) => {
39766
40321
  exports.wrapSpanContext = exports.isSpanContextValid = exports.isValidSpanId = exports.isValidTraceId = undefined;
39767
40322
  var invalid_span_constants_1 = require_invalid_span_constants();
39768
40323
  var NonRecordingSpan_1 = require_NonRecordingSpan();
39769
- var isHex = new Uint8Array([
39770
- 0,
39771
- 0,
39772
- 0,
39773
- 0,
39774
- 0,
39775
- 0,
39776
- 0,
39777
- 0,
39778
- 0,
39779
- 0,
39780
- 0,
39781
- 0,
39782
- 0,
39783
- 0,
39784
- 0,
39785
- 0,
39786
- 0,
39787
- 0,
39788
- 0,
39789
- 0,
39790
- 0,
39791
- 0,
39792
- 0,
39793
- 0,
39794
- 0,
39795
- 0,
39796
- 0,
39797
- 0,
39798
- 0,
39799
- 0,
39800
- 0,
39801
- 0,
39802
- 0,
39803
- 0,
39804
- 0,
39805
- 0,
39806
- 0,
39807
- 0,
39808
- 0,
39809
- 0,
39810
- 0,
39811
- 0,
39812
- 0,
39813
- 0,
39814
- 0,
39815
- 0,
39816
- 0,
39817
- 0,
39818
- 1,
39819
- 1,
39820
- 1,
39821
- 1,
39822
- 1,
39823
- 1,
39824
- 1,
39825
- 1,
39826
- 1,
39827
- 1,
39828
- 0,
39829
- 0,
39830
- 0,
39831
- 0,
39832
- 0,
39833
- 0,
39834
- 0,
39835
- 1,
39836
- 1,
39837
- 1,
39838
- 1,
39839
- 1,
39840
- 1,
39841
- 0,
39842
- 0,
39843
- 0,
39844
- 0,
39845
- 0,
39846
- 0,
39847
- 0,
39848
- 0,
39849
- 0,
39850
- 0,
39851
- 0,
39852
- 0,
39853
- 0,
39854
- 0,
39855
- 0,
39856
- 0,
39857
- 0,
39858
- 0,
39859
- 0,
39860
- 0,
39861
- 0,
39862
- 0,
39863
- 0,
39864
- 0,
39865
- 0,
39866
- 0,
39867
- 1,
39868
- 1,
39869
- 1,
39870
- 1,
39871
- 1,
39872
- 1
39873
- ]);
39874
- function isValidHex(id, length) {
39875
- if (typeof id !== "string" || id.length !== length)
39876
- return false;
39877
- let r = 0;
39878
- for (let i = 0;i < id.length; i += 4) {
39879
- r += (isHex[id.charCodeAt(i)] | 0) + (isHex[id.charCodeAt(i + 1)] | 0) + (isHex[id.charCodeAt(i + 2)] | 0) + (isHex[id.charCodeAt(i + 3)] | 0);
39880
- }
39881
- return r === length;
39882
- }
40324
+ var VALID_TRACEID_REGEX = /^([0-9a-f]{32})$/i;
40325
+ var VALID_SPANID_REGEX = /^[0-9a-f]{16}$/i;
39883
40326
  function isValidTraceId(traceId) {
39884
- return isValidHex(traceId, 32) && traceId !== invalid_span_constants_1.INVALID_TRACEID;
40327
+ return VALID_TRACEID_REGEX.test(traceId) && traceId !== invalid_span_constants_1.INVALID_TRACEID;
39885
40328
  }
39886
40329
  exports.isValidTraceId = isValidTraceId;
39887
40330
  function isValidSpanId(spanId) {
39888
- return isValidHex(spanId, 16) && spanId !== invalid_span_constants_1.INVALID_SPANID;
40331
+ return VALID_SPANID_REGEX.test(spanId) && spanId !== invalid_span_constants_1.INVALID_SPANID;
39889
40332
  }
39890
40333
  exports.isValidSpanId = isValidSpanId;
39891
40334
  function isSpanContextValid(spanContext) {
@@ -39945,7 +40388,7 @@ var require_NoopTracer = __commonJS((exports) => {
39945
40388
  }
39946
40389
  exports.NoopTracer = NoopTracer;
39947
40390
  function isSpanContext(spanContext) {
39948
- return spanContext !== null && typeof spanContext === "object" && "spanId" in spanContext && typeof spanContext["spanId"] === "string" && "traceId" in spanContext && typeof spanContext["traceId"] === "string" && "traceFlags" in spanContext && typeof spanContext["traceFlags"] === "number";
40391
+ return typeof spanContext === "object" && typeof spanContext["spanId"] === "string" && typeof spanContext["traceId"] === "string" && typeof spanContext["traceFlags"] === "number";
39949
40392
  }
39950
40393
  });
39951
40394
 
@@ -39957,8 +40400,8 @@ var require_ProxyTracer = __commonJS((exports) => {
39957
40400
  var NOOP_TRACER = new NoopTracer_1.NoopTracer;
39958
40401
 
39959
40402
  class ProxyTracer {
39960
- constructor(provider, name15, version2, options) {
39961
- this._provider = provider;
40403
+ constructor(_provider, name15, version2, options) {
40404
+ this._provider = _provider;
39962
40405
  this.name = name15;
39963
40406
  this.version = version2;
39964
40407
  this.options = options;
@@ -40118,7 +40561,7 @@ var require_tracestate_impl = __commonJS((exports) => {
40118
40561
  return this._internalState.get(key);
40119
40562
  }
40120
40563
  serialize() {
40121
- return Array.from(this._internalState.keys()).reduceRight((agg, key) => {
40564
+ return this._keys().reduce((agg, key) => {
40122
40565
  agg.push(key + LIST_MEMBER_KEY_VALUE_SPLITTER + this.get(key));
40123
40566
  return agg;
40124
40567
  }, []).join(LIST_MEMBERS_SEPARATOR);
@@ -40126,7 +40569,7 @@ var require_tracestate_impl = __commonJS((exports) => {
40126
40569
  _parse(rawTraceState) {
40127
40570
  if (rawTraceState.length > MAX_TRACE_STATE_LEN)
40128
40571
  return;
40129
- this._internalState = rawTraceState.split(LIST_MEMBERS_SEPARATOR).reduceRight((agg, part) => {
40572
+ this._internalState = rawTraceState.split(LIST_MEMBERS_SEPARATOR).reverse().reduce((agg, part) => {
40130
40573
  const listMember = part.trim();
40131
40574
  const i = listMember.indexOf(LIST_MEMBER_KEY_VALUE_SPLITTER);
40132
40575
  if (i !== -1) {
@@ -41226,10 +41669,7 @@ function convertToLanguageModelMessage({
41226
41669
  type: "tool-result",
41227
41670
  toolCallId: part.toolCallId,
41228
41671
  toolName: part.toolName,
41229
- output: mapToolResultOutput({
41230
- output: part.output,
41231
- downloadedAssets
41232
- }),
41672
+ output: mapToolResultOutput(part.output),
41233
41673
  providerOptions
41234
41674
  };
41235
41675
  }
@@ -41248,10 +41688,7 @@ function convertToLanguageModelMessage({
41248
41688
  type: "tool-result",
41249
41689
  toolCallId: part.toolCallId,
41250
41690
  toolName: part.toolName,
41251
- output: mapToolResultOutput({
41252
- output: part.output,
41253
- downloadedAssets
41254
- }),
41691
+ output: mapToolResultOutput(part.output),
41255
41692
  providerOptions: part.providerOptions
41256
41693
  };
41257
41694
  }
@@ -41275,44 +41712,15 @@ function convertToLanguageModelMessage({
41275
41712
  }
41276
41713
  }
41277
41714
  async function downloadAssets(messages, download2, supportedUrls) {
41278
- var _a21;
41279
- const downloadableFiles = [];
41280
- for (const message of messages) {
41281
- if (message.role === "user" && Array.isArray(message.content)) {
41282
- for (const part of message.content) {
41283
- if (part.type === "image" || part.type === "file") {
41284
- downloadableFiles.push({
41285
- data: part.type === "image" ? part.image : part.data,
41286
- mediaType: (_a21 = part.mediaType) != null ? _a21 : part.type === "image" ? "image/*" : undefined
41287
- });
41288
- }
41289
- }
41290
- }
41291
- if (message.role === "tool" || message.role === "assistant") {
41292
- if (!Array.isArray(message.content)) {
41293
- continue;
41294
- }
41295
- for (const part of message.content) {
41296
- if (part.type !== "tool-result") {
41297
- continue;
41298
- }
41299
- if (part.output.type !== "content") {
41300
- continue;
41301
- }
41302
- for (const contentPart of part.output.value) {
41303
- if (contentPart.type === "image-url" || contentPart.type === "file-url") {
41304
- downloadableFiles.push({
41305
- data: new URL(contentPart.url),
41306
- mediaType: contentPart.type === "image-url" ? "image/*" : undefined
41307
- });
41308
- }
41309
- }
41310
- }
41715
+ const plannedDownloads = messages.filter((message) => message.role === "user").map((message) => message.content).filter((content) => Array.isArray(content)).flat().filter((part) => part.type === "image" || part.type === "file").map((part) => {
41716
+ var _a21;
41717
+ const mediaType = (_a21 = part.mediaType) != null ? _a21 : part.type === "image" ? "image/*" : undefined;
41718
+ let data = part.type === "image" ? part.image : part.data;
41719
+ if (typeof data === "string") {
41720
+ try {
41721
+ data = new URL(data);
41722
+ } catch (ignored) {}
41311
41723
  }
41312
- }
41313
- const plannedDownloads = downloadableFiles.map((part) => {
41314
- const mediaType = part.mediaType;
41315
- const { data } = convertToLanguageModelV3DataContent(part.data);
41316
41724
  return { mediaType, data };
41317
41725
  }).filter((part) => part.data instanceof URL).map((part) => ({
41318
41726
  url: part.data,
@@ -41386,41 +41794,13 @@ function convertPartToLanguageModelPart(part, downloadedAssets) {
41386
41794
  }
41387
41795
  }
41388
41796
  }
41389
- function mapToolResultOutput({
41390
- output,
41391
- downloadedAssets
41392
- }) {
41797
+ function mapToolResultOutput(output) {
41393
41798
  if (output.type !== "content") {
41394
41799
  return output;
41395
41800
  }
41396
41801
  return {
41397
41802
  type: "content",
41398
41803
  value: output.value.map((item) => {
41399
- var _a21, _b16;
41400
- if (item.type === "image-url") {
41401
- const downloadedFile = downloadedAssets[new URL(item.url).toString()];
41402
- if (downloadedFile) {
41403
- return {
41404
- type: "image-data",
41405
- data: convertDataContentToBase64String(downloadedFile.data),
41406
- mediaType: (_a21 = downloadedFile.mediaType) != null ? _a21 : "image/*",
41407
- providerOptions: item.providerOptions
41408
- };
41409
- }
41410
- return item;
41411
- }
41412
- if (item.type === "file-url") {
41413
- const downloadedFile = downloadedAssets[new URL(item.url).toString()];
41414
- if (downloadedFile) {
41415
- return {
41416
- type: "file-data",
41417
- data: convertDataContentToBase64String(downloadedFile.data),
41418
- mediaType: (_b16 = downloadedFile.mediaType) != null ? _b16 : "application/octet-stream",
41419
- providerOptions: item.providerOptions
41420
- };
41421
- }
41422
- return item;
41423
- }
41424
41804
  if (item.type !== "media") {
41425
41805
  return item;
41426
41806
  }
@@ -41973,7 +42353,7 @@ function getRetryDelayInMs({
41973
42353
  error: error40,
41974
42354
  exponentialBackoffDelay
41975
42355
  }) {
41976
- const headers = APICallError.isInstance(error40) ? error40.responseHeaders : APICallError.isInstance(error40.cause) ? error40.cause.responseHeaders : undefined;
42356
+ const headers = error40.responseHeaders;
41977
42357
  if (!headers)
41978
42358
  return exponentialBackoffDelay;
41979
42359
  let ms;
@@ -42023,7 +42403,7 @@ async function _retryWithExponentialBackoff(f, {
42023
42403
  errors: newErrors
42024
42404
  });
42025
42405
  }
42026
- if (error40 instanceof Error && (APICallError.isInstance(error40) && error40.isRetryable === true || GatewayError.isInstance(error40) && error40.isRetryable === true) && tryNumber <= maxRetries) {
42406
+ if (error40 instanceof Error && APICallError.isInstance(error40) && error40.isRetryable === true && tryNumber <= maxRetries) {
42027
42407
  await delay(getRetryDelayInMs({
42028
42408
  error: error40,
42029
42409
  exponentialBackoffDelay: delayInMs
@@ -42241,8 +42621,7 @@ async function executeToolCall({
42241
42621
  input,
42242
42622
  error: error40,
42243
42623
  dynamic: tool2.type === "dynamic",
42244
- ...toolCall.providerMetadata != null ? { providerMetadata: toolCall.providerMetadata } : {},
42245
- ...toolCall.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
42624
+ ...toolCall.providerMetadata != null ? { providerMetadata: toolCall.providerMetadata } : {}
42246
42625
  };
42247
42626
  }
42248
42627
  const durationMs = now2() - startTime;
@@ -42272,8 +42651,7 @@ async function executeToolCall({
42272
42651
  input,
42273
42652
  output,
42274
42653
  dynamic: tool2.type === "dynamic",
42275
- ...toolCall.providerMetadata != null ? { providerMetadata: toolCall.providerMetadata } : {},
42276
- ...toolCall.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
42654
+ ...toolCall.providerMetadata != null ? { providerMetadata: toolCall.providerMetadata } : {}
42277
42655
  };
42278
42656
  }
42279
42657
  });
@@ -42638,6 +43016,15 @@ async function parsePartialJson(jsonText) {
42638
43016
  }
42639
43017
  return { value: undefined, state: "failed-parse" };
42640
43018
  }
43019
+ function mergeToolProviderMetadata(toolMetadata, callMetadata) {
43020
+ if (toolMetadata == null) {
43021
+ return callMetadata;
43022
+ }
43023
+ if (callMetadata == null) {
43024
+ return toolMetadata;
43025
+ }
43026
+ return { ...toolMetadata, ...callMetadata };
43027
+ }
42641
43028
  async function parseToolCall({
42642
43029
  toolCall,
42643
43030
  tools,
@@ -42645,6 +43032,7 @@ async function parseToolCall({
42645
43032
  system,
42646
43033
  messages
42647
43034
  }) {
43035
+ var _a21, _b16;
42648
43036
  try {
42649
43037
  if (tools == null) {
42650
43038
  if (toolCall.providerExecuted && toolCall.dynamic) {
@@ -42685,7 +43073,6 @@ async function parseToolCall({
42685
43073
  } catch (error40) {
42686
43074
  const parsedInput = await safeParseJSON({ text: toolCall.input });
42687
43075
  const input = parsedInput.success ? parsedInput.value : toolCall.input;
42688
- const tool2 = tools == null ? undefined : tools[toolCall.toolName];
42689
43076
  return {
42690
43077
  type: "tool-call",
42691
43078
  toolCallId: toolCall.toolCallId,
@@ -42694,10 +43081,9 @@ async function parseToolCall({
42694
43081
  dynamic: true,
42695
43082
  invalid: true,
42696
43083
  error: error40,
42697
- title: tool2 == null ? undefined : tool2.title,
43084
+ title: (_a21 = tools == null ? undefined : tools[toolCall.toolName]) == null ? undefined : _a21.title,
42698
43085
  providerExecuted: toolCall.providerExecuted,
42699
- providerMetadata: toolCall.providerMetadata,
42700
- ...(tool2 == null ? undefined : tool2.metadata) != null ? { toolMetadata: tool2.metadata } : {}
43086
+ providerMetadata: mergeToolProviderMetadata((_b16 = tools == null ? undefined : tools[toolCall.toolName]) == null ? undefined : _b16.providerMetadata, toolCall.providerMetadata)
42701
43087
  };
42702
43088
  }
42703
43089
  }
@@ -42744,14 +43130,14 @@ async function doParseToolCall({
42744
43130
  cause: parseResult.error
42745
43131
  });
42746
43132
  }
43133
+ const mergedProviderMetadata = mergeToolProviderMetadata(tool2.providerMetadata, toolCall.providerMetadata);
42747
43134
  return tool2.type === "dynamic" ? {
42748
43135
  type: "tool-call",
42749
43136
  toolCallId: toolCall.toolCallId,
42750
43137
  toolName: toolCall.toolName,
42751
43138
  input: parseResult.value,
42752
43139
  providerExecuted: toolCall.providerExecuted,
42753
- providerMetadata: toolCall.providerMetadata,
42754
- ...tool2.metadata != null ? { toolMetadata: tool2.metadata } : {},
43140
+ providerMetadata: mergedProviderMetadata,
42755
43141
  dynamic: true,
42756
43142
  title: tool2.title
42757
43143
  } : {
@@ -42760,8 +43146,7 @@ async function doParseToolCall({
42760
43146
  toolName,
42761
43147
  input: parseResult.value,
42762
43148
  providerExecuted: toolCall.providerExecuted,
42763
- providerMetadata: toolCall.providerMetadata,
42764
- ...tool2.metadata != null ? { toolMetadata: tool2.metadata } : {},
43149
+ providerMetadata: mergedProviderMetadata,
42765
43150
  title: tool2.title
42766
43151
  };
42767
43152
  }
@@ -43593,8 +43978,7 @@ function asContent({
43593
43978
  error: part.result,
43594
43979
  providerExecuted: true,
43595
43980
  dynamic: part.dynamic,
43596
- ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
43597
- ...(tool2 == null ? undefined : tool2.metadata) != null ? { toolMetadata: tool2.metadata } : {}
43981
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
43598
43982
  });
43599
43983
  } else {
43600
43984
  contentParts.push({
@@ -43605,8 +43989,7 @@ function asContent({
43605
43989
  output: part.result,
43606
43990
  providerExecuted: true,
43607
43991
  dynamic: part.dynamic,
43608
- ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
43609
- ...(tool2 == null ? undefined : tool2.metadata) != null ? { toolMetadata: tool2.metadata } : {}
43992
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
43610
43993
  });
43611
43994
  }
43612
43995
  break;
@@ -43620,8 +44003,7 @@ function asContent({
43620
44003
  error: part.result,
43621
44004
  providerExecuted: true,
43622
44005
  dynamic: toolCall.dynamic,
43623
- ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
43624
- ...toolCall.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
44006
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
43625
44007
  });
43626
44008
  } else {
43627
44009
  contentParts.push({
@@ -43632,8 +44014,7 @@ function asContent({
43632
44014
  output: part.result,
43633
44015
  providerExecuted: true,
43634
44016
  dynamic: toolCall.dynamic,
43635
- ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
43636
- ...toolCall.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
44017
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
43637
44018
  });
43638
44019
  }
43639
44020
  break;
@@ -43847,9 +44228,6 @@ function processUIMessageStream({
43847
44228
  if (options.title !== undefined) {
43848
44229
  anyPart.title = options.title;
43849
44230
  }
43850
- if (options.toolMetadata !== undefined) {
43851
- anyPart.toolMetadata = options.toolMetadata;
43852
- }
43853
44231
  anyPart.providerExecuted = (_a222 = anyOptions.providerExecuted) != null ? _a222 : part.providerExecuted;
43854
44232
  const providerMetadata = anyOptions.providerMetadata;
43855
44233
  if (providerMetadata != null) {
@@ -43866,7 +44244,6 @@ function processUIMessageStream({
43866
44244
  toolCallId: options.toolCallId,
43867
44245
  state: options.state,
43868
44246
  title: options.title,
43869
- ...options.toolMetadata !== undefined ? { toolMetadata: options.toolMetadata } : {},
43870
44247
  input: anyOptions.input,
43871
44248
  output: anyOptions.output,
43872
44249
  rawInput: anyOptions.rawInput,
@@ -43894,9 +44271,6 @@ function processUIMessageStream({
43894
44271
  if (options.title !== undefined) {
43895
44272
  anyPart.title = options.title;
43896
44273
  }
43897
- if (options.toolMetadata !== undefined) {
43898
- anyPart.toolMetadata = options.toolMetadata;
43899
- }
43900
44274
  anyPart.providerExecuted = (_b23 = anyOptions.providerExecuted) != null ? _b23 : part.providerExecuted;
43901
44275
  const providerMetadata = anyOptions.providerMetadata;
43902
44276
  if (providerMetadata != null) {
@@ -43919,7 +44293,6 @@ function processUIMessageStream({
43919
44293
  preliminary: anyOptions.preliminary,
43920
44294
  providerExecuted: anyOptions.providerExecuted,
43921
44295
  title: options.title,
43922
- ...options.toolMetadata !== undefined ? { toolMetadata: options.toolMetadata } : {},
43923
44296
  ...anyOptions.providerMetadata != null && (options.state === "output-available" || options.state === "output-error") ? { resultProviderMetadata: anyOptions.providerMetadata } : {},
43924
44297
  ...anyOptions.providerMetadata != null && !(options.state === "output-available" || options.state === "output-error") ? { callProviderMetadata: anyOptions.providerMetadata } : {}
43925
44298
  });
@@ -44064,8 +44437,7 @@ function processUIMessageStream({
44064
44437
  toolName: chunk.toolName,
44065
44438
  index: toolInvocations.length,
44066
44439
  dynamic: chunk.dynamic,
44067
- title: chunk.title,
44068
- toolMetadata: chunk.toolMetadata
44440
+ title: chunk.title
44069
44441
  };
44070
44442
  if (chunk.dynamic) {
44071
44443
  updateDynamicToolPart({
@@ -44075,7 +44447,6 @@ function processUIMessageStream({
44075
44447
  input: undefined,
44076
44448
  providerExecuted: chunk.providerExecuted,
44077
44449
  title: chunk.title,
44078
- toolMetadata: chunk.toolMetadata,
44079
44450
  providerMetadata: chunk.providerMetadata
44080
44451
  });
44081
44452
  } else {
@@ -44086,7 +44457,6 @@ function processUIMessageStream({
44086
44457
  input: undefined,
44087
44458
  providerExecuted: chunk.providerExecuted,
44088
44459
  title: chunk.title,
44089
- toolMetadata: chunk.toolMetadata,
44090
44460
  providerMetadata: chunk.providerMetadata
44091
44461
  });
44092
44462
  }
@@ -44110,8 +44480,7 @@ function processUIMessageStream({
44110
44480
  toolName: partialToolCall.toolName,
44111
44481
  state: "input-streaming",
44112
44482
  input: partialArgs,
44113
- title: partialToolCall.title,
44114
- toolMetadata: partialToolCall.toolMetadata
44483
+ title: partialToolCall.title
44115
44484
  });
44116
44485
  } else {
44117
44486
  updateToolPart({
@@ -44119,8 +44488,7 @@ function processUIMessageStream({
44119
44488
  toolName: partialToolCall.toolName,
44120
44489
  state: "input-streaming",
44121
44490
  input: partialArgs,
44122
- title: partialToolCall.title,
44123
- toolMetadata: partialToolCall.toolMetadata
44491
+ title: partialToolCall.title
44124
44492
  });
44125
44493
  }
44126
44494
  write();
@@ -44135,8 +44503,7 @@ function processUIMessageStream({
44135
44503
  input: chunk.input,
44136
44504
  providerExecuted: chunk.providerExecuted,
44137
44505
  providerMetadata: chunk.providerMetadata,
44138
- title: chunk.title,
44139
- toolMetadata: chunk.toolMetadata
44506
+ title: chunk.title
44140
44507
  });
44141
44508
  } else {
44142
44509
  updateToolPart({
@@ -44146,8 +44513,7 @@ function processUIMessageStream({
44146
44513
  input: chunk.input,
44147
44514
  providerExecuted: chunk.providerExecuted,
44148
44515
  providerMetadata: chunk.providerMetadata,
44149
- title: chunk.title,
44150
- toolMetadata: chunk.toolMetadata
44516
+ title: chunk.title
44151
44517
  });
44152
44518
  }
44153
44519
  write();
@@ -44169,8 +44535,7 @@ function processUIMessageStream({
44169
44535
  input: chunk.input,
44170
44536
  errorText: chunk.errorText,
44171
44537
  providerExecuted: chunk.providerExecuted,
44172
- providerMetadata: chunk.providerMetadata,
44173
- toolMetadata: chunk.toolMetadata
44538
+ providerMetadata: chunk.providerMetadata
44174
44539
  });
44175
44540
  } else {
44176
44541
  updateToolPart({
@@ -44181,8 +44546,7 @@ function processUIMessageStream({
44181
44546
  rawInput: chunk.input,
44182
44547
  errorText: chunk.errorText,
44183
44548
  providerExecuted: chunk.providerExecuted,
44184
- providerMetadata: chunk.providerMetadata,
44185
- toolMetadata: chunk.toolMetadata
44549
+ providerMetadata: chunk.providerMetadata
44186
44550
  });
44187
44551
  }
44188
44552
  write();
@@ -44213,8 +44577,7 @@ function processUIMessageStream({
44213
44577
  preliminary: chunk.preliminary,
44214
44578
  providerExecuted: chunk.providerExecuted,
44215
44579
  providerMetadata: chunk.providerMetadata,
44216
- title: toolInvocation.title,
44217
- toolMetadata: toolInvocation.toolMetadata
44580
+ title: toolInvocation.title
44218
44581
  });
44219
44582
  } else {
44220
44583
  updateToolPart({
@@ -44226,8 +44589,7 @@ function processUIMessageStream({
44226
44589
  providerExecuted: chunk.providerExecuted,
44227
44590
  preliminary: chunk.preliminary,
44228
44591
  providerMetadata: chunk.providerMetadata,
44229
- title: toolInvocation.title,
44230
- toolMetadata: toolInvocation.toolMetadata
44592
+ title: toolInvocation.title
44231
44593
  });
44232
44594
  }
44233
44595
  write();
@@ -44244,8 +44606,7 @@ function processUIMessageStream({
44244
44606
  errorText: chunk.errorText,
44245
44607
  providerExecuted: chunk.providerExecuted,
44246
44608
  providerMetadata: chunk.providerMetadata,
44247
- title: toolInvocation.title,
44248
- toolMetadata: toolInvocation.toolMetadata
44609
+ title: toolInvocation.title
44249
44610
  });
44250
44611
  } else {
44251
44612
  updateToolPart({
@@ -44257,8 +44618,7 @@ function processUIMessageStream({
44257
44618
  errorText: chunk.errorText,
44258
44619
  providerExecuted: chunk.providerExecuted,
44259
44620
  providerMetadata: chunk.providerMetadata,
44260
- title: toolInvocation.title,
44261
- toolMetadata: toolInvocation.toolMetadata
44621
+ title: toolInvocation.title
44262
44622
  });
44263
44623
  }
44264
44624
  write();
@@ -44716,8 +45076,7 @@ function runToolsTransformation({
44716
45076
  input: toolCall.input,
44717
45077
  error: getErrorMessage2(toolCall.error),
44718
45078
  dynamic: true,
44719
- title: toolCall.title,
44720
- ...toolCall.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
45079
+ title: toolCall.title
44721
45080
  });
44722
45081
  break;
44723
45082
  }
@@ -44785,7 +45144,6 @@ function runToolsTransformation({
44785
45144
  }
44786
45145
  case "tool-result": {
44787
45146
  const toolName = chunk.toolName;
44788
- const toolCall = toolCallsByToolCallId.get(chunk.toolCallId);
44789
45147
  if (chunk.isError) {
44790
45148
  toolResultsStreamController.enqueue({
44791
45149
  type: "tool-error",
@@ -44795,8 +45153,7 @@ function runToolsTransformation({
44795
45153
  providerExecuted: true,
44796
45154
  error: chunk.result,
44797
45155
  dynamic: chunk.dynamic,
44798
- ...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {},
44799
- ...(toolCall == null ? undefined : toolCall.toolMetadata) != null ? { toolMetadata: toolCall.toolMetadata } : {}
45156
+ ...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {}
44800
45157
  });
44801
45158
  } else {
44802
45159
  controller.enqueue({
@@ -44807,8 +45164,7 @@ function runToolsTransformation({
44807
45164
  output: chunk.result,
44808
45165
  providerExecuted: true,
44809
45166
  dynamic: chunk.dynamic,
44810
- ...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {},
44811
- ...(toolCall == null ? undefined : toolCall.toolMetadata) != null ? { toolMetadata: toolCall.toolMetadata } : {}
45167
+ ...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {}
44812
45168
  });
44813
45169
  }
44814
45170
  break;
@@ -45591,7 +45947,7 @@ async function embed({
45591
45947
  }),
45592
45948
  tracer,
45593
45949
  fn: async (doEmbedSpan) => {
45594
- var _a21, _b16;
45950
+ var _a21;
45595
45951
  const modelResponse = await model.doEmbed({
45596
45952
  values: [value],
45597
45953
  abortSignal,
@@ -45612,7 +45968,7 @@ async function embed({
45612
45968
  return {
45613
45969
  embedding: embedding2,
45614
45970
  usage: usage2,
45615
- warnings: (_b16 = modelResponse.warnings) != null ? _b16 : [],
45971
+ warnings: modelResponse.warnings,
45616
45972
  providerMetadata: modelResponse.providerMetadata,
45617
45973
  response: modelResponse.response
45618
45974
  };
@@ -45708,7 +46064,7 @@ async function embedMany({
45708
46064
  }),
45709
46065
  tracer,
45710
46066
  fn: async (doEmbedSpan) => {
45711
- var _a222, _b16;
46067
+ var _a222;
45712
46068
  const modelResponse = await model.doEmbed({
45713
46069
  values,
45714
46070
  abortSignal,
@@ -45729,7 +46085,7 @@ async function embedMany({
45729
46085
  return {
45730
46086
  embeddings: embeddings3,
45731
46087
  usage: usage2,
45732
- warnings: (_b16 = modelResponse.warnings) != null ? _b16 : [],
46088
+ warnings: modelResponse.warnings,
45733
46089
  providerMetadata: modelResponse.providerMetadata,
45734
46090
  response: modelResponse.response
45735
46091
  };
@@ -45786,7 +46142,7 @@ async function embedMany({
45786
46142
  }),
45787
46143
  tracer,
45788
46144
  fn: async (doEmbedSpan) => {
45789
- var _a222, _b16;
46145
+ var _a222;
45790
46146
  const modelResponse = await model.doEmbed({
45791
46147
  values: chunk,
45792
46148
  abortSignal,
@@ -45807,7 +46163,7 @@ async function embedMany({
45807
46163
  return {
45808
46164
  embeddings: embeddings2,
45809
46165
  usage,
45810
- warnings: (_b16 = modelResponse.warnings) != null ? _b16 : [],
46166
+ warnings: modelResponse.warnings,
45811
46167
  providerMetadata: modelResponse.providerMetadata,
45812
46168
  response: modelResponse.response
45813
46169
  };
@@ -47921,7 +48277,7 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
47921
48277
  const bytes = typeof data === "string" ? convertBase64ToUint8Array(data) : data;
47922
48278
  const id3Size = (bytes[6] & 127) << 21 | (bytes[7] & 127) << 14 | (bytes[8] & 127) << 7 | bytes[9] & 127;
47923
48279
  return bytes.slice(id3Size + 10);
47924
- }, VERSION3 = "6.0.191", download = async ({
48280
+ }, VERSION3 = "6.0.175", download = async ({
47925
48281
  url: url2,
47926
48282
  maxBytes,
47927
48283
  abortSignal
@@ -48429,7 +48785,7 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
48429
48785
  }
48430
48786
  return this._output;
48431
48787
  }
48432
- }, JsonToSseTransformStream, UI_MESSAGE_STREAM_HEADERS, toolMetadataSchema, uiMessageChunkSchema, isToolOrDynamicToolUIPart, getToolOrDynamicToolName, originalGenerateId2, DefaultStreamTextResult = class {
48788
+ }, JsonToSseTransformStream, UI_MESSAGE_STREAM_HEADERS, uiMessageChunkSchema, isToolOrDynamicToolUIPart, getToolOrDynamicToolName, originalGenerateId2, DefaultStreamTextResult = class {
48433
48789
  constructor({
48434
48790
  model,
48435
48791
  telemetry,
@@ -49677,7 +50033,6 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
49677
50033
  toolName: part.toolName,
49678
50034
  ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
49679
50035
  ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
49680
- ...part.toolMetadata != null ? { toolMetadata: part.toolMetadata } : {},
49681
50036
  ...dynamic != null ? { dynamic } : {},
49682
50037
  ...part.title != null ? { title: part.title } : {}
49683
50038
  });
@@ -49701,7 +50056,6 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
49701
50056
  input: part.input,
49702
50057
  ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
49703
50058
  ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
49704
- ...part.toolMetadata != null ? { toolMetadata: part.toolMetadata } : {},
49705
50059
  ...dynamic != null ? { dynamic } : {},
49706
50060
  errorText: onError(part.error),
49707
50061
  ...part.title != null ? { title: part.title } : {}
@@ -49714,7 +50068,6 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
49714
50068
  input: part.input,
49715
50069
  ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
49716
50070
  ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
49717
- ...part.toolMetadata != null ? { toolMetadata: part.toolMetadata } : {},
49718
50071
  ...dynamic != null ? { dynamic } : {},
49719
50072
  ...part.title != null ? { title: part.title } : {}
49720
50073
  });
@@ -49737,7 +50090,6 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
49737
50090
  output: part.output,
49738
50091
  ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
49739
50092
  ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
49740
- ...part.toolMetadata != null ? { toolMetadata: part.toolMetadata } : {},
49741
50093
  ...part.preliminary != null ? { preliminary: part.preliminary } : {},
49742
50094
  ...dynamic != null ? { dynamic } : {}
49743
50095
  });
@@ -49751,7 +50103,6 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
49751
50103
  errorText: part.providerExecuted ? typeof part.error === "string" ? part.error : JSON.stringify(part.error) : onError(part.error),
49752
50104
  ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
49753
50105
  ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
49754
- ...part.toolMetadata != null ? { toolMetadata: part.toolMetadata } : {},
49755
50106
  ...dynamic != null ? { dynamic } : {}
49756
50107
  });
49757
50108
  break;
@@ -49925,21 +50276,10 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
49925
50276
  ...options
49926
50277
  };
49927
50278
  const preparedCallArgs = (_d = await ((_c = (_b16 = this.settings).prepareCall) == null ? undefined : _c.call(_b16, baseCallArgs))) != null ? _d : baseCallArgs;
49928
- const {
49929
- instructions,
49930
- allowSystemInMessages,
49931
- messages,
49932
- prompt,
49933
- ...callArgs
49934
- } = preparedCallArgs;
50279
+ const { instructions, messages, prompt, ...callArgs } = preparedCallArgs;
49935
50280
  return {
49936
50281
  ...callArgs,
49937
- ...{
49938
- system: instructions,
49939
- allowSystemInMessages,
49940
- messages,
49941
- prompt
49942
- }
50282
+ ...{ system: instructions, messages, prompt }
49943
50283
  };
49944
50284
  }
49945
50285
  mergeOnStepFinishCallbacks(methodCallback) {
@@ -49980,7 +50320,7 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
49980
50320
  onStepFinish: this.mergeOnStepFinishCallbacks(onStepFinish)
49981
50321
  });
49982
50322
  }
49983
- }, toolMetadataSchema2, uiMessagesSchema, DefaultEmbedResult = class {
50323
+ }, uiMessagesSchema, DefaultEmbedResult = class {
49984
50324
  constructor(options) {
49985
50325
  this.value = options.value;
49986
50326
  this.embedding = options.embedding;
@@ -51488,7 +51828,6 @@ var init_dist6 = __esm(() => {
51488
51828
  init_dist5();
51489
51829
  init_dist2();
51490
51830
  init_dist2();
51491
- init_dist5();
51492
51831
  init_dist4();
51493
51832
  init_dist4();
51494
51833
  init_dist4();
@@ -52348,7 +52687,6 @@ var init_dist6 = __esm(() => {
52348
52687
  "x-vercel-ai-ui-message-stream": "v1",
52349
52688
  "x-accel-buffering": "no"
52350
52689
  };
52351
- toolMetadataSchema = exports_external3.record(exports_external3.string(), jsonValueSchema.optional());
52352
52690
  uiMessageChunkSchema = lazySchema(() => zodSchema(exports_external3.union([
52353
52691
  exports_external3.strictObject({
52354
52692
  type: exports_external3.literal("text-start"),
@@ -52376,7 +52714,6 @@ var init_dist6 = __esm(() => {
52376
52714
  toolName: exports_external3.string(),
52377
52715
  providerExecuted: exports_external3.boolean().optional(),
52378
52716
  providerMetadata: providerMetadataSchema.optional(),
52379
- toolMetadata: toolMetadataSchema.optional(),
52380
52717
  dynamic: exports_external3.boolean().optional(),
52381
52718
  title: exports_external3.string().optional()
52382
52719
  }),
@@ -52392,7 +52729,6 @@ var init_dist6 = __esm(() => {
52392
52729
  input: exports_external3.unknown(),
52393
52730
  providerExecuted: exports_external3.boolean().optional(),
52394
52731
  providerMetadata: providerMetadataSchema.optional(),
52395
- toolMetadata: toolMetadataSchema.optional(),
52396
52732
  dynamic: exports_external3.boolean().optional(),
52397
52733
  title: exports_external3.string().optional()
52398
52734
  }),
@@ -52403,7 +52739,6 @@ var init_dist6 = __esm(() => {
52403
52739
  input: exports_external3.unknown(),
52404
52740
  providerExecuted: exports_external3.boolean().optional(),
52405
52741
  providerMetadata: providerMetadataSchema.optional(),
52406
- toolMetadata: toolMetadataSchema.optional(),
52407
52742
  dynamic: exports_external3.boolean().optional(),
52408
52743
  errorText: exports_external3.string(),
52409
52744
  title: exports_external3.string().optional()
@@ -52419,7 +52754,6 @@ var init_dist6 = __esm(() => {
52419
52754
  output: exports_external3.unknown(),
52420
52755
  providerExecuted: exports_external3.boolean().optional(),
52421
52756
  providerMetadata: providerMetadataSchema.optional(),
52422
- toolMetadata: toolMetadataSchema.optional(),
52423
52757
  dynamic: exports_external3.boolean().optional(),
52424
52758
  preliminary: exports_external3.boolean().optional()
52425
52759
  }),
@@ -52429,7 +52763,6 @@ var init_dist6 = __esm(() => {
52429
52763
  errorText: exports_external3.string(),
52430
52764
  providerExecuted: exports_external3.boolean().optional(),
52431
52765
  providerMetadata: providerMetadataSchema.optional(),
52432
- toolMetadata: toolMetadataSchema.optional(),
52433
52766
  dynamic: exports_external3.boolean().optional()
52434
52767
  }),
52435
52768
  exports_external3.strictObject({
@@ -52517,7 +52850,6 @@ var init_dist6 = __esm(() => {
52517
52850
  prefix: "aitxt",
52518
52851
  size: 24
52519
52852
  });
52520
- toolMetadataSchema2 = exports_external3.record(exports_external3.string(), jsonValueSchema.optional());
52521
52853
  uiMessagesSchema = lazySchema(() => zodSchema(exports_external3.array(exports_external3.object({
52522
52854
  id: exports_external3.string(),
52523
52855
  role: exports_external3.enum(["system", "user", "assistant"]),
@@ -52569,7 +52901,6 @@ var init_dist6 = __esm(() => {
52569
52901
  type: exports_external3.literal("dynamic-tool"),
52570
52902
  toolName: exports_external3.string(),
52571
52903
  toolCallId: exports_external3.string(),
52572
- toolMetadata: toolMetadataSchema2.optional(),
52573
52904
  state: exports_external3.literal("input-streaming"),
52574
52905
  input: exports_external3.unknown().optional(),
52575
52906
  providerExecuted: exports_external3.boolean().optional(),
@@ -52582,7 +52913,6 @@ var init_dist6 = __esm(() => {
52582
52913
  type: exports_external3.literal("dynamic-tool"),
52583
52914
  toolName: exports_external3.string(),
52584
52915
  toolCallId: exports_external3.string(),
52585
- toolMetadata: toolMetadataSchema2.optional(),
52586
52916
  state: exports_external3.literal("input-available"),
52587
52917
  input: exports_external3.unknown(),
52588
52918
  providerExecuted: exports_external3.boolean().optional(),
@@ -52595,7 +52925,6 @@ var init_dist6 = __esm(() => {
52595
52925
  type: exports_external3.literal("dynamic-tool"),
52596
52926
  toolName: exports_external3.string(),
52597
52927
  toolCallId: exports_external3.string(),
52598
- toolMetadata: toolMetadataSchema2.optional(),
52599
52928
  state: exports_external3.literal("approval-requested"),
52600
52929
  input: exports_external3.unknown(),
52601
52930
  providerExecuted: exports_external3.boolean().optional(),
@@ -52612,7 +52941,6 @@ var init_dist6 = __esm(() => {
52612
52941
  type: exports_external3.literal("dynamic-tool"),
52613
52942
  toolName: exports_external3.string(),
52614
52943
  toolCallId: exports_external3.string(),
52615
- toolMetadata: toolMetadataSchema2.optional(),
52616
52944
  state: exports_external3.literal("approval-responded"),
52617
52945
  input: exports_external3.unknown(),
52618
52946
  providerExecuted: exports_external3.boolean().optional(),
@@ -52629,7 +52957,6 @@ var init_dist6 = __esm(() => {
52629
52957
  type: exports_external3.literal("dynamic-tool"),
52630
52958
  toolName: exports_external3.string(),
52631
52959
  toolCallId: exports_external3.string(),
52632
- toolMetadata: toolMetadataSchema2.optional(),
52633
52960
  state: exports_external3.literal("output-available"),
52634
52961
  input: exports_external3.unknown(),
52635
52962
  providerExecuted: exports_external3.boolean().optional(),
@@ -52648,9 +52975,8 @@ var init_dist6 = __esm(() => {
52648
52975
  type: exports_external3.literal("dynamic-tool"),
52649
52976
  toolName: exports_external3.string(),
52650
52977
  toolCallId: exports_external3.string(),
52651
- toolMetadata: toolMetadataSchema2.optional(),
52652
52978
  state: exports_external3.literal("output-error"),
52653
- input: exports_external3.unknown().optional(),
52979
+ input: exports_external3.unknown(),
52654
52980
  rawInput: exports_external3.unknown().optional(),
52655
52981
  providerExecuted: exports_external3.boolean().optional(),
52656
52982
  output: exports_external3.never().optional(),
@@ -52667,7 +52993,6 @@ var init_dist6 = __esm(() => {
52667
52993
  type: exports_external3.literal("dynamic-tool"),
52668
52994
  toolName: exports_external3.string(),
52669
52995
  toolCallId: exports_external3.string(),
52670
- toolMetadata: toolMetadataSchema2.optional(),
52671
52996
  state: exports_external3.literal("output-denied"),
52672
52997
  input: exports_external3.unknown(),
52673
52998
  providerExecuted: exports_external3.boolean().optional(),
@@ -52683,7 +53008,6 @@ var init_dist6 = __esm(() => {
52683
53008
  exports_external3.object({
52684
53009
  type: exports_external3.string().startsWith("tool-"),
52685
53010
  toolCallId: exports_external3.string(),
52686
- toolMetadata: toolMetadataSchema2.optional(),
52687
53011
  state: exports_external3.literal("input-streaming"),
52688
53012
  providerExecuted: exports_external3.boolean().optional(),
52689
53013
  callProviderMetadata: providerMetadataSchema.optional(),
@@ -52695,7 +53019,6 @@ var init_dist6 = __esm(() => {
52695
53019
  exports_external3.object({
52696
53020
  type: exports_external3.string().startsWith("tool-"),
52697
53021
  toolCallId: exports_external3.string(),
52698
- toolMetadata: toolMetadataSchema2.optional(),
52699
53022
  state: exports_external3.literal("input-available"),
52700
53023
  providerExecuted: exports_external3.boolean().optional(),
52701
53024
  input: exports_external3.unknown(),
@@ -52707,7 +53030,6 @@ var init_dist6 = __esm(() => {
52707
53030
  exports_external3.object({
52708
53031
  type: exports_external3.string().startsWith("tool-"),
52709
53032
  toolCallId: exports_external3.string(),
52710
- toolMetadata: toolMetadataSchema2.optional(),
52711
53033
  state: exports_external3.literal("approval-requested"),
52712
53034
  input: exports_external3.unknown(),
52713
53035
  providerExecuted: exports_external3.boolean().optional(),
@@ -52723,7 +53045,6 @@ var init_dist6 = __esm(() => {
52723
53045
  exports_external3.object({
52724
53046
  type: exports_external3.string().startsWith("tool-"),
52725
53047
  toolCallId: exports_external3.string(),
52726
- toolMetadata: toolMetadataSchema2.optional(),
52727
53048
  state: exports_external3.literal("approval-responded"),
52728
53049
  input: exports_external3.unknown(),
52729
53050
  providerExecuted: exports_external3.boolean().optional(),
@@ -52739,7 +53060,6 @@ var init_dist6 = __esm(() => {
52739
53060
  exports_external3.object({
52740
53061
  type: exports_external3.string().startsWith("tool-"),
52741
53062
  toolCallId: exports_external3.string(),
52742
- toolMetadata: toolMetadataSchema2.optional(),
52743
53063
  state: exports_external3.literal("output-available"),
52744
53064
  providerExecuted: exports_external3.boolean().optional(),
52745
53065
  input: exports_external3.unknown(),
@@ -52757,10 +53077,9 @@ var init_dist6 = __esm(() => {
52757
53077
  exports_external3.object({
52758
53078
  type: exports_external3.string().startsWith("tool-"),
52759
53079
  toolCallId: exports_external3.string(),
52760
- toolMetadata: toolMetadataSchema2.optional(),
52761
53080
  state: exports_external3.literal("output-error"),
52762
53081
  providerExecuted: exports_external3.boolean().optional(),
52763
- input: exports_external3.unknown().optional(),
53082
+ input: exports_external3.unknown(),
52764
53083
  rawInput: exports_external3.unknown().optional(),
52765
53084
  output: exports_external3.never().optional(),
52766
53085
  errorText: exports_external3.string(),
@@ -52775,7 +53094,6 @@ var init_dist6 = __esm(() => {
52775
53094
  exports_external3.object({
52776
53095
  type: exports_external3.string().startsWith("tool-"),
52777
53096
  toolCallId: exports_external3.string(),
52778
- toolMetadata: toolMetadataSchema2.optional(),
52779
53097
  state: exports_external3.literal("output-denied"),
52780
53098
  providerExecuted: exports_external3.boolean().optional(),
52781
53099
  input: exports_external3.unknown(),
@@ -53265,54 +53583,52 @@ import { promises as fsPromises } from "fs";
53265
53583
  import { createHash, createPrivateKey, createPublicKey, sign } from "crypto";
53266
53584
  import { promises as fs2 } from "fs";
53267
53585
  import { homedir as homedir22 } from "os";
53268
- import { dirname as dirname3, join as join62 } from "path";
53586
+ import { dirname as dirname3, join as join52 } from "path";
53269
53587
  import { exec } from "child_process";
53270
53588
  import { promisify } from "util";
53271
- import { readFileSync as readFileSync4 } from "fs";
53589
+ import { readFileSync as readFileSync3 } from "fs";
53272
53590
  import { webcrypto as crypto2 } from "crypto";
53273
- import { existsSync as existsSync5, writeFileSync as writeFileSync4, readFileSync as readFileSync3, mkdirSync as mkdirSync32 } from "fs";
53274
- import { join as join52 } from "path";
53591
+ import { existsSync as existsSync42, writeFileSync as writeFileSync32, readFileSync as readFileSync22, mkdirSync as mkdirSync32 } from "fs";
53592
+ import { join as join42 } from "path";
53275
53593
  import { Database as Database4 } from "bun:sqlite";
53276
53594
  import { existsSync as existsSync11, mkdirSync as mkdirSync9 } from "fs";
53277
- import { dirname as dirname4, join as join14, resolve as resolve2 } from "path";
53278
- import { existsSync as existsSync22, writeFileSync as writeFileSync3 } from "fs";
53595
+ import { dirname as dirname4, join as join15, resolve as resolve2 } from "path";
53596
+ import { existsSync as existsSync22, writeFileSync as writeFileSync4 } from "fs";
53279
53597
  import { join as join22 } from "path";
53280
- import { execFileSync } from "child_process";
53281
- import { writeFileSync as writeFileSync22, existsSync as existsSync32, readFileSync as readFileSync5 } from "fs";
53282
- import { join as join32 } from "path";
53283
- import { hostname as hostname3 } from "os";
53284
- import { existsSync as existsSync42, readFileSync as readFileSync22, writeFileSync as writeFileSync32, mkdirSync as mkdirSync22 } from "fs";
53598
+ import { execSync as execSync2, execFileSync } from "child_process";
53599
+ import { existsSync as existsSync32, readFileSync as readFileSync4, writeFileSync as writeFileSync22, mkdirSync as mkdirSync22 } from "fs";
53285
53600
  import { homedir as homedir11 } from "os";
53286
- import { join as join42, dirname as dirname22 } from "path";
53601
+ import { join as join32, dirname as dirname22 } from "path";
53602
+ import { hostname as hostname3 } from "os";
53287
53603
  import { Buffer as Buffer2 } from "buffer";
53288
53604
  import * as zlib from "zlib";
53289
53605
  import { Readable } from "stream";
53290
53606
  import { Writable } from "stream";
53291
53607
  import { createHash as createHash2 } from "crypto";
53292
- import { mkdirSync as mkdirSync4, statSync, writeFileSync as writeFileSync5 } from "fs";
53293
- import { dirname as dirname42, join as join72, relative as relative2 } from "path";
53608
+ import { mkdirSync as mkdirSync4, statSync, writeFileSync as writeFileSync42 } from "fs";
53609
+ import { dirname as dirname42, join as join62, relative as relative2 } from "path";
53294
53610
  import { readdir, readFile as readFile2 } from "fs/promises";
53295
- import { existsSync as existsSync72, readdirSync as readdirSync3, readFileSync as readFileSync52, statSync as statSync2 } from "fs";
53296
- import { basename, join as join82, resolve as resolve22 } from "path";
53611
+ import { existsSync as existsSync62, readdirSync as readdirSync3, readFileSync as readFileSync42, statSync as statSync2 } from "fs";
53612
+ import { basename, join as join72, resolve as resolve22 } from "path";
53297
53613
  import { execFileSync as execFileSync2 } from "child_process";
53298
- import { existsSync as existsSync82, readFileSync as readFileSync6, writeFileSync as writeFileSync6, mkdirSync as mkdirSync52 } from "fs";
53299
- import { dirname as dirname5, join as join92 } from "path";
53614
+ import { existsSync as existsSync72, readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync52 } from "fs";
53615
+ import { dirname as dirname5, join as join82 } from "path";
53300
53616
  import { execFileSync as execFileSync4 } from "child_process";
53301
- import { existsSync as existsSync112 } from "fs";
53302
- import { join as join122 } from "path";
53303
- import { execFileSync as execFileSync3 } from "child_process";
53304
- import { existsSync as existsSync92 } from "fs";
53305
- import { homedir as homedir32, hostname as hostname22, platform as platform2, type } from "os";
53306
- import { join as join102 } from "path";
53307
53617
  import { existsSync as existsSync102 } from "fs";
53308
- import { execSync as execSync2 } from "child_process";
53309
53618
  import { join as join112 } from "path";
53619
+ import { execFileSync as execFileSync3 } from "child_process";
53620
+ import { existsSync as existsSync82 } from "fs";
53621
+ import { homedir as homedir32, hostname as hostname22, platform as platform2, type } from "os";
53622
+ import { join as join92 } from "path";
53623
+ import { existsSync as existsSync92 } from "fs";
53310
53624
  import { execSync as execSync22 } from "child_process";
53311
- import { readFileSync as readFileSync7 } from "fs";
53625
+ import { join as join102 } from "path";
53626
+ import { execSync as execSync3 } from "child_process";
53627
+ import { readFileSync as readFileSync6 } from "fs";
53312
53628
  import { mkdirSync as mkdirSync62 } from "fs";
53313
- import { dirname as dirname6, join as join132 } from "path";
53629
+ import { dirname as dirname6, join as join122 } from "path";
53314
53630
  import { fileURLToPath } from "url";
53315
- import { existsSync as existsSync12 } from "fs";
53631
+ import { existsSync as existsSync112 } from "fs";
53316
53632
  function __accessProp3(key) {
53317
53633
  return this[key];
53318
53634
  }
@@ -53451,7 +53767,7 @@ function getDbPath2() {
53451
53767
  return process.env["PROJECTS_DB_PATH"];
53452
53768
  }
53453
53769
  const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
53454
- return join14(home, ".hasna", "projects", "projects.db");
53770
+ return join15(home, ".hasna", "projects", "projects.db");
53455
53771
  }
53456
53772
  function ensureDir2(filePath) {
53457
53773
  if (filePath === ":memory:")
@@ -53489,25 +53805,14 @@ function uuid5() {
53489
53805
  function isGitRepo(path) {
53490
53806
  return existsSync22(join22(path, ".git"));
53491
53807
  }
53492
- function getCurrentBranch(path) {
53493
- return execFileSync("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
53494
- cwd: path,
53495
- stdio: "pipe",
53496
- encoding: "utf-8",
53497
- env: process.env
53498
- }).trim();
53499
- }
53500
- function bootstrapPathsToStage(path) {
53501
- return BOOTSTRAP_PATHS.filter((entry) => existsSync22(join22(path, entry)));
53502
- }
53503
53808
  function gitInit(project) {
53504
53809
  const { path, name: name21, id, slug } = project;
53505
53810
  if (isGitRepo(path))
53506
53811
  return;
53507
- execFileSync("git", ["init", "-b", "main"], { cwd: path, stdio: "pipe", env: process.env });
53812
+ execSync2("git init", { cwd: path, stdio: "pipe" });
53508
53813
  const gitignorePath = join22(path, ".gitignore");
53509
53814
  if (!existsSync22(gitignorePath)) {
53510
- writeFileSync3(gitignorePath, GITIGNORE_TEMPLATE, "utf-8");
53815
+ writeFileSync4(gitignorePath, GITIGNORE_TEMPLATE, "utf-8");
53511
53816
  }
53512
53817
  const projectJson = {
53513
53818
  id,
@@ -53516,18 +53821,26 @@ function gitInit(project) {
53516
53821
  created_at: project.created_at,
53517
53822
  integrations: project.integrations ?? {}
53518
53823
  };
53519
- writeFileSync3(join22(path, ".project.json"), JSON.stringify(projectJson, null, 2) + `
53824
+ writeFileSync4(join22(path, ".project.json"), JSON.stringify(projectJson, null, 2) + `
53520
53825
  `, "utf-8");
53521
- const staged = bootstrapPathsToStage(path);
53522
- if (staged.length === 0)
53523
- return;
53524
- execFileSync("git", ["add", ...staged], { cwd: path, stdio: "pipe", env: process.env });
53525
- execFileSync("git", ["commit", "-m", `chore: init project ${name21}`], {
53826
+ execSync2("git add .gitignore .project.json", { cwd: path, stdio: "pipe" });
53827
+ execSync2(`git commit -m "chore: init project ${name21}"`, {
53526
53828
  cwd: path,
53527
53829
  stdio: "pipe",
53528
53830
  env: { ...process.env, GIT_AUTHOR_NAME: "open-projects", GIT_COMMITTER_NAME: "open-projects" }
53529
53831
  });
53530
53832
  }
53833
+ function getConfig() {
53834
+ if (existsSync32(CONFIG_PATH3)) {
53835
+ try {
53836
+ const user = JSON.parse(readFileSync4(CONFIG_PATH3, "utf-8"));
53837
+ return { ...DEFAULTS, ...user };
53838
+ } catch {
53839
+ return { ...DEFAULTS };
53840
+ }
53841
+ }
53842
+ return { ...DEFAULTS };
53843
+ }
53531
53844
  function rowToWorkdir(row) {
53532
53845
  return {
53533
53846
  ...row,
@@ -53571,176 +53884,6 @@ function removeWorkdir(projectId, path, db2) {
53571
53884
  const d = db2 || getDatabase2();
53572
53885
  d.run("DELETE FROM project_workdirs WHERE project_id = ? AND path = ?", [projectId, path]);
53573
53886
  }
53574
- function markWorkdirGenerated(projectId, path, db2) {
53575
- const d = db2 || getDatabase2();
53576
- d.run("UPDATE project_workdirs SET claude_md_generated = 1, agents_md_generated = 1 WHERE project_id = ? AND path = ?", [projectId, path]);
53577
- }
53578
- function buildWorkdirList(workdirs, currentPath) {
53579
- return workdirs.map((w) => {
53580
- const isCurrent = w.path === currentPath;
53581
- const primary = w.is_primary ? " (primary)" : "";
53582
- const current = isCurrent ? " \u2190 you are here" : "";
53583
- return `- \`${w.path}\` [${w.label}]${primary}${current} *(machine: ${w.machine_id})*`;
53584
- }).join(`
53585
- `);
53586
- }
53587
- function claudeMdContent(project, workdir, allWorkdirs) {
53588
- const otherDirs = allWorkdirs.filter((w) => w.path !== workdir.path);
53589
- const otherSection = otherDirs.length ? `
53590
- ## Other Working Directories
53591
- ${buildWorkdirList(otherDirs, workdir.path)}
53592
- ` : "";
53593
- const integrations = Object.keys(project.integrations).length ? `
53594
- ## Integrations
53595
- ${Object.entries(project.integrations).filter(([, v]) => v).map(([k, v]) => `- **${k}:** \`${v}\``).join(`
53596
- `)}
53597
- ` : "";
53598
- const tags = project.tags.length ? `
53599
- **Tags:** ${project.tags.join(", ")}` : "";
53600
- return `# Project: ${project.name}
53601
-
53602
- > ${project.description ?? `Working directory for project **${project.name}**`}
53603
- ${tags}
53604
-
53605
- ## Working Directory
53606
-
53607
- You are working in the **${workdir.label}** directory for this project:
53608
-
53609
- \`\`\`
53610
- ${workdir.path}
53611
- \`\`\`
53612
-
53613
- **Write all code to this directory.** Do not write to other project directories unless explicitly instructed.
53614
-
53615
- ## Project Metadata
53616
-
53617
- | Field | Value |
53618
- |-------|-------|
53619
- | ID | \`${project.id}\` |
53620
- | Slug | \`${project.slug}\` |
53621
- | Label | \`${workdir.label}\` |
53622
- | Machine | \`${workdir.machine_id}\` |
53623
- | Status | ${project.status} |
53624
- ${project.git_remote ? `| Git Remote | ${project.git_remote} |` : ""}
53625
- ${project.s3_bucket ? `| S3 Bucket | \`${project.s3_bucket}\` |` : ""}
53626
- ${integrations}${otherSection}
53627
- ## All Working Directories
53628
-
53629
- ${buildWorkdirList(allWorkdirs, workdir.path)}
53630
-
53631
- ## Instructions for AI Agents
53632
-
53633
- 1. **Write code in \`${workdir.path}\`** \u2014 this is your working directory for this session.
53634
- 2. Use \`projects sync ${project.slug}\` to push changes to S3.
53635
- 3. Use \`projects git ${project.slug} <args>\` to run git commands.
53636
- 4. If you need to switch to a different workdir, call \`projects_open\` with the project ID.
53637
-
53638
- ---
53639
- *Generated by open-projects. Regenerate: \`projects workdir generate ${project.slug}\`*
53640
- `.trimStart();
53641
- }
53642
- function agentsMdContent(project, workdir, allWorkdirs) {
53643
- const otherDirs = allWorkdirs.filter((w) => w.path !== workdir.path);
53644
- return `---
53645
- project_id: ${project.id}
53646
- project_slug: ${project.slug}
53647
- project_name: ${project.name}
53648
- working_directory: ${workdir.path}
53649
- label: ${workdir.label}
53650
- machine_id: ${workdir.machine_id}
53651
- is_primary: ${workdir.is_primary}
53652
- ---
53653
-
53654
- # ${project.name} \u2014 Agent Instructions
53655
-
53656
- ## Scope
53657
-
53658
- This agent session is scoped to the **${workdir.label}** working directory:
53659
-
53660
- \`\`\`
53661
- ${workdir.path}
53662
- \`\`\`
53663
-
53664
- **Only write files inside this directory** unless the user explicitly asks you to work elsewhere.
53665
- ${otherDirs.length ? `
53666
- ## Other workdirs for this project
53667
-
53668
- ${otherDirs.map((w) => `- \`${w.path}\` [${w.label}] on ${w.machine_id}`).join(`
53669
- `)}
53670
- ` : ""}
53671
- ## Quick Reference
53672
-
53673
- \`\`\`bash
53674
- # Open this project
53675
- cd ${workdir.path}
53676
-
53677
- # Sync to S3
53678
- projects sync ${project.slug}
53679
-
53680
- # Git operations
53681
- projects git ${project.slug} status
53682
- projects git ${project.slug} log --oneline -10
53683
- \`\`\`
53684
- ${Object.keys(project.integrations).length ? `
53685
- ## Service IDs
53686
-
53687
- ${Object.entries(project.integrations).filter(([, v]) => v).map(([k, v]) => `- **${k}:** \`${v}\``).join(`
53688
- `)}
53689
- ` : ""}
53690
- ---
53691
- *Generated by open-projects ${new Date().toISOString().slice(0, 10)}*
53692
- `.trimStart();
53693
- }
53694
- function generateForWorkdir(project, workdir, allWorkdirs, options = {}) {
53695
- const claudeMd = claudeMdContent(project, workdir, allWorkdirs);
53696
- const agentsMd = agentsMdContent(project, workdir, allWorkdirs);
53697
- const claudePath = join32(workdir.path, "CLAUDE.md");
53698
- const agentsPath = join32(workdir.path, "AGENTS.md");
53699
- let written = false;
53700
- if (!options.dryRun && existsSync32(workdir.path)) {
53701
- if (existsSync32(claudePath) && !options.force) {
53702
- const existing = readFileSync5(claudePath, "utf-8");
53703
- if (existing.includes("Generated by open-projects")) {
53704
- writeFileSync22(claudePath, claudeMd, "utf-8");
53705
- } else {
53706
- const separator = `
53707
-
53708
- ---
53709
-
53710
- <!-- open-projects -->
53711
- `;
53712
- const marker21 = "<!-- open-projects -->";
53713
- if (existing.includes(marker21)) {
53714
- const before = existing.slice(0, existing.indexOf(marker21) - separator.length + 1);
53715
- writeFileSync22(claudePath, before + separator + claudeMd, "utf-8");
53716
- } else {
53717
- writeFileSync22(claudePath, existing.trimEnd() + separator + claudeMd, "utf-8");
53718
- }
53719
- }
53720
- } else {
53721
- writeFileSync22(claudePath, claudeMd, "utf-8");
53722
- }
53723
- writeFileSync22(agentsPath, agentsMd, "utf-8");
53724
- markWorkdirGenerated(project.id, workdir.path, options.db);
53725
- written = true;
53726
- }
53727
- return { path: workdir.path, claude_md: claudeMd, agents_md: agentsMd, written };
53728
- }
53729
- function generateAllWorkdirs(project, options = {}) {
53730
- const workdirs = listWorkdirs(project.id, options.db);
53731
- return workdirs.map((w) => generateForWorkdir(project, w, workdirs, options));
53732
- }
53733
- function getConfig() {
53734
- if (existsSync42(CONFIG_PATH3)) {
53735
- try {
53736
- const user = JSON.parse(readFileSync22(CONFIG_PATH3, "utf-8"));
53737
- return { ...DEFAULTS, ...user };
53738
- } catch {
53739
- return { ...DEFAULTS };
53740
- }
53741
- }
53742
- return { ...DEFAULTS };
53743
- }
53744
53887
  function generateProjectId() {
53745
53888
  return `prj_${nanoid3()}`;
53746
53889
  }
@@ -53748,10 +53891,12 @@ function slugify2(name21) {
53748
53891
  return name21.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
53749
53892
  }
53750
53893
  function scaffoldProject(path) {
53894
+ if (existsSync42(path))
53895
+ return;
53751
53896
  mkdirSync32(path, { recursive: true });
53752
53897
  const config2 = getConfig();
53753
53898
  for (const dir of config2.scaffold_dirs || ["data", "scripts", "assets", "docs"]) {
53754
- mkdirSync32(join52(path, dir), { recursive: true });
53899
+ mkdirSync32(join42(path, dir), { recursive: true });
53755
53900
  }
53756
53901
  }
53757
53902
  function ensureUniqueSlug(base, db2, excludeId) {
@@ -53802,9 +53947,6 @@ function createProject2(input, db2) {
53802
53947
  try {
53803
53948
  addWorkdir({ project_id: id, path: input.path, label: "main", is_primary: true }, d);
53804
53949
  } catch {}
53805
- try {
53806
- generateAllWorkdirs(project, { db: d });
53807
- } catch {}
53808
53950
  const shouldGitInit = input.git_init !== false;
53809
53951
  if (shouldGitInit) {
53810
53952
  try {
@@ -53910,10 +54052,10 @@ function setIntegrations(id, integrations, db2) {
53910
54052
  id
53911
54053
  ]);
53912
54054
  try {
53913
- const jsonPath = join52(project.path, ".project.json");
53914
- if (existsSync5(jsonPath)) {
53915
- const existing = JSON.parse(readFileSync3(jsonPath, "utf-8"));
53916
- writeFileSync4(jsonPath, JSON.stringify({ ...existing, integrations: merged }, null, 2) + `
54055
+ const jsonPath = join42(project.path, ".project.json");
54056
+ if (existsSync42(jsonPath)) {
54057
+ const existing = JSON.parse(readFileSync22(jsonPath, "utf-8"));
54058
+ writeFileSync32(jsonPath, JSON.stringify({ ...existing, integrations: merged }, null, 2) + `
53917
54059
  `, "utf-8");
53918
54060
  }
53919
54061
  } catch {}
@@ -54987,7 +55129,7 @@ async function collectLocalFiles(rootPath) {
54987
55129
  async function walk(dir) {
54988
55130
  const entries = await readdir(dir, { withFileTypes: true });
54989
55131
  for (const entry of entries) {
54990
- const fullPath = join72(dir, entry.name);
55132
+ const fullPath = join62(dir, entry.name);
54991
55133
  if (entry.isDirectory()) {
54992
55134
  await walk(fullPath);
54993
55135
  } else if (entry.isFile()) {
@@ -55059,7 +55201,7 @@ async function syncProject(project, options = {}) {
55059
55201
  continue;
55060
55202
  }
55061
55203
  try {
55062
- const data = await readFile2(join72(project.path, relPath));
55204
+ const data = await readFile2(join62(project.path, relPath));
55063
55205
  await client.send(new PutObjectCommand({
55064
55206
  Bucket: bucket,
55065
55207
  Key: s3Key,
@@ -55097,9 +55239,9 @@ async function syncProject(project, options = {}) {
55097
55239
  chunks.push(chunk);
55098
55240
  }
55099
55241
  const data = Buffer.concat(chunks);
55100
- const localPath = join72(project.path, relPath);
55242
+ const localPath = join62(project.path, relPath);
55101
55243
  mkdirSync4(dirname42(localPath), { recursive: true });
55102
- writeFileSync5(localPath, data);
55244
+ writeFileSync42(localPath, data);
55103
55245
  log(`pull: ${relPath} (${data.length}B)`);
55104
55246
  result.pulled++;
55105
55247
  result.bytes += data.length;
@@ -55120,18 +55262,18 @@ async function syncProject(project, options = {}) {
55120
55262
  return result;
55121
55263
  }
55122
55264
  function inferProjectName(projectPath) {
55123
- const pkgPath = join82(projectPath, "package.json");
55124
- if (existsSync72(pkgPath)) {
55265
+ const pkgPath = join72(projectPath, "package.json");
55266
+ if (existsSync62(pkgPath)) {
55125
55267
  try {
55126
- const pkg = JSON.parse(readFileSync52(pkgPath, "utf-8"));
55268
+ const pkg = JSON.parse(readFileSync42(pkgPath, "utf-8"));
55127
55269
  if (pkg.name)
55128
55270
  return pkg.name.replace(/^@[^/]+\//, "");
55129
55271
  } catch {}
55130
55272
  }
55131
- const projPath = join82(projectPath, ".project.json");
55132
- if (existsSync72(projPath)) {
55273
+ const projPath = join72(projectPath, ".project.json");
55274
+ if (existsSync62(projPath)) {
55133
55275
  try {
55134
- const p2 = JSON.parse(readFileSync52(projPath, "utf-8"));
55276
+ const p2 = JSON.parse(readFileSync42(projPath, "utf-8"));
55135
55277
  if (p2.name)
55136
55278
  return p2.name;
55137
55279
  } catch {}
@@ -55139,11 +55281,11 @@ function inferProjectName(projectPath) {
55139
55281
  return basename(projectPath);
55140
55282
  }
55141
55283
  function inferGitRemote(projectPath) {
55142
- const gitConfigPath = join82(projectPath, ".git", "config");
55143
- if (!existsSync72(gitConfigPath))
55284
+ const gitConfigPath = join72(projectPath, ".git", "config");
55285
+ if (!existsSync62(gitConfigPath))
55144
55286
  return;
55145
55287
  try {
55146
- const config2 = readFileSync52(gitConfigPath, "utf-8");
55288
+ const config2 = readFileSync42(gitConfigPath, "utf-8");
55147
55289
  const match = config2.match(/\[remote "origin"\][\s\S]*?url\s*=\s*(.+)/);
55148
55290
  return match?.[1]?.trim();
55149
55291
  } catch {
@@ -55153,7 +55295,7 @@ function inferGitRemote(projectPath) {
55153
55295
  async function importProject(projectPath, options = {}) {
55154
55296
  const absPath = resolve22(projectPath);
55155
55297
  const log = options.onProgress ?? (() => {});
55156
- if (!existsSync72(absPath)) {
55298
+ if (!existsSync62(absPath)) {
55157
55299
  return { error: `Path does not exist: ${absPath}` };
55158
55300
  }
55159
55301
  const stat = statSync2(absPath);
@@ -55188,7 +55330,7 @@ async function importBulk(dirPath, options = {}) {
55188
55330
  const absDir = resolve22(dirPath);
55189
55331
  const result = { imported: [], skipped: [], errors: [] };
55190
55332
  const log = options.onProgress ?? (() => {});
55191
- if (!existsSync72(absDir)) {
55333
+ if (!existsSync62(absDir)) {
55192
55334
  result.errors.push({ path: absDir, error: "Directory does not exist" });
55193
55335
  return result;
55194
55336
  }
@@ -55196,7 +55338,7 @@ async function importBulk(dirPath, options = {}) {
55196
55338
  const dirs = entries.filter((e2) => e2.isDirectory() && !e2.name.startsWith("."));
55197
55339
  log(`Found ${dirs.length} subdirectories in ${absDir}`);
55198
55340
  for (const entry of dirs) {
55199
- const subPath = join82(absDir, entry.name);
55341
+ const subPath = join72(absDir, entry.name);
55200
55342
  const res = await importProject(subPath, options);
55201
55343
  if (res.project) {
55202
55344
  result.imported.push(res.project);
@@ -55231,8 +55373,7 @@ function publishProject(name21, path, options = {}) {
55231
55373
  } else {
55232
55374
  execFileSync2("git", ["remote", "add", "origin", remote], { cwd: path, stdio: "pipe", env: process.env });
55233
55375
  }
55234
- const branch = getCurrentBranch(path);
55235
- execFileSync2("git", ["push", "-u", "origin", branch, "--quiet"], { cwd: path, stdio: "pipe", env: process.env });
55376
+ execFileSync2("git", ["push", "-u", "origin", "main", "--quiet"], { cwd: path, stdio: "pipe", env: process.env });
55236
55377
  pushed = true;
55237
55378
  } catch {}
55238
55379
  }
@@ -55258,14 +55399,14 @@ function getGitHubUrl(path) {
55258
55399
  }
55259
55400
  }
55260
55401
  function getScheduleConfig() {
55261
- if (!existsSync82(CONFIG_PATH22)) {
55402
+ if (!existsSync72(CONFIG_PATH22)) {
55262
55403
  return { enabled: false, interval: "daily", direction: "both" };
55263
55404
  }
55264
- return JSON.parse(readFileSync6(CONFIG_PATH22, "utf-8"));
55405
+ return JSON.parse(readFileSync5(CONFIG_PATH22, "utf-8"));
55265
55406
  }
55266
55407
  function saveScheduleConfig(config2) {
55267
55408
  mkdirSync52(dirname5(CONFIG_PATH22), { recursive: true });
55268
- writeFileSync6(CONFIG_PATH22, JSON.stringify(config2, null, 2) + `
55409
+ writeFileSync5(CONFIG_PATH22, JSON.stringify(config2, null, 2) + `
55269
55410
  `, "utf-8");
55270
55411
  }
55271
55412
  async function syncAll(direction = "both", onProgress) {
@@ -55295,7 +55436,7 @@ async function syncAll(direction = "both", onProgress) {
55295
55436
  function getMachineProfile() {
55296
55437
  const host = (process.env["HOSTNAME"] || hostname22()).split(".")[0] || hostname22();
55297
55438
  const currentPlatform = platform2();
55298
- const workspaceRoot = currentPlatform === "darwin" ? join102(homedir32(), "Workspace") : join102(homedir32(), "workspace");
55439
+ const workspaceRoot = currentPlatform === "darwin" ? join92(homedir32(), "Workspace") : join92(homedir32(), "workspace");
55299
55440
  return {
55300
55441
  hostname: host,
55301
55442
  platform: currentPlatform,
@@ -55322,7 +55463,7 @@ function commandAvailability(command, versionArgs = ["--version"]) {
55322
55463
  return { command, available: true, path: commandPath, version: version2 };
55323
55464
  }
55324
55465
  function pathExists(path) {
55325
- return existsSync92(path);
55466
+ return existsSync82(path);
55326
55467
  }
55327
55468
  function classifyMachine(host, currentPlatform) {
55328
55469
  if (host === "apple01")
@@ -55336,10 +55477,10 @@ function classifyMachine(host, currentPlatform) {
55336
55477
  return "unknown";
55337
55478
  }
55338
55479
  function gitStatus(path) {
55339
- if (!existsSync102(join112(path, ".git")))
55480
+ if (!existsSync92(join102(path, ".git")))
55340
55481
  return "not a repo";
55341
55482
  try {
55342
- const out = execSync2("git status --porcelain", { cwd: path, stdio: "pipe", encoding: "utf-8" }).trim();
55483
+ const out = execSync22("git status --porcelain", { cwd: path, stdio: "pipe", encoding: "utf-8" }).trim();
55343
55484
  if (!out)
55344
55485
  return "clean";
55345
55486
  const n2 = out.split(`
@@ -55350,17 +55491,17 @@ function gitStatus(path) {
55350
55491
  }
55351
55492
  }
55352
55493
  function dirSize(path) {
55353
- if (!existsSync102(path))
55494
+ if (!existsSync92(path))
55354
55495
  return 0;
55355
55496
  try {
55356
- const out = execSync2(`du -sb -- "${path}" 2>/dev/null || du -sk -- "${path}" 2>/dev/null`, { stdio: "pipe", encoding: "utf-8" }).trim();
55497
+ const out = execSync22(`du -sb -- "${path}" 2>/dev/null || du -sk -- "${path}" 2>/dev/null`, { stdio: "pipe", encoding: "utf-8" }).trim();
55357
55498
  return parseInt(out.split("\t")[0] ?? "0", 10);
55358
55499
  } catch {
55359
55500
  return 0;
55360
55501
  }
55361
55502
  }
55362
55503
  function getProjectStatus(project) {
55363
- const pathExists2 = existsSync102(project.path);
55504
+ const pathExists2 = existsSync92(project.path);
55364
55505
  const workdirs = listWorkdirs(project.id);
55365
55506
  const lastSync = getDatabase2().query("SELECT completed_at FROM sync_log WHERE project_id = ? AND status = 'completed' ORDER BY completed_at DESC LIMIT 1").get(project.id)?.completed_at ?? null;
55366
55507
  return {
@@ -55373,21 +55514,18 @@ function getProjectStatus(project) {
55373
55514
  };
55374
55515
  }
55375
55516
  function run(cmd) {
55376
- return execSync22(cmd, { encoding: "utf-8", stdio: "pipe" }).trim();
55517
+ return execSync3(cmd, { encoding: "utf-8", stdio: "pipe" }).trim();
55377
55518
  }
55378
55519
  function getTmuxSessionName(project) {
55379
- return project.slug || project.name;
55520
+ const raw = project.slug || project.name;
55521
+ if (project.path?.includes("opensourcedev")) {
55522
+ const normalized = raw.replace(/^proj-/, "");
55523
+ return normalized.startsWith("open-") ? normalized : `open-${normalized}`;
55524
+ }
55525
+ return raw;
55380
55526
  }
55381
55527
  function listSessions() {
55382
- let output = "";
55383
- try {
55384
- output = run("tmux list-sessions -F '#{session_name}:#{session_group}:#{session_windows}:#{session_attached}'");
55385
- } catch (err) {
55386
- const message = err instanceof Error ? err.message : String(err);
55387
- if (message.includes("no server running"))
55388
- return [];
55389
- throw err;
55390
- }
55528
+ const output = run("tmux list-sessions -F '#{session_name}:#{session_group}:#{session_windows}:#{session_attached}'");
55391
55529
  return output.split(`
55392
55530
  `).filter(Boolean).map((line) => {
55393
55531
  const [name21, group, windows, attached] = line.split(":");
@@ -55495,7 +55633,7 @@ function getProjectLocations(project) {
55495
55633
  const currentMachine = getMachineId();
55496
55634
  return listWorkdirs(project.id).map((workdir) => ({
55497
55635
  ...workdir,
55498
- exists: existsSync112(workdir.path),
55636
+ exists: existsSync102(workdir.path),
55499
55637
  currentMachine: workdir.machine_id === currentMachine,
55500
55638
  recommended: workdir.is_primary || workdir.path === project.path
55501
55639
  }));
@@ -55532,7 +55670,7 @@ function buildProjectContext(project) {
55532
55670
  };
55533
55671
  }
55534
55672
  function getGitContext(path) {
55535
- if (!existsSync112(join122(path, ".git"))) {
55673
+ if (!existsSync102(join112(path, ".git"))) {
55536
55674
  return { isRepo: false, branch: null, dirtyCount: null, remote: null };
55537
55675
  }
55538
55676
  return {
@@ -55575,7 +55713,7 @@ function setupMachineReport(options = {}) {
55575
55713
  const dryRun = options.dryRun !== false;
55576
55714
  const checks3 = [];
55577
55715
  const dbDir = dirname6(getDbPath2());
55578
- const cloudConfig = join132(process.env["HOME"] || "~", ".hasna", "cloud", "config.json");
55716
+ const cloudConfig = join122(process.env["HOME"] || "~", ".hasna", "cloud", "config.json");
55579
55717
  checks3.push(pathCheck("PROJECTS_DATA_DIR", "projects data dir", dbDir, options));
55580
55718
  checks3.push(pathCheck("WORKSPACE_ROOT", "workspace root", machine.workspaceRoot, options));
55581
55719
  checks3.push(commandCheck("bun", ["--version"], "Bun runtime"));
@@ -55636,8 +55774,8 @@ function commandCheck(command, versionArgs, label, missingStatus = "error") {
55636
55774
  }
55637
55775
  function packageVersion() {
55638
55776
  try {
55639
- const pkgPath = join132(dirname6(fileURLToPath(import.meta.url)), "..", "..", "package.json");
55640
- return JSON.parse(readFileSync7(pkgPath, "utf-8")).version || "0.0.0";
55777
+ const pkgPath = join122(dirname6(fileURLToPath(import.meta.url)), "..", "..", "package.json");
55778
+ return JSON.parse(readFileSync6(pkgPath, "utf-8")).version || "0.0.0";
55641
55779
  } catch {
55642
55780
  return "0.0.0";
55643
55781
  }
@@ -55651,7 +55789,7 @@ function findStaleIssues(project) {
55651
55789
  const issues = [];
55652
55790
  const currentMachine = getMachineId();
55653
55791
  for (const p2 of projects) {
55654
- if (p2.status === "active" && !existsSync12(p2.path)) {
55792
+ if (p2.status === "active" && !existsSync112(p2.path)) {
55655
55793
  issues.push({
55656
55794
  code: "PROJECT_PATH_MISSING",
55657
55795
  severity: "error",
@@ -55662,7 +55800,7 @@ function findStaleIssues(project) {
55662
55800
  });
55663
55801
  }
55664
55802
  for (const workdir of listWorkdirs(p2.id)) {
55665
- if (workdir.machine_id === currentMachine && !existsSync12(workdir.path)) {
55803
+ if (workdir.machine_id === currentMachine && !existsSync112(workdir.path)) {
55666
55804
  issues.push({
55667
55805
  code: "WORKDIR_PATH_MISSING",
55668
55806
  severity: "warn",
@@ -56604,7 +56742,7 @@ Reference: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.ht
56604
56742
  }
56605
56743
  const credentials = await fromWebToken({
56606
56744
  ...init,
56607
- webIdentityToken: import_shared_ini_file_loader10.externalDataInterceptor?.getTokenRecord?.()[webIdentityTokenFile] ?? readFileSync4(webIdentityTokenFile, { encoding: "ascii" }),
56745
+ webIdentityToken: import_shared_ini_file_loader10.externalDataInterceptor?.getTokenRecord?.()[webIdentityTokenFile] ?? readFileSync3(webIdentityTokenFile, { encoding: "ascii" }),
56608
56746
  roleArn,
56609
56747
  roleSessionName
56610
56748
  })(awsIdentityProperties);
@@ -56691,7 +56829,7 @@ coverage/
56691
56829
  # Cache
56692
56830
  .cache/
56693
56831
  .turbo/
56694
- `, BOOTSTRAP_PATHS, CONFIG_PATH3, DEFAULTS, nanoid3, import_protocol_http, addExpectContinueMiddlewareOptions, getAddExpectContinuePlugin = (options) => ({
56832
+ `, CONFIG_PATH3, DEFAULTS, nanoid3, import_protocol_http, addExpectContinueMiddlewareOptions, getAddExpectContinuePlugin = (options) => ({
56695
56833
  applyToStack: (clientStack) => {
56696
56834
  clientStack.add(addExpectContinueMiddleware(options), addExpectContinueMiddlewareOptions);
56697
56835
  }
@@ -69770,11 +69908,11 @@ More information can be found at: https://a.co/c895JFp`);
69770
69908
  var numberSelector = (obj, key, type2) => {
69771
69909
  if (!(key in obj))
69772
69910
  return;
69773
- const numberValue = parseInt(obj[key], 10);
69774
- if (Number.isNaN(numberValue)) {
69911
+ const numberValue2 = parseInt(obj[key], 10);
69912
+ if (Number.isNaN(numberValue2)) {
69775
69913
  throw new TypeError(`Cannot load ${type2} '${key}'. Expected number, got '${obj[key]}'.`);
69776
69914
  }
69777
- return numberValue;
69915
+ return numberValue2;
69778
69916
  };
69779
69917
  exports.SelectorType = undefined;
69780
69918
  (function(SelectorType2) {
@@ -74502,7 +74640,7 @@ More information can be found at: https://a.co/c895JFp`);
74502
74640
  };
74503
74641
  });
74504
74642
  require_dist_cjs41 = __commonJS3((exports) => {
74505
- var __dirname2 = "/Users/hasna/Workspace/hasna/opensource/open-projects/node_modules/@aws-sdk/util-user-agent-node/dist-cjs";
74643
+ var __dirname2 = "/home/hasna/workspace/hasna/opensource/open-projects/node_modules/@aws-sdk/util-user-agent-node/dist-cjs";
74506
74644
  var node_os = __require3("os");
74507
74645
  var node_process = __require3("process");
74508
74646
  var utilConfigProvider = require_dist_cjs28();
@@ -78172,10 +78310,10 @@ More information can be found at: https://a.co/c895JFp`);
78172
78310
  await fs2.writeFile(tokenFilePath, JSON.stringify(token, null, 2), "utf8");
78173
78311
  }
78174
78312
  getTokenFilePath() {
78175
- const directory = process.env.AWS_LOGIN_CACHE_DIRECTORY ?? join62(homedir22(), ".aws", "login", "cache");
78313
+ const directory = process.env.AWS_LOGIN_CACHE_DIRECTORY ?? join52(homedir22(), ".aws", "login", "cache");
78176
78314
  const loginSessionBytes = Buffer.from(this.loginSession, "utf8");
78177
78315
  const loginSessionSha256 = createHash("sha256").update(loginSessionBytes).digest("hex");
78178
- return join62(directory, `${loginSessionSha256}.json`);
78316
+ return join52(directory, `${loginSessionSha256}.json`);
78179
78317
  }
78180
78318
  derToRawSignature(derSignature) {
78181
78319
  let offset = 2;
@@ -78476,18 +78614,7 @@ More information can be found at: https://a.co/c895JFp`);
78476
78614
  INSERT OR IGNORE INTO _migrations (id) VALUES (4);
78477
78615
  `
78478
78616
  ];
78479
- BOOTSTRAP_PATHS = [
78480
- ".gitignore",
78481
- ".project.json",
78482
- "CLAUDE.md",
78483
- "AGENTS.md",
78484
- "README.md",
78485
- "docs",
78486
- "data",
78487
- "scripts",
78488
- "assets"
78489
- ];
78490
- CONFIG_PATH3 = join42(homedir11(), ".hasna", "projects", "config.json");
78617
+ CONFIG_PATH3 = join32(homedir11(), ".hasna", "projects", "config.json");
78491
78618
  DEFAULTS = {
78492
78619
  default_path: process.cwd(),
78493
78620
  default_github_org: "hasnaxyz",
@@ -84273,7 +84400,7 @@ More information can be found at: https://a.co/c895JFp`);
84273
84400
  }).s("AmazonS3", "PutObject", {}).n("S3Client", "PutObjectCommand").sc(PutObject$).build() {
84274
84401
  };
84275
84402
  MAX_FILE_SIZE = 100 * 1024 * 1024;
84276
- CONFIG_PATH22 = join92(process.env["HOME"] || "~", ".hasna", "projects", "scheduler.json");
84403
+ CONFIG_PATH22 = join82(process.env["HOME"] || "~", ".hasna", "projects", "scheduler.json");
84277
84404
  SPARK_MACHINES = new Set(["spark01", "spark02"]);
84278
84405
  });
84279
84406
 
@@ -85264,12 +85391,12 @@ __export(exports_contacts_connector, {
85264
85391
  });
85265
85392
  function getContactsDb() {
85266
85393
  const { Database: Database5 } = __require("bun:sqlite");
85267
- const { existsSync: existsSync13 } = __require("fs");
85268
- const { join: join15 } = __require("path");
85394
+ const { existsSync: existsSync5 } = __require("fs");
85395
+ const { join: join16 } = __require("path");
85269
85396
  const { homedir: homedir7 } = __require("os");
85270
85397
  const envPath = process.env["HASNA_CONTACTS_DB_PATH"] ?? process.env["OPEN_CONTACTS_DB"];
85271
- const dbPath = envPath ?? join15(homedir7(), ".hasna", "contacts", "contacts.db");
85272
- if (!existsSync13(dbPath))
85398
+ const dbPath = envPath ?? join16(homedir7(), ".hasna", "contacts", "contacts.db");
85399
+ if (!existsSync5(dbPath))
85273
85400
  return null;
85274
85401
  const db2 = new Database5(dbPath, { readonly: true });
85275
85402
  return db2;
@@ -85389,7 +85516,7 @@ __export(exports_army_runner, {
85389
85516
  waitForArmyRun: () => waitForArmyRun,
85390
85517
  runWithArmy: () => runWithArmy
85391
85518
  });
85392
- import { join as join15 } from "path";
85519
+ import { join as join16 } from "path";
85393
85520
  function chunkArray(arr, n2) {
85394
85521
  const chunks = [];
85395
85522
  const size = Math.ceil(arr.length / n2);
@@ -85399,7 +85526,7 @@ function chunkArray(arr, n2) {
85399
85526
  return chunks;
85400
85527
  }
85401
85528
  function getCliPath() {
85402
- const srcPath = join15(import.meta.dir, "../cli/index.tsx");
85529
+ const srcPath = join16(import.meta.dir, "../cli/index.tsx");
85403
85530
  return srcPath;
85404
85531
  }
85405
85532
  async function runWithArmy(options) {
@@ -85602,12 +85729,28 @@ Rules:
85602
85729
  ];
85603
85730
  const messages = [{ role: "user", content: contentParts }];
85604
85731
  try {
85605
- const response = await anthropicClient.messages.create({
85606
- model,
85607
- max_tokens: 2048,
85608
- messages
85609
- });
85610
- const text2 = response.content.filter((b2) => b2.type === "text").map((b2) => b2.text).join("");
85732
+ let text2;
85733
+ const provider = detectProvider(model);
85734
+ if (provider !== "anthropic") {
85735
+ const compat2 = client;
85736
+ const response = await callOpenAICompatible({
85737
+ baseUrl: compat2.baseUrl,
85738
+ apiKey: compat2.apiKey,
85739
+ model,
85740
+ system: "You are a QA engineer.",
85741
+ messages: [{ role: "user", content: prompt }],
85742
+ tools: [],
85743
+ maxTokens: 2048
85744
+ });
85745
+ text2 = response.content.filter((b2) => b2.type === "text").map((b2) => b2.text).join("");
85746
+ } else {
85747
+ const response = await anthropicClient.messages.create({
85748
+ model,
85749
+ max_tokens: 2048,
85750
+ messages
85751
+ });
85752
+ text2 = response.content.filter((b2) => b2.type === "text").map((b2) => b2.text).join("");
85753
+ }
85611
85754
  const match = text2.match(/\[[\s\S]*\]/);
85612
85755
  if (!match)
85613
85756
  return [];
@@ -85635,7 +85778,7 @@ async function crawlAndGenerate(options) {
85635
85778
  } = options;
85636
85779
  const config2 = loadConfig();
85637
85780
  const model = resolveModel2(options.model ?? config2.defaultModel ?? "thorough");
85638
- const client = createClient(options.apiKey ?? config2.anthropicApiKey);
85781
+ const client = createClientForModel(model, resolveProviderApiKeyForModel(model, options.apiKey, config2.anthropicApiKey));
85639
85782
  const rootOrigin = new URL(url2).origin;
85640
85783
  const visited = new Set;
85641
85784
  const queue = [url2];
@@ -85715,7 +85858,6 @@ var init_crawl_and_generate = __esm(() => {
85715
85858
  init_scenarios();
85716
85859
  init_ai_client();
85717
85860
  init_config2();
85718
- init_ai_client();
85719
85861
  DEFAULT_SKIP_PATTERNS = [
85720
85862
  "/logout",
85721
85863
  "/sign-out",
@@ -86171,9 +86313,30 @@ function buildServer() {
86171
86313
  goalPrompt: exports_external.string().optional().describe("Goal prompt for the AI SDK workflow agent"),
86172
86314
  successCriteria: exports_external.array(exports_external.string()).optional().describe("Goal success criteria"),
86173
86315
  maxIterations: exports_external.number().int().min(1).max(20).optional().describe("Max goal loop iterations"),
86174
- executionTarget: exports_external.enum(["local", "connector:e2b"]).optional().describe("Run locally or through the open-connectors E2B connector"),
86175
- e2bTemplate: exports_external.string().optional().describe("E2B sandbox template for connector:e2b")
86176
- }, async ({ name: name21, description, projectId, scenarioIds, tags, priority, personaIds, goalPrompt, successCriteria, maxIterations, executionTarget, e2bTemplate }) => {
86316
+ executionTarget: exports_external.enum(["local", "sandbox", "connector:e2b"]).optional().describe("Run locally or through the sandboxes SDK"),
86317
+ sandboxProvider: exports_external.string().optional().describe("Sandbox provider: e2b, daytona, or modal"),
86318
+ sandboxImage: exports_external.string().optional().describe("Sandbox image/template"),
86319
+ sandboxRemoteDir: exports_external.string().optional().describe("Remote working directory for sandbox runs"),
86320
+ sandboxCleanup: exports_external.enum(["delete", "stop", "keep"]).optional().describe("Sandbox cleanup mode"),
86321
+ e2bTemplate: exports_external.string().optional().describe("Legacy alias for sandboxImage")
86322
+ }, async ({
86323
+ name: name21,
86324
+ description,
86325
+ projectId,
86326
+ scenarioIds,
86327
+ tags,
86328
+ priority,
86329
+ personaIds,
86330
+ goalPrompt,
86331
+ successCriteria,
86332
+ maxIterations,
86333
+ executionTarget,
86334
+ sandboxProvider,
86335
+ sandboxImage,
86336
+ sandboxRemoteDir,
86337
+ sandboxCleanup,
86338
+ e2bTemplate
86339
+ }) => {
86177
86340
  try {
86178
86341
  return json3(createTestingWorkflow({
86179
86342
  name: name21,
@@ -86184,8 +86347,10 @@ function buildServer() {
86184
86347
  goal: goalPrompt ? { prompt: goalPrompt, successCriteria, maxIterations } : null,
86185
86348
  execution: {
86186
86349
  target: executionTarget ?? "local",
86187
- connector: executionTarget === "connector:e2b" ? "e2b" : undefined,
86188
- sandboxTemplate: e2bTemplate
86350
+ provider: sandboxProvider ?? (executionTarget === "connector:e2b" ? "e2b" : undefined),
86351
+ sandboxImage: sandboxImage ?? e2bTemplate,
86352
+ sandboxRemoteDir,
86353
+ sandboxCleanup
86189
86354
  }
86190
86355
  }));
86191
86356
  } catch (error40) {
@@ -86949,12 +87114,12 @@ function buildServer() {
86949
87114
  }
86950
87115
  if (!resolvedUrl)
86951
87116
  return errorResponse(new Error("No URL provided and no default environment set. Pass url or env."));
86952
- const { execSync: execSync3 } = await import("child_process");
87117
+ const { execSync: execSync4 } = await import("child_process");
86953
87118
  let diffOutput = "";
86954
87119
  try {
86955
87120
  const ref = baseRef ?? "HEAD";
86956
- const stagedOut = execSync3(`git diff --cached --name-only`, { cwd: process.cwd(), encoding: "utf-8" }).trim();
86957
- const unstagedOut = execSync3(`git diff --name-only ${ref}`, { cwd: process.cwd(), encoding: "utf-8" }).trim();
87121
+ const stagedOut = execSync4(`git diff --cached --name-only`, { cwd: process.cwd(), encoding: "utf-8" }).trim();
87122
+ const unstagedOut = execSync4(`git diff --name-only ${ref}`, { cwd: process.cwd(), encoding: "utf-8" }).trim();
86958
87123
  diffOutput = [stagedOut, unstagedOut].filter(Boolean).join(`
86959
87124
  `);
86960
87125
  } catch {
@@ -87091,8 +87256,8 @@ function buildServer() {
87091
87256
  let allFiles = [...filePaths];
87092
87257
  if (includeAutoDetect) {
87093
87258
  try {
87094
- const { execSync: execSync3 } = await import("child_process");
87095
- const diffOutput = execSync3("git diff --name-only HEAD", { encoding: "utf-8", cwd: process.cwd() }).trim();
87259
+ const { execSync: execSync4 } = await import("child_process");
87260
+ const diffOutput = execSync4("git diff --name-only HEAD", { encoding: "utf-8", cwd: process.cwd() }).trim();
87096
87261
  const gitFiles = diffOutput.split(`
87097
87262
  `).filter(Boolean);
87098
87263
  allFiles = [...new Set([...allFiles, ...gitFiles])];
@@ -87637,7 +87802,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
87637
87802
  // src/mcp/http.ts
87638
87803
  import { createServer } from "http";
87639
87804
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
87640
- var DEFAULT_MCP_HTTP_PORT = 8880;
87805
+ var DEFAULT_MCP_HTTP_PORT = 8840;
87641
87806
  var DEFAULT_HOST = "127.0.0.1";
87642
87807
  function resolveMcpHttpPort(explicitPort) {
87643
87808
  if (explicitPort !== undefined && !Number.isNaN(explicitPort))
@@ -87659,8 +87824,8 @@ function parseCliPort(args) {
87659
87824
  }
87660
87825
  return;
87661
87826
  }
87662
- function isStdioMode(args) {
87663
- return args.includes("--stdio") || process.env.MCP_STDIO === "1";
87827
+ function isHttpMode(args) {
87828
+ return args.includes("--http") || process.env.MCP_HTTP === "1";
87664
87829
  }
87665
87830
  async function readJsonBody(req) {
87666
87831
  const chunks = [];
@@ -87748,14 +87913,14 @@ process.on("uncaughtException", (err) => {
87748
87913
  });
87749
87914
  async function main() {
87750
87915
  const args = process.argv.slice(2);
87751
- if (isStdioMode(args)) {
87752
- const { buildServer: buildServer2 } = await Promise.resolve().then(() => (init_server(), exports_server));
87753
- const server = buildServer2();
87754
- const transport = new StdioServerTransport;
87755
- await server.connect(transport);
87916
+ if (isHttpMode(args)) {
87917
+ await startMcpHttpServer({ name: "testers", port: parseCliPort(args) });
87756
87918
  return;
87757
87919
  }
87758
- await startMcpHttpServer({ name: "testers", port: parseCliPort(args) });
87920
+ const { buildServer: buildServer2 } = await Promise.resolve().then(() => (init_server(), exports_server));
87921
+ const server = buildServer2();
87922
+ const transport = new StdioServerTransport;
87923
+ await server.connect(transport);
87759
87924
  }
87760
87925
  main().catch((error40) => {
87761
87926
  console.error("Failed to start testers:", error40);