orbit-code-ai 0.1.33 → 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.
- package/dist/cli.mjs +141 -23
- 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.
|
|
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-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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 =
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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=
|
|
527759
|
+
//# debugId=29BC5C9893E4168464756E2164756E21
|