@ai-sdk/harness-opencode 1.0.78 → 1.0.80
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 +16 -0
- package/dist/bridge/index.mjs +196 -23
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +192 -41
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/bridge/index.ts +62 -15
- package/src/opencode-harness.ts +242 -45
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';
|
|
2
2
|
import * as _ai_sdk_harness from '@ai-sdk/harness';
|
|
3
|
-
import { HarnessV1, HarnessV1BuiltinTool } from '@ai-sdk/harness';
|
|
3
|
+
import { HarnessV1PortEndpoint, HarnessV1, HarnessV1BuiltinTool } from '@ai-sdk/harness';
|
|
4
4
|
|
|
5
5
|
type OpenCodeResolvedAuthenticationMode = 'anthropic' | 'openai' | 'ai-gateway';
|
|
6
6
|
type OpenCodeAuthenticationMode = OpenCodeResolvedAuthenticationMode | 'auto';
|
|
@@ -48,6 +48,11 @@ type OpenCodeHarnessSettings = {
|
|
|
48
48
|
*/
|
|
49
49
|
readonly reasoningVariant?: string;
|
|
50
50
|
readonly port?: number;
|
|
51
|
+
/**
|
|
52
|
+
* Override the host endpoint used to connect to the sandbox bridge. Required
|
|
53
|
+
* together with `port` when using a basic sandbox session.
|
|
54
|
+
*/
|
|
55
|
+
readonly portEndpoint?: HarnessV1PortEndpoint;
|
|
51
56
|
readonly startupTimeoutMs?: number;
|
|
52
57
|
/**
|
|
53
58
|
* Creates the authentication token used by the sandbox bridge. Defaults to
|
package/dist/index.js
CHANGED
|
@@ -8,12 +8,15 @@ import {
|
|
|
8
8
|
} from "@ai-sdk/harness";
|
|
9
9
|
import {
|
|
10
10
|
classifyDiskLog,
|
|
11
|
+
experimental_createBridgeUserMessageSubmitter,
|
|
11
12
|
createBridgeErrorHandler,
|
|
12
13
|
createBridgeStartupError,
|
|
13
14
|
drainBridgeProcessStream,
|
|
14
15
|
forwardBridgeProcessStream,
|
|
16
|
+
getRestrictedSandboxSession,
|
|
15
17
|
markBridgeStarting,
|
|
16
18
|
maskSandboxCredentials,
|
|
19
|
+
resolveSandboxDefaultWorkingDirectory,
|
|
17
20
|
resolveSandboxHomeDir,
|
|
18
21
|
SandboxChannel,
|
|
19
22
|
shellQuote,
|
|
@@ -22,6 +25,7 @@ import {
|
|
|
22
25
|
writeSkills as writeHarnessSkills
|
|
23
26
|
} from "@ai-sdk/harness/utils";
|
|
24
27
|
import {
|
|
28
|
+
safeParseJSON,
|
|
25
29
|
tool
|
|
26
30
|
} from "@ai-sdk/provider-utils";
|
|
27
31
|
import { WebSocket } from "ws";
|
|
@@ -317,7 +321,7 @@ var inboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
317
321
|
]);
|
|
318
322
|
|
|
319
323
|
// src/version.ts
|
|
320
|
-
var VERSION = true ? "1.0.
|
|
324
|
+
var VERSION = true ? "1.0.80" : "0.0.0-test";
|
|
321
325
|
|
|
322
326
|
// src/opencode-harness.ts
|
|
323
327
|
var OPENCODE_CLIENT_APP = `ai-sdk/harness-opencode/${VERSION}`;
|
|
@@ -445,6 +449,23 @@ function createOpenCode(settings = {}) {
|
|
|
445
449
|
getBootstrap: getOpenCodeBootstrap,
|
|
446
450
|
doStart: async (startOpts) => {
|
|
447
451
|
const sandboxSession = startOpts.sandboxSession;
|
|
452
|
+
const toolSafeSandboxSession = getRestrictedSandboxSession(sandboxSession);
|
|
453
|
+
const sandboxId = "id" in sandboxSession ? sandboxSession.id : void 0;
|
|
454
|
+
validateBasicSandboxSettings({
|
|
455
|
+
sandboxSession,
|
|
456
|
+
port: settings.port,
|
|
457
|
+
portEndpoint: settings.portEndpoint
|
|
458
|
+
});
|
|
459
|
+
if (settings.mintBridgeToken != null && sandboxId == null) {
|
|
460
|
+
throw new HarnessCapabilityUnsupportedError({
|
|
461
|
+
harnessId: "opencode",
|
|
462
|
+
message: "The OpenCode harness cannot use `mintBridgeToken` with a sandbox session that does not expose an id."
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
const defaultWorkingDirectory = await resolveSandboxDefaultWorkingDirectory({
|
|
466
|
+
sandboxSession,
|
|
467
|
+
abortSignal: startOpts.abortSignal
|
|
468
|
+
});
|
|
448
469
|
const authenticationMode = resolveOpenCodeAuthenticationMode({
|
|
449
470
|
auth: settings.auth,
|
|
450
471
|
model: settings.model,
|
|
@@ -456,7 +477,7 @@ function createOpenCode(settings = {}) {
|
|
|
456
477
|
provider: settings.provider
|
|
457
478
|
});
|
|
458
479
|
let sandboxAuthEnvironment = resolvedAuthEnvironment;
|
|
459
|
-
if (sandboxSession.addRequestTransformations != null) {
|
|
480
|
+
if ("addRequestTransformations" in sandboxSession && sandboxSession.addRequestTransformations != null) {
|
|
460
481
|
const requestTransformations = createOpenCodeRequestTransformations(
|
|
461
482
|
resolvedAuthEnvironment,
|
|
462
483
|
authenticationMode
|
|
@@ -473,10 +494,8 @@ function createOpenCode(settings = {}) {
|
|
|
473
494
|
} else {
|
|
474
495
|
warnCredentialBrokeringUnavailable();
|
|
475
496
|
}
|
|
476
|
-
const session = sandboxSession.restricted();
|
|
477
|
-
const sandboxId = sandboxSession.id;
|
|
478
497
|
const bootstrapDir = path.posix.resolve(
|
|
479
|
-
|
|
498
|
+
defaultWorkingDirectory,
|
|
480
499
|
OPENCODE_BOOTSTRAP_DIR
|
|
481
500
|
);
|
|
482
501
|
const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;
|
|
@@ -486,7 +505,7 @@ function createOpenCode(settings = {}) {
|
|
|
486
505
|
const resumeSessionId = typeof resumeData?.openCodeSessionId === "string" && resumeData.openCodeSessionId.length > 0 ? resumeData.openCodeSessionId : void 0;
|
|
487
506
|
const coords = resumeData?.bridge;
|
|
488
507
|
const workDir = startOpts.sessionWorkDir;
|
|
489
|
-
const sessionDataDir = `${
|
|
508
|
+
const sessionDataDir = `${defaultWorkingDirectory}/.agent-runs/${startOpts.sessionId}`;
|
|
490
509
|
const bridgeStateDir = `${sessionDataDir}/bridge`;
|
|
491
510
|
const timeoutMs = settings.startupTimeoutMs ?? 12e4;
|
|
492
511
|
const model = splitOpenCodeModel(settings.model, settings.provider).model;
|
|
@@ -503,16 +522,24 @@ function createOpenCode(settings = {}) {
|
|
|
503
522
|
});
|
|
504
523
|
if (coords) {
|
|
505
524
|
try {
|
|
506
|
-
const endpoint2 = await
|
|
507
|
-
|
|
508
|
-
|
|
525
|
+
const endpoint2 = await resolveBridgeEndpoint({
|
|
526
|
+
sandboxSession,
|
|
527
|
+
override: settings.portEndpoint,
|
|
528
|
+
port: coords.port
|
|
509
529
|
});
|
|
510
530
|
const attachEndpoint = withBridgeToken({
|
|
511
531
|
endpoint: endpoint2,
|
|
512
532
|
token: coords.token
|
|
513
533
|
});
|
|
534
|
+
let supportsUserMessageResponses2 = false;
|
|
514
535
|
const attachChannel = new SandboxChannel({
|
|
515
|
-
connect: () => openWebSocket(
|
|
536
|
+
connect: () => openWebSocket({
|
|
537
|
+
endpoint: attachEndpoint,
|
|
538
|
+
helloTimeoutMs: Math.min(timeoutMs, 5e3),
|
|
539
|
+
onHello: (supported) => {
|
|
540
|
+
supportsUserMessageResponses2 = supported;
|
|
541
|
+
}
|
|
542
|
+
}),
|
|
516
543
|
outboundSchema: outboundMessageSchema,
|
|
517
544
|
initialLastSeenEventId: coords.lastSeenEventId,
|
|
518
545
|
onDiagnostic,
|
|
@@ -536,7 +563,8 @@ function createOpenCode(settings = {}) {
|
|
|
536
563
|
sandboxId,
|
|
537
564
|
debug: startOpts.observability?.debug,
|
|
538
565
|
permissionMode: startOpts.permissionMode,
|
|
539
|
-
builtinToolFiltering: startOpts.builtinToolFiltering
|
|
566
|
+
builtinToolFiltering: startOpts.builtinToolFiltering,
|
|
567
|
+
supportsUserMessageResponses: () => supportsUserMessageResponses2
|
|
540
568
|
});
|
|
541
569
|
} catch {
|
|
542
570
|
}
|
|
@@ -544,7 +572,7 @@ function createOpenCode(settings = {}) {
|
|
|
544
572
|
let respawnStrategy = isResume ? "rerun" : void 0;
|
|
545
573
|
if (coords && isContinue) {
|
|
546
574
|
const logRaw = await Promise.resolve(
|
|
547
|
-
|
|
575
|
+
toolSafeSandboxSession.readTextFile({
|
|
548
576
|
path: `${bridgeStateDir}/event-log.ndjson`,
|
|
549
577
|
abortSignal: startOpts.abortSignal
|
|
550
578
|
})
|
|
@@ -553,10 +581,13 @@ function createOpenCode(settings = {}) {
|
|
|
553
581
|
respawnStrategy = "replay";
|
|
554
582
|
}
|
|
555
583
|
}
|
|
556
|
-
const port = resolveBridgePort(
|
|
584
|
+
const port = resolveBridgePort({
|
|
585
|
+
sandboxSession,
|
|
586
|
+
override: settings.port
|
|
587
|
+
});
|
|
557
588
|
const token = settings.mintBridgeToken == null ? randomBytes(32).toString("hex") : settings.mintBridgeToken(sandboxId);
|
|
558
589
|
const sandboxHomeDir = await resolveSandboxHomeDir({
|
|
559
|
-
sandbox:
|
|
590
|
+
sandbox: toolSafeSandboxSession,
|
|
560
591
|
abortSignal: startOpts.abortSignal
|
|
561
592
|
});
|
|
562
593
|
const xdgConfigHome = `${sandboxHomeDir}/.config`;
|
|
@@ -564,7 +595,7 @@ function createOpenCode(settings = {}) {
|
|
|
564
595
|
const xdgDataHome = `${sandboxHomeDir}/.local/share`;
|
|
565
596
|
const xdgStateHome = `${sandboxHomeDir}/.local/state`;
|
|
566
597
|
const skillSetup = startOpts.skills && startOpts.skills.length > 0 ? await writeOpenCodeSkills({
|
|
567
|
-
sandbox:
|
|
598
|
+
sandbox: toolSafeSandboxSession,
|
|
568
599
|
skills: startOpts.skills,
|
|
569
600
|
homeDir: sandboxHomeDir,
|
|
570
601
|
abortSignal: startOpts.abortSignal
|
|
@@ -583,18 +614,18 @@ function createOpenCode(settings = {}) {
|
|
|
583
614
|
...respawnStrategy === "replay" ? { BRIDGE_REPLAY_FROM_DISK: "1" } : {}
|
|
584
615
|
};
|
|
585
616
|
if (respawnStrategy === void 0) {
|
|
586
|
-
await
|
|
617
|
+
await toolSafeSandboxSession.run({
|
|
587
618
|
command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)} ${shellQuote(xdgConfigHome)} ${shellQuote(xdgCacheHome)} ${shellQuote(xdgDataHome)} ${shellQuote(xdgStateHome)}`,
|
|
588
619
|
abortSignal: startOpts.abortSignal
|
|
589
620
|
});
|
|
590
621
|
}
|
|
591
622
|
await markBridgeStarting({
|
|
592
|
-
sandbox:
|
|
623
|
+
sandbox: toolSafeSandboxSession,
|
|
593
624
|
bridgeStateDir,
|
|
594
625
|
bridgeType: "opencode",
|
|
595
626
|
abortSignal: startOpts.abortSignal
|
|
596
627
|
});
|
|
597
|
-
const proc = await
|
|
628
|
+
const proc = await toolSafeSandboxSession.spawn({
|
|
598
629
|
command: `node ${shellQuote(`${bootstrapDir}/bridge.mjs`)} --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)} --bootstrap-dir ${shellQuote(bootstrapDir)}${skillSetup ? ` --skills-dir ${shellQuote(skillSetup.skillsDir)}` : ""}`,
|
|
599
630
|
env,
|
|
600
631
|
abortSignal: startOpts.abortSignal
|
|
@@ -608,7 +639,7 @@ function createOpenCode(settings = {}) {
|
|
|
608
639
|
});
|
|
609
640
|
const { port: boundPort } = await waitForBridgeReady({
|
|
610
641
|
proc,
|
|
611
|
-
sandbox:
|
|
642
|
+
sandbox: toolSafeSandboxSession,
|
|
612
643
|
bridgeStateDir,
|
|
613
644
|
bridgeType: "opencode",
|
|
614
645
|
timeoutMs,
|
|
@@ -629,13 +660,21 @@ function createOpenCode(settings = {}) {
|
|
|
629
660
|
})
|
|
630
661
|
});
|
|
631
662
|
void drainBridgeProcessStream(proc.stdout);
|
|
632
|
-
const endpoint = await
|
|
633
|
-
|
|
634
|
-
|
|
663
|
+
const endpoint = await resolveBridgeEndpoint({
|
|
664
|
+
sandboxSession,
|
|
665
|
+
override: settings.portEndpoint,
|
|
666
|
+
port: boundPort
|
|
635
667
|
});
|
|
636
668
|
const bridgeEndpoint = withBridgeToken({ endpoint, token });
|
|
669
|
+
let supportsUserMessageResponses = false;
|
|
637
670
|
const channel = new SandboxChannel({
|
|
638
|
-
connect: () => openWebSocket(
|
|
671
|
+
connect: () => openWebSocket({
|
|
672
|
+
endpoint: bridgeEndpoint,
|
|
673
|
+
helloTimeoutMs: Math.min(timeoutMs, 5e3),
|
|
674
|
+
onHello: (supported) => {
|
|
675
|
+
supportsUserMessageResponses = supported;
|
|
676
|
+
}
|
|
677
|
+
}),
|
|
639
678
|
outboundSchema: outboundMessageSchema,
|
|
640
679
|
onDiagnostic,
|
|
641
680
|
onBridgeError,
|
|
@@ -661,19 +700,58 @@ function createOpenCode(settings = {}) {
|
|
|
661
700
|
sandboxId,
|
|
662
701
|
debug: startOpts.observability?.debug,
|
|
663
702
|
permissionMode: startOpts.permissionMode,
|
|
664
|
-
builtinToolFiltering: startOpts.builtinToolFiltering
|
|
703
|
+
builtinToolFiltering: startOpts.builtinToolFiltering,
|
|
704
|
+
supportsUserMessageResponses: () => supportsUserMessageResponses
|
|
665
705
|
});
|
|
666
706
|
}
|
|
667
707
|
};
|
|
668
708
|
}
|
|
669
|
-
function resolveBridgePort(
|
|
709
|
+
function resolveBridgePort({
|
|
710
|
+
sandboxSession,
|
|
711
|
+
override
|
|
712
|
+
}) {
|
|
670
713
|
if (override !== void 0) return override;
|
|
671
|
-
if (sandboxSession.ports.length > 0)
|
|
714
|
+
if ("ports" in sandboxSession && sandboxSession.ports.length > 0) {
|
|
715
|
+
return sandboxSession.ports[0];
|
|
716
|
+
}
|
|
672
717
|
throw new HarnessCapabilityUnsupportedError({
|
|
673
718
|
harnessId: "opencode",
|
|
674
719
|
message: "The OpenCode harness needs a TCP port exposed by the sandbox. Create the sandbox with `ports: [<port>]` or pass `createOpenCode({ port })`."
|
|
675
720
|
});
|
|
676
721
|
}
|
|
722
|
+
function validateBasicSandboxSettings({
|
|
723
|
+
sandboxSession,
|
|
724
|
+
port,
|
|
725
|
+
portEndpoint
|
|
726
|
+
}) {
|
|
727
|
+
if ("getPortEndpoint" in sandboxSession) return;
|
|
728
|
+
if (port == null) {
|
|
729
|
+
throw new HarnessCapabilityUnsupportedError({
|
|
730
|
+
harnessId: "opencode",
|
|
731
|
+
message: "The OpenCode harness requires an explicit `port` when using a basic sandbox session."
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
if (portEndpoint == null) {
|
|
735
|
+
throw new HarnessCapabilityUnsupportedError({
|
|
736
|
+
harnessId: "opencode",
|
|
737
|
+
message: "The OpenCode harness requires an explicit `portEndpoint` when using a basic sandbox session."
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
async function resolveBridgeEndpoint({
|
|
742
|
+
sandboxSession,
|
|
743
|
+
override,
|
|
744
|
+
port
|
|
745
|
+
}) {
|
|
746
|
+
if (override != null) return override;
|
|
747
|
+
if ("getPortEndpoint" in sandboxSession) {
|
|
748
|
+
return sandboxSession.getPortEndpoint({ port, protocol: "ws" });
|
|
749
|
+
}
|
|
750
|
+
throw new HarnessCapabilityUnsupportedError({
|
|
751
|
+
harnessId: "opencode",
|
|
752
|
+
message: "The OpenCode harness requires an explicit `portEndpoint` when using a basic sandbox session."
|
|
753
|
+
});
|
|
754
|
+
}
|
|
677
755
|
async function writeOpenCodeSkills({
|
|
678
756
|
sandbox,
|
|
679
757
|
skills,
|
|
@@ -692,25 +770,88 @@ async function writeOpenCodeSkills({
|
|
|
692
770
|
return { skillsDir };
|
|
693
771
|
}
|
|
694
772
|
function openWebSocket({
|
|
695
|
-
|
|
696
|
-
|
|
773
|
+
endpoint,
|
|
774
|
+
helloTimeoutMs,
|
|
775
|
+
onHello
|
|
697
776
|
}) {
|
|
698
777
|
return new Promise((resolve, reject) => {
|
|
699
|
-
const ws = new WebSocket(url, {
|
|
700
|
-
headers: headers == null ? void 0 : { ...headers }
|
|
778
|
+
const ws = new WebSocket(endpoint.url, {
|
|
779
|
+
headers: endpoint.headers == null ? void 0 : { ...endpoint.headers }
|
|
701
780
|
});
|
|
702
|
-
|
|
781
|
+
let opened = false;
|
|
782
|
+
let receivedHello = false;
|
|
783
|
+
let settled = false;
|
|
784
|
+
const cleanup = () => {
|
|
785
|
+
clearTimeout(helloTimer);
|
|
786
|
+
ws.off("open", onOpen);
|
|
787
|
+
ws.off("message", onMessage);
|
|
788
|
+
ws.off("close", onClose);
|
|
703
789
|
ws.off("error", onError);
|
|
704
|
-
resolve(ws);
|
|
705
790
|
};
|
|
791
|
+
const settle = (error) => {
|
|
792
|
+
if (settled) return;
|
|
793
|
+
settled = true;
|
|
794
|
+
cleanup();
|
|
795
|
+
if (error == null) {
|
|
796
|
+
resolve(ws);
|
|
797
|
+
} else {
|
|
798
|
+
reject(error);
|
|
799
|
+
}
|
|
800
|
+
};
|
|
801
|
+
const tryResolve = () => {
|
|
802
|
+
if (opened && receivedHello) settle();
|
|
803
|
+
};
|
|
804
|
+
const onOpen = () => {
|
|
805
|
+
opened = true;
|
|
806
|
+
tryResolve();
|
|
807
|
+
};
|
|
808
|
+
const onMessage = (raw) => {
|
|
809
|
+
void (async () => {
|
|
810
|
+
const parsed = await safeParseJSON({
|
|
811
|
+
text: webSocketMessageToString(raw)
|
|
812
|
+
});
|
|
813
|
+
if (!parsed.success) return;
|
|
814
|
+
const value = parsed.value;
|
|
815
|
+
if (typeof value !== "object" || value == null || Array.isArray(value) || value.type !== "bridge-hello") {
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
const capabilities = value.capabilities;
|
|
819
|
+
onHello(capabilities?.experimental_userMessageResponses === true);
|
|
820
|
+
receivedHello = true;
|
|
821
|
+
tryResolve();
|
|
822
|
+
})();
|
|
823
|
+
};
|
|
824
|
+
const onClose = () => settle(new Error("OpenCode bridge closed before sending bridge-hello."));
|
|
706
825
|
const onError = (err) => {
|
|
707
|
-
|
|
708
|
-
reject(err);
|
|
826
|
+
settle(err);
|
|
709
827
|
};
|
|
710
|
-
ws.
|
|
711
|
-
ws.
|
|
828
|
+
ws.on("open", onOpen);
|
|
829
|
+
ws.on("message", onMessage);
|
|
830
|
+
ws.on("close", onClose);
|
|
831
|
+
ws.on("error", onError);
|
|
832
|
+
const helloTimer = setTimeout(
|
|
833
|
+
() => settle(
|
|
834
|
+
new Error(
|
|
835
|
+
`OpenCode bridge did not send bridge-hello within ${helloTimeoutMs}ms.`
|
|
836
|
+
)
|
|
837
|
+
),
|
|
838
|
+
helloTimeoutMs
|
|
839
|
+
);
|
|
840
|
+
helloTimer.unref?.();
|
|
712
841
|
});
|
|
713
842
|
}
|
|
843
|
+
function webSocketMessageToString(raw) {
|
|
844
|
+
if (typeof raw === "string") return raw;
|
|
845
|
+
if (Buffer.isBuffer(raw)) return raw.toString("utf8");
|
|
846
|
+
if (Array.isArray(raw)) return Buffer.concat(raw).toString("utf8");
|
|
847
|
+
if (raw instanceof ArrayBuffer) return Buffer.from(raw).toString("utf8");
|
|
848
|
+
if (ArrayBuffer.isView(raw)) {
|
|
849
|
+
return Buffer.from(raw.buffer, raw.byteOffset, raw.byteLength).toString(
|
|
850
|
+
"utf8"
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
return String(raw);
|
|
854
|
+
}
|
|
714
855
|
function withBridgeToken({
|
|
715
856
|
endpoint,
|
|
716
857
|
token
|
|
@@ -736,7 +877,8 @@ function createSession({
|
|
|
736
877
|
sandboxId,
|
|
737
878
|
debug,
|
|
738
879
|
permissionMode,
|
|
739
|
-
builtinToolFiltering
|
|
880
|
+
builtinToolFiltering,
|
|
881
|
+
supportsUserMessageResponses
|
|
740
882
|
}) {
|
|
741
883
|
let stopped = false;
|
|
742
884
|
let stopPromise;
|
|
@@ -755,6 +897,11 @@ function createSession({
|
|
|
755
897
|
pendingResolve = resolve;
|
|
756
898
|
pendingReject = reject;
|
|
757
899
|
});
|
|
900
|
+
const userMessageSubmitter = supportsUserMessageResponses() ? experimental_createBridgeUserMessageSubmitter({
|
|
901
|
+
send: (message) => channel.send(message),
|
|
902
|
+
onResponse: (listener) => channel.on("user-message-response", listener),
|
|
903
|
+
onReconnect: (listener) => channel.onReconnect(listener)
|
|
904
|
+
}) : void 0;
|
|
758
905
|
const unsubs = [];
|
|
759
906
|
const forward = (event) => {
|
|
760
907
|
try {
|
|
@@ -783,6 +930,7 @@ function createSession({
|
|
|
783
930
|
if (isSettled) return;
|
|
784
931
|
isSettled = true;
|
|
785
932
|
activeTurn = false;
|
|
933
|
+
userMessageSubmitter?.close();
|
|
786
934
|
for (const u of unsubs) u();
|
|
787
935
|
pendingResolve();
|
|
788
936
|
};
|
|
@@ -790,6 +938,7 @@ function createSession({
|
|
|
790
938
|
if (isSettled) return;
|
|
791
939
|
isSettled = true;
|
|
792
940
|
activeTurn = false;
|
|
941
|
+
userMessageSubmitter?.close(err);
|
|
793
942
|
for (const u of unsubs) u();
|
|
794
943
|
pendingReject(err);
|
|
795
944
|
};
|
|
@@ -862,8 +1011,10 @@ function createSession({
|
|
|
862
1011
|
reason: input.reason
|
|
863
1012
|
});
|
|
864
1013
|
},
|
|
865
|
-
|
|
866
|
-
|
|
1014
|
+
...userMessageSubmitter == null ? {} : {
|
|
1015
|
+
submitUserMessage: async (text) => {
|
|
1016
|
+
await userMessageSubmitter.submit(text);
|
|
1017
|
+
}
|
|
867
1018
|
},
|
|
868
1019
|
done
|
|
869
1020
|
};
|
|
@@ -980,7 +1131,7 @@ function createSession({
|
|
|
980
1131
|
port: bridgePort,
|
|
981
1132
|
token: bridgeToken,
|
|
982
1133
|
lastSeenEventId,
|
|
983
|
-
sandboxId
|
|
1134
|
+
...sandboxId == null ? {} : { sandboxId }
|
|
984
1135
|
}
|
|
985
1136
|
}
|
|
986
1137
|
};
|
|
@@ -1094,7 +1245,7 @@ function createSession({
|
|
|
1094
1245
|
port: bridgePort,
|
|
1095
1246
|
token: bridgeToken,
|
|
1096
1247
|
lastSeenEventId,
|
|
1097
|
-
sandboxId
|
|
1248
|
+
...sandboxId == null ? {} : { sandboxId }
|
|
1098
1249
|
}
|
|
1099
1250
|
}
|
|
1100
1251
|
};
|