@smithers-orchestrator/agents 0.20.4 → 0.21.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smithers-orchestrator/agents",
3
- "version": "0.20.4",
3
+ "version": "0.21.0",
4
4
  "description": "AI SDK and CLI agent adapters for Smithers",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -50,9 +50,9 @@
50
50
  "ai": "^6.0.168",
51
51
  "effect": "^3.21.1",
52
52
  "zod": "^4.3.6",
53
- "@smithers-orchestrator/errors": "0.20.4",
54
- "@smithers-orchestrator/driver": "0.20.4",
55
- "@smithers-orchestrator/observability": "0.20.4"
53
+ "@smithers-orchestrator/errors": "0.21.0",
54
+ "@smithers-orchestrator/observability": "0.21.0",
55
+ "@smithers-orchestrator/driver": "0.21.0"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/bun": "latest",
@@ -0,0 +1,267 @@
1
+ import { BaseCliAgent, pushFlag, pushList, isRecord, asString, truncate, toolKindFromName, createSyntheticIdGenerator, } from "./BaseCliAgent/index.js";
2
+ import { normalizeCapabilityStringList, } from "./capability-registry/index.js";
3
+ /** @typedef {import("./capability-registry/AgentCapabilityRegistry.ts").AgentCapabilityRegistry} AgentCapabilityRegistry */
4
+ /** @typedef {import("./BaseCliAgent/CliOutputInterpreter.ts").CliOutputInterpreter} CliOutputInterpreter */
5
+ /** @typedef {import("./AntigravityAgentOptions.ts").AntigravityAgentOptions} AntigravityAgentOptions */
6
+
7
+ /**
8
+ * @param {AntigravityAgentOptions} opts
9
+ */
10
+ function resolveAntigravityBuiltIns(opts) {
11
+ return opts.allowedTools?.length
12
+ ? normalizeCapabilityStringList(opts.allowedTools)
13
+ : ["default"];
14
+ }
15
+
16
+ /**
17
+ * @param {AntigravityAgentOptions} [opts]
18
+ * @returns {AgentCapabilityRegistry}
19
+ */
20
+ export function createAntigravityCapabilityRegistry(opts = {}) {
21
+ return {
22
+ version: 1,
23
+ engine: "antigravity",
24
+ runtimeTools: {},
25
+ mcp: {
26
+ bootstrap: "project-config",
27
+ supportsProjectScope: true,
28
+ supportsUserScope: true,
29
+ },
30
+ skills: {
31
+ supportsSkills: true,
32
+ installMode: "plugin",
33
+ smithersSkillIds: [],
34
+ },
35
+ humanInteraction: {
36
+ supportsUiRequests: false,
37
+ methods: [],
38
+ },
39
+ builtIns: resolveAntigravityBuiltIns(opts),
40
+ };
41
+ }
42
+
43
+ export class AntigravityAgent extends BaseCliAgent {
44
+ opts;
45
+ capabilities;
46
+ cliEngine = "antigravity";
47
+ /**
48
+ * @param {AntigravityAgentOptions} [opts]
49
+ */
50
+ constructor(opts = {}) {
51
+ super(opts);
52
+ this.opts = opts;
53
+ this.capabilities = createAntigravityCapabilityRegistry(opts);
54
+ }
55
+ /**
56
+ * @returns {CliOutputInterpreter}
57
+ */
58
+ createOutputInterpreter() {
59
+ let sessionId;
60
+ let finalAnswer = "";
61
+ let didEmitCompleted = false;
62
+ const nextSyntheticId = createSyntheticIdGenerator();
63
+ /**
64
+ * @param {string} line
65
+ * @returns {AgentCliEvent[]}
66
+ */
67
+ const parseLine = (line) => {
68
+ const trimmed = line.trim();
69
+ if (!trimmed)
70
+ return [];
71
+ let payload;
72
+ try {
73
+ payload = JSON.parse(trimmed);
74
+ }
75
+ catch {
76
+ return [];
77
+ }
78
+ if (!isRecord(payload))
79
+ return [];
80
+ const type = asString(payload.type);
81
+ if (!type)
82
+ return [];
83
+ if (type === "init") {
84
+ const resume = asString(payload.session_id);
85
+ if (resume) {
86
+ sessionId = resume;
87
+ }
88
+ return [{
89
+ type: "started",
90
+ engine: this.cliEngine,
91
+ title: "Antigravity CLI",
92
+ resume: sessionId,
93
+ detail: {
94
+ model: asString(payload.model),
95
+ },
96
+ }];
97
+ }
98
+ if (type === "MESSAGE") {
99
+ const role = asString(payload.role);
100
+ const content = asString(payload.content);
101
+ if (role === "assistant" && content) {
102
+ if (payload.delta === true) {
103
+ finalAnswer += content;
104
+ }
105
+ else {
106
+ finalAnswer = content;
107
+ }
108
+ }
109
+ return [];
110
+ }
111
+ if (type === "TOOL_USE") {
112
+ const toolName = asString(payload.tool_name) ?? "tool";
113
+ const toolId = asString(payload.tool_id) ?? nextSyntheticId("antigravity-tool");
114
+ return [{
115
+ type: "action",
116
+ engine: this.cliEngine,
117
+ phase: "started",
118
+ entryType: "thought",
119
+ action: {
120
+ id: toolId,
121
+ kind: toolKindFromName(toolName),
122
+ title: toolName,
123
+ detail: {
124
+ parameters: payload.parameters,
125
+ },
126
+ },
127
+ message: `Running ${toolName}`,
128
+ level: "info",
129
+ }];
130
+ }
131
+ if (type === "TOOL_RESULT") {
132
+ const toolId = asString(payload.tool_id) ?? nextSyntheticId("antigravity-tool");
133
+ const ok = asString(payload.status) !== "error";
134
+ const error = isRecord(payload.error) ? asString(payload.error.message) : undefined;
135
+ const output = asString(payload.output);
136
+ return [{
137
+ type: "action",
138
+ engine: this.cliEngine,
139
+ phase: "completed",
140
+ entryType: "thought",
141
+ action: {
142
+ id: toolId,
143
+ kind: "tool",
144
+ title: "tool result",
145
+ detail: {
146
+ status: asString(payload.status),
147
+ output: output ? truncate(output, 400) : undefined,
148
+ },
149
+ },
150
+ message: error ?? output,
151
+ ok,
152
+ level: ok ? "info" : "warning",
153
+ }];
154
+ }
155
+ if (type === "ERROR") {
156
+ return [{
157
+ type: "action",
158
+ engine: this.cliEngine,
159
+ phase: "completed",
160
+ entryType: "thought",
161
+ action: {
162
+ id: nextSyntheticId("antigravity-warning"),
163
+ kind: "warning",
164
+ title: "warning",
165
+ detail: {
166
+ severity: asString(payload.severity),
167
+ },
168
+ },
169
+ message: asString(payload.message),
170
+ ok: asString(payload.severity) !== "error",
171
+ level: asString(payload.severity) === "error" ? "error" : "warning",
172
+ }];
173
+ }
174
+ if (type === "RESULT") {
175
+ if (didEmitCompleted)
176
+ return [];
177
+ didEmitCompleted = true;
178
+ return [{
179
+ type: "completed",
180
+ engine: this.cliEngine,
181
+ ok: asString(payload.status) !== "error",
182
+ answer: finalAnswer || asString(payload.response),
183
+ resume: sessionId,
184
+ usage: isRecord(payload.stats) ? payload.stats : undefined,
185
+ }];
186
+ }
187
+ return [];
188
+ };
189
+ return {
190
+ onStdoutLine: parseLine,
191
+ onExit: (result) => {
192
+ if (didEmitCompleted)
193
+ return [];
194
+ if (result.exitCode === 0)
195
+ return [];
196
+ didEmitCompleted = true;
197
+ return [{
198
+ type: "completed",
199
+ engine: this.cliEngine,
200
+ ok: false,
201
+ answer: finalAnswer || undefined,
202
+ error: result.stderr.trim() || `Antigravity exited with code ${result.exitCode}`,
203
+ resume: sessionId,
204
+ }];
205
+ },
206
+ };
207
+ }
208
+ /**
209
+ * @param {{ prompt: string; systemPrompt?: string; cwd: string; options: any; }} params
210
+ */
211
+ async buildCommand(params) {
212
+ const args = [];
213
+ const yoloEnabled = this.opts.dangerouslySkipPermissions ?? this.opts.yolo ?? this.yolo;
214
+ const outputFormat = this.opts.outputFormat ??
215
+ (params.options?.onEvent ? "stream-json" : "json");
216
+ const resumeSession = typeof params.options?.resumeSession === "string"
217
+ ? params.options.resumeSession
218
+ : this.opts.resume;
219
+ if (this.opts.debug)
220
+ args.push("--debug");
221
+ pushFlag(args, "--model", this.opts.model ?? this.model);
222
+ if (this.opts.sandbox)
223
+ args.push("--sandbox");
224
+ if (yoloEnabled)
225
+ args.push("--dangerously-skip-permissions");
226
+ pushList(args, "--allowed-mcp-server-names", this.opts.allowedMcpServerNames);
227
+ if (this.opts.allowedTools !== undefined) {
228
+ if (this.opts.allowedTools.length === 0) {
229
+ pushFlag(args, "--allowed-tools", "");
230
+ }
231
+ else {
232
+ pushList(args, "--allowed-tools", this.opts.allowedTools);
233
+ }
234
+ }
235
+ pushList(args, "--extensions", this.opts.extensions);
236
+ if (this.opts.listExtensions)
237
+ args.push("--list-extensions");
238
+ pushFlag(args, "--resume", resumeSession);
239
+ if (this.opts.listSessions)
240
+ args.push("--list-sessions");
241
+ pushFlag(args, "--delete-session", this.opts.deleteSession);
242
+ pushList(args, "--include-directories", this.opts.includeDirectories);
243
+ if (this.opts.screenReader)
244
+ args.push("--screen-reader");
245
+ pushFlag(args, "--gemini_dir", this.opts.geminiDir ?? this.opts.configDir);
246
+ pushFlag(args, "--output-format", outputFormat);
247
+ if (this.extraArgs?.length)
248
+ args.push(...this.extraArgs);
249
+ const systemPrefix = params.systemPrompt
250
+ ? `${params.systemPrompt}\n\n`
251
+ : "";
252
+ const jsonReminder = params.prompt?.includes("REQUIRED OUTPUT")
253
+ ? "\n\nREMINDER: Your response MUST be ONLY the required raw JSON object. Do not include prose, markdown, or code fences. The first character must be `{` and the last character must be `}`.\n"
254
+ : "";
255
+ const fullPrompt = `${systemPrefix}${params.prompt ?? ""}${jsonReminder}`;
256
+ args.push("--prompt", fullPrompt);
257
+ const accountEnv = {};
258
+ if (this.opts.apiKey)
259
+ accountEnv.GEMINI_API_KEY = this.opts.apiKey;
260
+ return {
261
+ command: this.opts.binary ?? "agy",
262
+ args,
263
+ outputFormat,
264
+ env: Object.keys(accountEnv).length > 0 ? accountEnv : undefined,
265
+ };
266
+ }
267
+ }
@@ -0,0 +1,38 @@
1
+ import type { BaseCliAgentOptions } from "./BaseCliAgent/BaseCliAgentOptions";
2
+
3
+ export type AntigravityAgentOptions = BaseCliAgentOptions & {
4
+ debug?: boolean;
5
+ model?: string;
6
+ sandbox?: boolean;
7
+ yolo?: boolean;
8
+ dangerouslySkipPermissions?: boolean;
9
+ allowedMcpServerNames?: string[];
10
+ allowedTools?: string[];
11
+ extensions?: string[];
12
+ listExtensions?: boolean;
13
+ resume?: string;
14
+ listSessions?: boolean;
15
+ deleteSession?: string;
16
+ includeDirectories?: string[];
17
+ screenReader?: boolean;
18
+ outputFormat?: "text" | "json" | "stream-json";
19
+ /**
20
+ * Antigravity CLI binary to execute. The official CLI currently installs
21
+ * `agy`; this exists for test harnesses and future binary renames.
22
+ */
23
+ binary?: string;
24
+ /**
25
+ * Path to an isolated Google CLI config root. Passed as `--gemini_dir` so
26
+ * Antigravity reads/writes `<configDir>/antigravity-cli/...` instead of the
27
+ * user's default `~/.gemini/antigravity-cli/...`.
28
+ */
29
+ configDir?: string;
30
+ /**
31
+ * Explicit alias for `configDir` when matching the Antigravity CLI flag name.
32
+ */
33
+ geminiDir?: string;
34
+ /**
35
+ * Google API key for API-billed invocations when supported by the CLI.
36
+ */
37
+ apiKey?: string;
38
+ };
@@ -38,6 +38,10 @@ export function createGeminiCapabilityRegistry(opts = {}) {
38
38
  builtIns: resolveGeminiBuiltIns(opts),
39
39
  };
40
40
  }
41
+ /**
42
+ * @deprecated Use AntigravityAgent for new Google CLI integrations. GeminiAgent
43
+ * remains for legacy and enterprise Gemini CLI setups.
44
+ */
41
45
  export class GeminiAgent extends BaseCliAgent {
42
46
  opts;
43
47
  capabilities;
@@ -1,5 +1,10 @@
1
1
  import type { BaseCliAgentOptions } from "./BaseCliAgent/BaseCliAgentOptions";
2
2
 
3
+ /**
4
+ * @deprecated Use AntigravityAgentOptions with the Antigravity CLI (`agy`) for
5
+ * new Google CLI integrations. GeminiAgentOptions remains for legacy and
6
+ * enterprise Gemini CLI setups.
7
+ */
3
8
  export type GeminiAgentOptions = BaseCliAgentOptions & {
4
9
  debug?: boolean;
5
10
  model?: string;
@@ -1,6 +1,7 @@
1
1
  import type {
2
2
  AgentLike,
3
3
  AmpAgent,
4
+ AntigravityAgent,
4
5
  AnthropicAgent,
5
6
  ClaudeCodeAgent,
6
7
  CodexAgent,
@@ -20,6 +21,7 @@ type _CustomNativeStructuredAgent = AssertAssignable<{
20
21
 
21
22
  type _ConcreteAgentsAreAgentLike = [
22
23
  AssertAssignable<AmpAgent>,
24
+ AssertAssignable<AntigravityAgent>,
23
25
  AssertAssignable<AnthropicAgent>,
24
26
  AssertAssignable<ClaudeCodeAgent>,
25
27
  AssertAssignable<CodexAgent>,
@@ -2,7 +2,7 @@ import type { AgentToolDescriptor } from "./AgentToolDescriptor";
2
2
 
3
3
  export type AgentCapabilityRegistry = {
4
4
  version: 1;
5
- engine: "claude-code" | "codex" | "gemini" | "kimi" | "pi" | "amp" | "forge" | "opencode";
5
+ engine: "claude-code" | "codex" | "antigravity" | "gemini" | "kimi" | "pi" | "amp" | "forge" | "opencode";
6
6
  runtimeTools: Record<string, AgentToolDescriptor>;
7
7
  mcp: {
8
8
  bootstrap: "inline-config" | "project-config" | "allow-list" | "unsupported";
@@ -1,5 +1,6 @@
1
1
  export type CliAgentCapabilityAdapterId =
2
2
  | "claude"
3
+ | "antigravity"
3
4
  | "codex"
4
5
  | "gemini"
5
6
  | "kimi"
@@ -1,4 +1,5 @@
1
1
  import { hashCapabilityRegistry, normalizeCapabilityRegistry, } from "../capability-registry/index.js";
2
+ import { createAntigravityCapabilityRegistry } from "../AntigravityAgent.js";
2
3
  import { createClaudeCodeCapabilityRegistry } from "../ClaudeCodeAgent.js";
3
4
  import { createCodexCapabilityRegistry } from "../CodexAgent.js";
4
5
  import { createGeminiCapabilityRegistry } from "../GeminiAgent.js";
@@ -18,6 +19,11 @@ const CLI_AGENT_CAPABILITY_ADAPTERS = [
18
19
  binary: "codex",
19
20
  buildRegistry: () => createCodexCapabilityRegistry(),
20
21
  },
22
+ {
23
+ id: "antigravity",
24
+ binary: "agy",
25
+ buildRegistry: () => createAntigravityCapabilityRegistry(),
26
+ },
21
27
  {
22
28
  id: "gemini",
23
29
  binary: "gemini",
@@ -321,7 +321,7 @@ const codexStrategy = {
321
321
  ],
322
322
  };
323
323
  // ---------------------------------------------------------------------------
324
- // Gemini strategy
324
+ // Google CLI strategies
325
325
  // ---------------------------------------------------------------------------
326
326
  // Validate Google auth via GET /v1beta/models (free, no tokens)
327
327
  const googleAuthCheck = {
@@ -438,6 +438,37 @@ const geminiStrategy = {
438
438
  googleRateLimitCheck,
439
439
  ],
440
440
  };
441
+ const antigravityAuthSkip = {
442
+ id: "api_key_valid",
443
+ run: async () => {
444
+ return {
445
+ id: "api_key_valid",
446
+ status: "skip",
447
+ message: "Antigravity CLI uses Google Sign-In/keyring auth; run `agy` to authenticate.",
448
+ durationMs: 0,
449
+ };
450
+ },
451
+ };
452
+ const antigravityRateLimitSkip = {
453
+ id: "rate_limit_status",
454
+ run: async () => {
455
+ return {
456
+ id: "rate_limit_status",
457
+ status: "skip",
458
+ message: "Antigravity CLI rate limits are checked by the CLI at runtime.",
459
+ durationMs: 0,
460
+ };
461
+ },
462
+ };
463
+ const antigravityStrategy = {
464
+ agentId: "antigravity",
465
+ command: "agy",
466
+ checks: [
467
+ checkCliInstalled("agy", "Antigravity CLI"),
468
+ antigravityAuthSkip,
469
+ antigravityRateLimitSkip,
470
+ ],
471
+ };
441
472
  // ---------------------------------------------------------------------------
442
473
  // Pi strategy
443
474
  // ---------------------------------------------------------------------------
@@ -490,6 +521,8 @@ const ampStrategy = {
490
521
  const strategies = {
491
522
  claude: claudeStrategy,
492
523
  codex: codexStrategy,
524
+ antigravity: antigravityStrategy,
525
+ agy: antigravityStrategy,
493
526
  gemini: geminiStrategy,
494
527
  pi: piStrategy,
495
528
  amp: ampStrategy,
package/src/index.d.ts CHANGED
@@ -138,7 +138,7 @@ type AgentToolDescriptor$1 = {
138
138
 
139
139
  type AgentCapabilityRegistry$3 = {
140
140
  version: 1;
141
- engine: "claude-code" | "codex" | "gemini" | "kimi" | "pi" | "amp" | "forge" | "opencode";
141
+ engine: "claude-code" | "codex" | "antigravity" | "gemini" | "kimi" | "pi" | "amp" | "forge" | "opencode";
142
142
  runtimeTools: Record<string, AgentToolDescriptor$1>;
143
143
  mcp: {
144
144
  bootstrap: "inline-config" | "project-config" | "allow-list" | "unsupported";
@@ -425,6 +425,57 @@ declare class AmpAgent extends BaseCliAgent {
425
425
  type AmpAgentOptions = AmpAgentOptions$1;
426
426
  type CliOutputInterpreter$6 = CliOutputInterpreter$8;
427
427
 
428
+ type AntigravityAgentOptions$1 = BaseCliAgentOptions$1 & {
429
+ debug?: boolean;
430
+ model?: string;
431
+ sandbox?: boolean;
432
+ yolo?: boolean;
433
+ dangerouslySkipPermissions?: boolean;
434
+ allowedMcpServerNames?: string[];
435
+ allowedTools?: string[];
436
+ extensions?: string[];
437
+ listExtensions?: boolean;
438
+ resume?: string;
439
+ listSessions?: boolean;
440
+ deleteSession?: string;
441
+ includeDirectories?: string[];
442
+ screenReader?: boolean;
443
+ outputFormat?: "text" | "json" | "stream-json";
444
+ binary?: string;
445
+ configDir?: string;
446
+ geminiDir?: string;
447
+ apiKey?: string;
448
+ };
449
+ declare function createAntigravityCapabilityRegistry(opts?: AntigravityAgentOptions): AgentCapabilityRegistry$3;
450
+ declare class AntigravityAgent extends BaseCliAgent {
451
+ /**
452
+ * @param {AntigravityAgentOptions} [opts]
453
+ */
454
+ constructor(opts?: AntigravityAgentOptions);
455
+ opts: AntigravityAgentOptions$1;
456
+ capabilities: AgentCapabilityRegistry$3;
457
+ cliEngine: string;
458
+ /**
459
+ * @returns {CliOutputInterpreter}
460
+ */
461
+ createOutputInterpreter(): CliOutputInterpreter$6;
462
+ /**
463
+ * @param {{ prompt: string; systemPrompt?: string; cwd: string; options: any; }} params
464
+ */
465
+ buildCommand(params: {
466
+ prompt: string;
467
+ systemPrompt?: string;
468
+ cwd: string;
469
+ options: any;
470
+ }): Promise<{
471
+ command: string;
472
+ args: string[];
473
+ outputFormat: "text" | "json" | "stream-json";
474
+ env: Record<string, string> | undefined;
475
+ }>;
476
+ }
477
+ type AntigravityAgentOptions = AntigravityAgentOptions$1;
478
+
428
479
  type ClaudeCodeAgentOptions$1 = BaseCliAgentOptions$1 & {
429
480
  addDir?: string[];
430
481
  agent?: string;
@@ -896,4 +947,4 @@ type SmithersAgentToolCategory = SmithersAgentToolCategory$1;
896
947
  type SmithersListedTool = SmithersListedTool$2;
897
948
  type SmithersToolSurface = SmithersToolSurface$2;
898
949
 
899
- export { type AgentCapabilityRegistry, type AgentGenerateOptions, type AgentLike, type AgentToolDescriptor, AmpAgent, AnthropicAgent, type AnthropicAgentOptions, BaseCliAgent, ClaudeCodeAgent, CodexAgent, ForgeAgent, GeminiAgent, KimiAgent, OpenAIAgent, type OpenAIAgentOptions, OpenCodeAgent, type OpenCodeAgentOptions, PiAgent, type PiAgentOptions, type PiExtensionUiRequest, type PiExtensionUiResponse, type SmithersAgentContract, type SmithersAgentContractTool, type SmithersAgentToolCategory, type SmithersListedTool, type SmithersToolSurface, createSmithersAgentContract, hashCapabilityRegistry, renderSmithersAgentPromptGuidance, sanitizeForOpenAI, zodToOpenAISchema };
950
+ export { type AgentCapabilityRegistry, type AgentGenerateOptions, type AgentLike, type AgentToolDescriptor, AmpAgent, AnthropicAgent, type AnthropicAgentOptions, AntigravityAgent, BaseCliAgent, ClaudeCodeAgent, CodexAgent, ForgeAgent, GeminiAgent, KimiAgent, OpenAIAgent, type OpenAIAgentOptions, OpenCodeAgent, type OpenCodeAgentOptions, PiAgent, type PiAgentOptions, type PiExtensionUiRequest, type PiExtensionUiResponse, type SmithersAgentContract, type SmithersAgentContractTool, type SmithersAgentToolCategory, type SmithersListedTool, type SmithersToolSurface, createAntigravityCapabilityRegistry, createSmithersAgentContract, hashCapabilityRegistry, renderSmithersAgentPromptGuidance, sanitizeForOpenAI, zodToOpenAISchema };
package/src/index.js CHANGED
@@ -29,6 +29,7 @@ export { hashCapabilityRegistry } from "./capability-registry/index.js";
29
29
  export { AnthropicAgent } from "./AnthropicAgent.js";
30
30
  export { OpenAIAgent } from "./OpenAIAgent.js";
31
31
  export { AmpAgent } from "./AmpAgent.js";
32
+ export { AntigravityAgent, createAntigravityCapabilityRegistry } from "./AntigravityAgent.js";
32
33
  export { ClaudeCodeAgent } from "./ClaudeCodeAgent.js";
33
34
  export { CodexAgent } from "./CodexAgent.js";
34
35
  export { GeminiAgent } from "./GeminiAgent.js";