grokbox 0.1.0-alpha.7 → 0.1.0-alpha.8
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 +3 -4
- package/README.zh-CN.md +2 -2
- package/dist/index.js +170 -19
- package/package.json +1 -1
- package/skills/core.md +1 -1
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.
|
|
14
|
-
> `0.1.0-alpha.
|
|
15
|
-
> `v0.1.0-alpha.6` exist as Git tags only. Prereleases publish only after
|
|
13
|
+
> **Alpha:** current source is `0.1.0-alpha.8`. npm `next` currently points to
|
|
14
|
+
> `0.1.0-alpha.7`; `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.
|
|
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.
|
|
9
|
+
> **Alpha:** 当前源码版本是 `0.1.0-alpha.8`。npm 的 `next` dist-tag 目前指向 `0.1.0-alpha.7`;`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 字段。
|
|
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.
|
|
3477
|
+
version: "0.1.0-alpha.8",
|
|
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 sensitive webhook key 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 {
|
|
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,12 +14973,46 @@ async function resolveAgent(client2, target, timeoutMs) {
|
|
|
14912
14973
|
);
|
|
14913
14974
|
}
|
|
14914
14975
|
}
|
|
14915
|
-
async function
|
|
14916
|
-
|
|
14976
|
+
async function resolveRoutineAuthority(client2, agent, timeoutMs) {
|
|
14977
|
+
if (agent.harness !== "temporal") {
|
|
14978
|
+
return { authority: "box-local", discovery: agent.discovery };
|
|
14979
|
+
}
|
|
14980
|
+
let response;
|
|
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
|
+
}
|
|
14917
15011
|
try {
|
|
14918
15012
|
return {
|
|
14919
|
-
...projectNativeRoutines(
|
|
14920
|
-
discovery
|
|
15013
|
+
...projectNativeRoutines(agent.id, response.result),
|
|
15014
|
+
discovery,
|
|
15015
|
+
authority: authority.authority
|
|
14921
15016
|
};
|
|
14922
15017
|
} catch (error) {
|
|
14923
15018
|
throw routineCliError(error);
|
|
@@ -14984,19 +15079,19 @@ function listTable(catalog) {
|
|
|
14984
15079
|
async function listOrShow(deps, client2, action, agentTarget, routineTarget, raw) {
|
|
14985
15080
|
const io = ioFromOpts(raw);
|
|
14986
15081
|
const agent = await resolveAgent(client2, agentTarget, io.timeoutMs);
|
|
14987
|
-
const snapshot = await readSnapshot(client2, agent
|
|
15082
|
+
const snapshot = await readSnapshot(client2, agent, io.timeoutMs);
|
|
14988
15083
|
if (action === "list") {
|
|
14989
15084
|
if (io.table) {
|
|
14990
15085
|
deps.stdout.write(listTable(snapshot.catalog));
|
|
14991
15086
|
return;
|
|
14992
15087
|
}
|
|
14993
|
-
writeSuccess(deps.stdout, snapshot.catalog, snapshot.discovery);
|
|
15088
|
+
writeSuccess(deps.stdout, { ...snapshot.catalog, authority: snapshot.authority }, snapshot.discovery);
|
|
14994
15089
|
return;
|
|
14995
15090
|
}
|
|
14996
15091
|
const routine = findRoutine(snapshot, routineTarget ?? "");
|
|
14997
15092
|
writeSuccess(
|
|
14998
15093
|
deps.stdout,
|
|
14999
|
-
{ schemaVersion: 1, agentId: agent.id, routine, coverage: snapshot.catalog.coverage },
|
|
15094
|
+
{ schemaVersion: 1, agentId: agent.id, authority: snapshot.authority, routine, coverage: snapshot.catalog.coverage },
|
|
15000
15095
|
snapshot.discovery
|
|
15001
15096
|
);
|
|
15002
15097
|
}
|
|
@@ -15004,9 +15099,15 @@ async function createRoutine(deps, client2, agentTarget, raw) {
|
|
|
15004
15099
|
requireConfirmed(raw);
|
|
15005
15100
|
const io = ioFromOpts(raw);
|
|
15006
15101
|
const op = operationId(raw, deps);
|
|
15007
|
-
const desired = await definition(raw, deps);
|
|
15008
15102
|
const agent = await resolveAgent(client2, agentTarget, io.timeoutMs);
|
|
15009
|
-
|
|
15103
|
+
if (agent.harness === "temporal") {
|
|
15104
|
+
throw new CliError(
|
|
15105
|
+
"capability_unavailable",
|
|
15106
|
+
"The current official Temporal Routine contract does not expose create through the Box management surface."
|
|
15107
|
+
);
|
|
15108
|
+
}
|
|
15109
|
+
const desired = await definition(raw, deps);
|
|
15110
|
+
const before = await readSnapshot(client2, agent, io.timeoutMs);
|
|
15010
15111
|
if (before.catalog.coverage.atLimit) {
|
|
15011
15112
|
throw new CliError(
|
|
15012
15113
|
"capability_unavailable",
|
|
@@ -15029,7 +15130,7 @@ async function createRoutine(deps, client2, agentTarget, raw) {
|
|
|
15029
15130
|
if (!sameGeneration(before.discovery, gatewayMeta(write.discovery))) {
|
|
15030
15131
|
return unknown(op, "Gateway generation changed during Routine create; inspect the Routine list before any retry.");
|
|
15031
15132
|
}
|
|
15032
|
-
const after = await readSnapshot(client2, agent
|
|
15133
|
+
const after = await readSnapshot(client2, agent, io.timeoutMs);
|
|
15033
15134
|
if (!sameGeneration(before.discovery, after.discovery)) {
|
|
15034
15135
|
return unknown(op, "Gateway generation changed after Routine create; inspect the Routine list before any retry.");
|
|
15035
15136
|
}
|
|
@@ -15056,9 +15157,15 @@ async function updateRoutine(deps, client2, agentTarget, routineTarget, raw) {
|
|
|
15056
15157
|
const io = ioFromOpts(raw);
|
|
15057
15158
|
const op = operationId(raw, deps);
|
|
15058
15159
|
const expected = expectedRevision(raw);
|
|
15059
|
-
const desired = await definition(raw, deps);
|
|
15060
15160
|
const agent = await resolveAgent(client2, agentTarget, io.timeoutMs);
|
|
15061
|
-
|
|
15161
|
+
if (agent.harness === "temporal") {
|
|
15162
|
+
throw new CliError(
|
|
15163
|
+
"capability_unavailable",
|
|
15164
|
+
"The current official Temporal Routine contract does not expose definition update through the Box management surface."
|
|
15165
|
+
);
|
|
15166
|
+
}
|
|
15167
|
+
const desired = await definition(raw, deps);
|
|
15168
|
+
const before = await readSnapshot(client2, agent, io.timeoutMs);
|
|
15062
15169
|
const prior = mutableRoutine(before, routineTarget);
|
|
15063
15170
|
if (prior.revision !== expected) throw routineCliError(new RoutineError("revision_conflict"));
|
|
15064
15171
|
const desiredDigest = routineDefinitionDigest(desired, prior.enabled);
|
|
@@ -15091,7 +15198,7 @@ async function updateRoutine(deps, client2, agentTarget, routineTarget, raw) {
|
|
|
15091
15198
|
if (!sameGeneration(before.discovery, gatewayMeta(write.discovery))) {
|
|
15092
15199
|
return unknown(op, "Gateway generation changed during Routine update; inspect the Routine before any retry.");
|
|
15093
15200
|
}
|
|
15094
|
-
const after = await readSnapshot(client2, agent
|
|
15201
|
+
const after = await readSnapshot(client2, agent, io.timeoutMs);
|
|
15095
15202
|
if (!sameGeneration(before.discovery, after.discovery)) {
|
|
15096
15203
|
return unknown(op, "Gateway generation changed after Routine update; inspect the Routine before any retry.");
|
|
15097
15204
|
}
|
|
@@ -15118,7 +15225,7 @@ async function setRoutineEnabled(deps, client2, agentTarget, routineTarget, acti
|
|
|
15118
15225
|
const op = operationId(raw, deps);
|
|
15119
15226
|
const expected = expectedRevision(raw);
|
|
15120
15227
|
const agent = await resolveAgent(client2, agentTarget, io.timeoutMs);
|
|
15121
|
-
const before = await readSnapshot(client2, agent
|
|
15228
|
+
const before = await readSnapshot(client2, agent, io.timeoutMs);
|
|
15122
15229
|
const prior = mutableRoutine(before, routineTarget);
|
|
15123
15230
|
if (prior.revision !== expected) throw routineCliError(new RoutineError("revision_conflict"));
|
|
15124
15231
|
const enabled = action === "enable";
|
|
@@ -15151,7 +15258,7 @@ async function setRoutineEnabled(deps, client2, agentTarget, routineTarget, acti
|
|
|
15151
15258
|
if (!sameGeneration(before.discovery, gatewayMeta(write.discovery))) {
|
|
15152
15259
|
return unknown(op, "Gateway generation changed during Routine state change; inspect the Routine before any retry.");
|
|
15153
15260
|
}
|
|
15154
|
-
const after = await readSnapshot(client2, agent
|
|
15261
|
+
const after = await readSnapshot(client2, agent, io.timeoutMs);
|
|
15155
15262
|
if (!sameGeneration(before.discovery, after.discovery)) {
|
|
15156
15263
|
return unknown(op, "Gateway generation changed after Routine state change; inspect the Routine before any retry.");
|
|
15157
15264
|
}
|
|
@@ -15172,13 +15279,51 @@ async function setRoutineEnabled(deps, client2, agentTarget, routineTarget, acti
|
|
|
15172
15279
|
routine: current
|
|
15173
15280
|
}, after.discovery);
|
|
15174
15281
|
}
|
|
15282
|
+
async function showWebhookCredential(deps, client2, agentTarget, routineTarget, raw) {
|
|
15283
|
+
requireConfirmed(raw);
|
|
15284
|
+
const io = ioFromOpts(raw);
|
|
15285
|
+
const agent = await resolveAgent(client2, agentTarget, io.timeoutMs);
|
|
15286
|
+
const snapshot = await readSnapshot(client2, agent, io.timeoutMs);
|
|
15287
|
+
const routine = findRoutine(snapshot, routineTarget);
|
|
15288
|
+
if (routine.trigger.type !== "webhook") {
|
|
15289
|
+
throw new CliError("capability_unavailable", "Routine is not webhook-triggered.");
|
|
15290
|
+
}
|
|
15291
|
+
const response = await client2.getAutomationWebhookCredential(agent.id, routine.id, io.timeoutMs);
|
|
15292
|
+
const discovery = gatewayMeta(response.discovery);
|
|
15293
|
+
if (!sameGeneration(snapshot.discovery, discovery)) {
|
|
15294
|
+
throw new CliError("gateway_conflict", "Gateway generation changed while reading webhook credentials.");
|
|
15295
|
+
}
|
|
15296
|
+
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")) {
|
|
15297
|
+
throw new CliError("gateway_internal", "Gateway returned an invalid webhook credential.");
|
|
15298
|
+
}
|
|
15299
|
+
let url;
|
|
15300
|
+
try {
|
|
15301
|
+
url = new URL(response.result.url);
|
|
15302
|
+
} catch {
|
|
15303
|
+
throw new CliError("gateway_internal", "Gateway returned an invalid webhook URL.");
|
|
15304
|
+
}
|
|
15305
|
+
if (url.protocol !== "https:" || url.username || url.password || url.hash) {
|
|
15306
|
+
throw new CliError("gateway_internal", "Gateway returned an unsafe webhook URL.");
|
|
15307
|
+
}
|
|
15308
|
+
const revealKey = raw.revealKey === true;
|
|
15309
|
+
writeSuccess(deps.stdout, {
|
|
15310
|
+
schemaVersion: 1,
|
|
15311
|
+
agentId: agent.id,
|
|
15312
|
+
routineId: routine.id,
|
|
15313
|
+
authority: snapshot.authority,
|
|
15314
|
+
url: url.toString(),
|
|
15315
|
+
keyPresent: true,
|
|
15316
|
+
keyIncluded: revealKey,
|
|
15317
|
+
...revealKey ? { key: response.result.key } : {}
|
|
15318
|
+
}, discovery);
|
|
15319
|
+
}
|
|
15175
15320
|
async function deleteRoutine(deps, client2, agentTarget, routineTarget, raw) {
|
|
15176
15321
|
requireConfirmed(raw);
|
|
15177
15322
|
const io = ioFromOpts(raw);
|
|
15178
15323
|
const op = operationId(raw, deps);
|
|
15179
15324
|
const expected = expectedRevision(raw);
|
|
15180
15325
|
const agent = await resolveAgent(client2, agentTarget, io.timeoutMs);
|
|
15181
|
-
const before = await readSnapshot(client2, agent
|
|
15326
|
+
const before = await readSnapshot(client2, agent, io.timeoutMs);
|
|
15182
15327
|
const prior = mutableRoutine(before, routineTarget);
|
|
15183
15328
|
if (prior.revision !== expected) throw routineCliError(new RoutineError("revision_conflict"));
|
|
15184
15329
|
let write;
|
|
@@ -15195,7 +15340,7 @@ async function deleteRoutine(deps, client2, agentTarget, routineTarget, raw) {
|
|
|
15195
15340
|
if (!sameGeneration(before.discovery, gatewayMeta(write.discovery))) {
|
|
15196
15341
|
return unknown(op, "Gateway generation changed during Routine delete; inspect the Routine list before any retry.");
|
|
15197
15342
|
}
|
|
15198
|
-
const after = await readSnapshot(client2, agent
|
|
15343
|
+
const after = await readSnapshot(client2, agent, io.timeoutMs);
|
|
15199
15344
|
if (!sameGeneration(before.discovery, after.discovery)) {
|
|
15200
15345
|
return unknown(op, "Gateway generation changed after Routine delete; inspect the Routine list before any retry.");
|
|
15201
15346
|
}
|
|
@@ -15225,6 +15370,10 @@ async function runRoutines(deps, action, agentTarget, routineTarget, raw) {
|
|
|
15225
15370
|
return;
|
|
15226
15371
|
}
|
|
15227
15372
|
if (!routineTarget) throw usage("Routine ID is required.");
|
|
15373
|
+
if (action === "webhook-credential") {
|
|
15374
|
+
await showWebhookCredential(deps, client2, agentTarget, routineTarget, raw);
|
|
15375
|
+
return;
|
|
15376
|
+
}
|
|
15228
15377
|
if (action === "update") {
|
|
15229
15378
|
await updateRoutine(deps, client2, agentTarget, routineTarget, raw);
|
|
15230
15379
|
return;
|
|
@@ -15330,6 +15479,7 @@ var FAMILY_DESCRIPTIONS = {
|
|
|
15330
15479
|
daemon: "Local daemon lifecycle",
|
|
15331
15480
|
agents: "Non-group Grok Bot agents",
|
|
15332
15481
|
"agents routines": "Native Grok Bot Routines",
|
|
15482
|
+
"agents routines webhook": "Webhook Routine credentials",
|
|
15333
15483
|
groups: "Product groups",
|
|
15334
15484
|
"groups members": "Product group membership",
|
|
15335
15485
|
history: "Search and read display transcript",
|
|
@@ -15397,6 +15547,7 @@ function actionBindings() {
|
|
|
15397
15547
|
"agents routines enable": async (deps, args, options2) => await runRoutines(deps, "enable", args[0] ?? "", args[1], options2),
|
|
15398
15548
|
"agents routines disable": async (deps, args, options2) => await runRoutines(deps, "disable", args[0] ?? "", args[1], options2),
|
|
15399
15549
|
"agents routines delete": async (deps, args, options2) => await runRoutines(deps, "delete", args[0] ?? "", args[1], options2),
|
|
15550
|
+
"agents routines webhook credential": async (deps, args, options2) => await runRoutines(deps, "webhook-credential", args[0] ?? "", args[1], options2),
|
|
15400
15551
|
"groups list": async (deps, _args, options2) => await runGroupsList(deps, options2),
|
|
15401
15552
|
"groups show": async (deps, args, options2) => await runGroupsShow(deps, args[0] ?? "", options2),
|
|
15402
15553
|
"groups create": async (deps, _args, options2) => await runGroupsCreate(deps, options2),
|
package/package.json
CHANGED
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.
|
|
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` hides the key by default; `--reveal-key` is the explicit secret-output boundary. 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.
|