grokbot-control 0.0.0-stage → 0.1.3

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 (122) hide show
  1. package/README.md +160 -2
  2. package/dist/auth/lock.d.ts +14 -0
  3. package/dist/auth/lock.js +71 -0
  4. package/dist/auth/provider.d.ts +89 -0
  5. package/dist/auth/provider.js +884 -0
  6. package/dist/auth/store.d.ts +25 -0
  7. package/dist/auth/store.js +106 -0
  8. package/dist/auth/types.d.ts +138 -0
  9. package/dist/auth/types.js +1 -0
  10. package/dist/cli/config.d.ts +26 -0
  11. package/dist/cli/config.js +98 -0
  12. package/dist/cli/help.d.ts +1 -0
  13. package/dist/cli/help.js +83 -0
  14. package/dist/cli/io.d.ts +6 -0
  15. package/dist/cli/io.js +61 -0
  16. package/dist/cli/main.d.ts +2 -0
  17. package/dist/cli/main.js +275 -0
  18. package/dist/cli/sync.d.ts +4 -0
  19. package/dist/cli/sync.js +105 -0
  20. package/dist/connect/client.d.ts +32 -0
  21. package/dist/connect/client.js +257 -0
  22. package/dist/dto/result.d.ts +33 -0
  23. package/dist/dto/result.js +29 -0
  24. package/dist/dto/types.d.ts +63 -0
  25. package/dist/dto/types.js +2 -0
  26. package/dist/errors.d.ts +31 -0
  27. package/dist/errors.js +64 -0
  28. package/dist/index.d.ts +13 -0
  29. package/dist/index.js +11 -0
  30. package/dist/mcp/main.d.ts +2 -0
  31. package/dist/mcp/main.js +82 -0
  32. package/dist/mcp/tools.d.ts +24 -0
  33. package/dist/mcp/tools.js +408 -0
  34. package/dist/mcp/zod-json.d.ts +2 -0
  35. package/dist/mcp/zod-json.js +4 -0
  36. package/dist/ops/auth.d.ts +48 -0
  37. package/dist/ops/auth.js +89 -0
  38. package/dist/ops/bot.d.ts +52 -0
  39. package/dist/ops/bot.js +211 -0
  40. package/dist/ops/limits.d.ts +10 -0
  41. package/dist/ops/limits.js +31 -0
  42. package/dist/ops/map.d.ts +7 -0
  43. package/dist/ops/map.js +57 -0
  44. package/dist/ops/message.d.ts +33 -0
  45. package/dist/ops/message.js +118 -0
  46. package/dist/ops/plane.d.ts +26 -0
  47. package/dist/ops/plane.js +33 -0
  48. package/dist/ops/progress.d.ts +34 -0
  49. package/dist/ops/progress.js +92 -0
  50. package/dist/ops/session.d.ts +13 -0
  51. package/dist/ops/session.js +34 -0
  52. package/dist/ops/sidebar.d.ts +70 -0
  53. package/dist/ops/sidebar.js +205 -0
  54. package/dist/sync/attachments.d.ts +76 -0
  55. package/dist/sync/attachments.js +274 -0
  56. package/dist/sync/core.d.ts +92 -0
  57. package/dist/sync/core.js +1027 -0
  58. package/dist/sync/decode.d.ts +83 -0
  59. package/dist/sync/decode.js +229 -0
  60. package/dist/sync/download-policy.d.ts +3 -0
  61. package/dist/sync/download-policy.js +103 -0
  62. package/dist/sync/fs.d.ts +24 -0
  63. package/dist/sync/fs.js +252 -0
  64. package/dist/sync/hydrate.d.ts +43 -0
  65. package/dist/sync/hydrate.js +472 -0
  66. package/dist/sync/render.d.ts +5 -0
  67. package/dist/sync/render.js +100 -0
  68. package/dist/testing/mock-persist.d.ts +3 -0
  69. package/dist/testing/mock-persist.js +45 -0
  70. package/dist/testing/mock-transport.d.ts +18 -0
  71. package/dist/testing/mock-transport.js +202 -0
  72. package/docs/acceptance.md +19 -0
  73. package/docs/architecture.md +128 -0
  74. package/docs/auth-lock.md +87 -0
  75. package/docs/implementation-plan.md +14 -0
  76. package/docs/implementation-status.md +92 -0
  77. package/docs/proto-drift.md +9 -0
  78. package/docs/protocol/README.md +34 -0
  79. package/docs/protocol/attachment-pagination-0.79.3.md +32 -0
  80. package/docs/protocol/auth-flow.md +51 -0
  81. package/docs/protocol/baseline-manifest.md +72 -0
  82. package/docs/protocol/baselines/full-schema-diff-0.78.4-to-0.79.2.txt +239 -0
  83. package/docs/protocol/baselines/full-schema-diff-0.78.4-to-0.79.3.txt +240 -0
  84. package/docs/protocol/baselines/full-schema-diff-0.79.2-to-0.79.3.txt +23 -0
  85. package/docs/protocol/baselines/schema-0.79.3/README.md +7 -0
  86. package/docs/protocol/baselines/schema-0.79.3/agent.v1.proto +5184 -0
  87. package/docs/protocol/baselines/schema-0.79.3/aiserver.v1.proto +18182 -0
  88. package/docs/protocol/baselines/schema-0.79.3/aiserver.v1_2.proto +54 -0
  89. package/docs/protocol/baselines/schema-0.79.3/anyrun.v1.proto +37 -0
  90. package/docs/protocol/baselines/schema-0.79.3/internapi.v1.proto +35 -0
  91. package/docs/protocol/baselines/schema-0.79.3/snapshot.json.gz +0 -0
  92. package/docs/protocol/baselines/schema-0.79.3/svc_aiserver.v1.AgentStoreService.proto +34 -0
  93. package/docs/protocol/baselines/schema-0.79.3/svc_aiserver.v1.AiService.proto +17 -0
  94. package/docs/protocol/baselines/schema-0.79.3/svc_aiserver.v1.AnalyticsService.proto +17 -0
  95. package/docs/protocol/baselines/schema-0.79.3/svc_aiserver.v1.BackgroundComposerService.proto +19 -0
  96. package/docs/protocol/baselines/schema-0.79.3/svc_aiserver.v1.DashboardService.proto +101 -0
  97. package/docs/protocol/baselines/schema-0.79.3/svc_aiserver.v1.GrokBotService.proto +473 -0
  98. package/docs/protocol/baselines/schema-0.79.3/svc_aiserver.v1.SandBoxService.proto +64 -0
  99. package/docs/protocol/baselines/used-surface-0.78.4.json +3694 -0
  100. package/docs/protocol/baselines/used-surface-0.79.2.json +3835 -0
  101. package/docs/protocol/baselines/used-surface-0.79.3.json +3835 -0
  102. package/docs/protocol/baselines/used-surface-diff-0.78.4-to-0.79.2.md +34 -0
  103. package/docs/protocol/baselines/used-surface-diff-0.78.4-to-0.79.3.md +33 -0
  104. package/docs/protocol/compat-matrix.md +20 -0
  105. package/docs/protocol/static-restore.md +64 -0
  106. package/docs/protocol/surface-map.md +39 -0
  107. package/docs/protocol/transcript-body-0.79.3.md +98 -0
  108. package/docs/protocol/update-runbook.md +30 -0
  109. package/docs/protocol-map.md +106 -0
  110. package/docs/references.md +55 -0
  111. package/docs/requirements.md +26 -0
  112. package/docs/review.md +36 -0
  113. package/docs/sync-format.md +98 -0
  114. package/package.json +60 -4
  115. package/vendor/proto-gen/NOTICE.md +23 -0
  116. package/vendor/proto-gen/agent.v1_pb.js +9503 -0
  117. package/vendor/proto-gen/aiserver.v1_2_pb.js +105 -0
  118. package/vendor/proto-gen/aiserver.v1_pb.js +33163 -0
  119. package/vendor/proto-gen/anyrun.v1_pb.js +64 -0
  120. package/vendor/proto-gen/internapi.v1_pb.js +60 -0
  121. package/vendor/proto-gen/package.json +10 -0
  122. package/vendor/proto-gen/svc_aiserver.v1.GrokBotService_connect.js +4193 -0
@@ -0,0 +1,408 @@
1
+ import path from "node:path";
2
+ import { GbcError } from "../errors.js";
3
+ import { z } from "zod";
4
+ import { LIMIT_MAX } from "../ops/limits.js";
5
+ const limitSchema = z.number().int().positive().max(LIMIT_MAX).optional();
6
+ const agentId = z.string().min(1);
7
+ const writeFlags = {
8
+ dry_run: z.boolean().optional(),
9
+ allow_writes: z.boolean().optional(),
10
+ };
11
+ export function buildTools(opts) {
12
+ const all = [
13
+ {
14
+ name: "list_bots",
15
+ description: "List Grok Bot agents (ListGrokBotAgents)",
16
+ readOnly: true,
17
+ inputSchema: z.object({ limit: limitSchema }),
18
+ handler: (p, a) => p.bot.list({ limit: a.limit }),
19
+ },
20
+ {
21
+ name: "get_bot",
22
+ description: "Get one bot by filtering ListGrokBotAgents (no Get RPC)",
23
+ readOnly: true,
24
+ inputSchema: z.object({ agent_id: agentId }),
25
+ handler: (p, a) => p.bot.get(String(a.agent_id)),
26
+ },
27
+ {
28
+ name: "create_bot",
29
+ description: "Create temporal harness bot (CreateGrokBotTemporalAgent)",
30
+ inputSchema: z.object({
31
+ name: z.string().min(1),
32
+ description: z.string().optional(),
33
+ title: z.string().optional(),
34
+ agent_id: z.string().optional(),
35
+ language: z.string().optional(),
36
+ kickstart: z.boolean().optional(),
37
+ ...writeFlags,
38
+ }),
39
+ handler: (p, a) => p.bot.create({
40
+ name: String(a.name),
41
+ description: a.description,
42
+ title: a.title,
43
+ agentId: a.agent_id,
44
+ language: a.language,
45
+ kickstart: Boolean(a.kickstart),
46
+ }, { dryRun: Boolean(a.dry_run), allowWrite: Boolean(a.allow_writes) }),
47
+ },
48
+ {
49
+ name: "update_bot",
50
+ description: "Partial update bot (UpdateGrokBotAgent)",
51
+ inputSchema: z.object({
52
+ agent_id: agentId,
53
+ name: z.string().optional(),
54
+ description: z.string().optional(),
55
+ title: z.string().optional(),
56
+ ...writeFlags,
57
+ }),
58
+ handler: (p, a) => p.bot.update(String(a.agent_id), {
59
+ name: a.name,
60
+ description: a.description,
61
+ title: a.title,
62
+ }, { dryRun: Boolean(a.dry_run), allowWrite: Boolean(a.allow_writes) }),
63
+ },
64
+ {
65
+ name: "delete_bot",
66
+ description: "Delete bot; requires confirm=agent_id. Sidebar cleanup unverified.",
67
+ inputSchema: z.object({
68
+ agent_id: agentId,
69
+ confirm: z.string().min(1),
70
+ ...writeFlags,
71
+ }),
72
+ handler: (p, a) => p.bot.delete(String(a.agent_id), {
73
+ confirm: String(a.confirm),
74
+ dryRun: Boolean(a.dry_run),
75
+ allowWrite: Boolean(a.allow_writes),
76
+ }),
77
+ },
78
+ {
79
+ name: "send_message",
80
+ description: "Send user message directly (SendGrokBotUserMessage). No task_id required. Delivery ≠ success.",
81
+ inputSchema: z.object({
82
+ agent_id: agentId,
83
+ session_id: z.string().optional(),
84
+ text: z.string().min(1),
85
+ message_id: z.string().optional(),
86
+ ...writeFlags,
87
+ }),
88
+ handler: (p, a) => p.message.send({
89
+ agentId: String(a.agent_id),
90
+ sessionId: a.session_id ?? "",
91
+ text: String(a.text),
92
+ messageId: a.message_id,
93
+ dryRun: Boolean(a.dry_run),
94
+ allowWrite: Boolean(a.allow_writes),
95
+ }),
96
+ },
97
+ {
98
+ name: "get_send_status",
99
+ description: "Get message send status (delivery path)",
100
+ readOnly: true,
101
+ inputSchema: z.object({
102
+ agent_id: agentId,
103
+ session_id: z.string().optional(),
104
+ message_id: z.string().min(1),
105
+ }),
106
+ handler: (p, a) => p.message.status({
107
+ agentId: String(a.agent_id),
108
+ sessionId: a.session_id ?? "",
109
+ messageId: String(a.message_id),
110
+ }),
111
+ },
112
+ {
113
+ name: "list_transcript",
114
+ description: "List transcript entries; ciphertext not decrypted",
115
+ readOnly: true,
116
+ inputSchema: z.object({ agent_id: agentId, limit: limitSchema }),
117
+ handler: (p, a) => p.message.history({
118
+ agentId: String(a.agent_id),
119
+ limit: a.limit,
120
+ }),
121
+ },
122
+ {
123
+ name: "list_sessions",
124
+ description: "List agent sessions",
125
+ readOnly: true,
126
+ inputSchema: z.object({ agent_id: agentId }),
127
+ handler: (p, a) => p.session.list(String(a.agent_id)),
128
+ },
129
+ {
130
+ name: "get_bot_status",
131
+ description: "Native live progress status",
132
+ readOnly: true,
133
+ inputSchema: z.object({ agent_id: agentId }),
134
+ handler: (p, a) => p.progress.status([String(a.agent_id)]),
135
+ },
136
+ {
137
+ name: "list_agent_todos",
138
+ description: "Native agent todos (not bridge tasks)",
139
+ readOnly: true,
140
+ inputSchema: z.object({ agent_id: agentId }),
141
+ handler: (p, a) => p.progress.todos(String(a.agent_id)),
142
+ },
143
+ {
144
+ name: "list_agent_tasks",
145
+ description: "Native agent tasks",
146
+ readOnly: true,
147
+ inputSchema: z.object({ agent_id: agentId }),
148
+ handler: (p, a) => p.progress.tasks(String(a.agent_id)),
149
+ },
150
+ {
151
+ name: "list_agent_subagents",
152
+ description: "ListGrokBotSubagents",
153
+ readOnly: true,
154
+ inputSchema: z.object({ agent_id: agentId }),
155
+ handler: (p, a) => p.progress.subagents(String(a.agent_id)),
156
+ },
157
+ {
158
+ name: "interrupt_run",
159
+ description: "InterruptGrokBotAgentRun. MCP request cancel does NOT call this.",
160
+ inputSchema: z.object({
161
+ agent_id: agentId,
162
+ confirm: z.string().min(1),
163
+ reason: z.string().optional(),
164
+ session_id: z.string().optional(),
165
+ ...writeFlags,
166
+ }),
167
+ handler: (p, a) => p.progress.interrupt(String(a.agent_id), {
168
+ confirm: String(a.confirm),
169
+ reason: a.reason,
170
+ sessionId: a.session_id,
171
+ dryRun: Boolean(a.dry_run),
172
+ allowWrite: Boolean(a.allow_writes),
173
+ }),
174
+ },
175
+ {
176
+ name: "get_sidebar_sections",
177
+ description: "Read SidebarSections from runtime settings",
178
+ readOnly: true,
179
+ inputSchema: z.object({}),
180
+ handler: (p) => p.sidebar.list(),
181
+ },
182
+ {
183
+ name: "create_sidebar_section",
184
+ description: "Create sidebar section (does not delete bots)",
185
+ inputSchema: z.object({ name: z.string().min(1), ...writeFlags }),
186
+ handler: (p, a) => p.sidebar.createSection(String(a.name), {
187
+ dryRun: Boolean(a.dry_run),
188
+ allowWrite: Boolean(a.allow_writes),
189
+ }),
190
+ },
191
+ {
192
+ name: "rename_sidebar_section",
193
+ inputSchema: z.object({
194
+ section_id: z.string().min(1),
195
+ name: z.string().min(1),
196
+ ...writeFlags,
197
+ }),
198
+ description: "Rename sidebar section",
199
+ handler: (p, a) => p.sidebar.renameSection(String(a.section_id), String(a.name), {
200
+ dryRun: Boolean(a.dry_run),
201
+ allowWrite: Boolean(a.allow_writes),
202
+ }),
203
+ },
204
+ {
205
+ name: "delete_sidebar_section",
206
+ description: "Delete sidebar section only — does not delete bots",
207
+ inputSchema: z.object({
208
+ section_id: z.string().min(1),
209
+ confirm: z.string().min(1),
210
+ ...writeFlags,
211
+ }),
212
+ handler: (p, a) => p.sidebar.deleteSection(String(a.section_id), {
213
+ confirm: String(a.confirm),
214
+ dryRun: Boolean(a.dry_run),
215
+ allowWrite: Boolean(a.allow_writes),
216
+ }),
217
+ },
218
+ {
219
+ name: "move_bot_to_sidebar_section",
220
+ description: "Move bot into a sidebar section",
221
+ inputSchema: z.object({
222
+ agent_id: agentId,
223
+ section_id: z.string().min(1),
224
+ ...writeFlags,
225
+ }),
226
+ handler: (p, a) => p.sidebar.moveBot(String(a.agent_id), String(a.section_id), {
227
+ dryRun: Boolean(a.dry_run),
228
+ allowWrite: Boolean(a.allow_writes),
229
+ }),
230
+ },
231
+ {
232
+ name: "auth_whoami",
233
+ description: "Local credential status (no network; never returns tokens)",
234
+ readOnly: true,
235
+ inputSchema: z.object({}),
236
+ handler: (p) => p.authOps.whoami(),
237
+ },
238
+ {
239
+ name: "auth_login_begin",
240
+ description: "Start independent Cursor browser login. Returns authorization_url for the user to open; verifier stays in a 0600 pending file.",
241
+ readOnly: true,
242
+ authTool: true,
243
+ inputSchema: z.object({}),
244
+ handler: (p) => p.authOps.begin(),
245
+ },
246
+ {
247
+ name: "auth_login_complete",
248
+ description: "Poll the pending login until signed in or timeout (default 60s, max 120s). Returns auth_pending (retryable) if not yet signed in.",
249
+ readOnly: true,
250
+ authTool: true,
251
+ inputSchema: z.object({
252
+ timeout_seconds: z.number().int().min(1).max(120).optional(),
253
+ }),
254
+ handler: (p, a) => p.authOps.complete(a.timeout_seconds ?? 60),
255
+ },
256
+ {
257
+ name: "auth_login_cancel",
258
+ description: "Discard the pending login (local only)",
259
+ readOnly: true,
260
+ authTool: true,
261
+ inputSchema: z.object({}),
262
+ handler: (p) => p.authOps.cancel(),
263
+ },
264
+ {
265
+ name: "auth_logout",
266
+ description: "Remove this tool's own local credential (does not revoke server session or touch the App)",
267
+ readOnly: true,
268
+ authTool: true,
269
+ inputSchema: z.object({}),
270
+ handler: (p) => p.authOps.logout(),
271
+ },
272
+ {
273
+ name: "auth_refresh",
274
+ description: "Refresh local Cursor OAuth credentials (non-secret metadata only). Without force, may report already_fresh with no network call. Auto refresh still happens before RPCs when near expiry. Not exposed under GBT_MCP_READONLY=1.",
275
+ authTool: true,
276
+ inputSchema: z.object({
277
+ force: z.boolean().optional(),
278
+ }),
279
+ handler: (p, a) => p.authOps.refresh({ force: Boolean(a.force) }),
280
+ },
281
+ ];
282
+ if (opts?.sync) {
283
+ const c = { ...opts.sync }; // startup-only copy: callers cannot choose paths or account scope
284
+ if (!path.isAbsolute(c.root))
285
+ throw new GbcError("invalid_argument", "MCP sync root must be absolute");
286
+ const selectors = {
287
+ agent_id: agentId.optional(),
288
+ session_id: agentId.optional(),
289
+ };
290
+ all.push({
291
+ name: "sync_status",
292
+ description: "Read bounded local archive status; no login/RPC",
293
+ readOnly: true,
294
+ inputSchema: z.object(selectors).strict(),
295
+ handler: (p, a) => p.sync.status({
296
+ dir: c.root,
297
+ agentId: a.agent_id,
298
+ sessionId: a.session_id,
299
+ }),
300
+ });
301
+ if (c.allowLocalWrites && !opts.readOnly) {
302
+ all.push({
303
+ name: "sync_pull",
304
+ description: "Write a bounded local snapshot to the configured private root. Only remote read RPCs; known JSON entry kinds decoded, unknown bodies opaque, completeness unknown.",
305
+ inputSchema: z
306
+ .object({
307
+ agent_id: agentId,
308
+ session_id: agentId.optional(),
309
+ dry_run: z.boolean().optional(),
310
+ page_size: z.number().int().min(1).max(500).optional(),
311
+ hydrate: z.enum(["off", "missing"]).optional(),
312
+ max_hydrate_requests: z.number().int().min(1).max(256).optional(),
313
+ hydrate_max_bytes: z
314
+ .number()
315
+ .int()
316
+ .min(1)
317
+ .max(64 * 1024 * 1024)
318
+ .optional(),
319
+ hydrate_max_body_bytes: z
320
+ .number()
321
+ .int()
322
+ .min(1)
323
+ .max(4 * 1024 * 1024)
324
+ .optional(),
325
+ max_pages: z.number().int().min(1).max(1000).optional(),
326
+ max_bytes: z
327
+ .number()
328
+ .int()
329
+ .min(1)
330
+ .max(256 * 1024 * 1024)
331
+ .optional(),
332
+ timeout_ms: z.number().int().min(1).max(300000).optional(),
333
+ })
334
+ .strict(),
335
+ handler: (p, a) => p.sync.pull({
336
+ dir: c.root,
337
+ agentId: String(a.agent_id),
338
+ sessionId: a.session_id,
339
+ accountId: c.accountId ?? "",
340
+ teamId: c.teamId ?? "",
341
+ acknowledgeUnverifiedScope: c.acknowledgeUnverifiedScope === true,
342
+ dryRun: a.dry_run,
343
+ pageSize: a.page_size,
344
+ hydrate: a.hydrate,
345
+ maxHydrateRequests: a.max_hydrate_requests,
346
+ hydrateMaxBytes: a.hydrate_max_bytes,
347
+ hydrateMaxBodyBytes: a.hydrate_max_body_bytes,
348
+ maxPages: a.max_pages,
349
+ maxBytes: a.max_bytes,
350
+ timeoutMs: a.timeout_ms,
351
+ }),
352
+ });
353
+ all.push({
354
+ name: "sync_render",
355
+ description: "Rebuild readable Markdown for verified JSON message/tool-summary shapes locally; unknown bodies opaque, no decryption or RPC",
356
+ inputSchema: z
357
+ .object({ ...selectors, dry_run: z.boolean().optional() })
358
+ .strict(),
359
+ handler: (p, a) => p.sync.render({
360
+ dir: c.root,
361
+ agentId: a.agent_id,
362
+ sessionId: a.session_id,
363
+ dryRun: a.dry_run,
364
+ }),
365
+ });
366
+ all.push({
367
+ name: "sync_attachments",
368
+ description: "On-demand download of synced user-attachment file_path via ResolveGrokBotAttachmentReads + HTTPS GET into the configured private root. Not live verified; signed URLs never stored; not blob_hash hydration.",
369
+ inputSchema: z
370
+ .object({
371
+ ...selectors,
372
+ path: z.string().min(1).max(4096).optional(),
373
+ dry_run: z.boolean().optional(),
374
+ max_bytes: z
375
+ .number()
376
+ .int()
377
+ .min(1)
378
+ .max(256 * 1024 * 1024)
379
+ .optional(),
380
+ max_file_bytes: z
381
+ .number()
382
+ .int()
383
+ .min(1)
384
+ .max(128 * 1024 * 1024)
385
+ .optional(),
386
+ timeout_ms: z.number().int().min(1).max(300000).optional(),
387
+ })
388
+ .strict(),
389
+ handler: (p, a) => p.sync.attachments({
390
+ dir: c.root,
391
+ agentId: a.agent_id,
392
+ sessionId: a.session_id,
393
+ path: a.path,
394
+ accountId: c.accountId ?? "",
395
+ teamId: c.teamId ?? "",
396
+ acknowledgeUnverifiedScope: c.acknowledgeUnverifiedScope === true,
397
+ dryRun: a.dry_run,
398
+ maxBytes: a.max_bytes,
399
+ maxFileBytes: a.max_file_bytes,
400
+ timeoutMs: a.timeout_ms,
401
+ }),
402
+ });
403
+ }
404
+ }
405
+ if (opts?.readOnly)
406
+ return all.filter((t) => t.readOnly && !t.authTool);
407
+ return all;
408
+ }
@@ -0,0 +1,2 @@
1
+ /** Placeholder — MCP SDK uses Zod shapes directly; keep file for future schema export. */
2
+ export declare function zodToJsonSchema(_z: unknown): unknown;
@@ -0,0 +1,4 @@
1
+ /** Placeholder — MCP SDK uses Zod shapes directly; keep file for future schema export. */
2
+ export function zodToJsonSchema(_z) {
3
+ return {};
4
+ }
@@ -0,0 +1,48 @@
1
+ import type { AuthProvider } from "../auth/types.js";
2
+ import { type ResultEnvelope } from "../dto/result.js";
3
+ export declare const AUTH_TIMEOUT_MAX_S = 900;
4
+ /** Shared CLI/MCP auth operations. Results never contain verifier/access/refresh tokens. */
5
+ export declare class AuthOps {
6
+ private auth;
7
+ private flags;
8
+ constructor(auth: AuthProvider | undefined, flags?: {
9
+ simulated?: boolean;
10
+ });
11
+ private guard;
12
+ private run;
13
+ whoami(): Promise<ResultEnvelope<never>> | Promise<{
14
+ simulated: boolean | undefined;
15
+ schema_version: typeof import("../dto/result.js").SCHEMA_VERSION;
16
+ ok: boolean;
17
+ outcome: import("../dto/result.js").Outcome;
18
+ code: string;
19
+ retryable: boolean;
20
+ request_id: string;
21
+ data?: import("../auth/types.js").WhoamiLocal | undefined;
22
+ error?: {
23
+ message: string;
24
+ hint?: string;
25
+ details?: unknown;
26
+ };
27
+ }>;
28
+ begin(): Promise<ResultEnvelope<import("../auth/types.js").AuthBeginResult>>;
29
+ /** Single poll; pending -> ok:false code auth_pending retryable (safe: read-only poll). */
30
+ poll(): Promise<ResultEnvelope<import("../auth/types.js").AuthCompleteResult>>;
31
+ complete(timeoutSeconds?: number, signal?: AbortSignal): Promise<ResultEnvelope<import("../auth/types.js").AuthCompleteResult>>;
32
+ cancel(): Promise<ResultEnvelope<{
33
+ had_pending: boolean;
34
+ }>>;
35
+ /**
36
+ * Refresh credentials. Without force: may return refreshed:false / reason already_fresh
37
+ * when the token is still outside the 5-minute early window (no network call).
38
+ * With force: always attempts a network refresh (for verification / 401 recovery).
39
+ */
40
+ refresh(opts?: {
41
+ force?: boolean;
42
+ }): Promise<ResultEnvelope<import("../auth/types.js").RefreshResult>>;
43
+ logout(): Promise<ResultEnvelope<{
44
+ note: string;
45
+ removed_credential: boolean;
46
+ removed_pending: boolean;
47
+ }>>;
48
+ }
@@ -0,0 +1,89 @@
1
+ import { failResult, newRequestId, okResult } from "../dto/result.js";
2
+ import { GbcError } from "../errors.js";
3
+ export const AUTH_TIMEOUT_MAX_S = 900;
4
+ /** Shared CLI/MCP auth operations. Results never contain verifier/access/refresh tokens. */
5
+ export class AuthOps {
6
+ auth;
7
+ flags;
8
+ constructor(auth, flags = {}) {
9
+ this.auth = auth;
10
+ this.flags = flags;
11
+ }
12
+ guard() {
13
+ if (!this.auth)
14
+ throw new GbcError("auth", "no auth provider", { exitCode: 4 });
15
+ if (this.flags.simulated) {
16
+ throw new GbcError("unsupported", "auth login/refresh is not available in --mock mode", { exitCode: 9 });
17
+ }
18
+ return this.auth;
19
+ }
20
+ async run(fn) {
21
+ const request_id = newRequestId();
22
+ try {
23
+ return okResult(await fn(this.guard()), { request_id });
24
+ }
25
+ catch (e) {
26
+ const err = e instanceof GbcError ? e : new GbcError("auth", "auth operation failed", { exitCode: 4 });
27
+ return failResult(err.code, err.message, {
28
+ request_id,
29
+ outcome: err.outcome,
30
+ retryable: err.retryable,
31
+ hint: err.hint,
32
+ details: err.details,
33
+ });
34
+ }
35
+ }
36
+ whoami() {
37
+ const request_id = newRequestId();
38
+ if (!this.auth)
39
+ return Promise.resolve(failResult("auth", "no auth provider", { request_id }));
40
+ return this.auth.whoamiLocal().then((w) => ({ ...okResult(w, { request_id }), simulated: this.flags.simulated }));
41
+ }
42
+ begin() {
43
+ return this.run((a) => a.beginLogin());
44
+ }
45
+ /** Single poll; pending -> ok:false code auth_pending retryable (safe: read-only poll). */
46
+ async poll() {
47
+ const r = await this.run((a) => a.pollLogin());
48
+ return pendingToFail(r);
49
+ }
50
+ async complete(timeoutSeconds, signal) {
51
+ const t = timeoutSeconds ?? 300;
52
+ if (!Number.isInteger(t) || t < 1 || t > AUTH_TIMEOUT_MAX_S) {
53
+ return failResult("invalid_argument", `timeout must be an integer in 1..${AUTH_TIMEOUT_MAX_S} seconds`, {
54
+ hint: "--timeout=300",
55
+ });
56
+ }
57
+ const r = await this.run((a) => a.completeLogin({ timeoutMs: t * 1000, signal }));
58
+ return pendingToFail(r);
59
+ }
60
+ cancel() {
61
+ return this.run((a) => a.cancelLogin());
62
+ }
63
+ /**
64
+ * Refresh credentials. Without force: may return refreshed:false / reason already_fresh
65
+ * when the token is still outside the 5-minute early window (no network call).
66
+ * With force: always attempts a network refresh (for verification / 401 recovery).
67
+ */
68
+ refresh(opts) {
69
+ return this.run(async (a) => a.refresh({ force: Boolean(opts?.force) }));
70
+ }
71
+ logout() {
72
+ return this.run(async (a) => ({
73
+ ...(await a.logout()),
74
+ note: "Local only: removed this tool's own credential/pending files; server-side session not revoked.",
75
+ }));
76
+ }
77
+ }
78
+ function pendingToFail(r) {
79
+ const d = r.data;
80
+ if (r.ok && d?.status === "pending") {
81
+ return failResult("auth_pending", d.note ?? "login still pending", {
82
+ request_id: r.request_id,
83
+ retryable: true,
84
+ hint: "Finish sign-in in the browser, then run `gbc auth complete` again.",
85
+ details: { expires_at_ms: d.expires_at_ms },
86
+ });
87
+ }
88
+ return r;
89
+ }
@@ -0,0 +1,52 @@
1
+ import type { GrokBotClient } from "../connect/client.js";
2
+ import { type ResultEnvelope } from "../dto/result.js";
3
+ import type { BotSummary } from "../dto/types.js";
4
+ export type WriteOpts = {
5
+ dryRun?: boolean;
6
+ /** Required for delete: must equal agent_id. */
7
+ confirm?: string;
8
+ allowWrite?: boolean;
9
+ };
10
+ export declare class BotOps {
11
+ private client;
12
+ private flags;
13
+ constructor(client: GrokBotClient, flags?: {
14
+ simulated?: boolean;
15
+ });
16
+ private wrapSim;
17
+ /** Update/Delete RPC `id` is the numeric server id (App: serverId); accept agent_id UUID by resolving via list. */
18
+ private serverId;
19
+ list(opts?: {
20
+ limit?: number;
21
+ }): Promise<ResultEnvelope<{
22
+ bots: BotSummary[];
23
+ truncated: boolean;
24
+ }>>;
25
+ /** No GetBot RPC — filter ListGrokBotAgents client-side (full server page, not the user-facing cap). */
26
+ get(agentId: string): Promise<ResultEnvelope<{
27
+ bot: BotSummary;
28
+ }>>;
29
+ create(input: {
30
+ name: string;
31
+ description?: string;
32
+ title?: string;
33
+ agentId?: string;
34
+ language?: string;
35
+ kickstart?: boolean;
36
+ }, write?: WriteOpts): Promise<ResultEnvelope<{
37
+ bot: BotSummary;
38
+ agent_id: string;
39
+ }>>;
40
+ update(agentId: string, patch: {
41
+ name?: string;
42
+ description?: string;
43
+ title?: string;
44
+ }, write?: WriteOpts): Promise<ResultEnvelope<{
45
+ bot: BotSummary;
46
+ }>>;
47
+ delete(agentId: string, write?: WriteOpts): Promise<ResultEnvelope<{
48
+ deleted: boolean;
49
+ note: string;
50
+ }>>;
51
+ private fromErr;
52
+ }