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.
- package/README.md +160 -2
- package/dist/auth/lock.d.ts +14 -0
- package/dist/auth/lock.js +71 -0
- package/dist/auth/provider.d.ts +89 -0
- package/dist/auth/provider.js +884 -0
- package/dist/auth/store.d.ts +25 -0
- package/dist/auth/store.js +106 -0
- package/dist/auth/types.d.ts +138 -0
- package/dist/auth/types.js +1 -0
- package/dist/cli/config.d.ts +26 -0
- package/dist/cli/config.js +98 -0
- package/dist/cli/help.d.ts +1 -0
- package/dist/cli/help.js +83 -0
- package/dist/cli/io.d.ts +6 -0
- package/dist/cli/io.js +61 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +275 -0
- package/dist/cli/sync.d.ts +4 -0
- package/dist/cli/sync.js +105 -0
- package/dist/connect/client.d.ts +32 -0
- package/dist/connect/client.js +257 -0
- package/dist/dto/result.d.ts +33 -0
- package/dist/dto/result.js +29 -0
- package/dist/dto/types.d.ts +63 -0
- package/dist/dto/types.js +2 -0
- package/dist/errors.d.ts +31 -0
- package/dist/errors.js +64 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +11 -0
- package/dist/mcp/main.d.ts +2 -0
- package/dist/mcp/main.js +82 -0
- package/dist/mcp/tools.d.ts +24 -0
- package/dist/mcp/tools.js +408 -0
- package/dist/mcp/zod-json.d.ts +2 -0
- package/dist/mcp/zod-json.js +4 -0
- package/dist/ops/auth.d.ts +48 -0
- package/dist/ops/auth.js +89 -0
- package/dist/ops/bot.d.ts +52 -0
- package/dist/ops/bot.js +211 -0
- package/dist/ops/limits.d.ts +10 -0
- package/dist/ops/limits.js +31 -0
- package/dist/ops/map.d.ts +7 -0
- package/dist/ops/map.js +57 -0
- package/dist/ops/message.d.ts +33 -0
- package/dist/ops/message.js +118 -0
- package/dist/ops/plane.d.ts +26 -0
- package/dist/ops/plane.js +33 -0
- package/dist/ops/progress.d.ts +34 -0
- package/dist/ops/progress.js +92 -0
- package/dist/ops/session.d.ts +13 -0
- package/dist/ops/session.js +34 -0
- package/dist/ops/sidebar.d.ts +70 -0
- package/dist/ops/sidebar.js +205 -0
- package/dist/sync/attachments.d.ts +76 -0
- package/dist/sync/attachments.js +274 -0
- package/dist/sync/core.d.ts +92 -0
- package/dist/sync/core.js +1027 -0
- package/dist/sync/decode.d.ts +83 -0
- package/dist/sync/decode.js +229 -0
- package/dist/sync/download-policy.d.ts +3 -0
- package/dist/sync/download-policy.js +103 -0
- package/dist/sync/fs.d.ts +24 -0
- package/dist/sync/fs.js +252 -0
- package/dist/sync/hydrate.d.ts +43 -0
- package/dist/sync/hydrate.js +472 -0
- package/dist/sync/render.d.ts +5 -0
- package/dist/sync/render.js +100 -0
- package/dist/testing/mock-persist.d.ts +3 -0
- package/dist/testing/mock-persist.js +45 -0
- package/dist/testing/mock-transport.d.ts +18 -0
- package/dist/testing/mock-transport.js +202 -0
- package/docs/acceptance.md +19 -0
- package/docs/architecture.md +128 -0
- package/docs/auth-lock.md +87 -0
- package/docs/implementation-plan.md +14 -0
- package/docs/implementation-status.md +92 -0
- package/docs/proto-drift.md +9 -0
- package/docs/protocol/README.md +34 -0
- package/docs/protocol/attachment-pagination-0.79.3.md +32 -0
- package/docs/protocol/auth-flow.md +51 -0
- package/docs/protocol/baseline-manifest.md +72 -0
- package/docs/protocol/baselines/full-schema-diff-0.78.4-to-0.79.2.txt +239 -0
- package/docs/protocol/baselines/full-schema-diff-0.78.4-to-0.79.3.txt +240 -0
- package/docs/protocol/baselines/full-schema-diff-0.79.2-to-0.79.3.txt +23 -0
- package/docs/protocol/baselines/schema-0.79.3/README.md +7 -0
- package/docs/protocol/baselines/schema-0.79.3/agent.v1.proto +5184 -0
- package/docs/protocol/baselines/schema-0.79.3/aiserver.v1.proto +18182 -0
- package/docs/protocol/baselines/schema-0.79.3/aiserver.v1_2.proto +54 -0
- package/docs/protocol/baselines/schema-0.79.3/anyrun.v1.proto +37 -0
- package/docs/protocol/baselines/schema-0.79.3/internapi.v1.proto +35 -0
- package/docs/protocol/baselines/schema-0.79.3/snapshot.json.gz +0 -0
- package/docs/protocol/baselines/schema-0.79.3/svc_aiserver.v1.AgentStoreService.proto +34 -0
- package/docs/protocol/baselines/schema-0.79.3/svc_aiserver.v1.AiService.proto +17 -0
- package/docs/protocol/baselines/schema-0.79.3/svc_aiserver.v1.AnalyticsService.proto +17 -0
- package/docs/protocol/baselines/schema-0.79.3/svc_aiserver.v1.BackgroundComposerService.proto +19 -0
- package/docs/protocol/baselines/schema-0.79.3/svc_aiserver.v1.DashboardService.proto +101 -0
- package/docs/protocol/baselines/schema-0.79.3/svc_aiserver.v1.GrokBotService.proto +473 -0
- package/docs/protocol/baselines/schema-0.79.3/svc_aiserver.v1.SandBoxService.proto +64 -0
- package/docs/protocol/baselines/used-surface-0.78.4.json +3694 -0
- package/docs/protocol/baselines/used-surface-0.79.2.json +3835 -0
- package/docs/protocol/baselines/used-surface-0.79.3.json +3835 -0
- package/docs/protocol/baselines/used-surface-diff-0.78.4-to-0.79.2.md +34 -0
- package/docs/protocol/baselines/used-surface-diff-0.78.4-to-0.79.3.md +33 -0
- package/docs/protocol/compat-matrix.md +20 -0
- package/docs/protocol/static-restore.md +64 -0
- package/docs/protocol/surface-map.md +39 -0
- package/docs/protocol/transcript-body-0.79.3.md +98 -0
- package/docs/protocol/update-runbook.md +30 -0
- package/docs/protocol-map.md +106 -0
- package/docs/references.md +55 -0
- package/docs/requirements.md +26 -0
- package/docs/review.md +36 -0
- package/docs/sync-format.md +98 -0
- package/package.json +60 -4
- package/vendor/proto-gen/NOTICE.md +23 -0
- package/vendor/proto-gen/agent.v1_pb.js +9503 -0
- package/vendor/proto-gen/aiserver.v1_2_pb.js +105 -0
- package/vendor/proto-gen/aiserver.v1_pb.js +33163 -0
- package/vendor/proto-gen/anyrun.v1_pb.js +64 -0
- package/vendor/proto-gen/internapi.v1_pb.js +60 -0
- package/vendor/proto-gen/package.json +10 -0
- package/vendor/proto-gen/svc_aiserver.v1.GrokBotService_connect.js +4193 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Used-surface diff (aiserver.v1.GrokBotService)
|
|
2
|
+
|
|
3
|
+
RPCs used by `src`: 15
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Messages
|
|
7
|
+
|
|
8
|
+
- `aiserver.v1.CreateGrokBotAgentRequest`
|
|
9
|
+
- additive +18: optional aiserver.v1.GrokBotAgentVisibility visibility
|
|
10
|
+
- additive +19: optional int32 team_id
|
|
11
|
+
- additive +20: optional bool bot_builder_requested
|
|
12
|
+
- `aiserver.v1.GetGrokBotUserRuntimeSettingsRequest`
|
|
13
|
+
- additive +1: bool after_main_agent_change
|
|
14
|
+
- `aiserver.v1.GrokBotAgent`
|
|
15
|
+
- additive +36: optional bool shared_with_others
|
|
16
|
+
- `aiserver.v1.GrokBotAgentTask`
|
|
17
|
+
- additive +12: repeated string cloud_agent_bc_ids
|
|
18
|
+
- additive +13: optional int32 file_count
|
|
19
|
+
- additive +14: optional string last_message_entry_id
|
|
20
|
+
- additive +15: optional int64 last_message_at_ms
|
|
21
|
+
- `aiserver.v1.GrokBotUserRuntimeSettings`
|
|
22
|
+
- additive +16: optional string user_time_zone_override
|
|
23
|
+
- additive +17: optional int32 main_agent_team_id
|
|
24
|
+
- `aiserver.v1.SendGrokBotUserMessageRequest`
|
|
25
|
+
- additive +26: repeated string rendered_card_kinds
|
|
26
|
+
- `aiserver.v1.UpdateGrokBotUserRuntimeSettingsRequest`
|
|
27
|
+
- additive +13: optional string user_time_zone
|
|
28
|
+
- additive +14: optional string user_time_zone_override
|
|
29
|
+
|
|
30
|
+
## Enums
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
**Summary:** 0 breaking change(s) in the used surface.
|
|
34
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Used-surface diff (aiserver.v1.GrokBotService)
|
|
2
|
+
|
|
3
|
+
RPCs used by `src`: 15
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Messages
|
|
7
|
+
|
|
8
|
+
- `aiserver.v1.CreateGrokBotAgentRequest`
|
|
9
|
+
- additive +18: optional aiserver.v1.GrokBotAgentVisibility visibility
|
|
10
|
+
- additive +19: optional int32 team_id
|
|
11
|
+
- additive +20: optional bool bot_builder_requested
|
|
12
|
+
- `aiserver.v1.GetGrokBotUserRuntimeSettingsRequest`
|
|
13
|
+
- additive +1: bool after_main_agent_change
|
|
14
|
+
- `aiserver.v1.GrokBotAgent`
|
|
15
|
+
- additive +36: optional bool shared_with_others
|
|
16
|
+
- `aiserver.v1.GrokBotAgentTask`
|
|
17
|
+
- additive +12: repeated string cloud_agent_bc_ids
|
|
18
|
+
- additive +13: optional int32 file_count
|
|
19
|
+
- additive +14: optional string last_message_entry_id
|
|
20
|
+
- additive +15: optional int64 last_message_at_ms
|
|
21
|
+
- `aiserver.v1.GrokBotUserRuntimeSettings`
|
|
22
|
+
- additive +16: optional string user_time_zone_override
|
|
23
|
+
- additive +17: optional int32 main_agent_team_id
|
|
24
|
+
- `aiserver.v1.SendGrokBotUserMessageRequest`
|
|
25
|
+
- additive +26: repeated string rendered_card_kinds
|
|
26
|
+
- `aiserver.v1.UpdateGrokBotUserRuntimeSettingsRequest`
|
|
27
|
+
- additive +13: optional string user_time_zone
|
|
28
|
+
- additive +14: optional string user_time_zone_override
|
|
29
|
+
|
|
30
|
+
## Enums
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
**Summary:** 0 breaking change(s) in the used surface.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Compatibility matrix & remaining risks
|
|
2
|
+
|
|
3
|
+
| App version | Schema source | Used surface vs 0.78.4 | Auth anchors | Live |
|
|
4
|
+
|---|---|---|---|---|
|
|
5
|
+
| 0.78.4 (macOS) | upstream grokbot-proto `49fd8ce` | identical (previous vendor) | not analysed on this build | — |
|
|
6
|
+
| 0.79.2 (Linux amd64) | `extract_proto.py` run 2026-11-07 | **0 breaking**, additive only | analysed (auth-flow.md) | 2026-11-07: login (`redirectTarget=cli`) + ListGrokBotAgents / GetGrokBotUserRuntimeSettings / ListGrokBotAgentStatuses OK (**with 0.78.4 vendor**) |
|
|
7
|
+
| **0.79.3 (Linux amd64) — current vendor** | `extract_proto.py` + protoc + protoc-gen-es, 2026-11-07 | **0 breaking**, additive only; identical to 0.79.2 | `fingerprint.py`: same anchors as 0.79.2, only minified names differ | not run with this vendor; offline only |
|
|
8
|
+
|
|
9
|
+
## Remaining risks (unverified)
|
|
10
|
+
- Refresh: needs a user-approved public `GBT_OAUTH_CLIENT_ID`; never tested live.
|
|
11
|
+
- All write RPCs untested live: `id` vs `agent_id` for Delete/Update; `source`/`initiator`/`send_source` = 0 on send;
|
|
12
|
+
sidebar base-conflict error code; whether writes need App client headers.
|
|
13
|
+
- `viewer_session_id` came back empty for at least one bot; default session for `message send` must come from `session list`.
|
|
14
|
+
- Transcript `limit=0` semantics; streaming RPCs not used.
|
|
15
|
+
- Second login implementation present in 0.79.2/0.79.3 bundles (not analysed).
|
|
16
|
+
- Vendor is 0.79.3; the new 0.79.x fields are encodable/decodable but **not exposed** by SDK/CLI/MCP (no evidence of required semantics).
|
|
17
|
+
- App-side wire cross-check (`compare.mjs`/`cross-wire.mjs`) not run: it executes the App bundle. Replaced by `verify_generated.mjs` (generated code vs statically extracted snapshot) + contract tests.
|
|
18
|
+
- 0.79.3 vendor has had no live call.
|
|
19
|
+
- macOS vs Linux bundles for the same version not byte-compared.
|
|
20
|
+
- Third-party use of the desktop client identity / protocol is not an official API and may change or be disallowed.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Static restore method
|
|
2
|
+
|
|
3
|
+
Goal: recover the schema and auth entry points from an **official** build without running it, logging in,
|
|
4
|
+
or reading any user data. Each step lists what was actually executed for 0.79.2 (2026-11-07).
|
|
5
|
+
|
|
6
|
+
## 1. Obtain the official build
|
|
7
|
+
- Linux feed (JSON with version / commitSha / debUrl): `https://api2.cursor.sh/updates/api/download/stable/linux-x64/sand`
|
|
8
|
+
(source listed by https://docs.x.ai/grok-bot/deployment). Download the `debUrl` **without** following cross-domain redirects;
|
|
9
|
+
record size + sha256. A local sha256 is not a publisher signature.
|
|
10
|
+
- macOS: the upstream proto repo restores from `/Applications/Grok Bot.app/Contents/Resources/app.asar`.
|
|
11
|
+
- *Executed:* re-hashed the existing 0.79.2 deb (matches manifest). Not re-downloaded.
|
|
12
|
+
|
|
13
|
+
## 2. Extract without executing
|
|
14
|
+
```bash
|
|
15
|
+
dpkg-deb -x grok-bot_X_amd64.deb ./extracted # no maintainer scripts run
|
|
16
|
+
python3 tools/protocol/asar_extract.py list "./extracted/opt/Grok Bot/resources/app.asar" --grep 'electron-main/.*\.cjs$'
|
|
17
|
+
python3 tools/protocol/asar_extract.py extract "./extracted/opt/Grok Bot/resources/app.asar" /tmp/gb-X \
|
|
18
|
+
package.json dist/electron-main/proto.cjs dist/electron-main/main-app.cjs dist/electron-main/main-core.cjs
|
|
19
|
+
```
|
|
20
|
+
*Executed:* yes; hashes equal the earlier record (baseline-manifest.md).
|
|
21
|
+
|
|
22
|
+
## 3. Schema (compact descriptors in proto.cjs)
|
|
23
|
+
The App bundles `@bufbuild/protobuf` 1.10.x compact descriptors (`static $()` arrays). Upstream
|
|
24
|
+
[`grokbot-proto`](https://github.com/younglark/grokbot-proto) `scripts/extract_proto.py` turns them into `.proto` + `snapshot.json`:
|
|
25
|
+
```bash
|
|
26
|
+
python3 grokbot-proto/scripts/extract_proto.py /tmp/gb-X/dist/electron-main/proto.cjs /tmp/gb-X/out
|
|
27
|
+
# must report: unresolved refs: 0, types relocated: 0
|
|
28
|
+
```
|
|
29
|
+
Full pipeline with protoc compile, codegen, descriptor compare and wire cross-check:
|
|
30
|
+
`grokbot-proto/scripts/restore.sh --proto-cjs /tmp/gb-X/dist/electron-main/proto.cjs ./out --baseline <old>/proto`
|
|
31
|
+
(needs `pip install grpcio-tools`, node ≥ 18, and npx package downloads).
|
|
32
|
+
*Executed:* `extract_proto.py` (0 unresolved, 0 relocated) and `diff_snapshot.py`. **Not executed:** `restore.sh`
|
|
33
|
+
(protoc / codegen / wire cross-check) for 0.79.2.
|
|
34
|
+
|
|
35
|
+
Limits: restored `.proto` has no original comments, options or file layout; `google.protobuf.*` / OTEL types come from
|
|
36
|
+
libraries, not the bundle. Generator versions must match the App's `@bufbuild/protobuf` or enum names/shape drift.
|
|
37
|
+
|
|
38
|
+
## 4. Auth / transport entry points
|
|
39
|
+
```bash
|
|
40
|
+
python3 tools/protocol/fingerprint.py /tmp/gb-X/dist/electron-main/main-app.cjs /tmp/gb-X/dist/electron-main/main-core.cjs
|
|
41
|
+
```
|
|
42
|
+
Prints sha256 and, for each anchor category (login URL, poll, refresh, policy error, client headers, sidebar base, …),
|
|
43
|
+
the byte offset, nearest minified function name, and a redacted context line. Minified names (`Rdn`, `Odn`, …) change
|
|
44
|
+
every build — re-locate by anchor, then read the function in a prettified copy (`npx prettier --parser babel`), never run it.
|
|
45
|
+
*Executed:* yes on 0.79.2 main-app/main-core; anchors match auth-flow.md.
|
|
46
|
+
|
|
47
|
+
## 5. Map to this repo
|
|
48
|
+
```bash
|
|
49
|
+
python3 tools/protocol/used_surface.py --src src --old docs/protocol/baselines/used-surface-<old>.json \
|
|
50
|
+
--new /tmp/gb-X/out/snapshot.json -o /tmp/gb-X/used-surface.md # exit 1 = breaking change in used surface
|
|
51
|
+
```
|
|
52
|
+
*Executed:* 0.78.4 → 0.79.2: 0 breaking, 14 additive field lines.
|
|
53
|
+
|
|
54
|
+
## 0.79.3 run (2026-11-07) — current vendor
|
|
55
|
+
|
|
56
|
+
- Feed opened without login → 0.79.3 / `4739412…`; deb downloaded to a dir outside the repo, hashed, `dpkg-deb -x` (no install, no execution).
|
|
57
|
+
- `asar_extract.py` → proto.cjs / main-app.cjs / main-core.cjs (hashes in baseline-manifest.md).
|
|
58
|
+
- `extract_proto.py` (text parse, bundle not executed): 0 unresolved / 0 relocated / 0 backward edges.
|
|
59
|
+
- `grpc_tools.protoc` descriptor set + protoc-gen-es 1.10.1 / protoc-gen-connect-es 1.6.1 (`target=js`), installed with `npm install` in a temp dir.
|
|
60
|
+
- Toolchain reproducibility: regenerating from upstream 0.78.4 `.proto` gives the old vendor byte-for-byte.
|
|
61
|
+
- `tools/protocol/verify_generated.mjs`: 0 errors (2923 msgs / 387 enums / 464 GrokBotService RPCs; 2923 round-trips).
|
|
62
|
+
- Upstream `compare.mjs` / `cross-wire.mjs` **not run** (they `require()` the App's proto.cjs).
|
|
63
|
+
- `fingerprint.py` on main-app.cjs: same auth anchors as 0.79.2; only minified identifiers changed.
|
|
64
|
+
- Restored `.proto` live at **`proto/`** (formal protocol source); identical freeze kept under `docs/protocol/baselines/schema-0.79.3/`.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Used protocol surface → SDK / CLI / MCP
|
|
2
|
+
|
|
3
|
+
Service `aiserver.v1.GrokBotService`. Field-level detail: [baselines/used-surface-0.79.3.json](baselines/used-surface-0.79.3.json) (vendor = 0.79.3).
|
|
4
|
+
The RPC list is derived from code (`client.<rpc>(` in `src/`) by `tools/protocol/used_surface.py`.
|
|
5
|
+
|
|
6
|
+
| RPC | SDK (`src/ops`) | CLI | MCP tool | Write? | Level |
|
|
7
|
+
|---|---|---|---|---|---|
|
|
8
|
+
| ListGrokBotAgents | `bot.list` / `bot.get` | `bot list`, `bot get` | `list_bots`, `get_bot` | no | **L** (2026-11-07) |
|
|
9
|
+
| CreateGrokBotTemporalAgent (req `CreateGrokBotAgentRequest`) | `bot.create` | `bot create` | `create_bot` | yes | S + O |
|
|
10
|
+
| UpdateGrokBotAgent | `bot.update` | `bot update` | `update_bot` | yes | S + O |
|
|
11
|
+
| DeleteGrokBotAgent | `bot.delete` | `bot delete --confirm` | `delete_bot` | yes | S + O |
|
|
12
|
+
| SendGrokBotUserMessage | `message.send` | `message send` | `send_message` | yes | S + O |
|
|
13
|
+
| GetGrokBotSendStatus | `message.status` | `message status` | `get_send_status` | no | S + O |
|
|
14
|
+
| ListGrokBotTranscriptEntries | `message.history` | `message history` | `list_transcript` | no | S + O |
|
|
15
|
+
| ListGrokBotAgentSessions | `session.list` | `session list` | `list_sessions` | no | S + O |
|
|
16
|
+
| ListGrokBotAgentStatuses | `progress.status` | `bot status` | `get_bot_status` | no | **L** (2026-11-07) |
|
|
17
|
+
| ListGrokBotAgentTodos / Tasks, ListGrokBotSubagents | `progress.*` | `bot todos/tasks/subagents` | `list_agent_todos`, `list_agent_tasks`, `list_agent_subagents` | no | S + O |
|
|
18
|
+
| InterruptGrokBotAgentRun | `progress.interrupt` | `bot interrupt --confirm` | `interrupt_run` | yes | S + O |
|
|
19
|
+
| GetGrokBotUserRuntimeSettings | `sidebar.list` | `sidebar list` | `get_sidebar_sections` | no | **L** (2026-11-07) |
|
|
20
|
+
| UpdateGrokBotUserRuntimeSettings (`sidebar_sections` + `sidebar_sections_base`) | `sidebar.*` patch + read-back | `sidebar create/rename/delete/move` | `*_sidebar_section`, `move_bot_to_sidebar_section` | yes | S + O |
|
|
21
|
+
|
|
22
|
+
Live note (2026-11-07): the three **L** reads succeeded with only `authorization: Bearer`.
|
|
23
|
+
No write RPC has been executed live.
|
|
24
|
+
|
|
25
|
+
## Key semantics (see also ../protocol-map.md)
|
|
26
|
+
|
|
27
|
+
- SidebarSections: `GrokBotSidebarSection{1 id, 2 name, 3 agent_ids*}`; write sends full `sidebar_sections` (6)
|
|
28
|
+
plus `sidebar_sections_base` (12) as optimistic base. Server conflict code: unverified.
|
|
29
|
+
- Bot identity: `GrokBotAgent` has both `id` (1) and `agent_id` (12); Delete/Update requests take `id`;
|
|
30
|
+
the code sends the public `agent_id` — **unverified live**.
|
|
31
|
+
- `SendGrokBotUserMessageRequest` enums `source`(13)/`initiator`(18)/`send_source`(21) are sent as 0 — unverified.
|
|
32
|
+
- `ListGrokBotTranscriptEntriesRequest.limit` (4) is not sent (0); client-side cap only.
|
|
33
|
+
|
|
34
|
+
## 0.79.x additive fields relevant to this surface (present in vendor, not used/exposed)
|
|
35
|
+
|
|
36
|
+
From [baselines/used-surface-diff-0.78.4-to-0.79.3.md](baselines/used-surface-diff-0.78.4-to-0.79.3.md) (identical to the 0.79.2 diff):
|
|
37
|
+
`CreateGrokBotAgentRequest` +18 visibility / +19 team_id / +20 bot_builder_requested;
|
|
38
|
+
`GetGrokBotUserRuntimeSettingsRequest` +1 after_main_agent_change; `GrokBotAgent` +36 shared_with_others;
|
|
39
|
+
`SendGrokBotUserMessageRequest` +26 rendered_card_kinds; runtime settings time-zone fields; `GrokBotAgentTask` +12..15.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Transcript body 解码证据:Linux App 0.79.3
|
|
2
|
+
|
|
3
|
+
2026-11-07(Asia/Shanghai)。只读静态解包/格式化;没有启动/require/eval App,没有读取真实凭据、App 私有数据库或调用生产 RPC。
|
|
4
|
+
这是代码证据,不是生产消息抓包;测试中的文本和 ID 全是 synthetic。
|
|
5
|
+
|
|
6
|
+
## 来源与定位
|
|
7
|
+
|
|
8
|
+
| 对象 | SHA-256 |
|
|
9
|
+
|---|---|
|
|
10
|
+
| 官方包内 resources/app.asar | `5e13b57664c39a36a84d75dcfcd94f7321a38beab18fa417d1df322e5b2fabe9` |
|
|
11
|
+
| `dist/node-agent-coordinator/main.cjs` | `210bde6d8e098d178617cef13700e5ef8e5eb2a5c7325a07b8720006b135f09d` |
|
|
12
|
+
| `dist/renderer/assets/index.eager-app-BXVg2FvL.js` | `24273b47aa4bc0d416ba6731a830b535bf5f4652e3923ddf9dbcbcd1a836c254` |
|
|
13
|
+
|
|
14
|
+
原始包在 `/workspace/grokbot-linux-0.79.3/extracted/opt/Grok Bot/resources/app.asar`。
|
|
15
|
+
本轮派生证据位于 `/workspace/grokbot-sync-evidence-0793/`(不入库)。用本仓库纯 Python ASAR reader 提取上述成员,
|
|
16
|
+
再 `prettier@3.9.10 --parser babel < main.cjs > coordinator.formatted.cjs`,仅格式化不执行 JS。
|
|
17
|
+
下文行号是这个派生文件,不是 minified 原件;稳定定位以原成员哈希 + 函数/字符串锚点为准。
|
|
18
|
+
App code/schema 不作为本工具源码执行或依赖;只实现最小数据 decoder。
|
|
19
|
+
|
|
20
|
+
## 外层 protobuf,内层 JSON UI entry:不是 agent.v1.UserMessage
|
|
21
|
+
|
|
22
|
+
1. `vendor/proto-gen/aiserver.v1_pb.js` 的 GrokBotTranscriptEntry:
|
|
23
|
+
`seq / entry_kind / body:bytes / blob_hash / updated_seq / entry_id? / body_omitted`。
|
|
24
|
+
2. coordinator `Tt=(p,R)=>...`(formatted 55769–55783)执行:
|
|
25
|
+
`C=JSON.parse(h.decode(p))`,然后 `N=_b(C)`,成功返回 `{...N,seq:Number(R)}`。
|
|
26
|
+
同一函数作用域 `h=new TextDecoder`。没有 `.fromBinary(body)`、AES 或解密调用。
|
|
27
|
+
**body 是 UTF-8 JSON 编码的 UI entry;不能拿 agent.v1.UserMessage 等 protobuf 来猜解。**
|
|
28
|
+
3. `_b`(54995–54997)先 `Are(n)`,然后做 UI 兼容性清理。
|
|
29
|
+
`Are`(54868–54919)要求非空 string id,以 JSON 的 kind 分支验证 content/message/name/text/file_path 等。
|
|
30
|
+
4. renderer 的 `EF(e)` 有同样 discriminated entry validator;`dW(e)` 将 send-message 显示为 assistant、
|
|
31
|
+
user-attachment 为 user;message 用自身 role(路由/共享消息还有 UI attribution 修正)。
|
|
32
|
+
`TNn`/`ENn` 使用 tool-call 的 summary;状态/名称显示使用 name/status。
|
|
33
|
+
各 entry 的 timestampMs 用于显示时间。
|
|
34
|
+
`Szt(e)` 的 tool-call 分支直接使用 `e.id / e.status / e.summary?.length`,确认 summary/status 也属于原 entry 而非凭空拼接的另一协议;
|
|
35
|
+
`jbt(e)` 对 user-attachment 返回 `{path:e.file_path,name:e.file_name}`,确认可选文件名来源。
|
|
36
|
+
|
|
37
|
+
本实现比 App 更严格:UTF-8 必须有效,JSON 必须通过已支持子集结构,非空 outer entry_kind 若与 inner kind 不同则 opaque,
|
|
38
|
+
id 限 1024 chars、解码 body 限 4MiB。未知类型不使用 App 的宽松 fallback,也不把任何可打印字节当正文。
|
|
39
|
+
message 的 role 按源数据保留;send-message 的 assistant 和 attachment 的 user 标记 role_source=ui-kind,
|
|
40
|
+
仅表示 UI 类别,不证明真实作者身份。顺序/作用域仍采用外层 uint64 seq + 请求 agent/session,绝不使用 JSON body.seq/session。
|
|
41
|
+
|
|
42
|
+
## 已支持字段
|
|
43
|
+
|
|
44
|
+
| JSON kind | 正文/参考字段 | 角色来源 | 证据 |
|
|
45
|
+
|---|---|---|---|
|
|
46
|
+
| message | content:string;role:string 可选;timestampMs;suppressed 标记 | body.role;不擅自改写路由消息角色 | Are / EF / dW / xmn |
|
|
47
|
+
| send-message,message.type=text | message.content:string;timestampMs | renderer UI-kind=assistant | Are / EF / dW / xmn |
|
|
48
|
+
| tool-call | name:string;可选 status/summary:string(null 视为无值) | 无冒充 message role | Are / EF / TNn / ENn |
|
|
49
|
+
| notice | text:string;timestampMs | 只标 kind,不冒充 system 作者 | Are / EF |
|
|
50
|
+
| user-attachment | file_path:string;可选 file_name;timestampMs | UI-kind=user | Are / EF / dW / jbt |
|
|
51
|
+
|
|
52
|
+
工具 arguments/result/output 的完整结构没有在这条 UI entry 路径得到确认,**只显示名称/状态/summary,不声称是完整工具结果**。
|
|
53
|
+
未知工具名可以按数据显示,绝不会执行工具。附件路径只是文本引用,不打开/下载/拼成归档写路径。
|
|
54
|
+
|
|
55
|
+
未支持:非 text/attachment send-message(widget/secret-request/email-draft/approval 等)、mcp-app、event、voice-call、
|
|
56
|
+
feedback、labeler-question、未来种类、结构不符/不合法 UTF-8/非 JSON/超解码上限、body 省略/缺失。
|
|
57
|
+
这些都保留原 bytes/raw/wire,Markdown 明确占位。inline JSON 成功仅记 plaintext_json(包裹层可读),
|
|
58
|
+
其他情况记 encryption unknown;不会因解析失败而宣称是密文。协议其他文本字段的 FieldState.ENCRYPTED 不能套用到这里。
|
|
59
|
+
|
|
60
|
+
## inline / omitted / blob 的区别,以及未扩张的边界
|
|
61
|
+
|
|
62
|
+
coordinator `Ee`(formatted 55815 之后)优先 body;否则收集 blobHash;bodyOmitted 的 seq 会用同一 agent/session/generation
|
|
63
|
+
重新 List,`beforeSeq=seq+1,limit=1`,精确找回该 seq。blob 路径通过 `readBlobs` 读取,随后也交给同一个 Tt JSON decoder。
|
|
64
|
+
`j3` 的 client.readBlobs 用 PresignSandBoxStoreReads,relPaths=`blobs/<hash>`,fetch arrayBuffer 返回原始 bytes。
|
|
65
|
+
静态链中没有独立的 body 解密步骤;这不证明服务端磁盘/传输没有加密。
|
|
66
|
+
|
|
67
|
+
早期实现仅 inline 解码;现已加入显式 `--hydrate missing` 正文补读(默认off),证据与新增守卫见下节。blobHash 是 transcript 正文间接引用,
|
|
68
|
+
不应误称为普通附件,也不应当作已验证 SHA-256 或自由下载 URL。缺失正文仍是硬缺口。
|
|
69
|
+
|
|
70
|
+
coordinator 的 box gateway `getAgentTranscriptTail` 复用同一 List + hydrate + Tt 路径,不是另一个可任意替代的公开文本历史 RPC。
|
|
71
|
+
SearchGrokBotTranscripts 的 snippet 是搜索摘要,不是逐 seq 的全历史正文;本实现没有混用它补会话。
|
|
72
|
+
因此不引入额外 scope/顺序来源,不复用 App gateway 凭据。
|
|
73
|
+
|
|
74
|
+
## 合成 fixture 与测试
|
|
75
|
+
|
|
76
|
+
`test/fixtures/transcript-ui-0.79.3.synthetic.json`:**synthetic code-derived UI JSON,不是生产抓包**。
|
|
77
|
+
测试用真实生成的 GrokBotTranscriptEntry schema 编码/解码其外层 protobuf,再验证 JSON decoder、原 bytes 保存和 Markdown/rg。
|
|
78
|
+
负例用真实 agent.v1.UserMessage 编码证明“另一个 genuine protobuf 类型”不能被错误当作本路径正文。
|
|
79
|
+
大工具 summary、未知类型、乱码、omitted、scope/seq 不信 body、cached decode 不可信、Markdown/HTML/terminal 转义均有回归。
|
|
80
|
+
正文可读能力是静态协议证据 + synthetic genuine-envelope 验证;真实服务分页/正文覆盖比例/字段变种仍待 live 验证。
|
|
81
|
+
|
|
82
|
+
## 后续附件分支补充
|
|
83
|
+
renderer `rQ`/`jbt`静态确认send-message.message.type=attachment,path=message.url,name=message.file_name。
|
|
84
|
+
当前decoder支持该结构,下载只接受已证实canonical store alias,外部URL保持unsupported。
|
|
85
|
+
本次隔离live得到file:// alias、中文显示名、36字节文本,条件GET返回not_modified;
|
|
86
|
+
不将一次成功扩大为通用卡片、任意附件或blob正文支持。详见attachment-pagination-0.79.3.md与implementation-status.md。
|
|
87
|
+
|
|
88
|
+
## omitted/blob 补读修订(基于 main@8a6cf21)
|
|
89
|
+
仅静态读取 `/workspace/grokbot-sync-evidence-0793/coordinator.formatted.cjs`,未执行 App;原始 bundle 校验见本文前部。
|
|
90
|
+
- 55789–55814 `ge`:agentId/**generation(含0)**/beforeSeq=seq+1/limit=1/`_s(session)`;按返回 seq 精确找 row。
|
|
91
|
+
- 55815–55867 `Ee`:body!=null 优先,之后 blobHash,最后 bodyOmitted;omitted补读再选 body/blob;同批 ref 先 Set 去重;最终交 Tt 同 JSON decoder。
|
|
92
|
+
- 53129 `mL="blobs/"`;53230–53257 `j3.readBlobs`:GrokBotService.PresignSandBoxStoreReads 只传 relPaths,响应 instructions 按 relPath 去掉 prefix 做逐项 ref 映射,不按数组索引;每8项并行。请求没有 agent/session/generation;客户端共享已解析 access/backend/auth transport,store scope 不是用户附件 Resolve scope。
|
|
93
|
+
- 53139–53147 `Wte`:404 -> null,其他非ok报错,成功 arrayBuffer;此路径未见 blob 的403 re-presign 或 expiry 判断。不能把附件 reader 的重试推定为 blob reader 行为。
|
|
94
|
+
- proto List request/response(12337–12353)、GrokBotTranscriptEntry(10583–10591)确认 uint64 seq/updated_seq、optional body/blob、response generation,但无 session 回显,也无 caller inline字节上限。proto PresignSandBoxStoreReads(13591–13597)仅 rel_paths/instructions;SandBoxStoreReadInstruction(15421–15425)为 rel_path/url/expires_at_ms,**无 size/etag/hash-algorithm**。
|
|
95
|
+
- 此段代码没有证明 blobHash 的生成算法或跨版本不可变性,故仅当 opaque ref 使用;不根据字段名自行验证 SHA256,也不猜 store path。安全单段限制是本工具额外的保守约束,不宣称覆盖未知未来 ref 格式。
|
|
96
|
+
|
|
97
|
+
实现额外收紧:exact row generation/updated_seq/entry_id/kind 检查、uint64 successor边界;缺失/重复/额外 presign path 拒绝;合法 expiry/公开HTTPS/DNS pinning/无Bearer/URL不落盘;流式单body/总字节/时间/API预算、私有staging/fsync/rename;403最多1次新presign是有界增强,不是伪称App语义。并发改为顺序,单批去重,不实现 Watch。原始 envelope 与恢复 body 分开、版本绑定;本地 SHA256 仅表示下载内容/完整性,不表示已验证远端 ref 算法。
|
|
98
|
+
详细字段与失败/离线缓存语义见 ../sync-format.md;mock 覆盖不冒充 live。真实正文来源以本轮验收记录为准。
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Runbook: official App released a new version
|
|
2
|
+
|
|
3
|
+
1. **Keep the old baseline.** Do not overwrite `docs/protocol/baselines/*` or `vendor/proto-gen` until the end.
|
|
4
|
+
2. **Download + verify** the official build (static-restore.md §1). Record version, commitSha, size, sha256 in
|
|
5
|
+
baseline-manifest.md. Stop if the source is not official.
|
|
6
|
+
3. **Extract** with `tools/protocol/asar_extract.py` into a temp dir outside the repo (§2).
|
|
7
|
+
4. **Schema:** run upstream `extract_proto.py` (must be 0 unresolved / 0 relocated) and `diff_snapshot.py` against
|
|
8
|
+
the previous snapshot. Do **not** run upstream `restore.sh` as-is: its `compare.mjs`/`cross-wire.mjs` `require()` the App bundle.
|
|
9
|
+
Run its steps by hand instead (as done for 0.79.3): `python3 -m grpc_tools.protoc -I proto --descriptor_set_out=desc.pb proto/*.proto`,
|
|
10
|
+
then in a temp dir `npm install @bufbuild/protoc-gen-es@1.10.1 @connectrpc/protoc-gen-connect-es@1.6.1 @bufbuild/protobuf@1.10.1 @connectrpc/connect@1.6.1`
|
|
11
|
+
and `protoc --es_out=js --es_opt=target=js --connect-es_out=js --connect-es_opt=target=js`. Sanity: the toolchain must reproduce the
|
|
12
|
+
current vendor byte-for-byte from the current baseline `.proto`. Then `node tools/protocol/verify_generated.mjs <js> <snapshot.json>` must exit 0.
|
|
13
|
+
5. **Used-surface diff:** `tools/protocol/used_surface.py --old baselines/used-surface-<old>.json --new <new>/snapshot.json`.
|
|
14
|
+
- BREAKING (removed/renumbered/retyped field, RPC removed or I/O changed) → fix `src/ops/*` mapping before anything else.
|
|
15
|
+
- additive → decide per field whether SDK/CLI/MCP should expose it; old clients stay wire-compatible.
|
|
16
|
+
6. **Auth anchors:** `tools/protocol/fingerprint.py` on main-app/main-core. Re-read login URL params, poll status
|
|
17
|
+
handling, refresh endpoint/body, policy error, any new login implementation. Update auth-flow.md + `src/auth/*`
|
|
18
|
+
only from evidence; keep client_id configurable, never forge device/policy headers.
|
|
19
|
+
7. **Regenerate vendor + formal proto source:** copy the restored `.proto` set into **`proto/`** (formal source; update `proto/README.md` /
|
|
20
|
+
`proto/NOTICE.md`), keep a frozen identical copy under `baselines/schema-<new>/` (+ gzipped `snapshot.json`), copy the 6 used generated
|
|
21
|
+
files from `js/` into `vendor/proto-gen/`, update `vendor/proto-gen/NOTICE.md` (label: 本仓库从App恢复生成) + manifest hashes, keep generator
|
|
22
|
+
and runtime versions equal to the App's `@bufbuild/protobuf`, and update `test/proto-vendor-contract.test.ts`. `cmp proto/*.proto baselines/schema-<new>/*.proto` must be clean.
|
|
23
|
+
8. **Write new baseline:** `used_surface.py --src src --new <new>/snapshot.json --write-subset baselines/used-surface-<new>.json`
|
|
24
|
+
and commit the diff report next to it.
|
|
25
|
+
9. **Regression:** `npm run build && npm run typecheck && npm test && npm run test:protocol-tools`.
|
|
26
|
+
Offline/mock passing ≠ live.
|
|
27
|
+
10. **Live checks, in order, each with explicit user approval:** independent browser auth (`auth login-begin` /
|
|
28
|
+
`auth complete`) → read-only (`auth whoami`, `bot list`, `sidebar list`, `bot status`) → only then a single
|
|
29
|
+
approved write test on a disposable resource. Never blind-retry a write with an unknown outcome; reconcile first.
|
|
30
|
+
11. Update compat-matrix.md and the evidence levels in surface-map.md.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# 协议映射与覆盖矩阵(细化)
|
|
2
|
+
|
|
3
|
+
基线:vendor = App **0.79.3**(本仓库从App恢复生成,见 docs/protocol/baseline-manifest.md;此前为 `grokbot-proto` @ 49fd8ce / 0.78.4)。
|
|
4
|
+
App 行为旁证:Linux **0.79.2** `main-app.pretty.cjs`(静态,未登录)。
|
|
5
|
+
**0.78.4→0.79.3 used surface 0 breaking(仅新增字段);0.79.3 vendor 仅离线验证,未联调。**
|
|
6
|
+
|
|
7
|
+
## 覆盖矩阵
|
|
8
|
+
|
|
9
|
+
| App 动作 | 原生概念 | SDK 方法(建议) | CLI 示意(设计例,非现成命令) | MCP tool 示意 | RPC | 副作用 / 证据 |
|
|
10
|
+
|---|---|---|---|---|---|---|
|
|
11
|
+
| 列出 bots | Agent | `bot.list` | `gbc bot list --json` | `list_bots` | `ListGrokBotAgents` | 只读;可能 `truncated` |
|
|
12
|
+
| 查看 bot | Agent | `bot.get` | `gbc bot get --agent-id` | `get_bot` | **无 Get RPC**→list 筛选 | not_found |
|
|
13
|
+
| 创建 bot | Agent | `bot.create` | `gbc bot create --name …` | `create_bot` | **优先** `CreateGrokBotTemporalAgent`(I/O=CreateGrokBotAgent*) | 写;需预分配 `agent_id`;超时→unknown,禁止盲重试 |
|
|
14
|
+
| 更新 bot | Agent | `bot.update` | `gbc bot update …` | `update_bot` | `UpdateGrokBotAgent` | 写;`partial_update` |
|
|
15
|
+
| 删除 bot | Agent | `bot.delete` | `gbc bot delete --confirm=<id>` | `delete_bot` | `DeleteGrokBotAgent` | 写;App:NotFound→ok;**sidebar 清理未证** |
|
|
16
|
+
| 发消息 | UserMessage | `message.send` | `gbc message send --agent-id --session-id --text` | `send_message` | `SendGrokBotUserMessage` | 写;直接 RPC,**无强制 task** |
|
|
17
|
+
| 发送状态 | SendStatus | `message.status` | `gbc message status` | `get_send_status` | `GetGrokBotSendStatus` | 只读 |
|
|
18
|
+
| 历史 | Transcript | `message.history` | `gbc message history` | `list_transcript` | `ListGrokBotTranscriptEntries` | 只读;密文/省略不假装解密 |
|
|
19
|
+
| 会话列表 | Session | `session.list` | `gbc session list` | `list_sessions` | `ListGrokBotAgentSessions` | 只读 |
|
|
20
|
+
| 运行进展 | LiveState | `progress.status` | `gbc bot status` | `get_bot_status` | `ListGrokBotAgentStatuses` | 只读 |
|
|
21
|
+
| todos/tasks/subagents | 原生对象 | `progress.todos` 等 | `gbc bot todos`… | `list_agent_todos`… | `ListGrokBotAgentTodos` / `Tasks` / `Subagents` | 只读;≠自建 bridge_task |
|
|
22
|
+
| 中断 | Run | `progress.interrupt` | `gbc bot interrupt --confirm` | `interrupt_run` | `InterruptGrokBotAgentRun` | 写;作用域 agent(+session?) 待验 |
|
|
23
|
+
| **侧边栏分组读** | SidebarSections | `sidebar.get` | `gbc sidebar list` | `get_sidebar_sections` | `GetGrokBotUserRuntimeSettings` | 只读 |
|
|
24
|
+
| **侧边栏分组写** | SidebarSections | `sidebar.set/patch` | `gbc sidebar …` | `update_sidebar_sections` | `UpdateGrokBotUserRuntimeSettings`(仅 sections±base) | 写;冲突 best-effort;**删组≠删 bot** |
|
|
25
|
+
| 多 bot 房间 | Room | `room.*` | `gbc room …` | `create_room`… | `CreateGrokBotRoom` 等 | **非默认分组** |
|
|
26
|
+
| 团队组 | TeamGroup | `team.groups` | `gbc team groups` | `list_team_groups` | Dashboard `GetTeamGroups` | 权限/团队隔离;扩展 |
|
|
27
|
+
|
|
28
|
+
## Create 字段(已证实 vs 未证实)
|
|
29
|
+
|
|
30
|
+
**App 0.79.2 Temporal 创建路径已证实发送:**
|
|
31
|
+
`agentId`(nonce)、`name`、`description`、`title`、avatar*、`harness=TEMPORAL`、`kickstartRequested`、`introductionSuppressed`(与 kickstart 联动)、`language`、可选 `createdAutomatically`。
|
|
32
|
+
|
|
33
|
+
**0.78.4 Request 另有:** `purpose`/`origin`/`create_intent`/`create_caller` 等——App 该路径未全用;控制面默认值待定。
|
|
34
|
+
|
|
35
|
+
**未证实:** App 代码还传 `visibility`/`teamId`/`botBuilderRequested`;0.79.3 vendor 已含这些字段(+18/+19/+20),但取值语义未经 live 验证,本实现仍**不发送**。
|
|
36
|
+
|
|
37
|
+
## Sidebar 写语义(重点)
|
|
38
|
+
|
|
39
|
+
1. `get` → 得 `sections` 快照作 `base`
|
|
40
|
+
2. 本地修改最小集合(增删 section、移动 `agent_ids`)
|
|
41
|
+
3. `update({ sidebar_sections, sidebar_sections_base: base })`——**不**附带其它 runtime settings
|
|
42
|
+
4. 回读 verify
|
|
43
|
+
5. App 将部分失败映射为 `SidebarSectionsSaveConflictError`
|
|
44
|
+
|
|
45
|
+
**无真正 ETag/版本字段名**;`base` 为乐观并发快照。跨 App 并发仍可能 lost update——文档不得承诺强一致。
|
|
46
|
+
|
|
47
|
+
## 版本兼容清单(S0)
|
|
48
|
+
|
|
49
|
+
- [ ] CreateGrokBotTemporalAgent 在 0.79.2 后端行为
|
|
50
|
+
- [ ] Create 额外字段是否被忽略/拒绝
|
|
51
|
+
- [ ] RuntimeSettings base 冲突错误码
|
|
52
|
+
- [ ] `viewer_session_id` 作默认 session 是否总可用
|
|
53
|
+
- [ ] Watch/List transcript 与加密可见性
|
|
54
|
+
|
|
55
|
+
## Contract updates (review fixes on top of 14b88bf)
|
|
56
|
+
|
|
57
|
+
- `sidebar delete` / `delete_sidebar_section`: non-dry-run requires `confirm == section_id` in the SDK (CLI and MCP identical); otherwise `denied` (exit 7), no write.
|
|
58
|
+
- Value flags: `--flag value` or `--flag=value`. Missing value or next token starting with `--` → `usage` (exit 2). Dash-leading literals use `--text=--literal`. `--text-file` missing/unreadable → exit 2.
|
|
59
|
+
- Mutation RPCs (create/update/delete bot, send, sidebar write, interrupt): `unavailable`/`internal`/`unknown`/`resource_exhausted`/`deadline_exceeded`/`canceled`/transport errors → `outcome=unknown`, `retryable=false`, exit 10. Reads keep `unavailable` retryable (exit 8).
|
|
60
|
+
- Sidebar writes are read back: section id order + names + agent membership (set) must match; in-section `agent_ids` order is not compared. Mismatch or read-back failure → `sidebar_unverified`, `outcome=unknown`, exit 10, `details.diff`.
|
|
61
|
+
- `GBT_TRUST_BACKEND` / `--trust-backend`: only exact `"1"` trusts a non-allowlisted backend (SDK/CLI/MCP).
|
|
62
|
+
- `limit` (bot list, message history; CLI/MCP/SDK): integer 1..1000, default 50; invalid → `invalid_argument`/`usage` exit 2, no RPC.
|
|
63
|
+
- `bot get`: match missing in a server-`truncated` list → `lookup_incomplete` (`outcome=unknown`, exit 10), not `not_found`.
|
|
64
|
+
|
|
65
|
+
### Still unverified against the live server (mock/fake passing is not live proof)
|
|
66
|
+
- `DeleteGrokBotAgent{id}` / `UpdateGrokBotAgent{id}` are sent the public `agent_id`; whether proto `id` ≠ `agent_id` live (which would make delete NotFound→ok a false success) is unverified. Not changed.
|
|
67
|
+
- `SendGrokBotUserMessage` sends `source`/`initiator`/`send_source` = 0 (UNSPECIFIED). Not changed.
|
|
68
|
+
- `ListGrokBotTranscriptEntries` sends `limit=0`, `session_id=""`; server meaning of 0 unverified; client-side cap only.
|
|
69
|
+
- Real error code for a stale `sidebar_sections_base` (assumed `failed_precondition`/"conflict").
|
|
70
|
+
- Whether the server reorders `agent_ids` (treated as unordered) or sections (treated as ordered).
|
|
71
|
+
- Sidebar cleanup after bot delete; idempotency of `message_id`/`agent_id` on retry.
|
|
72
|
+
|
|
73
|
+
## Auth (independent Cursor browser login)
|
|
74
|
+
|
|
75
|
+
Source: STATIC reverse engineering of Grok Bot Linux 0.79.2 (`/workspace/grokbot-linux-auth-analysis.md`,
|
|
76
|
+
`evidence/main-app.pretty.cjs` = A, `main-core.pretty.cjs` = C). Not official public documentation.
|
|
77
|
+
|
|
78
|
+
| Step | Implementation | Evidence |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| Challenge | verifier = base64url(32 random bytes); challenge = base64url(SHA256(verifier)); uuid v4 | A:38644-38657 |
|
|
81
|
+
| Login URL | `https://cursor.com/loginDeepControl?challenge&uuid&mode=login&redirectTarget=cli` | A:38644-38657, A:38845 (library default `cli`; App uses `sand`, A:49834) |
|
|
82
|
+
| Poll | `GET {backend}/auth/poll?uuid&verifier`; 404 pending; 1s×1.2^i ≤10s; ≤150 tries; 3 consecutive non-404 → stop; 403 `sign_in_policy_violation` → denied | A:38720-38816 |
|
|
83
|
+
| Result | `{accessToken, refreshToken}` stored; `{xaiAccessToken,…}` → unsupported | A:38584-38622 |
|
|
84
|
+
| Refresh | `POST {backend}/oauth/token` JSON `{client_id, grant_type:"refresh_token", refresh_token}`; response `{access_token, refresh_token?, shouldLogout?, error?}`; 300s early window | A:56108-56125, A:54459, C:35811 |
|
|
85
|
+
| client_id | App picks a public id per backend (C:35866-35869). **Not embedded**; set `GBT_OAUTH_CLIENT_ID` explicitly | analysis §6 |
|
|
86
|
+
|
|
87
|
+
CLI: `auth login-begin` → `auth complete [--timeout 1..900]` (cross-process via 0600 pending file, 15 min TTL),
|
|
88
|
+
or `auth login`; `auth poll` (single), `auth cancel`, `auth refresh [--force]`, `auth whoami`/`status` (offline),
|
|
89
|
+
`auth logout` (local only). MCP: `auth_whoami`, `auth_login_begin`, `auth_login_complete` (≤120 s),
|
|
90
|
+
`auth_login_cancel`, `auth_logout` (credential writers excluded from `GBT_MCP_READONLY=1`); `auth_refresh` is **not** in READONLY.
|
|
91
|
+
Failure semantics: network/timeout/5xx/429 → retryable, creds kept, cooldown; fallback only if old token still
|
|
92
|
+
valid and revision unchanged. `shouldLogout`/policy/terminal → rescue newer pair under lock else clear; never
|
|
93
|
+
fallback revoked token. malformed/config → structured error, creds kept. Pre-RPC refresh failure keeps
|
|
94
|
+
`rpc_dispatched=false`. RPC 401: refresh for next request, return original error; write 0 replays; whitelisted
|
|
95
|
+
read-only unary may refresh+retry once. Credentials carry provenance (client_id binding, revision, session_id).
|
|
96
|
+
|
|
97
|
+
### Live status (2026-11-07, one manual run)
|
|
98
|
+
- Verified live: browser login (`loginDeepControl`, `redirectTarget=cli`) → `GET /auth/poll` → Cursor token (kind `cursor`, backend api2);
|
|
99
|
+
read-only RPCs `ListGrokBotAgents`, `GetGrokBotUserRuntimeSettings` (sidebar), `ListGrokBotAgentStatuses` succeeded with only `authorization: Bearer`.
|
|
100
|
+
- NOT verified live: token refresh (`GBT_OAUTH_CLIENT_ID` still must be configured), all write RPCs, history/session/todos/tasks.
|
|
101
|
+
|
|
102
|
+
### Auth items still unverified live
|
|
103
|
+
- Whether `supportsSelectedTeamLogin` / team selection (`x-cursor-team-id`) is needed for Grok Bot RPCs.
|
|
104
|
+
- Whether write RPCs need App headers (`x-cursor-client-type`, version, `x-ghost-mode`, …); reads worked with Bearer only.
|
|
105
|
+
- Which public client_id is appropriate for a third-party tool; refresh is off until configured.
|
|
106
|
+
- Login/refresh device-policy header `x-cursor-mdm-signin-policy` is not sent (not forged).
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# 一手来源与访问记录
|
|
2
|
+
|
|
3
|
+
访问日期:**2026-11-07(Asia/Shanghai)**。下列 URL 本轮实际打开;摘要仅据页面正文,非搜索摘要。
|
|
4
|
+
|
|
5
|
+
## MCP(钉 2025-11-25 兼容基线;latest 另见 2026-07-28)
|
|
6
|
+
|
|
7
|
+
| URL | 摘要 |
|
|
8
|
+
|---|---|
|
|
9
|
+
| https://modelcontextprotocol.io/specification/2025-11-25/server/tools | Tool schema;`annotations` **不可当信任权限**;结果可含 `isError`、`structuredContent` |
|
|
10
|
+
| https://modelcontextprotocol.io/specification/2025-11-25/basic/transports | stdio 与 Streamable HTTP;断连 **≠** 取消;取消用 `notifications/cancelled` |
|
|
11
|
+
| https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization | Authorization **可选**;**stdio SHOULD NOT** 跟 HTTP OAuth 规范 |
|
|
12
|
+
| https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/cancellation | 取消通知语义;initialize 不可取消;接收方可不响应已取消请求 |
|
|
13
|
+
| https://modelcontextprotocol.io/specification/latest | 本轮重定向至 **2026-07-28**(此前已核) |
|
|
14
|
+
|
|
15
|
+
## Connect / Protobuf
|
|
16
|
+
|
|
17
|
+
| URL | 摘要 |
|
|
18
|
+
|---|---|
|
|
19
|
+
| https://connectrpc.com/docs/protocol/ | `connect-timeout-ms`;幂等注解 `IdempotencyLevel`;取消与超时 |
|
|
20
|
+
| https://connectrpc.com/docs/go/errors/ | `ConnectError` 码;`deadline_exceeded`/`canceled`/`unknown`;RetryInfo details |
|
|
21
|
+
| https://protobuf.dev/programming-guides/field_presence/ | **implicit vs explicit presence**;proto3 `optional` 才有显式 presence;无 presence 时难做可靠 patch |
|
|
22
|
+
| https://protobuf.dev/programming-guides/proto3/#json | JSON Mapping;**int64 在 JSON 中为 string**(规范表) |
|
|
23
|
+
| https://buf.build/docs/reference/field-presence/ | **404**(本轮);改用 protobuf.dev |
|
|
24
|
+
|
|
25
|
+
## OAuth
|
|
26
|
+
|
|
27
|
+
| URL | 摘要 |
|
|
28
|
+
|---|---|
|
|
29
|
+
| https://datatracker.ietf.org/doc/html/rfc8252 | OAuth 2.0 for Native Apps(public client / 系统浏览器等) |
|
|
30
|
+
| https://datatracker.ietf.org/doc/html/rfc7636 | PKCE(S256) |
|
|
31
|
+
| https://datatracker.ietf.org/doc/html/rfc9700 | OAuth 2.0 Security BCP |
|
|
32
|
+
|
|
33
|
+
**本项目注意:** App 鉴权是 loginDeepControl + `/auth/poll`(见鉴权报告)。这是产品自定义轮询,**不应自称 RFC 8628 Device Authorization Grant**。
|
|
34
|
+
|
|
35
|
+
## CLI / 双入口开源对照(只读 remote)
|
|
36
|
+
|
|
37
|
+
| 项目 | URL | stars(gh api,本轮) | 借鉴 / 不适用 |
|
|
38
|
+
|---|---|---:|---|
|
|
39
|
+
| GitHub CLI | https://cli.github.com/manual/ | 46896(cli/cli) | `--json` 字段投影;noun-verb;**不是** Connect Bot API |
|
|
40
|
+
| GitHub MCP Server | https://github.com/github/github-mcp-server | 34284 | **toolsets / `--read-only` / 最小 scope**;双通道(remote HTTP + local);**原生 GitHub API,非 UI 自动化** |
|
|
41
|
+
| Playwright MCP | https://github.com/microsoft/playwright-mcp | 39261 | MCP vs **CLI+SKILLS** 权衡(token);**浏览器 UI 自动化 ≠ Connect 原生 RPC** |
|
|
42
|
+
| Chrome DevTools MCP | https://github.com/ChromeDevTools/chrome-devtools-mcp | 54877 | MCP+CLI 双入口;明确风险声明;**DevTools/浏览器控制,非 Bot Connect** |
|
|
43
|
+
| clig.dev | https://clig.dev/ | — | 人类/脚本友好 CLI 指南;**非硬规范** |
|
|
44
|
+
|
|
45
|
+
## 本机协议 / 鉴权证据
|
|
46
|
+
|
|
47
|
+
| 路径 | 摘要 |
|
|
48
|
+
|---|---|
|
|
49
|
+
| `/workspace/grokbot-proto` @ `49fd8ce` | 0.78.4 Schema;本轮 RPC/字段复核 |
|
|
50
|
+
| `/workspace/grokbot-linux-auth-analysis.md` | 0.79.2 静态鉴权结论 |
|
|
51
|
+
| `/workspace/grokbot-linux-0.79.2/evidence/main-app.pretty.cjs` | App:`read/writeSidebarSections` + `sidebarSectionsBase`;`SidebarSectionsSaveConflictError`;Temporal create;delete NotFound→ok |
|
|
52
|
+
|
|
53
|
+
## 宿主 timeout(此前已核,仍有效)
|
|
54
|
+
|
|
55
|
+
OpenCode / Codex / Grok Build 官方字段为**可配置默认**,非强制上限;见历史审查。本轮未重复打开全部页面。
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# 需求(审查修订版)
|
|
2
|
+
|
|
3
|
+
## 产品定义
|
|
4
|
+
|
|
5
|
+
人通过 **Grok Bot App** 驱动 → 改为 **agent CLI 经 MCP/CLI** 驱动同一 Bot。
|
|
6
|
+
可编程控制面 ≈ App 操作入口;**不是**另建任务系统。高层调度属上层 agent。
|
|
7
|
+
|
|
8
|
+
## 核心(不可降 P1)
|
|
9
|
+
|
|
10
|
+
1. Bot 生命周期:create / list / get(list筛) / update / delete
|
|
11
|
+
2. 直接发消息 + send status + history + sessions
|
|
12
|
+
3. 侧边栏分组(SidebarSections)CRUD/移动成员
|
|
13
|
+
4. 进展:status / 原生 todos·tasks·subagents / interrupt
|
|
14
|
+
5. MCP **与** CLI 同步
|
|
15
|
+
|
|
16
|
+
Room ≠ 默认分组;TeamGroup 权限隔离另列。
|
|
17
|
+
|
|
18
|
+
## 非目标
|
|
19
|
+
|
|
20
|
+
全量 607 RPC;Admin/Internal/Vault;替代 Codex 等;UI 点击自动化(Playwright/CDP 类仅作双入口借鉴);强制 taskID 账本。
|
|
21
|
+
|
|
22
|
+
## 与旧 task-bridge
|
|
23
|
+
|
|
24
|
+
保留参考;**停止作为产品交付**。吸取:勿用自建 task 状态机替代 CRUD/send。
|
|
25
|
+
|
|
26
|
+
细节矩阵 → [protocol-map.md](./protocol-map.md);审查 → [review.md](./review.md);来源 → [references.md](./references.md)。
|
package/docs/review.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# 方案审查(2026-11-07 Asia/Shanghai)
|
|
2
|
+
|
|
3
|
+
范围:`grokbot-control` 规划细化。无实现、无登录、无 push。
|
|
4
|
+
|
|
5
|
+
## 严重级别说明
|
|
6
|
+
|
|
7
|
+
- **P0**:会直接导致错误产品方向或不安全承诺
|
|
8
|
+
- **P1**:实施前必须钉死,否则易误删/丢更新/双写
|
|
9
|
+
- **P2**:质量/可运维;可分期但要写清
|
|
10
|
+
|
|
11
|
+
## 问题 → 修订 → 依据
|
|
12
|
+
|
|
13
|
+
| # | 级别 | 旧表述/风险 | 修订 | 依据 |
|
|
14
|
+
|---|---|---|---|---|
|
|
15
|
+
| 1 | P0 | 以 task 桥为中心 / CRUD 降级 | **废止**;App 等价控制面;CRUD+直接 send 为核心 | 用户定义 + 本仓产品定义 |
|
|
16
|
+
| 2 | P0 | 分组猜 Room / 或「不做」 | 默认 **SidebarSections**;Room/TeamGroup 分列 | proto RuntimeSettings;App `writeSidebarSections` |
|
|
17
|
+
| 3 | P0 | 暗示强一致分组事务 | **无 ETag**;仅有 `sidebar_sections_base` best-effort;冲突→`SaveConflict` 类错误;本进程锁≠跨 App 安全 | App `SidebarSectionsSaveConflictError`;protobuf presence 指南 |
|
|
18
|
+
| 4 | P1 | Update RuntimeSettings 像「全量覆盖 settings」 | App **只写** `sidebar_sections`(+可选 base);其它 settings 字段不随分组写带上 | main-app.pretty.cjs:131748–131754 |
|
|
19
|
+
| 5 | P1 | 编造 GetBot RPC / rawRPC 万能工具 | **无**独立 Get;list 客户端筛选;禁止默认 raw/admin 代理 | proto 方法表;GitHub MCP toolsets 反例(按域暴露) |
|
|
20
|
+
| 6 | P1 | create 字段想当然 | App 现路径走 `CreateGrokBotTemporalAgent`(同 Request);需 `agent_id` nonce、`harness=TEMPORAL`、`description`/`name`、kickstart/introduction 组合;0.79 App 代码另传 visibility/teamId 等 **0.78.4 Request 无这些字段**→标 drift | App create();snapshot CreateGrokBotAgentRequest |
|
|
21
|
+
| 7 | P1 | delete 副作用猜会清 sidebar | **未证实**;delete 仅 `DeleteGrokBotAgent{id}`;NotFound 当 ok;sidebar 残留待真机 | App g_t delete |
|
|
22
|
+
| 8 | P1 | 丢响应后自动重试 create/send/delete | **禁止**自动重发;对账→`outcome=unknown` | Connect timeout/cancel;CLI 幂等共识;MCP cancel≠业务 Interrupt |
|
|
23
|
+
| 9 | P1 | MCP cancel / tool timeout = Interrupt | 分离:MCP/CLI 请求取消 ≠ `InterruptGrokBotAgentRun` | MCP transports/cancellation |
|
|
24
|
+
| 10 | P1 | poll 登录自称 device flow | 称产品自定义 PKCE-ish + poll;引 RFC8252/7636/9700 作 **安全实践**,非协议等同 | 鉴权报告;RFC |
|
|
25
|
+
| 11 | P2 | 大工具面一次塞满 | 借鉴 GitHub MCP **toolsets + read-only**;按 bot/message/sidebar/progress 分组启用 | github-mcp-server README |
|
|
26
|
+
| 12 | P2 | CLI/MCP 混用 stdout | CLI:stdout 数据 stderr 进度;MCP stdio 专用于 JSON-RPC,禁止夹带 CLI JSON | MCP transports;agent-cli-design / clig |
|
|
27
|
+
| 13 | P2 | Playwright/Chrome MCP 当同构对照 | 仅借鉴「MCP+CLI 双入口 / 风险声明」;**UI 自动化 ≠ Connect 原生 API** | 各自 README |
|
|
28
|
+
|
|
29
|
+
## Open questions(少问卷)
|
|
30
|
+
|
|
31
|
+
1. 「分组」是否确认 = SidebarSections?(计划默认是)
|
|
32
|
+
2. create 对个人 bot:是否一律 `CreateGrokBotTemporalAgent` + TEMPORAL harness?(App 现路径倾向是;BOX harness 路径未完整静态追完)
|
|
33
|
+
3. 0.78.4↔0.79.2:Create 请求字段 drift、RuntimeSettings 行为是否一致?(必须 S0)
|
|
34
|
+
4. 服务端对 `sidebar_sections_base` 冲突的确切错误码/条件?(App 有映射;线上码待验)
|
|
35
|
+
5. delete 后 sidebar 是否仍引用已删 agent_id?(观察项)
|
|
36
|
+
6. 第三方身份政策是否允许独立控制面登录?(鉴权报告已标未验)
|