agl 1.0.17 → 21.0.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/.smartconfig.json +55 -0
- package/changelog.md +1026 -0
- package/cli.js +14 -0
- package/dist_serve/bundle.js +44778 -0
- package/dist_serve/index.html +13 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.authmodels.d.ts +126 -0
- package/dist_ts/classes.authmodels.js +1422 -0
- package/dist_ts/classes.authstore.d.ts +160 -0
- package/dist_ts/classes.authstore.js +2483 -0
- package/dist_ts/classes.browserresourcehost.d.ts +85 -0
- package/dist_ts/classes.browserresourcehost.js +912 -0
- package/dist_ts/classes.cli.d.ts +21 -0
- package/dist_ts/classes.cli.js +1082 -0
- package/dist_ts/classes.config.d.ts +23 -0
- package/dist_ts/classes.config.js +267 -0
- package/dist_ts/classes.controller.d.ts +523 -0
- package/dist_ts/classes.controller.js +10611 -0
- package/dist_ts/classes.controllermanagement.d.ts +32 -0
- package/dist_ts/classes.controllermanagement.js +222 -0
- package/dist_ts/classes.draftmanager.d.ts +30 -0
- package/dist_ts/classes.draftmanager.js +179 -0
- package/dist_ts/classes.embeddeddb.d.ts +30 -0
- package/dist_ts/classes.embeddeddb.js +159 -0
- package/dist_ts/classes.flexframedtransport.d.ts +56 -0
- package/dist_ts/classes.flexframedtransport.js +275 -0
- package/dist_ts/classes.flexmodels.private.d.ts +231 -0
- package/dist_ts/classes.flexmodels.private.js +985 -0
- package/dist_ts/classes.flexmodels.public.d.ts +207 -0
- package/dist_ts/classes.flexmodels.public.js +885 -0
- package/dist_ts/classes.flexprojectionreader.d.ts +89 -0
- package/dist_ts/classes.flexprojectionreader.js +580 -0
- package/dist_ts/classes.flexservice.d.ts +196 -0
- package/dist_ts/classes.flexservice.js +3704 -0
- package/dist_ts/classes.flexstore.d.ts +174 -0
- package/dist_ts/classes.flexstore.js +3400 -0
- package/dist_ts/classes.flexsupervisor.d.ts +105 -0
- package/dist_ts/classes.flexsupervisor.js +1191 -0
- package/dist_ts/classes.gitreversion.d.ts +431 -0
- package/dist_ts/classes.gitreversion.js +10592 -0
- package/dist_ts/classes.harnessoperationmanager.d.ts +113 -0
- package/dist_ts/classes.harnessoperationmanager.js +602 -0
- package/dist_ts/classes.opencodeclient.d.ts +146 -0
- package/dist_ts/classes.opencodeclient.js +3003 -0
- package/dist_ts/classes.opencodesupervisor.d.ts +60 -0
- package/dist_ts/classes.opencodesupervisor.js +1003 -0
- package/dist_ts/classes.passkeymanager.d.ts +34 -0
- package/dist_ts/classes.passkeymanager.js +456 -0
- package/dist_ts/classes.processinspection.d.ts +50 -0
- package/dist_ts/classes.processinspection.js +484 -0
- package/dist_ts/classes.resourcecoordinator.d.ts +64 -0
- package/dist_ts/classes.resourcecoordinator.js +294 -0
- package/dist_ts/classes.sessionintelligencereader.d.ts +13 -0
- package/dist_ts/classes.sessionintelligencereader.js +40 -0
- package/dist_ts/classes.systemmetricssampler.d.ts +53 -0
- package/dist_ts/classes.systemmetricssampler.js +168 -0
- package/dist_ts/classes.terminalmanager.d.ts +95 -0
- package/dist_ts/classes.terminalmanager.js +981 -0
- package/dist_ts/classes.terminalresourcehost.d.ts +20 -0
- package/dist_ts/classes.terminalresourcehost.js +84 -0
- package/dist_ts/classes.upgradecoordinator.d.ts +244 -0
- package/dist_ts/classes.upgradecoordinator.js +2155 -0
- package/dist_ts/classes.upgradetransaction.d.ts +92 -0
- package/dist_ts/classes.upgradetransaction.js +2125 -0
- package/dist_ts/classes.uploadmanager.d.ts +24 -0
- package/dist_ts/classes.uploadmanager.js +210 -0
- package/dist_ts/classes.validation.d.ts +91 -0
- package/dist_ts/classes.validation.js +1087 -0
- package/dist_ts/flexharness.child.d.ts +1 -0
- package/dist_ts/flexharness.child.js +28 -0
- package/dist_ts/functions.canonicaldirectory.d.ts +21 -0
- package/dist_ts/functions.canonicaldirectory.js +144 -0
- package/dist_ts/functions.controllerdataroot.d.ts +15 -0
- package/dist_ts/functions.controllerdataroot.js +76 -0
- package/dist_ts/functions.embeddeddb.d.ts +2 -0
- package/dist_ts/functions.embeddeddb.js +21 -0
- package/dist_ts/functions.flexcredentialstore.d.ts +16 -0
- package/dist_ts/functions.flexcredentialstore.js +93 -0
- package/dist_ts/functions.opencodeauth.d.ts +3 -0
- package/dist_ts/functions.opencodeauth.js +31 -0
- package/dist_ts/functions.runtimeenvironment.d.ts +2 -0
- package/dist_ts/functions.runtimeenvironment.js +79 -0
- package/dist_ts/functions.upgradefollower.d.ts +3 -0
- package/dist_ts/functions.upgradefollower.js +95 -0
- package/dist_ts/index.d.ts +24 -0
- package/dist_ts/index.js +25 -0
- package/dist_ts/interfaces.auth.d.ts +181 -0
- package/dist_ts/interfaces.auth.js +82 -0
- package/dist_ts/interfaces.config.d.ts +34 -0
- package/dist_ts/interfaces.config.js +2 -0
- package/dist_ts/interfaces.flexipc.d.ts +939 -0
- package/dist_ts/interfaces.flexipc.js +1492 -0
- package/dist_ts/interfaces.gitreversion.d.ts +246 -0
- package/dist_ts/interfaces.gitreversion.js +2 -0
- package/dist_ts/interfaces.lifecycle.d.ts +37 -0
- package/dist_ts/interfaces.lifecycle.js +2 -0
- package/dist_ts/interfaces.opencode.d.ts +101 -0
- package/dist_ts/interfaces.opencode.js +3 -0
- package/dist_ts/interfaces.projects.d.ts +156 -0
- package/dist_ts/interfaces.projects.js +5 -0
- package/dist_ts/plugins.d.ts +36 -0
- package/dist_ts/plugins.js +40 -0
- package/dist_ts_interfaces/index.d.ts +2 -0
- package/dist_ts_interfaces/index.js +3 -0
- package/dist_ts_interfaces/interfaces.d.ts +747 -0
- package/dist_ts_interfaces/interfaces.js +47 -0
- package/dist_ts_interfaces/plugins.d.ts +4 -0
- package/dist_ts_interfaces/plugins.js +3 -0
- package/dist_ts_interfaces/requests.d.ts +806 -0
- package/dist_ts_interfaces/requests.js +2 -0
- package/dist_ts_migration/classes.documentmigrationrunner.d.ts +8 -0
- package/dist_ts_migration/classes.documentmigrationrunner.js +24 -0
- package/dist_ts_migration/classes.flexmigrationrunner.d.ts +11 -0
- package/dist_ts_migration/classes.flexmigrationrunner.js +25 -0
- package/dist_ts_migration/classes.flexpostharnessmigrationrunner.d.ts +10 -0
- package/dist_ts_migration/classes.flexpostharnessmigrationrunner.js +15 -0
- package/dist_ts_migration/classes.migrationrunner.d.ts +8 -0
- package/dist_ts_migration/classes.migrationrunner.js +34 -0
- package/dist_ts_migration/index.d.ts +12 -0
- package/dist_ts_migration/index.js +13 -0
- package/dist_ts_migration/v10_flexharnessv3migration.d.ts +11 -0
- package/dist_ts_migration/v10_flexharnessv3migration.js +23 -0
- package/dist_ts_migration/v13_flexprojectionorder.d.ts +11 -0
- package/dist_ts_migration/v13_flexprojectionorder.js +23 -0
- package/dist_ts_migration/v16_flexprovidercredentials.d.ts +22 -0
- package/dist_ts_migration/v16_flexprovidercredentials.js +149 -0
- package/dist_ts_migration/v18_resourcelayout.d.ts +22 -0
- package/dist_ts_migration/v18_resourcelayout.js +23 -0
- package/dist_ts_migration/v18_resourcelayoutmigration.d.ts +6 -0
- package/dist_ts_migration/v18_resourcelayoutmigration.js +61 -0
- package/dist_ts_migration/v19_flexprojectmanagement.d.ts +11 -0
- package/dist_ts_migration/v19_flexprojectmanagement.js +21 -0
- package/dist_ts_migration/v1_embeddeddatabaselocation.d.ts +28 -0
- package/dist_ts_migration/v1_embeddeddatabaselocation.js +415 -0
- package/dist_ts_migration/v22_projectfilesystemidentitymigration.d.ts +7 -0
- package/dist_ts_migration/v22_projectfilesystemidentitymigration.js +105 -0
- package/dist_ts_migration/v2_controllerdataroot.d.ts +130 -0
- package/dist_ts_migration/v2_controllerdataroot.js +1887 -0
- package/dist_ts_migration/v6_protocoldocumentmigration.d.ts +7 -0
- package/dist_ts_migration/v6_protocoldocumentmigration.js +100 -0
- package/dist_ts_migration/v6_protocoldocuments.d.ts +7 -0
- package/dist_ts_migration/v6_protocoldocuments.js +138 -0
- package/html/index.html +13 -0
- package/{LICENSE → license.md} +2 -2
- package/package.json +86 -48
- package/readme.md +480 -0
- package/readme.plan.md +188 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.authmodels.ts +1245 -0
- package/ts/classes.authstore.ts +3274 -0
- package/ts/classes.browserresourcehost.ts +1205 -0
- package/ts/classes.cli.ts +1254 -0
- package/ts/classes.config.ts +351 -0
- package/ts/classes.controller.ts +14426 -0
- package/ts/classes.controllermanagement.ts +330 -0
- package/ts/classes.draftmanager.ts +232 -0
- package/ts/classes.embeddeddb.ts +166 -0
- package/ts/classes.flexframedtransport.ts +283 -0
- package/ts/classes.flexmodels.private.ts +823 -0
- package/ts/classes.flexmodels.public.ts +732 -0
- package/ts/classes.flexprojectionreader.ts +816 -0
- package/ts/classes.flexservice.ts +4302 -0
- package/ts/classes.flexstore.ts +4565 -0
- package/ts/classes.flexsupervisor.ts +1453 -0
- package/ts/classes.gitreversion.ts +13353 -0
- package/ts/classes.harnessoperationmanager.ts +870 -0
- package/ts/classes.opencodeclient.ts +4110 -0
- package/ts/classes.opencodesupervisor.ts +1280 -0
- package/ts/classes.passkeymanager.ts +570 -0
- package/ts/classes.processinspection.ts +623 -0
- package/ts/classes.resourcecoordinator.ts +436 -0
- package/ts/classes.sessionintelligencereader.ts +52 -0
- package/ts/classes.systemmetricssampler.ts +215 -0
- package/ts/classes.terminalmanager.ts +1207 -0
- package/ts/classes.terminalresourcehost.ts +122 -0
- package/ts/classes.upgradecoordinator.ts +2675 -0
- package/ts/classes.upgradetransaction.ts +2900 -0
- package/ts/classes.uploadmanager.ts +240 -0
- package/ts/classes.validation.ts +1409 -0
- package/ts/flexharness.child.ts +35 -0
- package/ts/functions.canonicaldirectory.ts +213 -0
- package/ts/functions.controllerdataroot.ts +107 -0
- package/ts/functions.embeddeddb.ts +22 -0
- package/ts/functions.flexcredentialstore.ts +128 -0
- package/ts/functions.opencodeauth.ts +34 -0
- package/ts/functions.runtimeenvironment.ts +90 -0
- package/ts/functions.upgradefollower.ts +115 -0
- package/ts/index.ts +36 -6
- package/ts/interfaces.auth.ts +316 -0
- package/ts/interfaces.config.ts +37 -0
- package/ts/interfaces.flexipc.ts +2586 -0
- package/ts/interfaces.gitreversion.ts +336 -0
- package/ts/interfaces.lifecycle.ts +46 -0
- package/ts/interfaces.opencode.ts +153 -0
- package/ts/interfaces.projects.ts +182 -0
- package/ts/plugins.ts +64 -0
- package/ts_interfaces/index.ts +2 -0
- package/ts_interfaces/interfaces.ts +827 -0
- package/ts_interfaces/plugins.ts +15 -0
- package/ts_interfaces/requests.ts +1186 -0
- package/ts_migration/classes.documentmigrationrunner.ts +32 -0
- package/ts_migration/classes.flexmigrationrunner.ts +33 -0
- package/ts_migration/classes.flexpostharnessmigrationrunner.ts +22 -0
- package/ts_migration/classes.migrationrunner.ts +40 -0
- package/ts_migration/index.ts +12 -0
- package/ts_migration/v10_flexharnessv3migration.ts +35 -0
- package/ts_migration/v13_flexprojectionorder.ts +33 -0
- package/ts_migration/v16_flexprovidercredentials.ts +196 -0
- package/ts_migration/v18_resourcelayout.ts +55 -0
- package/ts_migration/v18_resourcelayoutmigration.ts +68 -0
- package/ts_migration/v19_flexprojectmanagement.ts +28 -0
- package/ts_migration/v1_embeddeddatabaselocation.ts +560 -0
- package/ts_migration/v22_projectfilesystemidentitymigration.ts +121 -0
- package/ts_migration/v2_controllerdataroot.ts +2349 -0
- package/ts_migration/v6_protocoldocumentmigration.ts +144 -0
- package/ts_migration/v6_protocoldocuments.ts +198 -0
- package/ts_web/00_commitinfo_data.ts +8 -0
- package/ts_web/classes.controllersocketclient.ts +517 -0
- package/ts_web/classes.sessiondraftsync.ts +390 -0
- package/ts_web/elements.harnesscontrollerapp.ts +11494 -0
- package/ts_web/index.ts +2 -0
- package/ts_web/plugins.ts +31 -0
- package/.gitlab-ci.yml +0 -71
- package/.npmignore +0 -5
- package/README.md +0 -40
- package/dist/cli.js +0 -2
- package/dist/index.d.ts +0 -0
- package/dist/index.js +0 -9
- package/dist/mod_bundle/index.d.ts +0 -1
- package/dist/mod_bundle/index.js +0 -18
- package/dist/mod_bundle/mod.plugins.d.ts +0 -4
- package/dist/mod_bundle/mod.plugins.js +0 -11
- package/dist/mod_install/index.d.ts +0 -4
- package/dist/mod_install/index.js +0 -21
- package/dist/mod_install/mod.plugins.d.ts +0 -1
- package/dist/mod_install/mod.plugins.js +0 -7
- package/dist/mod_standard/index.d.ts +0 -4
- package/dist/mod_standard/index.js +0 -21
- package/dist/mod_standard/mod.browser.d.ts +0 -6
- package/dist/mod_standard/mod.browser.js +0 -14
- package/dist/mod_standard/mod.clean.d.ts +0 -4
- package/dist/mod_standard/mod.clean.js +0 -12
- package/dist/mod_standard/mod.compile.d.ts +0 -4
- package/dist/mod_standard/mod.compile.js +0 -21
- package/dist/mod_standard/mod.plugins.d.ts +0 -8
- package/dist/mod_standard/mod.plugins.js +0 -19
- package/dist/mod_standard/mod.test.d.ts +0 -4
- package/dist/mod_standard/mod.test.js +0 -12
- package/dist/plr.cli.d.ts +0 -3
- package/dist/plr.cli.js +0 -57
- package/dist/plr.config.d.ts +0 -11
- package/dist/plr.config.js +0 -26
- package/dist/plr.mods.d.ts +0 -17
- package/dist/plr.mods.js +0 -17
- package/dist/plr.paths.d.ts +0 -19
- package/dist/plr.paths.js +0 -26
- package/dist/plr.plugins.d.ts +0 -8
- package/dist/plr.plugins.js +0 -16
- package/npmextra.json +0 -10
- package/ts/mod_bundle/index.ts +0 -20
- package/ts/mod_bundle/mod.plugins.ts +0 -9
- package/ts/mod_install/index.ts +0 -20
- package/ts/mod_install/mod.plugins.ts +0 -1
- package/ts/mod_standard/index.ts +0 -23
- package/ts/mod_standard/mod.browser.ts +0 -17
- package/ts/mod_standard/mod.clean.ts +0 -13
- package/ts/mod_standard/mod.compile.ts +0 -23
- package/ts/mod_standard/mod.plugins.ts +0 -17
- package/ts/mod_standard/mod.test.ts +0 -13
- package/ts/plr.cli.ts +0 -60
- package/ts/plr.config.ts +0 -36
- package/ts/plr.mods.ts +0 -25
- package/ts/plr.paths.ts +0 -29
- package/ts/plr.plugins.ts +0 -17
- package/tslint.json +0 -3
- package/yarn.lock +0 -3464
|
@@ -0,0 +1,3003 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { controllerMaxAttachmentPromptSuffixBytes, controllerMaxDraftTextBytes, controllerInitialMessageBundleLimit, controllerMaxLiveMessageEventBytes, controllerMaxToolEventBytes, controllerRuntimeIdKey, } from '../dist_ts_interfaces/index.js';
|
|
3
|
+
// Every normalized response must fit the transport. TypedSocket allows 16 MiB
|
|
4
|
+
// frames here; these lower per-response budgets also bound memory and fan-out.
|
|
5
|
+
const maxIdentifierBytes = 512;
|
|
6
|
+
const maxTitleBytes = 2048;
|
|
7
|
+
const maxPromptBytes = controllerMaxDraftTextBytes + controllerMaxAttachmentPromptSuffixBytes;
|
|
8
|
+
const maxMessageTextBytes = 96 * 1024;
|
|
9
|
+
const maxToolPayloadBytes = 48 * 1024;
|
|
10
|
+
const maxLiveToolExecutionBytes = controllerMaxToolEventBytes - (8 * 1024);
|
|
11
|
+
const maxLiveMessageSnapshotBytes = controllerMaxLiveMessageEventBytes - (8 * 1024);
|
|
12
|
+
const maxLiveMessagePartCacheEntries = 512;
|
|
13
|
+
const maxLiveMessagePartCacheBytes = 4 * 1024 * 1024;
|
|
14
|
+
const maxMetadataStringBytes = 16 * 1024;
|
|
15
|
+
const maxMetadataNodes = 4096;
|
|
16
|
+
const maxCollectionEntries = 512;
|
|
17
|
+
const maxMessagesPerRequest = 200;
|
|
18
|
+
const maxMessagesPerPage = 50;
|
|
19
|
+
const maxMessagePartsPerResponse = 2048;
|
|
20
|
+
const maxNormalizedMessageBytes = 512 * 1024;
|
|
21
|
+
const maxNormalizedPermissionBytes = 128 * 1024;
|
|
22
|
+
const maxPerMessageReasoningBytes = 128 * 1024;
|
|
23
|
+
const maxNormalizedQuestionBytes = 128 * 1024;
|
|
24
|
+
const maxQuestionsPerRequest = 16;
|
|
25
|
+
const maxOptionsPerQuestion = 64;
|
|
26
|
+
const maxNormalizedSessionDetailBytes = 576 * 1024;
|
|
27
|
+
// Read-side memory guards only: the transcript is trimmed to the transfer
|
|
28
|
+
// budget after parsing, so these just bound transient buffering while a
|
|
29
|
+
// response streams in. Long-running local sessions legitimately produce
|
|
30
|
+
// tens of megabytes of raw message history.
|
|
31
|
+
const maxRawOpenCodeResponseBytes = 64 * 1024 * 1024;
|
|
32
|
+
const maxRawOpenCodeSseEventBytes = 8 * 1024 * 1024;
|
|
33
|
+
const defaultSdkRequestTimeoutMs = 30_000;
|
|
34
|
+
// compact/init run a full model call server-side before responding.
|
|
35
|
+
const builtinModelCommandTimeoutMs = 10 * 60_000;
|
|
36
|
+
const normalizedNodeCostBytes = 64;
|
|
37
|
+
const truncatedSuffix = '\n… [truncated]';
|
|
38
|
+
const openCodeHarnessId = 'opencode';
|
|
39
|
+
const sessionIntelligenceProviderId = 'openai';
|
|
40
|
+
const sessionIntelligenceModelId = 'gpt-5.6-luna';
|
|
41
|
+
const sessionIntelligenceModel = `${sessionIntelligenceProviderId}/${sessionIntelligenceModelId}`;
|
|
42
|
+
const sessionIntelligenceTimeoutMs = 5 * 60_000;
|
|
43
|
+
const maxExhaustiveMessagePages = 400;
|
|
44
|
+
const sessionMetricsCacheTtlMs = 30_000;
|
|
45
|
+
const maxSessionMetricsCacheEntries = 512;
|
|
46
|
+
const maxIntelligenceTranscriptBytes = 256 * 1024;
|
|
47
|
+
const maxIntelligenceTranscriptMessages = 256;
|
|
48
|
+
// One persisted cleanup page can contain 500 states with eight exchanges each.
|
|
49
|
+
const maxSessionIntelligenceCleanupObligations = 4_000;
|
|
50
|
+
const sessionIntelligenceTitle = 'Session Intelligence';
|
|
51
|
+
const eventStreamResubscribeDelayMs = 500;
|
|
52
|
+
const eventStreamMaxResubscribeDelayMs = 10_000;
|
|
53
|
+
const openCodeRuntimeId = (nativeIdArg) => ({
|
|
54
|
+
harnessId: openCodeHarnessId,
|
|
55
|
+
nativeId: nativeIdArg,
|
|
56
|
+
});
|
|
57
|
+
const controllerRuntimeIdsEqual = (leftArg, rightArg) => controllerRuntimeIdKey(leftArg) === controllerRuntimeIdKey(rightArg);
|
|
58
|
+
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
59
|
+
const isOpenCodeNotFoundError = (valueArg) => isRecord(valueArg)
|
|
60
|
+
&& valueArg.name === 'NotFoundError'
|
|
61
|
+
&& isRecord(valueArg.data)
|
|
62
|
+
&& typeof valueArg.data.message === 'string';
|
|
63
|
+
const hasExactKeys = (valueArg, requiredArg, optionalArg = []) => {
|
|
64
|
+
const keys = Object.keys(valueArg);
|
|
65
|
+
const allowed = new Set([...requiredArg, ...optionalArg]);
|
|
66
|
+
return requiredArg.every((key) => Object.hasOwn(valueArg, key))
|
|
67
|
+
&& keys.every((key) => allowed.has(key));
|
|
68
|
+
};
|
|
69
|
+
export class OpenCodeSessionIntelligenceCleanupError extends AggregateError {
|
|
70
|
+
temporarySessionId;
|
|
71
|
+
constructor(temporarySessionIdArg, isolationErrorArg, cleanupErrorArg) {
|
|
72
|
+
super([isolationErrorArg, cleanupErrorArg], 'OpenCode rejected the Session Intelligence isolation contract and cleanup failed.');
|
|
73
|
+
this.temporarySessionId = temporarySessionIdArg;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const isSessionIntelligenceMetadata = (valueArg, controllerIdArg, expectedMarkerArg) => {
|
|
77
|
+
if (!isRecord(valueArg) || !isRecord(valueArg.modelprofileSessionIntelligence))
|
|
78
|
+
return false;
|
|
79
|
+
const marker = valueArg.modelprofileSessionIntelligence;
|
|
80
|
+
return hasExactKeys(valueArg, ['modelprofileSessionIntelligence'])
|
|
81
|
+
&& hasExactKeys(marker, [
|
|
82
|
+
'schemaVersion',
|
|
83
|
+
'controllerId',
|
|
84
|
+
'projectId',
|
|
85
|
+
'sourceSessionId',
|
|
86
|
+
'exchangeId',
|
|
87
|
+
])
|
|
88
|
+
&& marker.schemaVersion === 1
|
|
89
|
+
&& typeof marker.controllerId === 'string'
|
|
90
|
+
&& (controllerIdArg === undefined || marker.controllerId === controllerIdArg)
|
|
91
|
+
&& typeof marker.projectId === 'string'
|
|
92
|
+
&& isRecord(marker.sourceSessionId)
|
|
93
|
+
&& hasExactKeys(marker.sourceSessionId, ['harnessId', 'nativeId'])
|
|
94
|
+
&& (marker.sourceSessionId.harnessId === 'opencode' || marker.sourceSessionId.harnessId === 'flex')
|
|
95
|
+
&& typeof marker.sourceSessionId.nativeId === 'string'
|
|
96
|
+
&& typeof marker.exchangeId === 'string'
|
|
97
|
+
&& (expectedMarkerArg === undefined
|
|
98
|
+
|| (marker.controllerId === expectedMarkerArg.controllerId
|
|
99
|
+
&& marker.projectId === expectedMarkerArg.projectId
|
|
100
|
+
&& marker.sourceSessionId.harnessId === expectedMarkerArg.sourceSessionId.harnessId
|
|
101
|
+
&& marker.sourceSessionId.nativeId === expectedMarkerArg.sourceSessionId.nativeId
|
|
102
|
+
&& marker.exchangeId === expectedMarkerArg.exchangeId));
|
|
103
|
+
};
|
|
104
|
+
const truncateUtf8 = (value, byteLimit) => {
|
|
105
|
+
if (Buffer.byteLength(value, 'utf8') <= byteLimit) {
|
|
106
|
+
return value;
|
|
107
|
+
}
|
|
108
|
+
const suffixBytes = Buffer.byteLength(truncatedSuffix, 'utf8');
|
|
109
|
+
if (byteLimit <= suffixBytes) {
|
|
110
|
+
return Buffer.from(value, 'utf8')
|
|
111
|
+
.subarray(0, Math.max(0, byteLimit))
|
|
112
|
+
.toString('utf8')
|
|
113
|
+
.replace(/\uFFFD$/u, '');
|
|
114
|
+
}
|
|
115
|
+
const contentBytes = Math.max(0, byteLimit - suffixBytes);
|
|
116
|
+
let truncated = Buffer.from(value, 'utf8').subarray(0, contentBytes).toString('utf8');
|
|
117
|
+
truncated = truncated.replace(/\uFFFD$/u, '');
|
|
118
|
+
return `${truncated}${truncatedSuffix}`;
|
|
119
|
+
};
|
|
120
|
+
const createOutputBudget = (byteLimit, label) => ({
|
|
121
|
+
bytesRemaining: byteLimit,
|
|
122
|
+
label,
|
|
123
|
+
});
|
|
124
|
+
const consumeOutputBytes = (budget, byteLength) => {
|
|
125
|
+
budget.bytesRemaining -= byteLength;
|
|
126
|
+
if (budget.bytesRemaining < 0) {
|
|
127
|
+
throw new Error(`OpenCode returned ${budget.label} that exceeded its aggregate output budget.`);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
const consumeOutputString = (budget, value) => {
|
|
131
|
+
consumeOutputBytes(budget, Buffer.byteLength(value, 'utf8'));
|
|
132
|
+
return value;
|
|
133
|
+
};
|
|
134
|
+
const elidedPayloadNotice = '[elided: this transcript exceeds the transfer budget]';
|
|
135
|
+
const elidedHistoryNotice = '[earlier messages elided: this transcript exceeds the transfer budget]';
|
|
136
|
+
const createElidedHistoryId = (messagesArg) => {
|
|
137
|
+
const occupiedKeys = new Set(messagesArg.map((message) => controllerRuntimeIdKey(message.id)));
|
|
138
|
+
const transcriptDigest = plugins.crypto
|
|
139
|
+
.createHash('sha256')
|
|
140
|
+
.update(JSON.stringify(messagesArg.map((message) => controllerRuntimeIdKey(message.id))))
|
|
141
|
+
.digest('hex');
|
|
142
|
+
const nativeIdBase = `harness-controller:elided-history:${transcriptDigest}`;
|
|
143
|
+
let disambiguator = 0;
|
|
144
|
+
let candidate = openCodeRuntimeId(nativeIdBase);
|
|
145
|
+
while (occupiedKeys.has(controllerRuntimeIdKey(candidate))) {
|
|
146
|
+
disambiguator += 1;
|
|
147
|
+
candidate = openCodeRuntimeId(`${nativeIdBase}:${disambiguator}`);
|
|
148
|
+
}
|
|
149
|
+
return candidate;
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Drops the OLDEST transcript entries until the serialized form fits,
|
|
153
|
+
* leaving a marker so readers can see history was cut. Newest messages are
|
|
154
|
+
* what a conversation view needs; a transcript must never fail to load over
|
|
155
|
+
* its size.
|
|
156
|
+
*/
|
|
157
|
+
const trimOldestMessagesToFit = (messages, byteLimit) => {
|
|
158
|
+
let current = messages;
|
|
159
|
+
const markerId = createElidedHistoryId(messages);
|
|
160
|
+
const markerIdKey = controllerRuntimeIdKey(markerId);
|
|
161
|
+
while (current.length > 1
|
|
162
|
+
&& Buffer.byteLength(JSON.stringify(current), 'utf8') > byteLimit) {
|
|
163
|
+
const realMessages = current.filter((message) => controllerRuntimeIdKey(message.id) !== markerIdKey);
|
|
164
|
+
const dropCount = Math.max(1, Math.ceil(realMessages.length / 10));
|
|
165
|
+
const kept = realMessages.slice(dropCount);
|
|
166
|
+
const marker = {
|
|
167
|
+
id: markerId,
|
|
168
|
+
role: 'system',
|
|
169
|
+
text: elidedHistoryNotice,
|
|
170
|
+
createdAt: kept[0]?.createdAt ?? 0,
|
|
171
|
+
};
|
|
172
|
+
current = [marker, ...kept];
|
|
173
|
+
}
|
|
174
|
+
return current;
|
|
175
|
+
};
|
|
176
|
+
const assertSerializedOutputWithinLimit = (value, byteLimit, label) => {
|
|
177
|
+
const serialized = JSON.stringify(value);
|
|
178
|
+
if (Buffer.byteLength(serialized, 'utf8') > byteLimit) {
|
|
179
|
+
throw new Error(`OpenCode returned ${label} that exceeded its aggregate output budget.`);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
const createBoundedResponse = async (responseArg, byteLimitArg, sseEventModeArg, releaseArg) => {
|
|
183
|
+
const declaredLength = responseArg.headers.get('content-length');
|
|
184
|
+
if (!sseEventModeArg && declaredLength !== null) {
|
|
185
|
+
const parsedLength = Number(declaredLength);
|
|
186
|
+
if (Number.isFinite(parsedLength) && parsedLength > byteLimitArg) {
|
|
187
|
+
let cancellation;
|
|
188
|
+
try {
|
|
189
|
+
cancellation = responseArg.body?.cancel(new Error('OpenCode response exceeded its declared raw byte limit.'));
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
releaseArg?.();
|
|
193
|
+
}
|
|
194
|
+
void cancellation?.catch(() => undefined);
|
|
195
|
+
throw new Error('OpenCode response exceeded its raw byte limit.');
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (!responseArg.body) {
|
|
199
|
+
releaseArg?.();
|
|
200
|
+
return responseArg;
|
|
201
|
+
}
|
|
202
|
+
if (sseEventModeArg)
|
|
203
|
+
releaseArg?.();
|
|
204
|
+
let bytesSeen = 0;
|
|
205
|
+
let eventText = '';
|
|
206
|
+
let trailingCarriageReturn = false;
|
|
207
|
+
const decoder = sseEventModeArg ? new TextDecoder() : undefined;
|
|
208
|
+
const sourceReader = responseArg.body.getReader();
|
|
209
|
+
let released = sseEventModeArg;
|
|
210
|
+
let sourceLockReleased = false;
|
|
211
|
+
const release = () => {
|
|
212
|
+
if (released)
|
|
213
|
+
return;
|
|
214
|
+
released = true;
|
|
215
|
+
releaseArg?.();
|
|
216
|
+
};
|
|
217
|
+
const releaseSourceLock = () => {
|
|
218
|
+
if (sourceLockReleased)
|
|
219
|
+
return;
|
|
220
|
+
sourceLockReleased = true;
|
|
221
|
+
sourceReader.releaseLock();
|
|
222
|
+
};
|
|
223
|
+
const fail = (reasonArg) => {
|
|
224
|
+
release();
|
|
225
|
+
let cancellation;
|
|
226
|
+
try {
|
|
227
|
+
cancellation = sourceReader.cancel(reasonArg);
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
releaseSourceLock();
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
try {
|
|
234
|
+
releaseSourceLock();
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
void cancellation.finally(() => releaseSourceLock()).catch(() => undefined);
|
|
238
|
+
}
|
|
239
|
+
void cancellation.catch(() => undefined);
|
|
240
|
+
};
|
|
241
|
+
const stream = new ReadableStream({
|
|
242
|
+
async pull(controllerArg) {
|
|
243
|
+
try {
|
|
244
|
+
const result = await sourceReader.read();
|
|
245
|
+
if (result.done) {
|
|
246
|
+
if (sseEventModeArg) {
|
|
247
|
+
const finalText = `${eventText}${trailingCarriageReturn ? '\r' : ''}${decoder.decode()}`;
|
|
248
|
+
if (Buffer.byteLength(finalText, 'utf8') > byteLimitArg) {
|
|
249
|
+
throw new Error('OpenCode SSE event exceeded its raw byte limit.');
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
release();
|
|
253
|
+
releaseSourceLock();
|
|
254
|
+
controllerArg.close();
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const chunkArg = result.value;
|
|
258
|
+
if (!sseEventModeArg) {
|
|
259
|
+
bytesSeen += chunkArg.byteLength;
|
|
260
|
+
if (bytesSeen > byteLimitArg) {
|
|
261
|
+
throw new Error('OpenCode response exceeded its raw byte limit.');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
let decoded = decoder.decode(chunkArg, { stream: true });
|
|
266
|
+
if (trailingCarriageReturn) {
|
|
267
|
+
decoded = `\r${decoded}`;
|
|
268
|
+
trailingCarriageReturn = false;
|
|
269
|
+
}
|
|
270
|
+
if (decoded.endsWith('\r')) {
|
|
271
|
+
decoded = decoded.slice(0, -1);
|
|
272
|
+
trailingCarriageReturn = true;
|
|
273
|
+
}
|
|
274
|
+
const normalized = `${eventText}${decoded}`
|
|
275
|
+
.replace(/\r\n/gu, '\n')
|
|
276
|
+
.replace(/\r/gu, '\n');
|
|
277
|
+
const lastBoundary = normalized.lastIndexOf('\n\n');
|
|
278
|
+
eventText = lastBoundary >= 0
|
|
279
|
+
? normalized.slice(lastBoundary + 2)
|
|
280
|
+
: normalized;
|
|
281
|
+
if (Buffer.byteLength(eventText, 'utf8') > byteLimitArg) {
|
|
282
|
+
throw new Error('OpenCode SSE event exceeded its raw byte limit.');
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
controllerArg.enqueue(chunkArg);
|
|
286
|
+
}
|
|
287
|
+
catch (errorArg) {
|
|
288
|
+
fail(errorArg);
|
|
289
|
+
throw errorArg;
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
cancel(reasonArg) {
|
|
293
|
+
fail(reasonArg);
|
|
294
|
+
},
|
|
295
|
+
});
|
|
296
|
+
return new Response(stream, {
|
|
297
|
+
status: responseArg.status,
|
|
298
|
+
statusText: responseArg.statusText,
|
|
299
|
+
headers: responseArg.headers,
|
|
300
|
+
});
|
|
301
|
+
};
|
|
302
|
+
export const createBoundedOpenCodeFetch = (expectedBaseUrlArg, fetchImplementationArg = globalThis.fetch, acquireRuntimeLeaseArg) => {
|
|
303
|
+
const expectedOrigin = new URL(expectedBaseUrlArg).origin;
|
|
304
|
+
return (async (inputArg, initArg) => {
|
|
305
|
+
const request = new Request(inputArg, { ...initArg, redirect: 'error' });
|
|
306
|
+
if (new URL(request.url).origin !== expectedOrigin) {
|
|
307
|
+
throw new Error('OpenCode SDK attempted a request outside its loopback server origin.');
|
|
308
|
+
}
|
|
309
|
+
const release = acquireRuntimeLeaseArg?.();
|
|
310
|
+
let response;
|
|
311
|
+
try {
|
|
312
|
+
response = await fetchImplementationArg(request);
|
|
313
|
+
}
|
|
314
|
+
catch (errorArg) {
|
|
315
|
+
release?.();
|
|
316
|
+
throw errorArg;
|
|
317
|
+
}
|
|
318
|
+
const contentType = response.headers.get('content-type')?.split(';', 1)[0]?.trim();
|
|
319
|
+
return createBoundedResponse(response, contentType === 'text/event-stream'
|
|
320
|
+
? maxRawOpenCodeSseEventBytes
|
|
321
|
+
: maxRawOpenCodeResponseBytes, contentType === 'text/event-stream', release);
|
|
322
|
+
});
|
|
323
|
+
};
|
|
324
|
+
const runSdkRequest = async (callerSignal, operation, timeoutMs = defaultSdkRequestTimeoutMs) => {
|
|
325
|
+
callerSignal?.throwIfAborted();
|
|
326
|
+
const requestAbortController = new AbortController();
|
|
327
|
+
const abortFromCaller = () => {
|
|
328
|
+
requestAbortController.abort(callerSignal?.reason);
|
|
329
|
+
};
|
|
330
|
+
callerSignal?.addEventListener('abort', abortFromCaller, { once: true });
|
|
331
|
+
if (callerSignal?.aborted) {
|
|
332
|
+
abortFromCaller();
|
|
333
|
+
}
|
|
334
|
+
const timeout = timeoutMs === undefined
|
|
335
|
+
? undefined
|
|
336
|
+
: setTimeout(() => {
|
|
337
|
+
requestAbortController.abort(new Error(`OpenCode SDK request exceeded ${timeoutMs}ms.`));
|
|
338
|
+
}, timeoutMs);
|
|
339
|
+
timeout?.unref();
|
|
340
|
+
try {
|
|
341
|
+
return await operation(requestAbortController.signal);
|
|
342
|
+
}
|
|
343
|
+
finally {
|
|
344
|
+
if (timeout)
|
|
345
|
+
clearTimeout(timeout);
|
|
346
|
+
callerSignal?.removeEventListener('abort', abortFromCaller);
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
const requireString = (value, fieldName, byteLimit) => {
|
|
350
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
351
|
+
throw new Error(`OpenCode returned an invalid ${fieldName}.`);
|
|
352
|
+
}
|
|
353
|
+
if (Buffer.byteLength(value, 'utf8') > byteLimit) {
|
|
354
|
+
throw new Error(`OpenCode returned an oversized ${fieldName}.`);
|
|
355
|
+
}
|
|
356
|
+
return value;
|
|
357
|
+
};
|
|
358
|
+
const normalizeModelVariants = (value) => {
|
|
359
|
+
if (!isRecord(value))
|
|
360
|
+
return [];
|
|
361
|
+
const entries = Object.entries(value);
|
|
362
|
+
if (entries.length > 16) {
|
|
363
|
+
throw new Error('OpenCode returned too many variants for one model.');
|
|
364
|
+
}
|
|
365
|
+
const variants = [];
|
|
366
|
+
for (const [variantKey, variant] of entries) {
|
|
367
|
+
if (variantKey === '__proto__'
|
|
368
|
+
|| variantKey === 'constructor'
|
|
369
|
+
|| variantKey === 'prototype')
|
|
370
|
+
continue;
|
|
371
|
+
if (isRecord(variant) && variant.disabled === true)
|
|
372
|
+
continue;
|
|
373
|
+
variants.push(requireString(variantKey, 'model variant name', 64));
|
|
374
|
+
}
|
|
375
|
+
return variants;
|
|
376
|
+
};
|
|
377
|
+
const requireFiniteNumber = (value, fieldName) => {
|
|
378
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {
|
|
379
|
+
throw new Error(`OpenCode returned an invalid ${fieldName}.`);
|
|
380
|
+
}
|
|
381
|
+
return value;
|
|
382
|
+
};
|
|
383
|
+
const optionalFiniteNumber = (value) => {
|
|
384
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {
|
|
385
|
+
return undefined;
|
|
386
|
+
}
|
|
387
|
+
return value;
|
|
388
|
+
};
|
|
389
|
+
const optionalNonNegativeSafeInteger = (value) => (typeof value === 'number' && Number.isSafeInteger(value) && value >= 0
|
|
390
|
+
? value
|
|
391
|
+
: undefined);
|
|
392
|
+
const validateInputString = (value, fieldName, byteLimit, allowEmpty = false) => {
|
|
393
|
+
if (typeof value !== 'string' || (!allowEmpty && value.trim().length === 0)) {
|
|
394
|
+
throw new Error(`${fieldName} must be a non-empty string.`);
|
|
395
|
+
}
|
|
396
|
+
if (Buffer.byteLength(value, 'utf8') > byteLimit) {
|
|
397
|
+
throw new Error(`${fieldName} exceeds the ${byteLimit}-byte limit.`);
|
|
398
|
+
}
|
|
399
|
+
return value;
|
|
400
|
+
};
|
|
401
|
+
const validateOpenCodeModelChoice = (modelArg, identifierByteLimitArg = 256) => {
|
|
402
|
+
if (modelArg === undefined)
|
|
403
|
+
return undefined;
|
|
404
|
+
if (modelArg.harnessId !== openCodeHarnessId) {
|
|
405
|
+
throw new Error('OpenCode adapter requires an OpenCode model choice.');
|
|
406
|
+
}
|
|
407
|
+
return {
|
|
408
|
+
providerID: validateInputString(modelArg.providerID, 'Model provider ID', identifierByteLimitArg),
|
|
409
|
+
modelID: validateInputString(modelArg.modelID, 'Model ID', identifierByteLimitArg),
|
|
410
|
+
...(modelArg.variant === undefined
|
|
411
|
+
? {}
|
|
412
|
+
: { variant: validateInputString(modelArg.variant, 'Model variant', 64) }),
|
|
413
|
+
};
|
|
414
|
+
};
|
|
415
|
+
const sanitizeUnknown = (value, budget = {
|
|
416
|
+
nodesRemaining: maxMetadataNodes,
|
|
417
|
+
outputBudget: createOutputBudget(maxNormalizedPermissionBytes, 'metadata'),
|
|
418
|
+
}, depth = 0, seen = new WeakSet()) => {
|
|
419
|
+
budget.nodesRemaining -= 1;
|
|
420
|
+
if (budget.nodesRemaining < 0) {
|
|
421
|
+
return consumeOutputString(budget.outputBudget, '[truncated]');
|
|
422
|
+
}
|
|
423
|
+
consumeOutputBytes(budget.outputBudget, normalizedNodeCostBytes);
|
|
424
|
+
if (value === null || typeof value === 'boolean') {
|
|
425
|
+
return value;
|
|
426
|
+
}
|
|
427
|
+
if (typeof value === 'number') {
|
|
428
|
+
return Number.isFinite(value)
|
|
429
|
+
? value
|
|
430
|
+
: consumeOutputString(budget.outputBudget, String(value));
|
|
431
|
+
}
|
|
432
|
+
if (typeof value === 'string') {
|
|
433
|
+
return consumeOutputString(budget.outputBudget, truncateUtf8(value, maxMetadataStringBytes));
|
|
434
|
+
}
|
|
435
|
+
if (typeof value === 'bigint') {
|
|
436
|
+
return consumeOutputString(budget.outputBudget, value.toString());
|
|
437
|
+
}
|
|
438
|
+
if (typeof value !== 'object') {
|
|
439
|
+
return consumeOutputString(budget.outputBudget, `[${typeof value}]`);
|
|
440
|
+
}
|
|
441
|
+
if (depth >= 8) {
|
|
442
|
+
return consumeOutputString(budget.outputBudget, '[maximum depth reached]');
|
|
443
|
+
}
|
|
444
|
+
if (seen.has(value)) {
|
|
445
|
+
return consumeOutputString(budget.outputBudget, '[circular]');
|
|
446
|
+
}
|
|
447
|
+
seen.add(value);
|
|
448
|
+
if (Array.isArray(value)) {
|
|
449
|
+
const result = value
|
|
450
|
+
.slice(0, maxCollectionEntries)
|
|
451
|
+
.map((item) => sanitizeUnknown(item, budget, depth + 1, seen));
|
|
452
|
+
if (value.length > maxCollectionEntries) {
|
|
453
|
+
result.push(consumeOutputString(budget.outputBudget, `[${value.length - maxCollectionEntries} items omitted]`));
|
|
454
|
+
}
|
|
455
|
+
return result;
|
|
456
|
+
}
|
|
457
|
+
const prototype = Object.getPrototypeOf(value);
|
|
458
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
459
|
+
return consumeOutputString(budget.outputBudget, `[unsupported ${value.constructor?.name || 'object'}]`);
|
|
460
|
+
}
|
|
461
|
+
const recordValue = value;
|
|
462
|
+
const result = {};
|
|
463
|
+
let includedEntryCount = 0;
|
|
464
|
+
let wasTruncated = false;
|
|
465
|
+
for (const rawKey in recordValue) {
|
|
466
|
+
if (!Object.hasOwn(recordValue, rawKey)) {
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
if (includedEntryCount >= maxCollectionEntries) {
|
|
470
|
+
wasTruncated = true;
|
|
471
|
+
break;
|
|
472
|
+
}
|
|
473
|
+
if (rawKey === '__proto__' || rawKey === 'constructor' || rawKey === 'prototype') {
|
|
474
|
+
continue;
|
|
475
|
+
}
|
|
476
|
+
const key = truncateUtf8(rawKey, maxIdentifierBytes);
|
|
477
|
+
consumeOutputString(budget.outputBudget, key);
|
|
478
|
+
result[key] = sanitizeUnknown(recordValue[rawKey], budget, depth + 1, seen);
|
|
479
|
+
includedEntryCount += 1;
|
|
480
|
+
}
|
|
481
|
+
if (wasTruncated) {
|
|
482
|
+
result.__truncated = true;
|
|
483
|
+
}
|
|
484
|
+
return result;
|
|
485
|
+
};
|
|
486
|
+
const sanitizeRecord = (value, fieldName, budget) => {
|
|
487
|
+
if (!isRecord(value)) {
|
|
488
|
+
throw new Error(`OpenCode returned invalid ${fieldName}.`);
|
|
489
|
+
}
|
|
490
|
+
const sanitized = sanitizeUnknown(value, budget);
|
|
491
|
+
if (!isRecord(sanitized)) {
|
|
492
|
+
throw new Error(`OpenCode returned invalid ${fieldName}.`);
|
|
493
|
+
}
|
|
494
|
+
return sanitized;
|
|
495
|
+
};
|
|
496
|
+
const normalizeSessionStatus = (value) => {
|
|
497
|
+
if (!isRecord(value)) {
|
|
498
|
+
throw new Error('OpenCode returned an invalid session status.');
|
|
499
|
+
}
|
|
500
|
+
switch (value.type) {
|
|
501
|
+
case 'idle':
|
|
502
|
+
case 'busy':
|
|
503
|
+
case 'retry':
|
|
504
|
+
return value.type;
|
|
505
|
+
default:
|
|
506
|
+
throw new Error('OpenCode returned an unknown session status.');
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
export const normalizeOpenCodeSession = (value, directory, status = 'idle') => {
|
|
510
|
+
if (!isRecord(value) || !isRecord(value.time)) {
|
|
511
|
+
throw new Error('OpenCode returned an invalid session.');
|
|
512
|
+
}
|
|
513
|
+
if (value.directory !== directory) {
|
|
514
|
+
throw new Error('OpenCode returned a session outside the configured directory.');
|
|
515
|
+
}
|
|
516
|
+
const parentId = value.parentID === undefined
|
|
517
|
+
? undefined
|
|
518
|
+
: openCodeRuntimeId(requireString(value.parentID, 'session parent ID', maxIdentifierBytes));
|
|
519
|
+
// A zero timestamp reads as "not archived" rather than 1970.
|
|
520
|
+
const archivedAt = optionalFiniteNumber(value.time.archived);
|
|
521
|
+
return {
|
|
522
|
+
id: openCodeRuntimeId(requireString(value.id, 'session ID', maxIdentifierBytes)),
|
|
523
|
+
title: truncateUtf8(requireString(value.title, 'session title', maxMessageTextBytes), maxTitleBytes),
|
|
524
|
+
...(parentId ? { parentId } : {}),
|
|
525
|
+
createdAt: requireFiniteNumber(value.time.created, 'session creation time'),
|
|
526
|
+
updatedAt: requireFiniteNumber(value.time.updated, 'session update time'),
|
|
527
|
+
...(archivedAt ? { archivedAt } : {}),
|
|
528
|
+
status,
|
|
529
|
+
};
|
|
530
|
+
};
|
|
531
|
+
const normalizeUsage = (value) => {
|
|
532
|
+
if (!isRecord(value)) {
|
|
533
|
+
return undefined;
|
|
534
|
+
}
|
|
535
|
+
const cache = isRecord(value.cache) ? value.cache : undefined;
|
|
536
|
+
const usage = {
|
|
537
|
+
inputTokens: optionalFiniteNumber(value.input),
|
|
538
|
+
outputTokens: optionalFiniteNumber(value.output),
|
|
539
|
+
totalTokens: optionalFiniteNumber(value.total),
|
|
540
|
+
cacheReadTokens: optionalFiniteNumber(cache?.read),
|
|
541
|
+
cacheWriteTokens: optionalFiniteNumber(cache?.write),
|
|
542
|
+
};
|
|
543
|
+
return Object.values(usage).some((item) => item !== undefined) ? usage : undefined;
|
|
544
|
+
};
|
|
545
|
+
const normalizeErrorText = (value) => {
|
|
546
|
+
if (!isRecord(value)) {
|
|
547
|
+
return undefined;
|
|
548
|
+
}
|
|
549
|
+
const data = isRecord(value.data) ? value.data : undefined;
|
|
550
|
+
if (typeof data?.message === 'string') {
|
|
551
|
+
return truncateUtf8(data.message, maxToolPayloadBytes);
|
|
552
|
+
}
|
|
553
|
+
if (typeof value.message === 'string') {
|
|
554
|
+
return truncateUtf8(value.message, maxToolPayloadBytes);
|
|
555
|
+
}
|
|
556
|
+
if (typeof value.name === 'string') {
|
|
557
|
+
return truncateUtf8(value.name, maxTitleBytes);
|
|
558
|
+
}
|
|
559
|
+
return 'OpenCode reported an unspecified error.';
|
|
560
|
+
};
|
|
561
|
+
const normalizeReasoningPart = (value) => {
|
|
562
|
+
const time = isRecord(value.time) ? value.time : undefined;
|
|
563
|
+
return {
|
|
564
|
+
id: openCodeRuntimeId(requireString(value.id, 'reasoning part ID', maxIdentifierBytes)),
|
|
565
|
+
text: truncateUtf8(typeof value.text === 'string' ? value.text : '', maxMessageTextBytes),
|
|
566
|
+
startedAt: optionalFiniteNumber(time?.start),
|
|
567
|
+
endedAt: optionalFiniteNumber(time?.end),
|
|
568
|
+
};
|
|
569
|
+
};
|
|
570
|
+
const normalizeToolCall = (value) => {
|
|
571
|
+
if (!isRecord(value.state)) {
|
|
572
|
+
throw new Error('OpenCode returned an invalid tool state.');
|
|
573
|
+
}
|
|
574
|
+
const state = value.state;
|
|
575
|
+
const status = state.status;
|
|
576
|
+
if (status !== 'pending' && status !== 'running' && status !== 'completed' && status !== 'error') {
|
|
577
|
+
throw new Error('OpenCode returned an unknown tool state.');
|
|
578
|
+
}
|
|
579
|
+
const time = isRecord(state.time) ? state.time : undefined;
|
|
580
|
+
const stateMetadata = isRecord(state.metadata) ? state.metadata : undefined;
|
|
581
|
+
// Every tool call gets its own payload budget: one call's giant payload
|
|
582
|
+
// elides itself and can never starve the rest of the transcript.
|
|
583
|
+
const metadataBudget = {
|
|
584
|
+
nodesRemaining: maxMetadataNodes,
|
|
585
|
+
outputBudget: createOutputBudget(maxToolPayloadBytes * 2, 'tool payload'),
|
|
586
|
+
};
|
|
587
|
+
const sanitizePayload = (payload) => {
|
|
588
|
+
if (metadataBudget.outputBudget.bytesRemaining <= 0) {
|
|
589
|
+
return elidedPayloadNotice;
|
|
590
|
+
}
|
|
591
|
+
try {
|
|
592
|
+
return sanitizeUnknown(payload, metadataBudget);
|
|
593
|
+
}
|
|
594
|
+
catch {
|
|
595
|
+
// Structured payloads past the budget degrade like string payloads do.
|
|
596
|
+
return elidedPayloadNotice;
|
|
597
|
+
}
|
|
598
|
+
};
|
|
599
|
+
const rawOutput = state.output !== undefined
|
|
600
|
+
? state.output
|
|
601
|
+
: (status === 'running' || status === 'error') && typeof stateMetadata?.output === 'string'
|
|
602
|
+
? stateMetadata.output
|
|
603
|
+
: undefined;
|
|
604
|
+
const output = rawOutput === undefined
|
|
605
|
+
? undefined
|
|
606
|
+
: typeof rawOutput === 'string'
|
|
607
|
+
? truncateUtf8(rawOutput, maxToolPayloadBytes)
|
|
608
|
+
: sanitizePayload(rawOutput);
|
|
609
|
+
const exitCode = optionalNonNegativeSafeInteger(stateMetadata?.exit);
|
|
610
|
+
const childSessionId = typeof stateMetadata?.sessionId === 'string'
|
|
611
|
+
&& stateMetadata.sessionId.length > 0
|
|
612
|
+
&& Buffer.byteLength(stateMetadata.sessionId, 'utf8') <= maxIdentifierBytes
|
|
613
|
+
? openCodeRuntimeId(stateMetadata.sessionId)
|
|
614
|
+
: undefined;
|
|
615
|
+
// Subagent (task) calls report the model their child session runs on.
|
|
616
|
+
const childModel = isRecord(stateMetadata?.model)
|
|
617
|
+
? normalizeMessageModel(stateMetadata.model)
|
|
618
|
+
: undefined;
|
|
619
|
+
return {
|
|
620
|
+
id: openCodeRuntimeId(requireString(value.callID, 'tool call ID', maxIdentifierBytes)),
|
|
621
|
+
name: requireString(value.tool, 'tool name', maxTitleBytes),
|
|
622
|
+
status,
|
|
623
|
+
...(childSessionId === undefined ? {} : { childSessionId }),
|
|
624
|
+
...(childModel === undefined ? {} : { model: childModel }),
|
|
625
|
+
...(state.input === undefined ? {} : { input: sanitizePayload(state.input) }),
|
|
626
|
+
...(output === undefined ? {} : { output }),
|
|
627
|
+
...(exitCode === undefined ? {} : { exitCode }),
|
|
628
|
+
...(typeof state.error === 'string'
|
|
629
|
+
? { errorText: truncateUtf8(state.error, maxToolPayloadBytes) }
|
|
630
|
+
: {}),
|
|
631
|
+
startedAt: optionalFiniteNumber(time?.start),
|
|
632
|
+
finishedAt: optionalFiniteNumber(time?.end),
|
|
633
|
+
};
|
|
634
|
+
};
|
|
635
|
+
/**
|
|
636
|
+
* "providerID/modelID" for an assistant message, when OpenCode reported
|
|
637
|
+
* both. Malformed or oversized values are dropped rather than thrown on:
|
|
638
|
+
* the model label is display metadata and must never fail a transcript.
|
|
639
|
+
*/
|
|
640
|
+
const normalizeMessageModel = (info) => {
|
|
641
|
+
const providerId = info.providerID;
|
|
642
|
+
const modelId = info.modelID;
|
|
643
|
+
if (typeof providerId !== 'string' || typeof modelId !== 'string')
|
|
644
|
+
return undefined;
|
|
645
|
+
if (!providerId || !modelId)
|
|
646
|
+
return undefined;
|
|
647
|
+
const combined = `${providerId}/${modelId}`;
|
|
648
|
+
if (Buffer.byteLength(combined, 'utf8') > maxIdentifierBytes)
|
|
649
|
+
return undefined;
|
|
650
|
+
return combined;
|
|
651
|
+
};
|
|
652
|
+
/**
|
|
653
|
+
* The model variant (reasoning effort) an assistant message ran with, when
|
|
654
|
+
* OpenCode reported one. Display metadata: malformed values are dropped
|
|
655
|
+
* rather than thrown on.
|
|
656
|
+
*/
|
|
657
|
+
const normalizeMessageEffort = (info) => {
|
|
658
|
+
const variant = info.variant;
|
|
659
|
+
if (typeof variant !== 'string' || !variant)
|
|
660
|
+
return undefined;
|
|
661
|
+
if (Buffer.byteLength(variant, 'utf8') > maxTitleBytes)
|
|
662
|
+
return undefined;
|
|
663
|
+
return variant;
|
|
664
|
+
};
|
|
665
|
+
const normalizeOpenCodeMessageBundle = (bundle, aggregatePartCount, expectedSessionIdArg) => {
|
|
666
|
+
if (!isRecord(bundle) || !isRecord(bundle.info) || !Array.isArray(bundle.parts)) {
|
|
667
|
+
throw new Error('OpenCode returned an invalid message bundle.');
|
|
668
|
+
}
|
|
669
|
+
const info = bundle.info;
|
|
670
|
+
const sourceSessionId = requireString(info.sessionID, 'message session ID', maxIdentifierBytes);
|
|
671
|
+
if (expectedSessionIdArg !== undefined && sourceSessionId !== expectedSessionIdArg) {
|
|
672
|
+
throw new Error('OpenCode returned a message for the wrong session.');
|
|
673
|
+
}
|
|
674
|
+
const role = info.role;
|
|
675
|
+
if (role !== 'user' && role !== 'assistant') {
|
|
676
|
+
throw new Error('OpenCode returned an unknown message role.');
|
|
677
|
+
}
|
|
678
|
+
if (!isRecord(info.time)) {
|
|
679
|
+
throw new Error('OpenCode returned invalid message timing.');
|
|
680
|
+
}
|
|
681
|
+
const sourceMessageId = openCodeRuntimeId(requireString(info.id, 'message ID', maxIdentifierBytes));
|
|
682
|
+
const createdAt = requireFiniteNumber(info.time.created, 'message creation time');
|
|
683
|
+
const textParts = [];
|
|
684
|
+
let textBytes = 0;
|
|
685
|
+
const reasoningParts = [];
|
|
686
|
+
const toolParts = [];
|
|
687
|
+
if (bundle.parts.length > maxCollectionEntries) {
|
|
688
|
+
throw new Error('OpenCode returned too many message parts.');
|
|
689
|
+
}
|
|
690
|
+
aggregatePartCount.value += bundle.parts.length;
|
|
691
|
+
if (aggregatePartCount.value > maxMessagePartsPerResponse) {
|
|
692
|
+
throw new Error('OpenCode returned too many aggregate message parts.');
|
|
693
|
+
}
|
|
694
|
+
for (const part of bundle.parts) {
|
|
695
|
+
if (!isRecord(part) || typeof part.type !== 'string') {
|
|
696
|
+
throw new Error('OpenCode returned an invalid message part.');
|
|
697
|
+
}
|
|
698
|
+
if (requireString(part.sessionID, 'message part session ID', maxIdentifierBytes) !== sourceSessionId
|
|
699
|
+
|| requireString(part.messageID, 'message part message ID', maxIdentifierBytes)
|
|
700
|
+
!== sourceMessageId.nativeId) {
|
|
701
|
+
throw new Error('OpenCode returned a message part with mismatched ownership.');
|
|
702
|
+
}
|
|
703
|
+
if (part.type === 'text') {
|
|
704
|
+
if (typeof part.text !== 'string') {
|
|
705
|
+
throw new Error('OpenCode returned an invalid text part.');
|
|
706
|
+
}
|
|
707
|
+
if (part.ignored !== true) {
|
|
708
|
+
const separatorBytes = textParts.length > 0 ? 2 : 0;
|
|
709
|
+
const remainingTextBytes = Math.max(0, maxMessageTextBytes - textBytes - separatorBytes);
|
|
710
|
+
if (remainingTextBytes > 0) {
|
|
711
|
+
const normalizedTextPart = truncateUtf8(part.text, remainingTextBytes);
|
|
712
|
+
textParts.push(normalizedTextPart);
|
|
713
|
+
textBytes += separatorBytes + Buffer.byteLength(normalizedTextPart, 'utf8');
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
else if (part.type === 'reasoning') {
|
|
718
|
+
reasoningParts.push(normalizeReasoningPart(part));
|
|
719
|
+
}
|
|
720
|
+
else if (part.type === 'tool') {
|
|
721
|
+
toolParts.push({
|
|
722
|
+
part,
|
|
723
|
+
call: normalizeToolCall(part),
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
// One message's reasoning is capped as a whole: parts past the cap elide
|
|
728
|
+
// individually so a marathon trace cannot dominate the transcript.
|
|
729
|
+
let reasoningBytesRemaining = maxPerMessageReasoningBytes;
|
|
730
|
+
for (const reasoningPart of reasoningParts) {
|
|
731
|
+
const partBytes = Buffer.byteLength(reasoningPart.text, 'utf8');
|
|
732
|
+
if (partBytes <= reasoningBytesRemaining) {
|
|
733
|
+
reasoningBytesRemaining -= partBytes;
|
|
734
|
+
}
|
|
735
|
+
else {
|
|
736
|
+
reasoningPart.text = elidedPayloadNotice;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
const completedAt = optionalFiniteNumber(info.time.completed);
|
|
740
|
+
const errorText = normalizeErrorText(info.error);
|
|
741
|
+
const usage = normalizeUsage(info.tokens);
|
|
742
|
+
// Assistant messages carry the model that produced them, so a transcript
|
|
743
|
+
// shows exactly which model answered — including after a mid-chat switch.
|
|
744
|
+
const model = normalizeMessageModel(info);
|
|
745
|
+
const effort = normalizeMessageEffort(info);
|
|
746
|
+
const messages = [{
|
|
747
|
+
id: sourceMessageId,
|
|
748
|
+
role,
|
|
749
|
+
text: textParts.join('\n\n'),
|
|
750
|
+
createdAt,
|
|
751
|
+
...(completedAt === undefined ? {} : { updatedAt: completedAt }),
|
|
752
|
+
...(role === 'assistant' ? { streaming: completedAt === undefined } : {}),
|
|
753
|
+
...(reasoningParts.length > 0 ? { reasoning: reasoningParts } : {}),
|
|
754
|
+
...(usage ? { usage } : {}),
|
|
755
|
+
...(errorText ? { error: errorText } : {}),
|
|
756
|
+
...(model ? { model } : {}),
|
|
757
|
+
...(effort ? { effort } : {}),
|
|
758
|
+
}];
|
|
759
|
+
for (const toolPart of toolParts) {
|
|
760
|
+
const state = toolPart.part.state;
|
|
761
|
+
const stateTime = isRecord(state) && isRecord(state.time) ? state.time : undefined;
|
|
762
|
+
const toolMessageId = openCodeRuntimeId(requireString(toolPart.part.id, 'tool part ID', maxIdentifierBytes));
|
|
763
|
+
messages.push({
|
|
764
|
+
id: toolMessageId,
|
|
765
|
+
role: 'tool',
|
|
766
|
+
text: '',
|
|
767
|
+
createdAt: optionalFiniteNumber(stateTime?.start) ?? createdAt,
|
|
768
|
+
updatedAt: optionalFiniteNumber(stateTime?.end),
|
|
769
|
+
streaming: toolPart.call.status === 'pending' || toolPart.call.status === 'running',
|
|
770
|
+
toolCall: toolPart.call,
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
const structuralDigest = plugins.crypto
|
|
774
|
+
.createHash('sha256')
|
|
775
|
+
.update(JSON.stringify({
|
|
776
|
+
sourceMessageId: controllerRuntimeIdKey(sourceMessageId),
|
|
777
|
+
entries: messages.map((message) => ({
|
|
778
|
+
id: controllerRuntimeIdKey(message.id),
|
|
779
|
+
type: message.role,
|
|
780
|
+
})),
|
|
781
|
+
}))
|
|
782
|
+
.digest('hex');
|
|
783
|
+
return {
|
|
784
|
+
sourceMessageId,
|
|
785
|
+
structuralDigest,
|
|
786
|
+
sourceRole: role,
|
|
787
|
+
...(role === 'assistant' && typeof info.parentID === 'string'
|
|
788
|
+
? {
|
|
789
|
+
parentMessageId: openCodeRuntimeId(requireString(info.parentID, 'assistant parent message ID', maxIdentifierBytes)),
|
|
790
|
+
}
|
|
791
|
+
: {}),
|
|
792
|
+
terminal: role === 'user' || completedAt !== undefined || info.error !== undefined,
|
|
793
|
+
messages,
|
|
794
|
+
};
|
|
795
|
+
};
|
|
796
|
+
const normalizeOpenCodeMessageBundlesWithPartCount = (value, expectedSessionIdArg, aggregatePartCount) => {
|
|
797
|
+
if (!Array.isArray(value)) {
|
|
798
|
+
throw new Error('OpenCode returned an invalid message list.');
|
|
799
|
+
}
|
|
800
|
+
if (value.length > maxMessagesPerRequest) {
|
|
801
|
+
throw new Error('OpenCode returned too many messages in one response.');
|
|
802
|
+
}
|
|
803
|
+
const result = [];
|
|
804
|
+
for (const bundle of value) {
|
|
805
|
+
result.push(normalizeOpenCodeMessageBundle(bundle, aggregatePartCount, expectedSessionIdArg));
|
|
806
|
+
}
|
|
807
|
+
return result;
|
|
808
|
+
};
|
|
809
|
+
export const normalizeOpenCodeMessageBundles = (value, expectedSessionIdArg) => normalizeOpenCodeMessageBundlesWithPartCount(value, expectedSessionIdArg, { value: 0 });
|
|
810
|
+
export const normalizeOpenCodeMessages = (value, expectedSessionIdArg) => {
|
|
811
|
+
const result = normalizeOpenCodeMessageBundles(value, expectedSessionIdArg)
|
|
812
|
+
.flatMap((bundle) => bundle.messages);
|
|
813
|
+
// A transcript never fails over its size: the oldest entries drop first.
|
|
814
|
+
return trimOldestMessagesToFit(result, maxNormalizedMessageBytes);
|
|
815
|
+
};
|
|
816
|
+
export const mergeOpenCodeToolExecutionsIntoDetail = (detailArg, executionsArg) => {
|
|
817
|
+
const messages = detailArg.messages.map((messageArg) => ({ ...messageArg }));
|
|
818
|
+
for (const execution of executionsArg) {
|
|
819
|
+
const { sessionId: _sessionId, messageId: _messageId, partId, callId, toolName, order, sourceUpdatedAt, revision: _revision, streamEpoch: _streamEpoch, ...state } = execution;
|
|
820
|
+
const toolCall = {
|
|
821
|
+
id: callId,
|
|
822
|
+
name: toolName,
|
|
823
|
+
...state,
|
|
824
|
+
};
|
|
825
|
+
const existingIndex = messages.findIndex((messageArg) => (controllerRuntimeIdsEqual(messageArg.id, partId)));
|
|
826
|
+
if (existingIndex >= 0) {
|
|
827
|
+
const existingCall = messages[existingIndex].toolCall;
|
|
828
|
+
if (existingCall) {
|
|
829
|
+
const existingTerminal = existingCall.status === 'completed'
|
|
830
|
+
|| existingCall.status === 'error';
|
|
831
|
+
if (existingTerminal) {
|
|
832
|
+
if (controllerRuntimeIdsEqual(existingCall.id, execution.callId)
|
|
833
|
+
&& existingCall.name === execution.toolName
|
|
834
|
+
&& existingCall.status === execution.status
|
|
835
|
+
&& (execution.finishedAt === undefined
|
|
836
|
+
|| (existingCall.finishedAt !== undefined
|
|
837
|
+
&& existingCall.finishedAt >= execution.finishedAt))) {
|
|
838
|
+
messages[existingIndex] = {
|
|
839
|
+
...messages[existingIndex],
|
|
840
|
+
toolCall: {
|
|
841
|
+
...existingCall,
|
|
842
|
+
...(existingCall.input === undefined && toolCall.input !== undefined
|
|
843
|
+
? { input: toolCall.input }
|
|
844
|
+
: {}),
|
|
845
|
+
...(existingCall.output === undefined && toolCall.output !== undefined
|
|
846
|
+
? { output: toolCall.output }
|
|
847
|
+
: {}),
|
|
848
|
+
...(existingCall.errorText === undefined && toolCall.errorText !== undefined
|
|
849
|
+
? { errorText: toolCall.errorText }
|
|
850
|
+
: {}),
|
|
851
|
+
...(existingCall.exitCode === undefined && toolCall.exitCode !== undefined
|
|
852
|
+
? { exitCode: toolCall.exitCode }
|
|
853
|
+
: {}),
|
|
854
|
+
...(existingCall.startedAt === undefined && toolCall.startedAt !== undefined
|
|
855
|
+
? { startedAt: toolCall.startedAt }
|
|
856
|
+
: {}),
|
|
857
|
+
...(existingCall.finishedAt === undefined && toolCall.finishedAt !== undefined
|
|
858
|
+
? { finishedAt: toolCall.finishedAt }
|
|
859
|
+
: {}),
|
|
860
|
+
...(existingCall.childSessionId === undefined && toolCall.childSessionId !== undefined
|
|
861
|
+
? { childSessionId: toolCall.childSessionId }
|
|
862
|
+
: {}),
|
|
863
|
+
...(existingCall.model === undefined && toolCall.model !== undefined
|
|
864
|
+
? { model: toolCall.model }
|
|
865
|
+
: {}),
|
|
866
|
+
},
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
continue;
|
|
870
|
+
}
|
|
871
|
+
if (existingCall.status === 'running' && execution.status === 'pending')
|
|
872
|
+
continue;
|
|
873
|
+
const existingSourceTime = existingCall.finishedAt ?? existingCall.startedAt ?? 0;
|
|
874
|
+
if (sourceUpdatedAt < existingSourceTime)
|
|
875
|
+
continue;
|
|
876
|
+
}
|
|
877
|
+
messages[existingIndex] = {
|
|
878
|
+
...messages[existingIndex],
|
|
879
|
+
...(order === undefined ? {} : { order }),
|
|
880
|
+
toolCall,
|
|
881
|
+
};
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
884
|
+
messages.push({
|
|
885
|
+
id: partId,
|
|
886
|
+
role: 'tool',
|
|
887
|
+
text: '',
|
|
888
|
+
createdAt: execution.startedAt ?? sourceUpdatedAt,
|
|
889
|
+
...(order === undefined ? {} : { order }),
|
|
890
|
+
...(execution.finishedAt === undefined ? {} : { updatedAt: execution.finishedAt }),
|
|
891
|
+
toolCall,
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
const detailWithoutMessages = { ...detailArg, messages: [] };
|
|
895
|
+
const otherPartsBytes = Buffer.byteLength(JSON.stringify(detailWithoutMessages), 'utf8');
|
|
896
|
+
const boundedMessages = trimOldestMessagesToFit(messages, Math.max(64 * 1024, maxNormalizedSessionDetailBytes - otherPartsBytes));
|
|
897
|
+
const result = { ...detailArg, messages: boundedMessages };
|
|
898
|
+
assertSerializedOutputWithinLimit(result, maxNormalizedSessionDetailBytes + 64 * 1024, 'session detail with live tool snapshots');
|
|
899
|
+
return result;
|
|
900
|
+
};
|
|
901
|
+
export const createBoundedOpenCodeSelectedMessageSlice = (messagesArg) => {
|
|
902
|
+
if (messagesArg.length > maxMessagesPerPage) {
|
|
903
|
+
throw new Error(`An OpenCode message slice cannot exceed ${maxMessagesPerPage} entries.`);
|
|
904
|
+
}
|
|
905
|
+
const messages = messagesArg.map((message) => ({
|
|
906
|
+
...message,
|
|
907
|
+
...(message.reasoning
|
|
908
|
+
? { reasoning: message.reasoning.map((reasoningPart) => ({ ...reasoningPart })) }
|
|
909
|
+
: {}),
|
|
910
|
+
...(message.toolCall ? { toolCall: { ...message.toolCall } } : {}),
|
|
911
|
+
}));
|
|
912
|
+
const isWithinBudget = () => Buffer.byteLength(JSON.stringify(messages), 'utf8') <= maxNormalizedMessageBytes;
|
|
913
|
+
if (isWithinBudget())
|
|
914
|
+
return messages;
|
|
915
|
+
// Preserve every selected shell and its order. Payloads disappear from the
|
|
916
|
+
// oldest entries first until the selected slice fits the transfer budget.
|
|
917
|
+
for (const message of messages) {
|
|
918
|
+
if (message.toolCall && Object.hasOwn(message.toolCall, 'input')) {
|
|
919
|
+
delete message.toolCall.input;
|
|
920
|
+
if (isWithinBudget())
|
|
921
|
+
return messages;
|
|
922
|
+
}
|
|
923
|
+
if (message.toolCall && Object.hasOwn(message.toolCall, 'output')) {
|
|
924
|
+
delete message.toolCall.output;
|
|
925
|
+
if (isWithinBudget())
|
|
926
|
+
return messages;
|
|
927
|
+
}
|
|
928
|
+
if (message.reasoning) {
|
|
929
|
+
for (const reasoningPart of message.reasoning) {
|
|
930
|
+
if (!reasoningPart.text)
|
|
931
|
+
continue;
|
|
932
|
+
reasoningPart.text = '';
|
|
933
|
+
if (isWithinBudget())
|
|
934
|
+
return messages;
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
if (message.text) {
|
|
938
|
+
message.text = '';
|
|
939
|
+
if (isWithinBudget())
|
|
940
|
+
return messages;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
throw new Error('Selected OpenCode message shells exceeded the aggregate output budget.');
|
|
944
|
+
};
|
|
945
|
+
export const normalizeOpenCodePermissions = (value) => {
|
|
946
|
+
if (!Array.isArray(value) || value.length > maxCollectionEntries) {
|
|
947
|
+
throw new Error('OpenCode returned an invalid permission list.');
|
|
948
|
+
}
|
|
949
|
+
const outputBudget = createOutputBudget(maxNormalizedPermissionBytes, 'permissions');
|
|
950
|
+
const metadataBudget = {
|
|
951
|
+
nodesRemaining: maxMetadataNodes,
|
|
952
|
+
outputBudget,
|
|
953
|
+
};
|
|
954
|
+
const result = value.map((permission) => {
|
|
955
|
+
if (!isRecord(permission) || !Array.isArray(permission.patterns)) {
|
|
956
|
+
throw new Error('OpenCode returned an invalid permission request.');
|
|
957
|
+
}
|
|
958
|
+
if (permission.patterns.length > maxCollectionEntries) {
|
|
959
|
+
throw new Error('OpenCode returned too many permission patterns.');
|
|
960
|
+
}
|
|
961
|
+
consumeOutputBytes(outputBudget, normalizedNodeCostBytes);
|
|
962
|
+
const type = consumeOutputString(outputBudget, requireString(permission.permission, 'permission type', maxTitleBytes));
|
|
963
|
+
const patterns = permission.patterns.map((pattern) => consumeOutputString(outputBudget, requireString(pattern, 'permission pattern', maxMetadataStringBytes)));
|
|
964
|
+
const id = consumeOutputString(outputBudget, requireString(permission.id, 'permission ID', maxIdentifierBytes));
|
|
965
|
+
const sessionId = consumeOutputString(outputBudget, requireString(permission.sessionID, 'permission session ID', maxIdentifierBytes));
|
|
966
|
+
return {
|
|
967
|
+
id: openCodeRuntimeId(id),
|
|
968
|
+
sessionId: openCodeRuntimeId(sessionId),
|
|
969
|
+
title: type,
|
|
970
|
+
type,
|
|
971
|
+
patterns,
|
|
972
|
+
metadata: sanitizeRecord(permission.metadata, 'permission metadata', metadataBudget),
|
|
973
|
+
};
|
|
974
|
+
});
|
|
975
|
+
assertSerializedOutputWithinLimit(result, maxNormalizedPermissionBytes, 'permissions');
|
|
976
|
+
return result;
|
|
977
|
+
};
|
|
978
|
+
export const normalizeOpenCodeQuestions = (value) => {
|
|
979
|
+
if (!Array.isArray(value) || value.length > maxCollectionEntries) {
|
|
980
|
+
throw new Error('OpenCode returned an invalid question list.');
|
|
981
|
+
}
|
|
982
|
+
const outputBudget = createOutputBudget(maxNormalizedQuestionBytes, 'questions');
|
|
983
|
+
const result = value.map((request) => {
|
|
984
|
+
if (!isRecord(request) || !Array.isArray(request.questions)) {
|
|
985
|
+
throw new Error('OpenCode returned an invalid question request.');
|
|
986
|
+
}
|
|
987
|
+
if (request.questions.length === 0 || request.questions.length > maxQuestionsPerRequest) {
|
|
988
|
+
throw new Error('OpenCode returned an unsupported question count.');
|
|
989
|
+
}
|
|
990
|
+
consumeOutputBytes(outputBudget, normalizedNodeCostBytes);
|
|
991
|
+
const questions = request.questions.map((question) => {
|
|
992
|
+
if (!isRecord(question) || !Array.isArray(question.options)) {
|
|
993
|
+
throw new Error('OpenCode returned an invalid question.');
|
|
994
|
+
}
|
|
995
|
+
if (question.options.length > maxOptionsPerQuestion) {
|
|
996
|
+
throw new Error('OpenCode returned too many question options.');
|
|
997
|
+
}
|
|
998
|
+
consumeOutputBytes(outputBudget, normalizedNodeCostBytes);
|
|
999
|
+
const options = question.options.map((option) => {
|
|
1000
|
+
if (!isRecord(option)) {
|
|
1001
|
+
throw new Error('OpenCode returned an invalid question option.');
|
|
1002
|
+
}
|
|
1003
|
+
consumeOutputBytes(outputBudget, normalizedNodeCostBytes);
|
|
1004
|
+
return {
|
|
1005
|
+
label: consumeOutputString(outputBudget, requireString(option.label, 'question option label', maxTitleBytes)),
|
|
1006
|
+
description: consumeOutputString(outputBudget, truncateUtf8(requireString(option.description, 'question option description', maxMetadataStringBytes), maxTitleBytes)),
|
|
1007
|
+
};
|
|
1008
|
+
});
|
|
1009
|
+
return {
|
|
1010
|
+
question: consumeOutputString(outputBudget, truncateUtf8(requireString(question.question, 'question text', maxMessageTextBytes), maxMetadataStringBytes)),
|
|
1011
|
+
header: consumeOutputString(outputBudget, requireString(question.header, 'question header', maxTitleBytes)),
|
|
1012
|
+
options,
|
|
1013
|
+
// An explicit false matters downstream: the UI hides free-text input
|
|
1014
|
+
// only when custom answers are explicitly disallowed.
|
|
1015
|
+
...(typeof question.multiple === 'boolean' ? { multiple: question.multiple } : {}),
|
|
1016
|
+
...(typeof question.custom === 'boolean' ? { custom: question.custom } : {}),
|
|
1017
|
+
};
|
|
1018
|
+
});
|
|
1019
|
+
const toolCallId = isRecord(request.tool) && typeof request.tool.callID === 'string'
|
|
1020
|
+
? openCodeRuntimeId(consumeOutputString(outputBudget, requireString(request.tool.callID, 'question tool call ID', maxIdentifierBytes)))
|
|
1021
|
+
: undefined;
|
|
1022
|
+
const id = consumeOutputString(outputBudget, requireString(request.id, 'question request ID', maxIdentifierBytes));
|
|
1023
|
+
const sessionId = consumeOutputString(outputBudget, requireString(request.sessionID, 'question session ID', maxIdentifierBytes));
|
|
1024
|
+
return {
|
|
1025
|
+
id: openCodeRuntimeId(id),
|
|
1026
|
+
sessionId: openCodeRuntimeId(sessionId),
|
|
1027
|
+
questions,
|
|
1028
|
+
...(toolCallId === undefined ? {} : { toolCallId }),
|
|
1029
|
+
};
|
|
1030
|
+
});
|
|
1031
|
+
assertSerializedOutputWithinLimit(result, maxNormalizedQuestionBytes, 'questions');
|
|
1032
|
+
return result;
|
|
1033
|
+
};
|
|
1034
|
+
export const normalizeOpenCodePtys = (value) => {
|
|
1035
|
+
if (!Array.isArray(value) || value.length > maxCollectionEntries) {
|
|
1036
|
+
throw new Error('OpenCode returned an invalid PTY list.');
|
|
1037
|
+
}
|
|
1038
|
+
return value.map((pty) => {
|
|
1039
|
+
if (!isRecord(pty)) {
|
|
1040
|
+
throw new Error('OpenCode returned an invalid PTY session.');
|
|
1041
|
+
}
|
|
1042
|
+
return {
|
|
1043
|
+
id: requireString(pty.id, 'PTY ID', maxIdentifierBytes),
|
|
1044
|
+
title: truncateUtf8(requireString(pty.title, 'PTY title', maxMetadataStringBytes), maxTitleBytes),
|
|
1045
|
+
command: truncateUtf8(requireString(pty.command, 'PTY command', maxMetadataStringBytes), maxTitleBytes),
|
|
1046
|
+
cwd: requireString(pty.cwd, 'PTY cwd', 4096),
|
|
1047
|
+
};
|
|
1048
|
+
});
|
|
1049
|
+
};
|
|
1050
|
+
export const normalizeOpenCodeTodos = (value) => {
|
|
1051
|
+
if (!Array.isArray(value) || value.length > maxCollectionEntries) {
|
|
1052
|
+
throw new Error('OpenCode returned an invalid todo list.');
|
|
1053
|
+
}
|
|
1054
|
+
return value.map((todo) => {
|
|
1055
|
+
if (!isRecord(todo)) {
|
|
1056
|
+
throw new Error('OpenCode returned an invalid todo.');
|
|
1057
|
+
}
|
|
1058
|
+
const status = todo.status;
|
|
1059
|
+
if (status !== 'pending' &&
|
|
1060
|
+
status !== 'in_progress' &&
|
|
1061
|
+
status !== 'completed' &&
|
|
1062
|
+
status !== 'cancelled') {
|
|
1063
|
+
throw new Error('OpenCode returned an unknown todo status.');
|
|
1064
|
+
}
|
|
1065
|
+
const id = todo.id === undefined
|
|
1066
|
+
? undefined
|
|
1067
|
+
: openCodeRuntimeId(requireString(todo.id, 'todo ID', maxIdentifierBytes));
|
|
1068
|
+
return {
|
|
1069
|
+
...(id === undefined ? {} : { id }),
|
|
1070
|
+
content: truncateUtf8(requireString(todo.content, 'todo content', maxMessageTextBytes), maxTitleBytes),
|
|
1071
|
+
status: status,
|
|
1072
|
+
};
|
|
1073
|
+
});
|
|
1074
|
+
};
|
|
1075
|
+
const normalizeLiveToolExecution = (partArg, expectedSessionIdArg, eventTimeArg) => {
|
|
1076
|
+
if (partArg.type !== 'tool') {
|
|
1077
|
+
throw new Error('OpenCode returned a non-tool part for live tool normalization.');
|
|
1078
|
+
}
|
|
1079
|
+
const nativeSessionId = requireString(partArg.sessionID, 'live tool session ID', maxIdentifierBytes);
|
|
1080
|
+
if (nativeSessionId !== expectedSessionIdArg) {
|
|
1081
|
+
throw new Error('OpenCode returned a live tool part for the wrong session.');
|
|
1082
|
+
}
|
|
1083
|
+
const sessionId = openCodeRuntimeId(nativeSessionId);
|
|
1084
|
+
const messageId = openCodeRuntimeId(requireString(partArg.messageID, 'live tool message ID', maxIdentifierBytes));
|
|
1085
|
+
const partId = openCodeRuntimeId(requireString(partArg.id, 'live tool part ID', maxIdentifierBytes));
|
|
1086
|
+
const call = normalizeToolCall(partArg);
|
|
1087
|
+
const sourceUpdatedAt = optionalFiniteNumber(eventTimeArg)
|
|
1088
|
+
?? call.finishedAt
|
|
1089
|
+
?? call.startedAt
|
|
1090
|
+
?? Date.now();
|
|
1091
|
+
const { id: callId, name: toolName, ...state } = call;
|
|
1092
|
+
const result = {
|
|
1093
|
+
sessionId,
|
|
1094
|
+
messageId,
|
|
1095
|
+
partId,
|
|
1096
|
+
callId,
|
|
1097
|
+
toolName,
|
|
1098
|
+
...state,
|
|
1099
|
+
sourceUpdatedAt,
|
|
1100
|
+
};
|
|
1101
|
+
const serializedBytes = () => Buffer.byteLength(JSON.stringify(result), 'utf8');
|
|
1102
|
+
if (serializedBytes() <= maxLiveToolExecutionBytes)
|
|
1103
|
+
return result;
|
|
1104
|
+
if (result.input !== undefined)
|
|
1105
|
+
result.input = elidedPayloadNotice;
|
|
1106
|
+
if (serializedBytes() <= maxLiveToolExecutionBytes)
|
|
1107
|
+
return result;
|
|
1108
|
+
if (result.errorText !== undefined) {
|
|
1109
|
+
result.errorText = truncateUtf8(result.errorText, 4 * 1024);
|
|
1110
|
+
}
|
|
1111
|
+
if (serializedBytes() <= maxLiveToolExecutionBytes)
|
|
1112
|
+
return result;
|
|
1113
|
+
if (result.output !== undefined && typeof result.output !== 'string') {
|
|
1114
|
+
result.output = elidedPayloadNotice;
|
|
1115
|
+
}
|
|
1116
|
+
if (serializedBytes() <= maxLiveToolExecutionBytes)
|
|
1117
|
+
return result;
|
|
1118
|
+
if (typeof result.output === 'string') {
|
|
1119
|
+
const originalOutput = result.output;
|
|
1120
|
+
let lowerBound = 0;
|
|
1121
|
+
let upperBound = Buffer.byteLength(originalOutput, 'utf8');
|
|
1122
|
+
let fittedOutput = '';
|
|
1123
|
+
while (lowerBound <= upperBound) {
|
|
1124
|
+
const candidateLimit = Math.floor((lowerBound + upperBound) / 2);
|
|
1125
|
+
const candidateOutput = truncateUtf8(originalOutput, candidateLimit);
|
|
1126
|
+
result.output = candidateOutput;
|
|
1127
|
+
if (serializedBytes() <= maxLiveToolExecutionBytes) {
|
|
1128
|
+
fittedOutput = candidateOutput;
|
|
1129
|
+
lowerBound = candidateLimit + 1;
|
|
1130
|
+
}
|
|
1131
|
+
else {
|
|
1132
|
+
upperBound = candidateLimit - 1;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
result.output = fittedOutput;
|
|
1136
|
+
}
|
|
1137
|
+
if (serializedBytes() <= maxLiveToolExecutionBytes)
|
|
1138
|
+
return result;
|
|
1139
|
+
throw new Error('OpenCode returned a live tool execution that exceeded its transfer budget.');
|
|
1140
|
+
};
|
|
1141
|
+
const messageStreamEventSessionId = (valueArg) => {
|
|
1142
|
+
if (!isRecord(valueArg) || !isRecord(valueArg.payload) || !isRecord(valueArg.payload.properties)) {
|
|
1143
|
+
return undefined;
|
|
1144
|
+
}
|
|
1145
|
+
const type = valueArg.payload.type;
|
|
1146
|
+
if (type !== 'message.part.updated'
|
|
1147
|
+
&& type !== 'message.part.delta'
|
|
1148
|
+
&& type !== 'message.part.removed'
|
|
1149
|
+
&& type !== 'message.removed')
|
|
1150
|
+
return undefined;
|
|
1151
|
+
const sessionId = valueArg.payload.properties.sessionID;
|
|
1152
|
+
return typeof sessionId === 'string' ? sessionId : undefined;
|
|
1153
|
+
};
|
|
1154
|
+
const normalizeEvent = (value) => {
|
|
1155
|
+
if (!isRecord(value)
|
|
1156
|
+
|| typeof value.directory !== 'string'
|
|
1157
|
+
|| value.directory.length === 0
|
|
1158
|
+
|| Buffer.byteLength(value.directory, 'utf8') > 4096
|
|
1159
|
+
|| !isRecord(value.payload)) {
|
|
1160
|
+
return undefined;
|
|
1161
|
+
}
|
|
1162
|
+
const directory = value.directory;
|
|
1163
|
+
const payload = value.payload;
|
|
1164
|
+
if (typeof payload.type !== 'string') {
|
|
1165
|
+
return undefined;
|
|
1166
|
+
}
|
|
1167
|
+
if (!isRecord(payload.properties))
|
|
1168
|
+
return undefined;
|
|
1169
|
+
const properties = payload.properties;
|
|
1170
|
+
if (payload.type === 'message.updated' && isRecord(properties.info)) {
|
|
1171
|
+
const info = properties.info;
|
|
1172
|
+
try {
|
|
1173
|
+
const role = info.role;
|
|
1174
|
+
if (role !== 'user' && role !== 'assistant')
|
|
1175
|
+
return undefined;
|
|
1176
|
+
const sessionId = openCodeRuntimeId(requireString(info.sessionID, 'live message session ID', maxIdentifierBytes));
|
|
1177
|
+
const messageId = openCodeRuntimeId(requireString(info.id, 'live message ID', maxIdentifierBytes));
|
|
1178
|
+
const parentMessageId = role === 'assistant'
|
|
1179
|
+
? openCodeRuntimeId(requireString(info.parentID, 'live assistant parent message ID', maxIdentifierBytes))
|
|
1180
|
+
: undefined;
|
|
1181
|
+
const terminal = role === 'user'
|
|
1182
|
+
|| (isRecord(info.time) && optionalFiniteNumber(info.time.completed) !== undefined)
|
|
1183
|
+
|| info.error !== undefined;
|
|
1184
|
+
return {
|
|
1185
|
+
directory,
|
|
1186
|
+
messageLifecycle: {
|
|
1187
|
+
sessionId,
|
|
1188
|
+
messageId,
|
|
1189
|
+
role,
|
|
1190
|
+
...(parentMessageId === undefined ? {} : { parentMessageId }),
|
|
1191
|
+
terminal,
|
|
1192
|
+
},
|
|
1193
|
+
event: {
|
|
1194
|
+
type: 'session.changed',
|
|
1195
|
+
harnessId: openCodeHarnessId,
|
|
1196
|
+
sessionId,
|
|
1197
|
+
timestamp: Date.now(),
|
|
1198
|
+
},
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
catch {
|
|
1202
|
+
return undefined;
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
if (payload.type === 'message.part.updated') {
|
|
1206
|
+
if (!isRecord(properties.part))
|
|
1207
|
+
return { directory, toolStreamGap: true };
|
|
1208
|
+
if (properties.part.type === 'tool') {
|
|
1209
|
+
try {
|
|
1210
|
+
const nativeSessionId = requireString(properties.sessionID, 'live tool event session ID', maxIdentifierBytes);
|
|
1211
|
+
const timestamp = optionalFiniteNumber(properties.time) ?? Date.now();
|
|
1212
|
+
return {
|
|
1213
|
+
directory,
|
|
1214
|
+
toolExecution: normalizeLiveToolExecution(properties.part, nativeSessionId, properties.time),
|
|
1215
|
+
timestamp,
|
|
1216
|
+
};
|
|
1217
|
+
}
|
|
1218
|
+
catch {
|
|
1219
|
+
return { directory, toolStreamGap: true };
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
const sessionId = typeof properties.sessionID === 'string' &&
|
|
1224
|
+
properties.sessionID.length > 0 &&
|
|
1225
|
+
Buffer.byteLength(properties.sessionID, 'utf8') <= maxIdentifierBytes
|
|
1226
|
+
? openCodeRuntimeId(properties.sessionID)
|
|
1227
|
+
: undefined;
|
|
1228
|
+
if (sessionId && payload.type === 'session.status') {
|
|
1229
|
+
return {
|
|
1230
|
+
directory,
|
|
1231
|
+
event: {
|
|
1232
|
+
type: 'session.changed',
|
|
1233
|
+
harnessId: openCodeHarnessId,
|
|
1234
|
+
sessionId,
|
|
1235
|
+
sessionStatus: normalizeSessionStatus(properties.status),
|
|
1236
|
+
timestamp: Date.now(),
|
|
1237
|
+
},
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
if (sessionId && payload.type === 'session.idle') {
|
|
1241
|
+
return {
|
|
1242
|
+
directory,
|
|
1243
|
+
event: {
|
|
1244
|
+
type: 'session.changed',
|
|
1245
|
+
harnessId: openCodeHarnessId,
|
|
1246
|
+
sessionId,
|
|
1247
|
+
sessionStatus: 'idle',
|
|
1248
|
+
timestamp: Date.now(),
|
|
1249
|
+
},
|
|
1250
|
+
};
|
|
1251
|
+
}
|
|
1252
|
+
if (sessionId && payload.type === 'session.error') {
|
|
1253
|
+
return {
|
|
1254
|
+
directory,
|
|
1255
|
+
event: {
|
|
1256
|
+
type: 'session.changed',
|
|
1257
|
+
harnessId: openCodeHarnessId,
|
|
1258
|
+
sessionId,
|
|
1259
|
+
sessionError: true,
|
|
1260
|
+
timestamp: Date.now(),
|
|
1261
|
+
},
|
|
1262
|
+
};
|
|
1263
|
+
}
|
|
1264
|
+
if (sessionId
|
|
1265
|
+
&& (payload.type === 'session.created'
|
|
1266
|
+
|| payload.type === 'session.updated'
|
|
1267
|
+
|| payload.type === 'session.deleted')) {
|
|
1268
|
+
return {
|
|
1269
|
+
directory,
|
|
1270
|
+
event: {
|
|
1271
|
+
type: 'sessions.changed',
|
|
1272
|
+
harnessId: openCodeHarnessId,
|
|
1273
|
+
sessionId,
|
|
1274
|
+
timestamp: Date.now(),
|
|
1275
|
+
},
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
if (sessionId && payload.type.startsWith('permission.')) {
|
|
1279
|
+
return {
|
|
1280
|
+
directory,
|
|
1281
|
+
event: {
|
|
1282
|
+
type: 'permissions.changed',
|
|
1283
|
+
harnessId: openCodeHarnessId,
|
|
1284
|
+
sessionId,
|
|
1285
|
+
timestamp: Date.now(),
|
|
1286
|
+
},
|
|
1287
|
+
};
|
|
1288
|
+
}
|
|
1289
|
+
if (sessionId &&
|
|
1290
|
+
(payload.type.startsWith('message.') ||
|
|
1291
|
+
payload.type.startsWith('session.') ||
|
|
1292
|
+
payload.type === 'todo.updated' ||
|
|
1293
|
+
payload.type.startsWith('question.') ||
|
|
1294
|
+
payload.type === 'command.executed')) {
|
|
1295
|
+
return {
|
|
1296
|
+
directory,
|
|
1297
|
+
event: {
|
|
1298
|
+
type: 'session.changed',
|
|
1299
|
+
harnessId: openCodeHarnessId,
|
|
1300
|
+
sessionId,
|
|
1301
|
+
timestamp: Date.now(),
|
|
1302
|
+
},
|
|
1303
|
+
};
|
|
1304
|
+
}
|
|
1305
|
+
if (payload.type.startsWith('installation.') ||
|
|
1306
|
+
payload.type === 'server.connected' ||
|
|
1307
|
+
payload.type === 'global.disposed' ||
|
|
1308
|
+
payload.type === 'server.instance.disposed') {
|
|
1309
|
+
return {
|
|
1310
|
+
directory,
|
|
1311
|
+
event: {
|
|
1312
|
+
type: 'harness.changed',
|
|
1313
|
+
harnessId: openCodeHarnessId,
|
|
1314
|
+
timestamp: Date.now(),
|
|
1315
|
+
},
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1318
|
+
return undefined;
|
|
1319
|
+
};
|
|
1320
|
+
const asError = (value, message) => {
|
|
1321
|
+
if (value instanceof Error) {
|
|
1322
|
+
return value;
|
|
1323
|
+
}
|
|
1324
|
+
return new Error(message, { cause: value });
|
|
1325
|
+
};
|
|
1326
|
+
const waitForAbortableDelay = async (delayMsArg, signalArg) => {
|
|
1327
|
+
if (signalArg.aborted)
|
|
1328
|
+
return;
|
|
1329
|
+
await new Promise((resolve) => {
|
|
1330
|
+
const finish = () => {
|
|
1331
|
+
clearTimeout(timer);
|
|
1332
|
+
signalArg.removeEventListener('abort', finish);
|
|
1333
|
+
resolve();
|
|
1334
|
+
};
|
|
1335
|
+
const timer = setTimeout(finish, delayMsArg);
|
|
1336
|
+
signalArg.addEventListener('abort', finish, { once: true });
|
|
1337
|
+
});
|
|
1338
|
+
};
|
|
1339
|
+
export class OpenCodeClientAdapter {
|
|
1340
|
+
directory;
|
|
1341
|
+
baseUrl;
|
|
1342
|
+
client;
|
|
1343
|
+
controlClient;
|
|
1344
|
+
authorization;
|
|
1345
|
+
eventAbortController;
|
|
1346
|
+
eventTask;
|
|
1347
|
+
temporarySessionIds = new Set();
|
|
1348
|
+
sessionMetricsCache = new Map();
|
|
1349
|
+
liveMessagePartCache = new Map();
|
|
1350
|
+
liveMessagePartCacheBytes = 0;
|
|
1351
|
+
constructor(options) {
|
|
1352
|
+
this.directory = plugins.fs.realpathSync.native(options.directory);
|
|
1353
|
+
const parsedBaseUrl = new URL(options.baseUrl);
|
|
1354
|
+
if (parsedBaseUrl.protocol !== 'http:' || parsedBaseUrl.hostname !== '127.0.0.1') {
|
|
1355
|
+
throw new Error('OpenCode SDK traffic must use loopback HTTP.');
|
|
1356
|
+
}
|
|
1357
|
+
parsedBaseUrl.pathname = '/';
|
|
1358
|
+
parsedBaseUrl.search = '';
|
|
1359
|
+
parsedBaseUrl.hash = '';
|
|
1360
|
+
this.baseUrl = parsedBaseUrl.toString().replace(/\/$/u, '');
|
|
1361
|
+
const username = validateInputString(options.username, 'OpenCode username', 128);
|
|
1362
|
+
const password = validateInputString(options.password, 'OpenCode password', 1024);
|
|
1363
|
+
const authorization = `Basic ${Buffer.from(`${username}:${password}`, 'utf8').toString('base64')}`;
|
|
1364
|
+
this.authorization = authorization;
|
|
1365
|
+
const clientFactory = options.clientFactory ?? plugins.opencodeSdk.createOpencodeClient;
|
|
1366
|
+
const boundedFetch = createBoundedOpenCodeFetch(this.baseUrl, options.fetchImplementation ?? globalThis.fetch, options.acquireRuntimeLease);
|
|
1367
|
+
const clientOptions = {
|
|
1368
|
+
baseUrl: this.baseUrl,
|
|
1369
|
+
directory: this.directory,
|
|
1370
|
+
headers: {
|
|
1371
|
+
Authorization: authorization,
|
|
1372
|
+
},
|
|
1373
|
+
responseStyle: 'data',
|
|
1374
|
+
throwOnError: true,
|
|
1375
|
+
};
|
|
1376
|
+
this.client = clientFactory({
|
|
1377
|
+
...clientOptions,
|
|
1378
|
+
fetch: boundedFetch,
|
|
1379
|
+
});
|
|
1380
|
+
this.controlClient = clientFactory({
|
|
1381
|
+
...clientOptions,
|
|
1382
|
+
fetch: createBoundedOpenCodeFetch(this.baseUrl, options.fetchImplementation ?? globalThis.fetch),
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
requireDirectory(directoryArg) {
|
|
1386
|
+
if (typeof directoryArg !== 'string' || !plugins.path.isAbsolute(directoryArg)) {
|
|
1387
|
+
throw new Error('The OpenCode call requires an absolute project directory.');
|
|
1388
|
+
}
|
|
1389
|
+
return directoryArg;
|
|
1390
|
+
}
|
|
1391
|
+
async getStatuses(directoryArg, signal) {
|
|
1392
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1393
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.session.status({ directory }, { signal: requestSignal }));
|
|
1394
|
+
if (!isRecord(response)) {
|
|
1395
|
+
throw new Error('OpenCode returned an invalid session status map.');
|
|
1396
|
+
}
|
|
1397
|
+
if (Object.keys(response).length > maxCollectionEntries) {
|
|
1398
|
+
throw new Error('OpenCode returned too many session statuses.');
|
|
1399
|
+
}
|
|
1400
|
+
const result = {};
|
|
1401
|
+
for (const [sessionId, status] of Object.entries(response)) {
|
|
1402
|
+
if (sessionId === '__proto__' ||
|
|
1403
|
+
sessionId === 'constructor' ||
|
|
1404
|
+
sessionId === 'prototype') {
|
|
1405
|
+
continue;
|
|
1406
|
+
}
|
|
1407
|
+
requireString(sessionId, 'session status ID', maxIdentifierBytes);
|
|
1408
|
+
result[sessionId] = normalizeSessionStatus(status);
|
|
1409
|
+
}
|
|
1410
|
+
return result;
|
|
1411
|
+
}
|
|
1412
|
+
async listSessions(directoryArg, signal) {
|
|
1413
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1414
|
+
const [response, statuses] = await Promise.all([
|
|
1415
|
+
runSdkRequest(signal, (requestSignal) => this.client.session.list({
|
|
1416
|
+
directory,
|
|
1417
|
+
// Stable /session has no lossless cursor. Request the complete
|
|
1418
|
+
// bounded window and reject a full window instead of returning a
|
|
1419
|
+
// snapshot whose missing tail looks like deletion.
|
|
1420
|
+
limit: maxCollectionEntries,
|
|
1421
|
+
// Subagent child sessions are internal to their parent chat; they
|
|
1422
|
+
// would otherwise dominate the list and crowd out real
|
|
1423
|
+
// conversations before the limit is reached.
|
|
1424
|
+
roots: true,
|
|
1425
|
+
}, { signal: requestSignal })),
|
|
1426
|
+
this.getStatuses(directory, signal),
|
|
1427
|
+
]);
|
|
1428
|
+
if (!Array.isArray(response) || response.length > maxCollectionEntries) {
|
|
1429
|
+
throw new Error('OpenCode returned an invalid session list.');
|
|
1430
|
+
}
|
|
1431
|
+
if (response.length === maxCollectionEntries) {
|
|
1432
|
+
throw new Error('The OpenCode session list reached its exhaustive read bound.');
|
|
1433
|
+
}
|
|
1434
|
+
return response
|
|
1435
|
+
.filter((session) => {
|
|
1436
|
+
if (!isRecord(session))
|
|
1437
|
+
throw new Error('OpenCode returned an invalid session.');
|
|
1438
|
+
const id = requireString(session.id, 'session ID', maxIdentifierBytes);
|
|
1439
|
+
return !this.temporarySessionIds.has(id)
|
|
1440
|
+
&& !isSessionIntelligenceMetadata(session.metadata);
|
|
1441
|
+
})
|
|
1442
|
+
.map((session) => {
|
|
1443
|
+
if (!isRecord(session)) {
|
|
1444
|
+
throw new Error('OpenCode returned an invalid session.');
|
|
1445
|
+
}
|
|
1446
|
+
const id = requireString(session.id, 'session ID', maxIdentifierBytes);
|
|
1447
|
+
return normalizeOpenCodeSession(session, directory, statuses[id] ?? 'idle');
|
|
1448
|
+
})
|
|
1449
|
+
// The official TUI applies the same defense on top of roots=true: a
|
|
1450
|
+
// child session must never surface as a conversation of its own.
|
|
1451
|
+
.filter((session) => session.parentId === undefined);
|
|
1452
|
+
}
|
|
1453
|
+
async getSessionReversionInfo(directoryArg, sessionIdArg, signal) {
|
|
1454
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1455
|
+
const sessionId = validateInputString(sessionIdArg, 'Session ID', maxIdentifierBytes);
|
|
1456
|
+
const [session, messages] = await Promise.all([
|
|
1457
|
+
runSdkRequest(signal, (requestSignal) => this.client.session.get({ sessionID: sessionId, directory }, { signal: requestSignal })),
|
|
1458
|
+
this.readRawMessagePage(directory, sessionId, { limit: 1 }, signal),
|
|
1459
|
+
]);
|
|
1460
|
+
normalizeOpenCodeSession(session, directory);
|
|
1461
|
+
if (!isRecord(session))
|
|
1462
|
+
throw new Error('OpenCode returned an invalid session.');
|
|
1463
|
+
const sessionRecord = session;
|
|
1464
|
+
return {
|
|
1465
|
+
undoAvailable: messages.data.length > 0,
|
|
1466
|
+
redoAvailable: isRecord(sessionRecord.revert),
|
|
1467
|
+
groups: [],
|
|
1468
|
+
};
|
|
1469
|
+
}
|
|
1470
|
+
async getSession(directoryArg, sessionId, signal) {
|
|
1471
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1472
|
+
const validatedSessionId = validateInputString(sessionId, 'Session ID', maxIdentifierBytes);
|
|
1473
|
+
const [session, statuses] = await Promise.all([
|
|
1474
|
+
this.getSessionSnapshot(directory, validatedSessionId, signal),
|
|
1475
|
+
this.getStatuses(directory, signal),
|
|
1476
|
+
]);
|
|
1477
|
+
return { ...session, status: statuses[validatedSessionId] ?? 'idle' };
|
|
1478
|
+
}
|
|
1479
|
+
async getSessionSnapshot(directoryArg, sessionId, signal) {
|
|
1480
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1481
|
+
const validatedSessionId = validateInputString(sessionId, 'Session ID', maxIdentifierBytes);
|
|
1482
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.session.get({
|
|
1483
|
+
sessionID: validatedSessionId,
|
|
1484
|
+
directory,
|
|
1485
|
+
}, { signal: requestSignal }));
|
|
1486
|
+
return normalizeOpenCodeSession(response, directory, 'idle');
|
|
1487
|
+
}
|
|
1488
|
+
async getSessionIfPresent(directoryArg, sessionId, signal) {
|
|
1489
|
+
try {
|
|
1490
|
+
return await this.getSessionSnapshot(directoryArg, sessionId, signal);
|
|
1491
|
+
}
|
|
1492
|
+
catch (errorArg) {
|
|
1493
|
+
if (isOpenCodeNotFoundError(errorArg))
|
|
1494
|
+
return undefined;
|
|
1495
|
+
throw errorArg;
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
async updateSession(directoryArg, sessionId, patch, signal) {
|
|
1499
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1500
|
+
const validatedSessionId = validateInputString(sessionId, 'Session ID', maxIdentifierBytes);
|
|
1501
|
+
if (patch.title === undefined && patch.archivedAt === undefined) {
|
|
1502
|
+
throw new Error('A session update requires a title or an archive timestamp.');
|
|
1503
|
+
}
|
|
1504
|
+
const validatedTitle = patch.title === undefined
|
|
1505
|
+
? undefined
|
|
1506
|
+
: validateInputString(patch.title, 'Session title', maxTitleBytes);
|
|
1507
|
+
if (patch.archivedAt !== undefined
|
|
1508
|
+
&& (!Number.isFinite(patch.archivedAt) || patch.archivedAt <= 0)) {
|
|
1509
|
+
throw new Error('The archive timestamp is invalid.');
|
|
1510
|
+
}
|
|
1511
|
+
// Archived sessions are admitted only while idle and immediately leave the
|
|
1512
|
+
// active UI. Avoid a fallible supplemental read before irreversible dispatch.
|
|
1513
|
+
const statuses = patch.archivedAt === undefined
|
|
1514
|
+
? await this.getStatuses(directory, signal)
|
|
1515
|
+
: {};
|
|
1516
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.session.update({
|
|
1517
|
+
sessionID: validatedSessionId,
|
|
1518
|
+
directory,
|
|
1519
|
+
...(validatedTitle === undefined ? {} : { title: validatedTitle }),
|
|
1520
|
+
...(patch.archivedAt === undefined ? {} : { time: { archived: patch.archivedAt } }),
|
|
1521
|
+
}, { signal: requestSignal }), patch.archivedAt === undefined ? defaultSdkRequestTimeoutMs : undefined);
|
|
1522
|
+
return normalizeOpenCodeSession(response, directory, statuses[validatedSessionId] ?? 'idle');
|
|
1523
|
+
}
|
|
1524
|
+
async createSession(directoryArg, title, signal) {
|
|
1525
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1526
|
+
const validatedTitle = title === undefined ? undefined : validateInputString(title, 'Session title', maxTitleBytes);
|
|
1527
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.session.create({
|
|
1528
|
+
directory,
|
|
1529
|
+
...(validatedTitle ? { title: validatedTitle } : {}),
|
|
1530
|
+
}, { signal: requestSignal }));
|
|
1531
|
+
return normalizeOpenCodeSession(response, directory, 'idle');
|
|
1532
|
+
}
|
|
1533
|
+
async deleteSession(directoryArg, sessionId, signal) {
|
|
1534
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1535
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.session.delete({
|
|
1536
|
+
sessionID: validateInputString(sessionId, 'Session ID', maxIdentifierBytes),
|
|
1537
|
+
directory,
|
|
1538
|
+
}, { signal: requestSignal }));
|
|
1539
|
+
if (typeof response !== 'boolean') {
|
|
1540
|
+
throw new Error('OpenCode returned an invalid session deletion result.');
|
|
1541
|
+
}
|
|
1542
|
+
if (response) {
|
|
1543
|
+
this.sessionMetricsCache.delete(this.sessionMetricsCacheKey(directory, sessionId));
|
|
1544
|
+
this.clearLiveMessagePartsForSession(directory, sessionId);
|
|
1545
|
+
}
|
|
1546
|
+
return response;
|
|
1547
|
+
}
|
|
1548
|
+
async deleteSessionIfPresent(directoryArg, sessionIdArg, signal) {
|
|
1549
|
+
try {
|
|
1550
|
+
const deleted = await this.deleteSession(directoryArg, sessionIdArg, signal);
|
|
1551
|
+
if (!deleted)
|
|
1552
|
+
throw new Error('OpenCode did not delete the session.');
|
|
1553
|
+
}
|
|
1554
|
+
catch (errorArg) {
|
|
1555
|
+
if (!isOpenCodeNotFoundError(errorArg))
|
|
1556
|
+
throw errorArg;
|
|
1557
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1558
|
+
const sessionId = validateInputString(sessionIdArg, 'Session ID', maxIdentifierBytes);
|
|
1559
|
+
this.sessionMetricsCache.delete(this.sessionMetricsCacheKey(directory, sessionId));
|
|
1560
|
+
this.clearLiveMessagePartsForSession(directory, sessionId);
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
async sendMessage(directoryArg, sessionId, text, model, agent, signal, messageIdArg) {
|
|
1564
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1565
|
+
const validatedSessionId = validateInputString(sessionId, 'Session ID', maxIdentifierBytes);
|
|
1566
|
+
this.sessionMetricsCache.delete(this.sessionMetricsCacheKey(directory, validatedSessionId));
|
|
1567
|
+
const validatedChoice = validateOpenCodeModelChoice(model);
|
|
1568
|
+
const validatedModel = validatedChoice === undefined
|
|
1569
|
+
? undefined
|
|
1570
|
+
: {
|
|
1571
|
+
providerID: validatedChoice.providerID,
|
|
1572
|
+
modelID: validatedChoice.modelID,
|
|
1573
|
+
};
|
|
1574
|
+
// The variant is a body-level sibling of the model reference in the OpenCode API.
|
|
1575
|
+
const validatedVariant = validatedChoice?.variant;
|
|
1576
|
+
const validatedAgent = agent === undefined
|
|
1577
|
+
? undefined
|
|
1578
|
+
: validateInputString(agent, 'Agent name', 128);
|
|
1579
|
+
const messageID = messageIdArg === undefined
|
|
1580
|
+
? undefined
|
|
1581
|
+
: validateInputString(messageIdArg, 'Message ID', maxIdentifierBytes);
|
|
1582
|
+
if (messageID !== undefined && !messageID.startsWith('msg')) {
|
|
1583
|
+
throw new Error('The OpenCode message ID must start with msg.');
|
|
1584
|
+
}
|
|
1585
|
+
await runSdkRequest(signal, (requestSignal) => this.client.session.promptAsync({
|
|
1586
|
+
sessionID: validatedSessionId,
|
|
1587
|
+
directory,
|
|
1588
|
+
...(messageID === undefined ? {} : { messageID }),
|
|
1589
|
+
...(validatedModel ? { model: validatedModel } : {}),
|
|
1590
|
+
...(validatedVariant !== undefined ? { variant: validatedVariant } : {}),
|
|
1591
|
+
...(validatedAgent !== undefined ? { agent: validatedAgent } : {}),
|
|
1592
|
+
parts: [
|
|
1593
|
+
{
|
|
1594
|
+
type: 'text',
|
|
1595
|
+
text: validateInputString(text, 'Message text', maxPromptBytes),
|
|
1596
|
+
},
|
|
1597
|
+
],
|
|
1598
|
+
}, { signal: requestSignal }));
|
|
1599
|
+
}
|
|
1600
|
+
async sendMessageAndWait(directoryArg, sessionId, text, signal) {
|
|
1601
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1602
|
+
const validatedSessionId = validateInputString(sessionId, 'Session ID', maxIdentifierBytes);
|
|
1603
|
+
this.sessionMetricsCache.delete(this.sessionMetricsCacheKey(directory, validatedSessionId));
|
|
1604
|
+
const response = await runSdkRequest(signal, (requestSignal) => (this.client.session.prompt({
|
|
1605
|
+
sessionID: validatedSessionId,
|
|
1606
|
+
directory,
|
|
1607
|
+
parts: [{
|
|
1608
|
+
type: 'text',
|
|
1609
|
+
text: validateInputString(text, 'Message text', maxPromptBytes),
|
|
1610
|
+
}],
|
|
1611
|
+
}, { signal: requestSignal })));
|
|
1612
|
+
if (!isRecord(response) || !isRecord(response.info) || !Array.isArray(response.parts)) {
|
|
1613
|
+
throw new Error('OpenCode returned an invalid completed prompt response.');
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
async sendHarnessControlMessageAndWait(directoryArg, sessionId, text, signal, timeoutMsArg = defaultSdkRequestTimeoutMs) {
|
|
1617
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1618
|
+
const response = await runSdkRequest(signal, (requestSignal) => (this.controlClient.session.prompt({
|
|
1619
|
+
sessionID: validateInputString(sessionId, 'Session ID', maxIdentifierBytes),
|
|
1620
|
+
directory,
|
|
1621
|
+
parts: [{ type: 'text', text: validateInputString(text, 'Message text', maxPromptBytes) }],
|
|
1622
|
+
}, { signal: requestSignal })), timeoutMsArg);
|
|
1623
|
+
if (!isRecord(response) || !isRecord(response.info) || !Array.isArray(response.parts)) {
|
|
1624
|
+
throw new Error('OpenCode returned an invalid completed control prompt response.');
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
async sendHarnessControlMessage(directoryArg, sessionId, text, signal) {
|
|
1628
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1629
|
+
await runSdkRequest(signal, (requestSignal) => this.controlClient.session.promptAsync({
|
|
1630
|
+
sessionID: validateInputString(sessionId, 'Session ID', maxIdentifierBytes),
|
|
1631
|
+
directory,
|
|
1632
|
+
parts: [{ type: 'text', text: validateInputString(text, 'Message text', maxPromptBytes) }],
|
|
1633
|
+
}, { signal: requestSignal }));
|
|
1634
|
+
}
|
|
1635
|
+
async abortSession(directoryArg, sessionId, signal) {
|
|
1636
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1637
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.session.abort({
|
|
1638
|
+
sessionID: validateInputString(sessionId, 'Session ID', maxIdentifierBytes),
|
|
1639
|
+
directory,
|
|
1640
|
+
}, { signal: requestSignal }));
|
|
1641
|
+
if (typeof response !== 'boolean') {
|
|
1642
|
+
throw new Error('OpenCode returned an invalid abort result.');
|
|
1643
|
+
}
|
|
1644
|
+
return response;
|
|
1645
|
+
}
|
|
1646
|
+
async setOpenCodeOAuthAuth(authArg, signal) {
|
|
1647
|
+
try {
|
|
1648
|
+
const response = await runSdkRequest(signal, (requestSignal) => (this.controlClient.auth.set({ providerID: 'openai', auth: { ...authArg } }, { signal: requestSignal })));
|
|
1649
|
+
if (response !== true)
|
|
1650
|
+
throw new Error('OpenCode returned an invalid auth update result.');
|
|
1651
|
+
}
|
|
1652
|
+
catch {
|
|
1653
|
+
// SDK errors may retain request options. Never preserve a cause containing auth material.
|
|
1654
|
+
throw new Error('OpenCode rejected the replacement OpenAI authentication.');
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
async listMessages(directoryArg, sessionId, signal) {
|
|
1658
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1659
|
+
const validatedSessionId = validateInputString(sessionId, 'Session ID', maxIdentifierBytes);
|
|
1660
|
+
const aggregatePartCount = { value: 0 };
|
|
1661
|
+
const pages = [];
|
|
1662
|
+
const seenCursors = new Set();
|
|
1663
|
+
let before;
|
|
1664
|
+
let sourceMessageCount = 0;
|
|
1665
|
+
for (let pageIndex = 0; pageIndex < Math.ceil(maxMessagesPerRequest / maxMessagesPerPage); pageIndex += 1) {
|
|
1666
|
+
const page = await this.readRawMessagePage(directory, validatedSessionId, {
|
|
1667
|
+
limit: Math.min(maxMessagesPerPage, maxMessagesPerRequest - sourceMessageCount),
|
|
1668
|
+
...(before === undefined ? {} : { before }),
|
|
1669
|
+
}, signal);
|
|
1670
|
+
if (page.data.length === 0 && page.nextCursor !== undefined) {
|
|
1671
|
+
throw new Error('OpenCode returned an empty message page with a continuation cursor.');
|
|
1672
|
+
}
|
|
1673
|
+
const bundles = normalizeOpenCodeMessageBundlesWithPartCount(page.data, validatedSessionId, aggregatePartCount);
|
|
1674
|
+
pages.unshift(bundles);
|
|
1675
|
+
sourceMessageCount += bundles.length;
|
|
1676
|
+
if (page.nextCursor === undefined || sourceMessageCount >= maxMessagesPerRequest)
|
|
1677
|
+
break;
|
|
1678
|
+
if (seenCursors.has(page.nextCursor)) {
|
|
1679
|
+
throw new Error('OpenCode repeated a message page cursor.');
|
|
1680
|
+
}
|
|
1681
|
+
seenCursors.add(page.nextCursor);
|
|
1682
|
+
before = page.nextCursor;
|
|
1683
|
+
}
|
|
1684
|
+
return trimOldestMessagesToFit(pages.flat(2).flatMap((bundle) => bundle.messages), maxNormalizedMessageBytes);
|
|
1685
|
+
}
|
|
1686
|
+
async readRawMessagePage(directoryArg, sessionIdArg, optionsArg, signal) {
|
|
1687
|
+
const fields = await runSdkRequest(signal, (requestSignal) => this.client.session.messages({
|
|
1688
|
+
sessionID: validateInputString(sessionIdArg, 'Session ID', maxIdentifierBytes),
|
|
1689
|
+
directory: this.requireDirectory(directoryArg),
|
|
1690
|
+
limit: optionsArg.limit,
|
|
1691
|
+
...(optionsArg.before === undefined ? {} : {
|
|
1692
|
+
before: validateInputString(optionsArg.before, 'Message page cursor', 4096),
|
|
1693
|
+
}),
|
|
1694
|
+
}, { signal: requestSignal, responseStyle: 'fields' }));
|
|
1695
|
+
if (!isRecord(fields) || !(fields.response instanceof Response) || !Array.isArray(fields.data)) {
|
|
1696
|
+
throw new Error('OpenCode returned invalid message page response fields.');
|
|
1697
|
+
}
|
|
1698
|
+
if (fields.data.length > optionsArg.limit) {
|
|
1699
|
+
throw new Error('OpenCode returned too many messages in one page.');
|
|
1700
|
+
}
|
|
1701
|
+
const cursorHeader = fields.response.headers.get('x-next-cursor');
|
|
1702
|
+
const nextCursor = cursorHeader === null
|
|
1703
|
+
? undefined
|
|
1704
|
+
: requireString(cursorHeader, 'message page cursor', 4096);
|
|
1705
|
+
return {
|
|
1706
|
+
data: fields.data,
|
|
1707
|
+
...(nextCursor === undefined ? {} : { nextCursor }),
|
|
1708
|
+
};
|
|
1709
|
+
}
|
|
1710
|
+
async listMessagePage(directoryArg, sessionId, options, signal) {
|
|
1711
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1712
|
+
if (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > maxMessagesPerPage) {
|
|
1713
|
+
throw new Error(`Message page limit must be an integer from 1 to ${maxMessagesPerPage}.`);
|
|
1714
|
+
}
|
|
1715
|
+
const before = options.before === undefined
|
|
1716
|
+
? undefined
|
|
1717
|
+
: validateInputString(options.before, 'Message page cursor', 4096);
|
|
1718
|
+
const page = await this.readRawMessagePage(directory, sessionId, { limit: options.limit, ...(before === undefined ? {} : { before }) }, signal);
|
|
1719
|
+
const bundles = normalizeOpenCodeMessageBundles(page.data, sessionId);
|
|
1720
|
+
return {
|
|
1721
|
+
bundles,
|
|
1722
|
+
...(page.nextCursor === undefined ? {} : { nextCursor: page.nextCursor }),
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
async getSessionMetrics(directoryArg, sessionIdArg, signal) {
|
|
1726
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1727
|
+
const sessionId = validateInputString(sessionIdArg, 'Session ID', maxIdentifierBytes);
|
|
1728
|
+
const cacheKey = this.sessionMetricsCacheKey(directory, sessionId);
|
|
1729
|
+
const cached = this.sessionMetricsCache.get(cacheKey);
|
|
1730
|
+
if (cached && cached.expiresAt > Date.now())
|
|
1731
|
+
return cached.promise;
|
|
1732
|
+
const entry = {
|
|
1733
|
+
promise: Promise.resolve({}),
|
|
1734
|
+
expiresAt: Number.MAX_SAFE_INTEGER,
|
|
1735
|
+
};
|
|
1736
|
+
const calculation = this.calculateSessionMetrics(directory, sessionId, signal);
|
|
1737
|
+
entry.promise = calculation;
|
|
1738
|
+
this.sessionMetricsCache.delete(cacheKey);
|
|
1739
|
+
this.sessionMetricsCache.set(cacheKey, entry);
|
|
1740
|
+
while (this.sessionMetricsCache.size > maxSessionMetricsCacheEntries) {
|
|
1741
|
+
const oldestKey = this.sessionMetricsCache.keys().next().value;
|
|
1742
|
+
if (oldestKey === undefined)
|
|
1743
|
+
break;
|
|
1744
|
+
this.sessionMetricsCache.delete(oldestKey);
|
|
1745
|
+
}
|
|
1746
|
+
calculation.then(() => {
|
|
1747
|
+
if (this.sessionMetricsCache.get(cacheKey) === entry) {
|
|
1748
|
+
entry.expiresAt = Date.now() + sessionMetricsCacheTtlMs;
|
|
1749
|
+
}
|
|
1750
|
+
}, () => {
|
|
1751
|
+
if (this.sessionMetricsCache.get(cacheKey) === entry) {
|
|
1752
|
+
this.sessionMetricsCache.delete(cacheKey);
|
|
1753
|
+
}
|
|
1754
|
+
});
|
|
1755
|
+
return calculation;
|
|
1756
|
+
}
|
|
1757
|
+
sessionMetricsCacheKey(directoryArg, sessionIdArg) {
|
|
1758
|
+
return `${directoryArg}\0${sessionIdArg}`;
|
|
1759
|
+
}
|
|
1760
|
+
async calculateSessionMetrics(directory, sessionId, signal) {
|
|
1761
|
+
let before;
|
|
1762
|
+
const seenCursors = new Set();
|
|
1763
|
+
let exhaustive = false;
|
|
1764
|
+
let lifetimeUsedTokens = 0;
|
|
1765
|
+
let lifetimeProvable = true;
|
|
1766
|
+
let compactionCount = 0;
|
|
1767
|
+
let latestCompaction;
|
|
1768
|
+
let latestCurrent;
|
|
1769
|
+
let latestMessage;
|
|
1770
|
+
const tokenFacts = (infoArg) => {
|
|
1771
|
+
if (!isRecord(infoArg.tokens) || !isRecord(infoArg.tokens.cache))
|
|
1772
|
+
return undefined;
|
|
1773
|
+
const values = [
|
|
1774
|
+
infoArg.tokens.input,
|
|
1775
|
+
infoArg.tokens.output,
|
|
1776
|
+
infoArg.tokens.reasoning,
|
|
1777
|
+
infoArg.tokens.cache.read,
|
|
1778
|
+
infoArg.tokens.cache.write,
|
|
1779
|
+
];
|
|
1780
|
+
if (!values.every((value) => Number.isSafeInteger(value) && value >= 0)) {
|
|
1781
|
+
return undefined;
|
|
1782
|
+
}
|
|
1783
|
+
const [input, output, reasoning, cacheRead, cacheWrite] = values;
|
|
1784
|
+
const lifetime = input + output + reasoning + cacheRead + cacheWrite;
|
|
1785
|
+
const context = input + cacheRead + cacheWrite;
|
|
1786
|
+
if (!Number.isSafeInteger(lifetime) || !Number.isSafeInteger(context))
|
|
1787
|
+
return undefined;
|
|
1788
|
+
return { lifetime, context };
|
|
1789
|
+
};
|
|
1790
|
+
for (let pageIndex = 0; pageIndex < maxExhaustiveMessagePages; pageIndex += 1) {
|
|
1791
|
+
const page = await this.readRawMessagePage(directory, sessionId, { limit: maxMessagesPerPage, ...(before === undefined ? {} : { before }) }, signal);
|
|
1792
|
+
for (const bundle of page.data) {
|
|
1793
|
+
if (!isRecord(bundle) || !isRecord(bundle.info) || !Array.isArray(bundle.parts)) {
|
|
1794
|
+
throw new Error('OpenCode returned an invalid message while calculating metrics.');
|
|
1795
|
+
}
|
|
1796
|
+
const info = bundle.info;
|
|
1797
|
+
if (info.role !== 'assistant' && info.role !== 'user')
|
|
1798
|
+
continue;
|
|
1799
|
+
const id = requireString(info.id, 'message ID', maxIdentifierBytes);
|
|
1800
|
+
const createdAt = isRecord(info.time)
|
|
1801
|
+
? requireFiniteNumber(info.time.created, 'message creation time')
|
|
1802
|
+
: (() => { throw new Error('OpenCode returned an invalid message time.'); })();
|
|
1803
|
+
if (!latestMessage
|
|
1804
|
+
|| createdAt > latestMessage.createdAt
|
|
1805
|
+
|| (createdAt === latestMessage.createdAt && id > latestMessage.id)) {
|
|
1806
|
+
latestMessage = { createdAt, id };
|
|
1807
|
+
}
|
|
1808
|
+
if (info.role !== 'assistant')
|
|
1809
|
+
continue;
|
|
1810
|
+
const usage = tokenFacts(info);
|
|
1811
|
+
if (!usage) {
|
|
1812
|
+
lifetimeProvable = false;
|
|
1813
|
+
}
|
|
1814
|
+
else if (lifetimeProvable) {
|
|
1815
|
+
lifetimeUsedTokens += usage.lifetime;
|
|
1816
|
+
if (!Number.isSafeInteger(lifetimeUsedTokens))
|
|
1817
|
+
lifetimeProvable = false;
|
|
1818
|
+
}
|
|
1819
|
+
const completed = typeof info.finish === 'string'
|
|
1820
|
+
&& info.finish.length > 0
|
|
1821
|
+
&& info.error === undefined
|
|
1822
|
+
&& isRecord(info.time)
|
|
1823
|
+
&& optionalFiniteNumber(info.time.completed) !== undefined;
|
|
1824
|
+
if (info.summary === true && completed) {
|
|
1825
|
+
compactionCount += 1;
|
|
1826
|
+
if (!latestCompaction
|
|
1827
|
+
|| createdAt > latestCompaction.createdAt
|
|
1828
|
+
|| (createdAt === latestCompaction.createdAt && id > latestCompaction.id)) {
|
|
1829
|
+
latestCompaction = {
|
|
1830
|
+
createdAt,
|
|
1831
|
+
id,
|
|
1832
|
+
...(usage === undefined ? {} : { contextTokens: usage.context }),
|
|
1833
|
+
};
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
else if (completed && usage) {
|
|
1837
|
+
const providerId = requireString(info.providerID, 'message provider ID', 256);
|
|
1838
|
+
const modelId = requireString(info.modelID, 'message model ID', 256);
|
|
1839
|
+
if (!latestCurrent
|
|
1840
|
+
|| createdAt > latestCurrent.createdAt
|
|
1841
|
+
|| (createdAt === latestCurrent.createdAt && id > latestCurrent.id)) {
|
|
1842
|
+
latestCurrent = { createdAt, id, contextTokens: usage.context, providerId, modelId };
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
if (!page.nextCursor) {
|
|
1847
|
+
exhaustive = true;
|
|
1848
|
+
break;
|
|
1849
|
+
}
|
|
1850
|
+
if (seenCursors.has(page.nextCursor)) {
|
|
1851
|
+
throw new Error('OpenCode repeated a message page cursor.');
|
|
1852
|
+
}
|
|
1853
|
+
seenCursors.add(page.nextCursor);
|
|
1854
|
+
before = page.nextCursor;
|
|
1855
|
+
}
|
|
1856
|
+
if (!exhaustive)
|
|
1857
|
+
return {};
|
|
1858
|
+
const currentCandidate = latestCurrent;
|
|
1859
|
+
const current = currentCandidate !== undefined
|
|
1860
|
+
&& latestMessage !== undefined
|
|
1861
|
+
&& currentCandidate.createdAt === latestMessage.createdAt
|
|
1862
|
+
&& currentCandidate.id === latestMessage.id
|
|
1863
|
+
&& (latestCompaction === undefined
|
|
1864
|
+
|| currentCandidate.createdAt > latestCompaction.createdAt
|
|
1865
|
+
|| (currentCandidate.createdAt === latestCompaction.createdAt
|
|
1866
|
+
&& currentCandidate.id > latestCompaction.id))
|
|
1867
|
+
? currentCandidate
|
|
1868
|
+
: undefined;
|
|
1869
|
+
let maxContextTokens;
|
|
1870
|
+
if (current) {
|
|
1871
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.config.providers({ directory }, { signal: requestSignal }));
|
|
1872
|
+
if (!isRecord(response) || !Array.isArray(response.providers)) {
|
|
1873
|
+
throw new Error('OpenCode returned an invalid provider list.');
|
|
1874
|
+
}
|
|
1875
|
+
const provider = response.providers.find((entry) => isRecord(entry) && entry.id === current.providerId);
|
|
1876
|
+
const model = isRecord(provider) && isRecord(provider.models)
|
|
1877
|
+
? provider.models[current.modelId]
|
|
1878
|
+
: undefined;
|
|
1879
|
+
const contextLimit = isRecord(model) && isRecord(model.limit)
|
|
1880
|
+
? model.limit.context
|
|
1881
|
+
: undefined;
|
|
1882
|
+
if (Number.isSafeInteger(contextLimit) && contextLimit > 0) {
|
|
1883
|
+
maxContextTokens = contextLimit;
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
return {
|
|
1887
|
+
...(lifetimeProvable ? { lifetimeUsedTokens } : {}),
|
|
1888
|
+
compactionCount,
|
|
1889
|
+
...(latestCompaction?.contextTokens === undefined
|
|
1890
|
+
? {}
|
|
1891
|
+
: { tokensBeforeLatestCompaction: latestCompaction.contextTokens }),
|
|
1892
|
+
...(current === undefined ? {} : { currentContextTokens: current.contextTokens }),
|
|
1893
|
+
...(maxContextTokens === undefined ? {} : { maxContextTokens }),
|
|
1894
|
+
};
|
|
1895
|
+
}
|
|
1896
|
+
async buildSessionIntelligenceTranscript(directoryArg, sessionIdArg, signal) {
|
|
1897
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1898
|
+
const sessionId = validateInputString(sessionIdArg, 'Session ID', maxIdentifierBytes);
|
|
1899
|
+
const messages = [];
|
|
1900
|
+
const seenCursors = new Set();
|
|
1901
|
+
let before;
|
|
1902
|
+
let earlierOmitted = false;
|
|
1903
|
+
for (let pageIndex = 0; pageIndex < maxExhaustiveMessagePages; pageIndex += 1) {
|
|
1904
|
+
const page = await this.listMessagePage(directory, sessionId, { limit: maxMessagesPerPage, ...(before === undefined ? {} : { before }) }, signal);
|
|
1905
|
+
const pageMessages = page.bundles.flatMap((bundle) => bundle.messages);
|
|
1906
|
+
messages.unshift(...pageMessages);
|
|
1907
|
+
while (messages.length > maxIntelligenceTranscriptMessages
|
|
1908
|
+
|| Buffer.byteLength(JSON.stringify(messages), 'utf8') > maxIntelligenceTranscriptBytes) {
|
|
1909
|
+
messages.shift();
|
|
1910
|
+
earlierOmitted = true;
|
|
1911
|
+
}
|
|
1912
|
+
if (!page.nextCursor)
|
|
1913
|
+
break;
|
|
1914
|
+
if (seenCursors.has(page.nextCursor)) {
|
|
1915
|
+
throw new Error('OpenCode repeated a message page cursor.');
|
|
1916
|
+
}
|
|
1917
|
+
seenCursors.add(page.nextCursor);
|
|
1918
|
+
before = page.nextCursor;
|
|
1919
|
+
if (earlierOmitted)
|
|
1920
|
+
break;
|
|
1921
|
+
if (pageIndex === maxExhaustiveMessagePages - 1)
|
|
1922
|
+
earlierOmitted = true;
|
|
1923
|
+
}
|
|
1924
|
+
const transcript = JSON.stringify({
|
|
1925
|
+
...(earlierOmitted
|
|
1926
|
+
? { notice: 'Earlier messages were omitted to keep the analysis transcript bounded.' }
|
|
1927
|
+
: {}),
|
|
1928
|
+
messages: messages.map((message) => ({
|
|
1929
|
+
role: message.role,
|
|
1930
|
+
createdAt: message.createdAt,
|
|
1931
|
+
...(message.model === undefined ? {} : { model: message.model }),
|
|
1932
|
+
...(message.text ? { text: message.text } : {}),
|
|
1933
|
+
...(message.error === undefined ? {} : { error: message.error }),
|
|
1934
|
+
...(message.toolCall === undefined ? {} : { toolCall: message.toolCall }),
|
|
1935
|
+
})),
|
|
1936
|
+
});
|
|
1937
|
+
if (Buffer.byteLength(transcript, 'utf8') > maxIntelligenceTranscriptBytes + 1024) {
|
|
1938
|
+
throw new Error('The bounded Session Intelligence transcript exceeded its output budget.');
|
|
1939
|
+
}
|
|
1940
|
+
return transcript;
|
|
1941
|
+
}
|
|
1942
|
+
async getMessageBundle(directoryArg, sessionId, messageId, signal) {
|
|
1943
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1944
|
+
const validatedMessageId = validateInputString(messageId, 'Message ID', maxIdentifierBytes);
|
|
1945
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.session.message({
|
|
1946
|
+
sessionID: validateInputString(sessionId, 'Session ID', maxIdentifierBytes),
|
|
1947
|
+
messageID: validatedMessageId,
|
|
1948
|
+
directory,
|
|
1949
|
+
}, { signal: requestSignal }));
|
|
1950
|
+
const bundles = normalizeOpenCodeMessageBundles([response], sessionId);
|
|
1951
|
+
if (bundles.length !== 1
|
|
1952
|
+
|| !controllerRuntimeIdsEqual(bundles[0].sourceMessageId, openCodeRuntimeId(validatedMessageId))) {
|
|
1953
|
+
throw new Error('OpenCode returned a different message than requested.');
|
|
1954
|
+
}
|
|
1955
|
+
return bundles[0];
|
|
1956
|
+
}
|
|
1957
|
+
async runBuiltinSessionCommand(directoryArg, sessionId, command, model, signal) {
|
|
1958
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1959
|
+
const sessionID = validateInputString(sessionId, 'Session ID', maxIdentifierBytes);
|
|
1960
|
+
this.sessionMetricsCache.delete(this.sessionMetricsCacheKey(directory, sessionID));
|
|
1961
|
+
const validatedModel = validateOpenCodeModelChoice(model, maxIdentifierBytes);
|
|
1962
|
+
const modelReference = validatedModel
|
|
1963
|
+
? {
|
|
1964
|
+
providerID: validatedModel.providerID,
|
|
1965
|
+
modelID: validatedModel.modelID,
|
|
1966
|
+
}
|
|
1967
|
+
: {};
|
|
1968
|
+
switch (command) {
|
|
1969
|
+
case 'compact':
|
|
1970
|
+
// Summarization runs a model call and blocks until done.
|
|
1971
|
+
await runSdkRequest(signal, (requestSignal) => this.client.session.summarize({ sessionID, directory, ...modelReference }, { signal: requestSignal }), builtinModelCommandTimeoutMs);
|
|
1972
|
+
return;
|
|
1973
|
+
case 'undo':
|
|
1974
|
+
await runSdkRequest(signal, (requestSignal) => this.client.session.revert({ sessionID, directory }, { signal: requestSignal }));
|
|
1975
|
+
return;
|
|
1976
|
+
case 'redo':
|
|
1977
|
+
await runSdkRequest(signal, (requestSignal) => this.client.session.unrevert({ sessionID, directory }, { signal: requestSignal }));
|
|
1978
|
+
return;
|
|
1979
|
+
case 'init':
|
|
1980
|
+
// AGENTS.md generation runs a model call and blocks until done.
|
|
1981
|
+
await runSdkRequest(signal, (requestSignal) => this.client.session.init({ sessionID, directory, ...modelReference }, { signal: requestSignal }), builtinModelCommandTimeoutMs);
|
|
1982
|
+
return;
|
|
1983
|
+
default: {
|
|
1984
|
+
const exhaustive = command;
|
|
1985
|
+
throw new Error(`Unsupported builtin command: ${String(exhaustive)}`);
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
async listPermissions(directoryArg, sessionId, signal) {
|
|
1990
|
+
const directory = this.requireDirectory(directoryArg);
|
|
1991
|
+
const validatedSessionId = sessionId === undefined
|
|
1992
|
+
? undefined
|
|
1993
|
+
: validateInputString(sessionId, 'Session ID', maxIdentifierBytes);
|
|
1994
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.permission.list({ directory }, { signal: requestSignal }));
|
|
1995
|
+
const permissions = normalizeOpenCodePermissions(response);
|
|
1996
|
+
return validatedSessionId
|
|
1997
|
+
? permissions.filter((permission) => permission.sessionId.nativeId === validatedSessionId)
|
|
1998
|
+
: permissions;
|
|
1999
|
+
}
|
|
2000
|
+
async listQuestions(directoryArg, sessionId, signal) {
|
|
2001
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2002
|
+
const validatedSessionId = sessionId === undefined
|
|
2003
|
+
? undefined
|
|
2004
|
+
: validateInputString(sessionId, 'Session ID', maxIdentifierBytes);
|
|
2005
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.question.list({ directory }, { signal: requestSignal }));
|
|
2006
|
+
const questions = normalizeOpenCodeQuestions(response);
|
|
2007
|
+
return validatedSessionId
|
|
2008
|
+
? questions.filter((question) => question.sessionId.nativeId === validatedSessionId)
|
|
2009
|
+
: questions;
|
|
2010
|
+
}
|
|
2011
|
+
async replyQuestion(directoryArg, requestId, answers, signal) {
|
|
2012
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2013
|
+
if (answers.length === 0
|
|
2014
|
+
|| answers.some((answerList) => answerList.length === 0)) {
|
|
2015
|
+
throw new Error('Question answers are invalid.');
|
|
2016
|
+
}
|
|
2017
|
+
const validatedAnswers = answers.map((answerList) => answerList.map((answer) => validateInputString(answer, 'Question answer', maxMetadataStringBytes)));
|
|
2018
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.question.reply({
|
|
2019
|
+
requestID: validateInputString(requestId, 'Question request ID', maxIdentifierBytes),
|
|
2020
|
+
directory,
|
|
2021
|
+
answers: validatedAnswers,
|
|
2022
|
+
}, { signal: requestSignal }));
|
|
2023
|
+
if (typeof response !== 'boolean') {
|
|
2024
|
+
throw new Error('OpenCode returned an invalid question result.');
|
|
2025
|
+
}
|
|
2026
|
+
return response;
|
|
2027
|
+
}
|
|
2028
|
+
async rejectQuestion(directoryArg, requestId, signal) {
|
|
2029
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2030
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.question.reject({
|
|
2031
|
+
requestID: validateInputString(requestId, 'Question request ID', maxIdentifierBytes),
|
|
2032
|
+
directory,
|
|
2033
|
+
}, { signal: requestSignal }));
|
|
2034
|
+
if (typeof response !== 'boolean') {
|
|
2035
|
+
throw new Error('OpenCode returned an invalid question result.');
|
|
2036
|
+
}
|
|
2037
|
+
return response;
|
|
2038
|
+
}
|
|
2039
|
+
async replyPermission(directoryArg, requestId, reply, message, signal) {
|
|
2040
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2041
|
+
if (reply !== 'once' && reply !== 'reject') {
|
|
2042
|
+
throw new Error('Permission reply is invalid.');
|
|
2043
|
+
}
|
|
2044
|
+
const validatedMessage = message === undefined
|
|
2045
|
+
? undefined
|
|
2046
|
+
: validateInputString(message, 'Permission message', maxTitleBytes, true);
|
|
2047
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.permission.reply({
|
|
2048
|
+
requestID: validateInputString(requestId, 'Permission request ID', maxIdentifierBytes),
|
|
2049
|
+
directory,
|
|
2050
|
+
reply,
|
|
2051
|
+
...(validatedMessage === undefined ? {} : { message: validatedMessage }),
|
|
2052
|
+
}, { signal: requestSignal }));
|
|
2053
|
+
if (typeof response !== 'boolean') {
|
|
2054
|
+
throw new Error('OpenCode returned an invalid permission result.');
|
|
2055
|
+
}
|
|
2056
|
+
return response;
|
|
2057
|
+
}
|
|
2058
|
+
async listPtys(directoryArg, signal) {
|
|
2059
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2060
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.pty.list({ directory }, { signal: requestSignal }));
|
|
2061
|
+
return normalizeOpenCodePtys(response);
|
|
2062
|
+
}
|
|
2063
|
+
async createPty(directoryArg, title, signal) {
|
|
2064
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2065
|
+
const validatedTitle = title === undefined
|
|
2066
|
+
? undefined
|
|
2067
|
+
: validateInputString(title, 'Terminal title', maxTitleBytes);
|
|
2068
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.pty.create({
|
|
2069
|
+
directory,
|
|
2070
|
+
cwd: directory,
|
|
2071
|
+
...(validatedTitle === undefined ? {} : { title: validatedTitle }),
|
|
2072
|
+
}, { signal: requestSignal }));
|
|
2073
|
+
const normalized = normalizeOpenCodePtys([response]);
|
|
2074
|
+
if (normalized.length !== 1) {
|
|
2075
|
+
throw new Error('OpenCode returned an invalid PTY session.');
|
|
2076
|
+
}
|
|
2077
|
+
return normalized[0];
|
|
2078
|
+
}
|
|
2079
|
+
async updatePty(directoryArg, ptyId, patch, signal) {
|
|
2080
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2081
|
+
const validatedPtyId = validateInputString(ptyId, 'PTY ID', maxIdentifierBytes);
|
|
2082
|
+
const validatedTitle = patch.title === undefined
|
|
2083
|
+
? undefined
|
|
2084
|
+
: validateInputString(patch.title, 'Terminal title', maxTitleBytes);
|
|
2085
|
+
if (patch.size !== undefined
|
|
2086
|
+
&& (!Number.isSafeInteger(patch.size.rows) || !Number.isSafeInteger(patch.size.cols)
|
|
2087
|
+
|| patch.size.rows < 2 || patch.size.cols < 2
|
|
2088
|
+
|| patch.size.rows > 500 || patch.size.cols > 500)) {
|
|
2089
|
+
throw new Error('The terminal size is invalid.');
|
|
2090
|
+
}
|
|
2091
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.pty.update({
|
|
2092
|
+
ptyID: validatedPtyId,
|
|
2093
|
+
directory,
|
|
2094
|
+
...(validatedTitle === undefined ? {} : { title: validatedTitle }),
|
|
2095
|
+
...(patch.size === undefined ? {} : { size: { rows: patch.size.rows, cols: patch.size.cols } }),
|
|
2096
|
+
}, { signal: requestSignal }));
|
|
2097
|
+
const normalized = normalizeOpenCodePtys([response]);
|
|
2098
|
+
if (normalized.length !== 1) {
|
|
2099
|
+
throw new Error('OpenCode returned an invalid PTY session.');
|
|
2100
|
+
}
|
|
2101
|
+
return normalized[0];
|
|
2102
|
+
}
|
|
2103
|
+
async removePty(directoryArg, ptyId, signal) {
|
|
2104
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2105
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.pty.remove({
|
|
2106
|
+
ptyID: validateInputString(ptyId, 'PTY ID', maxIdentifierBytes),
|
|
2107
|
+
directory,
|
|
2108
|
+
}, { signal: requestSignal }));
|
|
2109
|
+
if (typeof response !== 'boolean') {
|
|
2110
|
+
throw new Error('OpenCode returned an invalid PTY removal result.');
|
|
2111
|
+
}
|
|
2112
|
+
return response;
|
|
2113
|
+
}
|
|
2114
|
+
/**
|
|
2115
|
+
* Opens the PTY relay socket. The ticket flow mirrors the official web
|
|
2116
|
+
* client: mint a short-lived single-use ticket, then upgrade without Basic
|
|
2117
|
+
* auth. cursor 0 requests a full scrollback replay.
|
|
2118
|
+
*/
|
|
2119
|
+
async connectPty(directoryArg, ptyId, cursor, callbacks) {
|
|
2120
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2121
|
+
const validatedPtyId = validateInputString(ptyId, 'PTY ID', maxIdentifierBytes);
|
|
2122
|
+
const ticketResponse = await fetch(`${this.baseUrl}/pty/${encodeURIComponent(validatedPtyId)}/connect-token`
|
|
2123
|
+
+ `?directory=${encodeURIComponent(directory)}`, {
|
|
2124
|
+
method: 'POST',
|
|
2125
|
+
headers: {
|
|
2126
|
+
authorization: this.authorization,
|
|
2127
|
+
'x-opencode-ticket': '1',
|
|
2128
|
+
},
|
|
2129
|
+
});
|
|
2130
|
+
if (!ticketResponse.ok) {
|
|
2131
|
+
throw new Error(`OpenCode refused a PTY connect ticket (${ticketResponse.status}).`);
|
|
2132
|
+
}
|
|
2133
|
+
const ticketBody = await ticketResponse.json();
|
|
2134
|
+
const ticket = isRecord(ticketBody) && typeof ticketBody.ticket === 'string'
|
|
2135
|
+
? ticketBody.ticket
|
|
2136
|
+
: undefined;
|
|
2137
|
+
if (!ticket) {
|
|
2138
|
+
throw new Error('OpenCode returned an invalid PTY connect ticket.');
|
|
2139
|
+
}
|
|
2140
|
+
const wsUrl = `${this.baseUrl.replace(/^http:/u, 'ws:')}`
|
|
2141
|
+
+ `/pty/${encodeURIComponent(validatedPtyId)}/connect`
|
|
2142
|
+
+ `?cursor=${encodeURIComponent(String(cursor))}`
|
|
2143
|
+
+ `&ticket=${encodeURIComponent(ticket)}`
|
|
2144
|
+
+ `&directory=${encodeURIComponent(directory)}`;
|
|
2145
|
+
const socket = new WebSocket(wsUrl);
|
|
2146
|
+
socket.binaryType = 'arraybuffer';
|
|
2147
|
+
let closed = false;
|
|
2148
|
+
const finish = () => {
|
|
2149
|
+
if (closed)
|
|
2150
|
+
return;
|
|
2151
|
+
closed = true;
|
|
2152
|
+
callbacks.onClose();
|
|
2153
|
+
};
|
|
2154
|
+
socket.onmessage = (eventArg) => {
|
|
2155
|
+
const payload = eventArg.data;
|
|
2156
|
+
if (typeof payload === 'string') {
|
|
2157
|
+
callbacks.onData(Buffer.from(payload, 'utf8'));
|
|
2158
|
+
return;
|
|
2159
|
+
}
|
|
2160
|
+
if (payload instanceof ArrayBuffer) {
|
|
2161
|
+
const bytes = Buffer.from(payload);
|
|
2162
|
+
// A 0x00-prefixed frame is the JSON meta frame carrying the cursor.
|
|
2163
|
+
if (bytes.length > 0 && bytes[0] === 0) {
|
|
2164
|
+
try {
|
|
2165
|
+
const meta = JSON.parse(bytes.subarray(1).toString('utf8'));
|
|
2166
|
+
if (isRecord(meta) && typeof meta.cursor === 'number') {
|
|
2167
|
+
callbacks.onMeta?.(meta.cursor);
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
catch {
|
|
2171
|
+
// A malformed meta frame only loses resume information.
|
|
2172
|
+
}
|
|
2173
|
+
return;
|
|
2174
|
+
}
|
|
2175
|
+
callbacks.onData(bytes);
|
|
2176
|
+
}
|
|
2177
|
+
};
|
|
2178
|
+
socket.onclose = finish;
|
|
2179
|
+
socket.onerror = finish;
|
|
2180
|
+
await new Promise((resolve, reject) => {
|
|
2181
|
+
const openTimeout = setTimeout(() => {
|
|
2182
|
+
try {
|
|
2183
|
+
socket.close();
|
|
2184
|
+
}
|
|
2185
|
+
catch {
|
|
2186
|
+
// Never opened.
|
|
2187
|
+
}
|
|
2188
|
+
reject(new Error('The PTY relay connection timed out.'));
|
|
2189
|
+
}, 10_000);
|
|
2190
|
+
socket.onopen = () => {
|
|
2191
|
+
clearTimeout(openTimeout);
|
|
2192
|
+
resolve();
|
|
2193
|
+
};
|
|
2194
|
+
socket.addEventListener('close', () => {
|
|
2195
|
+
clearTimeout(openTimeout);
|
|
2196
|
+
reject(new Error('The PTY relay connection closed during setup.'));
|
|
2197
|
+
}, { once: true });
|
|
2198
|
+
});
|
|
2199
|
+
return {
|
|
2200
|
+
sendInput: (dataArg) => {
|
|
2201
|
+
if (socket.readyState === WebSocket.OPEN) {
|
|
2202
|
+
socket.send(dataArg);
|
|
2203
|
+
}
|
|
2204
|
+
},
|
|
2205
|
+
close: () => {
|
|
2206
|
+
closed = true;
|
|
2207
|
+
try {
|
|
2208
|
+
socket.close();
|
|
2209
|
+
}
|
|
2210
|
+
catch {
|
|
2211
|
+
// Already closed.
|
|
2212
|
+
}
|
|
2213
|
+
},
|
|
2214
|
+
};
|
|
2215
|
+
}
|
|
2216
|
+
async listTodos(directoryArg, sessionId, signal) {
|
|
2217
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2218
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.session.todo({
|
|
2219
|
+
sessionID: validateInputString(sessionId, 'Session ID', maxIdentifierBytes),
|
|
2220
|
+
directory,
|
|
2221
|
+
}, { signal: requestSignal }));
|
|
2222
|
+
return normalizeOpenCodeTodos(response);
|
|
2223
|
+
}
|
|
2224
|
+
async listCommands(directoryArg, signal) {
|
|
2225
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2226
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.command.list({ directory }, { signal: requestSignal }));
|
|
2227
|
+
if (!Array.isArray(response)) {
|
|
2228
|
+
throw new Error('OpenCode returned an invalid command list.');
|
|
2229
|
+
}
|
|
2230
|
+
if (response.length > 256) {
|
|
2231
|
+
throw new Error('OpenCode returned too many commands.');
|
|
2232
|
+
}
|
|
2233
|
+
return response.map((command) => {
|
|
2234
|
+
if (!isRecord(command)) {
|
|
2235
|
+
throw new Error('OpenCode returned an invalid command.');
|
|
2236
|
+
}
|
|
2237
|
+
const name = requireString(command.name, 'command name', 128);
|
|
2238
|
+
const template = truncateUtf8(requireString(command.template, 'command template', maxPromptBytes), maxPromptBytes);
|
|
2239
|
+
const description = typeof command.description === 'string' && command.description.length > 0
|
|
2240
|
+
? truncateUtf8(command.description, 1024)
|
|
2241
|
+
: undefined;
|
|
2242
|
+
const agent = typeof command.agent === 'string' && command.agent.length > 0
|
|
2243
|
+
? truncateUtf8(command.agent, 128)
|
|
2244
|
+
: undefined;
|
|
2245
|
+
const model = typeof command.model === 'string' && command.model.length > 0
|
|
2246
|
+
? truncateUtf8(command.model, 512)
|
|
2247
|
+
: undefined;
|
|
2248
|
+
return {
|
|
2249
|
+
name,
|
|
2250
|
+
...(description !== undefined ? { description } : {}),
|
|
2251
|
+
template,
|
|
2252
|
+
...(agent !== undefined ? { agent } : {}),
|
|
2253
|
+
...(model !== undefined ? { model } : {}),
|
|
2254
|
+
};
|
|
2255
|
+
});
|
|
2256
|
+
}
|
|
2257
|
+
async getSessionIntelligenceCapability(directoryArg, signal) {
|
|
2258
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2259
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.config.providers({ directory }, { signal: requestSignal }));
|
|
2260
|
+
if (!isRecord(response) || !Array.isArray(response.providers)) {
|
|
2261
|
+
throw new Error('OpenCode returned an invalid provider list.');
|
|
2262
|
+
}
|
|
2263
|
+
const provider = response.providers.find((entry) => isRecord(entry) && entry.id === sessionIntelligenceProviderId);
|
|
2264
|
+
const model = isRecord(provider) && isRecord(provider.models)
|
|
2265
|
+
? provider.models[sessionIntelligenceModelId]
|
|
2266
|
+
: undefined;
|
|
2267
|
+
if (!isRecord(model))
|
|
2268
|
+
return { enabled: false };
|
|
2269
|
+
const contextTokens = isRecord(model.limit)
|
|
2270
|
+
&& Number.isSafeInteger(model.limit.context)
|
|
2271
|
+
&& model.limit.context > 0
|
|
2272
|
+
? model.limit.context
|
|
2273
|
+
: undefined;
|
|
2274
|
+
return {
|
|
2275
|
+
enabled: true,
|
|
2276
|
+
model: sessionIntelligenceModel,
|
|
2277
|
+
...(contextTokens === undefined ? {} : { contextTokens }),
|
|
2278
|
+
};
|
|
2279
|
+
}
|
|
2280
|
+
async createSessionIntelligenceSession(directoryArg, markerArg, signal) {
|
|
2281
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2282
|
+
if (markerArg.sourceSessionId.harnessId !== 'opencode'
|
|
2283
|
+
&& markerArg.sourceSessionId.harnessId !== 'flex') {
|
|
2284
|
+
throw new Error('Session Intelligence requires an OpenCode or Flex source session.');
|
|
2285
|
+
}
|
|
2286
|
+
const capability = await this.getSessionIntelligenceCapability(directory, signal);
|
|
2287
|
+
if (!capability.enabled || capability.model !== sessionIntelligenceModel) {
|
|
2288
|
+
throw new Error(`${sessionIntelligenceModel} is not connected in OpenCode.`);
|
|
2289
|
+
}
|
|
2290
|
+
const metadata = {
|
|
2291
|
+
modelprofileSessionIntelligence: {
|
|
2292
|
+
schemaVersion: 1,
|
|
2293
|
+
controllerId: validateInputString(markerArg.controllerId, 'Controller ID', 512),
|
|
2294
|
+
projectId: validateInputString(markerArg.projectId, 'Project ID', 64),
|
|
2295
|
+
sourceSessionId: {
|
|
2296
|
+
harnessId: markerArg.sourceSessionId.harnessId,
|
|
2297
|
+
nativeId: validateInputString(markerArg.sourceSessionId.nativeId, 'Source session ID', maxIdentifierBytes),
|
|
2298
|
+
},
|
|
2299
|
+
exchangeId: validateInputString(markerArg.exchangeId, 'Exchange ID', 128),
|
|
2300
|
+
},
|
|
2301
|
+
};
|
|
2302
|
+
const permission = [{ permission: '*', pattern: '*', action: 'deny' }];
|
|
2303
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.session.create({
|
|
2304
|
+
directory,
|
|
2305
|
+
title: sessionIntelligenceTitle,
|
|
2306
|
+
agent: 'plan',
|
|
2307
|
+
model: {
|
|
2308
|
+
providerID: sessionIntelligenceProviderId,
|
|
2309
|
+
id: sessionIntelligenceModelId,
|
|
2310
|
+
},
|
|
2311
|
+
metadata,
|
|
2312
|
+
permission,
|
|
2313
|
+
}, { signal: requestSignal }));
|
|
2314
|
+
if (!isRecord(response)) {
|
|
2315
|
+
throw new Error('OpenCode returned an invalid Session Intelligence session.');
|
|
2316
|
+
}
|
|
2317
|
+
const sessionId = requireString(response.id, 'Session Intelligence session ID', maxIdentifierBytes);
|
|
2318
|
+
const responsePermission = response.permission;
|
|
2319
|
+
if (response.directory !== directory
|
|
2320
|
+
|| response.title !== sessionIntelligenceTitle
|
|
2321
|
+
|| response.agent !== 'plan'
|
|
2322
|
+
|| !isRecord(response.model)
|
|
2323
|
+
|| !hasExactKeys(response.model, ['id', 'providerID'])
|
|
2324
|
+
|| response.model.id !== sessionIntelligenceModelId
|
|
2325
|
+
|| response.model.providerID !== sessionIntelligenceProviderId
|
|
2326
|
+
|| !Array.isArray(responsePermission)
|
|
2327
|
+
|| responsePermission.length !== 1
|
|
2328
|
+
|| !isRecord(responsePermission[0])
|
|
2329
|
+
|| !hasExactKeys(responsePermission[0], ['permission', 'pattern', 'action'])
|
|
2330
|
+
|| responsePermission[0].permission !== '*'
|
|
2331
|
+
|| responsePermission[0].pattern !== '*'
|
|
2332
|
+
|| responsePermission[0].action !== 'deny'
|
|
2333
|
+
|| !isSessionIntelligenceMetadata(response.metadata, markerArg.controllerId, markerArg)) {
|
|
2334
|
+
const isolationError = new Error('OpenCode did not preserve the Session Intelligence isolation contract.');
|
|
2335
|
+
this.rememberTemporarySessionId(sessionId);
|
|
2336
|
+
try {
|
|
2337
|
+
await this.deleteSessionIntelligenceSession(directory, sessionId, AbortSignal.timeout(10_000));
|
|
2338
|
+
}
|
|
2339
|
+
catch (cleanupError) {
|
|
2340
|
+
throw new OpenCodeSessionIntelligenceCleanupError(sessionId, isolationError, cleanupError);
|
|
2341
|
+
}
|
|
2342
|
+
throw isolationError;
|
|
2343
|
+
}
|
|
2344
|
+
this.rememberTemporarySessionId(sessionId);
|
|
2345
|
+
return sessionId;
|
|
2346
|
+
}
|
|
2347
|
+
async runSessionIntelligence(directoryArg, temporarySessionIdArg, promptArg, signal) {
|
|
2348
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2349
|
+
const temporarySessionId = validateInputString(temporarySessionIdArg, 'Session Intelligence session ID', maxIdentifierBytes);
|
|
2350
|
+
const prompt = validateInputString(promptArg, 'Session Intelligence prompt', 512 * 1024);
|
|
2351
|
+
try {
|
|
2352
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.session.prompt({
|
|
2353
|
+
sessionID: temporarySessionId,
|
|
2354
|
+
directory,
|
|
2355
|
+
model: {
|
|
2356
|
+
providerID: sessionIntelligenceProviderId,
|
|
2357
|
+
modelID: sessionIntelligenceModelId,
|
|
2358
|
+
},
|
|
2359
|
+
agent: 'plan',
|
|
2360
|
+
system: [
|
|
2361
|
+
'You are Session Intelligence. Analyze only the supplied session transcript and scratchpad.',
|
|
2362
|
+
'Do not assume access to tools or files. Answer the question and return a concise updated scratchpad.',
|
|
2363
|
+
].join(' '),
|
|
2364
|
+
format: {
|
|
2365
|
+
type: 'json_schema',
|
|
2366
|
+
retryCount: 2,
|
|
2367
|
+
schema: {
|
|
2368
|
+
type: 'object',
|
|
2369
|
+
additionalProperties: false,
|
|
2370
|
+
properties: {
|
|
2371
|
+
answer: { type: 'string', maxLength: 32768 },
|
|
2372
|
+
scratchpad: { type: 'string', maxLength: 32768 },
|
|
2373
|
+
},
|
|
2374
|
+
required: ['answer', 'scratchpad'],
|
|
2375
|
+
},
|
|
2376
|
+
},
|
|
2377
|
+
parts: [{ type: 'text', text: prompt }],
|
|
2378
|
+
}, { signal: requestSignal }), sessionIntelligenceTimeoutMs);
|
|
2379
|
+
if (!isRecord(response) || !isRecord(response.info)) {
|
|
2380
|
+
throw new Error('OpenCode returned an invalid Session Intelligence response.');
|
|
2381
|
+
}
|
|
2382
|
+
const responseInfo = response.info;
|
|
2383
|
+
if (responseInfo.sessionID !== temporarySessionId
|
|
2384
|
+
|| responseInfo.role !== 'assistant'
|
|
2385
|
+
|| responseInfo.providerID !== sessionIntelligenceProviderId
|
|
2386
|
+
|| responseInfo.modelID !== sessionIntelligenceModelId
|
|
2387
|
+
|| responseInfo.agent !== 'plan') {
|
|
2388
|
+
throw new Error('OpenCode returned Session Intelligence output from a different execution context.');
|
|
2389
|
+
}
|
|
2390
|
+
if (responseInfo.error !== undefined) {
|
|
2391
|
+
throw new Error(normalizeErrorText(responseInfo.error) ?? 'Session Intelligence model execution failed.');
|
|
2392
|
+
}
|
|
2393
|
+
const structured = responseInfo.structured;
|
|
2394
|
+
if (!isRecord(structured)
|
|
2395
|
+
|| !hasExactKeys(structured, ['answer', 'scratchpad'])
|
|
2396
|
+
|| typeof structured.answer !== 'string'
|
|
2397
|
+
|| typeof structured.scratchpad !== 'string'
|
|
2398
|
+
|| structured.answer.length > 32_768
|
|
2399
|
+
|| structured.scratchpad.length > 32_768
|
|
2400
|
+
|| Buffer.byteLength(structured.answer, 'utf8') > 128 * 1024
|
|
2401
|
+
|| Buffer.byteLength(structured.scratchpad, 'utf8') > 128 * 1024) {
|
|
2402
|
+
throw new Error('OpenCode returned invalid structured Session Intelligence output.');
|
|
2403
|
+
}
|
|
2404
|
+
return {
|
|
2405
|
+
answer: structured.answer,
|
|
2406
|
+
scratchpad: structured.scratchpad,
|
|
2407
|
+
model: sessionIntelligenceModel,
|
|
2408
|
+
};
|
|
2409
|
+
}
|
|
2410
|
+
catch (errorArg) {
|
|
2411
|
+
await this.abortSession(directory, temporarySessionId, AbortSignal.timeout(10_000)).catch(() => undefined);
|
|
2412
|
+
throw errorArg;
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
async deleteSessionIntelligenceSession(directoryArg, temporarySessionIdArg, signal) {
|
|
2416
|
+
const sessionId = validateInputString(temporarySessionIdArg, 'Session Intelligence session ID', maxIdentifierBytes);
|
|
2417
|
+
this.rememberTemporarySessionId(sessionId);
|
|
2418
|
+
try {
|
|
2419
|
+
const deleted = await this.deleteSession(directoryArg, sessionId, signal);
|
|
2420
|
+
if (!deleted)
|
|
2421
|
+
throw new Error('OpenCode did not delete the Session Intelligence session.');
|
|
2422
|
+
}
|
|
2423
|
+
catch (errorArg) {
|
|
2424
|
+
if (!isOpenCodeNotFoundError(errorArg))
|
|
2425
|
+
throw errorArg;
|
|
2426
|
+
}
|
|
2427
|
+
this.temporarySessionIds.delete(sessionId);
|
|
2428
|
+
}
|
|
2429
|
+
rememberSessionIntelligenceTemporarySessionIds(sessionIdsArg) {
|
|
2430
|
+
if (sessionIdsArg.length > maxSessionIntelligenceCleanupObligations) {
|
|
2431
|
+
throw new Error('Too many Session Intelligence cleanup obligations were supplied.');
|
|
2432
|
+
}
|
|
2433
|
+
for (const sessionId of sessionIdsArg) {
|
|
2434
|
+
this.rememberTemporarySessionId(validateInputString(sessionId, 'Session Intelligence session ID', maxIdentifierBytes));
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
getRememberedSessionIntelligenceTemporarySessionIds() {
|
|
2438
|
+
return [...this.temporarySessionIds];
|
|
2439
|
+
}
|
|
2440
|
+
async cleanupOrphanedSessionIntelligenceSessions(directoryArg, controllerIdArg, olderThanArg, signal) {
|
|
2441
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2442
|
+
const controllerId = validateInputString(controllerIdArg, 'Controller ID', 512);
|
|
2443
|
+
if (!Number.isFinite(olderThanArg) || olderThanArg < 0) {
|
|
2444
|
+
throw new Error('The Session Intelligence orphan cutoff is invalid.');
|
|
2445
|
+
}
|
|
2446
|
+
let exhaustive = false;
|
|
2447
|
+
let start = 0;
|
|
2448
|
+
let deleted = 0;
|
|
2449
|
+
const deletionErrors = [];
|
|
2450
|
+
for (let pageIndex = 0; pageIndex < 16; pageIndex += 1) {
|
|
2451
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.session.list({
|
|
2452
|
+
directory,
|
|
2453
|
+
roots: true,
|
|
2454
|
+
search: sessionIntelligenceTitle,
|
|
2455
|
+
start,
|
|
2456
|
+
limit: maxMessagesPerRequest,
|
|
2457
|
+
}, { signal: requestSignal }));
|
|
2458
|
+
if (!Array.isArray(response) || response.length > maxMessagesPerRequest) {
|
|
2459
|
+
throw new Error('OpenCode returned an invalid Session Intelligence orphan list.');
|
|
2460
|
+
}
|
|
2461
|
+
const candidateIds = [];
|
|
2462
|
+
for (const session of response) {
|
|
2463
|
+
if (!isRecord(session)
|
|
2464
|
+
|| !isRecord(session.time)
|
|
2465
|
+
|| !isSessionIntelligenceMetadata(session.metadata, controllerId)
|
|
2466
|
+
|| optionalFiniteNumber(session.time.created) === undefined
|
|
2467
|
+
|| session.time.created >= olderThanArg)
|
|
2468
|
+
continue;
|
|
2469
|
+
candidateIds.push(requireString(session.id, 'Session Intelligence session ID', maxIdentifierBytes));
|
|
2470
|
+
}
|
|
2471
|
+
let pageDeleted = 0;
|
|
2472
|
+
for (const candidateId of candidateIds) {
|
|
2473
|
+
this.rememberTemporarySessionId(candidateId);
|
|
2474
|
+
try {
|
|
2475
|
+
await this.deleteSessionIntelligenceSession(directory, candidateId, signal);
|
|
2476
|
+
deleted += 1;
|
|
2477
|
+
pageDeleted += 1;
|
|
2478
|
+
}
|
|
2479
|
+
catch (errorArg) {
|
|
2480
|
+
deletionErrors.push(errorArg);
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
if (response.length < maxMessagesPerRequest) {
|
|
2484
|
+
exhaustive = true;
|
|
2485
|
+
break;
|
|
2486
|
+
}
|
|
2487
|
+
// Successful deletions shift later offset pages left. Advance only past
|
|
2488
|
+
// the sessions that remain so no unscanned session is skipped.
|
|
2489
|
+
start += response.length - pageDeleted;
|
|
2490
|
+
}
|
|
2491
|
+
if (deletionErrors.length > 0) {
|
|
2492
|
+
throw new AggregateError(deletionErrors, 'One or more orphaned Session Intelligence sessions could not be deleted.');
|
|
2493
|
+
}
|
|
2494
|
+
if (!exhaustive) {
|
|
2495
|
+
throw new Error(`Session Intelligence orphan cleanup deleted ${deleted} session(s) before exceeding its bounded scan.`);
|
|
2496
|
+
}
|
|
2497
|
+
return deleted;
|
|
2498
|
+
}
|
|
2499
|
+
rememberTemporarySessionId(sessionIdArg) {
|
|
2500
|
+
this.temporarySessionIds.delete(sessionIdArg);
|
|
2501
|
+
this.temporarySessionIds.add(sessionIdArg);
|
|
2502
|
+
while (this.temporarySessionIds.size > 2_048) {
|
|
2503
|
+
const oldestSessionId = this.temporarySessionIds.values().next().value;
|
|
2504
|
+
if (oldestSessionId === undefined)
|
|
2505
|
+
break;
|
|
2506
|
+
this.temporarySessionIds.delete(oldestSessionId);
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
async listModelOptions(signal) {
|
|
2510
|
+
const response = await runSdkRequest(signal, (requestSignal) => this.client.config.providers({ directory: this.directory }, { signal: requestSignal }));
|
|
2511
|
+
if (!isRecord(response) || !Array.isArray(response.providers)) {
|
|
2512
|
+
throw new Error('OpenCode returned an invalid provider list.');
|
|
2513
|
+
}
|
|
2514
|
+
if (response.providers.length > 64) {
|
|
2515
|
+
throw new Error('OpenCode returned too many providers.');
|
|
2516
|
+
}
|
|
2517
|
+
const options = [];
|
|
2518
|
+
for (const provider of response.providers) {
|
|
2519
|
+
if (!isRecord(provider) || !isRecord(provider.models)) {
|
|
2520
|
+
throw new Error('OpenCode returned an invalid provider.');
|
|
2521
|
+
}
|
|
2522
|
+
const providerID = requireString(provider.id, 'provider ID', 256);
|
|
2523
|
+
const providerName = typeof provider.name === 'string' && provider.name.length > 0
|
|
2524
|
+
? truncateUtf8(provider.name, 256)
|
|
2525
|
+
: providerID;
|
|
2526
|
+
const modelEntries = Object.entries(provider.models);
|
|
2527
|
+
if (modelEntries.length > 256) {
|
|
2528
|
+
throw new Error('OpenCode returned too many models for one provider.');
|
|
2529
|
+
}
|
|
2530
|
+
for (const [modelKey, model] of modelEntries) {
|
|
2531
|
+
if (modelKey === '__proto__'
|
|
2532
|
+
|| modelKey === 'constructor'
|
|
2533
|
+
|| modelKey === 'prototype')
|
|
2534
|
+
continue;
|
|
2535
|
+
const modelID = requireString(modelKey, 'model ID', 256);
|
|
2536
|
+
const modelName = isRecord(model) && typeof model.name === 'string' && model.name.length > 0
|
|
2537
|
+
? truncateUtf8(model.name, 256)
|
|
2538
|
+
: modelID;
|
|
2539
|
+
const variants = normalizeModelVariants(isRecord(model) ? model.variants : undefined);
|
|
2540
|
+
options.push({
|
|
2541
|
+
harnessId: openCodeHarnessId,
|
|
2542
|
+
providerID,
|
|
2543
|
+
providerName,
|
|
2544
|
+
modelID,
|
|
2545
|
+
modelName,
|
|
2546
|
+
variants,
|
|
2547
|
+
});
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
if (options.length > 2048) {
|
|
2551
|
+
throw new Error('OpenCode returned too many models.');
|
|
2552
|
+
}
|
|
2553
|
+
return options;
|
|
2554
|
+
}
|
|
2555
|
+
async getSessionDetail(directoryArg, sessionId, signal) {
|
|
2556
|
+
const directory = this.requireDirectory(directoryArg);
|
|
2557
|
+
const validatedSessionId = validateInputString(sessionId, 'Session ID', maxIdentifierBytes);
|
|
2558
|
+
const [session, messagePage, permissions, questions, todos] = await Promise.all([
|
|
2559
|
+
this.getSession(directory, validatedSessionId, signal),
|
|
2560
|
+
this.listMessagePage(directory, validatedSessionId, { limit: controllerInitialMessageBundleLimit }, signal),
|
|
2561
|
+
this.listPermissions(directory, validatedSessionId, signal),
|
|
2562
|
+
this.listQuestions(directory, validatedSessionId, signal),
|
|
2563
|
+
this.listTodos(directory, validatedSessionId, signal),
|
|
2564
|
+
]);
|
|
2565
|
+
const messages = messagePage.bundles.flatMap((bundle) => bundle.messages);
|
|
2566
|
+
let model;
|
|
2567
|
+
let effort;
|
|
2568
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
2569
|
+
const candidate = messages[index];
|
|
2570
|
+
if (candidate.role === 'assistant' && candidate.model) {
|
|
2571
|
+
model = candidate.model;
|
|
2572
|
+
effort = candidate.effort;
|
|
2573
|
+
break;
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
const detail = {
|
|
2577
|
+
session,
|
|
2578
|
+
messagePage,
|
|
2579
|
+
permissions,
|
|
2580
|
+
questions,
|
|
2581
|
+
todos,
|
|
2582
|
+
...(model ? { model } : {}),
|
|
2583
|
+
...(effort ? { effort } : {}),
|
|
2584
|
+
};
|
|
2585
|
+
return detail;
|
|
2586
|
+
}
|
|
2587
|
+
startEventStream(options) {
|
|
2588
|
+
if (this.eventTask) {
|
|
2589
|
+
throw new Error('The OpenCode event stream is already running.');
|
|
2590
|
+
}
|
|
2591
|
+
const abortController = new AbortController();
|
|
2592
|
+
this.eventAbortController = abortController;
|
|
2593
|
+
const signal = options.signal
|
|
2594
|
+
? AbortSignal.any([abortController.signal, options.signal])
|
|
2595
|
+
: abortController.signal;
|
|
2596
|
+
const task = this.consumeEventStream(options, signal).finally(() => {
|
|
2597
|
+
this.clearLiveMessagePartCache();
|
|
2598
|
+
});
|
|
2599
|
+
this.eventTask = task;
|
|
2600
|
+
task.then(() => {
|
|
2601
|
+
if (this.eventTask === task) {
|
|
2602
|
+
this.eventTask = undefined;
|
|
2603
|
+
this.eventAbortController = undefined;
|
|
2604
|
+
}
|
|
2605
|
+
}, () => {
|
|
2606
|
+
if (this.eventTask === task) {
|
|
2607
|
+
this.eventTask = undefined;
|
|
2608
|
+
this.eventAbortController = undefined;
|
|
2609
|
+
}
|
|
2610
|
+
});
|
|
2611
|
+
return task;
|
|
2612
|
+
}
|
|
2613
|
+
async stopEventStream() {
|
|
2614
|
+
const task = this.eventTask;
|
|
2615
|
+
if (!task) {
|
|
2616
|
+
this.clearLiveMessagePartCache();
|
|
2617
|
+
return;
|
|
2618
|
+
}
|
|
2619
|
+
const abortController = this.eventAbortController;
|
|
2620
|
+
abortController?.abort();
|
|
2621
|
+
try {
|
|
2622
|
+
await task;
|
|
2623
|
+
}
|
|
2624
|
+
catch (error) {
|
|
2625
|
+
if (!abortController?.signal.aborted) {
|
|
2626
|
+
throw error;
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2629
|
+
finally {
|
|
2630
|
+
this.clearLiveMessagePartCache();
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
liveMessagePartKey(directoryArg, sessionIdArg, messageIdArg, partIdArg) {
|
|
2634
|
+
return JSON.stringify([directoryArg, sessionIdArg, messageIdArg, partIdArg]);
|
|
2635
|
+
}
|
|
2636
|
+
clearLiveMessagePartCache() {
|
|
2637
|
+
this.liveMessagePartCache.clear();
|
|
2638
|
+
this.liveMessagePartCacheBytes = 0;
|
|
2639
|
+
}
|
|
2640
|
+
clearLiveMessagePartsForSession(directoryArg, sessionIdArg) {
|
|
2641
|
+
for (const [key, entry] of this.liveMessagePartCache) {
|
|
2642
|
+
if (entry.directory === directoryArg
|
|
2643
|
+
&& entry.update.sessionId.nativeId === sessionIdArg) {
|
|
2644
|
+
this.liveMessagePartCache.delete(key);
|
|
2645
|
+
this.liveMessagePartCacheBytes = Math.max(0, this.liveMessagePartCacheBytes - entry.bytes);
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
clearLiveMessagePartsForMessage(directoryArg, sessionIdArg, messageIdArg) {
|
|
2650
|
+
for (const [key, entry] of this.liveMessagePartCache) {
|
|
2651
|
+
if (entry.directory === directoryArg
|
|
2652
|
+
&& entry.update.sessionId.nativeId === sessionIdArg
|
|
2653
|
+
&& entry.update.messageId.nativeId === messageIdArg) {
|
|
2654
|
+
this.liveMessagePartCache.delete(key);
|
|
2655
|
+
this.liveMessagePartCacheBytes = Math.max(0, this.liveMessagePartCacheBytes - entry.bytes);
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
projectLiveMessageUpdate(directoryArg, sessionIdArg, messageIdArg, updateArg) {
|
|
2660
|
+
if (updateArg.type === 'reasoning')
|
|
2661
|
+
return updateArg;
|
|
2662
|
+
const textEntries = [...this.liveMessagePartCache.values()].filter((entryArg) => (entryArg.directory === directoryArg
|
|
2663
|
+
&& entryArg.type === 'text'
|
|
2664
|
+
&& !entryArg.ignored
|
|
2665
|
+
&& entryArg.update.sessionId.nativeId === sessionIdArg
|
|
2666
|
+
&& entryArg.update.messageId.nativeId === messageIdArg));
|
|
2667
|
+
if (textEntries.length === 0)
|
|
2668
|
+
return undefined;
|
|
2669
|
+
const text = textEntries.map((entryArg) => entryArg.update.text).join('\n\n');
|
|
2670
|
+
if (Buffer.byteLength(text, 'utf8') > maxMessageTextBytes)
|
|
2671
|
+
return undefined;
|
|
2672
|
+
const update = {
|
|
2673
|
+
sessionId: openCodeRuntimeId(sessionIdArg),
|
|
2674
|
+
messageId: openCodeRuntimeId(messageIdArg),
|
|
2675
|
+
// OpenCode normalizes every text part into one source-message entry.
|
|
2676
|
+
partId: openCodeRuntimeId(messageIdArg),
|
|
2677
|
+
text,
|
|
2678
|
+
status: textEntries.some((entryArg) => entryArg.update.status === 'running')
|
|
2679
|
+
? 'running'
|
|
2680
|
+
: 'completed',
|
|
2681
|
+
sourceUpdatedAt: Math.max(...textEntries.map((entryArg) => entryArg.update.sourceUpdatedAt)),
|
|
2682
|
+
};
|
|
2683
|
+
if (Buffer.byteLength(JSON.stringify(update), 'utf8') > maxLiveMessageSnapshotBytes) {
|
|
2684
|
+
return undefined;
|
|
2685
|
+
}
|
|
2686
|
+
return { type: 'text', update };
|
|
2687
|
+
}
|
|
2688
|
+
normalizeLiveMessageStreamEvent(valueArg) {
|
|
2689
|
+
if (!isRecord(valueArg)
|
|
2690
|
+
|| typeof valueArg.directory !== 'string'
|
|
2691
|
+
|| valueArg.directory.length === 0
|
|
2692
|
+
|| Buffer.byteLength(valueArg.directory, 'utf8') > 4096
|
|
2693
|
+
|| !isRecord(valueArg.payload)
|
|
2694
|
+
|| !isRecord(valueArg.payload.properties))
|
|
2695
|
+
return undefined;
|
|
2696
|
+
const directory = valueArg.directory;
|
|
2697
|
+
const payload = valueArg.payload;
|
|
2698
|
+
const properties = payload.properties;
|
|
2699
|
+
const sessionNativeId = typeof properties.sessionID === 'string'
|
|
2700
|
+
? properties.sessionID
|
|
2701
|
+
: undefined;
|
|
2702
|
+
const gap = () => {
|
|
2703
|
+
this.clearLiveMessagePartCache();
|
|
2704
|
+
return {
|
|
2705
|
+
directory,
|
|
2706
|
+
...(sessionNativeId === undefined ? {} : { sessionNativeId }),
|
|
2707
|
+
messageStreamGap: true,
|
|
2708
|
+
};
|
|
2709
|
+
};
|
|
2710
|
+
if (payload.type === 'message.part.updated') {
|
|
2711
|
+
if (!isRecord(properties.part)) {
|
|
2712
|
+
this.clearLiveMessagePartCache();
|
|
2713
|
+
return {
|
|
2714
|
+
directory,
|
|
2715
|
+
...(sessionNativeId === undefined ? {} : { sessionNativeId }),
|
|
2716
|
+
sharedStreamGap: true,
|
|
2717
|
+
};
|
|
2718
|
+
}
|
|
2719
|
+
const part = properties.part;
|
|
2720
|
+
if (part.type !== 'text' && part.type !== 'reasoning')
|
|
2721
|
+
return undefined;
|
|
2722
|
+
try {
|
|
2723
|
+
const validatedSessionId = requireString(properties.sessionID, 'live message event session ID', maxIdentifierBytes);
|
|
2724
|
+
const partSessionId = requireString(part.sessionID, 'live message part session ID', maxIdentifierBytes);
|
|
2725
|
+
const messageId = requireString(part.messageID, 'live message part message ID', maxIdentifierBytes);
|
|
2726
|
+
const partId = requireString(part.id, 'live message part ID', maxIdentifierBytes);
|
|
2727
|
+
if (partSessionId !== validatedSessionId || typeof part.text !== 'string')
|
|
2728
|
+
return gap();
|
|
2729
|
+
const sourceUpdatedAt = optionalFiniteNumber(properties.time) ?? Date.now();
|
|
2730
|
+
const endedAt = isRecord(part.time) ? optionalFiniteNumber(part.time.end) : undefined;
|
|
2731
|
+
const common = {
|
|
2732
|
+
sessionId: openCodeRuntimeId(validatedSessionId),
|
|
2733
|
+
messageId: openCodeRuntimeId(messageId),
|
|
2734
|
+
partId: openCodeRuntimeId(partId),
|
|
2735
|
+
text: part.text,
|
|
2736
|
+
status: endedAt === undefined ? 'running' : 'completed',
|
|
2737
|
+
sourceUpdatedAt,
|
|
2738
|
+
};
|
|
2739
|
+
const update = part.type === 'text'
|
|
2740
|
+
? { type: 'text', update: common }
|
|
2741
|
+
: { type: 'reasoning', update: common };
|
|
2742
|
+
const ignored = part.type === 'text' && part.ignored === true;
|
|
2743
|
+
const bytes = Buffer.byteLength(JSON.stringify(update.update), 'utf8');
|
|
2744
|
+
if (bytes > maxLiveMessageSnapshotBytes)
|
|
2745
|
+
return gap();
|
|
2746
|
+
const key = this.liveMessagePartKey(directory, validatedSessionId, messageId, partId);
|
|
2747
|
+
const existing = this.liveMessagePartCache.get(key);
|
|
2748
|
+
if (!existing && !ignored && (part.text.length > 0 || endedAt !== undefined))
|
|
2749
|
+
return gap();
|
|
2750
|
+
const nextTotalBytes = this.liveMessagePartCacheBytes - (existing?.bytes ?? 0) + bytes;
|
|
2751
|
+
if ((!existing && this.liveMessagePartCache.size >= maxLiveMessagePartCacheEntries)
|
|
2752
|
+
|| nextTotalBytes > maxLiveMessagePartCacheBytes)
|
|
2753
|
+
return gap();
|
|
2754
|
+
this.liveMessagePartCache.set(key, {
|
|
2755
|
+
directory,
|
|
2756
|
+
type: update.type,
|
|
2757
|
+
update: update.update,
|
|
2758
|
+
ignored,
|
|
2759
|
+
bytes,
|
|
2760
|
+
});
|
|
2761
|
+
this.liveMessagePartCacheBytes = nextTotalBytes;
|
|
2762
|
+
if (ignored)
|
|
2763
|
+
return undefined;
|
|
2764
|
+
const projected = this.projectLiveMessageUpdate(directory, validatedSessionId, messageId, update);
|
|
2765
|
+
return projected
|
|
2766
|
+
? { directory, sessionNativeId: validatedSessionId, update: projected }
|
|
2767
|
+
: gap();
|
|
2768
|
+
}
|
|
2769
|
+
catch {
|
|
2770
|
+
return gap();
|
|
2771
|
+
}
|
|
2772
|
+
}
|
|
2773
|
+
if (payload.type === 'message.part.delta') {
|
|
2774
|
+
try {
|
|
2775
|
+
const validatedSessionId = requireString(properties.sessionID, 'live message delta session ID', maxIdentifierBytes);
|
|
2776
|
+
const messageId = requireString(properties.messageID, 'live message delta message ID', maxIdentifierBytes);
|
|
2777
|
+
const partId = requireString(properties.partID, 'live message delta part ID', maxIdentifierBytes);
|
|
2778
|
+
if (properties.field !== 'text' || typeof properties.delta !== 'string')
|
|
2779
|
+
return gap();
|
|
2780
|
+
const key = this.liveMessagePartKey(directory, validatedSessionId, messageId, partId);
|
|
2781
|
+
const existing = this.liveMessagePartCache.get(key);
|
|
2782
|
+
if (!existing)
|
|
2783
|
+
return gap();
|
|
2784
|
+
const update = {
|
|
2785
|
+
...existing.update,
|
|
2786
|
+
text: `${existing.update.text}${properties.delta}`,
|
|
2787
|
+
sourceUpdatedAt: Date.now(),
|
|
2788
|
+
};
|
|
2789
|
+
const bytes = Buffer.byteLength(JSON.stringify(update), 'utf8');
|
|
2790
|
+
const nextTotalBytes = this.liveMessagePartCacheBytes - existing.bytes + bytes;
|
|
2791
|
+
if (bytes > maxLiveMessageSnapshotBytes || nextTotalBytes > maxLiveMessagePartCacheBytes) {
|
|
2792
|
+
return gap();
|
|
2793
|
+
}
|
|
2794
|
+
const normalizedUpdate = existing.type === 'text'
|
|
2795
|
+
? { type: 'text', update: update }
|
|
2796
|
+
: { type: 'reasoning', update: update };
|
|
2797
|
+
this.liveMessagePartCache.set(key, {
|
|
2798
|
+
directory,
|
|
2799
|
+
type: normalizedUpdate.type,
|
|
2800
|
+
update: normalizedUpdate.update,
|
|
2801
|
+
ignored: existing.ignored,
|
|
2802
|
+
bytes,
|
|
2803
|
+
});
|
|
2804
|
+
this.liveMessagePartCacheBytes = nextTotalBytes;
|
|
2805
|
+
if (existing.ignored)
|
|
2806
|
+
return undefined;
|
|
2807
|
+
const projected = this.projectLiveMessageUpdate(directory, validatedSessionId, messageId, normalizedUpdate);
|
|
2808
|
+
return projected
|
|
2809
|
+
? { directory, sessionNativeId: validatedSessionId, update: projected }
|
|
2810
|
+
: gap();
|
|
2811
|
+
}
|
|
2812
|
+
catch {
|
|
2813
|
+
return gap();
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2816
|
+
if (payload.type === 'message.part.removed') {
|
|
2817
|
+
try {
|
|
2818
|
+
const validatedSessionId = requireString(properties.sessionID, 'removed message part session ID', maxIdentifierBytes);
|
|
2819
|
+
const messageId = requireString(properties.messageID, 'removed message part message ID', maxIdentifierBytes);
|
|
2820
|
+
const partId = requireString(properties.partID, 'removed message part ID', maxIdentifierBytes);
|
|
2821
|
+
const key = this.liveMessagePartKey(directory, validatedSessionId, messageId, partId);
|
|
2822
|
+
const existing = this.liveMessagePartCache.get(key);
|
|
2823
|
+
if (existing) {
|
|
2824
|
+
this.liveMessagePartCache.delete(key);
|
|
2825
|
+
this.liveMessagePartCacheBytes = Math.max(0, this.liveMessagePartCacheBytes - existing.bytes);
|
|
2826
|
+
}
|
|
2827
|
+
this.clearLiveMessagePartCache();
|
|
2828
|
+
return { directory, sessionNativeId: validatedSessionId, sharedStreamGap: true };
|
|
2829
|
+
}
|
|
2830
|
+
catch {
|
|
2831
|
+
this.clearLiveMessagePartCache();
|
|
2832
|
+
return {
|
|
2833
|
+
directory,
|
|
2834
|
+
...(sessionNativeId === undefined ? {} : { sessionNativeId }),
|
|
2835
|
+
sharedStreamGap: true,
|
|
2836
|
+
};
|
|
2837
|
+
}
|
|
2838
|
+
}
|
|
2839
|
+
if (payload.type === 'message.removed') {
|
|
2840
|
+
try {
|
|
2841
|
+
const validatedSessionId = requireString(properties.sessionID, 'removed message session ID', maxIdentifierBytes);
|
|
2842
|
+
const messageId = requireString(properties.messageID, 'removed message ID', maxIdentifierBytes);
|
|
2843
|
+
for (const [key, entry] of this.liveMessagePartCache) {
|
|
2844
|
+
if (entry.directory === directory
|
|
2845
|
+
&& controllerRuntimeIdsEqual(entry.update.sessionId, openCodeRuntimeId(validatedSessionId))
|
|
2846
|
+
&& controllerRuntimeIdsEqual(entry.update.messageId, openCodeRuntimeId(messageId))) {
|
|
2847
|
+
this.liveMessagePartCache.delete(key);
|
|
2848
|
+
this.liveMessagePartCacheBytes = Math.max(0, this.liveMessagePartCacheBytes - entry.bytes);
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2851
|
+
this.clearLiveMessagePartCache();
|
|
2852
|
+
return { directory, sessionNativeId: validatedSessionId, sharedStreamGap: true };
|
|
2853
|
+
}
|
|
2854
|
+
catch {
|
|
2855
|
+
this.clearLiveMessagePartCache();
|
|
2856
|
+
return {
|
|
2857
|
+
directory,
|
|
2858
|
+
...(sessionNativeId === undefined ? {} : { sessionNativeId }),
|
|
2859
|
+
sharedStreamGap: true,
|
|
2860
|
+
};
|
|
2861
|
+
}
|
|
2862
|
+
}
|
|
2863
|
+
return undefined;
|
|
2864
|
+
}
|
|
2865
|
+
async consumeEventStream(options, signal) {
|
|
2866
|
+
let resubscribeDelayMs = eventStreamResubscribeDelayMs;
|
|
2867
|
+
while (!signal.aborted) {
|
|
2868
|
+
let lastStreamError;
|
|
2869
|
+
try {
|
|
2870
|
+
const subscription = await this.client.global.event({
|
|
2871
|
+
signal,
|
|
2872
|
+
// One SDK attempt avoids its non-abortable retry sleep. The adapter's
|
|
2873
|
+
// outer loop owns reconnect backoff so stopEventStream stays prompt.
|
|
2874
|
+
sseMaxRetryAttempts: 1,
|
|
2875
|
+
sseDefaultRetryDelay: eventStreamResubscribeDelayMs,
|
|
2876
|
+
sseMaxRetryDelay: eventStreamMaxResubscribeDelayMs,
|
|
2877
|
+
onSseError: (error) => {
|
|
2878
|
+
if (signal.aborted)
|
|
2879
|
+
return;
|
|
2880
|
+
lastStreamError = asError(error, 'The OpenCode event stream failed.');
|
|
2881
|
+
try {
|
|
2882
|
+
options.onError?.(lastStreamError);
|
|
2883
|
+
}
|
|
2884
|
+
catch {
|
|
2885
|
+
// Diagnostics must not terminate stream recovery.
|
|
2886
|
+
}
|
|
2887
|
+
},
|
|
2888
|
+
});
|
|
2889
|
+
for await (const event of subscription.stream) {
|
|
2890
|
+
if (signal.aborted)
|
|
2891
|
+
return;
|
|
2892
|
+
if (isRecord(event)
|
|
2893
|
+
&& isRecord(event.payload)
|
|
2894
|
+
&& event.payload.type === 'server.connected') {
|
|
2895
|
+
lastStreamError = undefined;
|
|
2896
|
+
resubscribeDelayMs = eventStreamResubscribeDelayMs;
|
|
2897
|
+
this.clearLiveMessagePartCache();
|
|
2898
|
+
await options.onConnected?.();
|
|
2899
|
+
continue;
|
|
2900
|
+
}
|
|
2901
|
+
const messageStreamSessionId = messageStreamEventSessionId(event);
|
|
2902
|
+
if (messageStreamSessionId !== undefined
|
|
2903
|
+
&& this.temporarySessionIds.has(messageStreamSessionId))
|
|
2904
|
+
continue;
|
|
2905
|
+
const normalizedMessageStream = this.normalizeLiveMessageStreamEvent(event);
|
|
2906
|
+
if (normalizedMessageStream) {
|
|
2907
|
+
if (normalizedMessageStream.sessionNativeId !== undefined) {
|
|
2908
|
+
this.sessionMetricsCache.delete(this.sessionMetricsCacheKey(normalizedMessageStream.directory, normalizedMessageStream.sessionNativeId));
|
|
2909
|
+
}
|
|
2910
|
+
if ('sharedStreamGap' in normalizedMessageStream) {
|
|
2911
|
+
if (options.onStreamGap) {
|
|
2912
|
+
await options.onStreamGap();
|
|
2913
|
+
}
|
|
2914
|
+
else {
|
|
2915
|
+
await options.onToolStreamGap?.();
|
|
2916
|
+
await options.onMessageStreamGap?.();
|
|
2917
|
+
}
|
|
2918
|
+
continue;
|
|
2919
|
+
}
|
|
2920
|
+
if ('messageStreamGap' in normalizedMessageStream) {
|
|
2921
|
+
if (options.onMessageStreamGap) {
|
|
2922
|
+
await options.onMessageStreamGap();
|
|
2923
|
+
continue;
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
else if (normalizedMessageStream.update.type === 'text') {
|
|
2927
|
+
if (options.onTextUpdate) {
|
|
2928
|
+
await options.onTextUpdate(normalizedMessageStream.update.update, normalizedMessageStream.directory);
|
|
2929
|
+
continue;
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2932
|
+
else {
|
|
2933
|
+
if (options.onReasoningUpdate) {
|
|
2934
|
+
await options.onReasoningUpdate(normalizedMessageStream.update.update, normalizedMessageStream.directory);
|
|
2935
|
+
continue;
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2939
|
+
const normalized = normalizeEvent(event);
|
|
2940
|
+
if (!normalized)
|
|
2941
|
+
continue;
|
|
2942
|
+
if ('toolStreamGap' in normalized) {
|
|
2943
|
+
await options.onToolStreamGap?.();
|
|
2944
|
+
continue;
|
|
2945
|
+
}
|
|
2946
|
+
if ('toolExecution' in normalized) {
|
|
2947
|
+
this.sessionMetricsCache.delete(this.sessionMetricsCacheKey(normalized.directory, normalized.toolExecution.sessionId.nativeId));
|
|
2948
|
+
if (!this.temporarySessionIds.has(normalized.toolExecution.sessionId.nativeId)) {
|
|
2949
|
+
await options.onToolExecution?.(normalized.toolExecution, normalized.directory, normalized.timestamp);
|
|
2950
|
+
}
|
|
2951
|
+
continue;
|
|
2952
|
+
}
|
|
2953
|
+
if ('messageLifecycle' in normalized) {
|
|
2954
|
+
await options.onMessageLifecycle?.(normalized.messageLifecycle, normalized.directory);
|
|
2955
|
+
if (normalized.messageLifecycle.terminal) {
|
|
2956
|
+
this.clearLiveMessagePartsForMessage(normalized.directory, normalized.messageLifecycle.sessionId.nativeId, normalized.messageLifecycle.messageId.nativeId);
|
|
2957
|
+
}
|
|
2958
|
+
}
|
|
2959
|
+
if (normalized.event.sessionId?.harnessId === 'opencode') {
|
|
2960
|
+
this.sessionMetricsCache.delete(this.sessionMetricsCacheKey(normalized.directory, normalized.event.sessionId.nativeId));
|
|
2961
|
+
}
|
|
2962
|
+
if (normalized.event.sessionId === undefined
|
|
2963
|
+
|| !this.temporarySessionIds.has(normalized.event.sessionId.nativeId)) {
|
|
2964
|
+
await options.onEvent(normalized.event, normalized.directory);
|
|
2965
|
+
}
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
catch (error) {
|
|
2969
|
+
if (signal.aborted)
|
|
2970
|
+
return;
|
|
2971
|
+
lastStreamError = asError(error, 'The OpenCode event stream failed.');
|
|
2972
|
+
try {
|
|
2973
|
+
options.onError?.(lastStreamError);
|
|
2974
|
+
}
|
|
2975
|
+
catch {
|
|
2976
|
+
// Diagnostics must not terminate stream recovery.
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2979
|
+
if (signal.aborted)
|
|
2980
|
+
return;
|
|
2981
|
+
if (!lastStreamError) {
|
|
2982
|
+
lastStreamError = new Error('The OpenCode event stream ended unexpectedly.');
|
|
2983
|
+
try {
|
|
2984
|
+
options.onError?.(lastStreamError);
|
|
2985
|
+
}
|
|
2986
|
+
catch {
|
|
2987
|
+
// Diagnostics must not terminate stream recovery.
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
this.clearLiveMessagePartCache();
|
|
2991
|
+
if (options.onStreamGap) {
|
|
2992
|
+
await options.onStreamGap();
|
|
2993
|
+
}
|
|
2994
|
+
else {
|
|
2995
|
+
await options.onToolStreamGap?.();
|
|
2996
|
+
await options.onMessageStreamGap?.();
|
|
2997
|
+
}
|
|
2998
|
+
await waitForAbortableDelay(resubscribeDelayMs, signal);
|
|
2999
|
+
resubscribeDelayMs = Math.min(resubscribeDelayMs * 2, eventStreamMaxResubscribeDelayMs);
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5vcGVuY29kZWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2NsYXNzZXMub3BlbmNvZGVjbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUNMLHdDQUF3QyxFQUN4QywyQkFBMkIsRUFDM0IsbUNBQW1DLEVBQ25DLGtDQUFrQyxFQUNsQywyQkFBMkIsRUFDM0Isc0JBQXNCLEdBQ3ZCLE1BQU0sMkJBQTJCLENBQUM7QUFxQ25DLDhFQUE4RTtBQUM5RSwrRUFBK0U7QUFDL0UsTUFBTSxrQkFBa0IsR0FBRyxHQUFHLENBQUM7QUFDL0IsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDO0FBQzNCLE1BQU0sY0FBYyxHQUFHLDJCQUEyQixHQUFHLHdDQUF3QyxDQUFDO0FBQzlGLE1BQU0sbUJBQW1CLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUN0QyxNQUFNLG1CQUFtQixHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFDdEMsTUFBTSx5QkFBeUIsR0FBRywyQkFBMkIsR0FBRyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztBQUMzRSxNQUFNLDJCQUEyQixHQUFHLGtDQUFrQyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO0FBQ3BGLE1BQU0sOEJBQThCLEdBQUcsR0FBRyxDQUFDO0FBQzNDLE1BQU0sNEJBQTRCLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFDckQsTUFBTSxzQkFBc0IsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBQ3pDLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO0FBQzlCLE1BQU0sb0JBQW9CLEdBQUcsR0FBRyxDQUFDO0FBQ2pDLE1BQU0scUJBQXFCLEdBQUcsR0FBRyxDQUFDO0FBQ2xDLE1BQU0sa0JBQWtCLEdBQUcsRUFBRSxDQUFDO0FBQzlC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LFNBQVM7b0NBQ3BFLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxRQUFRLENBQUMsTUFBTSxFQUFFO29DQUM3QixDQUFDLENBQUMsRUFBRSxDQUFDO2dDQUNQLEdBQUcsQ0FBQyxZQUFZLENBQUMsU0FBUyxLQUFLLFNBQVMsSUFBSSxRQUFRLENBQUMsU0FBUyxLQUFLLFNBQVM7b0NBQzFFLENBQUMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsU0FBUyxFQUFFO29DQUNuQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dDQUNQLEdBQUcsQ0FBQyxZQUFZLENBQUMsUUFBUSxLQUFLLFNBQVMsSUFBSSxRQUFRLENBQUMsUUFBUSxLQUFLLFNBQVM7b0NBQ3hFLENBQUMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxRQUFRLENBQUMsUUFBUSxFQUFFO29DQUNqQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dDQUNQLEdBQUcsQ0FBQyxZQUFZLENBQUMsU0FBUyxLQUFLLFNBQVMsSUFBSSxRQUFRLENBQUMsU0FBUyxLQUFLLFNBQVM7b0NBQzFFLENBQUMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsU0FBUyxFQUFFO29DQUNuQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dDQUNQLEdBQUcsQ0FBQyxZQUFZLENBQUMsVUFBVSxLQUFLLFNBQVMsSUFBSSxRQUFRLENBQUMsVUFBVSxLQUFLLFNBQVM7b0NBQzVFLENBQUMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxRQUFRLENBQUMsVUFBVSxFQUFFO29DQUNyQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dDQUNQLEdBQUcsQ0FBQyxZQUFZLENBQUMsY0FBYyxLQUFLLFNBQVMsSUFBSSxRQUFRLENBQUMsY0FBYyxLQUFLLFNBQVM7b0NBQ3BGLENBQUMsQ0FBQyxFQUFFLGNBQWMsRUFBRSxRQUFRLENBQUMsY0FBYyxFQUFFO29DQUM3QyxDQUFDLENBQUMsRUFBRSxDQUFDO2dDQUNQLEdBQUcsQ0FBQyxZQUFZLENBQUMsS0FBSyxLQUFLLFNBQVMsSUFBSSxRQUFRLENBQUMsS0FBSyxLQUFL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
|