@mininglamp-oss/octo-runtime 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/README.md +4 -2
  2. package/apps/cli/README.md +3 -1
  3. package/apps/cli/dist/build-info.json +2 -2
  4. package/apps/cli/dist/extras.d.ts +4 -2
  5. package/apps/cli/dist/extras.js +20 -21
  6. package/apps/cli/dist/help.js +3 -0
  7. package/apps/cli/dist/logs.d.ts +10 -0
  8. package/apps/cli/dist/logs.js +186 -0
  9. package/apps/cli/dist/main.d.ts +1 -0
  10. package/apps/cli/dist/main.js +94 -19
  11. package/apps/cli/dist/{default_adapters.json → manifest.json} +10 -0
  12. package/apps/cli/dist/module-manifest.d.ts +3 -0
  13. package/apps/cli/dist/module-manifest.js +11 -0
  14. package/apps/cli/dist/openclaw.js +30 -6
  15. package/apps/cli/dist/output.js +3 -0
  16. package/apps/cli/dist/playboard.js +10 -8
  17. package/apps/cli/dist/status-output.d.ts +10 -0
  18. package/apps/cli/dist/status-output.js +65 -0
  19. package/apps/cli/dist/worker.d.ts +1 -0
  20. package/apps/cli/dist/worker.js +18 -0
  21. package/dist/public/host.d.ts +1 -0
  22. package/node_modules/@mininglamp-oss/octo-runtime-acp-client/package.json +3 -3
  23. package/node_modules/@mininglamp-oss/octo-runtime-adapter-acp/package.json +4 -4
  24. package/node_modules/@mininglamp-oss/octo-runtime-adapter-antigravity/package.json +3 -3
  25. package/node_modules/@mininglamp-oss/octo-runtime-adapter-claude-code/package.json +3 -3
  26. package/node_modules/@mininglamp-oss/octo-runtime-adapter-codebuddy/package.json +4 -4
  27. package/node_modules/@mininglamp-oss/octo-runtime-adapter-codex/package.json +3 -3
  28. package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/adapter.d.ts +54 -0
  29. package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/adapter.js +399 -0
  30. package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/client.d.ts +14 -0
  31. package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/client.js +156 -0
  32. package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/index.d.ts +29 -0
  33. package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/index.js +273 -0
  34. package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/interactions.d.ts +27 -0
  35. package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/interactions.js +161 -0
  36. package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/package.json +17 -0
  37. package/node_modules/@mininglamp-oss/octo-runtime-adapter-hermes/package.json +2 -2
  38. package/node_modules/@mininglamp-oss/octo-runtime-adapter-kimi-code/package.json +2 -2
  39. package/node_modules/@mininglamp-oss/octo-runtime-adapter-mcode/package.json +2 -2
  40. package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/dist/compatibility.d.ts +24 -0
  41. package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/dist/compatibility.js +181 -0
  42. package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/dist/gateway.d.ts +9 -0
  43. package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/dist/gateway.js +24 -8
  44. package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/dist/index.js +229 -225
  45. package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/package.json +3 -3
  46. package/node_modules/@mininglamp-oss/octo-runtime-adapter-opencode/package.json +4 -4
  47. package/node_modules/@mininglamp-oss/octo-runtime-adapter-qodercli/package.json +2 -2
  48. package/node_modules/@mininglamp-oss/octo-runtime-adapter-qoderclicn/package.json +2 -2
  49. package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/approval.d.ts +4 -0
  50. package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/approval.js +5 -6
  51. package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/index.d.ts +1 -0
  52. package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/index.js +1 -0
  53. package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/module-manifest.d.ts +33 -0
  54. package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/module-manifest.js +118 -0
  55. package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/runtime-log-worker.js +7 -5
  56. package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/runtime-log.d.ts +3 -0
  57. package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/runtime-log.js +45 -10
  58. package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/service-status.d.ts +11 -0
  59. package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/service-status.js +70 -0
  60. package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/package.json +5 -3
  61. package/node_modules/@mininglamp-oss/octo-runtime-adapter-zcode-gui/package.json +3 -3
  62. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/build-info.json +2 -2
  63. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/extras.d.ts +4 -2
  64. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/extras.js +20 -21
  65. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/help.js +3 -0
  66. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/logs.d.ts +10 -0
  67. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/logs.js +186 -0
  68. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/main.d.ts +1 -0
  69. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/main.js +94 -19
  70. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/{default_adapters.json → manifest.json} +10 -0
  71. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/module-manifest.d.ts +3 -0
  72. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/module-manifest.js +11 -0
  73. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/openclaw.js +30 -6
  74. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/output.js +3 -0
  75. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/playboard.js +10 -8
  76. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/status-output.d.ts +10 -0
  77. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/status-output.js +65 -0
  78. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/worker.d.ts +1 -0
  79. package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/worker.js +18 -0
  80. package/node_modules/@mininglamp-oss/octo-runtime-cli/package.json +23 -9
  81. package/node_modules/@mininglamp-oss/octo-runtime-cross-service/package.json +2 -2
  82. package/node_modules/@mininglamp-oss/octo-runtime-executor-core/dist/model-input.d.ts +1 -1
  83. package/node_modules/@mininglamp-oss/octo-runtime-executor-core/dist/model-input.js +13 -9
  84. package/node_modules/@mininglamp-oss/octo-runtime-executor-core/package.json +3 -3
  85. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/heartbeat.d.ts +16 -0
  86. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/heartbeat.js +59 -0
  87. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/invocation-manifest.d.ts +1 -0
  88. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/invocation-manifest.js +4 -1
  89. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/manifest-adapters.d.ts +6 -0
  90. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/manifest-adapters.js +88 -0
  91. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/module-specifier.d.ts +1 -2
  92. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/module-specifier.js +2 -9
  93. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/process.d.ts +7 -2
  94. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/process.js +138 -9
  95. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/runner.js +3 -92
  96. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/serve.js +36 -12
  97. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/server.d.ts +4 -1
  98. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/server.js +14 -6
  99. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/service.js +2 -1
  100. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/supervisor.d.ts +2 -2
  101. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/dist/supervisor.js +57 -34
  102. package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/package.json +8 -16
  103. package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/config-schema.json +2 -2
  104. package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/application/im-channel.js +18 -18
  105. package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/contracts.d.ts +1 -0
  106. package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/execution/dispatcher.js +24 -0
  107. package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/transport/contexts.js +2 -2
  108. package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/transport/mentions.d.ts +5 -2
  109. package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/transport/mentions.js +19 -5
  110. package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/transport/normalize.js +1 -0
  111. package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/package.json +6 -6
  112. package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-wecom/config-schema.json +2 -2
  113. package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-wecom/package.json +5 -5
  114. package/node_modules/@mininglamp-oss/octo-runtime-extra-webui/config-schema.json +2 -2
  115. package/node_modules/@mininglamp-oss/octo-runtime-extra-webui/dist/index.js +1 -1
  116. package/node_modules/@mininglamp-oss/octo-runtime-extra-webui/dist/store.d.ts +4 -1
  117. package/node_modules/@mininglamp-oss/octo-runtime-extra-webui/dist/store.js +54 -4
  118. package/node_modules/@mininglamp-oss/octo-runtime-extra-webui/package.json +2 -2
  119. package/node_modules/@mininglamp-oss/octo-runtime-host-sdk/dist/extra-config.d.ts +8 -1
  120. package/node_modules/@mininglamp-oss/octo-runtime-host-sdk/dist/extra-config.js +27 -12
  121. package/node_modules/@mininglamp-oss/octo-runtime-host-sdk/dist/extra-service.js +39 -2
  122. package/node_modules/@mininglamp-oss/octo-runtime-host-sdk/dist/index.d.ts +1 -0
  123. package/node_modules/@mininglamp-oss/octo-runtime-host-sdk/package.json +4 -4
  124. package/node_modules/@mininglamp-oss/octo-runtime-protocol/package.json +1 -1
  125. package/node_modules/import-meta-resolve/index.d.ts +19 -0
  126. package/node_modules/import-meta-resolve/index.d.ts.map +1 -0
  127. package/node_modules/import-meta-resolve/index.js +47 -0
  128. package/node_modules/import-meta-resolve/lib/errors.d.ts +24 -0
  129. package/node_modules/import-meta-resolve/lib/errors.d.ts.map +1 -0
  130. package/node_modules/import-meta-resolve/lib/errors.js +504 -0
  131. package/node_modules/import-meta-resolve/lib/get-format.d.ts +13 -0
  132. package/node_modules/import-meta-resolve/lib/get-format.d.ts.map +1 -0
  133. package/node_modules/import-meta-resolve/lib/get-format.js +159 -0
  134. package/node_modules/import-meta-resolve/lib/package-json-reader.d.ts +31 -0
  135. package/node_modules/import-meta-resolve/lib/package-json-reader.d.ts.map +1 -0
  136. package/node_modules/import-meta-resolve/lib/package-json-reader.js +177 -0
  137. package/node_modules/import-meta-resolve/lib/resolve.d.ts +29 -0
  138. package/node_modules/import-meta-resolve/lib/resolve.d.ts.map +1 -0
  139. package/node_modules/import-meta-resolve/lib/resolve.js +1301 -0
  140. package/node_modules/import-meta-resolve/lib/utils.d.ts +6 -0
  141. package/node_modules/import-meta-resolve/lib/utils.d.ts.map +1 -0
  142. package/node_modules/import-meta-resolve/lib/utils.js +47 -0
  143. package/node_modules/import-meta-resolve/license +74 -0
  144. package/node_modules/import-meta-resolve/package.json +78 -0
  145. package/node_modules/import-meta-resolve/readme.md +252 -0
  146. package/package.json +30 -26
  147. package/packages/octo-runtime-extra-channel-gateway/config-schema.json +2 -2
  148. package/packages/octo-runtime-extra-channel-wecom/config-schema.json +2 -2
  149. package/packages/octo-runtime-extra-webui/config-schema.json +2 -2
@@ -0,0 +1,399 @@
1
+ import { spawnGrokBuildAcpClient as spawnAcpClient } from "./client.js";
2
+ import { GrokBuildInteractionBridge as AcpApprovalBridge } from "./interactions.js";
3
+ import { acpModelSelectionRequest, acpActmodeSelectionRequest, normalizeAcpUpdate } from "@mininglamp-oss/octo-runtime-adapter-acp";
4
+ import { acpLoadSessionParams, acpNewSessionParams, acpPromptParams } from "@mininglamp-oss/octo-runtime-acp-client";
5
+ import { initialControlInstructions, actmodeEvidence, AcpTurnNormalizer, defineAdapter, invocationEnvironment, invocationMcpServers, assertMcpOptions, probeCommand } from "@mininglamp-oss/octo-runtime-adapter-sdk";
6
+ import { canonicalTerminalStatus, contextActmode, providerInputParts } from "@mininglamp-oss/octo-runtime-protocol";
7
+ function sessionModel(session) {
8
+ const modelOption = arrayField(session, "configOptions")
9
+ .map(recordValue)
10
+ .find((option) => stringField(option, "id") === "model" || stringField(option, "category") === "model");
11
+ return (stringField(modelOption ?? {}, "currentValue") ??
12
+ stringField(recordValue(session.models), "currentModelId") ??
13
+ stringField(session, "model"));
14
+ }
15
+ export function createGrokBuildAcpAdapter(definition, { acpClientFactory = spawnAcpClient, command = definition.command } = {}) {
16
+ const responders = new Map();
17
+ return defineAdapter({
18
+ metadata: {
19
+ mcp: true,
20
+ type: definition.type,
21
+ agentSources: ["provisioned"]
22
+ },
23
+ probe: definition.probe ?? (() => probeCommand(command)),
24
+ async respondInteraction(invocationId, response) {
25
+ const bridge = responders.get(invocationId);
26
+ if (!bridge)
27
+ throw new Error("INTERACTION_NOT_ACTIVE");
28
+ await bridge.respond(response);
29
+ },
30
+ async *invoke(request, context) {
31
+ if (request.approvalMode !== "ask" && request.approvalMode !== "full_access")
32
+ throw new Error("APPROVAL_MODE_UNSUPPORTED: this ACP adapter has no assisted policy");
33
+ if (responders.has(request.invocationId))
34
+ throw new Error("INVOCATION_ALREADY_ACTIVE");
35
+ const bridge = new AcpApprovalBridge(request);
36
+ responders.set(request.invocationId, bridge);
37
+ try {
38
+ yield* bridge.stream(execute(request, bridge, context));
39
+ }
40
+ finally {
41
+ bridge.close("execution_lost");
42
+ responders.delete(request.invocationId);
43
+ }
44
+ }
45
+ }, definition.reasoningLevels ?? null);
46
+ async function* execute(request, bridge, context) {
47
+ const args = typeof definition.args === "function"
48
+ ? definition.args(request)
49
+ : (definition.args ?? ["acp"]);
50
+ const runEnv = invocationEnvironment(request, definition.env?.(request));
51
+ const mcp = invocationMcpServers(request, runEnv);
52
+ assertMcpOptions(mcp, definition.type, []);
53
+ const servers = Object.entries(mcp).map(([name, server]) => server.type === "stdio"
54
+ ? {
55
+ name,
56
+ command: server.command,
57
+ args: server.args ?? [],
58
+ env: Object.entries(server.env ?? {}).map(([name, value]) => ({ name, value }))
59
+ }
60
+ : {
61
+ name,
62
+ type: "http",
63
+ url: server.url,
64
+ headers: Object.entries(server.headers ?? {}).map(([name, value]) => ({ name, value }))
65
+ });
66
+ const client = acpClientFactory({
67
+ command,
68
+ args: [...args],
69
+ env: runEnv,
70
+ cwd: request.workdir,
71
+ ...definition.clientOptions?.(request, bridge),
72
+ permissionHandler: (params) => bridge.requestPermission(params),
73
+ onPermissionResponseWritten: (params) => bridge.responseWritten(params),
74
+ onPermissionResponseFailed: (params, error) => bridge.responseFailed(params, error),
75
+ ...(context?.streamLimits ? { streamLimits: context.streamLimits } : {})
76
+ });
77
+ let sessionId;
78
+ let terminal = false;
79
+ let abortClose;
80
+ const closeAfterAbort = () => {
81
+ // 审批桥和 signal 共用关闭过程,先给取消通知留出发送窗口,再回收进程。
82
+ abortClose ??= (async () => {
83
+ if (sessionId)
84
+ client.cancel(sessionId);
85
+ await new Promise((resolve) => setTimeout(resolve, 250));
86
+ await client.close();
87
+ })();
88
+ return abortClose;
89
+ };
90
+ bridge.bindTransport(() => (request.signal?.aborted ? closeAfterAbort() : client.close()));
91
+ const abort = () => {
92
+ void closeAfterAbort().catch(() => undefined);
93
+ };
94
+ if (request.signal?.aborted)
95
+ abort();
96
+ else
97
+ request.signal?.addEventListener("abort", abort, { once: true });
98
+ try {
99
+ const initialization = recordValue(await client.initialize({ protocolVersion: definition.protocolVersion ?? 1 }));
100
+ await definition.initialize?.(client, initialization, request, runEnv);
101
+ if (servers.some((server) => server.type === "http") &&
102
+ recordValue(recordValue(initialization.agentCapabilities).mcpCapabilities).http !== true)
103
+ throw new Error(`MCP_TRANSPORT_UNSUPPORTED: ${definition.type}: http`);
104
+ const imageSupported = recordValue(recordValue(initialization.agentCapabilities).promptCapabilities).image ===
105
+ true;
106
+ const inputs = [
107
+ providerInputParts(request),
108
+ ...(request.providerSession ? [providerInputParts(request, true)] : [])
109
+ ];
110
+ if (!imageSupported && inputs.some((parts) => parts.some((part) => part.type === "image"))) {
111
+ throw new Error("UNSUPPORTED_INPUT_MODALITY: ACP agent did not advertise promptCapabilities.image");
112
+ }
113
+ const requestedSessionId = request.providerSession?.sessionId;
114
+ let providerModel;
115
+ let resumeFallback;
116
+ let sessionMethod = requestedSessionId ? "session/load" : "session/new";
117
+ let sessionParams = requestedSessionId
118
+ ? acpLoadSessionParams(requestedSessionId, { cwd: request.workdir })
119
+ : acpNewSessionParams({ cwd: request.workdir });
120
+ sessionParams.mcpServers = servers;
121
+ sessionParams =
122
+ definition.sessionParams?.(sessionParams, request, !requestedSessionId) ?? sessionParams;
123
+ let sessionRequestId = client.reserveRequestId();
124
+ let sessionResult = {};
125
+ let result = await client
126
+ .request(sessionMethod, sessionParams, {
127
+ requestId: sessionRequestId,
128
+ ...(requestedSessionId ? { timeoutMs: 600_000 } : {})
129
+ })
130
+ .catch((error) => {
131
+ if (requestedSessionId && definition.isMissingSessionError?.(error))
132
+ return null;
133
+ throw error;
134
+ });
135
+ const initialSessionId = requestedSessionId ?? (isRecord(result) ? stringField(result, "sessionId") : undefined);
136
+ if (!initialSessionId)
137
+ throw new Error("ACP session/new returned no sessionId");
138
+ const missingLoadedSession = requestedSessionId &&
139
+ (result === null ||
140
+ (definition.emptyLoadResultMeansMissing === true &&
141
+ isRecord(result) &&
142
+ Object.keys(result).length === 0));
143
+ if (missingLoadedSession) {
144
+ resumeFallback = "session_load_not_found";
145
+ sessionMethod = "session/new";
146
+ sessionParams = acpNewSessionParams({ cwd: request.workdir });
147
+ sessionParams.mcpServers = servers;
148
+ sessionParams = definition.sessionParams?.(sessionParams, request, true) ?? sessionParams;
149
+ sessionRequestId = client.reserveRequestId();
150
+ result = await client.request(sessionMethod, sessionParams, {
151
+ requestId: sessionRequestId
152
+ });
153
+ const freshSessionId = stringField(result, "sessionId");
154
+ if (!freshSessionId)
155
+ throw new Error("ACP session/new returned no sessionId");
156
+ }
157
+ sessionResult = isRecord(result) ? result : {};
158
+ sessionId = resumeFallback
159
+ ? stringField(sessionResult, "sessionId")
160
+ : (requestedSessionId ?? stringField(sessionResult, "sessionId"));
161
+ if (!sessionId)
162
+ throw new Error("ACP session/new returned no sessionId");
163
+ const requestedMode = contextActmode(request.context);
164
+ if (requestedMode !== undefined) {
165
+ const selection = (definition.selectActmode ?? acpActmodeSelectionRequest)(sessionResult, sessionId, requestedMode);
166
+ if (!selection.unchanged)
167
+ await client.request(selection.method, selection.params);
168
+ yield actmodeEvidence({
169
+ requested: requestedMode,
170
+ effective: selection.effective,
171
+ nativeMode: selection.nativeMode,
172
+ status: selection.effective === requestedMode ? "applied" : "fallback",
173
+ ...(selection.effective !== requestedMode
174
+ ? { reason: "provider_unsupported" }
175
+ : {})
176
+ });
177
+ }
178
+ const requestedModel = nonEmptyString(request.agentConfig?.model);
179
+ if (requestedModel) {
180
+ const selection = acpModelSelectionRequest(sessionResult, sessionId, requestedModel);
181
+ if (selection) {
182
+ const selectionRequestId = client.reserveRequestId();
183
+ const selected = recordValue(await client.request(selection.method, selection.params, {
184
+ requestId: selectionRequestId
185
+ }));
186
+ if (Array.isArray(selected.configOptions))
187
+ sessionResult.configOptions = selected.configOptions;
188
+ }
189
+ providerModel = requestedModel;
190
+ }
191
+ else {
192
+ providerModel = sessionModel(sessionResult);
193
+ }
194
+ if (definition.configureSession)
195
+ yield* definition.configureSession(client, sessionResult, sessionId, request);
196
+ yield {
197
+ protocolVersion: 2,
198
+ type: "session.update",
199
+ payload: {
200
+ providerSession: {
201
+ sessionId,
202
+ resumable: true,
203
+ ...(resumeFallback
204
+ ? {
205
+ resumeOutcome: "fresh_fallback",
206
+ resumeFallback,
207
+ contextInputVariant: request.freshFallbackModelInputParts || request.freshFallbackModelInput
208
+ ? "recovery"
209
+ : "primary"
210
+ }
211
+ : {}),
212
+ ...(providerModel ? { model: providerModel } : {})
213
+ }
214
+ }
215
+ };
216
+ const input = providerInputParts(request, resumeFallback !== undefined);
217
+ const instructions = definition.controlInstructions === "session"
218
+ ? ""
219
+ : initialControlInstructions(request, !requestedSessionId || resumeFallback !== undefined);
220
+ // Preserve the legacy text call while mixed prompts retain every block's position.
221
+ const prompt = input.length === 1 && input[0]?.type === "text"
222
+ ? `${input[0].text}${instructions ? `\n\n${instructions}` : ""}`
223
+ : [
224
+ ...input,
225
+ ...(instructions
226
+ ? [
227
+ {
228
+ type: "text",
229
+ text: instructions
230
+ }
231
+ ]
232
+ : [])
233
+ ];
234
+ const promptParams = acpPromptParams(sessionId, prompt);
235
+ const promptRequestId = client.reserveRequestId();
236
+ let stopReason;
237
+ let finishReason;
238
+ let promptResultPublicText;
239
+ let producedFinalOutput = false;
240
+ const activeTools = new Set();
241
+ const turn = new AcpTurnNormalizer(definition.provider);
242
+ for await (const update of client.prompt(sessionId, prompt, {
243
+ requestId: promptRequestId,
244
+ params: promptParams
245
+ })) {
246
+ if (update.type === "prompt_result") {
247
+ for (const event of definition.validatePromptResult?.(update) ?? [])
248
+ yield event;
249
+ stopReason = update.stopReason;
250
+ finishReason = update.finishReason;
251
+ promptResultPublicText = promptResultText(update);
252
+ continue;
253
+ }
254
+ const standardUpdate = update;
255
+ const events = turn.normalize(standardUpdate.sessionUpdate ?? standardUpdate.type, normalizeAcpUpdate(standardUpdate, definition.provider));
256
+ for (const event of events) {
257
+ const id = stringField(event.payload, "id");
258
+ if (event.type === "message.delta" &&
259
+ event.payload.channel !== "analysis" &&
260
+ typeof event.payload.text === "string" &&
261
+ event.payload.text.length > 0) {
262
+ producedFinalOutput = true;
263
+ }
264
+ if (event.type === "tool_call.create" && id)
265
+ activeTools.add(id);
266
+ if (event.type === "tool_call.update" && id && isTerminalToolStatus(event.payload.status))
267
+ activeTools.delete(id);
268
+ yield event;
269
+ }
270
+ }
271
+ const cancelled = request.signal?.aborted || isCancelledStopReason(stopReason);
272
+ if (!cancelled && !producedFinalOutput && promptResultPublicText) {
273
+ const fallbackEvents = turn.normalize("agent_message_chunk", normalizeAcpUpdate({
274
+ type: "prompt_result",
275
+ sessionUpdate: "agent_message_chunk",
276
+ content: { text: promptResultPublicText }
277
+ }, definition.provider));
278
+ for (const event of fallbackEvents)
279
+ yield event;
280
+ producedFinalOutput = true;
281
+ }
282
+ if (cancelled) {
283
+ for (const id of activeTools)
284
+ yield {
285
+ protocolVersion: 2,
286
+ type: "tool_call.update",
287
+ payload: { id, status: canonicalTerminalStatus("cancelled") }
288
+ };
289
+ }
290
+ if (!cancelled && !producedFinalOutput) {
291
+ for (const event of turn.finish("no-final-output", "failed"))
292
+ yield event;
293
+ yield {
294
+ protocolVersion: 2,
295
+ type: "message.update",
296
+ payload: { role: "assistant", status: "failed" }
297
+ };
298
+ terminal = true;
299
+ yield {
300
+ protocolVersion: 2,
301
+ type: "run.failed",
302
+ payload: {
303
+ code: "ACP_NO_FINAL_OUTPUT",
304
+ message: `${definition.provider} completed without assistant output`,
305
+ adapterType: definition.type
306
+ }
307
+ };
308
+ return;
309
+ }
310
+ for (const event of turn.finish(stopReason ?? finishReason, cancelled ? "stopped" : "completed"))
311
+ yield event;
312
+ yield {
313
+ protocolVersion: 2,
314
+ type: "message.update",
315
+ payload: { role: "assistant", status: cancelled ? "stopped" : "completed" }
316
+ };
317
+ terminal = true;
318
+ yield cancelled
319
+ ? {
320
+ protocolVersion: 2,
321
+ type: "run.cancelled",
322
+ payload: {
323
+ reason: stopReason ?? String(request.signal?.reason ?? "cancelled"),
324
+ ...(finishReason ? { finishReason } : {})
325
+ }
326
+ }
327
+ : { protocolVersion: 2, type: "run.completed", payload: {} };
328
+ }
329
+ catch (error) {
330
+ if (!terminal && request.signal?.aborted) {
331
+ yield {
332
+ protocolVersion: 2,
333
+ type: "run.cancelled",
334
+ payload: { reason: String(request.signal.reason ?? "cancelled") }
335
+ };
336
+ }
337
+ else {
338
+ throw error;
339
+ }
340
+ }
341
+ finally {
342
+ request.signal?.removeEventListener("abort", abort);
343
+ if (request.signal?.aborted)
344
+ await closeAfterAbort();
345
+ else
346
+ await client.close();
347
+ }
348
+ }
349
+ }
350
+ function contentText(value) {
351
+ if (isRecord(value) && typeof value.text === "string")
352
+ return value.text;
353
+ if (!Array.isArray(value))
354
+ return undefined;
355
+ const text = value
356
+ .filter(isRecord)
357
+ .map((item) => (typeof item.text === "string" ? item.text : ""))
358
+ .join("");
359
+ return text || undefined;
360
+ }
361
+ function promptResultText(update) {
362
+ for (const value of [
363
+ update.text,
364
+ update.content,
365
+ update.output,
366
+ update.response,
367
+ update.message
368
+ ]) {
369
+ if (typeof value === "string" && value)
370
+ return value;
371
+ const text = contentText(value);
372
+ if (text)
373
+ return text;
374
+ }
375
+ return undefined;
376
+ }
377
+ function isTerminalToolStatus(status) {
378
+ return (typeof status === "string" &&
379
+ ["completed", "failed", "error", "cancelled", "canceled", "stopped"].includes(status.toLowerCase()));
380
+ }
381
+ function isCancelledStopReason(reason) {
382
+ return (typeof reason === "string" &&
383
+ ["cancelled", "canceled", "interrupted", "aborted"].includes(reason.toLowerCase()));
384
+ }
385
+ function isRecord(value) {
386
+ return value !== null && typeof value === "object" && !Array.isArray(value);
387
+ }
388
+ function recordValue(value) {
389
+ return isRecord(value) ? value : {};
390
+ }
391
+ function arrayField(value, key) {
392
+ return Array.isArray(value[key]) ? value[key] : [];
393
+ }
394
+ function nonEmptyString(value) {
395
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
396
+ }
397
+ function stringField(value, key) {
398
+ return typeof value[key] === "string" ? value[key] : undefined;
399
+ }
@@ -0,0 +1,14 @@
1
+ import { AcpClient, type SpawnAcpClientOptions } from "@mininglamp-oss/octo-runtime-acp-client";
2
+ type JsonRecord = Record<string, unknown>;
3
+ export interface SpawnGrokBuildClientOptions extends SpawnAcpClientOptions {
4
+ requestHandler?: (method: string, params: JsonRecord) => unknown;
5
+ onRequestResponseWritten?: (params: JsonRecord) => void;
6
+ onRequestResponseFailed?: (params: JsonRecord, error: Error) => void;
7
+ }
8
+ export declare class GrokBuildRpcError extends Error {
9
+ readonly code: unknown;
10
+ readonly data: unknown;
11
+ constructor(error: JsonRecord);
12
+ }
13
+ export declare function spawnGrokBuildAcpClient(options: SpawnGrokBuildClientOptions): AcpClient;
14
+ export {};
@@ -0,0 +1,156 @@
1
+ import { AcpClient } from "@mininglamp-oss/octo-runtime-acp-client";
2
+ import { INVOKE_REQUEST_MAX_BYTES } from "@mininglamp-oss/octo-runtime-protocol";
3
+ import { spawn } from "node:child_process";
4
+ import { createInterface } from "node:readline";
5
+ export class GrokBuildRpcError extends Error {
6
+ code;
7
+ data;
8
+ constructor(error) {
9
+ super(typeof error.message === "string" ? error.message : "Grok Build ACP request failed");
10
+ this.code = error.code;
11
+ this.data = error.data;
12
+ }
13
+ }
14
+ /** 标准 RPC 和更新队列沿用通用客户端;此实例只补充 Grok Build 的反向请求和错误信息。 */
15
+ class GrokBuildAcpClient extends AcpClient {
16
+ child;
17
+ options;
18
+ #rpcErrors = new Map();
19
+ #activeRequests = new Set();
20
+ #reader;
21
+ #stderr = "";
22
+ #disconnected = false;
23
+ #closing = false;
24
+ constructor(child, options) {
25
+ super({ ...options, child, processGroup: process.platform !== "win32" });
26
+ this.child = child;
27
+ this.options = options;
28
+ child.stderr.on("data", this.#captureStderr);
29
+ child.stdout.once("end", this.#disconnect);
30
+ this.#reader = createInterface({ input: child.stdout });
31
+ this.#reader.on("error", () => undefined);
32
+ this.#reader.on("line", (line) => {
33
+ // 通用客户端在解析前执行容量守卫;旁路观察器也不解析超过协议上限的帧。
34
+ if (Buffer.byteLength(line) > INVOKE_REQUEST_MAX_BYTES)
35
+ return;
36
+ let message;
37
+ try {
38
+ message = JSON.parse(line);
39
+ }
40
+ catch {
41
+ return;
42
+ }
43
+ if (!isRecord(message))
44
+ return;
45
+ if (typeof message.id === "number" && isRecord(message.error)) {
46
+ if (this.#activeRequests.has(message.id))
47
+ this.#rpcErrors.set(message.id, message.error);
48
+ return;
49
+ }
50
+ if ((typeof message.id !== "number" && typeof message.id !== "string") ||
51
+ typeof message.method !== "string" ||
52
+ message.method === "session/request_permission")
53
+ return;
54
+ const params = isRecord(message.params) ? message.params : {};
55
+ void Promise.resolve()
56
+ .then(() => {
57
+ if (!options.requestHandler)
58
+ throw new Error("GROK_CLIENT_METHOD_UNSUPPORTED");
59
+ return options.requestHandler(message.method, params);
60
+ })
61
+ .then((result) => this.#reply({ id: message.id, result }, params), () => this.#reply({
62
+ id: message.id,
63
+ error: { code: -32603, message: "Grok Build client request failed" }
64
+ }));
65
+ });
66
+ }
67
+ #captureStderr = (value) => {
68
+ this.#stderr = (this.#stderr + value.toString()).slice(-8192);
69
+ };
70
+ #disconnect = () => {
71
+ if (this.#closing)
72
+ return;
73
+ this.#disconnected = true;
74
+ setImmediate(() => {
75
+ void this.close().catch(() => undefined);
76
+ });
77
+ };
78
+ #reply(message, params) {
79
+ if (this.#closing)
80
+ return;
81
+ const failed = (error) => {
82
+ if (params)
83
+ this.options.onRequestResponseFailed?.(params, error);
84
+ void this.close().catch(() => undefined);
85
+ };
86
+ try {
87
+ this.child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", ...message })}\n`, (error) => {
88
+ if (error)
89
+ failed(error);
90
+ else if (params)
91
+ this.options.onRequestResponseWritten?.(params);
92
+ });
93
+ }
94
+ catch (error) {
95
+ failed(error instanceof Error ? error : new Error("Grok Build response delivery failed"));
96
+ }
97
+ }
98
+ async request(method, params, options = {}) {
99
+ const requestId = options.requestId ?? this.reserveRequestId();
100
+ this.#activeRequests.add(requestId);
101
+ try {
102
+ return await super.request(method, params, { ...options, requestId });
103
+ }
104
+ catch (error) {
105
+ const rpcError = this.#rpcErrors.get(requestId);
106
+ if (rpcError)
107
+ throw new GrokBuildRpcError(rpcError);
108
+ if (this.#disconnected && error instanceof Error && error.message === "ACP client closed")
109
+ throw new Error(this.#stderr.trim() || "ACP stdout disconnected", { cause: error });
110
+ throw error;
111
+ }
112
+ finally {
113
+ this.#activeRequests.delete(requestId);
114
+ this.#rpcErrors.delete(requestId);
115
+ }
116
+ }
117
+ close() {
118
+ this.#closing = true;
119
+ this.child.stdout.removeListener("end", this.#disconnect);
120
+ this.child.stderr.removeListener("data", this.#captureStderr);
121
+ this.#reader.close();
122
+ return super.close();
123
+ }
124
+ async *prompt(...args) {
125
+ try {
126
+ yield* super.prompt(...args);
127
+ }
128
+ catch (error) {
129
+ if (this.#disconnected && error instanceof Error && error.message === "ACP client closed")
130
+ throw new Error(this.#stderr.trim() || "ACP stdout disconnected", { cause: error });
131
+ throw error;
132
+ }
133
+ }
134
+ }
135
+ export function spawnGrokBuildAcpClient(options) {
136
+ const child = spawn(options.command, options.args ?? [], {
137
+ cwd: options.cwd,
138
+ env: { ...process.env, ...options.env },
139
+ stdio: ["pipe", "pipe", "pipe"],
140
+ detached: process.platform !== "win32"
141
+ });
142
+ const client = new GrokBuildAcpClient(child, options);
143
+ if (options.signal?.aborted)
144
+ void client.close().catch(() => undefined);
145
+ else if (options.signal) {
146
+ const abort = () => {
147
+ void client.close().catch(() => undefined);
148
+ };
149
+ options.signal.addEventListener("abort", abort, { once: true });
150
+ child.once("exit", () => options.signal?.removeEventListener("abort", abort));
151
+ }
152
+ return client;
153
+ }
154
+ function isRecord(value) {
155
+ return value !== null && typeof value === "object" && !Array.isArray(value);
156
+ }
@@ -0,0 +1,29 @@
1
+ import { spawnGrokBuildAcpClient } from "./client.js";
2
+ import { type CanonicalEvent, type InvokeRequest } from "@mininglamp-oss/octo-runtime-adapter-sdk";
3
+ import type { InteractionResponse } from "@mininglamp-oss/octo-runtime-protocol";
4
+ export declare const GROK_BUILD_TESTED_VERSION = "1.0.67";
5
+ /** 宿主可指定已安装命令;每次调用拥有独立 ACP 子进程,不连接用户常驻 leader。 */
6
+ export declare function createGrokBuildAdapter({ command, acpClientFactory }?: {
7
+ command?: string;
8
+ acpClientFactory?: typeof spawnGrokBuildAcpClient;
9
+ }): Readonly<{
10
+ invoke(request: InvokeRequest, context?: Parameters<(request: InvokeRequest, context?: import("@mininglamp-oss/octo-runtime-adapter-sdk").AdapterInvocationContext) => AsyncGenerator<CanonicalEvent>>[1]): AsyncGenerator<CanonicalEvent, void, any>;
11
+ metadata: {
12
+ mcp: true;
13
+ type: string;
14
+ agentSources: "provisioned"[];
15
+ };
16
+ probe: () => Promise<import("@mininglamp-oss/octo-runtime-adapter-sdk").ProbeResult>;
17
+ respondInteraction: (invocationId: string, response: InteractionResponse) => Promise<void>;
18
+ }>;
19
+ export declare const grokBuildAdapter: Readonly<{
20
+ invoke(request: InvokeRequest, context?: Parameters<(request: InvokeRequest, context?: import("@mininglamp-oss/octo-runtime-adapter-sdk").AdapterInvocationContext) => AsyncGenerator<CanonicalEvent>>[1]): AsyncGenerator<CanonicalEvent, void, any>;
21
+ metadata: {
22
+ mcp: true;
23
+ type: string;
24
+ agentSources: "provisioned"[];
25
+ };
26
+ probe: () => Promise<import("@mininglamp-oss/octo-runtime-adapter-sdk").ProbeResult>;
27
+ respondInteraction: (invocationId: string, response: InteractionResponse) => Promise<void>;
28
+ }>;
29
+ export default grokBuildAdapter;