archal 0.9.17 → 0.9.18

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/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const version = "0.9.17";
3
+ const version = "0.9.18";
4
4
  const archal = { version };
5
5
 
6
6
  archal.default = archal;
@@ -7382,7 +7382,7 @@ var GENERATED_TWIN_CATALOG = [
7382
7382
  icon: "AP",
7383
7383
  name: "Apify",
7384
7384
  description: "Actors, runs, datasets, key-value stores, and request queues.",
7385
- toolCount: 43,
7385
+ toolCount: 45,
7386
7386
  transport: "rest"
7387
7387
  },
7388
7388
  {
@@ -7390,7 +7390,7 @@ var GENERATED_TWIN_CATALOG = [
7390
7390
  icon: "DC",
7391
7391
  name: "Discord",
7392
7392
  description: "Guilds, channels, messages, webhooks, threads, commands, and interaction responses.",
7393
- toolCount: 68,
7393
+ toolCount: 67,
7394
7394
  transport: "both"
7395
7395
  },
7396
7396
  {
@@ -7406,7 +7406,7 @@ var GENERATED_TWIN_CATALOG = [
7406
7406
  icon: "GW",
7407
7407
  name: "Google Workspace",
7408
7408
  description: "Gmail, Calendar, Drive, Sheets, and Contacts.",
7409
- toolCount: 9,
7409
+ toolCount: 249,
7410
7410
  transport: "both"
7411
7411
  },
7412
7412
  {
@@ -7566,6 +7566,51 @@ var LIFETIME_PERIOD_RESETS_AT = new Date(Date.UTC(9999, 11, 31));
7566
7566
  var SCENARIO_USAGE_WINDOW_DAYS = 7;
7567
7567
  var SCENARIO_USAGE_WINDOW_MS = SCENARIO_USAGE_WINDOW_DAYS * 24 * 60 * 60 * 1e3;
7568
7568
  var SCENARIO_USAGE_WINDOW_SECONDS = SCENARIO_USAGE_WINDOW_DAYS * 24 * 60 * 60;
7569
+ var LLM_PRICING_USD_PER_M_TOKENS = {
7570
+ // Google Gemini (verified 2026-05-05, standard tier <=200K input tokens)
7571
+ "gemini-2.5-pro": { input: 1.25, output: 10 },
7572
+ "gemini-2.5-flash": { input: 0.3, output: 2.5 },
7573
+ // OpenAI flagship text models (verified 2026-05-21, standard short-context tier)
7574
+ "gpt-5.5": { input: 5, output: 30 },
7575
+ "gpt-5.5-pro": { input: 30, output: 180 },
7576
+ "gpt-5.4": { input: 2.5, output: 15 },
7577
+ "gpt-5.4-mini": { input: 0.75, output: 4.5 },
7578
+ "gpt-5.4-nano": { input: 0.2, output: 1.25 },
7579
+ "gpt-5.4-pro": { input: 30, output: 180 },
7580
+ "gpt-4o-mini": { input: 0.15, output: 0.6 },
7581
+ "gpt-4o": { input: 2.5, output: 10 },
7582
+ "gpt-4.1-mini": { input: 0.4, output: 1.6 },
7583
+ "gpt-4.1-nano": { input: 0.1, output: 0.4 },
7584
+ "gpt-4.1": { input: 2, output: 8 },
7585
+ // DeepSeek (verified 2026-05-05; legacy names map to v4-flash per vendor)
7586
+ "deepseek-chat": { input: 0.14, output: 0.28 },
7587
+ "deepseek-reasoner": { input: 0.14, output: 0.28 },
7588
+ "deepseek-v4-flash": { input: 0.14, output: 0.28 }
7589
+ };
7590
+ var LLM_PRICING_FAMILY_RATES = [
7591
+ { match: /^gemini-2\.5-pro/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gemini-2.5-pro"] },
7592
+ { match: /^gemini-2\.5-flash/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gemini-2.5-flash"] },
7593
+ { match: /^gpt-5\.5-pro/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.5-pro"] },
7594
+ { match: /^gpt-5\.5/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.5"] },
7595
+ { match: /^gpt-5\.4-pro/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.4-pro"] },
7596
+ { match: /^gpt-5\.4-mini/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.4-mini"] },
7597
+ { match: /^gpt-5\.4-nano/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.4-nano"] },
7598
+ { match: /^gpt-5\.4/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-5.4"] },
7599
+ { match: /^gpt-4o-mini/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-4o-mini"] },
7600
+ { match: /^gpt-4o(?!-mini)/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-4o"] },
7601
+ { match: /^gpt-4\.1-mini/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-4.1-mini"] },
7602
+ { match: /^gpt-4\.1-nano/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-4.1-nano"] },
7603
+ { match: /^gpt-4\.1(?!-mini|-nano)/i, rate: LLM_PRICING_USD_PER_M_TOKENS["gpt-4.1"] },
7604
+ { match: /^claude-opus-/i, rate: { input: 15, output: 75 } },
7605
+ { match: /^claude-haiku-/i, rate: { input: 0.8, output: 4 } },
7606
+ { match: /^claude-sonnet-/i, rate: { input: 3, output: 15 } },
7607
+ { match: /^opus-/i, rate: { input: 15, output: 75 } },
7608
+ { match: /^haiku-/i, rate: { input: 0.8, output: 4 } },
7609
+ { match: /^sonnet-/i, rate: { input: 3, output: 15 } },
7610
+ { match: /^deepseek-chat/i, rate: LLM_PRICING_USD_PER_M_TOKENS["deepseek-chat"] },
7611
+ { match: /^deepseek-reasoner/i, rate: LLM_PRICING_USD_PER_M_TOKENS["deepseek-reasoner"] },
7612
+ { match: /^deepseek-v4-flash/i, rate: LLM_PRICING_USD_PER_M_TOKENS["deepseek-v4-flash"] }
7613
+ ];
7569
7614
 
7570
7615
  // ../twins/core/src/errors.ts
7571
7616
  function errorMessage2(error48) {
@@ -35915,7 +35960,7 @@ function buildCodegenUserPrompt(twinName, setupDescription) {
35915
35960
  const declarations = SDK_DECLARATIONS[twinName];
35916
35961
  const example = SDK_EXAMPLES[twinName];
35917
35962
  if (!declarations) {
35918
- return `Twin: ${twinName}
35963
+ return `Clone: ${twinName}
35919
35964
 
35920
35965
  Setup:
35921
35966
  ${setupDescription}
@@ -35936,7 +35981,7 @@ ${example.code}
35936
35981
  `;
35937
35982
  }
35938
35983
  prompt += `## Task
35939
- Twin: ${twinName}
35984
+ Clone: ${twinName}
35940
35985
 
35941
35986
  Setup:
35942
35987
  ${setupDescription}
@@ -35962,7 +36007,7 @@ ${originalCode}
35962
36007
  Fix the code and output ONLY the corrected JavaScript. No explanations.`;
35963
36008
  }
35964
36009
  function buildSimplifiedCodegenPrompt(twinName, setupDescription) {
35965
- return `Create seed data for the "${twinName}" twin.
36010
+ return `Create seed data for the "${twinName}" clone.
35966
36011
 
35967
36012
  Use ONLY these core functions (they are already defined globally):
35968
36013
  createUser(login), createRepo/createProject/createChannel/createCustomer(name),
@@ -36724,7 +36769,7 @@ RULES:
36724
36769
  - "3 active subscriptions" \u2192 ONE subscription entry with count:3
36725
36770
  - Entity type names: user, org, team, repo, branch, issue, pr, label, milestone, release, webhook, workflow, environment, secret, code_scanning_alert, collaborator, project, page, branch_protection, board, sprint, epic, component, version, filter, dashboard, customer, product, price, subscription, invoice, payment_method, coupon, tax_rate, webhook_endpoint, charge, dispute, channel, message`;
36726
36771
  function buildPlanPrompt(twinName, setupDescription) {
36727
- return `Twin: ${twinName}
36772
+ return `Clone: ${twinName}
36728
36773
 
36729
36774
  Setup:
36730
36775
  ${setupDescription}`;
@@ -42874,6 +42919,8 @@ IMPORTANT CONSTRAINTS:
42874
42919
  - For RLS policies, use simple expressions like: USING (true) or USING (current_setting('app.user_id')::int = user_id)
42875
42920
  - Use serial or bigserial for primary keys, not uuid (unless explicitly asked)
42876
42921
  - Use simple types: text, int, boolean, timestamptz
42922
+ - Do NOT use JSON-style array literals like ["a", "b"] in INSERT values.
42923
+ Use ARRAY['a', 'b'] for SQL array columns, or quoted JSON with ::jsonb for jsonb columns.
42877
42924
  - Always include INSERT statements with realistic test data
42878
42925
 
42879
42926
 
@@ -42894,6 +42941,222 @@ INSERT INTO users (email, name, role) VALUES
42894
42941
  ALTER TABLE users ENABLE ROW LEVEL SECURITY;
42895
42942
  CREATE POLICY "users_select" ON users FOR SELECT USING (true);
42896
42943
  CREATE POLICY "users_update_own" ON users FOR UPDATE USING (id = current_setting('app.user_id', true)::int);`;
42944
+ function sqlLiteral2(value) {
42945
+ if (value === null || value === void 0) return "NULL";
42946
+ if (typeof value === "number") return Number.isFinite(value) ? String(value) : "NULL";
42947
+ if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
42948
+ return `'${String(value).replace(/'/g, "''")}'`;
42949
+ }
42950
+ function sqlIdent2(value) {
42951
+ if (!value) throw new Error("SQL identifier must not be empty");
42952
+ if (value.includes("\0")) throw new Error("SQL identifier must not contain null bytes");
42953
+ return `"${value.replace(/"/g, '""')}"`;
42954
+ }
42955
+ function sqlValueLiteral(value, columnType) {
42956
+ const type = columnType?.toLowerCase() ?? "";
42957
+ if (Array.isArray(value)) {
42958
+ if (type.includes("[]")) {
42959
+ const baseType = type.replace(/\[\].*$/, "") || "text";
42960
+ if (value.length === 0) return `ARRAY[]::${baseType}[]`;
42961
+ return `ARRAY[${value.map(sqlLiteral2).join(", ")}]`;
42962
+ }
42963
+ const json2 = sqlLiteral2(JSON.stringify(value));
42964
+ if (type.includes("jsonb")) return `${json2}::jsonb`;
42965
+ if (type.includes("json")) return `${json2}::json`;
42966
+ return json2;
42967
+ }
42968
+ if (value && typeof value === "object") {
42969
+ const json2 = sqlLiteral2(JSON.stringify(value));
42970
+ if (type.includes("jsonb")) return `${json2}::jsonb`;
42971
+ if (type.includes("json")) return `${json2}::json`;
42972
+ return json2;
42973
+ }
42974
+ return sqlLiteral2(value);
42975
+ }
42976
+ function splitSqlTopLevel(input, separator) {
42977
+ const parts = [];
42978
+ let depth = 0;
42979
+ let bracketDepth = 0;
42980
+ let inQuote = false;
42981
+ let start = 0;
42982
+ for (let i = 0; i < input.length; i++) {
42983
+ const ch = input[i];
42984
+ if (ch === void 0) continue;
42985
+ const next = i + 1 < input.length ? input[i + 1] : void 0;
42986
+ if (ch === "'") {
42987
+ if (inQuote && next === "'") {
42988
+ i += 1;
42989
+ continue;
42990
+ }
42991
+ inQuote = !inQuote;
42992
+ continue;
42993
+ }
42994
+ if (inQuote) continue;
42995
+ if (ch === "(") depth += 1;
42996
+ else if (ch === ")") depth = Math.max(0, depth - 1);
42997
+ else if (ch === "[") bracketDepth += 1;
42998
+ else if (ch === "]") bracketDepth = Math.max(0, bracketDepth - 1);
42999
+ if (depth === 0 && bracketDepth === 0 && ch === separator) {
43000
+ parts.push(input.slice(start, i).trim());
43001
+ start = i + 1;
43002
+ }
43003
+ }
43004
+ const tail = input.slice(start).trim();
43005
+ if (tail) parts.push(tail);
43006
+ return parts;
43007
+ }
43008
+ function splitSqlStatements(sql) {
43009
+ return splitSqlTopLevel(sql, ";").map((statement) => statement.trim()).filter(Boolean);
43010
+ }
43011
+ function normalizeSqlIdentifier(raw) {
43012
+ const parts = raw.split(".").map((part) => part.trim().replace(/^"|"$/g, "").replace(/""/g, '"')).filter(Boolean);
43013
+ return parts[parts.length - 1] ?? raw.trim();
43014
+ }
43015
+ function collectTableSchemas(sql) {
43016
+ const tableSchemas = /* @__PURE__ */ new Map();
43017
+ for (const statement of splitSqlStatements(sql)) {
43018
+ const match = statement.match(
43019
+ /^CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?\s+([^\s(]+)\s*\(([\s\S]*)\)$/i
43020
+ );
43021
+ if (!match?.[1] || !match[2]) continue;
43022
+ const columnTypes = /* @__PURE__ */ new Map();
43023
+ const columnOrder = [];
43024
+ for (const columnDef of splitSqlTopLevel(match[2], ",")) {
43025
+ const columnMatch = columnDef.trim().match(/^("(?:""|[^"])+"|[a-zA-Z_][a-zA-Z0-9_]*)\s+([a-zA-Z0-9_."[\]]+)/);
43026
+ if (!columnMatch?.[1] || !columnMatch[2]) continue;
43027
+ const columnName = normalizeSqlIdentifier(columnMatch[1]);
43028
+ columnTypes.set(columnName, columnMatch[2].toLowerCase());
43029
+ columnOrder.push(columnName);
43030
+ }
43031
+ tableSchemas.set(normalizeSqlIdentifier(match[1]), { columnTypes, columnOrder });
43032
+ }
43033
+ return tableSchemas;
43034
+ }
43035
+ function normalizeJsonArrayLiteral(value, columnType) {
43036
+ const trimmed = value.trim();
43037
+ if (!trimmed.startsWith("[") || !trimmed.endsWith("]")) return value;
43038
+ let parsed;
43039
+ try {
43040
+ parsed = JSON.parse(trimmed);
43041
+ } catch {
43042
+ return value;
43043
+ }
43044
+ if (!Array.isArray(parsed)) return value;
43045
+ const type = columnType?.toLowerCase() ?? "";
43046
+ if (type.includes("[]")) {
43047
+ const baseType = type.replace(/\[\].*$/, "") || "text";
43048
+ if (parsed.length === 0) return `ARRAY[]::${baseType}[]`;
43049
+ return `ARRAY[${parsed.map(sqlLiteral2).join(", ")}]`;
43050
+ }
43051
+ const json2 = sqlLiteral2(JSON.stringify(parsed));
43052
+ if (type.includes("jsonb")) return `${json2}::jsonb`;
43053
+ if (type.includes("json")) return `${json2}::json`;
43054
+ return json2;
43055
+ }
43056
+ function renderStructuredTableSql(value) {
43057
+ const tables = Array.isArray(value) ? value : value && typeof value === "object" && Array.isArray(value["tables"]) ? value["tables"] : null;
43058
+ if (!Array.isArray(tables)) return null;
43059
+ const statements = [];
43060
+ for (const table of tables) {
43061
+ if (!table || typeof table !== "object") return null;
43062
+ const record2 = table;
43063
+ const tableName = typeof record2["name"] === "string" ? record2["name"] : void 0;
43064
+ const columns = Array.isArray(record2["columns"]) ? record2["columns"] : void 0;
43065
+ if (!tableName || !columns) return null;
43066
+ const columnTypes = /* @__PURE__ */ new Map();
43067
+ const columnDefinitions = columns.map((column) => {
43068
+ if (!column || typeof column !== "object") throw new Error("invalid column");
43069
+ const columnRecord = column;
43070
+ const name = typeof columnRecord["name"] === "string" ? columnRecord["name"] : void 0;
43071
+ const rawType = typeof columnRecord["type"] === "string" ? columnRecord["type"] : "text";
43072
+ if (!name) throw new Error("invalid column name");
43073
+ const isPrimary = columnRecord["is_primary"] === true || columnRecord["primary"] === true;
43074
+ const type = isPrimary && /^(bigint|int|integer|serial|bigserial)$/i.test(rawType) ? "bigserial" : rawType;
43075
+ columnTypes.set(name, type);
43076
+ return `${sqlIdent2(name)} ${type}${isPrimary ? " PRIMARY KEY" : ""}`;
43077
+ });
43078
+ statements.push(`CREATE TABLE IF NOT EXISTS public.${sqlIdent2(tableName)} (${columnDefinitions.join(", ")});`);
43079
+ const rows = Array.isArray(record2["rows"]) ? record2["rows"] : Array.isArray(record2["data"]) ? record2["data"] : [];
43080
+ for (const row of rows) {
43081
+ if (!row || typeof row !== "object") continue;
43082
+ const entries = Object.entries(row).filter(([column]) => columnTypes.has(column));
43083
+ if (entries.length === 0) continue;
43084
+ statements.push(
43085
+ `INSERT INTO public.${sqlIdent2(tableName)} (${entries.map(([column]) => sqlIdent2(column)).join(", ")}) VALUES (${entries.map(([column, rowValue]) => sqlValueLiteral(rowValue, columnTypes.get(column))).join(", ")});`
43086
+ );
43087
+ }
43088
+ }
43089
+ return statements.length > 0 ? statements.join("\n\n") : null;
43090
+ }
43091
+ function normalizeCreateTableStatement(statement) {
43092
+ const match = statement.match(
43093
+ /^(CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?\s+[^\s(]+\s*)\(([\s\S]*)\)$/i
43094
+ );
43095
+ if (!match?.[1] || !match[2]) return statement;
43096
+ const columnDefs = splitSqlTopLevel(match[2], ",").map((columnDef) => {
43097
+ const columnMatch = columnDef.trim().match(
43098
+ /^("(?:""|[^"])+"|[a-zA-Z_][a-zA-Z0-9_]*)\s+([a-zA-Z0-9_."[\]]+)([\s\S]*)$/i
43099
+ );
43100
+ if (!columnMatch?.[2] || !columnMatch[3]) return columnDef;
43101
+ const columnType = columnMatch[2].toLowerCase();
43102
+ const rest = columnMatch[3].replace(
43103
+ /\bDEFAULT\s+(\[[\s\S]*?\])(?=\s|,|$)/i,
43104
+ (_full, value) => `DEFAULT ${normalizeJsonArrayLiteral(value, columnType)}`
43105
+ );
43106
+ return `${columnMatch[1]} ${columnMatch[2]}${rest}`;
43107
+ });
43108
+ return `${match[1]}(${columnDefs.join(", ")})`;
43109
+ }
43110
+ function normalizeSupabaseSql(sql) {
43111
+ const tableSchemas = collectTableSchemas(sql);
43112
+ return splitSqlStatements(sql).map((statement) => {
43113
+ if (/^CREATE\s+TABLE/i.test(statement)) return normalizeCreateTableStatement(statement);
43114
+ const match = statement.match(/^INSERT\s+INTO\s+([^\s(]+)\s*\(([^)]+)\)\s*VALUES\s*([\s\S]*)$/i) ?? statement.match(/^INSERT\s+INTO\s+([^\s(]+)\s+VALUES\s*([\s\S]*)$/i);
43115
+ if (!match?.[1]) return statement;
43116
+ const tableName = normalizeSqlIdentifier(match[1]);
43117
+ const hasColumnList = match.length === 4;
43118
+ const valuesSql = hasColumnList ? match[3] : match[2];
43119
+ if (!valuesSql) return statement;
43120
+ const schema = tableSchemas.get(tableName);
43121
+ const columns = hasColumnList ? splitSqlTopLevel(match[2] ?? "", ",").map(normalizeSqlIdentifier) : schema?.columnOrder ?? [];
43122
+ const tuples = [];
43123
+ let depth = 0;
43124
+ let bracketDepth = 0;
43125
+ let inQuote = false;
43126
+ let tupleStart = -1;
43127
+ for (let i = 0; i < valuesSql.length; i++) {
43128
+ const ch = valuesSql[i];
43129
+ if (ch === void 0) continue;
43130
+ const next = i + 1 < valuesSql.length ? valuesSql[i + 1] : void 0;
43131
+ if (ch === "'") {
43132
+ if (inQuote && next === "'") {
43133
+ i += 1;
43134
+ continue;
43135
+ }
43136
+ inQuote = !inQuote;
43137
+ }
43138
+ if (inQuote) continue;
43139
+ if (ch === "[") bracketDepth += 1;
43140
+ else if (ch === "]") bracketDepth = Math.max(0, bracketDepth - 1);
43141
+ else if (ch === "(" && bracketDepth === 0) {
43142
+ if (depth === 0) tupleStart = i + 1;
43143
+ depth += 1;
43144
+ } else if (ch === ")" && bracketDepth === 0) {
43145
+ depth -= 1;
43146
+ if (depth === 0 && tupleStart >= 0) {
43147
+ tuples.push(valuesSql.slice(tupleStart, i));
43148
+ tupleStart = -1;
43149
+ }
43150
+ }
43151
+ }
43152
+ if (tuples.length === 0) return statement;
43153
+ const normalizedTuples = tuples.map((tuple2) => {
43154
+ const values = splitSqlTopLevel(tuple2, ",").map((value, index) => normalizeJsonArrayLiteral(value, schema?.columnTypes.get(columns[index] ?? "")));
43155
+ return `(${values.join(", ")})`;
43156
+ });
43157
+ return hasColumnList ? `INSERT INTO ${match[1]} (${match[2]}) VALUES ${normalizedTuples.join(", ")}` : `INSERT INTO ${match[1]} VALUES ${normalizedTuples.join(", ")}`;
43158
+ }).join(";\n") + ";";
43159
+ }
42897
43160
  function extractSupabaseSql(response) {
42898
43161
  let sql = response.trim();
42899
43162
  if (sql.startsWith("```")) {
@@ -42902,24 +43165,35 @@ function extractSupabaseSql(response) {
42902
43165
  if (sql.startsWith("{")) {
42903
43166
  try {
42904
43167
  const parsed = JSON.parse(sql);
43168
+ const structuredSql = renderStructuredTableSql(parsed);
43169
+ if (structuredSql) return normalizeSupabaseSql(structuredSql);
42905
43170
  const extracted = parsed["sql"] ?? parsed["query"] ?? parsed["script"] ?? parsed["content"];
42906
- if (extracted && typeof extracted === "string") return extracted;
43171
+ if (extracted && typeof extracted === "string") return normalizeSupabaseSql(extracted);
43172
+ } catch {
43173
+ }
43174
+ }
43175
+ if (sql.startsWith('"')) {
43176
+ try {
43177
+ const parsed = JSON.parse(sql);
43178
+ if (typeof parsed === "string") return normalizeSupabaseSql(parsed);
42907
43179
  } catch {
42908
43180
  }
42909
43181
  }
42910
43182
  if (sql.startsWith("[")) {
42911
43183
  try {
42912
43184
  const parsed = JSON.parse(sql);
43185
+ const structuredSql = renderStructuredTableSql(parsed);
43186
+ if (structuredSql) return normalizeSupabaseSql(structuredSql);
42913
43187
  const parts = [];
42914
43188
  for (const item of parsed) {
42915
43189
  const s = item["sql"] ?? item["query"] ?? item["script"];
42916
43190
  if (s && typeof s === "string") parts.push(s);
42917
43191
  }
42918
- if (parts.length > 0) return parts.join("\n\n");
43192
+ if (parts.length > 0) return normalizeSupabaseSql(parts.join("\n\n"));
42919
43193
  } catch {
42920
43194
  }
42921
43195
  }
42922
- return sql;
43196
+ return normalizeSupabaseSql(sql);
42923
43197
  }
42924
43198
 
42925
43199
  // ../packages/seedgen/src/runtime/session-context.ts
@@ -43264,7 +43538,7 @@ async function enrichSeedWithLlm(seed, twinName, setupDescription, deadline, coo
43264
43538
  try {
43265
43539
  const response = await callCodegenLlm({
43266
43540
  systemPrompt: ENRICH_SYSTEM_PROMPT,
43267
- userPrompt: `Twin: ${twinName}
43541
+ userPrompt: `Clone: ${twinName}
43268
43542
 
43269
43543
  Setup description:
43270
43544
  ${setupDescription}
@@ -44442,6 +44716,10 @@ var GOOGLE_WORKSPACE_BOOTSTRAP_SCOPES = [
44442
44716
  "https://www.googleapis.com/auth/drive.readonly",
44443
44717
  "https://www.googleapis.com/auth/contacts.readonly"
44444
44718
  ];
44719
+ var GOOGLE_WORKSPACE_SYNTHETIC_EMAIL = "self@local.invalid";
44720
+ function isSyntheticGoogleWorkspaceEmail(email3) {
44721
+ return email3 === GOOGLE_WORKSPACE_SYNTHETIC_EMAIL;
44722
+ }
44445
44723
  function googleWorkspaceEmailEntities(intent) {
44446
44724
  if (!intent || intent.twinName !== "google-workspace") return [];
44447
44725
  return intent.entities.filter((entity) => entity.kind === "email" && entity.key === "address" && typeof entity.value === "string" || entity.kind === "account" && entity.key === "email" && typeof entity.value === "string").map((entity) => normalizedEmail(entity.value)).filter((value) => Boolean(value));
@@ -44469,6 +44747,32 @@ function googleWorkspaceReferencedEmails(seed) {
44469
44747
  }
44470
44748
  return emails;
44471
44749
  }
44750
+ function googleWorkspaceBootstrapEmail(intentEmails, referencedEmails) {
44751
+ return intentEmails.find((email3) => !isSyntheticGoogleWorkspaceEmail(email3)) ?? referencedEmails.find((email3) => !isSyntheticGoogleWorkspaceEmail(email3)) ?? "user@example.com";
44752
+ }
44753
+ function rewriteSyntheticGoogleWorkspaceAccountRefs(seed, email3) {
44754
+ const collections = [
44755
+ "calendars",
44756
+ "calendarEvents",
44757
+ "gmailThreads",
44758
+ "gmailMessages",
44759
+ "gmailDrafts",
44760
+ "gmailAttachments",
44761
+ "gmailHistory",
44762
+ "driveFiles",
44763
+ "contacts",
44764
+ "googleAuthTokens"
44765
+ ];
44766
+ for (const collection of collections) {
44767
+ for (const item of seed[collection] ?? []) {
44768
+ const record2 = asRecord(item);
44769
+ if (!record2) continue;
44770
+ if (isSyntheticGoogleWorkspaceEmail(normalizedEmail(record2["accountEmail"]))) {
44771
+ record2["accountEmail"] = email3;
44772
+ }
44773
+ }
44774
+ }
44775
+ }
44472
44776
  function googleWorkspaceHasCalendarSurface(intent) {
44473
44777
  return intent.extractedSlots["workspace.surface.calendar"] === true || /\b(calendar|event|events|meeting|meetings|invite|invites)\b/i.test(intent.setupSummary);
44474
44778
  }
@@ -44503,6 +44807,15 @@ function ensureGoogleWorkspaceAccount(accounts, email3, primary) {
44503
44807
  primary
44504
44808
  });
44505
44809
  }
44810
+ function replaceGoogleWorkspaceAccount(account, email3) {
44811
+ account["accountId"] = "acct_primary";
44812
+ account["email"] = email3;
44813
+ account["displayName"] = "Primary Account";
44814
+ account["givenName"] = "Primary";
44815
+ account["familyName"] = "Account";
44816
+ account["timezone"] = "America/Los_Angeles";
44817
+ account["primary"] = true;
44818
+ }
44506
44819
  function ensureGoogleWorkspaceAuthToken(authTokens, email3) {
44507
44820
  if (authTokens.some((token) => normalizedEmail(token["accountEmail"]) === email3)) return;
44508
44821
  const localPart = email3.split("@")[0] ?? email3;
@@ -44522,7 +44835,8 @@ function ensureGoogleWorkspaceAuthToken(authTokens, email3) {
44522
44835
  function ensureGoogleWorkspacePrimaryCalendar(calendars, accountEmail) {
44523
44836
  const existingPrimary = calendars.find((calendar) => calendar["calendarId"] === "primary");
44524
44837
  if (existingPrimary) {
44525
- existingPrimary["accountEmail"] = normalizedEmail(existingPrimary["accountEmail"]) ?? accountEmail;
44838
+ const existingEmail = normalizedEmail(existingPrimary["accountEmail"]);
44839
+ existingPrimary["accountEmail"] = !existingEmail || isSyntheticGoogleWorkspaceEmail(existingEmail) ? accountEmail : existingEmail;
44526
44840
  existingPrimary["primary"] = true;
44527
44841
  return "primary";
44528
44842
  }
@@ -44547,6 +44861,15 @@ function ensureGoogleWorkspaceCalendarRows(mergedSeed) {
44547
44861
  for (const item of mergedSeed["calendarEvents"] ?? []) {
44548
44862
  const event = asRecord(item);
44549
44863
  if (!event) continue;
44864
+ if (typeof event["summary"] !== "string") {
44865
+ event["summary"] = "Calendar event";
44866
+ }
44867
+ if (typeof event["description"] !== "string") {
44868
+ event["description"] = "";
44869
+ }
44870
+ if (typeof event["location"] !== "string") {
44871
+ event["location"] = "";
44872
+ }
44550
44873
  const calendarId = typeof event["calendarId"] === "string" && event["calendarId"].trim() ? event["calendarId"].trim() : "primary";
44551
44874
  const accountEmail = normalizedEmail(event["accountEmail"]) ?? "self@local.invalid";
44552
44875
  if (existingCalendarIds.has(calendarId)) continue;
@@ -44586,21 +44909,28 @@ function ensureGoogleWorkspaceCalendarEvidence(mergedSeed, intent, accountEmail)
44586
44909
  organizerEmail: accountEmail,
44587
44910
  attendeeEmails: [],
44588
44911
  conferenceUrl: null,
44589
- extendedPropertiesShared: null
44912
+ extendedPropertiesShared: {}
44590
44913
  });
44591
44914
  }
44592
44915
  function ensureGoogleWorkspaceScenarioAccounts(mergedSeed, intent) {
44593
44916
  if (!intent || intent.twinName !== "google-workspace") return mergedSeed;
44594
44917
  const accounts = ensureArray(mergedSeed, "accounts");
44595
44918
  const authTokens = ensureArray(mergedSeed, "googleAuthTokens");
44919
+ const intentEmails = googleWorkspaceEmailEntities(intent);
44920
+ let referencedEmails = googleWorkspaceReferencedEmails(mergedSeed);
44921
+ const bootstrapEmail = googleWorkspaceBootstrapEmail(intentEmails, referencedEmails);
44596
44922
  if (accounts.length === 0) {
44597
- ensureGoogleWorkspaceAccount(accounts, "self@local.invalid", true);
44923
+ ensureGoogleWorkspaceAccount(accounts, bootstrapEmail, true);
44924
+ } else if (accounts.length === 1 && isSyntheticGoogleWorkspaceEmail(normalizedEmail(accounts[0]?.["email"]))) {
44925
+ replaceGoogleWorkspaceAccount(accounts[0], bootstrapEmail);
44598
44926
  }
44599
- const primaryEmail = normalizedEmail(accounts.find((account) => account["primary"] === true)?.["email"]) ?? normalizedEmail(accounts[0]?.["email"]) ?? "self@local.invalid";
44927
+ rewriteSyntheticGoogleWorkspaceAccountRefs(mergedSeed, bootstrapEmail);
44928
+ referencedEmails = googleWorkspaceReferencedEmails(mergedSeed);
44929
+ const primaryEmail = normalizedEmail(accounts.find((account) => account["primary"] === true)?.["email"]) ?? normalizedEmail(accounts[0]?.["email"]) ?? GOOGLE_WORKSPACE_SYNTHETIC_EMAIL;
44600
44930
  ensureGoogleWorkspaceAuthToken(authTokens, primaryEmail);
44601
44931
  const requiredEmails = Array.from(/* @__PURE__ */ new Set([
44602
- ...googleWorkspaceEmailEntities(intent),
44603
- ...googleWorkspaceReferencedEmails(mergedSeed),
44932
+ ...intentEmails,
44933
+ ...referencedEmails,
44604
44934
  ...accounts.map((account) => normalizedEmail(account["email"])).filter((value) => Boolean(value))
44605
44935
  ]));
44606
44936
  for (const email3 of requiredEmails) {
@@ -44627,7 +44957,7 @@ var DynamicSeedError = class extends Error {
44627
44957
  const details = validationErrors.length > 0 ? `:
44628
44958
  ${validationErrors.map((e) => ` - ${e}`).join("\n")}` : ".";
44629
44959
  const suffix = hint ?? "\n\nHint: Run `archal login` and retry. For deterministic reruns, use `--replay-seed <path>` with a previously saved managed seed snapshot.";
44630
- super(`Dynamic seed generation failed for twin "${twinName}"${details}${suffix}`);
44960
+ super(`Dynamic seed generation failed for clone "${twinName}"${details}${suffix}`);
44631
44961
  this.name = "DynamicSeedError";
44632
44962
  this.twinName = twinName;
44633
44963
  this.validationErrors = validationErrors;
@@ -44693,7 +45023,7 @@ ${fkDetails}
44693
45023
  // ../packages/seedgen/src/runner/seed/dynamic-generator.ts
44694
45024
  var SEED_CODEGEN_MAX_TOKENS = 4096;
44695
45025
  var MAX_CODEGEN_ATTEMPTS = 3;
44696
- var SEED_CACHE_PROMPT_TEMPLATE_VERSION = 4;
45026
+ var SEED_CACHE_PROMPT_TEMPLATE_VERSION = 5;
44697
45027
  var CODEGEN_TOTAL_BUDGET_MS = 12e4;
44698
45028
  function buildSeedCacheContext(twinName, systemPromptHash, intent, context) {
44699
45029
  return {
@@ -45222,8 +45552,8 @@ async function generateDynamicSeed(twinName, baseSeedName, baseSeedData, setupDe
45222
45552
  ],
45223
45553
  `
45224
45554
 
45225
- Hint: Dynamic seed generation failed for the "${twinName}" twin. Try adding a \`seed: <name>\` line to your scenario's Config section to use a pre-built seed instead.
45226
- Use a documented seed name for ${twinName}, or inspect the twin package assets in this repo.`
45555
+ Hint: Dynamic seed generation failed for the "${twinName}" clone. Try adding a \`seed: <name>\` line to your scenario's Config section to use a pre-built seed instead.
45556
+ Use a documented seed name for ${twinName}, or inspect the bundled clone assets in this repo.`
45227
45557
  );
45228
45558
  }
45229
45559
  // Annotate the CommonJS export names for ESM import in node: