llm-cli-gateway 2.11.0 → 2.12.0

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 (36) hide show
  1. package/.agents/skills/async-job-orchestration/SKILL.md +288 -0
  2. package/.agents/skills/implement-review-fix/SKILL.md +154 -0
  3. package/.agents/skills/multi-llm-review/SKILL.md +174 -0
  4. package/.agents/skills/public-demo-session/SKILL.md +100 -0
  5. package/.agents/skills/secure-orchestration/SKILL.md +227 -0
  6. package/.agents/skills/session-workflow/SKILL.md +271 -0
  7. package/CHANGELOG.md +63 -1
  8. package/README.md +86 -27
  9. package/dist/acp/provider-registry.js +6 -6
  10. package/dist/api-provider.d.ts +7 -0
  11. package/dist/api-provider.js +7 -0
  12. package/dist/api-request.js +1 -0
  13. package/dist/async-job-manager.d.ts +11 -1
  14. package/dist/async-job-manager.js +44 -3
  15. package/dist/config.d.ts +2 -0
  16. package/dist/config.js +3 -0
  17. package/dist/index.d.ts +40 -4
  18. package/dist/index.js +611 -158
  19. package/dist/job-store.d.ts +48 -1
  20. package/dist/job-store.js +184 -0
  21. package/dist/provider-codegen.js +3 -0
  22. package/dist/provider-tool-capabilities.d.ts +4 -0
  23. package/dist/provider-tool-capabilities.js +16 -13
  24. package/dist/upstream-contracts.d.ts +1 -0
  25. package/dist/upstream-contracts.js +202 -45
  26. package/dist/validation-orchestrator.d.ts +5 -2
  27. package/dist/validation-orchestrator.js +71 -5
  28. package/dist/validation-receipt.d.ts +68 -0
  29. package/dist/validation-receipt.js +245 -0
  30. package/dist/validation-report.d.ts +4 -2
  31. package/dist/validation-report.js +18 -1
  32. package/dist/validation-tools.js +58 -9
  33. package/npm-shrinkwrap.json +5 -5
  34. package/package.json +10 -4
  35. package/dist/xai-api-provider.d.ts +0 -43
  36. package/dist/xai-api-provider.js +0 -191
@@ -73,7 +73,46 @@ export interface OrphanedJobSnapshot {
73
73
  transport: JobTransport;
74
74
  httpStatus: number | null;
75
75
  }
76
- export declare class SqliteJobStore implements JobStore {
76
+ export interface ValidationRunLink {
77
+ provider: string;
78
+ jobId: string;
79
+ correlationId: string;
80
+ }
81
+ export interface ValidationRunRecord {
82
+ validationId: string;
83
+ ownerPrincipal: string;
84
+ intent: string;
85
+ createdAt: string;
86
+ requestJson: string;
87
+ providerLinks: ValidationRunLink[];
88
+ judgeLink: ValidationRunLink | null;
89
+ status: "running" | "finalized";
90
+ }
91
+ export interface ValidationReceiptRecord {
92
+ validationId: string;
93
+ ownerPrincipal: string;
94
+ mintedAt: string;
95
+ schemaVersion: string;
96
+ reportJson: string;
97
+ canonicalSha256: string;
98
+ prevSha256: string | null;
99
+ seq: number | null;
100
+ signature: string | null;
101
+ models: string[];
102
+ hasMaterialDisagreement: boolean;
103
+ confidence: string;
104
+ }
105
+ export interface ValidationRunStore {
106
+ recordValidationRun(run: ValidationRunRecord): void;
107
+ getValidationRun(validationId: string): ValidationRunRecord | null;
108
+ setValidationJudgeLink(validationId: string, judgeLink: ValidationRunLink): void;
109
+ setValidationRunStatus(validationId: string, status: ValidationRunRecord["status"]): void;
110
+ getValidationRunIdByJobId(jobId: string): string | null;
111
+ recordValidationReceipt(receipt: ValidationReceiptRecord): void;
112
+ getValidationReceipt(validationId: string): ValidationReceiptRecord | null;
113
+ }
114
+ export declare function isValidationRunStore(store: unknown): store is ValidationRunStore;
115
+ export declare class SqliteJobStore implements JobStore, ValidationRunStore {
77
116
  private logger;
78
117
  private db;
79
118
  private retentionMs;
@@ -122,6 +161,14 @@ export declare class SqliteJobStore implements JobStore {
122
161
  orphaned: Array<OrphanedJobSnapshot>;
123
162
  };
124
163
  evictExpired(): number;
164
+ recordValidationRun(run: ValidationRunRecord): void;
165
+ private linkRunJob;
166
+ getValidationRunIdByJobId(jobId: string): string | null;
167
+ getValidationRun(validationId: string): ValidationRunRecord | null;
168
+ setValidationJudgeLink(validationId: string, judgeLink: ValidationRunLink): void;
169
+ setValidationRunStatus(validationId: string, status: ValidationRunRecord["status"]): void;
170
+ recordValidationReceipt(receipt: ValidationReceiptRecord): void;
171
+ getValidationReceipt(validationId: string): ValidationReceiptRecord | null;
125
172
  close(): void;
126
173
  }
127
174
  export declare const JobStoreClass: typeof SqliteJobStore;
package/dist/job-store.js CHANGED
@@ -83,6 +83,13 @@ function ensureJobsTransportColumns(db) {
83
83
  db.exec("ALTER TABLE jobs ADD COLUMN payload_json TEXT");
84
84
  }
85
85
  }
86
+ export function isValidationRunStore(store) {
87
+ return (typeof store === "object" &&
88
+ store !== null &&
89
+ typeof store.recordValidationRun === "function" &&
90
+ typeof store.getValidationRun === "function" &&
91
+ typeof store.recordValidationReceipt === "function");
92
+ }
86
93
  export class SqliteJobStore {
87
94
  logger;
88
95
  db;
@@ -128,6 +135,42 @@ export class SqliteJobStore {
128
135
  CREATE INDEX IF NOT EXISTS idx_jobs_status ON jobs(status);
129
136
  CREATE INDEX IF NOT EXISTS idx_jobs_expires_at ON jobs(expires_at);
130
137
  CREATE INDEX IF NOT EXISTS idx_jobs_request_key_finished ON jobs(request_key, finished_at);
138
+ `);
139
+ this.db.exec(`
140
+ CREATE TABLE IF NOT EXISTS validation_runs (
141
+ validation_id TEXT PRIMARY KEY,
142
+ owner_principal TEXT NOT NULL,
143
+ intent TEXT NOT NULL,
144
+ created_at TEXT NOT NULL,
145
+ request_json TEXT NOT NULL,
146
+ provider_links TEXT NOT NULL,
147
+ judge_link TEXT,
148
+ status TEXT NOT NULL
149
+ );
150
+ CREATE INDEX IF NOT EXISTS idx_validation_runs_owner ON validation_runs(owner_principal);
151
+ `);
152
+ this.db.exec(`
153
+ CREATE TABLE IF NOT EXISTS validation_run_jobs (
154
+ job_id TEXT PRIMARY KEY,
155
+ validation_id TEXT NOT NULL,
156
+ role TEXT NOT NULL
157
+ );
158
+ CREATE INDEX IF NOT EXISTS idx_validation_run_jobs_run ON validation_run_jobs(validation_id);
159
+ CREATE TABLE IF NOT EXISTS validation_receipts (
160
+ validation_id TEXT PRIMARY KEY,
161
+ owner_principal TEXT NOT NULL,
162
+ minted_at TEXT NOT NULL,
163
+ schema_version TEXT NOT NULL,
164
+ report_json TEXT NOT NULL,
165
+ canonical_sha256 TEXT NOT NULL,
166
+ prev_sha256 TEXT,
167
+ seq INTEGER,
168
+ signature TEXT,
169
+ models TEXT NOT NULL,
170
+ has_material_disagreement INTEGER NOT NULL,
171
+ confidence TEXT NOT NULL
172
+ );
173
+ CREATE INDEX IF NOT EXISTS idx_validation_receipts_owner ON validation_receipts(owner_principal);
131
174
  `);
132
175
  ensureJobsOwnerColumn(this.db);
133
176
  ensureJobsTransportColumns(this.db);
@@ -262,6 +305,86 @@ export class SqliteJobStore {
262
305
  const result = this.deleteExpiredStmt.run(now);
263
306
  return Number(result.changes);
264
307
  }
308
+ recordValidationRun(run) {
309
+ this.db
310
+ .prepare(`INSERT OR IGNORE INTO validation_runs
311
+ (validation_id, owner_principal, intent, created_at, request_json,
312
+ provider_links, judge_link, status)
313
+ VALUES (@validation_id, @owner_principal, @intent, @created_at, @request_json,
314
+ @provider_links, @judge_link, @status)`)
315
+ .run({
316
+ validation_id: run.validationId,
317
+ owner_principal: run.ownerPrincipal,
318
+ intent: run.intent,
319
+ created_at: run.createdAt,
320
+ request_json: run.requestJson,
321
+ provider_links: JSON.stringify(run.providerLinks),
322
+ judge_link: run.judgeLink ? JSON.stringify(run.judgeLink) : null,
323
+ status: run.status,
324
+ });
325
+ for (const link of run.providerLinks) {
326
+ this.linkRunJob(run.validationId, link.jobId, "provider");
327
+ }
328
+ }
329
+ linkRunJob(validationId, jobId, role) {
330
+ this.db
331
+ .prepare(`INSERT OR IGNORE INTO validation_run_jobs (job_id, validation_id, role)
332
+ VALUES (?, ?, ?)`)
333
+ .run(jobId, validationId, role);
334
+ }
335
+ getValidationRunIdByJobId(jobId) {
336
+ const row = this.db
337
+ .prepare(`SELECT validation_id FROM validation_run_jobs WHERE job_id = ?`)
338
+ .get(jobId);
339
+ return row?.validation_id ?? null;
340
+ }
341
+ getValidationRun(validationId) {
342
+ const row = this.db
343
+ .prepare(`SELECT * FROM validation_runs WHERE validation_id = ?`)
344
+ .get(validationId);
345
+ return row ? rowToValidationRunRecord(row) : null;
346
+ }
347
+ setValidationJudgeLink(validationId, judgeLink) {
348
+ this.db
349
+ .prepare(`UPDATE validation_runs SET judge_link = ? WHERE validation_id = ?`)
350
+ .run(JSON.stringify(judgeLink), validationId);
351
+ this.linkRunJob(validationId, judgeLink.jobId, "judge");
352
+ }
353
+ setValidationRunStatus(validationId, status) {
354
+ this.db
355
+ .prepare(`UPDATE validation_runs SET status = ? WHERE validation_id = ?`)
356
+ .run(status, validationId);
357
+ }
358
+ recordValidationReceipt(receipt) {
359
+ this.db
360
+ .prepare(`INSERT OR IGNORE INTO validation_receipts
361
+ (validation_id, owner_principal, minted_at, schema_version, report_json,
362
+ canonical_sha256, prev_sha256, seq, signature, models,
363
+ has_material_disagreement, confidence)
364
+ VALUES (@validation_id, @owner_principal, @minted_at, @schema_version, @report_json,
365
+ @canonical_sha256, @prev_sha256, @seq, @signature, @models,
366
+ @has_material_disagreement, @confidence)`)
367
+ .run({
368
+ validation_id: receipt.validationId,
369
+ owner_principal: receipt.ownerPrincipal,
370
+ minted_at: receipt.mintedAt,
371
+ schema_version: receipt.schemaVersion,
372
+ report_json: receipt.reportJson,
373
+ canonical_sha256: receipt.canonicalSha256,
374
+ prev_sha256: receipt.prevSha256,
375
+ seq: receipt.seq,
376
+ signature: receipt.signature,
377
+ models: JSON.stringify(receipt.models),
378
+ has_material_disagreement: receipt.hasMaterialDisagreement ? 1 : 0,
379
+ confidence: receipt.confidence,
380
+ });
381
+ }
382
+ getValidationReceipt(validationId) {
383
+ const row = this.db
384
+ .prepare(`SELECT * FROM validation_receipts WHERE validation_id = ?`)
385
+ .get(validationId);
386
+ return row ? rowToValidationReceiptRecord(row) : null;
387
+ }
265
388
  close() {
266
389
  try {
267
390
  this.db.close();
@@ -271,6 +394,67 @@ export class SqliteJobStore {
271
394
  }
272
395
  }
273
396
  }
397
+ function rowToValidationRunRecord(row) {
398
+ return {
399
+ validationId: row.validation_id,
400
+ ownerPrincipal: row.owner_principal,
401
+ intent: row.intent,
402
+ createdAt: row.created_at,
403
+ requestJson: row.request_json,
404
+ providerLinks: parseLinks(row.provider_links) ?? [],
405
+ judgeLink: parseLink(row.judge_link),
406
+ status: row.status,
407
+ };
408
+ }
409
+ function rowToValidationReceiptRecord(row) {
410
+ return {
411
+ validationId: row.validation_id,
412
+ ownerPrincipal: row.owner_principal,
413
+ mintedAt: row.minted_at,
414
+ schemaVersion: row.schema_version,
415
+ reportJson: row.report_json,
416
+ canonicalSha256: row.canonical_sha256,
417
+ prevSha256: row.prev_sha256 ?? null,
418
+ seq: row.seq ?? null,
419
+ signature: row.signature ?? null,
420
+ models: parseStringArray(row.models),
421
+ hasMaterialDisagreement: Boolean(row.has_material_disagreement),
422
+ confidence: row.confidence,
423
+ };
424
+ }
425
+ function parseLinks(value) {
426
+ if (typeof value !== "string" || value.length === 0)
427
+ return null;
428
+ try {
429
+ const parsed = JSON.parse(value);
430
+ return Array.isArray(parsed) ? parsed : null;
431
+ }
432
+ catch {
433
+ return null;
434
+ }
435
+ }
436
+ function parseStringArray(value) {
437
+ if (typeof value !== "string" || value.length === 0)
438
+ return [];
439
+ try {
440
+ const parsed = JSON.parse(value);
441
+ return Array.isArray(parsed) ? parsed : [];
442
+ }
443
+ catch {
444
+ return [];
445
+ }
446
+ }
447
+ function parseLink(value) {
448
+ if (typeof value !== "string" || value.length === 0)
449
+ return null;
450
+ try {
451
+ const parsed = JSON.parse(value);
452
+ return parsed && typeof parsed === "object" ? parsed : null;
453
+ }
454
+ catch {
455
+ return null;
456
+ }
457
+ }
274
458
  export const JobStoreClass = SqliteJobStore;
275
459
  export class MemoryJobStore {
276
460
  rows = new Map();
@@ -329,6 +329,9 @@ export const UNGENERATED_GROK_FLAGS = [
329
329
  "--agents",
330
330
  "--prompt-json",
331
331
  "--worktree",
332
+ "--worktree-ref",
333
+ "--fork-session",
334
+ "--json-schema",
332
335
  "-p",
333
336
  "--resume",
334
337
  "--continue",
@@ -133,4 +133,8 @@ export type ProviderToolCapabilitiesMap = Partial<Record<ProviderCapabilityId, P
133
133
  export declare function getProviderToolCapabilities(queryOrCli?: ProviderCapabilityQuery | ProviderCapabilityId): ProviderToolCapabilitiesMap;
134
134
  export declare function getOneProviderToolCapabilities(cli: ProviderCapabilityId, queryOrCli?: ProviderCapabilityQuery | ProviderCapabilityId): ProviderToolCapabilities;
135
135
  export declare function clearProviderToolCapabilitiesCache(): void;
136
+ export declare function _getCapabilityCacheForTest(): Map<string, {
137
+ loadedAt: number;
138
+ value: ProviderToolCapabilities;
139
+ }>;
136
140
  export declare function providerCapabilityIds(): readonly KnownProviderCapabilityId[];
@@ -49,7 +49,7 @@ export const ACP_CONTRACT = {
49
49
  },
50
50
  gemini: {
51
51
  classification: "absent_watchlist",
52
- summary: "Google Antigravity agy 1.0.7 has no ACP surface; watchlist item only.",
52
+ summary: "Google Antigravity agy 1.0.13 has no ACP surface; watchlist item only.",
53
53
  },
54
54
  grok_api: {
55
55
  classification: "absent_watchlist",
@@ -66,7 +66,7 @@ const ACP_CAPABILITIES = {
66
66
  mistral: {
67
67
  status: "native_smoke_passed",
68
68
  mediation: "native",
69
- targetVersion: "vibe 2.14.1",
69
+ targetVersion: "vibe 2.17.1",
70
70
  entrypoint: { command: "vibe-acp", args: [] },
71
71
  runtimeEnabled: false,
72
72
  smokeSupported: true,
@@ -80,7 +80,7 @@ const ACP_CAPABILITIES = {
80
80
  grok: {
81
81
  status: "native_smoke_passed",
82
82
  mediation: "native",
83
- targetVersion: "grok 0.2.50 (cadf94855)",
83
+ targetVersion: "grok 0.2.73 (9ff14c43bb)",
84
84
  entrypoint: { command: "grok", args: ["agent", "stdio"] },
85
85
  runtimeEnabled: false,
86
86
  smokeSupported: true,
@@ -95,7 +95,7 @@ const ACP_CAPABILITIES = {
95
95
  codex: {
96
96
  status: "adapter_mediated_deferred",
97
97
  mediation: "adapter_mediated",
98
- targetVersion: "codex-cli 0.139.0",
98
+ targetVersion: "codex-cli 0.142.4",
99
99
  entrypoint: null,
100
100
  runtimeEnabled: false,
101
101
  smokeSupported: false,
@@ -109,7 +109,7 @@ const ACP_CAPABILITIES = {
109
109
  claude: {
110
110
  status: "adapter_mediated_deferred",
111
111
  mediation: "adapter_mediated",
112
- targetVersion: "claude 2.1.175",
112
+ targetVersion: "claude 2.1.195",
113
113
  entrypoint: null,
114
114
  runtimeEnabled: false,
115
115
  smokeSupported: false,
@@ -123,13 +123,13 @@ const ACP_CAPABILITIES = {
123
123
  gemini: {
124
124
  status: "absent_watchlist",
125
125
  mediation: "none",
126
- targetVersion: "agy 1.0.7",
126
+ targetVersion: "agy 1.0.13",
127
127
  entrypoint: null,
128
128
  runtimeEnabled: false,
129
129
  smokeSupported: false,
130
130
  smokeStatus: "unsupported",
131
131
  caveats: [
132
- "Antigravity agy 1.0.7 has no ACP flag or subcommand.",
132
+ "Antigravity agy 1.0.13 has no ACP flag or subcommand.",
133
133
  "Legacy Gemini CLI ACP evidence does not transfer to agy; kept on the upstream drift watchlist.",
134
134
  ],
135
135
  docs: ACP_DOCS_REFERENCE,
@@ -148,7 +148,7 @@ const ACP_CAPABILITIES = {
148
148
  devin: {
149
149
  status: "native_smoke_passed",
150
150
  mediation: "native",
151
- targetVersion: "devin 2026.5.26-8 (1a388fa9)",
151
+ targetVersion: "devin 2026.8.18 (16737566)",
152
152
  entrypoint: { command: "devin", args: ["acp"] },
153
153
  runtimeEnabled: false,
154
154
  smokeSupported: true,
@@ -777,7 +777,7 @@ const TOOL_CONTROLS = {
777
777
  supported: true,
778
778
  requestField: "permissionMode",
779
779
  cliFlag: "--permission-mode",
780
- behavior: "Maps to Devin CLI --permission-mode: normal (alias auto) auto-approves read-only tools; dangerous (aliases yolo, bypass) auto-approves all.",
780
+ behavior: "Maps to Devin CLI --permission-mode: auto auto-approves read-only tools; smart additionally auto-runs actions a fast model judges safe; dangerous auto-approves all.",
781
781
  },
782
782
  promptControl: {
783
783
  supported: true,
@@ -806,7 +806,7 @@ const TOOL_CONTROLS = {
806
806
  ],
807
807
  },
808
808
  };
809
- let capabilityCache = new Map();
809
+ const CAPABILITY_CACHE = new Map();
810
810
  export function getProviderToolCapabilities(queryOrCli = {}) {
811
811
  const query = normalizeQuery(queryOrCli);
812
812
  const providers = query.cli ? [query.cli] : PROVIDER_CAPABILITY_IDS;
@@ -819,16 +819,19 @@ export function getProviderToolCapabilities(queryOrCli = {}) {
819
819
  export function getOneProviderToolCapabilities(cli, queryOrCli = {}) {
820
820
  const query = normalizeQuery(typeof queryOrCli === "string" ? { cli: queryOrCli } : queryOrCli);
821
821
  const cacheKey = capabilityCacheKey(cli, query);
822
- const cached = capabilityCache.get(cacheKey);
822
+ const cached = CAPABILITY_CACHE.get(cacheKey);
823
823
  if (!query.refresh && cached && Date.now() - cached.loadedAt < CAPABILITY_CACHE_TTL_MS) {
824
824
  return cached.value;
825
825
  }
826
826
  const value = buildOneProviderToolCapabilities(cli, query);
827
- capabilityCache.set(cacheKey, { loadedAt: Date.now(), value });
827
+ CAPABILITY_CACHE.set(cacheKey, { loadedAt: Date.now(), value });
828
828
  return value;
829
829
  }
830
830
  export function clearProviderToolCapabilitiesCache() {
831
- capabilityCache = new Map();
831
+ CAPABILITY_CACHE.clear();
832
+ }
833
+ export function _getCapabilityCacheForTest() {
834
+ return CAPABILITY_CACHE;
832
835
  }
833
836
  export function providerCapabilityIds() {
834
837
  return PROVIDER_CAPABILITY_IDS;
@@ -62,6 +62,7 @@ export interface CliSubcommandContract {
62
62
  tokenCost: CliSubcommandTokenCost;
63
63
  summary: string;
64
64
  conformanceFixtures: readonly CliContractFixture[];
65
+ helpProbeExitTolerant?: boolean;
65
66
  }
66
67
  export interface ContractViolation {
67
68
  cli: CliType;