@di-code/coding-agent 0.1.6 → 0.1.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 +112 -68
- package/compositions/base.yml +54 -0
- package/compositions/interactive.yml +14 -0
- package/compositions/json.yml +6 -0
- package/compositions/print.yml +5 -0
- package/compositions/rpc.yml +12 -0
- package/compositions/webui.yml +9 -0
- package/dist/cli.d.ts +22 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +97 -3
- package/dist/cli.js.map +1 -1
- package/dist/composition-loader-entry.d.ts +11 -0
- package/dist/composition-loader-entry.d.ts.map +1 -0
- package/dist/composition-loader-entry.js +12 -0
- package/dist/composition-loader-entry.js.map +1 -0
- package/dist/compositions.d.ts +32 -0
- package/dist/compositions.d.ts.map +1 -0
- package/dist/compositions.js +173 -0
- package/dist/compositions.js.map +1 -0
- package/dist/core/session/session-manager.d.ts +9 -2
- package/dist/core/session/session-manager.d.ts.map +1 -1
- package/dist/core/session/session-manager.js +28 -0
- package/dist/core/session/session-manager.js.map +1 -1
- package/dist/core/session/session-storage.d.ts.map +1 -1
- package/dist/core/session/session-storage.js +20 -3
- package/dist/core/session/session-storage.js.map +1 -1
- package/dist/core/session/types.d.ts +11 -2
- package/dist/core/session/types.d.ts.map +1 -1
- package/dist/core/session/types.js.map +1 -1
- package/dist/core/session-tools.d.ts +5 -0
- package/dist/core/session-tools.d.ts.map +1 -0
- package/dist/core/session-tools.js +17 -0
- package/dist/core/session-tools.js.map +1 -0
- package/dist/core/session.d.ts +21 -7
- package/dist/core/session.d.ts.map +1 -1
- package/dist/core/session.js +77 -41
- package/dist/core/session.js.map +1 -1
- package/dist/core/tools/bash.d.ts +1 -38
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +1 -207
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts +1 -24
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +1 -135
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts +1 -26
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +1 -140
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js +1 -23
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/file-search.d.ts +1 -13
- package/dist/core/tools/file-search.d.ts.map +1 -1
- package/dist/core/tools/file-search.js +1 -98
- package/dist/core/tools/file-search.js.map +1 -1
- package/dist/core/tools/glob.d.ts +1 -10
- package/dist/core/tools/glob.d.ts.map +1 -1
- package/dist/core/tools/glob.js +1 -43
- package/dist/core/tools/glob.js.map +1 -1
- package/dist/core/tools/grep.d.ts +1 -12
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +1 -66
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/load-skill.d.ts +1 -9
- package/dist/core/tools/load-skill.d.ts.map +1 -1
- package/dist/core/tools/load-skill.js +1 -21
- package/dist/core/tools/load-skill.js.map +1 -1
- package/dist/core/tools/path-boundary.d.ts +1 -4
- package/dist/core/tools/path-boundary.d.ts.map +1 -1
- package/dist/core/tools/path-boundary.js +1 -65
- package/dist/core/tools/path-boundary.js.map +1 -1
- package/dist/core/tools/read.d.ts +1 -16
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -131
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/write.d.ts +1 -16
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +1 -44
- package/dist/core/tools/write.js.map +1 -1
- package/dist/entry.js +30 -28
- package/dist/entry.js.map +1 -1
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +2 -0
- package/dist/i18n.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/interactive/builtin.d.ts +17 -0
- package/dist/interactive/builtin.d.ts.map +1 -0
- package/dist/interactive/builtin.js +47 -0
- package/dist/interactive/builtin.js.map +1 -0
- package/dist/interactive/controller.d.ts +85 -0
- package/dist/interactive/controller.d.ts.map +1 -0
- package/dist/interactive/controller.js +211 -0
- package/dist/interactive/controller.js.map +1 -0
- package/dist/interactive/index.d.ts +3 -0
- package/dist/interactive/index.d.ts.map +1 -0
- package/dist/interactive/index.js +3 -0
- package/dist/interactive/index.js.map +1 -0
- package/dist/interactive-host-entry.d.ts +7 -0
- package/dist/interactive-host-entry.d.ts.map +1 -0
- package/dist/interactive-host-entry.js +123 -0
- package/dist/interactive-host-entry.js.map +1 -0
- package/dist/interactive-profile.d.ts +18 -0
- package/dist/interactive-profile.d.ts.map +1 -0
- package/dist/interactive-profile.js +290 -0
- package/dist/interactive-profile.js.map +1 -0
- package/dist/interactive-resources-entry.d.ts +7 -0
- package/dist/interactive-resources-entry.d.ts.map +1 -0
- package/dist/interactive-resources-entry.js +42 -0
- package/dist/interactive-resources-entry.js.map +1 -0
- package/dist/legacy-main.d.ts +39 -0
- package/dist/legacy-main.d.ts.map +1 -0
- package/dist/legacy-main.js +611 -0
- package/dist/legacy-main.js.map +1 -0
- package/dist/main.d.ts +15 -34
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +130 -513
- package/dist/main.js.map +1 -1
- package/dist/mcp/entries.d.ts +42 -0
- package/dist/mcp/entries.d.ts.map +1 -0
- package/dist/mcp/entries.js +98 -0
- package/dist/mcp/entries.js.map +1 -0
- package/dist/mcp-client-entry.d.ts +5 -0
- package/dist/mcp-client-entry.d.ts.map +1 -0
- package/dist/mcp-client-entry.js +6 -0
- package/dist/mcp-client-entry.js.map +1 -0
- package/dist/mcp-config-entry.d.ts +5 -0
- package/dist/mcp-config-entry.d.ts.map +1 -0
- package/dist/mcp-config-entry.js +6 -0
- package/dist/mcp-config-entry.js.map +1 -0
- package/dist/mcp-tools-entry.d.ts +5 -0
- package/dist/mcp-tools-entry.d.ts.map +1 -0
- package/dist/mcp-tools-entry.js +6 -0
- package/dist/mcp-tools-entry.js.map +1 -0
- package/dist/mcp-transport-entry.d.ts +5 -0
- package/dist/mcp-transport-entry.d.ts.map +1 -0
- package/dist/mcp-transport-entry.js +6 -0
- package/dist/mcp-transport-entry.js.map +1 -0
- package/dist/modes/interactive-entry.d.ts +18 -0
- package/dist/modes/interactive-entry.d.ts.map +1 -0
- package/dist/modes/interactive-entry.js +21 -0
- package/dist/modes/interactive-entry.js.map +1 -0
- package/dist/modes/interactive-state.js +1 -1
- package/dist/modes/interactive-state.js.map +1 -1
- package/dist/modes/interactive.d.ts +16 -6
- package/dist/modes/interactive.d.ts.map +1 -1
- package/dist/modes/interactive.js +99 -33
- package/dist/modes/interactive.js.map +1 -1
- package/dist/modes/json-entry.d.ts +13 -0
- package/dist/modes/json-entry.d.ts.map +1 -0
- package/dist/modes/json-entry.js +14 -0
- package/dist/modes/json-entry.js.map +1 -0
- package/dist/modes/json.d.ts +4 -1
- package/dist/modes/json.d.ts.map +1 -1
- package/dist/modes/json.js +3 -3
- package/dist/modes/json.js.map +1 -1
- package/dist/modes/print-entry.d.ts +10 -0
- package/dist/modes/print-entry.d.ts.map +1 -0
- package/dist/modes/print-entry.js +11 -0
- package/dist/modes/print-entry.js.map +1 -0
- package/dist/modes/tree-selector.d.ts.map +1 -1
- package/dist/modes/tree-selector.js +4 -0
- package/dist/modes/tree-selector.js.map +1 -1
- package/dist/plugin-dump-composition.d.ts +6 -0
- package/dist/plugin-dump-composition.d.ts.map +1 -0
- package/dist/plugin-dump-composition.js +7 -0
- package/dist/plugin-dump-composition.js.map +1 -0
- package/dist/plugin-inventory.d.ts +7 -0
- package/dist/plugin-inventory.d.ts.map +1 -0
- package/dist/plugin-inventory.js +8 -0
- package/dist/plugin-inventory.js.map +1 -0
- package/dist/plugin-manager.d.ts +6 -0
- package/dist/plugin-manager.d.ts.map +1 -0
- package/dist/plugin-manager.js +7 -0
- package/dist/plugin-manager.js.map +1 -0
- package/dist/plugin-trace.d.ts +6 -0
- package/dist/plugin-trace.d.ts.map +1 -0
- package/dist/plugin-trace.js +7 -0
- package/dist/plugin-trace.js.map +1 -0
- package/dist/plugins/dynamic-broker.d.ts +76 -0
- package/dist/plugins/dynamic-broker.d.ts.map +1 -0
- package/dist/plugins/dynamic-broker.js +852 -0
- package/dist/plugins/dynamic-broker.js.map +1 -0
- package/dist/plugins/profile.d.ts +15 -0
- package/dist/plugins/profile.d.ts.map +1 -0
- package/dist/plugins/profile.js +34 -0
- package/dist/plugins/profile.js.map +1 -0
- package/dist/plugins/runtime-host.d.ts +37 -0
- package/dist/plugins/runtime-host.d.ts.map +1 -0
- package/dist/plugins/runtime-host.js +95 -0
- package/dist/plugins/runtime-host.js.map +1 -0
- package/dist/plugins/trust.d.ts +8 -0
- package/dist/plugins/trust.d.ts.map +1 -0
- package/dist/plugins/trust.js +59 -0
- package/dist/plugins/trust.js.map +1 -0
- package/dist/project-trust-entry.d.ts +15 -0
- package/dist/project-trust-entry.d.ts.map +1 -0
- package/dist/project-trust-entry.js +15 -0
- package/dist/project-trust-entry.js.map +1 -0
- package/dist/rpc/client.d.ts +78 -6
- package/dist/rpc/client.d.ts.map +1 -1
- package/dist/rpc/client.js +172 -4
- package/dist/rpc/client.js.map +1 -1
- package/dist/rpc/dispatcher.d.ts +121 -0
- package/dist/rpc/dispatcher.d.ts.map +1 -0
- package/dist/rpc/dispatcher.js +994 -0
- package/dist/rpc/dispatcher.js.map +1 -0
- package/dist/rpc/index.d.ts +2 -0
- package/dist/rpc/index.d.ts.map +1 -1
- package/dist/rpc/index.js +2 -0
- package/dist/rpc/index.js.map +1 -1
- package/dist/rpc/lifecycle.d.ts +6 -0
- package/dist/rpc/lifecycle.d.ts.map +1 -0
- package/dist/rpc/lifecycle.js +24 -0
- package/dist/rpc/lifecycle.js.map +1 -0
- package/dist/rpc/protocol.d.ts +112 -31
- package/dist/rpc/protocol.d.ts.map +1 -1
- package/dist/rpc/protocol.js +569 -117
- package/dist/rpc/protocol.js.map +1 -1
- package/dist/rpc/server-service.d.ts +7 -0
- package/dist/rpc/server-service.d.ts.map +1 -0
- package/dist/rpc/server-service.js +3 -0
- package/dist/rpc/server-service.js.map +1 -0
- package/dist/rpc/server.d.ts +16 -19
- package/dist/rpc/server.d.ts.map +1 -1
- package/dist/rpc/server.js +59 -115
- package/dist/rpc/server.js.map +1 -1
- package/dist/rpc-client-sdk-entry.d.ts +12 -0
- package/dist/rpc-client-sdk-entry.d.ts.map +1 -0
- package/dist/rpc-client-sdk-entry.js +11 -0
- package/dist/rpc-client-sdk-entry.js.map +1 -0
- package/dist/rpc-entry.js +50 -18
- package/dist/rpc-entry.js.map +1 -1
- package/dist/rpc-server-entry.d.ts +8 -0
- package/dist/rpc-server-entry.d.ts.map +1 -0
- package/dist/rpc-server-entry.js +67 -0
- package/dist/rpc-server-entry.js.map +1 -0
- package/dist/runtime/attachment-store.d.ts +13 -0
- package/dist/runtime/attachment-store.d.ts.map +1 -0
- package/dist/runtime/attachment-store.js +93 -0
- package/dist/runtime/attachment-store.js.map +1 -0
- package/dist/runtime/bootstrap.d.ts +14 -0
- package/dist/runtime/bootstrap.d.ts.map +1 -0
- package/dist/runtime/bootstrap.js +29 -0
- package/dist/runtime/bootstrap.js.map +1 -0
- package/dist/runtime/interactive-host-service.d.ts +22 -0
- package/dist/runtime/interactive-host-service.d.ts.map +1 -0
- package/dist/runtime/interactive-host-service.js +2 -0
- package/dist/runtime/interactive-host-service.js.map +1 -0
- package/dist/runtime/interactive-resource-service.d.ts +11 -0
- package/dist/runtime/interactive-resource-service.d.ts.map +1 -0
- package/dist/runtime/interactive-resource-service.js +3 -0
- package/dist/runtime/interactive-resource-service.js.map +1 -0
- package/dist/runtime/plugin-inventory-entry.d.ts +5 -0
- package/dist/runtime/plugin-inventory-entry.d.ts.map +1 -0
- package/dist/runtime/plugin-inventory-entry.js +18 -0
- package/dist/runtime/plugin-inventory-entry.js.map +1 -0
- package/dist/runtime/plugin-inventory-service.d.ts +8 -0
- package/dist/runtime/plugin-inventory-service.d.ts.map +1 -0
- package/dist/runtime/plugin-inventory-service.js +3 -0
- package/dist/runtime/plugin-inventory-service.js.map +1 -0
- package/dist/runtime/plugin-manager-entry.d.ts +20 -0
- package/dist/runtime/plugin-manager-entry.d.ts.map +1 -0
- package/dist/runtime/plugin-manager-entry.js +96 -0
- package/dist/runtime/plugin-manager-entry.js.map +1 -0
- package/dist/runtime/plugin-observability-entry.d.ts +12 -0
- package/dist/runtime/plugin-observability-entry.d.ts.map +1 -0
- package/dist/runtime/plugin-observability-entry.js +73 -0
- package/dist/runtime/plugin-observability-entry.js.map +1 -0
- package/dist/runtime/product-host.d.ts +91 -0
- package/dist/runtime/product-host.d.ts.map +1 -0
- package/dist/runtime/product-host.js +529 -0
- package/dist/runtime/product-host.js.map +1 -0
- package/dist/runtime/session-factory.d.ts +17 -0
- package/dist/runtime/session-factory.d.ts.map +1 -0
- package/dist/runtime/session-factory.js +75 -0
- package/dist/runtime/session-factory.js.map +1 -0
- package/dist/runtime/session-host.d.ts +152 -0
- package/dist/runtime/session-host.d.ts.map +1 -0
- package/dist/runtime/session-host.js +895 -0
- package/dist/runtime/session-host.js.map +1 -0
- package/dist/runtime-core-entry.d.ts +11 -0
- package/dist/runtime-core-entry.d.ts.map +1 -0
- package/dist/runtime-core-entry.js +9 -0
- package/dist/runtime-core-entry.js.map +1 -0
- package/dist/session-factory-entry.d.ts +7 -0
- package/dist/session-factory-entry.d.ts.map +1 -0
- package/dist/session-factory-entry.js +9 -0
- package/dist/session-factory-entry.js.map +1 -0
- package/dist/session-store-jsonl-entry.d.ts +7 -0
- package/dist/session-store-jsonl-entry.d.ts.map +1 -0
- package/dist/session-store-jsonl-entry.js +33 -0
- package/dist/session-store-jsonl-entry.js.map +1 -0
- package/dist/startup.d.ts +21 -1
- package/dist/startup.d.ts.map +1 -1
- package/dist/startup.js +179 -10
- package/dist/startup.js.map +1 -1
- package/dist/subagents/index.d.ts +2 -0
- package/dist/subagents/index.d.ts.map +1 -0
- package/dist/subagents/index.js +2 -0
- package/dist/subagents/index.js.map +1 -0
- package/dist/subagents/service.d.ts +50 -0
- package/dist/subagents/service.d.ts.map +1 -0
- package/dist/subagents/service.js +521 -0
- package/dist/subagents/service.js.map +1 -0
- package/dist/ui-host.d.ts +125 -0
- package/dist/ui-host.d.ts.map +1 -0
- package/dist/ui-host.js +275 -0
- package/dist/ui-host.js.map +1 -0
- package/dist/web/assets/index-BwfuGMvv.css +1 -0
- package/dist/web/assets/index-DPUaJqFJ.js +41 -0
- package/dist/web/assets/index-DPUaJqFJ.js.map +1 -0
- package/dist/web/index.html +14 -0
- package/dist/web-command.d.ts +11 -0
- package/dist/web-command.d.ts.map +1 -0
- package/dist/web-command.js +114 -0
- package/dist/web-command.js.map +1 -0
- package/dist/web-frontend.d.ts +73 -0
- package/dist/web-frontend.d.ts.map +1 -0
- package/dist/web-frontend.js +249 -0
- package/dist/web-frontend.js.map +1 -0
- package/dist/web.d.ts +254 -0
- package/dist/web.d.ts.map +1 -0
- package/dist/web.js +740 -0
- package/dist/web.js.map +1 -0
- package/dist/webui-entry.d.ts +3 -0
- package/dist/webui-entry.d.ts.map +1 -0
- package/dist/webui-entry.js +73 -0
- package/dist/webui-entry.js.map +1 -0
- package/dist/webui.d.ts +91 -0
- package/dist/webui.d.ts.map +1 -0
- package/dist/webui.js +882 -0
- package/dist/webui.js.map +1 -0
- package/package.json +89 -8
package/dist/rpc/protocol.js
CHANGED
|
@@ -1,6 +1,67 @@
|
|
|
1
|
+
import { validateWebManifest } from "@di-code/plugin-runtime";
|
|
1
2
|
export const RPC_PROTOCOL_VERSION = 1;
|
|
2
3
|
export const RPC_MAX_ID_LENGTH = 128;
|
|
3
4
|
export const RPC_MAX_PROMPT_LENGTH = 1_000_000;
|
|
5
|
+
export const RPC_MAX_ATTACHMENTS_PER_REQUEST = 4;
|
|
6
|
+
export const RPC_MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024;
|
|
7
|
+
/** Allows one JSONL user entry containing a maximum-sized base64 image to be read in a single transcript page. */
|
|
8
|
+
export const RPC_MAX_TRANSCRIPT_BYTES = 8 * 1024 * 1024;
|
|
9
|
+
const RPC_MAX_ATTACHMENT_BASE64_LENGTH = Math.ceil(RPC_MAX_ATTACHMENT_BYTES / 3) * 4;
|
|
10
|
+
/** v1 grows only by methods and optional fields. Clients must negotiate extended events first. */
|
|
11
|
+
export const RPC_METHODS = [
|
|
12
|
+
"prompt",
|
|
13
|
+
"cancel",
|
|
14
|
+
"get_state",
|
|
15
|
+
"get_capabilities",
|
|
16
|
+
"resume_events",
|
|
17
|
+
"list_sessions",
|
|
18
|
+
"new_session",
|
|
19
|
+
"open_session",
|
|
20
|
+
"inspect_session",
|
|
21
|
+
"rename_session",
|
|
22
|
+
"delete_session",
|
|
23
|
+
"branch_session",
|
|
24
|
+
"get_transcript",
|
|
25
|
+
"get_tree",
|
|
26
|
+
"navigate_tree",
|
|
27
|
+
"steer",
|
|
28
|
+
"retry",
|
|
29
|
+
"get_operation",
|
|
30
|
+
"get_models",
|
|
31
|
+
"set_model",
|
|
32
|
+
"get_runtime",
|
|
33
|
+
"set_runtime",
|
|
34
|
+
"set_thinking_level",
|
|
35
|
+
"compact",
|
|
36
|
+
"set_compaction_enabled",
|
|
37
|
+
"get_usage",
|
|
38
|
+
"list_skills",
|
|
39
|
+
"get_resources",
|
|
40
|
+
"get_product_state",
|
|
41
|
+
"list_providers",
|
|
42
|
+
"get_settings",
|
|
43
|
+
"set_default_provider",
|
|
44
|
+
"set_default_model",
|
|
45
|
+
"set_locale",
|
|
46
|
+
"set_permission_mode",
|
|
47
|
+
"configure_custom_provider",
|
|
48
|
+
"login",
|
|
49
|
+
"logout",
|
|
50
|
+
"get_project_trust",
|
|
51
|
+
"set_project_trust",
|
|
52
|
+
"list_context_files",
|
|
53
|
+
"list_mcp_servers",
|
|
54
|
+
"configure_mcp_server",
|
|
55
|
+
"remove_mcp_server",
|
|
56
|
+
"reconnect_mcp_server",
|
|
57
|
+
"list_plugins",
|
|
58
|
+
"list_web_contributions",
|
|
59
|
+
"list_commands",
|
|
60
|
+
"run_command",
|
|
61
|
+
"set_plugin_enabled",
|
|
62
|
+
"create_attachment",
|
|
63
|
+
"approve_tool",
|
|
64
|
+
];
|
|
4
65
|
const RPC_ERROR_CODES = new Set([
|
|
5
66
|
"PARSE_ERROR",
|
|
6
67
|
"INVALID_REQUEST",
|
|
@@ -10,10 +71,14 @@ const RPC_ERROR_CODES = new Set([
|
|
|
10
71
|
"BUSY",
|
|
11
72
|
"NOT_FOUND",
|
|
12
73
|
"CANCELLED",
|
|
74
|
+
"DISPOSED",
|
|
75
|
+
"SESSION_IN_USE",
|
|
76
|
+
"INVALID_WORKSPACE",
|
|
77
|
+
"UNAUTHORIZED",
|
|
13
78
|
"INTERNAL_ERROR",
|
|
14
79
|
"PROCESS_EXIT",
|
|
15
80
|
]);
|
|
16
|
-
const
|
|
81
|
+
const LEGACY_EVENT_TYPES = new Set([
|
|
17
82
|
"agent_start",
|
|
18
83
|
"turn_start",
|
|
19
84
|
"message_start",
|
|
@@ -25,8 +90,25 @@ const RPC_EVENT_TYPES = new Set([
|
|
|
25
90
|
"agent_end",
|
|
26
91
|
"compaction_start",
|
|
27
92
|
"compaction_end",
|
|
93
|
+
"queue_update",
|
|
94
|
+
"tree_navigated",
|
|
28
95
|
"usage_update",
|
|
29
96
|
]);
|
|
97
|
+
const EXTENDED_EVENT_TYPES = new Set([
|
|
98
|
+
"snapshot_required",
|
|
99
|
+
"operation_update",
|
|
100
|
+
"session_changed",
|
|
101
|
+
"tool_approval",
|
|
102
|
+
"product_audit",
|
|
103
|
+
]);
|
|
104
|
+
const EXTENDED_EVENT_NAMES = new Set([
|
|
105
|
+
"sequence",
|
|
106
|
+
"operation_update",
|
|
107
|
+
"snapshot_required",
|
|
108
|
+
"session_changed",
|
|
109
|
+
"tool_approval",
|
|
110
|
+
"product_audit",
|
|
111
|
+
]);
|
|
30
112
|
const ASSISTANT_STOP_REASONS = new Set(["stop", "length", "tool_use", "error", "aborted"]);
|
|
31
113
|
export class RpcProtocolError extends Error {
|
|
32
114
|
code;
|
|
@@ -44,61 +126,214 @@ function objectRecord(value) {
|
|
|
44
126
|
: undefined;
|
|
45
127
|
}
|
|
46
128
|
function requiredId(value, field, requestId) {
|
|
47
|
-
if (typeof value !== "string" || value.length === 0 || value.length > RPC_MAX_ID_LENGTH)
|
|
129
|
+
if (typeof value !== "string" || value.length === 0 || value.length > RPC_MAX_ID_LENGTH)
|
|
48
130
|
throw new RpcProtocolError("INVALID_REQUEST", `${field} must be a non-empty string of at most ${RPC_MAX_ID_LENGTH} characters.`, requestId);
|
|
49
|
-
}
|
|
50
131
|
return value;
|
|
51
132
|
}
|
|
52
133
|
function parseJsonObject(line) {
|
|
53
|
-
let value;
|
|
54
134
|
try {
|
|
55
|
-
|
|
135
|
+
const result = objectRecord(JSON.parse(line));
|
|
136
|
+
if (!result)
|
|
137
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC input must be a JSON object.");
|
|
138
|
+
return result;
|
|
56
139
|
}
|
|
57
|
-
catch {
|
|
140
|
+
catch (cause) {
|
|
141
|
+
if (cause instanceof RpcProtocolError)
|
|
142
|
+
throw cause;
|
|
58
143
|
throw new RpcProtocolError("PARSE_ERROR", "RPC input must be valid JSON.");
|
|
59
144
|
}
|
|
60
|
-
const record = objectRecord(value);
|
|
61
|
-
if (!record)
|
|
62
|
-
throw new RpcProtocolError("INVALID_REQUEST", "RPC input must be a JSON object.");
|
|
63
|
-
return record;
|
|
64
145
|
}
|
|
65
146
|
function assertVersion(record, requestId) {
|
|
66
|
-
if (record.version !== RPC_PROTOCOL_VERSION)
|
|
147
|
+
if (record.version !== RPC_PROTOCOL_VERSION)
|
|
67
148
|
throw new RpcProtocolError("UNSUPPORTED_VERSION", `Unsupported RPC protocol version; expected ${RPC_PROTOCOL_VERSION}.`, requestId);
|
|
68
|
-
}
|
|
69
149
|
}
|
|
150
|
+
function stringParam(params, name, id, optional = false) {
|
|
151
|
+
const value = params[name];
|
|
152
|
+
if (optional && value === undefined)
|
|
153
|
+
return;
|
|
154
|
+
if (typeof value !== "string" || value.length === 0 || value.length > RPC_MAX_PROMPT_LENGTH)
|
|
155
|
+
throw new RpcProtocolError("INVALID_PARAMS", `${name} must be a non-empty string.`, id);
|
|
156
|
+
}
|
|
157
|
+
function booleanParam(params, name, id) {
|
|
158
|
+
if (typeof params[name] !== "boolean")
|
|
159
|
+
throw new RpcProtocolError("INVALID_PARAMS", `${name} must be a boolean.`, id);
|
|
160
|
+
}
|
|
161
|
+
function attachmentIdsParam(params, id) {
|
|
162
|
+
if (params.attachmentIds === undefined)
|
|
163
|
+
return;
|
|
164
|
+
if (!Array.isArray(params.attachmentIds) ||
|
|
165
|
+
params.attachmentIds.length > RPC_MAX_ATTACHMENTS_PER_REQUEST ||
|
|
166
|
+
!params.attachmentIds.every((value) => typeof value === "string" && value.length > 0 && value.length <= RPC_MAX_ID_LENGTH))
|
|
167
|
+
throw new RpcProtocolError("INVALID_PARAMS", `attachmentIds must contain at most ${RPC_MAX_ATTACHMENTS_PER_REQUEST} attachment IDs.`, id);
|
|
168
|
+
}
|
|
169
|
+
function attachmentDataParam(params, id) {
|
|
170
|
+
const data = params.data;
|
|
171
|
+
if (typeof data !== "string" || data.length === 0 || data.length > RPC_MAX_ATTACHMENT_BASE64_LENGTH)
|
|
172
|
+
throw new RpcProtocolError("INVALID_PARAMS", "Attachment data exceeds the permitted size.", id);
|
|
173
|
+
}
|
|
174
|
+
/** Parses every public v1 method before any dispatcher or transport observes it. */
|
|
70
175
|
export function parseRpcRequest(line) {
|
|
71
176
|
const record = parseJsonObject(line);
|
|
72
177
|
const candidateId = typeof record.id === "string" ? record.id : undefined;
|
|
73
178
|
assertVersion(record, candidateId);
|
|
74
|
-
if (record.kind !== "request")
|
|
179
|
+
if (record.kind !== "request")
|
|
75
180
|
throw new RpcProtocolError("INVALID_REQUEST", 'RPC request kind must be "request".', candidateId);
|
|
76
|
-
}
|
|
77
181
|
const id = requiredId(record.id, "id", candidateId);
|
|
78
182
|
const params = objectRecord(record.params);
|
|
79
183
|
if (!params)
|
|
80
184
|
throw new RpcProtocolError("INVALID_PARAMS", "RPC params must be an object.", id);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
185
|
+
if (typeof record.method !== "string" || !RPC_METHODS.includes(record.method))
|
|
186
|
+
throw new RpcProtocolError("METHOD_NOT_FOUND", "Unknown RPC method.", id);
|
|
187
|
+
const method = record.method;
|
|
188
|
+
switch (method) {
|
|
189
|
+
case "prompt":
|
|
190
|
+
case "steer":
|
|
191
|
+
stringParam(params, "message", id);
|
|
192
|
+
attachmentIdsParam(params, id);
|
|
193
|
+
break;
|
|
89
194
|
case "cancel":
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
case "
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
195
|
+
case "get_operation":
|
|
196
|
+
case "open_session":
|
|
197
|
+
case "inspect_session":
|
|
198
|
+
case "rename_session":
|
|
199
|
+
case "delete_session":
|
|
200
|
+
case "navigate_tree":
|
|
201
|
+
case "set_model":
|
|
202
|
+
case "logout":
|
|
203
|
+
case "reconnect_mcp_server":
|
|
204
|
+
stringParam(params, method === "cancel" || method === "get_operation"
|
|
205
|
+
? "requestId"
|
|
206
|
+
: method === "open_session"
|
|
207
|
+
? "sessionId"
|
|
208
|
+
: method === "inspect_session" || method === "rename_session" || method === "delete_session"
|
|
209
|
+
? "sessionId"
|
|
210
|
+
: method === "navigate_tree"
|
|
211
|
+
? "entryId"
|
|
212
|
+
: method === "set_model"
|
|
213
|
+
? "modelId"
|
|
214
|
+
: method === "logout"
|
|
215
|
+
? "providerId"
|
|
216
|
+
: "serverId", id);
|
|
217
|
+
if (method === "rename_session")
|
|
218
|
+
stringParam(params, "label", id);
|
|
219
|
+
if (method === "delete_session")
|
|
220
|
+
stringParam(params, "confirmation", id);
|
|
221
|
+
break;
|
|
222
|
+
case "branch_session":
|
|
223
|
+
if (params.sessionId !== undefined)
|
|
224
|
+
stringParam(params, "sessionId", id, true);
|
|
225
|
+
if (params.entryId !== undefined)
|
|
226
|
+
stringParam(params, "entryId", id, true);
|
|
227
|
+
break;
|
|
228
|
+
case "set_runtime":
|
|
229
|
+
stringParam(params, "providerId", id);
|
|
230
|
+
stringParam(params, "modelId", id);
|
|
231
|
+
break;
|
|
232
|
+
case "run_command":
|
|
233
|
+
stringParam(params, "name", id);
|
|
234
|
+
if (!/^[a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?$/.test(params.name))
|
|
235
|
+
throw new RpcProtocolError("INVALID_PARAMS", "run_command.name is invalid.", id);
|
|
236
|
+
if (params.args !== undefined && (typeof params.args !== "string" || params.args.length > RPC_MAX_PROMPT_LENGTH))
|
|
237
|
+
throw new RpcProtocolError("INVALID_PARAMS", "args must be a string of at most 1,000,000 characters.", id);
|
|
238
|
+
break;
|
|
239
|
+
case "set_default_provider":
|
|
240
|
+
case "set_default_model":
|
|
241
|
+
case "set_locale":
|
|
242
|
+
case "set_permission_mode":
|
|
243
|
+
stringParam(params, method === "set_default_provider"
|
|
244
|
+
? "providerId"
|
|
245
|
+
: method === "set_default_model"
|
|
246
|
+
? "modelId"
|
|
247
|
+
: method === "set_locale"
|
|
248
|
+
? "locale"
|
|
249
|
+
: "permissionMode", id);
|
|
250
|
+
if (method === "set_locale" && params.locale !== "en" && params.locale !== "zh-CN")
|
|
251
|
+
throw new RpcProtocolError("INVALID_PARAMS", "locale must be en or zh-CN.", id);
|
|
252
|
+
if (method === "set_permission_mode" &&
|
|
253
|
+
params.permissionMode !== "ask" &&
|
|
254
|
+
params.permissionMode !== "allow" &&
|
|
255
|
+
params.permissionMode !== "deny")
|
|
256
|
+
throw new RpcProtocolError("INVALID_PARAMS", "permissionMode must be ask, allow, or deny.", id);
|
|
257
|
+
break;
|
|
258
|
+
case "configure_custom_provider":
|
|
259
|
+
for (const name of ["api", "baseUrl", "apiKey", "modelId"])
|
|
260
|
+
stringParam(params, name, id);
|
|
261
|
+
if (!["openai-responses", "openai-chat-completions", "anthropic-messages"].includes(params.api))
|
|
262
|
+
throw new RpcProtocolError("INVALID_PARAMS", "Unsupported custom Provider API.", id);
|
|
263
|
+
break;
|
|
264
|
+
case "set_thinking_level":
|
|
265
|
+
if (params.level !== undefined &&
|
|
266
|
+
params.level !== "low" &&
|
|
267
|
+
params.level !== "medium" &&
|
|
268
|
+
params.level !== "high" &&
|
|
269
|
+
params.level !== "max")
|
|
270
|
+
throw new RpcProtocolError("INVALID_PARAMS", "set_thinking_level.level must be a valid thinking level.", id);
|
|
271
|
+
break;
|
|
272
|
+
case "retry":
|
|
273
|
+
stringParam(params, "targetRequestId", id);
|
|
274
|
+
break;
|
|
275
|
+
case "login":
|
|
276
|
+
stringParam(params, "providerId", id);
|
|
277
|
+
stringParam(params, "apiKey", id);
|
|
278
|
+
if (params.modelId !== undefined)
|
|
279
|
+
stringParam(params, "modelId", id, true);
|
|
280
|
+
if (params.api !== undefined)
|
|
281
|
+
stringParam(params, "api", id, true);
|
|
282
|
+
break;
|
|
283
|
+
case "configure_mcp_server":
|
|
284
|
+
stringParam(params, "serverId", id);
|
|
285
|
+
stringParam(params, "scope", id);
|
|
286
|
+
if (!objectRecord(params.config))
|
|
287
|
+
throw new RpcProtocolError("INVALID_PARAMS", "config must be an object.", id);
|
|
288
|
+
break;
|
|
289
|
+
case "remove_mcp_server":
|
|
290
|
+
stringParam(params, "serverId", id);
|
|
291
|
+
if (params.scope !== undefined)
|
|
292
|
+
stringParam(params, "scope", id, true);
|
|
293
|
+
break;
|
|
294
|
+
case "set_plugin_enabled":
|
|
295
|
+
stringParam(params, "pluginId", id);
|
|
296
|
+
booleanParam(params, "enabled", id);
|
|
297
|
+
break;
|
|
298
|
+
case "set_compaction_enabled":
|
|
299
|
+
case "set_project_trust":
|
|
300
|
+
booleanParam(params, method === "set_compaction_enabled" ? "enabled" : "trusted", id);
|
|
301
|
+
break;
|
|
302
|
+
case "get_capabilities":
|
|
303
|
+
if (params.events !== undefined &&
|
|
304
|
+
(!Array.isArray(params.events) || !params.events.every((item) => typeof item === "string")))
|
|
305
|
+
throw new RpcProtocolError("INVALID_PARAMS", "get_capabilities.events must be a string array.", id);
|
|
306
|
+
break;
|
|
307
|
+
case "resume_events":
|
|
308
|
+
if (params.lastSequence !== undefined &&
|
|
309
|
+
(!Number.isSafeInteger(params.lastSequence) || params.lastSequence < 0))
|
|
310
|
+
throw new RpcProtocolError("INVALID_PARAMS", "resume_events.lastSequence must be a non-negative integer.", id);
|
|
311
|
+
break;
|
|
312
|
+
case "create_attachment":
|
|
313
|
+
stringParam(params, "name", id);
|
|
314
|
+
stringParam(params, "contentType", id);
|
|
315
|
+
attachmentDataParam(params, id);
|
|
316
|
+
if (!["image/png", "image/jpeg", "image/webp", "image/gif"].includes(params.contentType))
|
|
317
|
+
throw new RpcProtocolError("INVALID_PARAMS", "Attachment contentType is unsupported.", id);
|
|
318
|
+
break;
|
|
319
|
+
case "get_transcript":
|
|
320
|
+
if (params.pageToken !== undefined)
|
|
321
|
+
stringParam(params, "pageToken", id, true);
|
|
322
|
+
if (params.pageSize !== undefined &&
|
|
323
|
+
(!Number.isSafeInteger(params.pageSize) || params.pageSize < 1 || params.pageSize > 200))
|
|
324
|
+
throw new RpcProtocolError("INVALID_PARAMS", "pageSize must be an integer between 1 and 200.", id);
|
|
325
|
+
if (params.maxBytes !== undefined &&
|
|
326
|
+
(!Number.isSafeInteger(params.maxBytes) ||
|
|
327
|
+
params.maxBytes < 1024 ||
|
|
328
|
+
params.maxBytes > RPC_MAX_TRANSCRIPT_BYTES))
|
|
329
|
+
throw new RpcProtocolError("INVALID_PARAMS", `maxBytes must be between 1024 and ${RPC_MAX_TRANSCRIPT_BYTES}.`, id);
|
|
330
|
+
break;
|
|
331
|
+
case "approve_tool":
|
|
332
|
+
stringParam(params, "approvalId", id);
|
|
333
|
+
booleanParam(params, "approved", id);
|
|
334
|
+
break;
|
|
101
335
|
}
|
|
336
|
+
return { version: RPC_PROTOCOL_VERSION, kind: "request", id, method, params };
|
|
102
337
|
}
|
|
103
338
|
export function parseRpcServerMessage(line) {
|
|
104
339
|
const record = parseJsonObject(line);
|
|
@@ -106,22 +341,26 @@ export function parseRpcServerMessage(line) {
|
|
|
106
341
|
if (record.kind === "event") {
|
|
107
342
|
requiredId(record.requestId, "requestId");
|
|
108
343
|
const event = objectRecord(record.event);
|
|
109
|
-
|
|
344
|
+
const type = event?.type;
|
|
345
|
+
if (typeof type !== "string" ||
|
|
346
|
+
(!LEGACY_EVENT_TYPES.has(type) && !EXTENDED_EVENT_TYPES.has(type)))
|
|
347
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC event must contain a typed event object.");
|
|
348
|
+
if (!event)
|
|
110
349
|
throw new RpcProtocolError("INVALID_REQUEST", "RPC event must contain a typed event object.");
|
|
111
|
-
|
|
350
|
+
if (record.sequence !== undefined && (!Number.isSafeInteger(record.sequence) || record.sequence < 0))
|
|
351
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC event sequence is invalid.");
|
|
352
|
+
assertEvent(event, type);
|
|
112
353
|
return record;
|
|
113
354
|
}
|
|
114
|
-
if (record.kind !== "response")
|
|
355
|
+
if (record.kind !== "response")
|
|
115
356
|
throw new RpcProtocolError("INVALID_REQUEST", 'RPC server message kind must be "response" or "event".');
|
|
116
|
-
}
|
|
117
357
|
if (record.ok === false) {
|
|
118
358
|
const error = objectRecord(record.error);
|
|
119
359
|
if (!error ||
|
|
120
360
|
typeof error.code !== "string" ||
|
|
121
361
|
!RPC_ERROR_CODES.has(error.code) ||
|
|
122
|
-
typeof error.message !== "string")
|
|
362
|
+
typeof error.message !== "string")
|
|
123
363
|
throw new RpcProtocolError("INVALID_REQUEST", "RPC error response has an invalid error object.");
|
|
124
|
-
}
|
|
125
364
|
if (record.id !== undefined)
|
|
126
365
|
requiredId(record.id, "id");
|
|
127
366
|
return record;
|
|
@@ -130,94 +369,307 @@ export function parseRpcServerMessage(line) {
|
|
|
130
369
|
throw new RpcProtocolError("INVALID_REQUEST", "RPC response ok must be a boolean.");
|
|
131
370
|
requiredId(record.id, "id");
|
|
132
371
|
const result = objectRecord(record.result);
|
|
133
|
-
if (!result)
|
|
134
|
-
throw new RpcProtocolError("INVALID_REQUEST", "RPC success response
|
|
135
|
-
}
|
|
372
|
+
if (!result || typeof result.method !== "string" || !RPC_METHODS.includes(result.method))
|
|
373
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC success response has an unknown method.");
|
|
136
374
|
assertSuccessResult(result);
|
|
137
375
|
return record;
|
|
138
376
|
}
|
|
139
377
|
function assertSuccessResult(result) {
|
|
140
378
|
switch (result.method) {
|
|
141
|
-
case "prompt":
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
message.role !== "assistant" ||
|
|
145
|
-
!Array.isArray(message.content) ||
|
|
146
|
-
!message.content.every(isAssistantContent) ||
|
|
147
|
-
typeof message.provider !== "string" ||
|
|
148
|
-
typeof message.model !== "string" ||
|
|
149
|
-
!finiteNumber(message.timestamp) ||
|
|
150
|
-
typeof message.stopReason !== "string" ||
|
|
151
|
-
!ASSISTANT_STOP_REASONS.has(message.stopReason) ||
|
|
152
|
-
!isUsage(message.usage) ||
|
|
153
|
-
(message.stopReason === "error" || message.stopReason === "aborted"
|
|
154
|
-
? typeof message.errorMessage !== "string"
|
|
155
|
-
: message.errorMessage !== undefined)) {
|
|
156
|
-
throw new RpcProtocolError("INVALID_REQUEST", "RPC prompt response has an invalid message.");
|
|
157
|
-
}
|
|
379
|
+
case "prompt":
|
|
380
|
+
case "retry":
|
|
381
|
+
assertAssistantMessage(result.message);
|
|
158
382
|
return;
|
|
159
|
-
}
|
|
160
383
|
case "cancel":
|
|
161
|
-
if (typeof result.cancelled !== "boolean")
|
|
162
|
-
throw new RpcProtocolError("INVALID_REQUEST", "RPC cancel
|
|
163
|
-
}
|
|
384
|
+
if (typeof result.cancelled !== "boolean")
|
|
385
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC cancel result is invalid.");
|
|
164
386
|
return;
|
|
165
|
-
case "get_state":
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
387
|
+
case "get_state":
|
|
388
|
+
assertState(result.state);
|
|
389
|
+
return;
|
|
390
|
+
case "get_capabilities":
|
|
391
|
+
assertCapabilities(result);
|
|
392
|
+
return;
|
|
393
|
+
case "resume_events":
|
|
394
|
+
if (typeof result.snapshotRequired !== "boolean")
|
|
395
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC resume_events result is invalid.");
|
|
396
|
+
return;
|
|
397
|
+
case "get_operation":
|
|
398
|
+
assertOperationState(result.operation);
|
|
399
|
+
return;
|
|
400
|
+
case "create_attachment":
|
|
401
|
+
assertAttachmentInfo(result.attachment);
|
|
402
|
+
return;
|
|
403
|
+
case "get_product_state":
|
|
404
|
+
assertProductState(result.state);
|
|
405
|
+
return;
|
|
406
|
+
case "get_project_trust":
|
|
407
|
+
if (typeof result.trusted !== "boolean")
|
|
408
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC get_project_trust result is invalid.");
|
|
409
|
+
return;
|
|
410
|
+
case "list_sessions":
|
|
411
|
+
if (!Array.isArray(result.sessions))
|
|
412
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC list_sessions result is invalid.");
|
|
413
|
+
for (const session of result.sessions)
|
|
414
|
+
assertSessionInfo(session);
|
|
415
|
+
return;
|
|
416
|
+
case "new_session":
|
|
417
|
+
case "open_session":
|
|
418
|
+
case "rename_session":
|
|
419
|
+
case "branch_session":
|
|
420
|
+
assertSessionInfo(result.session);
|
|
421
|
+
return;
|
|
422
|
+
case "inspect_session":
|
|
423
|
+
if (!objectRecord(result.snapshot))
|
|
424
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC Session snapshot is invalid.");
|
|
425
|
+
return;
|
|
426
|
+
case "list_providers":
|
|
427
|
+
if (!Array.isArray(result.providers))
|
|
428
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC providers result is invalid.");
|
|
429
|
+
return;
|
|
430
|
+
case "list_context_files":
|
|
431
|
+
if (!Array.isArray(result.files))
|
|
432
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC context files result is invalid.");
|
|
433
|
+
return;
|
|
434
|
+
case "list_mcp_servers":
|
|
435
|
+
if (!Array.isArray(result.servers))
|
|
436
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC MCP result is invalid.");
|
|
437
|
+
return;
|
|
438
|
+
case "list_web_contributions":
|
|
439
|
+
{
|
|
440
|
+
const manifest = objectRecord(result.manifest);
|
|
441
|
+
if (!manifest || !validateWebManifest(manifest))
|
|
442
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC Web contribution manifest is invalid.");
|
|
176
443
|
}
|
|
177
444
|
return;
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
445
|
+
case "list_commands":
|
|
446
|
+
if (!Array.isArray(result.commands))
|
|
447
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC commands result is invalid.");
|
|
448
|
+
for (const command of result.commands)
|
|
449
|
+
assertCommandInfo(command);
|
|
450
|
+
return;
|
|
451
|
+
case "run_command":
|
|
452
|
+
if (typeof result.command !== "string" || !result.command)
|
|
453
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC command result is invalid.");
|
|
454
|
+
if (result.action !== undefined)
|
|
455
|
+
assertCommandAction(result.action);
|
|
456
|
+
return;
|
|
457
|
+
case "configure_mcp_server":
|
|
458
|
+
case "reconnect_mcp_server":
|
|
459
|
+
if (!objectRecord(result.server))
|
|
460
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC MCP result is invalid.");
|
|
461
|
+
return;
|
|
462
|
+
case "login":
|
|
463
|
+
if (!objectRecord(result.provider))
|
|
464
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC login result is invalid.");
|
|
465
|
+
return;
|
|
466
|
+
case "set_project_trust":
|
|
467
|
+
if (typeof result.trusted !== "boolean")
|
|
468
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC trust result is invalid.");
|
|
469
|
+
return;
|
|
470
|
+
case "logout":
|
|
471
|
+
case "remove_mcp_server":
|
|
472
|
+
return;
|
|
473
|
+
case "get_settings":
|
|
474
|
+
if (!objectRecord(result.settings))
|
|
475
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC settings result is invalid.");
|
|
476
|
+
return;
|
|
477
|
+
case "set_default_provider":
|
|
478
|
+
case "set_default_model":
|
|
479
|
+
case "set_locale":
|
|
480
|
+
case "set_permission_mode":
|
|
481
|
+
case "configure_custom_provider":
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
function assertCapabilities(result) {
|
|
486
|
+
if (!Array.isArray(result.methods) ||
|
|
487
|
+
!result.methods.every((method) => typeof method === "string" && RPC_METHODS.includes(method)) ||
|
|
488
|
+
!Array.isArray(result.events) ||
|
|
489
|
+
!result.events.every((event) => typeof event === "string" && EXTENDED_EVENT_NAMES.has(event)) ||
|
|
490
|
+
!Number.isSafeInteger(result.eventBufferSize) ||
|
|
491
|
+
result.eventBufferSize < 0)
|
|
492
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC get_capabilities result is invalid.");
|
|
493
|
+
}
|
|
494
|
+
function assertSessionInfo(value) {
|
|
495
|
+
const session = objectRecord(value);
|
|
496
|
+
if (!session || typeof session.id !== "string" || !session.id || typeof session.label !== "string")
|
|
497
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC Session result is invalid.");
|
|
498
|
+
if (session.modifiedAt !== undefined && !Number.isFinite(session.modifiedAt))
|
|
499
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC Session modifiedAt is invalid.");
|
|
500
|
+
}
|
|
501
|
+
function assertCommandInfo(value) {
|
|
502
|
+
const command = objectRecord(value);
|
|
503
|
+
if (!command ||
|
|
504
|
+
typeof command.name !== "string" ||
|
|
505
|
+
!command.name ||
|
|
506
|
+
typeof command.description !== "string" ||
|
|
507
|
+
(command.kind !== "command" && command.kind !== "skill"))
|
|
508
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC command info is invalid.");
|
|
509
|
+
}
|
|
510
|
+
function assertCommandAction(value) {
|
|
511
|
+
const action = objectRecord(value);
|
|
512
|
+
if (!action || typeof action.command !== "string" || !action.command || typeof action.args !== "string")
|
|
513
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC command action is invalid.");
|
|
514
|
+
}
|
|
515
|
+
function assertOperationState(value) {
|
|
516
|
+
const operation = objectRecord(value);
|
|
517
|
+
if (!operation ||
|
|
518
|
+
typeof operation.requestId !== "string" ||
|
|
519
|
+
!operation.requestId ||
|
|
520
|
+
typeof operation.kind !== "string" ||
|
|
521
|
+
!RPC_METHODS.includes(operation.kind) ||
|
|
522
|
+
typeof operation.status !== "string" ||
|
|
523
|
+
!["queued", "running", "completed", "failed", "cancelled", "crashed"].includes(operation.status))
|
|
524
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC operation state is invalid.");
|
|
525
|
+
if (operation.sessionId !== undefined && typeof operation.sessionId !== "string")
|
|
526
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC operation session ID is invalid.");
|
|
527
|
+
if (operation.message !== undefined)
|
|
528
|
+
assertAssistantMessage(operation.message);
|
|
529
|
+
if (operation.error !== undefined)
|
|
530
|
+
assertError(operation.error);
|
|
531
|
+
}
|
|
532
|
+
function assertAttachmentInfo(value) {
|
|
533
|
+
const attachment = objectRecord(value);
|
|
534
|
+
if (!attachment ||
|
|
535
|
+
typeof attachment.id !== "string" ||
|
|
536
|
+
!attachment.id ||
|
|
537
|
+
typeof attachment.name !== "string" ||
|
|
538
|
+
!attachment.name ||
|
|
539
|
+
typeof attachment.contentType !== "string" ||
|
|
540
|
+
!["image/png", "image/jpeg", "image/webp", "image/gif"].includes(attachment.contentType) ||
|
|
541
|
+
!Number.isSafeInteger(attachment.bytes) ||
|
|
542
|
+
attachment.bytes < 0)
|
|
543
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC attachment result is invalid.");
|
|
544
|
+
}
|
|
545
|
+
function assertProductState(value) {
|
|
546
|
+
const state = objectRecord(value);
|
|
547
|
+
if (!state || typeof state.projectTrusted !== "boolean")
|
|
548
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC product state is invalid.");
|
|
549
|
+
}
|
|
550
|
+
function assertError(value) {
|
|
551
|
+
const error = objectRecord(value);
|
|
552
|
+
if (!error ||
|
|
553
|
+
typeof error.code !== "string" ||
|
|
554
|
+
!RPC_ERROR_CODES.has(error.code) ||
|
|
555
|
+
typeof error.message !== "string")
|
|
556
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC error result is invalid.");
|
|
557
|
+
}
|
|
558
|
+
function assertEvent(event, type) {
|
|
559
|
+
if (type === "operation_update") {
|
|
560
|
+
assertOperationState(event.operation);
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
if (type === "session_changed") {
|
|
564
|
+
if (event.session !== undefined)
|
|
565
|
+
assertSessionInfo(event.session);
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
if (type === "snapshot_required")
|
|
569
|
+
return;
|
|
570
|
+
if (type === "tool_approval") {
|
|
571
|
+
if (typeof event.approvalId !== "string")
|
|
572
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC tool_approval event is invalid.");
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
if (type === "product_audit") {
|
|
576
|
+
if (typeof event.action !== "string" ||
|
|
577
|
+
![
|
|
578
|
+
"login",
|
|
579
|
+
"logout",
|
|
580
|
+
"set_project_trust",
|
|
581
|
+
"configure_mcp_server",
|
|
582
|
+
"remove_mcp_server",
|
|
583
|
+
"reconnect_mcp_server",
|
|
584
|
+
].includes(event.action) ||
|
|
585
|
+
(event.target !== undefined && typeof event.target !== "string") ||
|
|
586
|
+
(event.projectTrusted !== undefined && typeof event.projectTrusted !== "boolean"))
|
|
587
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC product_audit event is invalid.");
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
if (type === "tool_execution_start") {
|
|
591
|
+
if (typeof event.toolCallId !== "string" || typeof event.toolName !== "string" || !objectRecord(event.arguments))
|
|
592
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC tool event is invalid.");
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
if (type === "tool_execution_end") {
|
|
596
|
+
if (typeof event.toolCallId !== "string" || typeof event.toolName !== "string" || !objectRecord(event.result))
|
|
597
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC tool event is invalid.");
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
if (type === "message_start" || type === "message_end") {
|
|
601
|
+
if (!objectRecord(event.message))
|
|
602
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC message event is invalid.");
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
if (type === "message_update") {
|
|
606
|
+
const update = objectRecord(event.event);
|
|
607
|
+
if (!update || typeof update.type !== "string")
|
|
608
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC message update event is invalid.");
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
if (type === "turn_end") {
|
|
612
|
+
if (!objectRecord(event.message) || !Array.isArray(event.toolResults))
|
|
613
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC turn event is invalid.");
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
if (type === "agent_end") {
|
|
617
|
+
if (!Array.isArray(event.messages))
|
|
618
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC agent event is invalid.");
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
if (type === "compaction_start") {
|
|
622
|
+
if (event.reason !== "threshold" && event.reason !== "manual")
|
|
623
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC compaction event is invalid.");
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
if (type === "compaction_end") {
|
|
627
|
+
if ((event.reason !== "threshold" && event.reason !== "manual") ||
|
|
628
|
+
typeof event.success !== "boolean" ||
|
|
629
|
+
(event.errorMessage !== undefined && typeof event.errorMessage !== "string"))
|
|
630
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC compaction event is invalid.");
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
if (type === "queue_update") {
|
|
634
|
+
if (!Array.isArray(event.steering) || !event.steering.every((item) => typeof item === "string"))
|
|
635
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC queue event is invalid.");
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
if (type === "tree_navigated") {
|
|
639
|
+
if (typeof event.oldLeafId !== "string" ||
|
|
640
|
+
typeof event.newLeafId !== "string" ||
|
|
641
|
+
typeof event.selectedEntryId !== "string" ||
|
|
642
|
+
typeof event.restoredEditorText !== "boolean")
|
|
643
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC tree event is invalid.");
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
if (type === "usage_update" && !objectRecord(event.usage)) {
|
|
647
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC usage event is invalid.");
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
function assertState(value) {
|
|
651
|
+
const state = objectRecord(value);
|
|
652
|
+
if (!state ||
|
|
653
|
+
typeof state.sessionId !== "string" ||
|
|
654
|
+
!state.sessionId ||
|
|
655
|
+
typeof state.modelId !== "string" ||
|
|
656
|
+
!state.modelId ||
|
|
657
|
+
typeof state.isStreaming !== "boolean" ||
|
|
658
|
+
!Number.isInteger(state.messageCount) ||
|
|
659
|
+
state.messageCount < 0)
|
|
660
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC get_state response has an invalid state.");
|
|
661
|
+
}
|
|
662
|
+
function assertAssistantMessage(value) {
|
|
663
|
+
const message = objectRecord(value);
|
|
664
|
+
if (!message ||
|
|
665
|
+
message.role !== "assistant" ||
|
|
666
|
+
!Array.isArray(message.content) ||
|
|
667
|
+
typeof message.provider !== "string" ||
|
|
668
|
+
typeof message.model !== "string" ||
|
|
669
|
+
!Number.isFinite(message.timestamp) ||
|
|
670
|
+
typeof message.stopReason !== "string" ||
|
|
671
|
+
!ASSISTANT_STOP_REASONS.has(message.stopReason))
|
|
672
|
+
throw new RpcProtocolError("INVALID_REQUEST", "RPC prompt response has an invalid message.");
|
|
221
673
|
}
|
|
222
674
|
export function rpcErrorResponse(error) {
|
|
223
675
|
return {
|