grokbox 0.1.0-alpha.7 → 0.1.0-alpha.9

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/README.md CHANGED
@@ -10,9 +10,8 @@ This project is not affiliated with or endorsed by Anysphere, Cursor, xAI, or
10
10
  Grok Bot. Grok Bot, Cursor, and related names identify compatible products and
11
11
  remain the property of their respective owners.
12
12
 
13
- > **Alpha:** current source is `0.1.0-alpha.7`. npm `next` currently points to
14
- > `0.1.0-alpha.6`; `0.0.1` remains `latest`. `v0.1.0-alpha.1` through
15
- > `v0.1.0-alpha.6` exist as Git tags only. Prereleases publish only after
13
+ > **Alpha:** current source is `0.1.0-alpha.9`. npm `next` currently points to
14
+ > `0.1.0-alpha.8`; `0.0.1` remains `latest`. Prereleases publish only after
16
15
  > release checks and explicitly scoped external acceptance.
17
16
 
18
17
  ## What it does
@@ -148,7 +147,7 @@ grokbox jobs list --table
148
147
  grokbox desktop status --table
149
148
  ```
150
149
 
151
- Routine reads expose bounded metadata only: prompt bodies, webhook credentials, native paths, and unknown provider fields stay private. Routine create always writes a disabled definition; update/enable/disable/delete require explicit confirmation, and all mutations other than create also require the exact revision from a fresh `agents routines list/show`. Upstream Routine writes have no native compare-and-swap or idempotency contract, so an uncertain acknowledgement is never replayed automatically.
150
+ Routine reads expose bounded metadata only: prompt bodies, webhook credentials, native paths, and unknown provider fields stay private. Box-local Bots support create/update/enable/disable/delete; create always writes a disabled definition and later mutations require explicit confirmation plus the exact revision from a fresh `agents routines list/show`. Temporal Bots are Server-authoritative: list/show, webhook credential, enable/disable, and delete use the bounded Temporal Routine bridge; current upstream contracts do not expose Temporal definition create/update, so those commands refuse instead of writing the legacy Box store. `agents routines webhook credential <agent> <routine-id> --confirm` returns the URL while hiding the key; add `--reveal-key` only when secret output is explicitly required. Without the Host bridge, Temporal Routine reads fail closed rather than reporting a false empty list. Upstream Routine writes have no native compare-and-swap or idempotency contract, so an uncertain acknowledgement is never replayed automatically.
152
151
 
153
152
  Mutating commands require explicit capability and, where destructive, explicit
154
153
  confirmation. `desktop prune run` defaults to dry-run; `--yes` invokes the
package/README.zh-CN.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  本项目与 Anysphere、Cursor、xAI 或 Grok Bot 没有隶属或背书关系。Grok Bot、Cursor 及相关名称仅用于标识兼容产品,其权利归各自所有者。
8
8
 
9
- > **Alpha:** 当前源码版本是 `0.1.0-alpha.7`。npm 的 `next` dist-tag 目前指向 `0.1.0-alpha.6`;`0.0.1` 仍是 `latest`。`v0.1.0-alpha.1` 到 `v0.1.0-alpha.6` 已有 Git tag。只有通过发布检查及明确范围的外部验收后,才会发布新的预发布版本。
9
+ > **Alpha:** 当前源码版本是 `0.1.0-alpha.9`。npm 的 `next` dist-tag 目前指向 `0.1.0-alpha.8`;`0.0.1` 仍是 `latest`。只有通过发布检查及明确范围的外部验收后,才会发布新的预发布版本。
10
10
 
11
11
  ## 它能做什么
12
12
 
@@ -128,7 +128,7 @@ grokbox jobs list --table
128
128
  grokbox desktop status --table
129
129
  ```
130
130
 
131
- Routine 读取只输出有界元数据,不暴露 prompt 正文、Webhook credential、原生路径或未知 provider 字段。Routine create 始终只创建 disabled definition;update/enable/disable/delete 需要显式确认,create 之外的 mutation 还必须携带刚从 `agents routines list/show` 读到的精确 revision。上游 Routine 写接口没有 native compare-and-swap 或 idempotency 合同,因此回执不确定时不会自动重放。
131
+ Routine 读取只输出有界元数据,不暴露 prompt 正文、Webhook credential、原生路径或未知 provider 字段。Box-local Bot 支持 create/update/enable/disable/delete;create 始终只创建 disabled definition,后续 mutation 需要显式确认,并携带刚从 `agents routines list/show` 读到的精确 revision。Temporal Bot 的 Routine 以 Server 为权威:list/show、Webhook credential、enable/disable/delete 通过受限的 Temporal Routine bridge;当前官方合同没有暴露 Temporal definition create/update,因此 CLI 会明确拒绝,而不会误写旧 Box store。`agents routines webhook credential <agent> <routine-id> --confirm` 默认返回 URL 并隐藏 key;只有显式增加 `--reveal-key` 才把 key 输出到 stdout。Host bridge 不可用时,Temporal Routine 查询 fail-closed,不再冒充为空列表。上游 Routine 写接口没有 native compare-and-swap 或 idempotency 合同,因此回执不确定时不会自动重放。
132
132
 
133
133
  变更命令需要显式 capability;破坏性操作还需要显式确认。`desktop prune run` 默认 dry-run;传入 `--yes` 后会调用上游 stop-window 路径,并删除该 fork 的 Chrome profile。
134
134
 
package/dist/index.js CHANGED
@@ -3474,7 +3474,7 @@ import { fileURLToPath } from "node:url";
3474
3474
  // package.json
3475
3475
  var package_default = {
3476
3476
  name: "grokbox",
3477
- version: "0.1.0-alpha.7",
3477
+ version: "0.1.0-alpha.9",
3478
3478
  packageManager: "bun@1.3.14",
3479
3479
  description: "Unofficial CLI and control plane for Grok Bot cloud computers",
3480
3480
  license: "MIT",
@@ -4069,6 +4069,25 @@ var LEAF_COMMANDS = [
4069
4069
  gateway: true,
4070
4070
  streaming: false
4071
4071
  },
4072
+ {
4073
+ path: ["agents", "routines", "webhook", "credential"],
4074
+ usage: "grokbox agents routines webhook credential <agent> <routine-id> --confirm [--reveal-key]",
4075
+ summary: "Read or mint one webhook Routine credential; key is hidden unless explicitly revealed.",
4076
+ arguments: [
4077
+ { syntax: "<agent>", description: "Agent ID or unambiguous name/title", role: "agent", kinds: ["agent"] },
4078
+ { syntax: "<routine-id>", description: "Exact native Routine ID" }
4079
+ ],
4080
+ options: options([
4081
+ { flags: "--confirm", description: "Confirm credential access/mint", required: true },
4082
+ { flags: "--reveal-key", description: "Include the webhook key and routine prompt in stdout" }
4083
+ ], { timeout: true }),
4084
+ stdin: "none",
4085
+ table: false,
4086
+ timeout: true,
4087
+ destructive: true,
4088
+ gateway: true,
4089
+ streaming: false
4090
+ },
4072
4091
  ...["enable", "disable", "delete"].map((action) => ({
4073
4092
  path: ["agents", "routines", action],
4074
4093
  usage: `grokbox agents routines ${action} <agent> <routine-id> --expect-revision <sha256> --confirm`,
@@ -5584,6 +5603,8 @@ var DAEMON_METHODS = [
5584
5603
  "getAgentThread",
5585
5604
  "getAgentMemories",
5586
5605
  "getAgentAutomations",
5606
+ "getGrokboxRoutineAuthority",
5607
+ "getAutomationWebhookCredential",
5587
5608
  "createAgentAutomation",
5588
5609
  "updateAgentAutomation",
5589
5610
  "setAgentAutomationEnabled",
@@ -5631,6 +5652,7 @@ var DAEMON_CAPABILITIES = [
5631
5652
  "grok.transcript.write",
5632
5653
  "grok.memory.read",
5633
5654
  "grok.routines.read",
5655
+ "grok.routines.credentials",
5634
5656
  "grok.routines.write",
5635
5657
  "grok.roster.write",
5636
5658
  "grok.events.read"
@@ -6302,6 +6324,28 @@ var GatewayClient = class {
6302
6324
  }
6303
6325
  return await this.rpc("getAgentAutomations", { id }, { timeoutMs });
6304
6326
  }
6327
+ async getGrokboxRoutineAuthority(id, timeoutMs) {
6328
+ const daemon = await this.daemonFor("grok.routines.read", timeoutMs);
6329
+ if (daemon) {
6330
+ const response = await daemon.call("getGrokboxRoutineAuthority", { id, timeoutMs });
6331
+ if (!response.gateway) throw new CliError("gateway_internal", "Daemon Routine authority response lacks generation.");
6332
+ const discovery = this.discoveryFromDaemon(response.gateway);
6333
+ this.lastDiscovery = discovery;
6334
+ return { result: response.result, discovery };
6335
+ }
6336
+ return await this.rpc("getGrokboxRoutineAuthority", { id }, { timeoutMs });
6337
+ }
6338
+ async getAutomationWebhookCredential(id, automationId, timeoutMs) {
6339
+ const daemon = await this.daemonFor("grok.routines.credentials", timeoutMs);
6340
+ if (daemon) {
6341
+ const response = await daemon.call("getAutomationWebhookCredential", { id, automationId, timeoutMs });
6342
+ if (!response.gateway) throw new CliError("gateway_internal", "Daemon Routine credential response lacks generation.");
6343
+ const discovery = this.discoveryFromDaemon(response.gateway);
6344
+ this.lastDiscovery = discovery;
6345
+ return { result: response.result, discovery };
6346
+ }
6347
+ return await this.rpc("getAutomationWebhookCredential", { id, automationId }, { timeoutMs });
6348
+ }
6305
6349
  async createAgentAutomation(body, timeoutMs, operationId2, expectedGateway) {
6306
6350
  return await this.routineWrite("createAgentAutomation", body, timeoutMs, operationId2, expectedGateway);
6307
6351
  }
@@ -11592,6 +11636,19 @@ async function startDaemonHost(deps, socketPath, networkConfig, filesystemRoots
11592
11636
  const value = await gateway.getAgentAutomations(id, params.timeoutMs);
11593
11637
  return { result: value.result, gateway: gatewayMeta(value.discovery) };
11594
11638
  }
11639
+ if (method === "getGrokboxRoutineAuthority") {
11640
+ assertExactParams(params, { id: "string", timeoutMs: "number" });
11641
+ const id = routineInput(() => routineAgentId(params.id));
11642
+ const value = await gateway.getGrokboxRoutineAuthority(id, params.timeoutMs);
11643
+ return { result: value.result, gateway: gatewayMeta(value.discovery) };
11644
+ }
11645
+ if (method === "getAutomationWebhookCredential") {
11646
+ assertExactParams(params, { id: "string", automationId: "string", timeoutMs: "number" });
11647
+ const id = routineInput(() => routineAgentId(params.id));
11648
+ const automationId = routineInput(() => routineId(params.automationId));
11649
+ const value = await gateway.getAutomationWebhookCredential(id, automationId, params.timeoutMs);
11650
+ return { result: value.result, gateway: gatewayMeta(value.discovery) };
11651
+ }
11595
11652
  if (method === "createAgentAutomation") {
11596
11653
  assertParamKeys(params, ["id", "spec", "timeoutMs", "expectedGatewayPid", "expectedGatewayStartedAt"], "Routine create");
11597
11654
  const id = routineInput(() => routineAgentId(params.id));
@@ -14904,7 +14961,11 @@ async function resolveAgent(client2, target, timeoutMs) {
14904
14961
  const roster = await client2.listAgents(timeoutMs);
14905
14962
  const row = findRosterRow(roster.agents, target, ["agent"]);
14906
14963
  try {
14907
- return { id: routineAgentId(asString(row.id)), discovery: gatewayMeta(roster.discovery) };
14964
+ return {
14965
+ id: routineAgentId(asString(row.id)),
14966
+ discovery: gatewayMeta(roster.discovery),
14967
+ harness: row.harness === "temporal" ? "temporal" : row.harness === "box" ? "box" : null
14968
+ };
14908
14969
  } catch {
14909
14970
  throw new CliError(
14910
14971
  "capability_unavailable",
@@ -14912,17 +14973,67 @@ async function resolveAgent(client2, target, timeoutMs) {
14912
14973
  );
14913
14974
  }
14914
14975
  }
14915
- async function readSnapshot(client2, agentId, timeoutMs) {
14916
- const response = await client2.getAgentAutomations(agentId, timeoutMs);
14976
+ async function resolveRoutineAuthority(client2, agent, timeoutMs) {
14977
+ if (agent.harness !== "temporal") {
14978
+ return { authority: "box-local", discovery: agent.discovery };
14979
+ }
14980
+ let response;
14917
14981
  try {
14982
+ response = await client2.getGrokboxRoutineAuthority(agent.id, timeoutMs);
14983
+ } catch (error) {
14984
+ if (error instanceof CliError && ["gateway_not_found", "gateway_bad_request", "capability_unavailable"].includes(error.code)) {
14985
+ throw new CliError(
14986
+ "capability_unavailable",
14987
+ "This Temporal Bot requires the Grokbox Temporal Routine bridge before Routine state can be read safely."
14988
+ );
14989
+ }
14990
+ throw error;
14991
+ }
14992
+ const discovery = gatewayMeta(response.discovery);
14993
+ if (!sameGeneration(agent.discovery, discovery)) {
14994
+ throw new CliError("gateway_conflict", "Gateway generation changed while resolving Routine authority.");
14995
+ }
14996
+ if (!isRecord(response.result) || JSON.stringify(Object.keys(response.result).sort()) !== JSON.stringify(["source"]) || response.result.source !== "server-temporal") {
14997
+ throw new CliError(
14998
+ "capability_unavailable",
14999
+ "Temporal Routine authority is not Server-backed on the selected Host."
15000
+ );
15001
+ }
15002
+ return { authority: "server-temporal", discovery };
15003
+ }
15004
+ async function readSnapshot(client2, agent, timeoutMs) {
15005
+ const authority = await resolveRoutineAuthority(client2, agent, timeoutMs);
15006
+ const response = await client2.getAgentAutomations(agent.id, timeoutMs);
15007
+ const discovery = gatewayMeta(response.discovery);
15008
+ if (!sameGeneration(authority.discovery, discovery)) {
15009
+ throw new CliError("gateway_conflict", "Gateway generation changed while reading Routines.");
15010
+ }
15011
+ try {
15012
+ const projected = projectNativeRoutines(agent.id, response.result);
14918
15013
  return {
14919
- ...projectNativeRoutines(agentId, response.result),
14920
- discovery: gatewayMeta(response.discovery)
15014
+ ...projected,
15015
+ discovery,
15016
+ authority: authority.authority,
15017
+ prompts: nativePrompts(response.result, projected.catalog)
14921
15018
  };
14922
15019
  } catch (error) {
14923
15020
  throw routineCliError(error);
14924
15021
  }
14925
15022
  }
15023
+ function nativePrompts(value, catalog) {
15024
+ if (!Array.isArray(value)) throw new RoutineError("unsupported_shape");
15025
+ const prompts = /* @__PURE__ */ new Map();
15026
+ for (const raw of value) {
15027
+ if (!isRecord(raw) || typeof raw.id !== "string" || typeof raw.prompt !== "string" || raw.prompt.length < 1 || raw.prompt.includes("\0") || Buffer.byteLength(raw.prompt) > 128 * 1024) {
15028
+ throw new RoutineError("unsupported_shape");
15029
+ }
15030
+ prompts.set(raw.id, raw.prompt);
15031
+ }
15032
+ for (const routine of catalog.routines) {
15033
+ if (!prompts.has(routine.id)) throw new RoutineError("unsupported_shape");
15034
+ }
15035
+ return prompts;
15036
+ }
14926
15037
  function findRoutine(snapshot, id) {
14927
15038
  let rid;
14928
15039
  try {
@@ -14984,19 +15095,19 @@ function listTable(catalog) {
14984
15095
  async function listOrShow(deps, client2, action, agentTarget, routineTarget, raw) {
14985
15096
  const io = ioFromOpts(raw);
14986
15097
  const agent = await resolveAgent(client2, agentTarget, io.timeoutMs);
14987
- const snapshot = await readSnapshot(client2, agent.id, io.timeoutMs);
15098
+ const snapshot = await readSnapshot(client2, agent, io.timeoutMs);
14988
15099
  if (action === "list") {
14989
15100
  if (io.table) {
14990
15101
  deps.stdout.write(listTable(snapshot.catalog));
14991
15102
  return;
14992
15103
  }
14993
- writeSuccess(deps.stdout, snapshot.catalog, snapshot.discovery);
15104
+ writeSuccess(deps.stdout, { ...snapshot.catalog, authority: snapshot.authority }, snapshot.discovery);
14994
15105
  return;
14995
15106
  }
14996
15107
  const routine = findRoutine(snapshot, routineTarget ?? "");
14997
15108
  writeSuccess(
14998
15109
  deps.stdout,
14999
- { schemaVersion: 1, agentId: agent.id, routine, coverage: snapshot.catalog.coverage },
15110
+ { schemaVersion: 1, agentId: agent.id, authority: snapshot.authority, routine, coverage: snapshot.catalog.coverage },
15000
15111
  snapshot.discovery
15001
15112
  );
15002
15113
  }
@@ -15004,9 +15115,15 @@ async function createRoutine(deps, client2, agentTarget, raw) {
15004
15115
  requireConfirmed(raw);
15005
15116
  const io = ioFromOpts(raw);
15006
15117
  const op = operationId(raw, deps);
15007
- const desired = await definition(raw, deps);
15008
15118
  const agent = await resolveAgent(client2, agentTarget, io.timeoutMs);
15009
- const before = await readSnapshot(client2, agent.id, io.timeoutMs);
15119
+ if (agent.harness === "temporal") {
15120
+ throw new CliError(
15121
+ "capability_unavailable",
15122
+ "The current official Temporal Routine contract does not expose create through the Box management surface."
15123
+ );
15124
+ }
15125
+ const desired = await definition(raw, deps);
15126
+ const before = await readSnapshot(client2, agent, io.timeoutMs);
15010
15127
  if (before.catalog.coverage.atLimit) {
15011
15128
  throw new CliError(
15012
15129
  "capability_unavailable",
@@ -15029,7 +15146,7 @@ async function createRoutine(deps, client2, agentTarget, raw) {
15029
15146
  if (!sameGeneration(before.discovery, gatewayMeta(write.discovery))) {
15030
15147
  return unknown(op, "Gateway generation changed during Routine create; inspect the Routine list before any retry.");
15031
15148
  }
15032
- const after = await readSnapshot(client2, agent.id, io.timeoutMs);
15149
+ const after = await readSnapshot(client2, agent, io.timeoutMs);
15033
15150
  if (!sameGeneration(before.discovery, after.discovery)) {
15034
15151
  return unknown(op, "Gateway generation changed after Routine create; inspect the Routine list before any retry.");
15035
15152
  }
@@ -15056,9 +15173,15 @@ async function updateRoutine(deps, client2, agentTarget, routineTarget, raw) {
15056
15173
  const io = ioFromOpts(raw);
15057
15174
  const op = operationId(raw, deps);
15058
15175
  const expected = expectedRevision(raw);
15059
- const desired = await definition(raw, deps);
15060
15176
  const agent = await resolveAgent(client2, agentTarget, io.timeoutMs);
15061
- const before = await readSnapshot(client2, agent.id, io.timeoutMs);
15177
+ if (agent.harness === "temporal") {
15178
+ throw new CliError(
15179
+ "capability_unavailable",
15180
+ "The current official Temporal Routine contract does not expose definition update through the Box management surface."
15181
+ );
15182
+ }
15183
+ const desired = await definition(raw, deps);
15184
+ const before = await readSnapshot(client2, agent, io.timeoutMs);
15062
15185
  const prior = mutableRoutine(before, routineTarget);
15063
15186
  if (prior.revision !== expected) throw routineCliError(new RoutineError("revision_conflict"));
15064
15187
  const desiredDigest = routineDefinitionDigest(desired, prior.enabled);
@@ -15091,7 +15214,7 @@ async function updateRoutine(deps, client2, agentTarget, routineTarget, raw) {
15091
15214
  if (!sameGeneration(before.discovery, gatewayMeta(write.discovery))) {
15092
15215
  return unknown(op, "Gateway generation changed during Routine update; inspect the Routine before any retry.");
15093
15216
  }
15094
- const after = await readSnapshot(client2, agent.id, io.timeoutMs);
15217
+ const after = await readSnapshot(client2, agent, io.timeoutMs);
15095
15218
  if (!sameGeneration(before.discovery, after.discovery)) {
15096
15219
  return unknown(op, "Gateway generation changed after Routine update; inspect the Routine before any retry.");
15097
15220
  }
@@ -15118,7 +15241,7 @@ async function setRoutineEnabled(deps, client2, agentTarget, routineTarget, acti
15118
15241
  const op = operationId(raw, deps);
15119
15242
  const expected = expectedRevision(raw);
15120
15243
  const agent = await resolveAgent(client2, agentTarget, io.timeoutMs);
15121
- const before = await readSnapshot(client2, agent.id, io.timeoutMs);
15244
+ const before = await readSnapshot(client2, agent, io.timeoutMs);
15122
15245
  const prior = mutableRoutine(before, routineTarget);
15123
15246
  if (prior.revision !== expected) throw routineCliError(new RoutineError("revision_conflict"));
15124
15247
  const enabled = action === "enable";
@@ -15151,7 +15274,7 @@ async function setRoutineEnabled(deps, client2, agentTarget, routineTarget, acti
15151
15274
  if (!sameGeneration(before.discovery, gatewayMeta(write.discovery))) {
15152
15275
  return unknown(op, "Gateway generation changed during Routine state change; inspect the Routine before any retry.");
15153
15276
  }
15154
- const after = await readSnapshot(client2, agent.id, io.timeoutMs);
15277
+ const after = await readSnapshot(client2, agent, io.timeoutMs);
15155
15278
  if (!sameGeneration(before.discovery, after.discovery)) {
15156
15279
  return unknown(op, "Gateway generation changed after Routine state change; inspect the Routine before any retry.");
15157
15280
  }
@@ -15172,13 +15295,56 @@ async function setRoutineEnabled(deps, client2, agentTarget, routineTarget, acti
15172
15295
  routine: current
15173
15296
  }, after.discovery);
15174
15297
  }
15298
+ async function showWebhookCredential(deps, client2, agentTarget, routineTarget, raw) {
15299
+ requireConfirmed(raw);
15300
+ const io = ioFromOpts(raw);
15301
+ const agent = await resolveAgent(client2, agentTarget, io.timeoutMs);
15302
+ const snapshot = await readSnapshot(client2, agent, io.timeoutMs);
15303
+ const routine = findRoutine(snapshot, routineTarget);
15304
+ if (routine.trigger.type !== "webhook") {
15305
+ throw new CliError("capability_unavailable", "Routine is not webhook-triggered.");
15306
+ }
15307
+ const response = await client2.getAutomationWebhookCredential(agent.id, routine.id, io.timeoutMs);
15308
+ const discovery = gatewayMeta(response.discovery);
15309
+ if (!sameGeneration(snapshot.discovery, discovery)) {
15310
+ throw new CliError("gateway_conflict", "Gateway generation changed while reading webhook credentials.");
15311
+ }
15312
+ if (!isRecord(response.result) || JSON.stringify(Object.keys(response.result).sort()) !== JSON.stringify(["key", "url"]) || typeof response.result.url !== "string" || typeof response.result.key !== "string" || response.result.key.length < 1 || response.result.key.length > 4096 || response.result.key.includes("\0")) {
15313
+ throw new CliError("gateway_internal", "Gateway returned an invalid webhook credential.");
15314
+ }
15315
+ let url;
15316
+ try {
15317
+ url = new URL(response.result.url);
15318
+ } catch {
15319
+ throw new CliError("gateway_internal", "Gateway returned an invalid webhook URL.");
15320
+ }
15321
+ if (url.protocol !== "https:" || url.username || url.password || url.hash) {
15322
+ throw new CliError("gateway_internal", "Gateway returned an unsafe webhook URL.");
15323
+ }
15324
+ const prompt = snapshot.prompts.get(routine.id);
15325
+ if (prompt === void 0) {
15326
+ throw new CliError("gateway_internal", "Gateway returned a Routine without a prompt.");
15327
+ }
15328
+ const revealKey = raw.revealKey === true;
15329
+ writeSuccess(deps.stdout, {
15330
+ schemaVersion: 1,
15331
+ agentId: agent.id,
15332
+ routineId: routine.id,
15333
+ authority: snapshot.authority,
15334
+ url: url.toString(),
15335
+ keyPresent: true,
15336
+ keyIncluded: revealKey,
15337
+ promptIncluded: revealKey,
15338
+ ...revealKey ? { key: response.result.key, prompt } : {}
15339
+ }, discovery);
15340
+ }
15175
15341
  async function deleteRoutine(deps, client2, agentTarget, routineTarget, raw) {
15176
15342
  requireConfirmed(raw);
15177
15343
  const io = ioFromOpts(raw);
15178
15344
  const op = operationId(raw, deps);
15179
15345
  const expected = expectedRevision(raw);
15180
15346
  const agent = await resolveAgent(client2, agentTarget, io.timeoutMs);
15181
- const before = await readSnapshot(client2, agent.id, io.timeoutMs);
15347
+ const before = await readSnapshot(client2, agent, io.timeoutMs);
15182
15348
  const prior = mutableRoutine(before, routineTarget);
15183
15349
  if (prior.revision !== expected) throw routineCliError(new RoutineError("revision_conflict"));
15184
15350
  let write;
@@ -15195,7 +15361,7 @@ async function deleteRoutine(deps, client2, agentTarget, routineTarget, raw) {
15195
15361
  if (!sameGeneration(before.discovery, gatewayMeta(write.discovery))) {
15196
15362
  return unknown(op, "Gateway generation changed during Routine delete; inspect the Routine list before any retry.");
15197
15363
  }
15198
- const after = await readSnapshot(client2, agent.id, io.timeoutMs);
15364
+ const after = await readSnapshot(client2, agent, io.timeoutMs);
15199
15365
  if (!sameGeneration(before.discovery, after.discovery)) {
15200
15366
  return unknown(op, "Gateway generation changed after Routine delete; inspect the Routine list before any retry.");
15201
15367
  }
@@ -15225,6 +15391,10 @@ async function runRoutines(deps, action, agentTarget, routineTarget, raw) {
15225
15391
  return;
15226
15392
  }
15227
15393
  if (!routineTarget) throw usage("Routine ID is required.");
15394
+ if (action === "webhook-credential") {
15395
+ await showWebhookCredential(deps, client2, agentTarget, routineTarget, raw);
15396
+ return;
15397
+ }
15228
15398
  if (action === "update") {
15229
15399
  await updateRoutine(deps, client2, agentTarget, routineTarget, raw);
15230
15400
  return;
@@ -15330,6 +15500,7 @@ var FAMILY_DESCRIPTIONS = {
15330
15500
  daemon: "Local daemon lifecycle",
15331
15501
  agents: "Non-group Grok Bot agents",
15332
15502
  "agents routines": "Native Grok Bot Routines",
15503
+ "agents routines webhook": "Webhook Routine credentials",
15333
15504
  groups: "Product groups",
15334
15505
  "groups members": "Product group membership",
15335
15506
  history: "Search and read display transcript",
@@ -15397,6 +15568,7 @@ function actionBindings() {
15397
15568
  "agents routines enable": async (deps, args, options2) => await runRoutines(deps, "enable", args[0] ?? "", args[1], options2),
15398
15569
  "agents routines disable": async (deps, args, options2) => await runRoutines(deps, "disable", args[0] ?? "", args[1], options2),
15399
15570
  "agents routines delete": async (deps, args, options2) => await runRoutines(deps, "delete", args[0] ?? "", args[1], options2),
15571
+ "agents routines webhook credential": async (deps, args, options2) => await runRoutines(deps, "webhook-credential", args[0] ?? "", args[1], options2),
15400
15572
  "groups list": async (deps, _args, options2) => await runGroupsList(deps, options2),
15401
15573
  "groups show": async (deps, args, options2) => await runGroupsShow(deps, args[0] ?? "", options2),
15402
15574
  "groups create": async (deps, _args, options2) => await runGroupsCreate(deps, options2),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grokbox",
3
- "version": "0.1.0-alpha.7",
3
+ "version": "0.1.0-alpha.9",
4
4
  "packageManager": "bun@1.3.14",
5
5
  "description": "Unofficial CLI and control plane for Grok Bot cloud computers",
6
6
  "license": "MIT",
package/skills/core.md CHANGED
@@ -72,7 +72,7 @@ Targets accept an exact ID first, then an unambiguous case-insensitive name/titl
72
72
  `groups list/show/create/update/delete` only own product groups. Membership is only
73
73
  `groups members list/add/remove/set`; every member must resolve to a non-group agent and a group
74
74
  must retain 1-6 unique members.
75
- 3. **Manage native Routines**: `agents routines list/show` returns bounded metadata only and never emits prompt bodies, credentials, or native paths. `create` writes a disabled definition; `update/enable/disable/delete` require `--expect-revision` from a fresh read and `--confirm`. `update` is a complete name/prompt/trigger replacement and preserves enabled state. Native writes have no upstream CAS or idempotency guarantee; uncertain writes return `operation_outcome_unknown` and must be reconciled by another read, never automatic replay. Credential minting, webhook invocation, and run-now are intentionally absent.
75
+ 3. **Manage native Routines**: `agents routines list/show` returns bounded metadata only and never emits prompt bodies, credentials, or native paths. Box-local Bots support create/update/enable/disable/delete; create writes a disabled definition and later mutations require `--expect-revision` from a fresh read plus `--confirm`. Temporal Bots are Server-authoritative: list/show, webhook credential, enable/disable, and delete require the bounded Temporal Routine Host bridge; create/update refuse because the current official Temporal contract exposes neither mutation. `agents routines webhook credential <agent> <routine-id> --confirm` returns the webhook URL and hides the key and prompt by default; `--reveal-key` is the explicit boundary that also emits both. `list` and `show` still never emit them. Without the bridge, Temporal reads fail closed instead of reporting the legacy local store. Native writes have no upstream CAS or idempotency guarantee; uncertain writes return `operation_outcome_unknown` and must be reconciled by another read, never automatic replay.
76
76
  4. **Search/read transcript**: `history search <query>`, `history tail <target>`, and
77
77
  `history thread <target> --root <entry-id>` own transcript access. Object `show` commands do
78
78
  not add transcript side projections.