@agent-native/core 0.11.2 → 0.11.4
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/agent/index.d.ts +1 -1
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/production-agent.d.ts +29 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +57 -2
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +12 -8
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +1 -1
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ConnectBuilderCard.d.ts +3 -3
- package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
- package/dist/client/ConnectBuilderCard.js +5 -6
- package/dist/client/ConnectBuilderCard.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +8 -6
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.js +2 -0
- package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
- package/dist/client/composer/TiptapComposer.js +2 -2
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.js +36 -4
- package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
- package/dist/client/route-chunk-recovery.d.ts.map +1 -1
- package/dist/client/route-chunk-recovery.js +11 -0
- package/dist/client/route-chunk-recovery.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +2 -1
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts +5 -3
- package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/client/settings/useBuilderStatus.js +16 -1
- package/dist/client/settings/useBuilderStatus.js.map +1 -1
- package/dist/extensions/actions.js +1 -1
- package/dist/extensions/actions.js.map +1 -1
- package/dist/extensions/html-shell.d.ts.map +1 -1
- package/dist/extensions/html-shell.js +47 -1
- package/dist/extensions/html-shell.js.map +1 -1
- package/dist/scripts/db/exec.d.ts.map +1 -1
- package/dist/scripts/db/exec.js +11 -3
- package/dist/scripts/db/exec.js.map +1 -1
- package/dist/scripts/db/scoping.d.ts +2 -1
- package/dist/scripts/db/scoping.d.ts.map +1 -1
- package/dist/scripts/db/scoping.js +12 -8
- package/dist/scripts/db/scoping.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +6 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +6 -2
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/builder-browser.d.ts +2 -0
- package/dist/server/builder-browser.d.ts.map +1 -1
- package/dist/server/builder-browser.js +24 -0
- package/dist/server/builder-browser.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +46 -29
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/index.d.ts +3 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/request-context.d.ts +11 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js.map +1 -1
- package/dist/templates/workspace-core/AGENTS.md +19 -3
- package/dist/templates/workspace-root/AGENTS.md +20 -0
- package/dist/templates/workspace-root/README.md +6 -0
- package/docs/content/extensions.md +12 -11
- package/package.json +1 -1
- package/src/templates/workspace-core/AGENTS.md +19 -3
- package/src/templates/workspace-root/AGENTS.md +20 -0
- package/src/templates/workspace-root/README.md +6 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../src/scripts/db/exec.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Core script: db-exec\n *\n * Execute write SQL statements (INSERT, UPDATE, DELETE, REPLACE)\n * against a SQLite or Postgres database.\n *\n * In production mode, temporary views scope UPDATE/DELETE to the current\n * user's data (AGENT_USER_EMAIL / AGENT_ORG_ID). For INSERT, the\n * `owner_email` and `org_id` columns are auto-injected if the target\n * table uses the ownership convention.\n *\n * Usage:\n * pnpm action db-exec --sql \"UPDATE forms SET status=? WHERE id=?\" [--args '[\"published\",\"abc\"]'] [--db path]\n * pnpm action db-exec --statements '[{\"sql\":\"INSERT INTO notes (id,title) VALUES (?,?)\",\"args\":[\"n1\",\"One\"]},{\"sql\":\"UPDATE counters SET value=value+1 WHERE key=?\",\"args\":[\"notes\"]}]'\n */\n\nimport path from \"path\";\nimport { createClient } from \"@libsql/client\";\nimport { getDatabaseUrl, getDatabaseAuthToken } from \"../../db/client.js\";\nimport { parseArgs, fail } from \"../utils.js\";\nimport {\n buildScopingPostgres,\n buildScopingSqlite,\n type ScopingContext,\n} from \"./scoping.js\";\nimport { assertNoSensitiveFrameworkTables } from \"./safety.js\";\n\nfunction isPostgresUrl(url: string): boolean {\n return url.startsWith(\"postgres://\") || url.startsWith(\"postgresql://\");\n}\n\ninterface DbExecStatement {\n sql: string;\n args: unknown[];\n}\n\ninterface DbExecResult {\n index: number;\n sql: string;\n changes?: number;\n lastInsertRowid?: bigint | number;\n rows?: Record<string, unknown>[];\n}\n\nfunction parseSqlArgs(raw: string | undefined, label = \"--args\"): unknown[] {\n if (!raw) return [];\n try {\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) return parsed;\n } catch {\n // Fall through to the shared error below.\n }\n fail(`${label} must be a JSON array`);\n}\n\nfunction parseStatements(parsed: Record<string, string>): DbExecStatement[] {\n if (parsed.statements) {\n if (parsed.sql) {\n fail(\"Pass either --sql or --statements, not both.\");\n }\n let raw: unknown;\n try {\n raw = JSON.parse(parsed.statements);\n } catch {\n fail(\n '--statements must be a JSON array of {\"sql\": string, \"args\"?: unknown[]} objects',\n );\n }\n if (!Array.isArray(raw) || raw.length === 0) {\n fail(\"--statements must be a non-empty JSON array\");\n }\n return raw.map((entry, index) => {\n if (\n !entry ||\n typeof entry !== \"object\" ||\n typeof (entry as any).sql !== \"string\" ||\n !(entry as any).sql.trim()\n ) {\n fail(`Statement ${index + 1} must include a non-empty sql string`);\n }\n const args = (entry as any).args;\n if (args != null && !Array.isArray(args)) {\n fail(`Statement ${index + 1} args must be a JSON array`);\n }\n return { sql: (entry as any).sql, args: args ?? [] };\n });\n }\n\n if (!parsed.sql) {\n fail(\n '--sql is required unless --statements is provided. Example: --sql \"UPDATE forms SET status=? WHERE id=?\" --args \\'[\"published\",\"abc\"]\\'',\n );\n }\n return [{ sql: parsed.sql, args: parseSqlArgs(parsed.args) }];\n}\n\nfunction stripLeadingSqlComments(sql: string): string {\n return sql\n .replace(/^\\s*--[^\\n]*\\n/gm, \"\")\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .trim();\n}\n\nfunction hasAdditionalStatement(sql: string): boolean {\n let state: \"normal\" | \"single\" | \"double\" | \"line-comment\" | \"block-comment\" =\n \"normal\";\n\n for (let i = 0; i < sql.length; i++) {\n const ch = sql[i];\n const next = sql[i + 1];\n\n if (state === \"line-comment\") {\n if (ch === \"\\n\") state = \"normal\";\n continue;\n }\n if (state === \"block-comment\") {\n if (ch === \"*\" && next === \"/\") {\n i++;\n state = \"normal\";\n }\n continue;\n }\n if (state === \"single\") {\n if (ch === \"'\" && next === \"'\") {\n i++;\n } else if (ch === \"'\") {\n state = \"normal\";\n }\n continue;\n }\n if (state === \"double\") {\n if (ch === '\"' && next === '\"') {\n i++;\n } else if (ch === '\"') {\n state = \"normal\";\n }\n continue;\n }\n\n if (ch === \"-\" && next === \"-\") {\n i++;\n state = \"line-comment\";\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n i++;\n state = \"block-comment\";\n continue;\n }\n if (ch === \"'\") {\n state = \"single\";\n continue;\n }\n if (ch === '\"') {\n state = \"double\";\n continue;\n }\n if (ch === \";\") {\n return sql.slice(i + 1).trim().length > 0;\n }\n }\n return false;\n}\n\nfunction normalizeUserSql(sql: string, index: number): string {\n const stripped = stripLeadingSqlComments(sql);\n if (!stripped) {\n fail(`Statement ${index} is empty`);\n }\n if (hasAdditionalStatement(stripped)) {\n fail(\n `Statement ${index} contains multiple SQL statements. Use --statements for batches so each write can be validated and run transactionally.`,\n );\n }\n return stripped.replace(/;\\s*$/, \"\");\n}\n\nfunction validateWriteSql(sql: string, index: number): string {\n const normalized = normalizeUserSql(sql, index);\n const upper = normalized.toUpperCase();\n const allowed = [\"INSERT\", \"UPDATE\", \"DELETE\", \"REPLACE\"];\n const blocked = [\"SELECT\", \"WITH\", \"EXPLAIN\", \"PRAGMA\"];\n\n if (blocked.some((kw) => upper.startsWith(kw))) {\n fail(\n `Statement ${index}: use db-query for SELECT/read statements. db-exec is for writes only.`,\n );\n }\n if (upper.startsWith(\"CREATE\") || upper.startsWith(\"ALTER\")) {\n fail(\n `Statement ${index}: schema changes are not allowed through db-exec. Additive schema changes must go through reviewed migrations/startup code, not ad-hoc agent SQL.`,\n );\n }\n if (!allowed.some((kw) => upper.startsWith(kw))) {\n fail(\n `Statement ${index}: only ${allowed.join(\", \")} statements are allowed. ` +\n `Dangerous operations like DROP, ATTACH, VACUUM, DETACH, CREATE, and ALTER are blocked.`,\n );\n }\n assertNoSensitiveFrameworkTables(normalized, \"write\");\n return normalized;\n}\n\nfunction convertQuestionMarksToPostgresParams(sql: string): string {\n let index = 0;\n let out = \"\";\n let state: \"normal\" | \"single\" | \"double\" | \"line-comment\" | \"block-comment\" =\n \"normal\";\n\n for (let i = 0; i < sql.length; i++) {\n const ch = sql[i];\n const next = sql[i + 1];\n\n if (state === \"line-comment\") {\n out += ch;\n if (ch === \"\\n\") state = \"normal\";\n continue;\n }\n\n if (state === \"block-comment\") {\n out += ch;\n if (ch === \"*\" && next === \"/\") {\n out += next;\n i++;\n state = \"normal\";\n }\n continue;\n }\n\n if (state === \"single\") {\n out += ch;\n if (ch === \"'\" && next === \"'\") {\n out += next;\n i++;\n } else if (ch === \"'\") {\n state = \"normal\";\n }\n continue;\n }\n\n if (state === \"double\") {\n out += ch;\n if (ch === '\"' && next === '\"') {\n out += next;\n i++;\n } else if (ch === '\"') {\n state = \"normal\";\n }\n continue;\n }\n\n if (ch === \"-\" && next === \"-\") {\n out += ch + next;\n i++;\n state = \"line-comment\";\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n out += ch + next;\n i++;\n state = \"block-comment\";\n continue;\n }\n if (ch === \"'\") {\n out += ch;\n state = \"single\";\n continue;\n }\n if (ch === '\"') {\n out += ch;\n state = \"double\";\n continue;\n }\n if (ch === \"?\") {\n index++;\n out += `$${index}`;\n continue;\n }\n out += ch;\n }\n\n return out;\n}\n\nfunction normalizePostgresSql(sql: string, args: unknown[]): string {\n if (args.length === 0 || /\\$\\d+\\b/.test(sql)) return sql;\n return convertQuestionMarksToPostgresParams(sql);\n}\n\n/**\n * For INSERT statements targeting a table with owner_email / org_id columns,\n * auto-inject the current user's email and org ID if not already present.\n *\n * Handles the explicit column list form:\n * INSERT INTO table (col1, col2) VALUES (val1, val2)\n */\nfunction injectOwnership(sql: string, scoping: ScopingContext): string {\n if (!scoping.active) return sql;\n\n const upper = sql\n .replace(/^\\s*--[^\\n]*\\n/gm, \"\")\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .trim()\n .toUpperCase();\n if (!upper.startsWith(\"INSERT\")) return sql;\n\n // Extract table name: INSERT INTO <table> ...\n const match = sql.match(/INSERT\\s+INTO\\s+[\"']?(\\w+)[\"']?/i);\n if (!match) return sql;\n\n const tableName = match[1];\n\n // Determine which columns to inject\n const injections: { col: string; value: string }[] = [];\n\n if (\n scoping.userEmail &&\n scoping.ownerEmailTables.has(tableName) &&\n !/owner_email/i.test(sql)\n ) {\n injections.push({\n col: \"owner_email\",\n value: `'${scoping.userEmail.replace(/'/g, \"''\")}'`,\n });\n }\n\n if (\n scoping.orgId &&\n scoping.orgIdTables.has(tableName) &&\n !/org_id/i.test(sql)\n ) {\n injections.push({\n col: \"org_id\",\n value: `'${scoping.orgId.replace(/'/g, \"''\")}'`,\n });\n }\n\n if (injections.length === 0) return sql;\n\n // Try to inject into explicit column list: INSERT INTO t (cols) VALUES (vals)\n const colListMatch = sql.match(\n /(INSERT\\s+INTO\\s+[\"']?\\w+[\"']?\\s*)\\(([^)]+)\\)(\\s*VALUES\\s*)\\(([^)]+)\\)/i,\n );\n if (colListMatch) {\n const [, prefix, cols, valueKeyword, vals] = colListMatch;\n const extraCols = injections.map((i) => i.col).join(\", \");\n const extraVals = injections.map((i) => i.value).join(\", \");\n return `${prefix}(${cols}, ${extraCols})${valueKeyword}(${vals}, ${extraVals})`;\n }\n\n return sql;\n}\n\nfunction escapeSqlString(value: string): string {\n return value.replace(/'/g, \"''\");\n}\n\nfunction sqliteScopePredicate(\n tableName: string,\n scoping: ScopingContext,\n): string | null {\n if (tableName === \"tool_data\" && scoping.userEmail) {\n const userClause = `(scope = 'user' AND owner_email = '${escapeSqlString(scoping.userEmail)}')`;\n const orgClause = scoping.orgId\n ? ` OR (scope = 'org' AND org_id = '${escapeSqlString(scoping.orgId)}')`\n : \"\";\n return `(${userClause}${orgClause})`;\n }\n\n const clauses: string[] = [];\n if (scoping.userEmail && scoping.ownerEmailTables.has(tableName)) {\n clauses.push(`owner_email = '${escapeSqlString(scoping.userEmail)}'`);\n }\n if (scoping.orgId && scoping.orgIdTables.has(tableName)) {\n clauses.push(`org_id = '${escapeSqlString(scoping.orgId)}'`);\n }\n return clauses.length > 0 ? clauses.join(\" AND \") : null;\n}\n\nfunction splitReturning(sql: string): { body: string; returning: string } {\n const match = /\\bRETURNING\\b/i.exec(sql);\n if (!match) return { body: sql, returning: \"\" };\n return {\n body: sql.slice(0, match.index).trimEnd(),\n returning: sql.slice(match.index),\n };\n}\n\nfunction addSqliteScopeToWhere(sql: string, predicate: string): string {\n const { body, returning } = splitReturning(sql);\n const whereMatch = /\\bWHERE\\b/i.exec(body);\n const scoped = whereMatch\n ? `${body.slice(0, whereMatch.index)}WHERE ${predicate} AND (${body.slice(whereMatch.index + whereMatch[0].length).trim()})`\n : `${body} WHERE ${predicate}`;\n return returning ? `${scoped} ${returning}` : scoped;\n}\n\nfunction qualifySqliteWrite(sql: string, scoping: ScopingContext): string {\n if (!scoping.active) return sql;\n\n const updateMatch = sql.match(/^\\s*UPDATE\\s+(?:\"([^\"]+)\"|'([^']+)'|(\\w+))/i);\n if (updateMatch) {\n const tableName = updateMatch[1] ?? updateMatch[2] ?? updateMatch[3];\n const predicate = sqliteScopePredicate(tableName, scoping);\n if (!predicate) return sql;\n const qualified = sql.replace(\n /^\\s*UPDATE\\s+(?:\"[^\"]+\"|'[^']+'|\\w+)/i,\n `UPDATE main.\"${tableName.replace(/\"/g, '\"\"')}\"`,\n );\n return addSqliteScopeToWhere(qualified, predicate);\n }\n\n const deleteMatch = sql.match(\n /^\\s*DELETE\\s+FROM\\s+(?:\"([^\"]+)\"|'([^']+)'|(\\w+))/i,\n );\n if (deleteMatch) {\n const tableName = deleteMatch[1] ?? deleteMatch[2] ?? deleteMatch[3];\n const predicate = sqliteScopePredicate(tableName, scoping);\n if (!predicate) return sql;\n const qualified = sql.replace(\n /^\\s*DELETE\\s+FROM\\s+(?:\"[^\"]+\"|'[^']+'|\\w+)/i,\n `DELETE FROM main.\"${tableName.replace(/\"/g, '\"\"')}\"`,\n );\n return addSqliteScopeToWhere(qualified, predicate);\n }\n\n return sql.replace(\n /^\\s*(INSERT\\s+INTO|REPLACE\\s+INTO)\\s+(?:\"([^\"]+)\"|'([^']+)'|(\\w+))/i,\n (match, keyword, quotedDouble, quotedSingle, bare) => {\n const tableName = quotedDouble ?? quotedSingle ?? bare;\n if (\n !scoping.ownerEmailTables.has(tableName) &&\n !scoping.orgIdTables.has(tableName)\n ) {\n return match;\n }\n return `${keyword} main.\"${tableName.replace(/\"/g, '\"\"')}\"`;\n },\n );\n}\n\nfunction printResult(\n sql: string,\n result: {\n count?: number;\n rowsAffected?: number;\n lastInsertRowid?: bigint | number;\n rows?: Record<string, unknown>[];\n },\n hasReturning: boolean,\n format?: string,\n) {\n if (hasReturning && result.rows && result.rows.length > 0) {\n if (format === \"json\") {\n console.log(\n JSON.stringify(\n { sql, rows: result.rows, count: result.rows.length },\n null,\n 2,\n ),\n );\n return;\n }\n console.log(`Executed: ${sql}`);\n console.log(`Returned ${result.rows.length} row(s):`);\n console.log(JSON.stringify(result.rows, null, 2));\n } else {\n const changes = result.count ?? result.rowsAffected ?? 0;\n if (format === \"json\") {\n console.log(\n JSON.stringify(\n {\n sql,\n changes,\n ...(result.lastInsertRowid && changes > 0\n ? { lastInsertRowid: Number(result.lastInsertRowid) }\n : {}),\n },\n null,\n 2,\n ),\n );\n return;\n }\n console.log(`Executed: ${sql}`);\n console.log(`Changes: ${changes}`);\n if (result.lastInsertRowid && changes > 0) {\n console.log(`Last Insert Row ID: ${result.lastInsertRowid}`);\n }\n if (changes === 0) {\n console.log(zeroChangesHint(sql));\n }\n }\n}\n\n/**\n * Hint emitted when an UPDATE/DELETE/REPLACE matches zero rows. Matches the\n * wording used by db-patch's \"no rows matched\" error so the agent gets the\n * same scoping nudge from both tools — without this hint, the agent reports\n * \"Changes: 0\" as success and the user sees no UI update because the row\n * either didn't exist or wasn't visible to the current user under per-user\n * scoping.\n */\nfunction zeroChangesHint(sql: string): string {\n const upper = sql.toUpperCase(); // leading whitespace already stripped by normalizeUserSql\n if (upper.startsWith(\"INSERT\")) {\n // INSERT changes=0 means INSERT OR IGNORE skipped a duplicate — different\n // failure mode, not a scoping issue.\n return \"Hint: 0 rows inserted. The row likely violated a UNIQUE / PRIMARY KEY constraint and was skipped (INSERT OR IGNORE).\";\n }\n return (\n \"Hint: 0 rows changed. The WHERE clause matched no rows — either the row \" +\n \"doesn't exist, or it exists but is owned by a different user (per-user \" +\n \"and per-org scoping is automatic for db-exec).\"\n );\n}\n\nfunction printBatchResult(results: DbExecResult[], format?: string): void {\n if (results.length === 1) {\n const result = results[0];\n printResult(\n result.sql,\n {\n count: result.changes,\n rowsAffected: result.changes,\n lastInsertRowid: result.lastInsertRowid,\n rows: result.rows,\n },\n Boolean(result.rows?.length),\n format,\n );\n return;\n }\n\n const totalChanges = results.reduce(\n (sum, result) => sum + Number(result.changes ?? 0),\n 0,\n );\n\n if (format === \"json\") {\n console.log(\n JSON.stringify(\n {\n statements: results.map((result) => ({\n index: result.index,\n sql: result.sql,\n changes: result.changes ?? 0,\n ...(result.lastInsertRowid && Number(result.changes ?? 0) > 0\n ? { lastInsertRowid: Number(result.lastInsertRowid) }\n : {}),\n ...(result.rows?.length\n ? { rows: result.rows, count: result.rows.length }\n : {}),\n })),\n changes: totalChanges,\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n console.log(`Executed ${results.length} statements in one transaction.`);\n for (const result of results) {\n if (result.rows?.length) {\n console.log(`[${result.index}] Returned ${result.rows.length} row(s):`);\n console.log(JSON.stringify(result.rows, null, 2));\n } else {\n const changes = Number(result.changes ?? 0);\n console.log(`[${result.index}] Changes: ${changes}`);\n if (changes === 0) {\n console.log(`[${result.index}] ${zeroChangesHint(result.sql)}`);\n }\n }\n }\n console.log(`Total changes: ${totalChanges}`);\n}\n\nfunction sqliteRowsToObjects(\n rows: any[],\n columns: string[],\n): Record<string, unknown>[] {\n return rows.map((row) => {\n if (!Array.isArray(row) && row && typeof row === \"object\") {\n return { ...row };\n }\n const obj: Record<string, unknown> = {};\n for (let i = 0; i < columns.length; i++) {\n obj[columns[i]] = row[i];\n }\n return obj;\n });\n}\n\nexport default async function dbExec(args: string[]): Promise<void> {\n const parsed = parseArgs(args);\n\n if (parsed.help === \"true\") {\n console.log(`Usage: pnpm action db-exec --sql \"<statement>\" [options]\n pnpm action db-exec --statements '[{\"sql\":\"UPDATE ...\",\"args\":[...]}]' [options]\n\nOptions:\n --sql <stmt> Single INSERT / UPDATE / DELETE / REPLACE statement\n --args <json> JSON array of positional SQL bind parameters for --sql\n --statements <json> JSON array of {sql, args?}; runs in one transaction\n --db <path> Path to SQLite database (default: data/app.db)\n --format json Output as JSON\n --help Show this help message`);\n return;\n }\n\n const statements = parseStatements(parsed).map((statement, index) => ({\n sql: validateWriteSql(statement.sql, index + 1),\n args: statement.args,\n }));\n\n // Resolve database URL: --db flag → DATABASE_URL env → default file path\n let url: string;\n if (parsed.db) {\n url = \"file:\" + path.resolve(parsed.db);\n } else if (getDatabaseUrl()) {\n url = getDatabaseUrl();\n } else {\n url = \"file:\" + path.resolve(process.cwd(), \"data\", \"app.db\");\n }\n\n // Postgres path\n if (isPostgresUrl(url)) {\n const { default: pg } = await import(\"postgres\");\n const pgSql = pg(url);\n try {\n // Set up user-scoped temp views in production\n const scoping = await buildScopingPostgres(pgSql);\n\n const results: DbExecResult[] = [];\n await pgSql.begin(async (tx: any) => {\n try {\n // For UPDATE/DELETE: temp views scope to current user's rows.\n // Creating and dropping them inside the same transaction keeps\n // pooled Postgres backends from retaining session-local views.\n for (const stmt of scoping.setup) {\n await tx.unsafe(stmt);\n }\n\n for (let i = 0; i < statements.length; i++) {\n const statement = statements[i];\n const hasReturning = /\\bRETURNING\\b/i.test(statement.sql);\n const finalSql = normalizePostgresSql(\n injectOwnership(statement.sql, scoping),\n statement.args,\n );\n try {\n const result =\n statement.args.length > 0\n ? await tx.unsafe(finalSql, statement.args as any[])\n : await tx.unsafe(finalSql);\n const rows: Record<string, unknown>[] =\n hasReturning && result.length > 0 ? Array.from(result) : [];\n results.push({\n index: i + 1,\n sql: finalSql,\n changes: result.count ?? 0,\n rows,\n });\n } catch (err: any) {\n throw new Error(\n `Statement ${i + 1} failed: ${err?.message ?? String(err)}`,\n );\n }\n }\n } finally {\n for (const stmt of scoping.teardown) {\n await tx.unsafe(stmt).catch(() => {});\n }\n }\n });\n\n printBatchResult(results, parsed.format);\n } finally {\n await pgSql.end();\n }\n return;\n }\n\n // libsql / SQLite path\n const client = createClient({\n url,\n authToken: getDatabaseAuthToken(),\n });\n\n try {\n // Set up user-scoped temp views in production\n const scoping = await buildScopingSqlite(client);\n for (const stmt of scoping.setup) {\n await client.execute(stmt);\n }\n\n const results: DbExecResult[] = [];\n const shouldTransact = statements.length > 1;\n if (shouldTransact) await client.execute(\"BEGIN\");\n try {\n for (let i = 0; i < statements.length; i++) {\n const statement = statements[i];\n const hasReturning = /\\bRETURNING\\b/i.test(statement.sql);\n const finalSql = qualifySqliteWrite(\n injectOwnership(statement.sql, scoping),\n scoping,\n );\n try {\n const result =\n statement.args.length > 0\n ? await client.execute({\n sql: finalSql,\n args: statement.args as any[],\n })\n : await client.execute(finalSql);\n\n const rows: Record<string, unknown>[] =\n hasReturning && result.rows.length > 0\n ? sqliteRowsToObjects(result.rows, result.columns)\n : [];\n results.push({\n index: i + 1,\n sql: finalSql,\n changes: result.rowsAffected,\n lastInsertRowid: result.lastInsertRowid,\n rows,\n });\n } catch (err: any) {\n throw new Error(\n `Statement ${i + 1} failed: ${err?.message ?? String(err)}`,\n );\n }\n }\n if (shouldTransact) await client.execute(\"COMMIT\");\n } catch (err) {\n if (shouldTransact) {\n await client.execute(\"ROLLBACK\").catch(() => {});\n }\n throw err;\n }\n\n printBatchResult(results, parsed.format);\n\n for (const stmt of scoping.teardown) {\n await client.execute(stmt).catch(() => {});\n }\n } finally {\n client.close();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../src/scripts/db/exec.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Core script: db-exec\n *\n * Execute write SQL statements (INSERT, UPDATE, DELETE, REPLACE)\n * against a SQLite or Postgres database.\n *\n * In production mode, temporary views scope UPDATE/DELETE to the current\n * user's data (AGENT_USER_EMAIL / AGENT_ORG_ID). For INSERT, the\n * `owner_email` and `org_id` columns are auto-injected if the target\n * table uses the ownership convention.\n *\n * Usage:\n * pnpm action db-exec --sql \"UPDATE forms SET status=? WHERE id=?\" [--args '[\"published\",\"abc\"]'] [--db path]\n * pnpm action db-exec --statements '[{\"sql\":\"INSERT INTO notes (id,title) VALUES (?,?)\",\"args\":[\"n1\",\"One\"]},{\"sql\":\"UPDATE counters SET value=value+1 WHERE key=?\",\"args\":[\"notes\"]}]'\n */\n\nimport path from \"path\";\nimport { createClient } from \"@libsql/client\";\nimport { getDatabaseUrl, getDatabaseAuthToken } from \"../../db/client.js\";\nimport { parseArgs, fail } from \"../utils.js\";\nimport {\n buildScopingPostgres,\n buildScopingSqlite,\n type ScopingContext,\n} from \"./scoping.js\";\nimport { assertNoSensitiveFrameworkTables } from \"./safety.js\";\n\nfunction isPostgresUrl(url: string): boolean {\n return url.startsWith(\"postgres://\") || url.startsWith(\"postgresql://\");\n}\n\ninterface DbExecStatement {\n sql: string;\n args: unknown[];\n}\n\ninterface DbExecResult {\n index: number;\n sql: string;\n changes?: number;\n lastInsertRowid?: bigint | number;\n rows?: Record<string, unknown>[];\n}\n\nfunction parseSqlArgs(raw: string | undefined, label = \"--args\"): unknown[] {\n if (!raw) return [];\n try {\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) return parsed;\n } catch {\n // Fall through to the shared error below.\n }\n fail(`${label} must be a JSON array`);\n}\n\nfunction parseStatements(parsed: Record<string, string>): DbExecStatement[] {\n if (parsed.statements) {\n if (parsed.sql) {\n fail(\"Pass either --sql or --statements, not both.\");\n }\n let raw: unknown;\n try {\n raw = JSON.parse(parsed.statements);\n } catch {\n fail(\n '--statements must be a JSON array of {\"sql\": string, \"args\"?: unknown[]} objects',\n );\n }\n if (!Array.isArray(raw) || raw.length === 0) {\n fail(\"--statements must be a non-empty JSON array\");\n }\n return raw.map((entry, index) => {\n if (\n !entry ||\n typeof entry !== \"object\" ||\n typeof (entry as any).sql !== \"string\" ||\n !(entry as any).sql.trim()\n ) {\n fail(`Statement ${index + 1} must include a non-empty sql string`);\n }\n const args = (entry as any).args;\n if (args != null && !Array.isArray(args)) {\n fail(`Statement ${index + 1} args must be a JSON array`);\n }\n return { sql: (entry as any).sql, args: args ?? [] };\n });\n }\n\n if (!parsed.sql) {\n fail(\n '--sql is required unless --statements is provided. Example: --sql \"UPDATE forms SET status=? WHERE id=?\" --args \\'[\"published\",\"abc\"]\\'',\n );\n }\n return [{ sql: parsed.sql, args: parseSqlArgs(parsed.args) }];\n}\n\nfunction stripLeadingSqlComments(sql: string): string {\n return sql\n .replace(/^\\s*--[^\\n]*\\n/gm, \"\")\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .trim();\n}\n\nfunction hasAdditionalStatement(sql: string): boolean {\n let state: \"normal\" | \"single\" | \"double\" | \"line-comment\" | \"block-comment\" =\n \"normal\";\n\n for (let i = 0; i < sql.length; i++) {\n const ch = sql[i];\n const next = sql[i + 1];\n\n if (state === \"line-comment\") {\n if (ch === \"\\n\") state = \"normal\";\n continue;\n }\n if (state === \"block-comment\") {\n if (ch === \"*\" && next === \"/\") {\n i++;\n state = \"normal\";\n }\n continue;\n }\n if (state === \"single\") {\n if (ch === \"'\" && next === \"'\") {\n i++;\n } else if (ch === \"'\") {\n state = \"normal\";\n }\n continue;\n }\n if (state === \"double\") {\n if (ch === '\"' && next === '\"') {\n i++;\n } else if (ch === '\"') {\n state = \"normal\";\n }\n continue;\n }\n\n if (ch === \"-\" && next === \"-\") {\n i++;\n state = \"line-comment\";\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n i++;\n state = \"block-comment\";\n continue;\n }\n if (ch === \"'\") {\n state = \"single\";\n continue;\n }\n if (ch === '\"') {\n state = \"double\";\n continue;\n }\n if (ch === \";\") {\n return sql.slice(i + 1).trim().length > 0;\n }\n }\n return false;\n}\n\nfunction normalizeUserSql(sql: string, index: number): string {\n const stripped = stripLeadingSqlComments(sql);\n if (!stripped) {\n fail(`Statement ${index} is empty`);\n }\n if (hasAdditionalStatement(stripped)) {\n fail(\n `Statement ${index} contains multiple SQL statements. Use --statements for batches so each write can be validated and run transactionally.`,\n );\n }\n return stripped.replace(/;\\s*$/, \"\");\n}\n\nfunction validateWriteSql(sql: string, index: number): string {\n const normalized = normalizeUserSql(sql, index);\n const upper = normalized.toUpperCase();\n const allowed = [\"INSERT\", \"UPDATE\", \"DELETE\", \"REPLACE\"];\n const blocked = [\"SELECT\", \"WITH\", \"EXPLAIN\", \"PRAGMA\"];\n\n if (blocked.some((kw) => upper.startsWith(kw))) {\n fail(\n `Statement ${index}: use db-query for SELECT/read statements. db-exec is for writes only.`,\n );\n }\n if (upper.startsWith(\"CREATE\") || upper.startsWith(\"ALTER\")) {\n fail(\n `Statement ${index}: schema changes are not allowed through db-exec. Additive schema changes must go through reviewed migrations/startup code, not ad-hoc agent SQL.`,\n );\n }\n if (!allowed.some((kw) => upper.startsWith(kw))) {\n fail(\n `Statement ${index}: only ${allowed.join(\", \")} statements are allowed. ` +\n `Dangerous operations like DROP, ATTACH, VACUUM, DETACH, CREATE, and ALTER are blocked.`,\n );\n }\n assertNoSensitiveFrameworkTables(normalized, \"write\");\n return normalized;\n}\n\nfunction convertQuestionMarksToPostgresParams(sql: string): string {\n let index = 0;\n let out = \"\";\n let state: \"normal\" | \"single\" | \"double\" | \"line-comment\" | \"block-comment\" =\n \"normal\";\n\n for (let i = 0; i < sql.length; i++) {\n const ch = sql[i];\n const next = sql[i + 1];\n\n if (state === \"line-comment\") {\n out += ch;\n if (ch === \"\\n\") state = \"normal\";\n continue;\n }\n\n if (state === \"block-comment\") {\n out += ch;\n if (ch === \"*\" && next === \"/\") {\n out += next;\n i++;\n state = \"normal\";\n }\n continue;\n }\n\n if (state === \"single\") {\n out += ch;\n if (ch === \"'\" && next === \"'\") {\n out += next;\n i++;\n } else if (ch === \"'\") {\n state = \"normal\";\n }\n continue;\n }\n\n if (state === \"double\") {\n out += ch;\n if (ch === '\"' && next === '\"') {\n out += next;\n i++;\n } else if (ch === '\"') {\n state = \"normal\";\n }\n continue;\n }\n\n if (ch === \"-\" && next === \"-\") {\n out += ch + next;\n i++;\n state = \"line-comment\";\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n out += ch + next;\n i++;\n state = \"block-comment\";\n continue;\n }\n if (ch === \"'\") {\n out += ch;\n state = \"single\";\n continue;\n }\n if (ch === '\"') {\n out += ch;\n state = \"double\";\n continue;\n }\n if (ch === \"?\") {\n index++;\n out += `$${index}`;\n continue;\n }\n out += ch;\n }\n\n return out;\n}\n\nfunction normalizePostgresSql(sql: string, args: unknown[]): string {\n if (args.length === 0 || /\\$\\d+\\b/.test(sql)) return sql;\n return convertQuestionMarksToPostgresParams(sql);\n}\n\n/**\n * For INSERT statements targeting a table with owner_email / org_id columns,\n * auto-inject the current user's email and org ID if not already present.\n *\n * Handles the explicit column list form:\n * INSERT INTO table (col1, col2) VALUES (val1, val2)\n */\nfunction injectOwnership(sql: string, scoping: ScopingContext): string {\n if (!scoping.active) return sql;\n\n const upper = sql\n .replace(/^\\s*--[^\\n]*\\n/gm, \"\")\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .trim()\n .toUpperCase();\n if (!upper.startsWith(\"INSERT\")) return sql;\n\n // Extract table name: INSERT INTO <table> ...\n const match = sql.match(/INSERT\\s+INTO\\s+[\"']?(\\w+)[\"']?/i);\n if (!match) return sql;\n\n const tableName = match[1];\n\n // Determine which columns to inject\n const injections: { col: string; value: string }[] = [];\n\n if (\n scoping.userEmail &&\n scoping.ownerEmailTables.has(tableName) &&\n !/owner_email/i.test(sql)\n ) {\n injections.push({\n col: \"owner_email\",\n value: `'${scoping.userEmail.replace(/'/g, \"''\")}'`,\n });\n }\n\n if (\n scoping.orgId &&\n scoping.orgIdTables.has(tableName) &&\n !/org_id/i.test(sql)\n ) {\n injections.push({\n col: \"org_id\",\n value: `'${scoping.orgId.replace(/'/g, \"''\")}'`,\n });\n }\n\n if (injections.length === 0) return sql;\n\n // Try to inject into explicit column list: INSERT INTO t (cols) VALUES (vals)\n const colListMatch = sql.match(\n /(INSERT\\s+INTO\\s+[\"']?\\w+[\"']?\\s*)\\(([^)]+)\\)(\\s*VALUES\\s*)\\(([^)]+)\\)/i,\n );\n if (colListMatch) {\n const [, prefix, cols, valueKeyword, vals] = colListMatch;\n const extraCols = injections.map((i) => i.col).join(\", \");\n const extraVals = injections.map((i) => i.value).join(\", \");\n return `${prefix}(${cols}, ${extraCols})${valueKeyword}(${vals}, ${extraVals})`;\n }\n\n return sql;\n}\n\nfunction escapeSqlString(value: string): string {\n return value.replace(/'/g, \"''\");\n}\n\nfunction sqliteScopePredicate(\n tableName: string,\n scoping: ScopingContext,\n): string | null {\n if (tableName === \"tool_data\" && scoping.userEmail) {\n const userClause = `(scope = 'user' AND owner_email = '${escapeSqlString(scoping.userEmail)}')`;\n const orgClause = scoping.orgId\n ? ` OR (scope = 'org' AND org_id = '${escapeSqlString(scoping.orgId)}')`\n : \"\";\n return `(${userClause}${orgClause})`;\n }\n\n const clauses: string[] = [];\n const hasOwner = scoping.ownerEmailTables.has(tableName);\n const hasOrg = scoping.orgIdTables.has(tableName);\n if (scoping.userEmail && hasOwner) {\n const ownerClause = `owner_email = '${escapeSqlString(scoping.userEmail)}'`;\n if (scoping.orgId && hasOrg) {\n clauses.push(\n `${ownerClause} AND (org_id = '${escapeSqlString(scoping.orgId)}' OR org_id IS NULL)`,\n );\n } else {\n clauses.push(ownerClause);\n }\n } else if (scoping.orgId && hasOrg) {\n clauses.push(`org_id = '${escapeSqlString(scoping.orgId)}'`);\n }\n return clauses.length > 0 ? clauses.join(\" AND \") : null;\n}\n\nfunction splitReturning(sql: string): { body: string; returning: string } {\n const match = /\\bRETURNING\\b/i.exec(sql);\n if (!match) return { body: sql, returning: \"\" };\n return {\n body: sql.slice(0, match.index).trimEnd(),\n returning: sql.slice(match.index),\n };\n}\n\nfunction addSqliteScopeToWhere(sql: string, predicate: string): string {\n const { body, returning } = splitReturning(sql);\n const whereMatch = /\\bWHERE\\b/i.exec(body);\n const scoped = whereMatch\n ? `${body.slice(0, whereMatch.index)}WHERE ${predicate} AND (${body.slice(whereMatch.index + whereMatch[0].length).trim()})`\n : `${body} WHERE ${predicate}`;\n return returning ? `${scoped} ${returning}` : scoped;\n}\n\nfunction qualifySqliteWrite(sql: string, scoping: ScopingContext): string {\n if (!scoping.active) return sql;\n\n const updateMatch = sql.match(/^\\s*UPDATE\\s+(?:\"([^\"]+)\"|'([^']+)'|(\\w+))/i);\n if (updateMatch) {\n const tableName = updateMatch[1] ?? updateMatch[2] ?? updateMatch[3];\n const predicate = sqliteScopePredicate(tableName, scoping);\n if (!predicate) return sql;\n const qualified = sql.replace(\n /^\\s*UPDATE\\s+(?:\"[^\"]+\"|'[^']+'|\\w+)/i,\n `UPDATE main.\"${tableName.replace(/\"/g, '\"\"')}\"`,\n );\n return addSqliteScopeToWhere(qualified, predicate);\n }\n\n const deleteMatch = sql.match(\n /^\\s*DELETE\\s+FROM\\s+(?:\"([^\"]+)\"|'([^']+)'|(\\w+))/i,\n );\n if (deleteMatch) {\n const tableName = deleteMatch[1] ?? deleteMatch[2] ?? deleteMatch[3];\n const predicate = sqliteScopePredicate(tableName, scoping);\n if (!predicate) return sql;\n const qualified = sql.replace(\n /^\\s*DELETE\\s+FROM\\s+(?:\"[^\"]+\"|'[^']+'|\\w+)/i,\n `DELETE FROM main.\"${tableName.replace(/\"/g, '\"\"')}\"`,\n );\n return addSqliteScopeToWhere(qualified, predicate);\n }\n\n return sql.replace(\n /^\\s*(INSERT\\s+INTO|REPLACE\\s+INTO)\\s+(?:\"([^\"]+)\"|'([^']+)'|(\\w+))/i,\n (match, keyword, quotedDouble, quotedSingle, bare) => {\n const tableName = quotedDouble ?? quotedSingle ?? bare;\n if (\n !scoping.ownerEmailTables.has(tableName) &&\n !scoping.orgIdTables.has(tableName)\n ) {\n return match;\n }\n return `${keyword} main.\"${tableName.replace(/\"/g, '\"\"')}\"`;\n },\n );\n}\n\nfunction printResult(\n sql: string,\n result: {\n count?: number;\n rowsAffected?: number;\n lastInsertRowid?: bigint | number;\n rows?: Record<string, unknown>[];\n },\n hasReturning: boolean,\n format?: string,\n) {\n if (hasReturning && result.rows && result.rows.length > 0) {\n if (format === \"json\") {\n console.log(\n JSON.stringify(\n { sql, rows: result.rows, count: result.rows.length },\n null,\n 2,\n ),\n );\n return;\n }\n console.log(`Executed: ${sql}`);\n console.log(`Returned ${result.rows.length} row(s):`);\n console.log(JSON.stringify(result.rows, null, 2));\n } else {\n const changes = result.count ?? result.rowsAffected ?? 0;\n if (format === \"json\") {\n console.log(\n JSON.stringify(\n {\n sql,\n changes,\n ...(result.lastInsertRowid && changes > 0\n ? { lastInsertRowid: Number(result.lastInsertRowid) }\n : {}),\n },\n null,\n 2,\n ),\n );\n return;\n }\n console.log(`Executed: ${sql}`);\n console.log(`Changes: ${changes}`);\n if (result.lastInsertRowid && changes > 0) {\n console.log(`Last Insert Row ID: ${result.lastInsertRowid}`);\n }\n if (changes === 0) {\n console.log(zeroChangesHint(sql));\n }\n }\n}\n\n/**\n * Hint emitted when an UPDATE/DELETE/REPLACE matches zero rows. Matches the\n * wording used by db-patch's \"no rows matched\" error so the agent gets the\n * same scoping nudge from both tools — without this hint, the agent reports\n * \"Changes: 0\" as success and the user sees no UI update because the row\n * either didn't exist or wasn't visible to the current user under per-user\n * scoping.\n */\nfunction zeroChangesHint(sql: string): string {\n const upper = sql.toUpperCase(); // leading whitespace already stripped by normalizeUserSql\n if (upper.startsWith(\"INSERT\")) {\n // INSERT changes=0 means INSERT OR IGNORE skipped a duplicate — different\n // failure mode, not a scoping issue.\n return \"Hint: 0 rows inserted. The row likely violated a UNIQUE / PRIMARY KEY constraint and was skipped (INSERT OR IGNORE).\";\n }\n return (\n \"Hint: 0 rows changed. The WHERE clause matched no rows — either the row \" +\n \"doesn't exist, or it exists but is owned by a different user (per-user \" +\n \"and per-org scoping is automatic for db-exec).\"\n );\n}\n\nfunction printBatchResult(results: DbExecResult[], format?: string): void {\n if (results.length === 1) {\n const result = results[0];\n printResult(\n result.sql,\n {\n count: result.changes,\n rowsAffected: result.changes,\n lastInsertRowid: result.lastInsertRowid,\n rows: result.rows,\n },\n Boolean(result.rows?.length),\n format,\n );\n return;\n }\n\n const totalChanges = results.reduce(\n (sum, result) => sum + Number(result.changes ?? 0),\n 0,\n );\n\n if (format === \"json\") {\n console.log(\n JSON.stringify(\n {\n statements: results.map((result) => ({\n index: result.index,\n sql: result.sql,\n changes: result.changes ?? 0,\n ...(result.lastInsertRowid && Number(result.changes ?? 0) > 0\n ? { lastInsertRowid: Number(result.lastInsertRowid) }\n : {}),\n ...(result.rows?.length\n ? { rows: result.rows, count: result.rows.length }\n : {}),\n })),\n changes: totalChanges,\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n console.log(`Executed ${results.length} statements in one transaction.`);\n for (const result of results) {\n if (result.rows?.length) {\n console.log(`[${result.index}] Returned ${result.rows.length} row(s):`);\n console.log(JSON.stringify(result.rows, null, 2));\n } else {\n const changes = Number(result.changes ?? 0);\n console.log(`[${result.index}] Changes: ${changes}`);\n if (changes === 0) {\n console.log(`[${result.index}] ${zeroChangesHint(result.sql)}`);\n }\n }\n }\n console.log(`Total changes: ${totalChanges}`);\n}\n\nfunction sqliteRowsToObjects(\n rows: any[],\n columns: string[],\n): Record<string, unknown>[] {\n return rows.map((row) => {\n if (!Array.isArray(row) && row && typeof row === \"object\") {\n return { ...row };\n }\n const obj: Record<string, unknown> = {};\n for (let i = 0; i < columns.length; i++) {\n obj[columns[i]] = row[i];\n }\n return obj;\n });\n}\n\nexport default async function dbExec(args: string[]): Promise<void> {\n const parsed = parseArgs(args);\n\n if (parsed.help === \"true\") {\n console.log(`Usage: pnpm action db-exec --sql \"<statement>\" [options]\n pnpm action db-exec --statements '[{\"sql\":\"UPDATE ...\",\"args\":[...]}]' [options]\n\nOptions:\n --sql <stmt> Single INSERT / UPDATE / DELETE / REPLACE statement\n --args <json> JSON array of positional SQL bind parameters for --sql\n --statements <json> JSON array of {sql, args?}; runs in one transaction\n --db <path> Path to SQLite database (default: data/app.db)\n --format json Output as JSON\n --help Show this help message`);\n return;\n }\n\n const statements = parseStatements(parsed).map((statement, index) => ({\n sql: validateWriteSql(statement.sql, index + 1),\n args: statement.args,\n }));\n\n // Resolve database URL: --db flag → DATABASE_URL env → default file path\n let url: string;\n if (parsed.db) {\n url = \"file:\" + path.resolve(parsed.db);\n } else if (getDatabaseUrl()) {\n url = getDatabaseUrl();\n } else {\n url = \"file:\" + path.resolve(process.cwd(), \"data\", \"app.db\");\n }\n\n // Postgres path\n if (isPostgresUrl(url)) {\n const { default: pg } = await import(\"postgres\");\n const pgSql = pg(url);\n try {\n // Set up user-scoped temp views in production\n const scoping = await buildScopingPostgres(pgSql);\n\n const results: DbExecResult[] = [];\n await pgSql.begin(async (tx: any) => {\n try {\n // For UPDATE/DELETE: temp views scope to current user's rows.\n // Creating and dropping them inside the same transaction keeps\n // pooled Postgres backends from retaining session-local views.\n for (const stmt of scoping.setup) {\n await tx.unsafe(stmt);\n }\n\n for (let i = 0; i < statements.length; i++) {\n const statement = statements[i];\n const hasReturning = /\\bRETURNING\\b/i.test(statement.sql);\n const finalSql = normalizePostgresSql(\n injectOwnership(statement.sql, scoping),\n statement.args,\n );\n try {\n const result =\n statement.args.length > 0\n ? await tx.unsafe(finalSql, statement.args as any[])\n : await tx.unsafe(finalSql);\n const rows: Record<string, unknown>[] =\n hasReturning && result.length > 0 ? Array.from(result) : [];\n results.push({\n index: i + 1,\n sql: finalSql,\n changes: result.count ?? 0,\n rows,\n });\n } catch (err: any) {\n throw new Error(\n `Statement ${i + 1} failed: ${err?.message ?? String(err)}`,\n );\n }\n }\n } finally {\n for (const stmt of scoping.teardown) {\n await tx.unsafe(stmt).catch(() => {});\n }\n }\n });\n\n printBatchResult(results, parsed.format);\n } finally {\n await pgSql.end();\n }\n return;\n }\n\n // libsql / SQLite path\n const client = createClient({\n url,\n authToken: getDatabaseAuthToken(),\n });\n\n try {\n // Set up user-scoped temp views in production\n const scoping = await buildScopingSqlite(client);\n for (const stmt of scoping.setup) {\n await client.execute(stmt);\n }\n\n const results: DbExecResult[] = [];\n const shouldTransact = statements.length > 1;\n if (shouldTransact) await client.execute(\"BEGIN\");\n try {\n for (let i = 0; i < statements.length; i++) {\n const statement = statements[i];\n const hasReturning = /\\bRETURNING\\b/i.test(statement.sql);\n const finalSql = qualifySqliteWrite(\n injectOwnership(statement.sql, scoping),\n scoping,\n );\n try {\n const result =\n statement.args.length > 0\n ? await client.execute({\n sql: finalSql,\n args: statement.args as any[],\n })\n : await client.execute(finalSql);\n\n const rows: Record<string, unknown>[] =\n hasReturning && result.rows.length > 0\n ? sqliteRowsToObjects(result.rows, result.columns)\n : [];\n results.push({\n index: i + 1,\n sql: finalSql,\n changes: result.rowsAffected,\n lastInsertRowid: result.lastInsertRowid,\n rows,\n });\n } catch (err: any) {\n throw new Error(\n `Statement ${i + 1} failed: ${err?.message ?? String(err)}`,\n );\n }\n }\n if (shouldTransact) await client.execute(\"COMMIT\");\n } catch (err) {\n if (shouldTransact) {\n await client.execute(\"ROLLBACK\").catch(() => {});\n }\n throw err;\n }\n\n printBatchResult(results, parsed.format);\n\n for (const stmt of scoping.teardown) {\n await client.execute(stmt).catch(() => {});\n }\n } finally {\n client.close();\n }\n}\n"]}
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* - Template tables use an `owner_email` column for user scoping.
|
|
9
9
|
* - Template tables use an `org_id` column for org scoping.
|
|
10
10
|
* - Core tables have their own scoping patterns (key prefix, session_id, etc.).
|
|
11
|
-
* - When both columns are present,
|
|
11
|
+
* - When both columns are present, owner_email is always required; org_id
|
|
12
|
+
* narrows to the current org while preserving legacy/personal NULL rows.
|
|
12
13
|
*
|
|
13
14
|
* Temp views take precedence over real tables in both SQLite and Postgres,
|
|
14
15
|
* so the user's SQL runs unmodified against the filtered views.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scoping.d.ts","sourceRoot":"","sources":["../../../src/scripts/db/scoping.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"scoping.d.ts","sourceRoot":"","sources":["../../../src/scripts/db/scoping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAiMH,MAAM,WAAW,cAAc;IAC7B,yEAAyE;IACzE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,sEAAsE;IACtE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,iCAAiC;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,gEAAgE;IAChE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,4DAA4D;IAC5D,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,mEAAmE;IACnE,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,8DAA8D;IAC9D,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,GAAG,GACT,OAAO,CAAC,cAAc,CAAC,CAmCzB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,cAAc,CAAC,CA8B7E"}
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* - Template tables use an `owner_email` column for user scoping.
|
|
9
9
|
* - Template tables use an `org_id` column for org scoping.
|
|
10
10
|
* - Core tables have their own scoping patterns (key prefix, session_id, etc.).
|
|
11
|
-
* - When both columns are present,
|
|
11
|
+
* - When both columns are present, owner_email is always required; org_id
|
|
12
|
+
* narrows to the current org while preserving legacy/personal NULL rows.
|
|
12
13
|
*
|
|
13
14
|
* Temp views take precedence over real tables in both SQLite and Postgres,
|
|
14
15
|
* so the user's SQL runs unmodified against the filtered views.
|
|
@@ -131,21 +132,24 @@ function buildScopedTables(allColumns, userEmail, orgId, isPostgres) {
|
|
|
131
132
|
});
|
|
132
133
|
continue;
|
|
133
134
|
}
|
|
134
|
-
// Build WHERE clauses for owner_email and org_id
|
|
135
|
-
const clauses = [];
|
|
136
135
|
const hasOwner = columns.includes(OWNER_COLUMN);
|
|
137
136
|
const hasOrg = columns.includes(ORG_COLUMN);
|
|
138
137
|
if (hasOwner) {
|
|
139
|
-
|
|
138
|
+
const orgClause = hasOrg && safeOrgId
|
|
139
|
+
? ` AND ("${ORG_COLUMN}" = '${safeOrgId}' OR "${ORG_COLUMN}" IS NULL)`
|
|
140
|
+
: "";
|
|
141
|
+
const realTable = `${qualifiedPrefix}"${table}"`;
|
|
142
|
+
scoped.push({
|
|
143
|
+
name: table,
|
|
144
|
+
viewSql: `${isPostgres ? "CREATE OR REPLACE TEMPORARY" : "CREATE TEMPORARY"} VIEW "${table}" AS SELECT * FROM ${realTable} WHERE "${OWNER_COLUMN}" = '${safeEmail}'${orgClause}${checkOption}`,
|
|
145
|
+
});
|
|
146
|
+
continue;
|
|
140
147
|
}
|
|
141
148
|
if (hasOrg && safeOrgId) {
|
|
142
|
-
clauses.push(`"${ORG_COLUMN}" = '${safeOrgId}'`);
|
|
143
|
-
}
|
|
144
|
-
if (clauses.length > 0) {
|
|
145
149
|
const realTable = `${qualifiedPrefix}"${table}"`;
|
|
146
150
|
scoped.push({
|
|
147
151
|
name: table,
|
|
148
|
-
viewSql: `${isPostgres ? "CREATE OR REPLACE TEMPORARY" : "CREATE TEMPORARY"} VIEW "${table}" AS SELECT * FROM ${realTable} WHERE ${
|
|
152
|
+
viewSql: `${isPostgres ? "CREATE OR REPLACE TEMPORARY" : "CREATE TEMPORARY"} VIEW "${table}" AS SELECT * FROM ${realTable} WHERE "${ORG_COLUMN}" = '${safeOrgId}'${checkOption}`,
|
|
149
153
|
});
|
|
150
154
|
}
|
|
151
155
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scoping.js","sourceRoot":"","sources":["../../../src/scripts/db/scoping.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Per-user and per-org data scoping for db-query / db-exec.\n *\n * In production mode, creates temporary views that shadow real tables so\n * that raw SQL only sees the current user's (and org's) data.\n *\n * Convention:\n * - Template tables use an `owner_email` column for user scoping.\n * - Template tables use an `org_id` column for org scoping.\n * - Core tables have their own scoping patterns (key prefix, session_id, etc.).\n * - When both columns are present, both WHERE clauses are applied (AND).\n *\n * Temp views take precedence over real tables in both SQLite and Postgres,\n * so the user's SQL runs unmodified against the filtered views.\n */\n\n// Core tables with non-standard scoping (not owner_email).\n// Map of table name → { column, mode }.\nconst CORE_TABLE_SCOPING: Record<\n string,\n { column: string; mode: \"prefix\" | \"exact\" }\n> = {\n settings: { column: \"key\", mode: \"prefix\" }, // keys like u:<email>:<key>\n application_state: { column: \"session_id\", mode: \"exact\" },\n oauth_tokens: { column: \"owner\", mode: \"exact\" },\n sessions: { column: \"email\", mode: \"exact\" },\n};\n\n// The conventional column names for user/org ownership in template tables.\nimport {\n getRequestUserEmail,\n getRequestOrgId,\n} from \"../../server/request-context.js\";\n\nconst OWNER_COLUMN = \"owner_email\";\nconst ORG_COLUMN = \"org_id\";\nconst DEV_FALLBACK_EMAIL = \"local@localhost\"; // guard:allow-localhost-fallback — sentinel is rejected below so DB scripts cannot silently scope to the dev fallback tenant\n\ninterface ScopedTable {\n name: string;\n viewSql: string;\n}\n\nfunction getUserEmail(): string {\n const userEmail = getRequestUserEmail() || null;\n if (!userEmail || userEmail === DEV_FALLBACK_EMAIL) {\n throw new Error(\n \"db-exec / db-query / db-patch require an authenticated user identity. \" +\n \"Easiest fix: open the app at http://localhost:3000 and sign in — \" +\n \"the CLI then auto-loads your session. Otherwise set \" +\n \"AGENT_USER_EMAIL=<email> in the env, or invoke through an HTTP \" +\n \"action that runs under runWithRequestContext. Refusing to run unscoped — \" +\n \"an unscoped UPDATE/DELETE would touch every user's rows, and an \" +\n \"unscoped INSERT would land with the dev sentinel owner and be invisible \" +\n \"to the UI.\",\n );\n }\n return userEmail;\n}\n\nfunction getOrgId(): string | null {\n return getRequestOrgId() || null;\n}\n\n// ─── Schema introspection ───────────────────────────────────────────────────\n\ninterface TableColumn {\n table: string;\n column: string;\n}\n\nasync function discoverColumnsPostgres(pgSql: any): Promise<TableColumn[]> {\n const rows: any[] = await pgSql`\n SELECT table_name, column_name\n FROM information_schema.columns\n WHERE table_schema = 'public'\n ORDER BY table_name, ordinal_position\n `;\n return rows.map((r) => ({ table: r.table_name, column: r.column_name }));\n}\n\nasync function discoverColumnsSqlite(client: any): Promise<TableColumn[]> {\n const tablesResult = await client.execute(\n `SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'`,\n );\n const tables = tablesResult.rows.map((r: any) => (r.name ?? r[0]) as string);\n\n const result: TableColumn[] = [];\n for (const table of tables) {\n const escaped = table.replace(/\"/g, '\"\"');\n const colsResult = await client.execute(`PRAGMA table_info(\"${escaped}\")`);\n for (const row of colsResult.rows) {\n result.push({\n table,\n column: (row.name ?? row[1]) as string,\n });\n }\n }\n return result;\n}\n\n// ─── View generation ────────────────────────────────────────────────────────\n\n/** Escape a string for safe inclusion in a SQL single-quoted literal. */\nfunction escapeSqlString(value: string): string {\n return value.replace(/'/g, \"''\");\n}\n\nfunction buildScopedTables(\n allColumns: TableColumn[],\n userEmail: string,\n orgId: string | null,\n isPostgres: boolean,\n): ScopedTable[] {\n // Group columns by table\n const columnsByTable = new Map<string, string[]>();\n for (const { table, column } of allColumns) {\n const cols = columnsByTable.get(table) || [];\n cols.push(column);\n columnsByTable.set(table, cols);\n }\n\n const scoped: ScopedTable[] = [];\n const qualifiedPrefix = isPostgres ? \"public.\" : \"main.\";\n const safeEmail = escapeSqlString(userEmail);\n const safeOrgId = orgId ? escapeSqlString(orgId) : null;\n\n // WITH CHECK OPTION ensures INSERTs/UPDATEs through the auto-updatable view\n // can't write rows that violate the WHERE filter. Without it, an attacker\n // could `INSERT INTO recordings (..., owner_email) VALUES (..., 'victim@x')`\n // through the view and the row would land in the base table under the\n // victim's identity. SQLite views are not auto-updatable in the same way\n // (they require triggers), so this clause is a no-op there but harmless.\n const checkOption = isPostgres ? \" WITH LOCAL CHECK OPTION\" : \"\";\n\n for (const [table, columns] of columnsByTable) {\n // Check core table scoping\n const coreScoping = CORE_TABLE_SCOPING[table];\n if (coreScoping) {\n const realTable = `${qualifiedPrefix}\"${table}\"`;\n let whereSql: string;\n if (coreScoping.mode === \"prefix\") {\n // settings: key starts with u:<email>:\n // Escape \\, % and _ in the email so LIKE treats them literally.\n const likeEmail = safeEmail\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/%/g, \"\\\\%\")\n .replace(/_/g, \"\\\\_\");\n const prefix = `u:${likeEmail}:`;\n whereSql = `\"${coreScoping.column}\" LIKE '${prefix}%' ESCAPE '\\\\'`;\n } else {\n whereSql = `\"${coreScoping.column}\" = '${safeEmail}'`;\n }\n scoped.push({\n name: table,\n viewSql: `${isPostgres ? \"CREATE OR REPLACE TEMPORARY\" : \"CREATE TEMPORARY\"} VIEW \"${table}\" AS SELECT * FROM ${realTable} WHERE ${whereSql}${checkOption}`,\n });\n continue;\n }\n\n if (\n table === \"tool_data\" &&\n columns.includes(\"scope\") &&\n columns.includes(OWNER_COLUMN) &&\n columns.includes(ORG_COLUMN)\n ) {\n const realTable = `${qualifiedPrefix}\"${table}\"`;\n const orgClause = safeOrgId\n ? ` OR (\"scope\" = 'org' AND \"${ORG_COLUMN}\" = '${safeOrgId}')`\n : \"\";\n scoped.push({\n name: table,\n viewSql: `${isPostgres ? \"CREATE OR REPLACE TEMPORARY\" : \"CREATE TEMPORARY\"} VIEW \"${table}\" AS SELECT * FROM ${realTable} WHERE ((\"scope\" = 'user' AND \"${OWNER_COLUMN}\" = '${safeEmail}')${orgClause})${checkOption}`,\n });\n continue;\n }\n\n // Build WHERE clauses for owner_email and org_id\n const clauses: string[] = [];\n const hasOwner = columns.includes(OWNER_COLUMN);\n const hasOrg = columns.includes(ORG_COLUMN);\n\n if (hasOwner) {\n clauses.push(`\"${OWNER_COLUMN}\" = '${safeEmail}'`);\n }\n if (hasOrg && safeOrgId) {\n clauses.push(`\"${ORG_COLUMN}\" = '${safeOrgId}'`);\n }\n\n if (clauses.length > 0) {\n const realTable = `${qualifiedPrefix}\"${table}\"`;\n scoped.push({\n name: table,\n viewSql: `${isPostgres ? \"CREATE OR REPLACE TEMPORARY\" : \"CREATE TEMPORARY\"} VIEW \"${table}\" AS SELECT * FROM ${realTable} WHERE ${clauses.join(\" AND \")}${checkOption}`,\n });\n }\n }\n\n return scoped;\n}\n\n// ─── Public API ─────────────────────────────────────────────────────────────\n\nexport interface ScopingContext {\n /** SQL statements to run before the user's query (create temp views). */\n setup: string[];\n /** SQL statements to run after the user's query (drop temp views). */\n teardown: string[];\n /** Whether scoping is active. */\n active: boolean;\n /** The current user email (for INSERT injection in db-exec). */\n userEmail: string | null;\n /** The current org ID (for INSERT injection in db-exec). */\n orgId: string | null;\n /** Tables that have owner_email columns (for INSERT injection). */\n ownerEmailTables: Set<string>;\n /** Tables that have org_id columns (for INSERT injection). */\n orgIdTables: Set<string>;\n}\n\n/**\n * Build scoping context for a Postgres connection.\n * Returns setup/teardown SQL to run before/after the user's query.\n */\nexport async function buildScopingPostgres(\n pgSql: any,\n): Promise<ScopingContext> {\n // getUserEmail() throws when there is no authenticated user (no request\n // context AND no AGENT_USER_EMAIL env) or when it resolves to the dev\n // sentinel `local@localhost`. We let that throw propagate: the script\n // refuses to run unscoped rather than silently writing rows that the UI\n // then can't see, or running an UPDATE/DELETE across every user's data.\n const userEmail = getUserEmail();\n\n const orgId = getOrgId();\n const allColumns = await discoverColumnsPostgres(pgSql);\n const scoped = buildScopedTables(allColumns, userEmail, orgId, true);\n\n // Track which tables have owner_email / org_id for INSERT injection\n const columnsByTable = new Map<string, string[]>();\n for (const { table, column } of allColumns) {\n const cols = columnsByTable.get(table) || [];\n cols.push(column);\n columnsByTable.set(table, cols);\n }\n const ownerEmailTables = new Set<string>();\n const orgIdTables = new Set<string>();\n for (const [table, columns] of columnsByTable) {\n if (columns.includes(OWNER_COLUMN)) ownerEmailTables.add(table);\n if (columns.includes(ORG_COLUMN)) orgIdTables.add(table);\n }\n\n return {\n setup: scoped.map((s) => s.viewSql),\n teardown: scoped.map((s) => `DROP VIEW IF EXISTS pg_temp.\"${s.name}\"`),\n active: scoped.length > 0,\n userEmail,\n orgId,\n ownerEmailTables,\n orgIdTables,\n };\n}\n\n/**\n * Build scoping context for a SQLite/libsql connection.\n * Returns setup/teardown SQL to run before/after the user's query.\n */\nexport async function buildScopingSqlite(client: any): Promise<ScopingContext> {\n // See buildScopingPostgres: getUserEmail() throws on no user / dev sentinel.\n const userEmail = getUserEmail();\n\n const orgId = getOrgId();\n const allColumns = await discoverColumnsSqlite(client);\n const scoped = buildScopedTables(allColumns, userEmail, orgId, false);\n\n const columnsByTable = new Map<string, string[]>();\n for (const { table, column } of allColumns) {\n const cols = columnsByTable.get(table) || [];\n cols.push(column);\n columnsByTable.set(table, cols);\n }\n const ownerEmailTables = new Set<string>();\n const orgIdTables = new Set<string>();\n for (const [table, columns] of columnsByTable) {\n if (columns.includes(OWNER_COLUMN)) ownerEmailTables.add(table);\n if (columns.includes(ORG_COLUMN)) orgIdTables.add(table);\n }\n\n return {\n setup: scoped.map((s) => s.viewSql),\n teardown: scoped.map((s) => `DROP VIEW IF EXISTS \"${s.name}\"`),\n active: scoped.length > 0,\n userEmail,\n orgId,\n ownerEmailTables,\n orgIdTables,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"scoping.js","sourceRoot":"","sources":["../../../src/scripts/db/scoping.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Per-user and per-org data scoping for db-query / db-exec.\n *\n * In production mode, creates temporary views that shadow real tables so\n * that raw SQL only sees the current user's (and org's) data.\n *\n * Convention:\n * - Template tables use an `owner_email` column for user scoping.\n * - Template tables use an `org_id` column for org scoping.\n * - Core tables have their own scoping patterns (key prefix, session_id, etc.).\n * - When both columns are present, owner_email is always required; org_id\n * narrows to the current org while preserving legacy/personal NULL rows.\n *\n * Temp views take precedence over real tables in both SQLite and Postgres,\n * so the user's SQL runs unmodified against the filtered views.\n */\n\n// Core tables with non-standard scoping (not owner_email).\n// Map of table name → { column, mode }.\nconst CORE_TABLE_SCOPING: Record<\n string,\n { column: string; mode: \"prefix\" | \"exact\" }\n> = {\n settings: { column: \"key\", mode: \"prefix\" }, // keys like u:<email>:<key>\n application_state: { column: \"session_id\", mode: \"exact\" },\n oauth_tokens: { column: \"owner\", mode: \"exact\" },\n sessions: { column: \"email\", mode: \"exact\" },\n};\n\n// The conventional column names for user/org ownership in template tables.\nimport {\n getRequestUserEmail,\n getRequestOrgId,\n} from \"../../server/request-context.js\";\n\nconst OWNER_COLUMN = \"owner_email\";\nconst ORG_COLUMN = \"org_id\";\nconst DEV_FALLBACK_EMAIL = \"local@localhost\"; // guard:allow-localhost-fallback — sentinel is rejected below so DB scripts cannot silently scope to the dev fallback tenant\n\ninterface ScopedTable {\n name: string;\n viewSql: string;\n}\n\nfunction getUserEmail(): string {\n const userEmail = getRequestUserEmail() || null;\n if (!userEmail || userEmail === DEV_FALLBACK_EMAIL) {\n throw new Error(\n \"db-exec / db-query / db-patch require an authenticated user identity. \" +\n \"Easiest fix: open the app at http://localhost:3000 and sign in — \" +\n \"the CLI then auto-loads your session. Otherwise set \" +\n \"AGENT_USER_EMAIL=<email> in the env, or invoke through an HTTP \" +\n \"action that runs under runWithRequestContext. Refusing to run unscoped — \" +\n \"an unscoped UPDATE/DELETE would touch every user's rows, and an \" +\n \"unscoped INSERT would land with the dev sentinel owner and be invisible \" +\n \"to the UI.\",\n );\n }\n return userEmail;\n}\n\nfunction getOrgId(): string | null {\n return getRequestOrgId() || null;\n}\n\n// ─── Schema introspection ───────────────────────────────────────────────────\n\ninterface TableColumn {\n table: string;\n column: string;\n}\n\nasync function discoverColumnsPostgres(pgSql: any): Promise<TableColumn[]> {\n const rows: any[] = await pgSql`\n SELECT table_name, column_name\n FROM information_schema.columns\n WHERE table_schema = 'public'\n ORDER BY table_name, ordinal_position\n `;\n return rows.map((r) => ({ table: r.table_name, column: r.column_name }));\n}\n\nasync function discoverColumnsSqlite(client: any): Promise<TableColumn[]> {\n const tablesResult = await client.execute(\n `SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'`,\n );\n const tables = tablesResult.rows.map((r: any) => (r.name ?? r[0]) as string);\n\n const result: TableColumn[] = [];\n for (const table of tables) {\n const escaped = table.replace(/\"/g, '\"\"');\n const colsResult = await client.execute(`PRAGMA table_info(\"${escaped}\")`);\n for (const row of colsResult.rows) {\n result.push({\n table,\n column: (row.name ?? row[1]) as string,\n });\n }\n }\n return result;\n}\n\n// ─── View generation ────────────────────────────────────────────────────────\n\n/** Escape a string for safe inclusion in a SQL single-quoted literal. */\nfunction escapeSqlString(value: string): string {\n return value.replace(/'/g, \"''\");\n}\n\nfunction buildScopedTables(\n allColumns: TableColumn[],\n userEmail: string,\n orgId: string | null,\n isPostgres: boolean,\n): ScopedTable[] {\n // Group columns by table\n const columnsByTable = new Map<string, string[]>();\n for (const { table, column } of allColumns) {\n const cols = columnsByTable.get(table) || [];\n cols.push(column);\n columnsByTable.set(table, cols);\n }\n\n const scoped: ScopedTable[] = [];\n const qualifiedPrefix = isPostgres ? \"public.\" : \"main.\";\n const safeEmail = escapeSqlString(userEmail);\n const safeOrgId = orgId ? escapeSqlString(orgId) : null;\n\n // WITH CHECK OPTION ensures INSERTs/UPDATEs through the auto-updatable view\n // can't write rows that violate the WHERE filter. Without it, an attacker\n // could `INSERT INTO recordings (..., owner_email) VALUES (..., 'victim@x')`\n // through the view and the row would land in the base table under the\n // victim's identity. SQLite views are not auto-updatable in the same way\n // (they require triggers), so this clause is a no-op there but harmless.\n const checkOption = isPostgres ? \" WITH LOCAL CHECK OPTION\" : \"\";\n\n for (const [table, columns] of columnsByTable) {\n // Check core table scoping\n const coreScoping = CORE_TABLE_SCOPING[table];\n if (coreScoping) {\n const realTable = `${qualifiedPrefix}\"${table}\"`;\n let whereSql: string;\n if (coreScoping.mode === \"prefix\") {\n // settings: key starts with u:<email>:\n // Escape \\, % and _ in the email so LIKE treats them literally.\n const likeEmail = safeEmail\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/%/g, \"\\\\%\")\n .replace(/_/g, \"\\\\_\");\n const prefix = `u:${likeEmail}:`;\n whereSql = `\"${coreScoping.column}\" LIKE '${prefix}%' ESCAPE '\\\\'`;\n } else {\n whereSql = `\"${coreScoping.column}\" = '${safeEmail}'`;\n }\n scoped.push({\n name: table,\n viewSql: `${isPostgres ? \"CREATE OR REPLACE TEMPORARY\" : \"CREATE TEMPORARY\"} VIEW \"${table}\" AS SELECT * FROM ${realTable} WHERE ${whereSql}${checkOption}`,\n });\n continue;\n }\n\n if (\n table === \"tool_data\" &&\n columns.includes(\"scope\") &&\n columns.includes(OWNER_COLUMN) &&\n columns.includes(ORG_COLUMN)\n ) {\n const realTable = `${qualifiedPrefix}\"${table}\"`;\n const orgClause = safeOrgId\n ? ` OR (\"scope\" = 'org' AND \"${ORG_COLUMN}\" = '${safeOrgId}')`\n : \"\";\n scoped.push({\n name: table,\n viewSql: `${isPostgres ? \"CREATE OR REPLACE TEMPORARY\" : \"CREATE TEMPORARY\"} VIEW \"${table}\" AS SELECT * FROM ${realTable} WHERE ((\"scope\" = 'user' AND \"${OWNER_COLUMN}\" = '${safeEmail}')${orgClause})${checkOption}`,\n });\n continue;\n }\n\n const hasOwner = columns.includes(OWNER_COLUMN);\n const hasOrg = columns.includes(ORG_COLUMN);\n\n if (hasOwner) {\n const orgClause =\n hasOrg && safeOrgId\n ? ` AND (\"${ORG_COLUMN}\" = '${safeOrgId}' OR \"${ORG_COLUMN}\" IS NULL)`\n : \"\";\n const realTable = `${qualifiedPrefix}\"${table}\"`;\n scoped.push({\n name: table,\n viewSql: `${isPostgres ? \"CREATE OR REPLACE TEMPORARY\" : \"CREATE TEMPORARY\"} VIEW \"${table}\" AS SELECT * FROM ${realTable} WHERE \"${OWNER_COLUMN}\" = '${safeEmail}'${orgClause}${checkOption}`,\n });\n continue;\n }\n\n if (hasOrg && safeOrgId) {\n const realTable = `${qualifiedPrefix}\"${table}\"`;\n scoped.push({\n name: table,\n viewSql: `${isPostgres ? \"CREATE OR REPLACE TEMPORARY\" : \"CREATE TEMPORARY\"} VIEW \"${table}\" AS SELECT * FROM ${realTable} WHERE \"${ORG_COLUMN}\" = '${safeOrgId}'${checkOption}`,\n });\n }\n }\n\n return scoped;\n}\n\n// ─── Public API ─────────────────────────────────────────────────────────────\n\nexport interface ScopingContext {\n /** SQL statements to run before the user's query (create temp views). */\n setup: string[];\n /** SQL statements to run after the user's query (drop temp views). */\n teardown: string[];\n /** Whether scoping is active. */\n active: boolean;\n /** The current user email (for INSERT injection in db-exec). */\n userEmail: string | null;\n /** The current org ID (for INSERT injection in db-exec). */\n orgId: string | null;\n /** Tables that have owner_email columns (for INSERT injection). */\n ownerEmailTables: Set<string>;\n /** Tables that have org_id columns (for INSERT injection). */\n orgIdTables: Set<string>;\n}\n\n/**\n * Build scoping context for a Postgres connection.\n * Returns setup/teardown SQL to run before/after the user's query.\n */\nexport async function buildScopingPostgres(\n pgSql: any,\n): Promise<ScopingContext> {\n // getUserEmail() throws when there is no authenticated user (no request\n // context AND no AGENT_USER_EMAIL env) or when it resolves to the dev\n // sentinel `local@localhost`. We let that throw propagate: the script\n // refuses to run unscoped rather than silently writing rows that the UI\n // then can't see, or running an UPDATE/DELETE across every user's data.\n const userEmail = getUserEmail();\n\n const orgId = getOrgId();\n const allColumns = await discoverColumnsPostgres(pgSql);\n const scoped = buildScopedTables(allColumns, userEmail, orgId, true);\n\n // Track which tables have owner_email / org_id for INSERT injection\n const columnsByTable = new Map<string, string[]>();\n for (const { table, column } of allColumns) {\n const cols = columnsByTable.get(table) || [];\n cols.push(column);\n columnsByTable.set(table, cols);\n }\n const ownerEmailTables = new Set<string>();\n const orgIdTables = new Set<string>();\n for (const [table, columns] of columnsByTable) {\n if (columns.includes(OWNER_COLUMN)) ownerEmailTables.add(table);\n if (columns.includes(ORG_COLUMN)) orgIdTables.add(table);\n }\n\n return {\n setup: scoped.map((s) => s.viewSql),\n teardown: scoped.map((s) => `DROP VIEW IF EXISTS pg_temp.\"${s.name}\"`),\n active: scoped.length > 0,\n userEmail,\n orgId,\n ownerEmailTables,\n orgIdTables,\n };\n}\n\n/**\n * Build scoping context for a SQLite/libsql connection.\n * Returns setup/teardown SQL to run before/after the user's query.\n */\nexport async function buildScopingSqlite(client: any): Promise<ScopingContext> {\n // See buildScopingPostgres: getUserEmail() throws on no user / dev sentinel.\n const userEmail = getUserEmail();\n\n const orgId = getOrgId();\n const allColumns = await discoverColumnsSqlite(client);\n const scoped = buildScopedTables(allColumns, userEmail, orgId, false);\n\n const columnsByTable = new Map<string, string[]>();\n for (const { table, column } of allColumns) {\n const cols = columnsByTable.get(table) || [];\n cols.push(column);\n columnsByTable.set(table, cols);\n }\n const ownerEmailTables = new Set<string>();\n const orgIdTables = new Set<string>();\n for (const [table, columns] of columnsByTable) {\n if (columns.includes(OWNER_COLUMN)) ownerEmailTables.add(table);\n if (columns.includes(ORG_COLUMN)) orgIdTables.add(table);\n }\n\n return {\n setup: scoped.map((s) => s.viewSql),\n teardown: scoped.map((s) => `DROP VIEW IF EXISTS \"${s.name}\"`),\n active: scoped.length > 0,\n userEmail,\n orgId,\n ownerEmailTables,\n orgIdTables,\n };\n}\n"]}
|
|
@@ -83,6 +83,12 @@ export interface AgentChatPluginOptions {
|
|
|
83
83
|
* `null` from the callback based on their own logic.
|
|
84
84
|
*/
|
|
85
85
|
extraContext?: (event: any, owner: string) => string | null | Promise<string | null>;
|
|
86
|
+
/**
|
|
87
|
+
* Optional final-answer guard. Templates can use this to require a
|
|
88
|
+
* corrective retry before accepting a text-only final answer, e.g. forcing
|
|
89
|
+
* real data-source tool calls for analytics requests.
|
|
90
|
+
*/
|
|
91
|
+
finalResponseGuard?: import("../agent/production-agent.js").AgentLoopFinalResponseGuard;
|
|
86
92
|
/**
|
|
87
93
|
* Use ONLY the template's `systemPrompt` and the actions list — skip the
|
|
88
94
|
* framework prompt wrapper, resource loading (AGENTS.md/LEARNINGS.md/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-chat-plugin.d.ts","sourceRoot":"","sources":["../../src/server/agent-chat-plugin.ts"],"names":[],"mappings":"AAaA,OAAO,EAUL,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AAKtC,OAAO,KAAK,EACV,cAAc,EAEd,eAAe,EAEhB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,gBAAgB,EAUjB,MAAM,wBAAwB,CAAC;AAmDhC,OAAO,EAGL,KAAK,0BAA0B,EAC/B,KAAK,oBAAoB,EAC1B,MAAM,6BAA6B,CAAC;AA0IrC,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,WAAW,EAAE,SAAS,oBAAoB,EAAE,EAC5C,OAAO,GAAE,0BAA0B,GAAG;IAAE,KAAK,CAAC,EAAE,GAAG,CAAA;CAAO,GACzD;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAO7C;
|
|
1
|
+
{"version":3,"file":"agent-chat-plugin.d.ts","sourceRoot":"","sources":["../../src/server/agent-chat-plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,7 +18,7 @@ import { resourceList, resourceListAccessible, resourceGet, resourceGetByPath, e
|
|
|
18
18
|
import { getFrontmatterValue, getSkillNameFromPath, parseFrontmatter, } from "../resources/metadata.js";
|
|
19
19
|
import nodePath from "node:path";
|
|
20
20
|
import { readBody } from "./h3-helpers.js";
|
|
21
|
-
import { getBuilderBrowserConnectUrl,
|
|
21
|
+
import { getBuilderBrowserConnectUrl, resolveBuilderBranchProjectId, } from "./builder-browser.js";
|
|
22
22
|
import { captureCliOutput } from "./cli-capture.js";
|
|
23
23
|
import { withConfiguredAppBasePath } from "./app-base-path.js";
|
|
24
24
|
import { appendA2AArtifactLinks, buildA2ARecoverableArtifactMessage, } from "../a2a/artifact-response.js";
|
|
@@ -787,11 +787,12 @@ function createBuilderBrowserTool(deps) {
|
|
|
787
787
|
const { resolveBuilderCredentials } = await import("./credential-provider.js");
|
|
788
788
|
const creds = await resolveBuilderCredentials();
|
|
789
789
|
const configured = !!(creds.privateKey && creds.publicKey);
|
|
790
|
+
const branchProjectId = await resolveBuilderBranchProjectId();
|
|
790
791
|
const prompt = typeof args?.prompt === "string" ? args.prompt : "";
|
|
791
792
|
return JSON.stringify({
|
|
792
793
|
kind: "connect-builder-card",
|
|
793
794
|
configured,
|
|
794
|
-
builderEnabled:
|
|
795
|
+
builderEnabled: !!branchProjectId,
|
|
795
796
|
connectUrl: getBuilderBrowserConnectUrl(deps.getOrigin()),
|
|
796
797
|
orgName: creds.orgName || null,
|
|
797
798
|
prompt,
|
|
@@ -2890,6 +2891,7 @@ export function createAgentChatPlugin(options) {
|
|
|
2890
2891
|
model: options?.model ?? DEFAULT_MODEL,
|
|
2891
2892
|
apiKey: options?.apiKey,
|
|
2892
2893
|
runSoftTimeoutMs: options?.runSoftTimeoutMs,
|
|
2894
|
+
finalResponseGuard: options?.finalResponseGuard,
|
|
2893
2895
|
skipFilesContext: leanPrompt,
|
|
2894
2896
|
onEngineResolved: (engine, model) => {
|
|
2895
2897
|
const runCtx = ensureRequestRunContext();
|
|
@@ -2924,6 +2926,7 @@ export function createAgentChatPlugin(options) {
|
|
|
2924
2926
|
model: options?.model ?? DEFAULT_MODEL,
|
|
2925
2927
|
apiKey: options?.apiKey,
|
|
2926
2928
|
runSoftTimeoutMs: options?.runSoftTimeoutMs,
|
|
2929
|
+
finalResponseGuard: options?.finalResponseGuard,
|
|
2927
2930
|
skipFilesContext: true,
|
|
2928
2931
|
onEngineResolved: (engine, model) => {
|
|
2929
2932
|
const runCtx = ensureRequestRunContext();
|
|
@@ -3006,6 +3009,7 @@ export function createAgentChatPlugin(options) {
|
|
|
3006
3009
|
model: options?.model,
|
|
3007
3010
|
apiKey: options?.apiKey,
|
|
3008
3011
|
runSoftTimeoutMs: options?.runSoftTimeoutMs,
|
|
3012
|
+
finalResponseGuard: options?.finalResponseGuard,
|
|
3009
3013
|
skipFilesContext: leanPrompt,
|
|
3010
3014
|
onEngineResolved: (engine, model) => {
|
|
3011
3015
|
const runCtx = ensureRequestRunContext();
|