@mininglamp-oss/octo-runtime 1.1.1 → 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.
- package/apps/cli/dist/build-info.json +2 -2
- package/apps/cli/dist/manifest.json +5 -0
- package/node_modules/@mininglamp-oss/octo-runtime-acp-client/package.json +3 -3
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-acp/package.json +4 -4
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-antigravity/package.json +3 -3
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-claude-code/package.json +3 -3
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-codebuddy/package.json +4 -4
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-codex/package.json +3 -3
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/adapter.d.ts +54 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/adapter.js +399 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/client.d.ts +14 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/client.js +156 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/index.d.ts +29 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/index.js +273 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/interactions.d.ts +27 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/dist/interactions.js +161 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-grok-build/package.json +17 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-hermes/package.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-kimi-code/package.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-mcode/package.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/dist/compatibility.d.ts +24 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/dist/compatibility.js +181 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/dist/gateway.d.ts +9 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/dist/gateway.js +24 -8
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/dist/index.js +229 -225
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-openclaw/package.json +3 -3
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-opencode/package.json +4 -4
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-qodercli/package.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-qoderclicn/package.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/approval.d.ts +4 -0
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/dist/approval.js +5 -6
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-sdk/package.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-adapter-zcode-gui/package.json +3 -3
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/build-info.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-cli/dist/manifest.json +5 -0
- package/node_modules/@mininglamp-oss/octo-runtime-cli/package.json +23 -22
- package/node_modules/@mininglamp-oss/octo-runtime-cross-service/package.json +1 -1
- package/node_modules/@mininglamp-oss/octo-runtime-executor-core/dist/model-input.d.ts +1 -1
- package/node_modules/@mininglamp-oss/octo-runtime-executor-core/dist/model-input.js +13 -9
- package/node_modules/@mininglamp-oss/octo-runtime-executor-core/package.json +3 -3
- package/node_modules/@mininglamp-oss/octo-runtime-executor-kernel/package.json +4 -4
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/application/im-channel.js +2 -1
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/contracts.d.ts +1 -0
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/execution/dispatcher.js +24 -0
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/transport/contexts.js +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/transport/mentions.d.ts +5 -2
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/transport/mentions.js +19 -5
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/dist/transport/normalize.js +1 -0
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-gateway/package.json +6 -6
- package/node_modules/@mininglamp-oss/octo-runtime-extra-channel-wecom/package.json +5 -5
- package/node_modules/@mininglamp-oss/octo-runtime-extra-webui/package.json +2 -2
- package/node_modules/@mininglamp-oss/octo-runtime-host-sdk/package.json +4 -4
- package/node_modules/@mininglamp-oss/octo-runtime-protocol/package.json +1 -1
- package/package.json +27 -25
|
@@ -16,6 +16,11 @@
|
|
|
16
16
|
"module": "@mininglamp-oss/octo-runtime-adapter-codebuddy",
|
|
17
17
|
"export": "codebuddyAdapter"
|
|
18
18
|
},
|
|
19
|
+
{
|
|
20
|
+
"type": "grok-build",
|
|
21
|
+
"module": "@mininglamp-oss/octo-runtime-adapter-grok-build",
|
|
22
|
+
"export": "grokBuildAdapter"
|
|
23
|
+
},
|
|
19
24
|
{
|
|
20
25
|
"type": "hermes",
|
|
21
26
|
"module": "@mininglamp-oss/octo-runtime-adapter-hermes",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mininglamp-oss/octo-runtime-acp-client",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./dist/index.js",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"dist"
|
|
10
10
|
],
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.
|
|
13
|
-
"@mininglamp-oss/octo-runtime-protocol": "1.1.
|
|
12
|
+
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.2",
|
|
13
|
+
"@mininglamp-oss/octo-runtime-protocol": "1.1.2"
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mininglamp-oss/octo-runtime-adapter-acp",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./dist/index.js",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"dist"
|
|
10
10
|
],
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@mininglamp-oss/octo-runtime-protocol": "1.1.
|
|
13
|
-
"@mininglamp-oss/octo-runtime-acp-client": "1.1.
|
|
14
|
-
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.
|
|
12
|
+
"@mininglamp-oss/octo-runtime-protocol": "1.1.2",
|
|
13
|
+
"@mininglamp-oss/octo-runtime-acp-client": "1.1.2",
|
|
14
|
+
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.2"
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mininglamp-oss/octo-runtime-adapter-antigravity",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./dist/index.js",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"README.md"
|
|
11
11
|
],
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.
|
|
14
|
-
"@mininglamp-oss/octo-runtime-protocol": "1.1.
|
|
13
|
+
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.2",
|
|
14
|
+
"@mininglamp-oss/octo-runtime-protocol": "1.1.2"
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mininglamp-oss/octo-runtime-adapter-claude-code",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./dist/index.js",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@mininglamp-oss/octo-runtime-protocol": "1.1.
|
|
9
|
-
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.
|
|
8
|
+
"@mininglamp-oss/octo-runtime-protocol": "1.1.2",
|
|
9
|
+
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.2"
|
|
10
10
|
},
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"files": [
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mininglamp-oss/octo-runtime-adapter-codebuddy",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./dist/index.js",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@mininglamp-oss/octo-runtime-protocol": "1.1.
|
|
9
|
-
"@mininglamp-oss/octo-runtime-acp-client": "1.1.
|
|
10
|
-
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.
|
|
8
|
+
"@mininglamp-oss/octo-runtime-protocol": "1.1.2",
|
|
9
|
+
"@mininglamp-oss/octo-runtime-acp-client": "1.1.2",
|
|
10
|
+
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.2"
|
|
11
11
|
},
|
|
12
12
|
"types": "./dist/index.d.ts",
|
|
13
13
|
"files": [
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mininglamp-oss/octo-runtime-adapter-codex",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./dist/index.js",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@mininglamp-oss/octo-runtime-protocol": "1.1.
|
|
9
|
-
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.
|
|
8
|
+
"@mininglamp-oss/octo-runtime-protocol": "1.1.2",
|
|
9
|
+
"@mininglamp-oss/octo-runtime-adapter-sdk": "1.1.2"
|
|
10
10
|
},
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"files": [
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { spawnGrokBuildAcpClient as spawnAcpClient, type SpawnGrokBuildClientOptions as SpawnAcpClientOptions } from "./client.js";
|
|
2
|
+
import { GrokBuildInteractionBridge as AcpApprovalBridge } from "./interactions.js";
|
|
3
|
+
import { acpActmodeSelectionRequest } from "@mininglamp-oss/octo-runtime-adapter-acp";
|
|
4
|
+
import { type AcpClient, type AcpUpdate } from "@mininglamp-oss/octo-runtime-acp-client";
|
|
5
|
+
import { type ProbeResult, type ReasoningLevelMap, type AdapterInvocationContext, type CanonicalEvent, type InvokeRequest } from "@mininglamp-oss/octo-runtime-adapter-sdk";
|
|
6
|
+
import { type InteractionResponse } from "@mininglamp-oss/octo-runtime-protocol";
|
|
7
|
+
type JsonRecord = Record<string, unknown>;
|
|
8
|
+
export interface AcpAdapterDefinition {
|
|
9
|
+
type: string;
|
|
10
|
+
provider: string;
|
|
11
|
+
command: string;
|
|
12
|
+
args?: readonly string[] | ((request: InvokeRequest) => readonly string[]);
|
|
13
|
+
env?: (request: InvokeRequest) => NodeJS.ProcessEnv;
|
|
14
|
+
protocolVersion?: string | number;
|
|
15
|
+
emptyLoadResultMeansMissing?: boolean;
|
|
16
|
+
probe?: () => Promise<ProbeResult>;
|
|
17
|
+
/** Grok Build 专用的握手、会话配置与交互策略,只在本包消费。 */
|
|
18
|
+
initialize?: (client: AcpClient, initialization: JsonRecord, request: InvokeRequest, env: NodeJS.ProcessEnv) => Promise<void>;
|
|
19
|
+
sessionParams?: (params: JsonRecord, request: InvokeRequest, fresh: boolean) => JsonRecord;
|
|
20
|
+
isMissingSessionError?: (error: unknown) => boolean;
|
|
21
|
+
configureSession?: (client: AcpClient, session: JsonRecord, sessionId: string, request: InvokeRequest) => AsyncIterable<CanonicalEvent>;
|
|
22
|
+
selectActmode?: typeof acpActmodeSelectionRequest;
|
|
23
|
+
controlInstructions?: "session";
|
|
24
|
+
reasoningLevels?: ReasoningLevelMap;
|
|
25
|
+
clientOptions?: (request: InvokeRequest, bridge: AcpApprovalBridge) => Pick<SpawnAcpClientOptions, "requestHandler" | "onRequestResponseWritten" | "onRequestResponseFailed">;
|
|
26
|
+
validatePromptResult?: (update: StandardAcpUpdate) => CanonicalEvent[];
|
|
27
|
+
}
|
|
28
|
+
export interface StandardAcpUpdate extends AcpUpdate {
|
|
29
|
+
sessionUpdate?: string;
|
|
30
|
+
content?: unknown;
|
|
31
|
+
text?: string;
|
|
32
|
+
toolCallId?: string;
|
|
33
|
+
name?: string;
|
|
34
|
+
title?: string;
|
|
35
|
+
rawInput?: unknown;
|
|
36
|
+
input?: unknown;
|
|
37
|
+
rawOutput?: unknown;
|
|
38
|
+
output?: unknown;
|
|
39
|
+
status?: string;
|
|
40
|
+
}
|
|
41
|
+
export declare function createGrokBuildAcpAdapter(definition: AcpAdapterDefinition, { acpClientFactory, command }?: {
|
|
42
|
+
acpClientFactory?: typeof spawnAcpClient;
|
|
43
|
+
command?: string;
|
|
44
|
+
}): Readonly<{
|
|
45
|
+
metadata: {
|
|
46
|
+
mcp: true;
|
|
47
|
+
type: string;
|
|
48
|
+
agentSources: "provisioned"[];
|
|
49
|
+
};
|
|
50
|
+
probe: () => Promise<ProbeResult>;
|
|
51
|
+
respondInteraction(invocationId: string, response: InteractionResponse): Promise<void>;
|
|
52
|
+
invoke(request: InvokeRequest, context?: AdapterInvocationContext): AsyncGenerator<CanonicalEvent>;
|
|
53
|
+
}>;
|
|
54
|
+
export {};
|
|
@@ -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 {};
|