orbit-code-ai 0.1.34 → 0.1.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.mjs +141 -23
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -83759,7 +83759,7 @@ async function printStartupScreen() {
83759
83759
  const sLen = ` ● ${sL} Ready — type /help to begin`.length;
83760
83760
  out.push(boxRow(sRow, W2, sLen));
83761
83761
  out.push(`${rgb(...BORDER)}╚${"═".repeat(W2 - 2)}╝${RESET}`);
83762
- out.push(` ${DIM}${rgb(...DIMCOL)}orbit-code ${RESET}${rgb(...ACCENT)}v${"0.1.34"}${RESET}`);
83762
+ out.push(` ${DIM}${rgb(...DIMCOL)}orbit-code ${RESET}${rgb(...ACCENT)}v${"0.1.35"}${RESET}`);
83763
83763
  out.push("");
83764
83764
  process.stdout.write(out.join(`
83765
83765
  `) + `
@@ -334266,7 +334266,7 @@ function getAnthropicEnvMetadata() {
334266
334266
  function getBuildAgeMinutes() {
334267
334267
  if (false)
334268
334268
  ;
334269
- const buildTime = new Date("2026-07-01T08:02:14.526Z").getTime();
334269
+ const buildTime = new Date("2026-07-01T09:45:32.083Z").getTime();
334270
334270
  if (isNaN(buildTime))
334271
334271
  return;
334272
334272
  return Math.floor((Date.now() - buildTime) / 60000);
@@ -358683,7 +358683,7 @@ function buildPrimarySection() {
358683
358683
  }, undefined, false, undefined, this);
358684
358684
  return [{
358685
358685
  label: "Version",
358686
- value: "0.1.34"
358686
+ value: "0.1.35"
358687
358687
  }, {
358688
358688
  label: "Session name",
358689
358689
  value: nameValue
@@ -470794,7 +470794,7 @@ function WelcomeV2() {
470794
470794
  dimColor: true,
470795
470795
  children: [
470796
470796
  "v",
470797
- "0.1.34",
470797
+ "0.1.35",
470798
470798
  " "
470799
470799
  ]
470800
470800
  }, undefined, true, undefined, this)
@@ -470994,7 +470994,7 @@ function WelcomeV2() {
470994
470994
  dimColor: true,
470995
470995
  children: [
470996
470996
  "v",
470997
- "0.1.34",
470997
+ "0.1.35",
470998
470998
  " "
470999
470999
  ]
471000
471000
  }, undefined, true, undefined, this)
@@ -471220,7 +471220,7 @@ function AppleTerminalWelcomeV2(t0) {
471220
471220
  dimColor: true,
471221
471221
  children: [
471222
471222
  "v",
471223
- "0.1.34",
471223
+ "0.1.35",
471224
471224
  " "
471225
471225
  ]
471226
471226
  }, undefined, true, undefined, this);
@@ -471474,7 +471474,7 @@ function AppleTerminalWelcomeV2(t0) {
471474
471474
  dimColor: true,
471475
471475
  children: [
471476
471476
  "v",
471477
- "0.1.34",
471477
+ "0.1.35",
471478
471478
  " "
471479
471479
  ]
471480
471480
  }, undefined, true, undefined, this);
@@ -509921,9 +509921,39 @@ async function testConnection(conn) {
509921
509921
  await runQuery(conn, "SELECT 1 AS ok");
509922
509922
  return true;
509923
509923
  }
509924
- var import_tedious;
509924
+ function assertReadOnlySelect(sql) {
509925
+ const cleaned = sql.trim().replace(/;\s*$/, "").trim();
509926
+ if (!cleaned)
509927
+ throw new ReadOnlyGuardError("Empty query.");
509928
+ if (cleaned.includes(";"))
509929
+ throw new ReadOnlyGuardError('Only a single statement is allowed (no ";" chaining).');
509930
+ if (cleaned.includes("--") || cleaned.includes("/*"))
509931
+ throw new ReadOnlyGuardError("Comments are not allowed in the query.");
509932
+ if (!/^(with|select)\b/i.test(cleaned))
509933
+ throw new ReadOnlyGuardError("Query must start with SELECT (or WITH … SELECT).");
509934
+ const banned = cleaned.match(FORBIDDEN_TOKENS);
509935
+ if (banned)
509936
+ throw new ReadOnlyGuardError(`Query contains a disallowed keyword: "${banned[0]}". Only read-only SELECTs are permitted.`);
509937
+ return cleaned;
509938
+ }
509939
+ async function runReadOnlySelect(conn, sql, maxRows = READONLY_ROW_CAP) {
509940
+ const gated = assertReadOnlySelect(sql);
509941
+ const cap = Math.max(1, Math.min(maxRows, READONLY_ROW_CAP));
509942
+ const batch = `SET ROWCOUNT ${cap};
509943
+ ${gated};
509944
+ SET ROWCOUNT 0;`;
509945
+ return runQuery(conn, batch);
509946
+ }
509947
+ var import_tedious, READONLY_ROW_CAP = 50, FORBIDDEN_TOKENS, ReadOnlyGuardError;
509925
509948
  var init_mssqlClient = __esm(() => {
509926
509949
  import_tedious = __toESM(require_tedious(), 1);
509950
+ FORBIDDEN_TOKENS = /\b(insert|update|delete|merge|drop|alter|truncate|create|exec|execute|grant|revoke|into|waitfor|shutdown|reconfigure|backup|restore|openrowset|openquery|opendatasource|bulk|sp_[a-z0-9_]+|xp_[a-z0-9_]+)\b/i;
509951
+ ReadOnlyGuardError = class ReadOnlyGuardError extends Error {
509952
+ constructor(message) {
509953
+ super(message);
509954
+ this.name = "ReadOnlyGuardError";
509955
+ }
509956
+ };
509927
509957
  });
509928
509958
 
509929
509959
  // src/utils/sql/spMetadata.ts
@@ -510205,6 +510235,73 @@ How to judge matches (ESQL LANGUAGE DATABASE rules):
510205
510235
  - REAL mismatches are: parameter COUNT, ORDER, direction (IN/OUT), type incompatibility, and \`DYNAMIC RESULT SETS <n>\` not matching the actual result-set count above (e.g. declaring RESULT SETS 1 when the DB proc returns none — this breaks any code reading the result set).
510206
510236
  Report concrete functional mismatches with file:line, or confirm it matches.${GROUND}`;
510207
510237
  }
510238
+ function renderCell(v) {
510239
+ if (v === null || v === undefined)
510240
+ return "NULL";
510241
+ if (v instanceof Date)
510242
+ return v.toISOString();
510243
+ if (typeof v === "object" && v !== null && "length" in v)
510244
+ return `0x${Buffer.from(v).toString("hex")}`;
510245
+ return String(v);
510246
+ }
510247
+ async function runQueryCmd(conn, sql) {
510248
+ let rows;
510249
+ try {
510250
+ rows = await runReadOnlySelect(conn, sql);
510251
+ } catch (e2) {
510252
+ if (e2 instanceof ReadOnlyGuardError)
510253
+ return `Query rejected by the read-only gate: ${e2.message}
510254
+
510255
+ Rewrite it as a single SELECT (or WITH … SELECT) with no other statements.`;
510256
+ return `Query failed: ${e2.message}. This is the real database error — report it; do not invent rows.`;
510257
+ }
510258
+ if (rows.length === 0)
510259
+ return `The SELECT returned NO rows. This is a real result — it means no row in the database matches those conditions. Do NOT fabricate values; tell the user no matching data exists (for an "error/not-found" case this may be exactly what you want).`;
510260
+ const cols = Object.keys(rows[0]);
510261
+ const lines = rows.map((r, i3) => `${i3 + 1}. ${cols.map((c6) => `${c6}=${renderCell(r[c6])}`).join(", ")}`).join(`
510262
+ `);
510263
+ return `Real rows from the live database (${rows.length}, capped at ${READONLY_ROW_CAP}):
510264
+ ${lines}
510265
+
510266
+ These are ACTUAL values from the database. Use them exactly as returned — never alter, round, or invent field values. State only what appears above; if a value is not shown, say it is not shown.`;
510267
+ }
510268
+ async function runTestData(conn, schema, name, caseHint) {
510269
+ const def2 = await getProcedureDefinition(conn, schema, name);
510270
+ if (!def2) {
510271
+ return `Could not read the source of ${schema}.${name} (missing or WITH ENCRYPTION). Without the real T-SQL I cannot know which tables/columns to sample. Ask the user for the correct procedure name (try /sql procs) — do NOT guess test data.`;
510272
+ }
510273
+ const sp = await describeProcedure(conn, schema, name);
510274
+ const params = sp.params.map((p) => ` - ${p.isOutput ? "OUT" : "IN "} @${p.name} : ${p.dataType}${p.maxLength ? `(${p.maxLength})` : ""}`).join(`
510275
+ `) || " (no parameters)";
510276
+ const MAX = 24000;
510277
+ const body = def2.length > MAX ? `${def2.slice(0, MAX)}
510278
+ -- …[truncated]…` : def2;
510279
+ const wanted = caseHint || "happy";
510280
+ return `Goal: produce REAL, runnable test-data for a "${wanted}" case, expressed as the application's input body.
510281
+
510282
+ Ground truth for ${schema}.${name} (live database):
510283
+
510284
+ Parameters (these are what the SP consumes — trace each back to a request-body field):
510285
+ ${params}
510286
+
510287
+ Actual T-SQL source:
510288
+ \`\`\`sql
510289
+ ${body}
510290
+ \`\`\`
510291
+
510292
+ Do this, in order:
510293
+ 1. From the T-SQL above, identify the driving table(s) and the WHERE/branch conditions the input parameters flow into. For a "${wanted}" case:
510294
+ - happy → conditions that make the SP's main/success path return a row.
510295
+ - error/not-found → a key that does NOT exist, or values that hit the SP's empty-result / validation branch.
510296
+ - boundary → real extremes (e.g. longest value, min/max, nullable edges) drawn from the actual data.
510297
+ 2. Write ONE read-only SELECT that pulls a REAL row supplying the parameter values for that case (e.g. \`SELECT TOP 1 <param-columns> FROM <table> WHERE <branch conditions>\`). It MUST be a single SELECT/CTE — no other statements.
510298
+ 3. Run it by invoking the /sql skill with: query <your SELECT>
510299
+ (This executes it against the live DB through the read-only gate and returns the actual rows.)
510300
+ 4. Take the returned real values and map each SP parameter back to its request-body field by reading this project's ESQL (Grep the working directory for "${name}" to find the CALL and the field-to-parameter mapping) and the app's XSD (the input body field names).
510301
+ 5. Return the finished input body (XML matching the app's request schema) with the concrete real values filled in, and show the exact SELECT you ran so the developer can see where each value came from.
510302
+
510303
+ Data-handling notice (state this once to the user): these values are REAL data pulled from the connected database and may include personal/production data. Return them as-is; do not fabricate or substitute values. If the SELECT returns no rows, say so plainly — for a happy case it means no qualifying data exists; do not invent a row.`;
510304
+ }
510208
510305
  async function handle(args) {
510209
510306
  const trimmed = args.trim();
510210
510307
  if (!trimmed)
@@ -510299,6 +510396,24 @@ Do NOT attempt to answer database questions — you have no connection or data.`
510299
510396
  return `Failed to verify ${restStr}: ${e2.message}`;
510300
510397
  }
510301
510398
  }
510399
+ if (firstTok === "query") {
510400
+ if (!restStr)
510401
+ return "Usage: /sql query <SELECT …>";
510402
+ return await runQueryCmd(conn, restStr);
510403
+ }
510404
+ if (firstTok === "testdata" || firstTok === "test-data") {
510405
+ if (!restStr)
510406
+ return "Usage: /sql testdata <schema.proc|AppName> [happy|error|boundary] [notes]";
510407
+ const tokens = restStr.split(/\s+/);
510408
+ const target = extractProcName(restStr) ?? tokens[0];
510409
+ const { schema: schema2, name: name2 } = splitProc(target);
510410
+ const caseHint = restStr.match(/\b(happy|error|not[- ]?found|boundary|edge)\b/i)?.[1] ?? "";
510411
+ try {
510412
+ return await runTestData(conn, schema2, name2, caseHint.toLowerCase());
510413
+ } catch (e2) {
510414
+ return `Failed to prepare test data for ${schema2}.${name2}: ${e2.message}`;
510415
+ }
510416
+ }
510302
510417
  const intent = inferIntent(trimmed);
510303
510418
  if (intent === "list" && !extractProcName(trimmed)) {
510304
510419
  try {
@@ -510327,9 +510442,9 @@ Do NOT attempt to answer database questions — you have no connection or data.`
510327
510442
  function registerSqlSkill() {
510328
510443
  registerBundledSkill({
510329
510444
  name: "sql",
510330
- description: "Connect to a SQL Server database (read-only) to list/describe stored procedures, generate the ESQL SP call, or verify how an ACE app calls an SP — all from live DB metadata.",
510331
- whenToUse: "When the user asks about the SQL database, stored procedures (their inputs/outputs), wants an ESQL stored-procedure CALL generated from the DB, or wants to verify SP parameters used inside an ACE application.",
510332
- argumentHint: "connect|status|procs|describe|gen|verify … (or plain English)",
510445
+ description: "Connect to a SQL Server database (read-only) to list/describe stored procedures, generate the ESQL SP call, verify how an ACE app calls an SP, or produce real test-data input for an application from live tables — all from live DB metadata and gated read-only SELECTs.",
510446
+ whenToUse: "When the user asks about the SQL database, stored procedures (their inputs/outputs), wants an ESQL stored-procedure CALL generated from the DB, wants to verify SP parameters used inside an ACE application, or wants real test-data (a happy/error/boundary input body) for an application built from actual rows in the database.",
510447
+ argumentHint: "connect|status|procs|describe|gen|verify|testdata|query … (or plain English)",
510333
510448
  userInvocable: true,
510334
510449
  allowedTools: ["Read", "Glob", "Grep"],
510335
510450
  async getPromptForCommand(args) {
@@ -510341,7 +510456,15 @@ function registerSqlSkill() {
510341
510456
  }
510342
510457
  });
510343
510458
  }
510344
- var HELP = `# /sql — SQL Server helper (native connection)
510459
+ var HELP, GROUND = `
510460
+
510461
+ IMPORTANT: The metadata above is the ONLY database information you have — you cannot query the DB yourself. State only what appears above; never invent, guess, or "fill in" parameters, columns, types, or procedures. If something is not shown, say it is not shown.`, STOPWORDS;
510462
+ var init_sql = __esm(() => {
510463
+ init_bundledSkills();
510464
+ init_connectionStore();
510465
+ init_mssqlClient();
510466
+ init_spMetadata();
510467
+ HELP = `# /sql — SQL Server helper (native connection)
510345
510468
 
510346
510469
  Subcommands (also understands plain English, e.g. "/sql details of the SP Get_UserInformation"):
510347
510470
  - \`/sql connect server=HOST database=DB user=USER password=PASS [port=1433] [encrypt=false]\` — save the connection once (OS secure vault; password never written to disk in plaintext).
@@ -510352,15 +510475,10 @@ Subcommands (also understands plain English, e.g. "/sql details of the SP Get_Us
510352
510475
  - \`/sql source <schema.proc>\` — the actual T-SQL body of the procedure (read the real code).
510353
510476
  - \`/sql gen <schema.proc>\` — generate the ESQL PROCEDURE declaration + CALL.
510354
510477
  - \`/sql verify <schema.proc>\` — pull the real SP signature, then check how this project's ESQL calls it.
510478
+ - \`/sql testdata <schema.proc|AppName> [happy|error|boundary] [notes]\` — read the SP's real T-SQL, pull a REAL matching row from the database, and return it as the application's input body.
510479
+ - \`/sql query <SELECT …>\` — run one read-only SELECT (SELECT/CTE only, capped to ${READONLY_ROW_CAP} rows). Used by /sql testdata to fetch real rows.
510355
510480
 
510356
- Everything is read-only and every answer comes from live DB metadata.`, GROUND = `
510357
-
510358
- IMPORTANT: The metadata above is the ONLY database information you have — you cannot query the DB yourself. State only what appears above; never invent, guess, or "fill in" parameters, columns, types, or procedures. If something is not shown, say it is not shown.`, STOPWORDS;
510359
- var init_sql = __esm(() => {
510360
- init_bundledSkills();
510361
- init_connectionStore();
510362
- init_mssqlClient();
510363
- init_spMetadata();
510481
+ Metadata/verify/gen are read-only catalog lookups. \`testdata\`/\`query\` execute a single gated SELECT against real tables and return ACTUAL data (which may include personal/production data).`;
510364
510482
  STOPWORDS = new Set([
510365
510483
  "sp",
510366
510484
  "the",
@@ -527012,7 +527130,7 @@ Usage: orbit --remote "your task description"`, () => gracefulShutdown(1));
527012
527130
  pendingHookMessages
527013
527131
  }, renderAndRun);
527014
527132
  }
527015
- }).version("0.1.34 (Orbit AI)", "-v, --version", "Output the version number");
527133
+ }).version("0.1.35 (Orbit AI)", "-v, --version", "Output the version number");
527016
527134
  program2.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
527017
527135
  program2.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
527018
527136
  if (canUserConfigureAdvisor()) {
@@ -527534,7 +527652,7 @@ if (false) {}
527534
527652
  async function main2() {
527535
527653
  const args = process.argv.slice(2);
527536
527654
  if (args.length === 1 && (args[0] === "--version" || args[0] === "-v" || args[0] === "-V")) {
527537
- console.log(`${"0.1.34"} (Orbit AI)`);
527655
+ console.log(`${"0.1.35"} (Orbit AI)`);
527538
527656
  return;
527539
527657
  }
527540
527658
  if (args.includes("--provider")) {
@@ -527638,4 +527756,4 @@ async function main2() {
527638
527756
  }
527639
527757
  main2();
527640
527758
 
527641
- //# debugId=2DF01C013452CDF264756E2164756E21
527759
+ //# debugId=29BC5C9893E4168464756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orbit-code-ai",
3
- "version": "0.1.34",
3
+ "version": "0.1.35",
4
4
  "description": "Orbit AI – Your AI-powered IBM ACE coding companion",
5
5
  "type": "module",
6
6
  "author": "moenawaf",