@ai-sdk/harness-opencode 1.0.91 → 1.0.93
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/CHANGELOG.md +13 -0
- package/dist/bridge/index.mjs +63 -4
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/src/bridge/create-emit-stream-event.ts +21 -0
- package/src/bridge/index.ts +62 -3
- package/src/bridge/opencode-events.ts +10 -0
- package/src/bridge/opencode-types.ts +1 -0
package/dist/index.js
CHANGED
|
@@ -364,7 +364,7 @@ var inboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
364
364
|
]);
|
|
365
365
|
|
|
366
366
|
// src/version.ts
|
|
367
|
-
var VERSION = true ? "1.0.
|
|
367
|
+
var VERSION = true ? "1.0.93" : "0.0.0-test";
|
|
368
368
|
|
|
369
369
|
// src/opencode-harness.ts
|
|
370
370
|
var OPENCODE_CLIENT_APP = `ai-sdk/harness-opencode/${VERSION}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/harness-opencode",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.93",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@ai-sdk/harness": "1.0.
|
|
29
|
+
"@ai-sdk/harness": "1.0.91",
|
|
30
30
|
"@ai-sdk/provider-utils": "5.0.32",
|
|
31
31
|
"ws": "8.21.0"
|
|
32
32
|
},
|
|
@@ -19,6 +19,11 @@ import {
|
|
|
19
19
|
|
|
20
20
|
type Emit = (message: Record<string, unknown>) => void;
|
|
21
21
|
|
|
22
|
+
type SubagentSession = {
|
|
23
|
+
parentSessionId: string;
|
|
24
|
+
sessionId: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
22
27
|
export function createEmitStreamEvent({
|
|
23
28
|
state,
|
|
24
29
|
emit,
|
|
@@ -28,6 +33,7 @@ export function createEmitStreamEvent({
|
|
|
28
33
|
nativeNameField,
|
|
29
34
|
getHostToolName,
|
|
30
35
|
authorizeHostToolCall,
|
|
36
|
+
onSubagentSession,
|
|
31
37
|
isMcpToolName,
|
|
32
38
|
stripWorkDir,
|
|
33
39
|
formatError,
|
|
@@ -49,6 +55,7 @@ export function createEmitStreamEvent({
|
|
|
49
55
|
toolName: string;
|
|
50
56
|
input: unknown;
|
|
51
57
|
}) => void;
|
|
58
|
+
onSubagentSession?: (session: SubagentSession) => void;
|
|
52
59
|
isMcpToolName: (toolName: string) => boolean;
|
|
53
60
|
stripWorkDir: (file: string) => string;
|
|
54
61
|
formatError: (error: unknown) => string;
|
|
@@ -83,6 +90,7 @@ export function createEmitStreamEvent({
|
|
|
83
90
|
nativeNameField,
|
|
84
91
|
getHostToolName,
|
|
85
92
|
authorizeHostToolCall,
|
|
93
|
+
onSubagentSession,
|
|
86
94
|
isMcpToolName,
|
|
87
95
|
});
|
|
88
96
|
return;
|
|
@@ -359,6 +367,7 @@ function emitLegacyToolPart({
|
|
|
359
367
|
nativeNameField,
|
|
360
368
|
getHostToolName,
|
|
361
369
|
authorizeHostToolCall,
|
|
370
|
+
onSubagentSession,
|
|
362
371
|
isMcpToolName,
|
|
363
372
|
}: {
|
|
364
373
|
part: unknown;
|
|
@@ -377,6 +386,7 @@ function emitLegacyToolPart({
|
|
|
377
386
|
toolName: string;
|
|
378
387
|
input: unknown;
|
|
379
388
|
}) => void;
|
|
389
|
+
onSubagentSession?: (session: SubagentSession) => void;
|
|
380
390
|
isMcpToolName: (toolName: string) => boolean;
|
|
381
391
|
}): void {
|
|
382
392
|
const toolPart = legacyToolPartFromValue(part);
|
|
@@ -389,6 +399,17 @@ function emitLegacyToolPart({
|
|
|
389
399
|
const rawToolName = toolPart.tool;
|
|
390
400
|
if (rawToolName === 'StructuredOutput') return;
|
|
391
401
|
const toolName = toWireToolName(rawToolName);
|
|
402
|
+
if (toolName === 'agent') {
|
|
403
|
+
const metadata = {
|
|
404
|
+
...(toolPart.metadata ?? {}),
|
|
405
|
+
...(toolPart.state?.metadata ?? {}),
|
|
406
|
+
};
|
|
407
|
+
const parentSessionId = stringValue(metadata.parentSessionId);
|
|
408
|
+
const sessionId = stringValue(metadata.sessionId);
|
|
409
|
+
if (parentSessionId && sessionId) {
|
|
410
|
+
onSubagentSession?.({ parentSessionId, sessionId });
|
|
411
|
+
}
|
|
412
|
+
}
|
|
392
413
|
state.toolNames.set(callID, { rawToolName, toolName });
|
|
393
414
|
const hostToolName = getHostToolName(toolName, rawToolName);
|
|
394
415
|
if (hostToolName) {
|
package/src/bridge/index.ts
CHANGED
|
@@ -232,6 +232,7 @@ function buildOpenCodeConfig({
|
|
|
232
232
|
webfetch: 'ask',
|
|
233
233
|
doom_loop: 'ask',
|
|
234
234
|
task: 'ask',
|
|
235
|
+
question: 'deny',
|
|
235
236
|
},
|
|
236
237
|
};
|
|
237
238
|
if (start.model) config.model = start.model;
|
|
@@ -878,6 +879,22 @@ async function consumeEvents({
|
|
|
878
879
|
const stream = await subscribeLegacyEvents({ client, signal });
|
|
879
880
|
onSubscribed?.();
|
|
880
881
|
if (!stream) return;
|
|
882
|
+
const taskSessionIds = new Set([sessionId]);
|
|
883
|
+
const registerSubagentSession = (sourceSessionId: string) =>
|
|
884
|
+
function register({
|
|
885
|
+
parentSessionId,
|
|
886
|
+
sessionId: subagentSessionId,
|
|
887
|
+
}: {
|
|
888
|
+
parentSessionId: string;
|
|
889
|
+
sessionId: string;
|
|
890
|
+
}) {
|
|
891
|
+
if (
|
|
892
|
+
parentSessionId === sourceSessionId &&
|
|
893
|
+
taskSessionIds.has(sourceSessionId)
|
|
894
|
+
) {
|
|
895
|
+
taskSessionIds.add(subagentSessionId);
|
|
896
|
+
}
|
|
897
|
+
};
|
|
881
898
|
const emitStreamEvent = createEmitStreamEvent({
|
|
882
899
|
state,
|
|
883
900
|
emit,
|
|
@@ -887,20 +904,59 @@ async function consumeEvents({
|
|
|
887
904
|
nativeNameField,
|
|
888
905
|
getHostToolName,
|
|
889
906
|
authorizeHostToolCall: input => authorizeHostToolCall({ ...input, state }),
|
|
907
|
+
onSubagentSession: registerSubagentSession(sessionId),
|
|
890
908
|
isMcpToolName: toolName =>
|
|
891
909
|
[...runtime.mcpToolPrefixes].some(prefix => toolName.startsWith(prefix)),
|
|
892
910
|
stripWorkDir,
|
|
893
911
|
formatError,
|
|
894
912
|
});
|
|
913
|
+
const descendantEventProcessors = new Map<
|
|
914
|
+
string,
|
|
915
|
+
(event: OpenCodeEvent) => void
|
|
916
|
+
>();
|
|
917
|
+
const processDescendantEvent = (
|
|
918
|
+
descendantSessionId: string,
|
|
919
|
+
event: OpenCodeEvent,
|
|
920
|
+
) => {
|
|
921
|
+
let processEvent = descendantEventProcessors.get(descendantSessionId);
|
|
922
|
+
if (!processEvent) {
|
|
923
|
+
const descendantState = createTranslationState();
|
|
924
|
+
processEvent = createEmitStreamEvent({
|
|
925
|
+
state: descendantState,
|
|
926
|
+
emit: () => undefined,
|
|
927
|
+
emitWarning: () => undefined,
|
|
928
|
+
emitError: () => undefined,
|
|
929
|
+
toWireToolName,
|
|
930
|
+
nativeNameField,
|
|
931
|
+
getHostToolName,
|
|
932
|
+
authorizeHostToolCall: input =>
|
|
933
|
+
authorizeHostToolCall({ ...input, state: descendantState }),
|
|
934
|
+
onSubagentSession: registerSubagentSession(descendantSessionId),
|
|
935
|
+
isMcpToolName: () => false,
|
|
936
|
+
stripWorkDir,
|
|
937
|
+
formatError,
|
|
938
|
+
});
|
|
939
|
+
descendantEventProcessors.set(descendantSessionId, processEvent);
|
|
940
|
+
}
|
|
941
|
+
processEvent(event);
|
|
942
|
+
};
|
|
895
943
|
for await (const rawEvent of stream) {
|
|
896
944
|
if (signal.aborted || turn.abortSignal.aborted) break;
|
|
897
945
|
const event = unwrapOpenCodeEvent(rawEvent);
|
|
898
946
|
const eventSessionId = event ? getOpenCodeEventSessionId(event) : undefined;
|
|
899
|
-
if (!event
|
|
947
|
+
if (!event) continue;
|
|
948
|
+
const scopedSessionId =
|
|
949
|
+
!eventSessionId || eventSessionId === sessionId
|
|
950
|
+
? sessionId
|
|
951
|
+
: taskSessionIds.has(eventSessionId)
|
|
952
|
+
? eventSessionId
|
|
953
|
+
: undefined;
|
|
954
|
+
if (!scopedSessionId) continue;
|
|
955
|
+
const isDescendant = scopedSessionId !== sessionId;
|
|
900
956
|
if (event.type === 'permission.v2.asked') {
|
|
901
957
|
await handlePermissionV2({
|
|
902
958
|
client,
|
|
903
|
-
sessionId,
|
|
959
|
+
sessionId: scopedSessionId,
|
|
904
960
|
permissionMode,
|
|
905
961
|
builtinToolFiltering,
|
|
906
962
|
turn,
|
|
@@ -910,16 +966,19 @@ async function consumeEvents({
|
|
|
910
966
|
} else if (event.type === 'permission.asked') {
|
|
911
967
|
await handlePermission({
|
|
912
968
|
client,
|
|
913
|
-
sessionId,
|
|
969
|
+
sessionId: scopedSessionId,
|
|
914
970
|
permissionMode,
|
|
915
971
|
builtinToolFiltering,
|
|
916
972
|
turn,
|
|
917
973
|
emit,
|
|
918
974
|
event,
|
|
919
975
|
});
|
|
976
|
+
} else if (isDescendant) {
|
|
977
|
+
processDescendantEvent(scopedSessionId, event);
|
|
920
978
|
} else {
|
|
921
979
|
emitStreamEvent(event);
|
|
922
980
|
}
|
|
981
|
+
if (isDescendant) continue;
|
|
923
982
|
if (onEvent?.(event)) break;
|
|
924
983
|
}
|
|
925
984
|
}
|
|
@@ -101,6 +101,16 @@ export function getOpenCodeEventSessionId(
|
|
|
101
101
|
if (event.type?.startsWith('session.') && typeof props.id === 'string') {
|
|
102
102
|
return props.id;
|
|
103
103
|
}
|
|
104
|
+
const info = asOpenCodeObject(props.info);
|
|
105
|
+
if (typeof info?.sessionID === 'string') return info.sessionID;
|
|
106
|
+
if (
|
|
107
|
+
(event.type === 'session.created' ||
|
|
108
|
+
event.type === 'session.updated' ||
|
|
109
|
+
event.type === 'session.deleted') &&
|
|
110
|
+
typeof info?.id === 'string'
|
|
111
|
+
) {
|
|
112
|
+
return info.id;
|
|
113
|
+
}
|
|
104
114
|
const part = props.part;
|
|
105
115
|
const partObject = asOpenCodeObject(part);
|
|
106
116
|
if (typeof partObject?.sessionID === 'string') return partObject.sessionID;
|