@hasna/testers 0.0.34 → 0.0.35

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.35",
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,
@@ -16703,6 +16747,7 @@ __export(exports_ai_client, {
16703
16747
  createClientForModel: () => createClientForModel,
16704
16748
  createClient: () => createClient,
16705
16749
  callOpenAICompatible: () => callOpenAICompatible,
16750
+ buildScenarioUserMessage: () => buildScenarioUserMessage,
16706
16751
  BROWSER_TOOLS: () => BROWSER_TOOLS
16707
16752
  });
16708
16753
  import Anthropic2 from "@anthropic-ai/sdk";
@@ -17115,7 +17160,6 @@ async function executeTool(page, screenshotter, toolName, toolInput, context) {
17115
17160
  const assertionType = toolInput.assertion_type;
17116
17161
  const selector = toolInput.selector;
17117
17162
  const expected = toolInput.expected;
17118
- const sessionId = context.sessionId ?? "default";
17119
17163
  switch (assertionType) {
17120
17164
  case "element_exists": {
17121
17165
  if (!selector)
@@ -17180,7 +17224,6 @@ async function executeTool(page, screenshotter, toolName, toolInput, context) {
17180
17224
  case "browser_intercept": {
17181
17225
  const action = toolInput.action;
17182
17226
  const pattern = toolInput.pattern;
17183
- const interceptAction = toolInput.intercept_action;
17184
17227
  const statusCode = toolInput.status_code;
17185
17228
  const body = toolInput.body;
17186
17229
  const sessionId = context.sessionId ?? "default";
@@ -17257,7 +17300,28 @@ ${JSON.stringify(har, null, 2)}` };
17257
17300
  }
17258
17301
  case "browser_a11y": {
17259
17302
  const level = toolInput.level ?? "AA";
17260
- const snapshot = await page.accessibility.snapshot();
17303
+ const snapshot = await page.evaluate(() => {
17304
+ function readRole(el) {
17305
+ return el.getAttribute("role") ?? el.tagName.toLowerCase();
17306
+ }
17307
+ function readName(el) {
17308
+ const labelledBy = el.getAttribute("aria-labelledby");
17309
+ if (labelledBy) {
17310
+ const labelledText = labelledBy.split(/\s+/).map((id) => document.getElementById(id)?.textContent?.trim()).filter(Boolean).join(" ");
17311
+ if (labelledText)
17312
+ return labelledText;
17313
+ }
17314
+ return el.getAttribute("aria-label") ?? el.getAttribute("alt") ?? el.textContent?.trim() ?? "";
17315
+ }
17316
+ function walk(el) {
17317
+ return {
17318
+ role: readRole(el),
17319
+ name: readName(el),
17320
+ children: Array.from(el.children).map((child) => walk(child))
17321
+ };
17322
+ }
17323
+ return document.body ? walk(document.body) : null;
17324
+ });
17261
17325
  if (!snapshot)
17262
17326
  return { result: "Error: could not capture accessibility tree" };
17263
17327
  const issues = [];
@@ -17299,6 +17363,38 @@ ${filtered.join(`
17299
17363
  return { result: `Error executing ${toolName}: ${message}` };
17300
17364
  }
17301
17365
  }
17366
+ function resolveStartUrl(baseUrl, targetPath) {
17367
+ try {
17368
+ return new URL(targetPath, baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`).toString();
17369
+ } catch {
17370
+ return `${baseUrl.replace(/\/+$/, "")}/${targetPath.replace(/^\/+/, "")}`;
17371
+ }
17372
+ }
17373
+ function buildScenarioUserMessage(scenario, baseUrl) {
17374
+ const userParts = [
17375
+ `**Scenario:** ${scenario.name}`,
17376
+ `**Description:** ${scenario.description}`
17377
+ ];
17378
+ if (baseUrl) {
17379
+ const normalizedBaseUrl = baseUrl.replace(/\/+$/, "");
17380
+ userParts.push(`**Base URL:** ${normalizedBaseUrl}`);
17381
+ if (scenario.targetPath) {
17382
+ userParts.push(`**Start URL:** ${resolveStartUrl(normalizedBaseUrl, scenario.targetPath)}`);
17383
+ }
17384
+ 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.");
17385
+ }
17386
+ if (scenario.targetPath) {
17387
+ userParts.push(`**Target Path:** ${scenario.targetPath}`);
17388
+ }
17389
+ if (scenario.steps.length > 0) {
17390
+ userParts.push("**Steps:**");
17391
+ for (let i = 0;i < scenario.steps.length; i++) {
17392
+ userParts.push(`${i + 1}. ${scenario.steps[i]}`);
17393
+ }
17394
+ }
17395
+ return userParts.join(`
17396
+ `);
17397
+ }
17302
17398
  async function runAgentLoop(options) {
17303
17399
  const {
17304
17400
  client,
@@ -17308,6 +17404,7 @@ async function runAgentLoop(options) {
17308
17404
  model,
17309
17405
  runId,
17310
17406
  sessionId,
17407
+ baseUrl,
17311
17408
  maxTurns = 30,
17312
17409
  onStep,
17313
17410
  persona,
@@ -17355,21 +17452,7 @@ Instructions: ${persona.instructions}` : "",
17355
17452
  "- Verify both positive and negative states"
17356
17453
  ].join(`
17357
17454
  `) + 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
- `);
17455
+ const userMessage = buildScenarioUserMessage(scenario, baseUrl);
17373
17456
  const screenshots = [];
17374
17457
  let tokensUsed = 0;
17375
17458
  let stepNumber = 0;
@@ -17432,7 +17515,7 @@ Instructions: ${persona.instructions}` : "",
17432
17515
  if (onStep) {
17433
17516
  onStep({ type: "tool_call", toolName: toolBlock.name, toolInput, stepNumber });
17434
17517
  }
17435
- const execResult = await executeTool(page, screenshotter, toolBlock.name, toolInput, { runId, scenarioSlug, stepNumber, sessionId, a11y });
17518
+ const execResult = await executeTool(page, screenshotter, toolBlock.name, toolInput, { runId, scenarioSlug, stepNumber, sessionId: sessionId ?? runId, a11y });
17436
17519
  if (onStep) {
17437
17520
  onStep({ type: "tool_result", toolName: toolBlock.name, toolResult: execResult.result, stepNumber });
17438
17521
  }
@@ -20631,6 +20714,292 @@ var init_failure_pipeline = __esm(() => {
20631
20714
  init_todos_connector();
20632
20715
  });
20633
20716
 
20717
+ // src/lib/a11y-audit.ts
20718
+ async function runA11yAudit(page, options = {}) {
20719
+ const { level = "AA", rules, exclude = [] } = options;
20720
+ await page.addScriptTag({ url: "https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.9.1/axe.min.js" });
20721
+ const config = {
20722
+ runOnly: {
20723
+ type: level === "AAA" ? "standard" : "tag",
20724
+ values: level === "AAA" ? undefined : [level, "best-practice"]
20725
+ }
20726
+ };
20727
+ if (rules && rules.length > 0) {
20728
+ config.rules = Object.fromEntries(rules.map((r) => [r, { enabled: true }]));
20729
+ }
20730
+ if (exclude.length > 0) {
20731
+ config.exclude = exclude;
20732
+ }
20733
+ const result = await page.evaluate(async (auditConfig) => {
20734
+ const axeResult = await window.axe.run(auditConfig);
20735
+ return axeResult;
20736
+ }, config);
20737
+ const violations = (result.violations ?? []).map((v) => ({
20738
+ id: v.id,
20739
+ impact: v.impact,
20740
+ description: v.description,
20741
+ help: v.help,
20742
+ helpUrl: v.helpUrl,
20743
+ nodes: (v.nodes ?? []).map((n) => ({
20744
+ html: n.html,
20745
+ target: n.target,
20746
+ failureSummary: n.failureSummary
20747
+ }))
20748
+ }));
20749
+ const passes = (result.passes ?? []).map((p) => ({
20750
+ id: p.id,
20751
+ description: p.description
20752
+ }));
20753
+ const incomplete = (result.incomplete ?? []).map((i) => ({
20754
+ id: i.id,
20755
+ description: i.description,
20756
+ impact: i.impact
20757
+ }));
20758
+ const criticalCount = violations.filter((v) => v.impact === "critical").length;
20759
+ const seriousCount = violations.filter((v) => v.impact === "serious").length;
20760
+ const moderateCount = violations.filter((v) => v.impact === "moderate").length;
20761
+ const minorCount = violations.filter((v) => v.impact === "minor").length;
20762
+ return {
20763
+ violations,
20764
+ passes,
20765
+ incomplete,
20766
+ url: page.url(),
20767
+ timestamp: new Date().toISOString(),
20768
+ totalViolations: violations.length,
20769
+ criticalCount,
20770
+ seriousCount,
20771
+ moderateCount,
20772
+ minorCount
20773
+ };
20774
+ }
20775
+
20776
+ // src/lib/assertions.ts
20777
+ async function evaluateAssertions(page, assertions, context = {}) {
20778
+ const results = [];
20779
+ for (const assertion of assertions) {
20780
+ try {
20781
+ const result = await evaluateOne(page, assertion, context);
20782
+ results.push(result);
20783
+ } catch (err) {
20784
+ results.push({
20785
+ assertion,
20786
+ passed: false,
20787
+ actual: "",
20788
+ error: err instanceof Error ? err.message : String(err)
20789
+ });
20790
+ }
20791
+ }
20792
+ return results;
20793
+ }
20794
+ async function evaluateOne(page, assertion, context) {
20795
+ switch (assertion.type) {
20796
+ case "visible": {
20797
+ const visible = await page.locator(assertion.selector).isVisible();
20798
+ return {
20799
+ assertion,
20800
+ passed: visible,
20801
+ actual: String(visible)
20802
+ };
20803
+ }
20804
+ case "not_visible": {
20805
+ const visible = await page.locator(assertion.selector).isVisible();
20806
+ return {
20807
+ assertion,
20808
+ passed: !visible,
20809
+ actual: String(visible)
20810
+ };
20811
+ }
20812
+ case "text_contains": {
20813
+ const text = await page.locator(assertion.selector).textContent() ?? "";
20814
+ const expected = String(assertion.expected ?? "");
20815
+ return {
20816
+ assertion,
20817
+ passed: text.includes(expected),
20818
+ actual: text
20819
+ };
20820
+ }
20821
+ case "text_equals": {
20822
+ const text = await page.locator(assertion.selector).textContent() ?? "";
20823
+ const expected = String(assertion.expected ?? "");
20824
+ return {
20825
+ assertion,
20826
+ passed: text.trim() === expected.trim(),
20827
+ actual: text
20828
+ };
20829
+ }
20830
+ case "element_count": {
20831
+ const count = await page.locator(assertion.selector).count();
20832
+ const expected = Number(assertion.expected ?? 0);
20833
+ return {
20834
+ assertion,
20835
+ passed: count === expected,
20836
+ actual: String(count)
20837
+ };
20838
+ }
20839
+ case "no_console_errors": {
20840
+ if (context.consoleErrors !== undefined) {
20841
+ const errors2 = context.consoleErrors.filter(Boolean);
20842
+ return {
20843
+ assertion,
20844
+ passed: errors2.length === 0,
20845
+ actual: errors2.length === 0 ? "No console errors captured" : errors2.slice(0, 3).join(" | ")
20846
+ };
20847
+ }
20848
+ const errorElements = await page.locator('[role="alert"], .error, .error-message, [data-testid="error"]').count();
20849
+ return {
20850
+ assertion,
20851
+ passed: errorElements === 0,
20852
+ actual: `${errorElements} error element(s) found`
20853
+ };
20854
+ }
20855
+ case "no_a11y_violations": {
20856
+ try {
20857
+ const auditResult = await runA11yAudit(page);
20858
+ const hasIssues = auditResult.violations.length > 0;
20859
+ return {
20860
+ assertion,
20861
+ passed: !hasIssues,
20862
+ actual: hasIssues ? `${auditResult.totalViolations} violation(s): ${auditResult.violations.map((v) => v.id).join(", ")}` : "No accessibility violations found"
20863
+ };
20864
+ } catch (err) {
20865
+ return {
20866
+ assertion,
20867
+ passed: false,
20868
+ actual: "",
20869
+ error: err instanceof Error ? err.message : String(err)
20870
+ };
20871
+ }
20872
+ }
20873
+ case "url_contains": {
20874
+ const url = page.url();
20875
+ const expected = String(assertion.expected ?? "");
20876
+ return {
20877
+ assertion,
20878
+ passed: url.includes(expected),
20879
+ actual: url
20880
+ };
20881
+ }
20882
+ case "title_contains": {
20883
+ const title = await page.title();
20884
+ const expected = String(assertion.expected ?? "");
20885
+ return {
20886
+ assertion,
20887
+ passed: title.includes(expected),
20888
+ actual: title
20889
+ };
20890
+ }
20891
+ case "cookie_exists": {
20892
+ const cookieName = assertion.expected;
20893
+ const cookies = await page.context().cookies();
20894
+ const found = cookies.some((c) => c.name === cookieName);
20895
+ return {
20896
+ assertion,
20897
+ passed: found,
20898
+ actual: found ? `Cookie "${cookieName}" exists` : `Cookie "${cookieName}" not found`
20899
+ };
20900
+ }
20901
+ case "cookie_not_exists": {
20902
+ const cookieName = assertion.expected;
20903
+ const cookies = await page.context().cookies();
20904
+ const found = cookies.some((c) => c.name === cookieName);
20905
+ return {
20906
+ assertion,
20907
+ passed: !found,
20908
+ actual: found ? `Cookie "${cookieName}" found (unexpected)` : `Cookie "${cookieName}" does not exist`
20909
+ };
20910
+ }
20911
+ case "cookie_value": {
20912
+ const [cookieName, expectedValue] = assertion.expected.split("=", 2);
20913
+ const cookies = await page.context().cookies();
20914
+ const cookie = cookies.find((c) => c.name === cookieName);
20915
+ const actualValue = cookie?.value ?? "";
20916
+ return {
20917
+ assertion,
20918
+ passed: actualValue === expectedValue,
20919
+ actual: cookie ? `${cookieName}=${actualValue}` : `Cookie "${cookieName}" not found`
20920
+ };
20921
+ }
20922
+ case "local_storage_exists": {
20923
+ const key = assertion.expected;
20924
+ const value = await page.evaluate((k) => localStorage.getItem(k), key);
20925
+ return {
20926
+ assertion,
20927
+ passed: value !== null,
20928
+ actual: value !== null ? `Key "${key}" exists with value "${value}"` : `Key "${key}" not found in localStorage`
20929
+ };
20930
+ }
20931
+ case "local_storage_not_exists": {
20932
+ const key = assertion.expected;
20933
+ const value = await page.evaluate((k) => localStorage.getItem(k), key);
20934
+ return {
20935
+ assertion,
20936
+ passed: value === null,
20937
+ actual: value !== null ? `Key "${key}" exists (unexpected)` : `Key "${key}" does not exist in localStorage`
20938
+ };
20939
+ }
20940
+ case "local_storage_value": {
20941
+ const [lsKey, expectedValue] = assertion.expected.split("=", 2);
20942
+ const value = await page.evaluate((k) => localStorage.getItem(k), lsKey ?? "");
20943
+ return {
20944
+ assertion,
20945
+ passed: value === expectedValue,
20946
+ actual: value !== null ? `${lsKey}=${value}` : `Key "${lsKey}" not found in localStorage`
20947
+ };
20948
+ }
20949
+ case "session_storage_value": {
20950
+ const [ssKey, expectedValue] = assertion.expected.split("=", 2);
20951
+ const value = await page.evaluate((k) => sessionStorage.getItem(k), ssKey ?? "");
20952
+ return {
20953
+ assertion,
20954
+ passed: value === expectedValue,
20955
+ actual: value !== null ? `${ssKey}=${value}` : `Key "${ssKey}" not found in sessionStorage`
20956
+ };
20957
+ }
20958
+ case "session_storage_not_exists": {
20959
+ const key = assertion.expected;
20960
+ const value = await page.evaluate((k) => sessionStorage.getItem(k), key);
20961
+ return {
20962
+ assertion,
20963
+ passed: value === null,
20964
+ actual: value !== null ? `Key "${key}" exists (unexpected)` : `Key "${key}" does not exist in sessionStorage`
20965
+ };
20966
+ }
20967
+ default: {
20968
+ return {
20969
+ assertion,
20970
+ passed: false,
20971
+ actual: "",
20972
+ error: `Unknown assertion type: ${assertion.type}`
20973
+ };
20974
+ }
20975
+ }
20976
+ }
20977
+ function allAssertionsPassed(results) {
20978
+ return results.every((r) => r.passed);
20979
+ }
20980
+ function formatAssertionResults(results) {
20981
+ if (results.length === 0)
20982
+ return "No assertions.";
20983
+ const lines = [];
20984
+ for (const r of results) {
20985
+ const icon = r.passed ? "PASS" : "FAIL";
20986
+ const desc = r.assertion.description || `${r.assertion.type}${r.assertion.selector ? ` ${r.assertion.selector}` : ""}`;
20987
+ let line = ` [${icon}] ${desc}`;
20988
+ if (!r.passed) {
20989
+ line += ` (actual: ${r.actual})`;
20990
+ if (r.error)
20991
+ line += ` \u2014 ${r.error}`;
20992
+ }
20993
+ lines.push(line);
20994
+ }
20995
+ const passed = results.filter((r) => r.passed).length;
20996
+ lines.push(`
20997
+ ${passed}/${results.length} assertions passed.`);
20998
+ return lines.join(`
20999
+ `);
21000
+ }
21001
+ var init_assertions = () => {};
21002
+
20634
21003
  // src/db/flows.ts
20635
21004
  var exports_flows = {};
20636
21005
  __export(exports_flows, {
@@ -20789,7 +21158,9 @@ __export(exports_runner, {
20789
21158
  runSingleScenario: () => runSingleScenario,
20790
21159
  runByFilter: () => runByFilter,
20791
21160
  runBatch: () => runBatch,
20792
- onRunEvent: () => onRunEvent
21161
+ resolveScenariosForRun: () => resolveScenariosForRun,
21162
+ onRunEvent: () => onRunEvent,
21163
+ applyStructuredAssertionsToResult: () => applyStructuredAssertionsToResult
20793
21164
  });
20794
21165
  import { mkdirSync as mkdirSync8 } from "fs";
20795
21166
  import { join as join13 } from "path";
@@ -20801,6 +21172,54 @@ function emit(event) {
20801
21172
  if (eventHandler)
20802
21173
  eventHandler(event);
20803
21174
  }
21175
+ function assertionDescription(result) {
21176
+ return result.assertion.description || `${result.assertion.type}${result.assertion.selector ? ` ${result.assertion.selector}` : ""}`;
21177
+ }
21178
+ function summarizeAssertionResult(result) {
21179
+ const description = assertionDescription(result);
21180
+ if (result.passed)
21181
+ return description;
21182
+ const suffix = result.error ? `; ${result.error}` : "";
21183
+ return `${description} (actual: ${result.actual}${suffix})`;
21184
+ }
21185
+ async function applyStructuredAssertionsToResult(input) {
21186
+ const assertions = input.scenario.assertions ?? [];
21187
+ if (assertions.length === 0) {
21188
+ return {
21189
+ status: input.status,
21190
+ reasoning: input.reasoning,
21191
+ assertionsPassed: [],
21192
+ assertionsFailed: [],
21193
+ assertionResults: []
21194
+ };
21195
+ }
21196
+ const results = await evaluateAssertions(input.page, assertions, {
21197
+ consoleErrors: input.consoleErrors
21198
+ });
21199
+ const assertionsPassed = results.filter((r) => r.passed).map(summarizeAssertionResult);
21200
+ const assertionsFailed = results.filter((r) => !r.passed).map(summarizeAssertionResult);
21201
+ const assertionResults = results.map((result) => ({
21202
+ type: result.assertion.type,
21203
+ description: assertionDescription(result),
21204
+ passed: result.passed,
21205
+ actual: result.actual,
21206
+ ...result.error ? { error: result.error } : {}
21207
+ }));
21208
+ const assertionsOk = allAssertionsPassed(results);
21209
+ const status = assertionsOk || input.status !== "passed" ? input.status : "failed";
21210
+ const assertionHeading = assertionsOk ? "Structured assertions passed:" : "Structured assertions failed:";
21211
+ const reasoningParts = [input.reasoning, `${assertionHeading}
21212
+ ${formatAssertionResults(results)}`].map((part) => part.trim()).filter(Boolean);
21213
+ return {
21214
+ status,
21215
+ reasoning: reasoningParts.join(`
21216
+
21217
+ `),
21218
+ assertionsPassed,
21219
+ assertionsFailed,
21220
+ assertionResults
21221
+ };
21222
+ }
20804
21223
  function withTimeout(promise, ms, label) {
20805
21224
  return new Promise((resolve, reject) => {
20806
21225
  const warningAt = Math.floor(ms * 0.8);
@@ -20971,6 +21390,7 @@ async function runSingleScenario(scenario, runId, options) {
20971
21390
  model,
20972
21391
  runId,
20973
21392
  sessionId: result.id,
21393
+ baseUrl: options.url,
20974
21394
  maxTurns: effectiveOptions.minimal ? 10 : 30,
20975
21395
  a11y: effectiveOptions.a11y,
20976
21396
  persona: persona ? {
@@ -21053,27 +21473,46 @@ async function runSingleScenario(scenario, runId, options) {
21053
21473
  closeSession(result.id);
21054
21474
  const lightpandaNote = options.engine === "lightpanda" ? " (Running with Lightpanda \u2014 no screenshots)" : options.engine === "bun" ? " (Running with Bun.WebView \u2014 native, ~11x faster)" : "";
21055
21475
  const networkMeta = networkErrors.length > 0 ? { networkErrors: networkErrors.slice(0, 20) } : {};
21056
- let updatedResult = updateResult(result.id, {
21476
+ const baseReasoning = agentResult.reasoning ? agentResult.reasoning + lightpandaNote : lightpandaNote || "";
21477
+ const assertionOutcome = await applyStructuredAssertionsToResult({
21478
+ page,
21479
+ scenario,
21480
+ consoleErrors,
21057
21481
  status: agentResult.status,
21058
- reasoning: agentResult.reasoning ? agentResult.reasoning + lightpandaNote : lightpandaNote || undefined,
21482
+ reasoning: baseReasoning
21483
+ });
21484
+ const structuredAssertionMeta = assertionOutcome.assertionResults.length > 0 ? {
21485
+ structuredAssertions: {
21486
+ passed: assertionOutcome.assertionsPassed,
21487
+ failed: assertionOutcome.assertionsFailed,
21488
+ results: assertionOutcome.assertionResults
21489
+ }
21490
+ } : {};
21491
+ let updatedResult = updateResult(result.id, {
21492
+ status: assertionOutcome.status,
21493
+ reasoning: assertionOutcome.reasoning || undefined,
21059
21494
  stepsCompleted: agentResult.stepsCompleted,
21060
21495
  durationMs: Date.now() - new Date(result.createdAt).getTime(),
21061
21496
  tokensUsed: agentResult.tokensUsed,
21062
21497
  costCents: estimateCost(model, agentResult.tokensUsed),
21063
- metadata: { consoleLogs, ...networkErrors.length > 0 ? networkMeta : {} }
21498
+ metadata: {
21499
+ consoleLogs,
21500
+ ...networkErrors.length > 0 ? networkMeta : {},
21501
+ ...structuredAssertionMeta
21502
+ }
21064
21503
  });
21065
- if (agentResult.status === "failed" || agentResult.status === "error") {
21066
- const failureAnalysis = analyzeFailure(null, agentResult.reasoning ?? null);
21504
+ if (assertionOutcome.status === "failed" || assertionOutcome.status === "error") {
21505
+ const failureAnalysis = analyzeFailure(null, assertionOutcome.reasoning ?? null);
21067
21506
  if (failureAnalysis) {
21068
21507
  updatedResult = updateResult(result.id, { failureAnalysis });
21069
21508
  }
21070
21509
  }
21071
- if (agentResult.status === "passed") {
21510
+ if (assertionOutcome.status === "passed") {
21072
21511
  try {
21073
21512
  updateScenarioPassedCache(scenario.id, options.url);
21074
21513
  } catch {}
21075
21514
  }
21076
- const eventType = agentResult.status === "passed" ? "scenario:pass" : "scenario:fail";
21515
+ const eventType = assertionOutcome.status === "passed" ? "scenario:pass" : "scenario:fail";
21077
21516
  emit({ type: eventType, scenarioId: scenario.id, scenarioName: scenario.name, resultId: result.id, runId });
21078
21517
  return updatedResult;
21079
21518
  } catch (error) {
@@ -21098,7 +21537,8 @@ async function runSingleScenario(scenario, runId, options) {
21098
21537
  } finally {
21099
21538
  if (harPath) {
21100
21539
  try {
21101
- updateResult(result.id, { metadata: { harPath } });
21540
+ const existing = getResult(result.id);
21541
+ updateResult(result.id, { metadata: { ...existing?.metadata ?? {}, harPath } });
21102
21542
  } catch {}
21103
21543
  }
21104
21544
  if (browser) {
@@ -21270,22 +21710,31 @@ async function runBatch(scenarios, options) {
21270
21710
  }
21271
21711
  return { run: finalRun, results };
21272
21712
  }
21273
- async function runByFilter(options) {
21274
- let scenarios;
21713
+ function findScenarioInList(scenarios, id) {
21714
+ return scenarios.find((scenario) => scenario.id === id || scenario.shortId === id || scenario.id.startsWith(id)) ?? null;
21715
+ }
21716
+ function resolveScenariosForRun(options) {
21275
21717
  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));
21718
+ const scoped = listScenarios({ projectId: options.projectId });
21719
+ const resolved = [];
21720
+ const seen = new Set;
21721
+ for (const id of options.scenarioIds) {
21722
+ const scenario = findScenarioInList(scoped, id) ?? getScenario(id);
21723
+ if (scenario && !seen.has(scenario.id)) {
21724
+ resolved.push(scenario);
21725
+ seen.add(scenario.id);
21726
+ }
21281
21727
  }
21282
- } else {
21283
- scenarios = listScenarios({
21284
- projectId: options.projectId,
21285
- tags: options.tags,
21286
- priority: options.priority
21287
- });
21728
+ return resolved;
21288
21729
  }
21730
+ return listScenarios({
21731
+ projectId: options.projectId,
21732
+ tags: options.tags,
21733
+ priority: options.priority
21734
+ });
21735
+ }
21736
+ async function runByFilter(options) {
21737
+ const scenarios = resolveScenariosForRun(options);
21289
21738
  if (scenarios.length === 0) {
21290
21739
  const config = loadConfig();
21291
21740
  const model = resolveModel2(options.model ?? config.defaultModel);
@@ -21298,17 +21747,7 @@ async function runByFilter(options) {
21298
21747
  function startRunAsync(options) {
21299
21748
  const config = loadConfig();
21300
21749
  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
- }
21750
+ const scenarios = resolveScenariosForRun(options);
21312
21751
  if (!options.skipBudgetCheck) {
21313
21752
  const cap = options.maxCostCents ?? config.defaultMaxCostCents;
21314
21753
  if (cap !== undefined && cap > 0 && scenarios.length > 0) {
@@ -21412,6 +21851,7 @@ var init_runner = __esm(() => {
21412
21851
  init_session_tracker();
21413
21852
  init_webhooks();
21414
21853
  init_failure_pipeline();
21854
+ init_assertions();
21415
21855
  });
21416
21856
 
21417
21857
  // src/lib/affected.ts
@@ -22886,18 +23326,7 @@ function normalizeFilter(input) {
22886
23326
  };
22887
23327
  }
22888
23328
  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 };
23329
+ return input ? workflowExecutionFromValue(input) : DEFAULT_EXECUTION;
22901
23330
  }
22902
23331
  function createTestingWorkflow(input) {
22903
23332
  const db2 = getDatabase();
@@ -22948,6 +23377,9 @@ var init_workflows = __esm(() => {
22948
23377
  });
22949
23378
 
22950
23379
  // src/lib/workflow-runner.ts
23380
+ import { mkdtempSync, rmSync, writeFileSync as writeFileSync3 } from "fs";
23381
+ import { tmpdir } from "os";
23382
+ import { join as join14 } from "path";
22951
23383
  function buildWorkflowRunPlan(workflow, options) {
22952
23384
  const runOptions = {
22953
23385
  url: options.url,
@@ -22964,10 +23396,10 @@ function buildWorkflowRunPlan(workflow, options) {
22964
23396
  return {
22965
23397
  workflow,
22966
23398
  runOptions,
22967
- connectorCommand: workflow.execution.target === "connector:e2b" ? buildConnectorCommand(workflow.execution, runOptions) : null
23399
+ sandbox: workflow.execution.target === "sandbox" ? buildSandboxPlan(workflow, workflow.execution, runOptions) : null
22968
23400
  };
22969
23401
  }
22970
- async function runTestingWorkflow(workflowId, options) {
23402
+ async function runTestingWorkflow(workflowId, options, dependencies = {}) {
22971
23403
  const workflow = getTestingWorkflow(workflowId);
22972
23404
  if (!workflow)
22973
23405
  throw new Error(`Testing workflow not found: ${workflowId}`);
@@ -22977,13 +23409,25 @@ async function runTestingWorkflow(workflowId, options) {
22977
23409
  const plan = buildWorkflowRunPlan(workflow, options);
22978
23410
  if (options.dryRun)
22979
23411
  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 };
23412
+ if (workflow.execution.target === "sandbox") {
23413
+ const sandboxResult = await runViaSandbox(plan, dependencies);
23414
+ return { run: null, results: [], plan, sandboxResult };
22983
23415
  }
22984
- const { run, results } = await runByFilter(plan.runOptions);
23416
+ const runLocal = dependencies.runByFilter ?? runByFilter;
23417
+ const { run, results } = await runLocal(plan.runOptions);
22985
23418
  return { run, results, plan };
22986
23419
  }
23420
+ function createWorkflowDatabaseBundle(workflow, plan) {
23421
+ if (!plan.sandbox)
23422
+ throw new Error(`Workflow is not configured for sandbox execution: ${workflow.name}`);
23423
+ const localDir = mkdtempSync(join14(tmpdir(), `testers-workflow-${workflow.id.slice(0, 8)}-`));
23424
+ writeFileSync3(join14(localDir, "testers.db"), getDatabase().serialize());
23425
+ return {
23426
+ localDir,
23427
+ remoteDir: plan.sandbox.stateRemoteDir,
23428
+ cleanup: () => rmSync(localDir, { recursive: true, force: true })
23429
+ };
23430
+ }
22987
23431
  function validatePersonaIds(workflow) {
22988
23432
  for (const personaId of workflow.personaIds) {
22989
23433
  if (!getPersona(personaId)) {
@@ -22991,48 +23435,112 @@ function validatePersonaIds(workflow) {
22991
23435
  }
22992
23436
  }
22993
23437
  }
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,
23438
+ function buildSandboxPlan(workflow, execution, runOptions) {
23439
+ const remoteDir = execution.sandboxRemoteDir ?? `/tmp/testers-workflow-${workflow.id.slice(0, 8)}`;
23440
+ const stateRemoteDir = `${remoteDir.replace(/\/+$/, "")}/.testers-state`;
23441
+ return {
23442
+ provider: execution.provider,
23443
+ image: execution.sandboxImage,
23444
+ name: `testers-${workflow.id.slice(0, 8)}`,
23445
+ remoteDir,
23446
+ stateRemoteDir,
23447
+ cleanup: execution.sandboxCleanup ?? "delete",
23000
23448
  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];
23449
+ env: execution.env,
23450
+ command: buildSandboxCommand({
23451
+ runOptions,
23452
+ remoteDir,
23453
+ dbPath: `${stateRemoteDir}/testers.db`,
23454
+ setupCommand: execution.setupCommand,
23455
+ packageSpec: execution.packageSpec ?? "@hasna/testers"
23456
+ })
23457
+ };
23016
23458
  }
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}`);
23459
+ function buildSandboxCommand(input) {
23460
+ const args = [
23461
+ "bunx",
23462
+ input.packageSpec,
23463
+ "run",
23464
+ input.runOptions.url,
23465
+ ...input.runOptions.scenarioIds?.length ? ["--scenario", input.runOptions.scenarioIds.join(",")] : [],
23466
+ ...input.runOptions.tags?.length ? input.runOptions.tags.flatMap((tag) => ["--tag", tag]) : [],
23467
+ ...input.runOptions.priority ? ["--priority", input.runOptions.priority] : [],
23468
+ ...input.runOptions.projectId ? ["--project", input.runOptions.projectId] : [],
23469
+ ...input.runOptions.model ? ["--model", input.runOptions.model] : [],
23470
+ ...input.runOptions.headed ? ["--headed"] : [],
23471
+ ...input.runOptions.parallel ? ["--parallel", String(input.runOptions.parallel)] : [],
23472
+ ...input.runOptions.timeout ? ["--timeout", String(input.runOptions.timeout)] : [],
23473
+ ...input.runOptions.personaIds?.length ? ["--persona", input.runOptions.personaIds.join(",")] : [],
23474
+ "--no-auto-generate",
23475
+ "--json"
23476
+ ];
23477
+ return [
23478
+ "set -euo pipefail",
23479
+ `mkdir -p ${shellQuote(input.remoteDir)}`,
23480
+ `cd ${shellQuote(input.remoteDir)}`,
23481
+ input.setupCommand,
23482
+ `HASNA_TESTERS_DB_PATH=${shellQuote(input.dbPath)} ${args.map(shellQuote).join(" ")}`
23483
+ ].filter(Boolean).join(`
23484
+ `);
23485
+ }
23486
+ async function runViaSandbox(plan, dependencies) {
23487
+ if (!plan.sandbox)
23488
+ throw new Error("Workflow does not have a sandbox plan");
23489
+ const sandboxes = await resolveSandboxesRuntime(dependencies);
23490
+ const createBundle = dependencies.createDatabaseBundle ?? createWorkflowDatabaseBundle;
23491
+ const bundle = createBundle(plan.workflow, plan);
23492
+ try {
23493
+ const raw = await sandboxes.runCommandInSandbox({
23494
+ command: plan.sandbox.command,
23495
+ provider: plan.sandbox.provider,
23496
+ name: plan.sandbox.name,
23497
+ image: plan.sandbox.image,
23498
+ sandboxTimeout: plan.sandbox.timeoutMs,
23499
+ commandTimeoutMs: plan.sandbox.timeoutMs,
23500
+ projectId: plan.workflow.projectId ?? undefined,
23501
+ config: {
23502
+ source: "testers",
23503
+ workflowId: plan.workflow.id,
23504
+ workflowName: plan.workflow.name
23505
+ },
23506
+ sandboxEnvVars: plan.sandbox.env,
23507
+ cleanup: plan.sandbox.cleanup,
23508
+ upload: {
23509
+ localDir: bundle.localDir,
23510
+ remoteDir: bundle.remoteDir
23511
+ }
23512
+ });
23513
+ const exitCode = raw.result.exit_code ?? raw.result.exitCode ?? 0;
23514
+ const stdout = raw.result.stdout ?? "";
23515
+ const stderr = raw.result.stderr ?? "";
23516
+ if (exitCode !== 0) {
23517
+ throw new Error(`Sandbox workflow execution failed (${exitCode}): ${stderr || stdout}`);
23518
+ }
23519
+ return {
23520
+ sandboxId: raw.sandbox.id,
23521
+ sessionId: raw.session.id,
23522
+ exitCode,
23523
+ stdout,
23524
+ stderr,
23525
+ cleanup: raw.cleanup
23526
+ };
23527
+ } finally {
23528
+ bundle.cleanup?.();
23032
23529
  }
23033
- return stdout.trim();
23530
+ }
23531
+ async function resolveSandboxesRuntime(dependencies) {
23532
+ if (dependencies.sandboxes)
23533
+ return dependencies.sandboxes;
23534
+ if (dependencies.createSandboxesSDK)
23535
+ return dependencies.createSandboxesSDK();
23536
+ const mod = await import("@hasna/sandboxes");
23537
+ return mod.createSandboxesSDK();
23538
+ }
23539
+ function shellQuote(value) {
23540
+ return `'${value.replaceAll("'", `'"'"'`)}'`;
23034
23541
  }
23035
23542
  var init_workflow_runner = __esm(() => {
23543
+ init_database();
23036
23544
  init_workflows();
23037
23545
  init_personas();
23038
23546
  init_runner();
@@ -34705,34 +35213,27 @@ var init_v3 = __esm(() => {
34705
35213
 
34706
35214
  // node_modules/@ai-sdk/provider-utils/node_modules/eventsource-parser/dist/index.js
34707
35215
  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;
35216
+ function createParser(callbacks) {
35217
+ if (typeof callbacks == "function")
35218
+ throw new TypeError("`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?");
35219
+ const { onEvent = noop, onError = noop, onRetry = noop, onComment } = callbacks, pendingFragments = [];
35220
+ let isFirstChunk = true, id, data = "", dataLines = 0, eventType;
34713
35221
  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
35222
  if (isFirstChunk && (isFirstChunk = false, chunk.charCodeAt(0) === 239 && chunk.charCodeAt(1) === 187 && chunk.charCodeAt(2) === 191 && (chunk = chunk.slice(3))), pendingFragments.length === 0) {
34717
35223
  const trailing2 = processLines(chunk);
34718
- trailing2 !== "" && (pendingFragments.push(trailing2), pendingFragmentsLength = trailing2.length), checkBufferSize();
35224
+ trailing2 !== "" && pendingFragments.push(trailing2);
34719
35225
  return;
34720
35226
  }
34721
35227
  if (chunk.indexOf(`
34722
35228
  `) === -1 && chunk.indexOf("\r") === -1) {
34723
- pendingFragments.push(chunk), pendingFragmentsLength += chunk.length, checkBufferSize();
35229
+ pendingFragments.push(chunk);
34724
35230
  return;
34725
35231
  }
34726
35232
  pendingFragments.push(chunk);
34727
35233
  const input = pendingFragments.join("");
34728
- pendingFragments.length = 0, pendingFragmentsLength = 0;
35234
+ pendingFragments.length = 0;
34729
35235
  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
- }))));
35236
+ trailing !== "" && pendingFragments.push(trailing);
34736
35237
  }
34737
35238
  function processLines(chunk) {
34738
35239
  let searchIndex = 0;
@@ -34844,7 +35345,7 @@ ${value}`, dataLines++;
34844
35345
  const incompleteLine = pendingFragments.join("");
34845
35346
  parseLine(incompleteLine, 0, incompleteLine.length);
34846
35347
  }
34847
- isFirstChunk = true, id = undefined, data = "", dataLines = 0, eventType = undefined, pendingFragments.length = 0, pendingFragmentsLength = 0, terminated = false;
35348
+ isFirstChunk = true, id = undefined, data = "", dataLines = 0, eventType = undefined, pendingFragments.length = 0;
34848
35349
  }
34849
35350
  return { feed, reset };
34850
35351
  }
@@ -34868,7 +35369,7 @@ var EventSourceParserStream;
34868
35369
  var init_stream = __esm(() => {
34869
35370
  init_dist3();
34870
35371
  EventSourceParserStream = class EventSourceParserStream extends TransformStream {
34871
- constructor({ onError, onRetry, onComment, maxBufferSize } = {}) {
35372
+ constructor({ onError, onRetry, onComment } = {}) {
34872
35373
  let parser;
34873
35374
  super({
34874
35375
  start(controller) {
@@ -34877,11 +35378,10 @@ var init_stream = __esm(() => {
34877
35378
  controller.enqueue(event);
34878
35379
  },
34879
35380
  onError(error40) {
34880
- typeof onError == "function" && onError(error40), (onError === "terminate" || error40.type === "max-buffer-size-exceeded") && controller.error(error40);
35381
+ onError === "terminate" ? controller.error(error40) : typeof onError == "function" && onError(error40);
34881
35382
  },
34882
35383
  onRetry,
34883
- onComment,
34884
- maxBufferSize
35384
+ onComment
34885
35385
  });
34886
35386
  },
34887
35387
  transform(chunk) {
@@ -36320,7 +36820,7 @@ var DelayedPromise = class {
36320
36820
  });
36321
36821
  }
36322
36822
  return () => `${prefix}${separator}${generator()}`;
36323
- }, generateId, FETCH_FAILED_ERROR_MESSAGES, BUN_ERROR_CODES, VERSION = "4.0.27", getOriginalFetch = () => globalThis.fetch, getFromApi = async ({
36823
+ }, generateId, FETCH_FAILED_ERROR_MESSAGES, BUN_ERROR_CODES, VERSION = "4.0.26", getOriginalFetch = () => globalThis.fetch, getFromApi = async ({
36324
36824
  url: url2,
36325
36825
  headers = {},
36326
36826
  successfulResponseHandler,
@@ -38459,7 +38959,7 @@ var import_oidc, import_oidc2, marker17 = "vercel.ai.gateway.error", symbol18, _
38459
38959
  "ai-model-id": this.modelId
38460
38960
  };
38461
38961
  }
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;
38962
+ }, 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
38963
  var init_dist5 = __esm(() => {
38464
38964
  init_dist4();
38465
38965
  init_dist2();
@@ -38498,15 +38998,13 @@ var init_dist5 = __esm(() => {
38498
38998
  message,
38499
38999
  statusCode = 500,
38500
39000
  cause,
38501
- generationId,
38502
- isRetryable = statusCode != null && (statusCode === 408 || statusCode === 409 || statusCode === 429 || statusCode >= 500)
39001
+ generationId
38503
39002
  }) {
38504
39003
  super(generationId ? `${message} [${generationId}]` : message);
38505
39004
  this[_a17] = true;
38506
39005
  this.statusCode = statusCode;
38507
39006
  this.cause = cause;
38508
39007
  this.generationId = generationId;
38509
- this.isRetryable = isRetryable;
38510
39008
  }
38511
39009
  static isInstance(error40) {
38512
39010
  return _GatewayError.hasMarker(error40);
@@ -39029,11 +39527,62 @@ Run 'npx vercel link' to link your project, then 'vc env pull' to fetch the toke
39029
39527
  gateway = createGatewayProvider();
39030
39528
  });
39031
39529
 
39530
+ // node_modules/@opentelemetry/api/build/src/platform/node/globalThis.js
39531
+ var require_globalThis = __commonJS((exports) => {
39532
+ Object.defineProperty(exports, "__esModule", { value: true });
39533
+ exports._globalThis = undefined;
39534
+ exports._globalThis = typeof globalThis === "object" ? globalThis : global;
39535
+ });
39536
+
39537
+ // node_modules/@opentelemetry/api/build/src/platform/node/index.js
39538
+ var require_node = __commonJS((exports) => {
39539
+ var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
39540
+ if (k2 === undefined)
39541
+ k2 = k;
39542
+ Object.defineProperty(o, k2, { enumerable: true, get: function() {
39543
+ return m[k];
39544
+ } });
39545
+ } : function(o, m, k, k2) {
39546
+ if (k2 === undefined)
39547
+ k2 = k;
39548
+ o[k2] = m[k];
39549
+ });
39550
+ var __exportStar = exports && exports.__exportStar || function(m, exports2) {
39551
+ for (var p in m)
39552
+ if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p))
39553
+ __createBinding(exports2, m, p);
39554
+ };
39555
+ Object.defineProperty(exports, "__esModule", { value: true });
39556
+ __exportStar(require_globalThis(), exports);
39557
+ });
39558
+
39559
+ // node_modules/@opentelemetry/api/build/src/platform/index.js
39560
+ var require_platform = __commonJS((exports) => {
39561
+ var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
39562
+ if (k2 === undefined)
39563
+ k2 = k;
39564
+ Object.defineProperty(o, k2, { enumerable: true, get: function() {
39565
+ return m[k];
39566
+ } });
39567
+ } : function(o, m, k, k2) {
39568
+ if (k2 === undefined)
39569
+ k2 = k;
39570
+ o[k2] = m[k];
39571
+ });
39572
+ var __exportStar = exports && exports.__exportStar || function(m, exports2) {
39573
+ for (var p in m)
39574
+ if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p))
39575
+ __createBinding(exports2, m, p);
39576
+ };
39577
+ Object.defineProperty(exports, "__esModule", { value: true });
39578
+ __exportStar(require_node(), exports);
39579
+ });
39580
+
39032
39581
  // node_modules/@opentelemetry/api/build/src/version.js
39033
39582
  var require_version = __commonJS((exports) => {
39034
39583
  Object.defineProperty(exports, "__esModule", { value: true });
39035
39584
  exports.VERSION = undefined;
39036
- exports.VERSION = "1.9.1";
39585
+ exports.VERSION = "1.9.0";
39037
39586
  });
39038
39587
 
39039
39588
  // node_modules/@opentelemetry/api/build/src/internal/semver.js
@@ -39111,11 +39660,12 @@ var require_semver = __commonJS((exports) => {
39111
39660
  var require_global_utils = __commonJS((exports) => {
39112
39661
  Object.defineProperty(exports, "__esModule", { value: true });
39113
39662
  exports.unregisterGlobal = exports.getGlobal = exports.registerGlobal = undefined;
39663
+ var platform_1 = require_platform();
39114
39664
  var version_1 = require_version();
39115
39665
  var semver_1 = require_semver();
39116
39666
  var major = version_1.VERSION.split(".")[0];
39117
39667
  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 : {};
39668
+ var _global = platform_1._globalThis;
39119
39669
  function registerGlobal(type, instance, diag, allowOverride = false) {
39120
39670
  var _a16;
39121
39671
  const api2 = _global[GLOBAL_OPENTELEMETRY_API_KEY] = (_a16 = _global[GLOBAL_OPENTELEMETRY_API_KEY]) !== null && _a16 !== undefined ? _a16 : {
@@ -39187,7 +39737,8 @@ var require_ComponentLogger = __commonJS((exports) => {
39187
39737
  if (!logger) {
39188
39738
  return;
39189
39739
  }
39190
- return logger[funcName](namespace, ...args);
39740
+ args.unshift(namespace);
39741
+ return logger[funcName](...args);
39191
39742
  }
39192
39743
  });
39193
39744
 
@@ -39248,12 +39799,6 @@ var require_diag = __commonJS((exports) => {
39248
39799
  var API_NAME = "diag";
39249
39800
 
39250
39801
  class DiagAPI {
39251
- static instance() {
39252
- if (!this._instance) {
39253
- this._instance = new DiagAPI;
39254
- }
39255
- return this._instance;
39256
- }
39257
39802
  constructor() {
39258
39803
  function _logProxy(funcName) {
39259
39804
  return function(...args) {
@@ -39298,6 +39843,12 @@ var require_diag = __commonJS((exports) => {
39298
39843
  self2.warn = _logProxy("warn");
39299
39844
  self2.error = _logProxy("error");
39300
39845
  }
39846
+ static instance() {
39847
+ if (!this._instance) {
39848
+ this._instance = new DiagAPI;
39849
+ }
39850
+ return this._instance;
39851
+ }
39301
39852
  }
39302
39853
  exports.DiagAPI = DiagAPI;
39303
39854
  });
@@ -39319,7 +39870,7 @@ var require_baggage_impl = __commonJS((exports) => {
39319
39870
  return Object.assign({}, entry);
39320
39871
  }
39321
39872
  getAllEntries() {
39322
- return Array.from(this._entries.entries());
39873
+ return Array.from(this._entries.entries()).map(([k, v]) => [k, v]);
39323
39874
  }
39324
39875
  setEntry(key, entry) {
39325
39876
  const newBaggage = new BaggageImpl(this._entries);
@@ -39411,7 +39962,7 @@ var require_context = __commonJS((exports) => {
39411
39962
  // node_modules/@opentelemetry/api/build/src/diag/consoleLogger.js
39412
39963
  var require_consoleLogger = __commonJS((exports) => {
39413
39964
  Object.defineProperty(exports, "__esModule", { value: true });
39414
- exports.DiagConsoleLogger = exports._originalConsoleMethods = undefined;
39965
+ exports.DiagConsoleLogger = undefined;
39415
39966
  var consoleMap = [
39416
39967
  { n: "error", c: "error" },
39417
39968
  { n: "warn", c: "warn" },
@@ -39419,39 +39970,19 @@ var require_consoleLogger = __commonJS((exports) => {
39419
39970
  { n: "debug", c: "debug" },
39420
39971
  { n: "verbose", c: "trace" }
39421
39972
  ];
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
39973
 
39439
39974
  class DiagConsoleLogger {
39440
39975
  constructor() {
39441
39976
  function _consoleFunc(funcName) {
39442
39977
  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];
39978
+ if (console) {
39979
+ let theFunc = console[funcName];
39449
39980
  if (typeof theFunc !== "function") {
39450
39981
  theFunc = console.log;
39451
39982
  }
39452
- }
39453
- if (typeof theFunc === "function") {
39454
- return theFunc.apply(console, args);
39983
+ if (typeof theFunc === "function") {
39984
+ return theFunc.apply(console, args);
39985
+ }
39455
39986
  }
39456
39987
  };
39457
39988
  }
@@ -39689,8 +40220,8 @@ var require_NonRecordingSpan = __commonJS((exports) => {
39689
40220
  var invalid_span_constants_1 = require_invalid_span_constants();
39690
40221
 
39691
40222
  class NonRecordingSpan {
39692
- constructor(spanContext = invalid_span_constants_1.INVALID_SPAN_CONTEXT) {
39693
- this._spanContext = spanContext;
40223
+ constructor(_spanContext = invalid_span_constants_1.INVALID_SPAN_CONTEXT) {
40224
+ this._spanContext = _spanContext;
39694
40225
  }
39695
40226
  spanContext() {
39696
40227
  return this._spanContext;
@@ -39766,126 +40297,14 @@ var require_spancontext_utils = __commonJS((exports) => {
39766
40297
  exports.wrapSpanContext = exports.isSpanContextValid = exports.isValidSpanId = exports.isValidTraceId = undefined;
39767
40298
  var invalid_span_constants_1 = require_invalid_span_constants();
39768
40299
  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
- }
40300
+ var VALID_TRACEID_REGEX = /^([0-9a-f]{32})$/i;
40301
+ var VALID_SPANID_REGEX = /^[0-9a-f]{16}$/i;
39883
40302
  function isValidTraceId(traceId) {
39884
- return isValidHex(traceId, 32) && traceId !== invalid_span_constants_1.INVALID_TRACEID;
40303
+ return VALID_TRACEID_REGEX.test(traceId) && traceId !== invalid_span_constants_1.INVALID_TRACEID;
39885
40304
  }
39886
40305
  exports.isValidTraceId = isValidTraceId;
39887
40306
  function isValidSpanId(spanId) {
39888
- return isValidHex(spanId, 16) && spanId !== invalid_span_constants_1.INVALID_SPANID;
40307
+ return VALID_SPANID_REGEX.test(spanId) && spanId !== invalid_span_constants_1.INVALID_SPANID;
39889
40308
  }
39890
40309
  exports.isValidSpanId = isValidSpanId;
39891
40310
  function isSpanContextValid(spanContext) {
@@ -39945,7 +40364,7 @@ var require_NoopTracer = __commonJS((exports) => {
39945
40364
  }
39946
40365
  exports.NoopTracer = NoopTracer;
39947
40366
  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";
40367
+ return typeof spanContext === "object" && typeof spanContext["spanId"] === "string" && typeof spanContext["traceId"] === "string" && typeof spanContext["traceFlags"] === "number";
39949
40368
  }
39950
40369
  });
39951
40370
 
@@ -39957,8 +40376,8 @@ var require_ProxyTracer = __commonJS((exports) => {
39957
40376
  var NOOP_TRACER = new NoopTracer_1.NoopTracer;
39958
40377
 
39959
40378
  class ProxyTracer {
39960
- constructor(provider, name15, version2, options) {
39961
- this._provider = provider;
40379
+ constructor(_provider, name15, version2, options) {
40380
+ this._provider = _provider;
39962
40381
  this.name = name15;
39963
40382
  this.version = version2;
39964
40383
  this.options = options;
@@ -40118,7 +40537,7 @@ var require_tracestate_impl = __commonJS((exports) => {
40118
40537
  return this._internalState.get(key);
40119
40538
  }
40120
40539
  serialize() {
40121
- return Array.from(this._internalState.keys()).reduceRight((agg, key) => {
40540
+ return this._keys().reduce((agg, key) => {
40122
40541
  agg.push(key + LIST_MEMBER_KEY_VALUE_SPLITTER + this.get(key));
40123
40542
  return agg;
40124
40543
  }, []).join(LIST_MEMBERS_SEPARATOR);
@@ -40126,7 +40545,7 @@ var require_tracestate_impl = __commonJS((exports) => {
40126
40545
  _parse(rawTraceState) {
40127
40546
  if (rawTraceState.length > MAX_TRACE_STATE_LEN)
40128
40547
  return;
40129
- this._internalState = rawTraceState.split(LIST_MEMBERS_SEPARATOR).reduceRight((agg, part) => {
40548
+ this._internalState = rawTraceState.split(LIST_MEMBERS_SEPARATOR).reverse().reduce((agg, part) => {
40130
40549
  const listMember = part.trim();
40131
40550
  const i = listMember.indexOf(LIST_MEMBER_KEY_VALUE_SPLITTER);
40132
40551
  if (i !== -1) {
@@ -41226,10 +41645,7 @@ function convertToLanguageModelMessage({
41226
41645
  type: "tool-result",
41227
41646
  toolCallId: part.toolCallId,
41228
41647
  toolName: part.toolName,
41229
- output: mapToolResultOutput({
41230
- output: part.output,
41231
- downloadedAssets
41232
- }),
41648
+ output: mapToolResultOutput(part.output),
41233
41649
  providerOptions
41234
41650
  };
41235
41651
  }
@@ -41248,10 +41664,7 @@ function convertToLanguageModelMessage({
41248
41664
  type: "tool-result",
41249
41665
  toolCallId: part.toolCallId,
41250
41666
  toolName: part.toolName,
41251
- output: mapToolResultOutput({
41252
- output: part.output,
41253
- downloadedAssets
41254
- }),
41667
+ output: mapToolResultOutput(part.output),
41255
41668
  providerOptions: part.providerOptions
41256
41669
  };
41257
41670
  }
@@ -41275,44 +41688,15 @@ function convertToLanguageModelMessage({
41275
41688
  }
41276
41689
  }
41277
41690
  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
- }
41691
+ 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) => {
41692
+ var _a21;
41693
+ const mediaType = (_a21 = part.mediaType) != null ? _a21 : part.type === "image" ? "image/*" : undefined;
41694
+ let data = part.type === "image" ? part.image : part.data;
41695
+ if (typeof data === "string") {
41696
+ try {
41697
+ data = new URL(data);
41698
+ } catch (ignored) {}
41311
41699
  }
41312
- }
41313
- const plannedDownloads = downloadableFiles.map((part) => {
41314
- const mediaType = part.mediaType;
41315
- const { data } = convertToLanguageModelV3DataContent(part.data);
41316
41700
  return { mediaType, data };
41317
41701
  }).filter((part) => part.data instanceof URL).map((part) => ({
41318
41702
  url: part.data,
@@ -41386,41 +41770,13 @@ function convertPartToLanguageModelPart(part, downloadedAssets) {
41386
41770
  }
41387
41771
  }
41388
41772
  }
41389
- function mapToolResultOutput({
41390
- output,
41391
- downloadedAssets
41392
- }) {
41773
+ function mapToolResultOutput(output) {
41393
41774
  if (output.type !== "content") {
41394
41775
  return output;
41395
41776
  }
41396
41777
  return {
41397
41778
  type: "content",
41398
41779
  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
41780
  if (item.type !== "media") {
41425
41781
  return item;
41426
41782
  }
@@ -41973,7 +42329,7 @@ function getRetryDelayInMs({
41973
42329
  error: error40,
41974
42330
  exponentialBackoffDelay
41975
42331
  }) {
41976
- const headers = APICallError.isInstance(error40) ? error40.responseHeaders : APICallError.isInstance(error40.cause) ? error40.cause.responseHeaders : undefined;
42332
+ const headers = error40.responseHeaders;
41977
42333
  if (!headers)
41978
42334
  return exponentialBackoffDelay;
41979
42335
  let ms;
@@ -42023,7 +42379,7 @@ async function _retryWithExponentialBackoff(f, {
42023
42379
  errors: newErrors
42024
42380
  });
42025
42381
  }
42026
- if (error40 instanceof Error && (APICallError.isInstance(error40) && error40.isRetryable === true || GatewayError.isInstance(error40) && error40.isRetryable === true) && tryNumber <= maxRetries) {
42382
+ if (error40 instanceof Error && APICallError.isInstance(error40) && error40.isRetryable === true && tryNumber <= maxRetries) {
42027
42383
  await delay(getRetryDelayInMs({
42028
42384
  error: error40,
42029
42385
  exponentialBackoffDelay: delayInMs
@@ -42241,8 +42597,7 @@ async function executeToolCall({
42241
42597
  input,
42242
42598
  error: error40,
42243
42599
  dynamic: tool2.type === "dynamic",
42244
- ...toolCall.providerMetadata != null ? { providerMetadata: toolCall.providerMetadata } : {},
42245
- ...toolCall.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
42600
+ ...toolCall.providerMetadata != null ? { providerMetadata: toolCall.providerMetadata } : {}
42246
42601
  };
42247
42602
  }
42248
42603
  const durationMs = now2() - startTime;
@@ -42272,8 +42627,7 @@ async function executeToolCall({
42272
42627
  input,
42273
42628
  output,
42274
42629
  dynamic: tool2.type === "dynamic",
42275
- ...toolCall.providerMetadata != null ? { providerMetadata: toolCall.providerMetadata } : {},
42276
- ...toolCall.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
42630
+ ...toolCall.providerMetadata != null ? { providerMetadata: toolCall.providerMetadata } : {}
42277
42631
  };
42278
42632
  }
42279
42633
  });
@@ -42638,6 +42992,15 @@ async function parsePartialJson(jsonText) {
42638
42992
  }
42639
42993
  return { value: undefined, state: "failed-parse" };
42640
42994
  }
42995
+ function mergeToolProviderMetadata(toolMetadata, callMetadata) {
42996
+ if (toolMetadata == null) {
42997
+ return callMetadata;
42998
+ }
42999
+ if (callMetadata == null) {
43000
+ return toolMetadata;
43001
+ }
43002
+ return { ...toolMetadata, ...callMetadata };
43003
+ }
42641
43004
  async function parseToolCall({
42642
43005
  toolCall,
42643
43006
  tools,
@@ -42645,6 +43008,7 @@ async function parseToolCall({
42645
43008
  system,
42646
43009
  messages
42647
43010
  }) {
43011
+ var _a21, _b16;
42648
43012
  try {
42649
43013
  if (tools == null) {
42650
43014
  if (toolCall.providerExecuted && toolCall.dynamic) {
@@ -42685,7 +43049,6 @@ async function parseToolCall({
42685
43049
  } catch (error40) {
42686
43050
  const parsedInput = await safeParseJSON({ text: toolCall.input });
42687
43051
  const input = parsedInput.success ? parsedInput.value : toolCall.input;
42688
- const tool2 = tools == null ? undefined : tools[toolCall.toolName];
42689
43052
  return {
42690
43053
  type: "tool-call",
42691
43054
  toolCallId: toolCall.toolCallId,
@@ -42694,10 +43057,9 @@ async function parseToolCall({
42694
43057
  dynamic: true,
42695
43058
  invalid: true,
42696
43059
  error: error40,
42697
- title: tool2 == null ? undefined : tool2.title,
43060
+ title: (_a21 = tools == null ? undefined : tools[toolCall.toolName]) == null ? undefined : _a21.title,
42698
43061
  providerExecuted: toolCall.providerExecuted,
42699
- providerMetadata: toolCall.providerMetadata,
42700
- ...(tool2 == null ? undefined : tool2.metadata) != null ? { toolMetadata: tool2.metadata } : {}
43062
+ providerMetadata: mergeToolProviderMetadata((_b16 = tools == null ? undefined : tools[toolCall.toolName]) == null ? undefined : _b16.providerMetadata, toolCall.providerMetadata)
42701
43063
  };
42702
43064
  }
42703
43065
  }
@@ -42744,14 +43106,14 @@ async function doParseToolCall({
42744
43106
  cause: parseResult.error
42745
43107
  });
42746
43108
  }
43109
+ const mergedProviderMetadata = mergeToolProviderMetadata(tool2.providerMetadata, toolCall.providerMetadata);
42747
43110
  return tool2.type === "dynamic" ? {
42748
43111
  type: "tool-call",
42749
43112
  toolCallId: toolCall.toolCallId,
42750
43113
  toolName: toolCall.toolName,
42751
43114
  input: parseResult.value,
42752
43115
  providerExecuted: toolCall.providerExecuted,
42753
- providerMetadata: toolCall.providerMetadata,
42754
- ...tool2.metadata != null ? { toolMetadata: tool2.metadata } : {},
43116
+ providerMetadata: mergedProviderMetadata,
42755
43117
  dynamic: true,
42756
43118
  title: tool2.title
42757
43119
  } : {
@@ -42760,8 +43122,7 @@ async function doParseToolCall({
42760
43122
  toolName,
42761
43123
  input: parseResult.value,
42762
43124
  providerExecuted: toolCall.providerExecuted,
42763
- providerMetadata: toolCall.providerMetadata,
42764
- ...tool2.metadata != null ? { toolMetadata: tool2.metadata } : {},
43125
+ providerMetadata: mergedProviderMetadata,
42765
43126
  title: tool2.title
42766
43127
  };
42767
43128
  }
@@ -43593,8 +43954,7 @@ function asContent({
43593
43954
  error: part.result,
43594
43955
  providerExecuted: true,
43595
43956
  dynamic: part.dynamic,
43596
- ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
43597
- ...(tool2 == null ? undefined : tool2.metadata) != null ? { toolMetadata: tool2.metadata } : {}
43957
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
43598
43958
  });
43599
43959
  } else {
43600
43960
  contentParts.push({
@@ -43605,8 +43965,7 @@ function asContent({
43605
43965
  output: part.result,
43606
43966
  providerExecuted: true,
43607
43967
  dynamic: part.dynamic,
43608
- ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
43609
- ...(tool2 == null ? undefined : tool2.metadata) != null ? { toolMetadata: tool2.metadata } : {}
43968
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
43610
43969
  });
43611
43970
  }
43612
43971
  break;
@@ -43620,8 +43979,7 @@ function asContent({
43620
43979
  error: part.result,
43621
43980
  providerExecuted: true,
43622
43981
  dynamic: toolCall.dynamic,
43623
- ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
43624
- ...toolCall.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
43982
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
43625
43983
  });
43626
43984
  } else {
43627
43985
  contentParts.push({
@@ -43632,8 +43990,7 @@ function asContent({
43632
43990
  output: part.result,
43633
43991
  providerExecuted: true,
43634
43992
  dynamic: toolCall.dynamic,
43635
- ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
43636
- ...toolCall.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
43993
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
43637
43994
  });
43638
43995
  }
43639
43996
  break;
@@ -43847,9 +44204,6 @@ function processUIMessageStream({
43847
44204
  if (options.title !== undefined) {
43848
44205
  anyPart.title = options.title;
43849
44206
  }
43850
- if (options.toolMetadata !== undefined) {
43851
- anyPart.toolMetadata = options.toolMetadata;
43852
- }
43853
44207
  anyPart.providerExecuted = (_a222 = anyOptions.providerExecuted) != null ? _a222 : part.providerExecuted;
43854
44208
  const providerMetadata = anyOptions.providerMetadata;
43855
44209
  if (providerMetadata != null) {
@@ -43866,7 +44220,6 @@ function processUIMessageStream({
43866
44220
  toolCallId: options.toolCallId,
43867
44221
  state: options.state,
43868
44222
  title: options.title,
43869
- ...options.toolMetadata !== undefined ? { toolMetadata: options.toolMetadata } : {},
43870
44223
  input: anyOptions.input,
43871
44224
  output: anyOptions.output,
43872
44225
  rawInput: anyOptions.rawInput,
@@ -43894,9 +44247,6 @@ function processUIMessageStream({
43894
44247
  if (options.title !== undefined) {
43895
44248
  anyPart.title = options.title;
43896
44249
  }
43897
- if (options.toolMetadata !== undefined) {
43898
- anyPart.toolMetadata = options.toolMetadata;
43899
- }
43900
44250
  anyPart.providerExecuted = (_b23 = anyOptions.providerExecuted) != null ? _b23 : part.providerExecuted;
43901
44251
  const providerMetadata = anyOptions.providerMetadata;
43902
44252
  if (providerMetadata != null) {
@@ -43919,7 +44269,6 @@ function processUIMessageStream({
43919
44269
  preliminary: anyOptions.preliminary,
43920
44270
  providerExecuted: anyOptions.providerExecuted,
43921
44271
  title: options.title,
43922
- ...options.toolMetadata !== undefined ? { toolMetadata: options.toolMetadata } : {},
43923
44272
  ...anyOptions.providerMetadata != null && (options.state === "output-available" || options.state === "output-error") ? { resultProviderMetadata: anyOptions.providerMetadata } : {},
43924
44273
  ...anyOptions.providerMetadata != null && !(options.state === "output-available" || options.state === "output-error") ? { callProviderMetadata: anyOptions.providerMetadata } : {}
43925
44274
  });
@@ -44064,8 +44413,7 @@ function processUIMessageStream({
44064
44413
  toolName: chunk.toolName,
44065
44414
  index: toolInvocations.length,
44066
44415
  dynamic: chunk.dynamic,
44067
- title: chunk.title,
44068
- toolMetadata: chunk.toolMetadata
44416
+ title: chunk.title
44069
44417
  };
44070
44418
  if (chunk.dynamic) {
44071
44419
  updateDynamicToolPart({
@@ -44075,7 +44423,6 @@ function processUIMessageStream({
44075
44423
  input: undefined,
44076
44424
  providerExecuted: chunk.providerExecuted,
44077
44425
  title: chunk.title,
44078
- toolMetadata: chunk.toolMetadata,
44079
44426
  providerMetadata: chunk.providerMetadata
44080
44427
  });
44081
44428
  } else {
@@ -44086,7 +44433,6 @@ function processUIMessageStream({
44086
44433
  input: undefined,
44087
44434
  providerExecuted: chunk.providerExecuted,
44088
44435
  title: chunk.title,
44089
- toolMetadata: chunk.toolMetadata,
44090
44436
  providerMetadata: chunk.providerMetadata
44091
44437
  });
44092
44438
  }
@@ -44110,8 +44456,7 @@ function processUIMessageStream({
44110
44456
  toolName: partialToolCall.toolName,
44111
44457
  state: "input-streaming",
44112
44458
  input: partialArgs,
44113
- title: partialToolCall.title,
44114
- toolMetadata: partialToolCall.toolMetadata
44459
+ title: partialToolCall.title
44115
44460
  });
44116
44461
  } else {
44117
44462
  updateToolPart({
@@ -44119,8 +44464,7 @@ function processUIMessageStream({
44119
44464
  toolName: partialToolCall.toolName,
44120
44465
  state: "input-streaming",
44121
44466
  input: partialArgs,
44122
- title: partialToolCall.title,
44123
- toolMetadata: partialToolCall.toolMetadata
44467
+ title: partialToolCall.title
44124
44468
  });
44125
44469
  }
44126
44470
  write();
@@ -44135,8 +44479,7 @@ function processUIMessageStream({
44135
44479
  input: chunk.input,
44136
44480
  providerExecuted: chunk.providerExecuted,
44137
44481
  providerMetadata: chunk.providerMetadata,
44138
- title: chunk.title,
44139
- toolMetadata: chunk.toolMetadata
44482
+ title: chunk.title
44140
44483
  });
44141
44484
  } else {
44142
44485
  updateToolPart({
@@ -44146,8 +44489,7 @@ function processUIMessageStream({
44146
44489
  input: chunk.input,
44147
44490
  providerExecuted: chunk.providerExecuted,
44148
44491
  providerMetadata: chunk.providerMetadata,
44149
- title: chunk.title,
44150
- toolMetadata: chunk.toolMetadata
44492
+ title: chunk.title
44151
44493
  });
44152
44494
  }
44153
44495
  write();
@@ -44169,8 +44511,7 @@ function processUIMessageStream({
44169
44511
  input: chunk.input,
44170
44512
  errorText: chunk.errorText,
44171
44513
  providerExecuted: chunk.providerExecuted,
44172
- providerMetadata: chunk.providerMetadata,
44173
- toolMetadata: chunk.toolMetadata
44514
+ providerMetadata: chunk.providerMetadata
44174
44515
  });
44175
44516
  } else {
44176
44517
  updateToolPart({
@@ -44181,8 +44522,7 @@ function processUIMessageStream({
44181
44522
  rawInput: chunk.input,
44182
44523
  errorText: chunk.errorText,
44183
44524
  providerExecuted: chunk.providerExecuted,
44184
- providerMetadata: chunk.providerMetadata,
44185
- toolMetadata: chunk.toolMetadata
44525
+ providerMetadata: chunk.providerMetadata
44186
44526
  });
44187
44527
  }
44188
44528
  write();
@@ -44213,8 +44553,7 @@ function processUIMessageStream({
44213
44553
  preliminary: chunk.preliminary,
44214
44554
  providerExecuted: chunk.providerExecuted,
44215
44555
  providerMetadata: chunk.providerMetadata,
44216
- title: toolInvocation.title,
44217
- toolMetadata: toolInvocation.toolMetadata
44556
+ title: toolInvocation.title
44218
44557
  });
44219
44558
  } else {
44220
44559
  updateToolPart({
@@ -44226,8 +44565,7 @@ function processUIMessageStream({
44226
44565
  providerExecuted: chunk.providerExecuted,
44227
44566
  preliminary: chunk.preliminary,
44228
44567
  providerMetadata: chunk.providerMetadata,
44229
- title: toolInvocation.title,
44230
- toolMetadata: toolInvocation.toolMetadata
44568
+ title: toolInvocation.title
44231
44569
  });
44232
44570
  }
44233
44571
  write();
@@ -44244,8 +44582,7 @@ function processUIMessageStream({
44244
44582
  errorText: chunk.errorText,
44245
44583
  providerExecuted: chunk.providerExecuted,
44246
44584
  providerMetadata: chunk.providerMetadata,
44247
- title: toolInvocation.title,
44248
- toolMetadata: toolInvocation.toolMetadata
44585
+ title: toolInvocation.title
44249
44586
  });
44250
44587
  } else {
44251
44588
  updateToolPart({
@@ -44257,8 +44594,7 @@ function processUIMessageStream({
44257
44594
  errorText: chunk.errorText,
44258
44595
  providerExecuted: chunk.providerExecuted,
44259
44596
  providerMetadata: chunk.providerMetadata,
44260
- title: toolInvocation.title,
44261
- toolMetadata: toolInvocation.toolMetadata
44597
+ title: toolInvocation.title
44262
44598
  });
44263
44599
  }
44264
44600
  write();
@@ -44716,8 +45052,7 @@ function runToolsTransformation({
44716
45052
  input: toolCall.input,
44717
45053
  error: getErrorMessage2(toolCall.error),
44718
45054
  dynamic: true,
44719
- title: toolCall.title,
44720
- ...toolCall.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
45055
+ title: toolCall.title
44721
45056
  });
44722
45057
  break;
44723
45058
  }
@@ -44785,7 +45120,6 @@ function runToolsTransformation({
44785
45120
  }
44786
45121
  case "tool-result": {
44787
45122
  const toolName = chunk.toolName;
44788
- const toolCall = toolCallsByToolCallId.get(chunk.toolCallId);
44789
45123
  if (chunk.isError) {
44790
45124
  toolResultsStreamController.enqueue({
44791
45125
  type: "tool-error",
@@ -44795,8 +45129,7 @@ function runToolsTransformation({
44795
45129
  providerExecuted: true,
44796
45130
  error: chunk.result,
44797
45131
  dynamic: chunk.dynamic,
44798
- ...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {},
44799
- ...(toolCall == null ? undefined : toolCall.toolMetadata) != null ? { toolMetadata: toolCall.toolMetadata } : {}
45132
+ ...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {}
44800
45133
  });
44801
45134
  } else {
44802
45135
  controller.enqueue({
@@ -44807,8 +45140,7 @@ function runToolsTransformation({
44807
45140
  output: chunk.result,
44808
45141
  providerExecuted: true,
44809
45142
  dynamic: chunk.dynamic,
44810
- ...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {},
44811
- ...(toolCall == null ? undefined : toolCall.toolMetadata) != null ? { toolMetadata: toolCall.toolMetadata } : {}
45143
+ ...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {}
44812
45144
  });
44813
45145
  }
44814
45146
  break;
@@ -45591,7 +45923,7 @@ async function embed({
45591
45923
  }),
45592
45924
  tracer,
45593
45925
  fn: async (doEmbedSpan) => {
45594
- var _a21, _b16;
45926
+ var _a21;
45595
45927
  const modelResponse = await model.doEmbed({
45596
45928
  values: [value],
45597
45929
  abortSignal,
@@ -45612,7 +45944,7 @@ async function embed({
45612
45944
  return {
45613
45945
  embedding: embedding2,
45614
45946
  usage: usage2,
45615
- warnings: (_b16 = modelResponse.warnings) != null ? _b16 : [],
45947
+ warnings: modelResponse.warnings,
45616
45948
  providerMetadata: modelResponse.providerMetadata,
45617
45949
  response: modelResponse.response
45618
45950
  };
@@ -45708,7 +46040,7 @@ async function embedMany({
45708
46040
  }),
45709
46041
  tracer,
45710
46042
  fn: async (doEmbedSpan) => {
45711
- var _a222, _b16;
46043
+ var _a222;
45712
46044
  const modelResponse = await model.doEmbed({
45713
46045
  values,
45714
46046
  abortSignal,
@@ -45729,7 +46061,7 @@ async function embedMany({
45729
46061
  return {
45730
46062
  embeddings: embeddings3,
45731
46063
  usage: usage2,
45732
- warnings: (_b16 = modelResponse.warnings) != null ? _b16 : [],
46064
+ warnings: modelResponse.warnings,
45733
46065
  providerMetadata: modelResponse.providerMetadata,
45734
46066
  response: modelResponse.response
45735
46067
  };
@@ -45786,7 +46118,7 @@ async function embedMany({
45786
46118
  }),
45787
46119
  tracer,
45788
46120
  fn: async (doEmbedSpan) => {
45789
- var _a222, _b16;
46121
+ var _a222;
45790
46122
  const modelResponse = await model.doEmbed({
45791
46123
  values: chunk,
45792
46124
  abortSignal,
@@ -45807,7 +46139,7 @@ async function embedMany({
45807
46139
  return {
45808
46140
  embeddings: embeddings2,
45809
46141
  usage,
45810
- warnings: (_b16 = modelResponse.warnings) != null ? _b16 : [],
46142
+ warnings: modelResponse.warnings,
45811
46143
  providerMetadata: modelResponse.providerMetadata,
45812
46144
  response: modelResponse.response
45813
46145
  };
@@ -47921,7 +48253,7 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
47921
48253
  const bytes = typeof data === "string" ? convertBase64ToUint8Array(data) : data;
47922
48254
  const id3Size = (bytes[6] & 127) << 21 | (bytes[7] & 127) << 14 | (bytes[8] & 127) << 7 | bytes[9] & 127;
47923
48255
  return bytes.slice(id3Size + 10);
47924
- }, VERSION3 = "6.0.191", download = async ({
48256
+ }, VERSION3 = "6.0.175", download = async ({
47925
48257
  url: url2,
47926
48258
  maxBytes,
47927
48259
  abortSignal
@@ -48429,7 +48761,7 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
48429
48761
  }
48430
48762
  return this._output;
48431
48763
  }
48432
- }, JsonToSseTransformStream, UI_MESSAGE_STREAM_HEADERS, toolMetadataSchema, uiMessageChunkSchema, isToolOrDynamicToolUIPart, getToolOrDynamicToolName, originalGenerateId2, DefaultStreamTextResult = class {
48764
+ }, JsonToSseTransformStream, UI_MESSAGE_STREAM_HEADERS, uiMessageChunkSchema, isToolOrDynamicToolUIPart, getToolOrDynamicToolName, originalGenerateId2, DefaultStreamTextResult = class {
48433
48765
  constructor({
48434
48766
  model,
48435
48767
  telemetry,
@@ -49677,7 +50009,6 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
49677
50009
  toolName: part.toolName,
49678
50010
  ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
49679
50011
  ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
49680
- ...part.toolMetadata != null ? { toolMetadata: part.toolMetadata } : {},
49681
50012
  ...dynamic != null ? { dynamic } : {},
49682
50013
  ...part.title != null ? { title: part.title } : {}
49683
50014
  });
@@ -49701,7 +50032,6 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
49701
50032
  input: part.input,
49702
50033
  ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
49703
50034
  ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
49704
- ...part.toolMetadata != null ? { toolMetadata: part.toolMetadata } : {},
49705
50035
  ...dynamic != null ? { dynamic } : {},
49706
50036
  errorText: onError(part.error),
49707
50037
  ...part.title != null ? { title: part.title } : {}
@@ -49714,7 +50044,6 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
49714
50044
  input: part.input,
49715
50045
  ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
49716
50046
  ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
49717
- ...part.toolMetadata != null ? { toolMetadata: part.toolMetadata } : {},
49718
50047
  ...dynamic != null ? { dynamic } : {},
49719
50048
  ...part.title != null ? { title: part.title } : {}
49720
50049
  });
@@ -49737,7 +50066,6 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
49737
50066
  output: part.output,
49738
50067
  ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
49739
50068
  ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
49740
- ...part.toolMetadata != null ? { toolMetadata: part.toolMetadata } : {},
49741
50069
  ...part.preliminary != null ? { preliminary: part.preliminary } : {},
49742
50070
  ...dynamic != null ? { dynamic } : {}
49743
50071
  });
@@ -49751,7 +50079,6 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
49751
50079
  errorText: part.providerExecuted ? typeof part.error === "string" ? part.error : JSON.stringify(part.error) : onError(part.error),
49752
50080
  ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
49753
50081
  ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
49754
- ...part.toolMetadata != null ? { toolMetadata: part.toolMetadata } : {},
49755
50082
  ...dynamic != null ? { dynamic } : {}
49756
50083
  });
49757
50084
  break;
@@ -49925,21 +50252,10 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
49925
50252
  ...options
49926
50253
  };
49927
50254
  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;
50255
+ const { instructions, messages, prompt, ...callArgs } = preparedCallArgs;
49935
50256
  return {
49936
50257
  ...callArgs,
49937
- ...{
49938
- system: instructions,
49939
- allowSystemInMessages,
49940
- messages,
49941
- prompt
49942
- }
50258
+ ...{ system: instructions, messages, prompt }
49943
50259
  };
49944
50260
  }
49945
50261
  mergeOnStepFinishCallbacks(methodCallback) {
@@ -49980,7 +50296,7 @@ var import_api2, import_api3, __defProp3, __export3 = (target, all) => {
49980
50296
  onStepFinish: this.mergeOnStepFinishCallbacks(onStepFinish)
49981
50297
  });
49982
50298
  }
49983
- }, toolMetadataSchema2, uiMessagesSchema, DefaultEmbedResult = class {
50299
+ }, uiMessagesSchema, DefaultEmbedResult = class {
49984
50300
  constructor(options) {
49985
50301
  this.value = options.value;
49986
50302
  this.embedding = options.embedding;
@@ -51488,7 +51804,6 @@ var init_dist6 = __esm(() => {
51488
51804
  init_dist5();
51489
51805
  init_dist2();
51490
51806
  init_dist2();
51491
- init_dist5();
51492
51807
  init_dist4();
51493
51808
  init_dist4();
51494
51809
  init_dist4();
@@ -52348,7 +52663,6 @@ var init_dist6 = __esm(() => {
52348
52663
  "x-vercel-ai-ui-message-stream": "v1",
52349
52664
  "x-accel-buffering": "no"
52350
52665
  };
52351
- toolMetadataSchema = exports_external3.record(exports_external3.string(), jsonValueSchema.optional());
52352
52666
  uiMessageChunkSchema = lazySchema(() => zodSchema(exports_external3.union([
52353
52667
  exports_external3.strictObject({
52354
52668
  type: exports_external3.literal("text-start"),
@@ -52376,7 +52690,6 @@ var init_dist6 = __esm(() => {
52376
52690
  toolName: exports_external3.string(),
52377
52691
  providerExecuted: exports_external3.boolean().optional(),
52378
52692
  providerMetadata: providerMetadataSchema.optional(),
52379
- toolMetadata: toolMetadataSchema.optional(),
52380
52693
  dynamic: exports_external3.boolean().optional(),
52381
52694
  title: exports_external3.string().optional()
52382
52695
  }),
@@ -52392,7 +52705,6 @@ var init_dist6 = __esm(() => {
52392
52705
  input: exports_external3.unknown(),
52393
52706
  providerExecuted: exports_external3.boolean().optional(),
52394
52707
  providerMetadata: providerMetadataSchema.optional(),
52395
- toolMetadata: toolMetadataSchema.optional(),
52396
52708
  dynamic: exports_external3.boolean().optional(),
52397
52709
  title: exports_external3.string().optional()
52398
52710
  }),
@@ -52403,7 +52715,6 @@ var init_dist6 = __esm(() => {
52403
52715
  input: exports_external3.unknown(),
52404
52716
  providerExecuted: exports_external3.boolean().optional(),
52405
52717
  providerMetadata: providerMetadataSchema.optional(),
52406
- toolMetadata: toolMetadataSchema.optional(),
52407
52718
  dynamic: exports_external3.boolean().optional(),
52408
52719
  errorText: exports_external3.string(),
52409
52720
  title: exports_external3.string().optional()
@@ -52419,7 +52730,6 @@ var init_dist6 = __esm(() => {
52419
52730
  output: exports_external3.unknown(),
52420
52731
  providerExecuted: exports_external3.boolean().optional(),
52421
52732
  providerMetadata: providerMetadataSchema.optional(),
52422
- toolMetadata: toolMetadataSchema.optional(),
52423
52733
  dynamic: exports_external3.boolean().optional(),
52424
52734
  preliminary: exports_external3.boolean().optional()
52425
52735
  }),
@@ -52429,7 +52739,6 @@ var init_dist6 = __esm(() => {
52429
52739
  errorText: exports_external3.string(),
52430
52740
  providerExecuted: exports_external3.boolean().optional(),
52431
52741
  providerMetadata: providerMetadataSchema.optional(),
52432
- toolMetadata: toolMetadataSchema.optional(),
52433
52742
  dynamic: exports_external3.boolean().optional()
52434
52743
  }),
52435
52744
  exports_external3.strictObject({
@@ -52517,7 +52826,6 @@ var init_dist6 = __esm(() => {
52517
52826
  prefix: "aitxt",
52518
52827
  size: 24
52519
52828
  });
52520
- toolMetadataSchema2 = exports_external3.record(exports_external3.string(), jsonValueSchema.optional());
52521
52829
  uiMessagesSchema = lazySchema(() => zodSchema(exports_external3.array(exports_external3.object({
52522
52830
  id: exports_external3.string(),
52523
52831
  role: exports_external3.enum(["system", "user", "assistant"]),
@@ -52569,7 +52877,6 @@ var init_dist6 = __esm(() => {
52569
52877
  type: exports_external3.literal("dynamic-tool"),
52570
52878
  toolName: exports_external3.string(),
52571
52879
  toolCallId: exports_external3.string(),
52572
- toolMetadata: toolMetadataSchema2.optional(),
52573
52880
  state: exports_external3.literal("input-streaming"),
52574
52881
  input: exports_external3.unknown().optional(),
52575
52882
  providerExecuted: exports_external3.boolean().optional(),
@@ -52582,7 +52889,6 @@ var init_dist6 = __esm(() => {
52582
52889
  type: exports_external3.literal("dynamic-tool"),
52583
52890
  toolName: exports_external3.string(),
52584
52891
  toolCallId: exports_external3.string(),
52585
- toolMetadata: toolMetadataSchema2.optional(),
52586
52892
  state: exports_external3.literal("input-available"),
52587
52893
  input: exports_external3.unknown(),
52588
52894
  providerExecuted: exports_external3.boolean().optional(),
@@ -52595,7 +52901,6 @@ var init_dist6 = __esm(() => {
52595
52901
  type: exports_external3.literal("dynamic-tool"),
52596
52902
  toolName: exports_external3.string(),
52597
52903
  toolCallId: exports_external3.string(),
52598
- toolMetadata: toolMetadataSchema2.optional(),
52599
52904
  state: exports_external3.literal("approval-requested"),
52600
52905
  input: exports_external3.unknown(),
52601
52906
  providerExecuted: exports_external3.boolean().optional(),
@@ -52612,7 +52917,6 @@ var init_dist6 = __esm(() => {
52612
52917
  type: exports_external3.literal("dynamic-tool"),
52613
52918
  toolName: exports_external3.string(),
52614
52919
  toolCallId: exports_external3.string(),
52615
- toolMetadata: toolMetadataSchema2.optional(),
52616
52920
  state: exports_external3.literal("approval-responded"),
52617
52921
  input: exports_external3.unknown(),
52618
52922
  providerExecuted: exports_external3.boolean().optional(),
@@ -52629,7 +52933,6 @@ var init_dist6 = __esm(() => {
52629
52933
  type: exports_external3.literal("dynamic-tool"),
52630
52934
  toolName: exports_external3.string(),
52631
52935
  toolCallId: exports_external3.string(),
52632
- toolMetadata: toolMetadataSchema2.optional(),
52633
52936
  state: exports_external3.literal("output-available"),
52634
52937
  input: exports_external3.unknown(),
52635
52938
  providerExecuted: exports_external3.boolean().optional(),
@@ -52648,9 +52951,8 @@ var init_dist6 = __esm(() => {
52648
52951
  type: exports_external3.literal("dynamic-tool"),
52649
52952
  toolName: exports_external3.string(),
52650
52953
  toolCallId: exports_external3.string(),
52651
- toolMetadata: toolMetadataSchema2.optional(),
52652
52954
  state: exports_external3.literal("output-error"),
52653
- input: exports_external3.unknown().optional(),
52955
+ input: exports_external3.unknown(),
52654
52956
  rawInput: exports_external3.unknown().optional(),
52655
52957
  providerExecuted: exports_external3.boolean().optional(),
52656
52958
  output: exports_external3.never().optional(),
@@ -52667,7 +52969,6 @@ var init_dist6 = __esm(() => {
52667
52969
  type: exports_external3.literal("dynamic-tool"),
52668
52970
  toolName: exports_external3.string(),
52669
52971
  toolCallId: exports_external3.string(),
52670
- toolMetadata: toolMetadataSchema2.optional(),
52671
52972
  state: exports_external3.literal("output-denied"),
52672
52973
  input: exports_external3.unknown(),
52673
52974
  providerExecuted: exports_external3.boolean().optional(),
@@ -52683,7 +52984,6 @@ var init_dist6 = __esm(() => {
52683
52984
  exports_external3.object({
52684
52985
  type: exports_external3.string().startsWith("tool-"),
52685
52986
  toolCallId: exports_external3.string(),
52686
- toolMetadata: toolMetadataSchema2.optional(),
52687
52987
  state: exports_external3.literal("input-streaming"),
52688
52988
  providerExecuted: exports_external3.boolean().optional(),
52689
52989
  callProviderMetadata: providerMetadataSchema.optional(),
@@ -52695,7 +52995,6 @@ var init_dist6 = __esm(() => {
52695
52995
  exports_external3.object({
52696
52996
  type: exports_external3.string().startsWith("tool-"),
52697
52997
  toolCallId: exports_external3.string(),
52698
- toolMetadata: toolMetadataSchema2.optional(),
52699
52998
  state: exports_external3.literal("input-available"),
52700
52999
  providerExecuted: exports_external3.boolean().optional(),
52701
53000
  input: exports_external3.unknown(),
@@ -52707,7 +53006,6 @@ var init_dist6 = __esm(() => {
52707
53006
  exports_external3.object({
52708
53007
  type: exports_external3.string().startsWith("tool-"),
52709
53008
  toolCallId: exports_external3.string(),
52710
- toolMetadata: toolMetadataSchema2.optional(),
52711
53009
  state: exports_external3.literal("approval-requested"),
52712
53010
  input: exports_external3.unknown(),
52713
53011
  providerExecuted: exports_external3.boolean().optional(),
@@ -52723,7 +53021,6 @@ var init_dist6 = __esm(() => {
52723
53021
  exports_external3.object({
52724
53022
  type: exports_external3.string().startsWith("tool-"),
52725
53023
  toolCallId: exports_external3.string(),
52726
- toolMetadata: toolMetadataSchema2.optional(),
52727
53024
  state: exports_external3.literal("approval-responded"),
52728
53025
  input: exports_external3.unknown(),
52729
53026
  providerExecuted: exports_external3.boolean().optional(),
@@ -52739,7 +53036,6 @@ var init_dist6 = __esm(() => {
52739
53036
  exports_external3.object({
52740
53037
  type: exports_external3.string().startsWith("tool-"),
52741
53038
  toolCallId: exports_external3.string(),
52742
- toolMetadata: toolMetadataSchema2.optional(),
52743
53039
  state: exports_external3.literal("output-available"),
52744
53040
  providerExecuted: exports_external3.boolean().optional(),
52745
53041
  input: exports_external3.unknown(),
@@ -52757,10 +53053,9 @@ var init_dist6 = __esm(() => {
52757
53053
  exports_external3.object({
52758
53054
  type: exports_external3.string().startsWith("tool-"),
52759
53055
  toolCallId: exports_external3.string(),
52760
- toolMetadata: toolMetadataSchema2.optional(),
52761
53056
  state: exports_external3.literal("output-error"),
52762
53057
  providerExecuted: exports_external3.boolean().optional(),
52763
- input: exports_external3.unknown().optional(),
53058
+ input: exports_external3.unknown(),
52764
53059
  rawInput: exports_external3.unknown().optional(),
52765
53060
  output: exports_external3.never().optional(),
52766
53061
  errorText: exports_external3.string(),
@@ -52775,7 +53070,6 @@ var init_dist6 = __esm(() => {
52775
53070
  exports_external3.object({
52776
53071
  type: exports_external3.string().startsWith("tool-"),
52777
53072
  toolCallId: exports_external3.string(),
52778
- toolMetadata: toolMetadataSchema2.optional(),
52779
53073
  state: exports_external3.literal("output-denied"),
52780
53074
  providerExecuted: exports_external3.boolean().optional(),
52781
53075
  input: exports_external3.unknown(),
@@ -53265,54 +53559,52 @@ import { promises as fsPromises } from "fs";
53265
53559
  import { createHash, createPrivateKey, createPublicKey, sign } from "crypto";
53266
53560
  import { promises as fs2 } from "fs";
53267
53561
  import { homedir as homedir22 } from "os";
53268
- import { dirname as dirname3, join as join62 } from "path";
53562
+ import { dirname as dirname3, join as join52 } from "path";
53269
53563
  import { exec } from "child_process";
53270
53564
  import { promisify } from "util";
53271
- import { readFileSync as readFileSync4 } from "fs";
53565
+ import { readFileSync as readFileSync3 } from "fs";
53272
53566
  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";
53567
+ import { existsSync as existsSync42, writeFileSync as writeFileSync32, readFileSync as readFileSync22, mkdirSync as mkdirSync32 } from "fs";
53568
+ import { join as join42 } from "path";
53275
53569
  import { Database as Database4 } from "bun:sqlite";
53276
53570
  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";
53571
+ import { dirname as dirname4, join as join15, resolve as resolve2 } from "path";
53572
+ import { existsSync as existsSync22, writeFileSync as writeFileSync4 } from "fs";
53279
53573
  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";
53574
+ import { execSync as execSync2, execFileSync } from "child_process";
53575
+ import { existsSync as existsSync32, readFileSync as readFileSync4, writeFileSync as writeFileSync22, mkdirSync as mkdirSync22 } from "fs";
53285
53576
  import { homedir as homedir11 } from "os";
53286
- import { join as join42, dirname as dirname22 } from "path";
53577
+ import { join as join32, dirname as dirname22 } from "path";
53578
+ import { hostname as hostname3 } from "os";
53287
53579
  import { Buffer as Buffer2 } from "buffer";
53288
53580
  import * as zlib from "zlib";
53289
53581
  import { Readable } from "stream";
53290
53582
  import { Writable } from "stream";
53291
53583
  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";
53584
+ import { mkdirSync as mkdirSync4, statSync, writeFileSync as writeFileSync42 } from "fs";
53585
+ import { dirname as dirname42, join as join62, relative as relative2 } from "path";
53294
53586
  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";
53587
+ import { existsSync as existsSync62, readdirSync as readdirSync3, readFileSync as readFileSync42, statSync as statSync2 } from "fs";
53588
+ import { basename, join as join72, resolve as resolve22 } from "path";
53297
53589
  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";
53590
+ import { existsSync as existsSync72, readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync52 } from "fs";
53591
+ import { dirname as dirname5, join as join82 } from "path";
53300
53592
  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
53593
  import { existsSync as existsSync102 } from "fs";
53308
- import { execSync as execSync2 } from "child_process";
53309
53594
  import { join as join112 } from "path";
53595
+ import { execFileSync as execFileSync3 } from "child_process";
53596
+ import { existsSync as existsSync82 } from "fs";
53597
+ import { homedir as homedir32, hostname as hostname22, platform as platform2, type } from "os";
53598
+ import { join as join92 } from "path";
53599
+ import { existsSync as existsSync92 } from "fs";
53310
53600
  import { execSync as execSync22 } from "child_process";
53311
- import { readFileSync as readFileSync7 } from "fs";
53601
+ import { join as join102 } from "path";
53602
+ import { execSync as execSync3 } from "child_process";
53603
+ import { readFileSync as readFileSync6 } from "fs";
53312
53604
  import { mkdirSync as mkdirSync62 } from "fs";
53313
- import { dirname as dirname6, join as join132 } from "path";
53605
+ import { dirname as dirname6, join as join122 } from "path";
53314
53606
  import { fileURLToPath } from "url";
53315
- import { existsSync as existsSync12 } from "fs";
53607
+ import { existsSync as existsSync112 } from "fs";
53316
53608
  function __accessProp3(key) {
53317
53609
  return this[key];
53318
53610
  }
@@ -53451,7 +53743,7 @@ function getDbPath2() {
53451
53743
  return process.env["PROJECTS_DB_PATH"];
53452
53744
  }
53453
53745
  const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
53454
- return join14(home, ".hasna", "projects", "projects.db");
53746
+ return join15(home, ".hasna", "projects", "projects.db");
53455
53747
  }
53456
53748
  function ensureDir2(filePath) {
53457
53749
  if (filePath === ":memory:")
@@ -53489,25 +53781,14 @@ function uuid5() {
53489
53781
  function isGitRepo(path) {
53490
53782
  return existsSync22(join22(path, ".git"));
53491
53783
  }
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
53784
  function gitInit(project) {
53504
53785
  const { path, name: name21, id, slug } = project;
53505
53786
  if (isGitRepo(path))
53506
53787
  return;
53507
- execFileSync("git", ["init", "-b", "main"], { cwd: path, stdio: "pipe", env: process.env });
53788
+ execSync2("git init", { cwd: path, stdio: "pipe" });
53508
53789
  const gitignorePath = join22(path, ".gitignore");
53509
53790
  if (!existsSync22(gitignorePath)) {
53510
- writeFileSync3(gitignorePath, GITIGNORE_TEMPLATE, "utf-8");
53791
+ writeFileSync4(gitignorePath, GITIGNORE_TEMPLATE, "utf-8");
53511
53792
  }
53512
53793
  const projectJson = {
53513
53794
  id,
@@ -53516,18 +53797,26 @@ function gitInit(project) {
53516
53797
  created_at: project.created_at,
53517
53798
  integrations: project.integrations ?? {}
53518
53799
  };
53519
- writeFileSync3(join22(path, ".project.json"), JSON.stringify(projectJson, null, 2) + `
53800
+ writeFileSync4(join22(path, ".project.json"), JSON.stringify(projectJson, null, 2) + `
53520
53801
  `, "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}`], {
53802
+ execSync2("git add .gitignore .project.json", { cwd: path, stdio: "pipe" });
53803
+ execSync2(`git commit -m "chore: init project ${name21}"`, {
53526
53804
  cwd: path,
53527
53805
  stdio: "pipe",
53528
53806
  env: { ...process.env, GIT_AUTHOR_NAME: "open-projects", GIT_COMMITTER_NAME: "open-projects" }
53529
53807
  });
53530
53808
  }
53809
+ function getConfig() {
53810
+ if (existsSync32(CONFIG_PATH3)) {
53811
+ try {
53812
+ const user = JSON.parse(readFileSync4(CONFIG_PATH3, "utf-8"));
53813
+ return { ...DEFAULTS, ...user };
53814
+ } catch {
53815
+ return { ...DEFAULTS };
53816
+ }
53817
+ }
53818
+ return { ...DEFAULTS };
53819
+ }
53531
53820
  function rowToWorkdir(row) {
53532
53821
  return {
53533
53822
  ...row,
@@ -53571,176 +53860,6 @@ function removeWorkdir(projectId, path, db2) {
53571
53860
  const d = db2 || getDatabase2();
53572
53861
  d.run("DELETE FROM project_workdirs WHERE project_id = ? AND path = ?", [projectId, path]);
53573
53862
  }
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
53863
  function generateProjectId() {
53745
53864
  return `prj_${nanoid3()}`;
53746
53865
  }
@@ -53748,10 +53867,12 @@ function slugify2(name21) {
53748
53867
  return name21.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
53749
53868
  }
53750
53869
  function scaffoldProject(path) {
53870
+ if (existsSync42(path))
53871
+ return;
53751
53872
  mkdirSync32(path, { recursive: true });
53752
53873
  const config2 = getConfig();
53753
53874
  for (const dir of config2.scaffold_dirs || ["data", "scripts", "assets", "docs"]) {
53754
- mkdirSync32(join52(path, dir), { recursive: true });
53875
+ mkdirSync32(join42(path, dir), { recursive: true });
53755
53876
  }
53756
53877
  }
53757
53878
  function ensureUniqueSlug(base, db2, excludeId) {
@@ -53802,9 +53923,6 @@ function createProject2(input, db2) {
53802
53923
  try {
53803
53924
  addWorkdir({ project_id: id, path: input.path, label: "main", is_primary: true }, d);
53804
53925
  } catch {}
53805
- try {
53806
- generateAllWorkdirs(project, { db: d });
53807
- } catch {}
53808
53926
  const shouldGitInit = input.git_init !== false;
53809
53927
  if (shouldGitInit) {
53810
53928
  try {
@@ -53910,10 +54028,10 @@ function setIntegrations(id, integrations, db2) {
53910
54028
  id
53911
54029
  ]);
53912
54030
  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) + `
54031
+ const jsonPath = join42(project.path, ".project.json");
54032
+ if (existsSync42(jsonPath)) {
54033
+ const existing = JSON.parse(readFileSync22(jsonPath, "utf-8"));
54034
+ writeFileSync32(jsonPath, JSON.stringify({ ...existing, integrations: merged }, null, 2) + `
53917
54035
  `, "utf-8");
53918
54036
  }
53919
54037
  } catch {}
@@ -54987,7 +55105,7 @@ async function collectLocalFiles(rootPath) {
54987
55105
  async function walk(dir) {
54988
55106
  const entries = await readdir(dir, { withFileTypes: true });
54989
55107
  for (const entry of entries) {
54990
- const fullPath = join72(dir, entry.name);
55108
+ const fullPath = join62(dir, entry.name);
54991
55109
  if (entry.isDirectory()) {
54992
55110
  await walk(fullPath);
54993
55111
  } else if (entry.isFile()) {
@@ -55059,7 +55177,7 @@ async function syncProject(project, options = {}) {
55059
55177
  continue;
55060
55178
  }
55061
55179
  try {
55062
- const data = await readFile2(join72(project.path, relPath));
55180
+ const data = await readFile2(join62(project.path, relPath));
55063
55181
  await client.send(new PutObjectCommand({
55064
55182
  Bucket: bucket,
55065
55183
  Key: s3Key,
@@ -55097,9 +55215,9 @@ async function syncProject(project, options = {}) {
55097
55215
  chunks.push(chunk);
55098
55216
  }
55099
55217
  const data = Buffer.concat(chunks);
55100
- const localPath = join72(project.path, relPath);
55218
+ const localPath = join62(project.path, relPath);
55101
55219
  mkdirSync4(dirname42(localPath), { recursive: true });
55102
- writeFileSync5(localPath, data);
55220
+ writeFileSync42(localPath, data);
55103
55221
  log(`pull: ${relPath} (${data.length}B)`);
55104
55222
  result.pulled++;
55105
55223
  result.bytes += data.length;
@@ -55120,18 +55238,18 @@ async function syncProject(project, options = {}) {
55120
55238
  return result;
55121
55239
  }
55122
55240
  function inferProjectName(projectPath) {
55123
- const pkgPath = join82(projectPath, "package.json");
55124
- if (existsSync72(pkgPath)) {
55241
+ const pkgPath = join72(projectPath, "package.json");
55242
+ if (existsSync62(pkgPath)) {
55125
55243
  try {
55126
- const pkg = JSON.parse(readFileSync52(pkgPath, "utf-8"));
55244
+ const pkg = JSON.parse(readFileSync42(pkgPath, "utf-8"));
55127
55245
  if (pkg.name)
55128
55246
  return pkg.name.replace(/^@[^/]+\//, "");
55129
55247
  } catch {}
55130
55248
  }
55131
- const projPath = join82(projectPath, ".project.json");
55132
- if (existsSync72(projPath)) {
55249
+ const projPath = join72(projectPath, ".project.json");
55250
+ if (existsSync62(projPath)) {
55133
55251
  try {
55134
- const p2 = JSON.parse(readFileSync52(projPath, "utf-8"));
55252
+ const p2 = JSON.parse(readFileSync42(projPath, "utf-8"));
55135
55253
  if (p2.name)
55136
55254
  return p2.name;
55137
55255
  } catch {}
@@ -55139,11 +55257,11 @@ function inferProjectName(projectPath) {
55139
55257
  return basename(projectPath);
55140
55258
  }
55141
55259
  function inferGitRemote(projectPath) {
55142
- const gitConfigPath = join82(projectPath, ".git", "config");
55143
- if (!existsSync72(gitConfigPath))
55260
+ const gitConfigPath = join72(projectPath, ".git", "config");
55261
+ if (!existsSync62(gitConfigPath))
55144
55262
  return;
55145
55263
  try {
55146
- const config2 = readFileSync52(gitConfigPath, "utf-8");
55264
+ const config2 = readFileSync42(gitConfigPath, "utf-8");
55147
55265
  const match = config2.match(/\[remote "origin"\][\s\S]*?url\s*=\s*(.+)/);
55148
55266
  return match?.[1]?.trim();
55149
55267
  } catch {
@@ -55153,7 +55271,7 @@ function inferGitRemote(projectPath) {
55153
55271
  async function importProject(projectPath, options = {}) {
55154
55272
  const absPath = resolve22(projectPath);
55155
55273
  const log = options.onProgress ?? (() => {});
55156
- if (!existsSync72(absPath)) {
55274
+ if (!existsSync62(absPath)) {
55157
55275
  return { error: `Path does not exist: ${absPath}` };
55158
55276
  }
55159
55277
  const stat = statSync2(absPath);
@@ -55188,7 +55306,7 @@ async function importBulk(dirPath, options = {}) {
55188
55306
  const absDir = resolve22(dirPath);
55189
55307
  const result = { imported: [], skipped: [], errors: [] };
55190
55308
  const log = options.onProgress ?? (() => {});
55191
- if (!existsSync72(absDir)) {
55309
+ if (!existsSync62(absDir)) {
55192
55310
  result.errors.push({ path: absDir, error: "Directory does not exist" });
55193
55311
  return result;
55194
55312
  }
@@ -55196,7 +55314,7 @@ async function importBulk(dirPath, options = {}) {
55196
55314
  const dirs = entries.filter((e2) => e2.isDirectory() && !e2.name.startsWith("."));
55197
55315
  log(`Found ${dirs.length} subdirectories in ${absDir}`);
55198
55316
  for (const entry of dirs) {
55199
- const subPath = join82(absDir, entry.name);
55317
+ const subPath = join72(absDir, entry.name);
55200
55318
  const res = await importProject(subPath, options);
55201
55319
  if (res.project) {
55202
55320
  result.imported.push(res.project);
@@ -55231,8 +55349,7 @@ function publishProject(name21, path, options = {}) {
55231
55349
  } else {
55232
55350
  execFileSync2("git", ["remote", "add", "origin", remote], { cwd: path, stdio: "pipe", env: process.env });
55233
55351
  }
55234
- const branch = getCurrentBranch(path);
55235
- execFileSync2("git", ["push", "-u", "origin", branch, "--quiet"], { cwd: path, stdio: "pipe", env: process.env });
55352
+ execFileSync2("git", ["push", "-u", "origin", "main", "--quiet"], { cwd: path, stdio: "pipe", env: process.env });
55236
55353
  pushed = true;
55237
55354
  } catch {}
55238
55355
  }
@@ -55258,14 +55375,14 @@ function getGitHubUrl(path) {
55258
55375
  }
55259
55376
  }
55260
55377
  function getScheduleConfig() {
55261
- if (!existsSync82(CONFIG_PATH22)) {
55378
+ if (!existsSync72(CONFIG_PATH22)) {
55262
55379
  return { enabled: false, interval: "daily", direction: "both" };
55263
55380
  }
55264
- return JSON.parse(readFileSync6(CONFIG_PATH22, "utf-8"));
55381
+ return JSON.parse(readFileSync5(CONFIG_PATH22, "utf-8"));
55265
55382
  }
55266
55383
  function saveScheduleConfig(config2) {
55267
55384
  mkdirSync52(dirname5(CONFIG_PATH22), { recursive: true });
55268
- writeFileSync6(CONFIG_PATH22, JSON.stringify(config2, null, 2) + `
55385
+ writeFileSync5(CONFIG_PATH22, JSON.stringify(config2, null, 2) + `
55269
55386
  `, "utf-8");
55270
55387
  }
55271
55388
  async function syncAll(direction = "both", onProgress) {
@@ -55295,7 +55412,7 @@ async function syncAll(direction = "both", onProgress) {
55295
55412
  function getMachineProfile() {
55296
55413
  const host = (process.env["HOSTNAME"] || hostname22()).split(".")[0] || hostname22();
55297
55414
  const currentPlatform = platform2();
55298
- const workspaceRoot = currentPlatform === "darwin" ? join102(homedir32(), "Workspace") : join102(homedir32(), "workspace");
55415
+ const workspaceRoot = currentPlatform === "darwin" ? join92(homedir32(), "Workspace") : join92(homedir32(), "workspace");
55299
55416
  return {
55300
55417
  hostname: host,
55301
55418
  platform: currentPlatform,
@@ -55322,7 +55439,7 @@ function commandAvailability(command, versionArgs = ["--version"]) {
55322
55439
  return { command, available: true, path: commandPath, version: version2 };
55323
55440
  }
55324
55441
  function pathExists(path) {
55325
- return existsSync92(path);
55442
+ return existsSync82(path);
55326
55443
  }
55327
55444
  function classifyMachine(host, currentPlatform) {
55328
55445
  if (host === "apple01")
@@ -55336,10 +55453,10 @@ function classifyMachine(host, currentPlatform) {
55336
55453
  return "unknown";
55337
55454
  }
55338
55455
  function gitStatus(path) {
55339
- if (!existsSync102(join112(path, ".git")))
55456
+ if (!existsSync92(join102(path, ".git")))
55340
55457
  return "not a repo";
55341
55458
  try {
55342
- const out = execSync2("git status --porcelain", { cwd: path, stdio: "pipe", encoding: "utf-8" }).trim();
55459
+ const out = execSync22("git status --porcelain", { cwd: path, stdio: "pipe", encoding: "utf-8" }).trim();
55343
55460
  if (!out)
55344
55461
  return "clean";
55345
55462
  const n2 = out.split(`
@@ -55350,17 +55467,17 @@ function gitStatus(path) {
55350
55467
  }
55351
55468
  }
55352
55469
  function dirSize(path) {
55353
- if (!existsSync102(path))
55470
+ if (!existsSync92(path))
55354
55471
  return 0;
55355
55472
  try {
55356
- const out = execSync2(`du -sb -- "${path}" 2>/dev/null || du -sk -- "${path}" 2>/dev/null`, { stdio: "pipe", encoding: "utf-8" }).trim();
55473
+ const out = execSync22(`du -sb -- "${path}" 2>/dev/null || du -sk -- "${path}" 2>/dev/null`, { stdio: "pipe", encoding: "utf-8" }).trim();
55357
55474
  return parseInt(out.split("\t")[0] ?? "0", 10);
55358
55475
  } catch {
55359
55476
  return 0;
55360
55477
  }
55361
55478
  }
55362
55479
  function getProjectStatus(project) {
55363
- const pathExists2 = existsSync102(project.path);
55480
+ const pathExists2 = existsSync92(project.path);
55364
55481
  const workdirs = listWorkdirs(project.id);
55365
55482
  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
55483
  return {
@@ -55373,21 +55490,18 @@ function getProjectStatus(project) {
55373
55490
  };
55374
55491
  }
55375
55492
  function run(cmd) {
55376
- return execSync22(cmd, { encoding: "utf-8", stdio: "pipe" }).trim();
55493
+ return execSync3(cmd, { encoding: "utf-8", stdio: "pipe" }).trim();
55377
55494
  }
55378
55495
  function getTmuxSessionName(project) {
55379
- return project.slug || project.name;
55496
+ const raw = project.slug || project.name;
55497
+ if (project.path?.includes("opensourcedev")) {
55498
+ const normalized = raw.replace(/^proj-/, "");
55499
+ return normalized.startsWith("open-") ? normalized : `open-${normalized}`;
55500
+ }
55501
+ return raw;
55380
55502
  }
55381
55503
  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
- }
55504
+ const output = run("tmux list-sessions -F '#{session_name}:#{session_group}:#{session_windows}:#{session_attached}'");
55391
55505
  return output.split(`
55392
55506
  `).filter(Boolean).map((line) => {
55393
55507
  const [name21, group, windows, attached] = line.split(":");
@@ -55495,7 +55609,7 @@ function getProjectLocations(project) {
55495
55609
  const currentMachine = getMachineId();
55496
55610
  return listWorkdirs(project.id).map((workdir) => ({
55497
55611
  ...workdir,
55498
- exists: existsSync112(workdir.path),
55612
+ exists: existsSync102(workdir.path),
55499
55613
  currentMachine: workdir.machine_id === currentMachine,
55500
55614
  recommended: workdir.is_primary || workdir.path === project.path
55501
55615
  }));
@@ -55532,7 +55646,7 @@ function buildProjectContext(project) {
55532
55646
  };
55533
55647
  }
55534
55648
  function getGitContext(path) {
55535
- if (!existsSync112(join122(path, ".git"))) {
55649
+ if (!existsSync102(join112(path, ".git"))) {
55536
55650
  return { isRepo: false, branch: null, dirtyCount: null, remote: null };
55537
55651
  }
55538
55652
  return {
@@ -55575,7 +55689,7 @@ function setupMachineReport(options = {}) {
55575
55689
  const dryRun = options.dryRun !== false;
55576
55690
  const checks3 = [];
55577
55691
  const dbDir = dirname6(getDbPath2());
55578
- const cloudConfig = join132(process.env["HOME"] || "~", ".hasna", "cloud", "config.json");
55692
+ const cloudConfig = join122(process.env["HOME"] || "~", ".hasna", "cloud", "config.json");
55579
55693
  checks3.push(pathCheck("PROJECTS_DATA_DIR", "projects data dir", dbDir, options));
55580
55694
  checks3.push(pathCheck("WORKSPACE_ROOT", "workspace root", machine.workspaceRoot, options));
55581
55695
  checks3.push(commandCheck("bun", ["--version"], "Bun runtime"));
@@ -55636,8 +55750,8 @@ function commandCheck(command, versionArgs, label, missingStatus = "error") {
55636
55750
  }
55637
55751
  function packageVersion() {
55638
55752
  try {
55639
- const pkgPath = join132(dirname6(fileURLToPath(import.meta.url)), "..", "..", "package.json");
55640
- return JSON.parse(readFileSync7(pkgPath, "utf-8")).version || "0.0.0";
55753
+ const pkgPath = join122(dirname6(fileURLToPath(import.meta.url)), "..", "..", "package.json");
55754
+ return JSON.parse(readFileSync6(pkgPath, "utf-8")).version || "0.0.0";
55641
55755
  } catch {
55642
55756
  return "0.0.0";
55643
55757
  }
@@ -55651,7 +55765,7 @@ function findStaleIssues(project) {
55651
55765
  const issues = [];
55652
55766
  const currentMachine = getMachineId();
55653
55767
  for (const p2 of projects) {
55654
- if (p2.status === "active" && !existsSync12(p2.path)) {
55768
+ if (p2.status === "active" && !existsSync112(p2.path)) {
55655
55769
  issues.push({
55656
55770
  code: "PROJECT_PATH_MISSING",
55657
55771
  severity: "error",
@@ -55662,7 +55776,7 @@ function findStaleIssues(project) {
55662
55776
  });
55663
55777
  }
55664
55778
  for (const workdir of listWorkdirs(p2.id)) {
55665
- if (workdir.machine_id === currentMachine && !existsSync12(workdir.path)) {
55779
+ if (workdir.machine_id === currentMachine && !existsSync112(workdir.path)) {
55666
55780
  issues.push({
55667
55781
  code: "WORKDIR_PATH_MISSING",
55668
55782
  severity: "warn",
@@ -56604,7 +56718,7 @@ Reference: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.ht
56604
56718
  }
56605
56719
  const credentials = await fromWebToken({
56606
56720
  ...init,
56607
- webIdentityToken: import_shared_ini_file_loader10.externalDataInterceptor?.getTokenRecord?.()[webIdentityTokenFile] ?? readFileSync4(webIdentityTokenFile, { encoding: "ascii" }),
56721
+ webIdentityToken: import_shared_ini_file_loader10.externalDataInterceptor?.getTokenRecord?.()[webIdentityTokenFile] ?? readFileSync3(webIdentityTokenFile, { encoding: "ascii" }),
56608
56722
  roleArn,
56609
56723
  roleSessionName
56610
56724
  })(awsIdentityProperties);
@@ -56691,7 +56805,7 @@ coverage/
56691
56805
  # Cache
56692
56806
  .cache/
56693
56807
  .turbo/
56694
- `, BOOTSTRAP_PATHS, CONFIG_PATH3, DEFAULTS, nanoid3, import_protocol_http, addExpectContinueMiddlewareOptions, getAddExpectContinuePlugin = (options) => ({
56808
+ `, CONFIG_PATH3, DEFAULTS, nanoid3, import_protocol_http, addExpectContinueMiddlewareOptions, getAddExpectContinuePlugin = (options) => ({
56695
56809
  applyToStack: (clientStack) => {
56696
56810
  clientStack.add(addExpectContinueMiddleware(options), addExpectContinueMiddlewareOptions);
56697
56811
  }
@@ -69770,11 +69884,11 @@ More information can be found at: https://a.co/c895JFp`);
69770
69884
  var numberSelector = (obj, key, type2) => {
69771
69885
  if (!(key in obj))
69772
69886
  return;
69773
- const numberValue = parseInt(obj[key], 10);
69774
- if (Number.isNaN(numberValue)) {
69887
+ const numberValue2 = parseInt(obj[key], 10);
69888
+ if (Number.isNaN(numberValue2)) {
69775
69889
  throw new TypeError(`Cannot load ${type2} '${key}'. Expected number, got '${obj[key]}'.`);
69776
69890
  }
69777
- return numberValue;
69891
+ return numberValue2;
69778
69892
  };
69779
69893
  exports.SelectorType = undefined;
69780
69894
  (function(SelectorType2) {
@@ -74502,7 +74616,7 @@ More information can be found at: https://a.co/c895JFp`);
74502
74616
  };
74503
74617
  });
74504
74618
  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";
74619
+ var __dirname2 = "/home/hasna/workspace/hasna/opensource/open-projects/node_modules/@aws-sdk/util-user-agent-node/dist-cjs";
74506
74620
  var node_os = __require3("os");
74507
74621
  var node_process = __require3("process");
74508
74622
  var utilConfigProvider = require_dist_cjs28();
@@ -78172,10 +78286,10 @@ More information can be found at: https://a.co/c895JFp`);
78172
78286
  await fs2.writeFile(tokenFilePath, JSON.stringify(token, null, 2), "utf8");
78173
78287
  }
78174
78288
  getTokenFilePath() {
78175
- const directory = process.env.AWS_LOGIN_CACHE_DIRECTORY ?? join62(homedir22(), ".aws", "login", "cache");
78289
+ const directory = process.env.AWS_LOGIN_CACHE_DIRECTORY ?? join52(homedir22(), ".aws", "login", "cache");
78176
78290
  const loginSessionBytes = Buffer.from(this.loginSession, "utf8");
78177
78291
  const loginSessionSha256 = createHash("sha256").update(loginSessionBytes).digest("hex");
78178
- return join62(directory, `${loginSessionSha256}.json`);
78292
+ return join52(directory, `${loginSessionSha256}.json`);
78179
78293
  }
78180
78294
  derToRawSignature(derSignature) {
78181
78295
  let offset = 2;
@@ -78476,18 +78590,7 @@ More information can be found at: https://a.co/c895JFp`);
78476
78590
  INSERT OR IGNORE INTO _migrations (id) VALUES (4);
78477
78591
  `
78478
78592
  ];
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");
78593
+ CONFIG_PATH3 = join32(homedir11(), ".hasna", "projects", "config.json");
78491
78594
  DEFAULTS = {
78492
78595
  default_path: process.cwd(),
78493
78596
  default_github_org: "hasnaxyz",
@@ -84273,7 +84376,7 @@ More information can be found at: https://a.co/c895JFp`);
84273
84376
  }).s("AmazonS3", "PutObject", {}).n("S3Client", "PutObjectCommand").sc(PutObject$).build() {
84274
84377
  };
84275
84378
  MAX_FILE_SIZE = 100 * 1024 * 1024;
84276
- CONFIG_PATH22 = join92(process.env["HOME"] || "~", ".hasna", "projects", "scheduler.json");
84379
+ CONFIG_PATH22 = join82(process.env["HOME"] || "~", ".hasna", "projects", "scheduler.json");
84277
84380
  SPARK_MACHINES = new Set(["spark01", "spark02"]);
84278
84381
  });
84279
84382
 
@@ -85264,12 +85367,12 @@ __export(exports_contacts_connector, {
85264
85367
  });
85265
85368
  function getContactsDb() {
85266
85369
  const { Database: Database5 } = __require("bun:sqlite");
85267
- const { existsSync: existsSync13 } = __require("fs");
85268
- const { join: join15 } = __require("path");
85370
+ const { existsSync: existsSync5 } = __require("fs");
85371
+ const { join: join16 } = __require("path");
85269
85372
  const { homedir: homedir7 } = __require("os");
85270
85373
  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))
85374
+ const dbPath = envPath ?? join16(homedir7(), ".hasna", "contacts", "contacts.db");
85375
+ if (!existsSync5(dbPath))
85273
85376
  return null;
85274
85377
  const db2 = new Database5(dbPath, { readonly: true });
85275
85378
  return db2;
@@ -85389,7 +85492,7 @@ __export(exports_army_runner, {
85389
85492
  waitForArmyRun: () => waitForArmyRun,
85390
85493
  runWithArmy: () => runWithArmy
85391
85494
  });
85392
- import { join as join15 } from "path";
85495
+ import { join as join16 } from "path";
85393
85496
  function chunkArray(arr, n2) {
85394
85497
  const chunks = [];
85395
85498
  const size = Math.ceil(arr.length / n2);
@@ -85399,7 +85502,7 @@ function chunkArray(arr, n2) {
85399
85502
  return chunks;
85400
85503
  }
85401
85504
  function getCliPath() {
85402
- const srcPath = join15(import.meta.dir, "../cli/index.tsx");
85505
+ const srcPath = join16(import.meta.dir, "../cli/index.tsx");
85403
85506
  return srcPath;
85404
85507
  }
85405
85508
  async function runWithArmy(options) {
@@ -86171,9 +86274,30 @@ function buildServer() {
86171
86274
  goalPrompt: exports_external.string().optional().describe("Goal prompt for the AI SDK workflow agent"),
86172
86275
  successCriteria: exports_external.array(exports_external.string()).optional().describe("Goal success criteria"),
86173
86276
  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 }) => {
86277
+ executionTarget: exports_external.enum(["local", "sandbox", "connector:e2b"]).optional().describe("Run locally or through the sandboxes SDK"),
86278
+ sandboxProvider: exports_external.string().optional().describe("Sandbox provider: e2b, daytona, or modal"),
86279
+ sandboxImage: exports_external.string().optional().describe("Sandbox image/template"),
86280
+ sandboxRemoteDir: exports_external.string().optional().describe("Remote working directory for sandbox runs"),
86281
+ sandboxCleanup: exports_external.enum(["delete", "stop", "keep"]).optional().describe("Sandbox cleanup mode"),
86282
+ e2bTemplate: exports_external.string().optional().describe("Legacy alias for sandboxImage")
86283
+ }, async ({
86284
+ name: name21,
86285
+ description,
86286
+ projectId,
86287
+ scenarioIds,
86288
+ tags,
86289
+ priority,
86290
+ personaIds,
86291
+ goalPrompt,
86292
+ successCriteria,
86293
+ maxIterations,
86294
+ executionTarget,
86295
+ sandboxProvider,
86296
+ sandboxImage,
86297
+ sandboxRemoteDir,
86298
+ sandboxCleanup,
86299
+ e2bTemplate
86300
+ }) => {
86177
86301
  try {
86178
86302
  return json3(createTestingWorkflow({
86179
86303
  name: name21,
@@ -86184,8 +86308,10 @@ function buildServer() {
86184
86308
  goal: goalPrompt ? { prompt: goalPrompt, successCriteria, maxIterations } : null,
86185
86309
  execution: {
86186
86310
  target: executionTarget ?? "local",
86187
- connector: executionTarget === "connector:e2b" ? "e2b" : undefined,
86188
- sandboxTemplate: e2bTemplate
86311
+ provider: sandboxProvider ?? (executionTarget === "connector:e2b" ? "e2b" : undefined),
86312
+ sandboxImage: sandboxImage ?? e2bTemplate,
86313
+ sandboxRemoteDir,
86314
+ sandboxCleanup
86189
86315
  }
86190
86316
  }));
86191
86317
  } catch (error40) {
@@ -86949,12 +87075,12 @@ function buildServer() {
86949
87075
  }
86950
87076
  if (!resolvedUrl)
86951
87077
  return errorResponse(new Error("No URL provided and no default environment set. Pass url or env."));
86952
- const { execSync: execSync3 } = await import("child_process");
87078
+ const { execSync: execSync4 } = await import("child_process");
86953
87079
  let diffOutput = "";
86954
87080
  try {
86955
87081
  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();
87082
+ const stagedOut = execSync4(`git diff --cached --name-only`, { cwd: process.cwd(), encoding: "utf-8" }).trim();
87083
+ const unstagedOut = execSync4(`git diff --name-only ${ref}`, { cwd: process.cwd(), encoding: "utf-8" }).trim();
86958
87084
  diffOutput = [stagedOut, unstagedOut].filter(Boolean).join(`
86959
87085
  `);
86960
87086
  } catch {
@@ -87091,8 +87217,8 @@ function buildServer() {
87091
87217
  let allFiles = [...filePaths];
87092
87218
  if (includeAutoDetect) {
87093
87219
  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();
87220
+ const { execSync: execSync4 } = await import("child_process");
87221
+ const diffOutput = execSync4("git diff --name-only HEAD", { encoding: "utf-8", cwd: process.cwd() }).trim();
87096
87222
  const gitFiles = diffOutput.split(`
87097
87223
  `).filter(Boolean);
87098
87224
  allFiles = [...new Set([...allFiles, ...gitFiles])];
@@ -87637,7 +87763,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
87637
87763
  // src/mcp/http.ts
87638
87764
  import { createServer } from "http";
87639
87765
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
87640
- var DEFAULT_MCP_HTTP_PORT = 8880;
87766
+ var DEFAULT_MCP_HTTP_PORT = 8840;
87641
87767
  var DEFAULT_HOST = "127.0.0.1";
87642
87768
  function resolveMcpHttpPort(explicitPort) {
87643
87769
  if (explicitPort !== undefined && !Number.isNaN(explicitPort))
@@ -87659,8 +87785,8 @@ function parseCliPort(args) {
87659
87785
  }
87660
87786
  return;
87661
87787
  }
87662
- function isStdioMode(args) {
87663
- return args.includes("--stdio") || process.env.MCP_STDIO === "1";
87788
+ function isHttpMode(args) {
87789
+ return args.includes("--http") || process.env.MCP_HTTP === "1";
87664
87790
  }
87665
87791
  async function readJsonBody(req) {
87666
87792
  const chunks = [];
@@ -87748,14 +87874,14 @@ process.on("uncaughtException", (err) => {
87748
87874
  });
87749
87875
  async function main() {
87750
87876
  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);
87877
+ if (isHttpMode(args)) {
87878
+ await startMcpHttpServer({ name: "testers", port: parseCliPort(args) });
87756
87879
  return;
87757
87880
  }
87758
- await startMcpHttpServer({ name: "testers", port: parseCliPort(args) });
87881
+ const { buildServer: buildServer2 } = await Promise.resolve().then(() => (init_server(), exports_server));
87882
+ const server = buildServer2();
87883
+ const transport = new StdioServerTransport;
87884
+ await server.connect(transport);
87759
87885
  }
87760
87886
  main().catch((error40) => {
87761
87887
  console.error("Failed to start testers:", error40);