@opencode/client 2.0.3 → 2.0.5
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/dist/effect/api/api.d.ts +321 -344
- package/dist/effect/api.d.ts +1 -5
- package/dist/effect/client.d.ts +59 -69
- package/dist/effect/generated/client.d.ts +60 -70
- package/dist/effect/generated/client.js +53 -91
- package/dist/effect/index.d.ts +1 -1
- package/dist/effect/service.js +43 -32
- package/dist/promise/api.d.ts +0 -4
- package/dist/promise/client.d.ts +22 -39
- package/dist/promise/generated/client.d.ts +23 -40
- package/dist/promise/generated/client.js +117 -192
- package/dist/promise/generated/types.d.ts +1352 -1867
- package/dist/promise/generated/types.js +6 -3
- package/dist/promise/index.d.ts +1 -1
- package/dist/promise/service.js +40 -24
- package/dist/rpc-runtime.d.ts +0 -1
- package/dist/solid/data.d.ts +4 -4
- package/dist/solid/data.js +68 -42
- package/dist/solid/pty.js +0 -2
- package/package.json +4 -4
|
@@ -15,12 +15,15 @@ export const isInstructionEntryValueTooLargeError = (value) => typeof value ===
|
|
|
15
15
|
value !== null &&
|
|
16
16
|
"_tag" in value &&
|
|
17
17
|
value["_tag"] === "InstructionEntryValueTooLargeError";
|
|
18
|
-
export const isProviderNotFoundError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "ProviderNotFoundError";
|
|
19
|
-
export const isMcpServerNotFoundError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "McpServerNotFoundError";
|
|
20
|
-
export const isProjectNotFoundError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "ProjectNotFoundError";
|
|
21
18
|
export const isFormNotFoundError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "FormNotFoundError";
|
|
22
19
|
export const isFormInvalidAnswerError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "FormInvalidAnswerError";
|
|
23
20
|
export const isFormAlreadySettledError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "FormAlreadySettledError";
|
|
21
|
+
export const isProviderNotFoundError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "ProviderNotFoundError";
|
|
22
|
+
export const isIntegrationNotFoundError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "IntegrationNotFoundError";
|
|
23
|
+
export const isIntegrationAttemptNotFoundError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "IntegrationAttemptNotFoundError";
|
|
24
|
+
export const isIntegrationMethodNotFoundError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "IntegrationMethodNotFoundError";
|
|
25
|
+
export const isMcpServerNotFoundError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "McpServerNotFoundError";
|
|
26
|
+
export const isProjectNotFoundError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "ProjectNotFoundError";
|
|
24
27
|
export const isPermissionNotFoundError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "PermissionNotFoundError";
|
|
25
28
|
export const isFileNotFoundError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "FileNotFoundError";
|
|
26
29
|
export const isRpcError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "RpcError";
|
package/dist/promise/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { OpenCode } from "./client.js";
|
|
2
2
|
export * from "./generated/index.js";
|
|
3
3
|
export { OpenCode } from "./client.js";
|
|
4
|
-
export type { AgentApi,
|
|
4
|
+
export type { AgentApi, CommandApi, ConfigApi, EventApi, IntegrationApi, ModelApi, PluginApi, ProviderApi, ReferenceApi, RpcApi, RpcCallOptions, RpcClient, RpcEventPayload, WebSearchApi, SessionApi, SkillApi, } from "./api.js";
|
|
5
5
|
export type { EventSubscribeOutput as OpenCodeEvent } from "./generated/types.js";
|
|
6
6
|
export type OpenCodeClient = ReturnType<typeof OpenCode.make>;
|
package/dist/promise/service.js
CHANGED
|
@@ -16,6 +16,8 @@ export async function discover(options = {}) {
|
|
|
16
16
|
const found = (await registered(options.file)).service;
|
|
17
17
|
if (found?.state !== "ready")
|
|
18
18
|
return undefined;
|
|
19
|
+
if (!found.compatible)
|
|
20
|
+
return undefined;
|
|
19
21
|
if (!matchesVersion(found.version, options))
|
|
20
22
|
return undefined;
|
|
21
23
|
return found.endpoint;
|
|
@@ -50,7 +52,7 @@ export async function ensure(options = {}) {
|
|
|
50
52
|
while (true) {
|
|
51
53
|
if (Date.now() >= deadline)
|
|
52
54
|
throw new Error("Timed out waiting for the background service to start");
|
|
53
|
-
const registration = await registered(options.file,
|
|
55
|
+
const registration = await registered(options.file, timing.requestTimeout);
|
|
54
56
|
if (registration.timedOut && registration.info !== undefined) {
|
|
55
57
|
timeouts = {
|
|
56
58
|
info: registration.info,
|
|
@@ -70,7 +72,7 @@ export async function ensure(options = {}) {
|
|
|
70
72
|
if (registration.service !== undefined) {
|
|
71
73
|
spawnDelay = timing.spawnDelay;
|
|
72
74
|
const service = registration.service;
|
|
73
|
-
const compatible =
|
|
75
|
+
const compatible = service.compatible && matchesVersion(service.version, options);
|
|
74
76
|
if (compatible && service.state === "ready") {
|
|
75
77
|
await PtyHandoff.complete(options.file ?? fallback(), service.info);
|
|
76
78
|
return service.endpoint;
|
|
@@ -79,11 +81,11 @@ export async function ensure(options = {}) {
|
|
|
79
81
|
throw new Error("Background service failed to start");
|
|
80
82
|
if (!compatible) {
|
|
81
83
|
announce("version-mismatch", service.version);
|
|
82
|
-
if (
|
|
84
|
+
if (service.state !== "ready")
|
|
83
85
|
console.warn("Background service is not ready; replacement cannot preserve persistent terminals");
|
|
84
86
|
await stop({
|
|
85
87
|
file: options.file,
|
|
86
|
-
pty:
|
|
88
|
+
pty: service.state === "ready" ? "handoff" : "clear",
|
|
87
89
|
}).catch(() => undefined);
|
|
88
90
|
lastSpawn = 0;
|
|
89
91
|
}
|
|
@@ -145,7 +147,7 @@ async function read(file) {
|
|
|
145
147
|
return undefined;
|
|
146
148
|
}
|
|
147
149
|
}
|
|
148
|
-
async function probeResult(info,
|
|
150
|
+
async function probeResult(info, timeout = defaultEnsureTiming.requestTimeout) {
|
|
149
151
|
const endpoint = {
|
|
150
152
|
url: info.url,
|
|
151
153
|
auth: info.password === undefined
|
|
@@ -153,47 +155,61 @@ async function probeResult(info, allowLegacy = false, timeout = defaultEnsureTim
|
|
|
153
155
|
: { type: "basic", username: "opencode", password: info.password },
|
|
154
156
|
};
|
|
155
157
|
const signal = AbortSignal.timeout(timeout);
|
|
156
|
-
const result = await fetch(new URL("/api/
|
|
157
|
-
headers: headers(endpoint),
|
|
158
|
-
signal,
|
|
159
|
-
})
|
|
158
|
+
const result = await fetch(new URL("/api/status", info.url), { headers: headers(endpoint), signal })
|
|
160
159
|
.then(async (response) => ({
|
|
161
160
|
response,
|
|
162
|
-
body: (await response.json()),
|
|
161
|
+
body: response.status === 404 ? undefined : (await response.json()),
|
|
163
162
|
}))
|
|
164
163
|
.then((value) => ({ value }), (cause) => ({ cause }));
|
|
165
164
|
if ("cause" in result)
|
|
166
165
|
return { service: undefined, timedOut: signal.aborted };
|
|
167
166
|
const response = result.value.response;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
167
|
+
// The previous V2 service exposes /api/health instead. Its authenticated 404 is enough
|
|
168
|
+
// to recognize the registered daemon as incompatible and route it through replacement.
|
|
169
|
+
if (response.status === 404)
|
|
170
|
+
return {
|
|
171
|
+
service: {
|
|
172
|
+
info,
|
|
173
|
+
endpoint,
|
|
174
|
+
version: info.version,
|
|
175
|
+
state: "ready",
|
|
176
|
+
compatible: false,
|
|
177
|
+
},
|
|
178
|
+
timedOut: false,
|
|
179
|
+
};
|
|
180
|
+
const status = decodeStatus(result.value.body);
|
|
181
|
+
if (status !== undefined) {
|
|
182
|
+
if (status.pid !== info.pid)
|
|
171
183
|
return { service: undefined, timedOut: false };
|
|
172
|
-
if (info.version !== undefined &&
|
|
184
|
+
if (info.version !== undefined && status.version !== info.version)
|
|
173
185
|
return { service: undefined, timedOut: false };
|
|
174
186
|
return {
|
|
175
187
|
service: {
|
|
176
188
|
info,
|
|
177
189
|
endpoint,
|
|
178
|
-
version:
|
|
190
|
+
version: status.version,
|
|
179
191
|
state: response.ok ? "ready" : response.status === 500 ? "failed" : "waiting",
|
|
180
|
-
|
|
192
|
+
compatible: true,
|
|
181
193
|
},
|
|
182
194
|
timedOut: false,
|
|
183
195
|
};
|
|
184
196
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
197
|
+
return { service: undefined, timedOut: false };
|
|
198
|
+
}
|
|
199
|
+
function decodeStatus(input) {
|
|
200
|
+
if (typeof input !== "object" || input === null)
|
|
201
|
+
return;
|
|
202
|
+
if (!("version" in input) || typeof input.version !== "string")
|
|
203
|
+
return;
|
|
204
|
+
if (!("pid" in input) || typeof input.pid !== "number" || !Number.isInteger(input.pid) || input.pid < 0)
|
|
205
|
+
return;
|
|
206
|
+
return { version: input.version, pid: input.pid };
|
|
191
207
|
}
|
|
192
|
-
async function registered(file,
|
|
208
|
+
async function registered(file, timeout) {
|
|
193
209
|
const info = await read(file);
|
|
194
210
|
if (info === undefined)
|
|
195
211
|
return { info: undefined, service: undefined, timedOut: false };
|
|
196
|
-
return { info, ...(await probeResult(info,
|
|
212
|
+
return { info, ...(await probeResult(info, timeout)) };
|
|
197
213
|
}
|
|
198
214
|
function signal(pid, name) {
|
|
199
215
|
try {
|
package/dist/rpc-runtime.d.ts
CHANGED
|
@@ -7,7 +7,6 @@ export declare const event: <D extends Rpc.Definition, Name extends keyof D["eve
|
|
|
7
7
|
readonly id: string & import("effect/Brand").Brand<"Event.ID">;
|
|
8
8
|
readonly location: {
|
|
9
9
|
readonly directory: string & import("effect/Brand").Brand<"AbsolutePath">;
|
|
10
|
-
readonly workspaceID?: (string & import("effect/Brand").Brand<"Workspace.ID">) | undefined;
|
|
11
10
|
};
|
|
12
11
|
readonly data: {
|
|
13
12
|
readonly [x: string]: unknown;
|
package/dist/solid/data.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentInfo, CommandInfo, ConfigEntry,
|
|
1
|
+
import type { AgentInfo, CommandInfo, ConfigEntry, SessionFormCancelInput, FormInfo, SessionFormReplyInput, IntegrationInfo, LocationRef, McpResource, McpServer, ModelInfo, ModelRef, PermissionSavedInfo, PermissionRequest, PermissionReplyInput, Project, ProviderInfo, ReferenceInfo, SessionMessageInfo, SessionInfo, SessionInboxInfo, SessionInboxCompaction, ShellInfo, SkillInfo, VcsInfo, OpenCodeEvent, OpenCodeClient, WebSearchProvider } from "../promise";
|
|
2
2
|
import { type SessionPromptInput } from "../promise";
|
|
3
3
|
export type DataSessionStatus = "idle" | "running";
|
|
4
4
|
type OpenCodeEventMap = {
|
|
@@ -106,8 +106,8 @@ export declare function createData(config: CreateDataInput): {
|
|
|
106
106
|
list(sessionID: string, ref?: LocationRef): FormWithLocation[] | undefined;
|
|
107
107
|
sync(sessionID: string, ref?: LocationRef): Promise<void>;
|
|
108
108
|
invalidate(sessionID: string, ref?: LocationRef): void;
|
|
109
|
-
reply(input:
|
|
110
|
-
cancel(input:
|
|
109
|
+
reply(input: SessionFormReplyInput, ref?: LocationRef): Promise<void>;
|
|
110
|
+
cancel(input: SessionFormCancelInput, ref?: LocationRef): Promise<void>;
|
|
111
111
|
};
|
|
112
112
|
};
|
|
113
113
|
project: {
|
|
@@ -129,7 +129,7 @@ export declare function createData(config: CreateDataInput): {
|
|
|
129
129
|
invalidate: (ref?: LocationRef) => void;
|
|
130
130
|
};
|
|
131
131
|
location: {
|
|
132
|
-
info(ref?: LocationRef):
|
|
132
|
+
info(ref?: LocationRef): import("../promise").LocationPublicInfo | undefined;
|
|
133
133
|
default(): LocationRef;
|
|
134
134
|
syncInfo(ref?: LocationRef): Promise<void>;
|
|
135
135
|
sync(ref?: LocationRef): Promise<void>;
|
package/dist/solid/data.js
CHANGED
|
@@ -16,7 +16,7 @@ export function locationKey(location) {
|
|
|
16
16
|
return JSON.stringify([location.directory, location.workspaceID]);
|
|
17
17
|
}
|
|
18
18
|
function locationQuery(ref) {
|
|
19
|
-
return { directory: ref.directory
|
|
19
|
+
return { directory: ref.directory };
|
|
20
20
|
}
|
|
21
21
|
function formRequestOptions(sessionID, ref) {
|
|
22
22
|
if (sessionID !== "global" || !ref)
|
|
@@ -24,7 +24,6 @@ function formRequestOptions(sessionID, ref) {
|
|
|
24
24
|
return {
|
|
25
25
|
headers: {
|
|
26
26
|
"x-opencode-directory": encodeURIComponent(ref.directory),
|
|
27
|
-
...(ref.workspaceID ? { "x-opencode-workspace": ref.workspaceID } : {}),
|
|
28
27
|
},
|
|
29
28
|
};
|
|
30
29
|
}
|
|
@@ -137,6 +136,7 @@ export function createData(config) {
|
|
|
137
136
|
const messageIndex = new Map();
|
|
138
137
|
const sync = createSync();
|
|
139
138
|
let activeUpdates;
|
|
139
|
+
const pendingUpdates = new Map();
|
|
140
140
|
function setSessionActive(sessionID, status) {
|
|
141
141
|
activeUpdates?.set(sessionID, status);
|
|
142
142
|
setStore("session", "active", sessionID, status);
|
|
@@ -144,6 +144,7 @@ export function createData(config) {
|
|
|
144
144
|
function removePending(sessionID, inboxID) {
|
|
145
145
|
if (!inboxID)
|
|
146
146
|
return;
|
|
147
|
+
pendingUpdates.get(sessionID)?.set(inboxID, undefined);
|
|
147
148
|
if (store.session.pending[sessionID]?.some((item) => item.id === inboxID))
|
|
148
149
|
setStore("session", "pending", sessionID, (store.session.pending[sessionID] ?? []).filter((item) => item.id !== inboxID));
|
|
149
150
|
}
|
|
@@ -186,6 +187,7 @@ export function createData(config) {
|
|
|
186
187
|
function updatePending(sessionID, inboxID, delivery) {
|
|
187
188
|
const index = store.session.pending[sessionID]?.findIndex((item) => item.id === inboxID) ?? -1;
|
|
188
189
|
const item = store.session.pending[sessionID]?.[index];
|
|
190
|
+
pendingUpdates.get(sessionID)?.set(inboxID, item ? { ...item, delivery } : delivery);
|
|
189
191
|
if (index < 0 || !item || item.delivery === delivery)
|
|
190
192
|
return;
|
|
191
193
|
setStore("session", "pending", sessionID, index, { ...item, delivery });
|
|
@@ -252,8 +254,8 @@ export function createData(config) {
|
|
|
252
254
|
return;
|
|
253
255
|
message.update(item.sessionID, (draft, index) => {
|
|
254
256
|
const row = item.type === "user"
|
|
255
|
-
? { id: item.id, type: "user", ...item.payload, time: { created: item.
|
|
256
|
-
: { id: item.id, type: "synthetic", ...item.payload, time: { created: item.
|
|
257
|
+
? { id: item.id, type: "user", ...item.payload, time: { created: item.time.created } }
|
|
258
|
+
: { id: item.id, type: "synthetic", ...item.payload, time: { created: item.time.created } };
|
|
257
259
|
const position = index.get(item.id);
|
|
258
260
|
if (position === undefined)
|
|
259
261
|
return message.append(draft, index, row);
|
|
@@ -527,7 +529,7 @@ export function createData(config) {
|
|
|
527
529
|
time: { created: event.created },
|
|
528
530
|
});
|
|
529
531
|
refresh(() => api()
|
|
530
|
-
.session.message({ sessionID: event.data.sessionID, messageID: messageIDFromEvent(event.id) })
|
|
532
|
+
.session.message.get({ sessionID: event.data.sessionID, messageID: messageIDFromEvent(event.id) })
|
|
531
533
|
.then((item) => {
|
|
532
534
|
message.update(event.data.sessionID, (draft, index) => {
|
|
533
535
|
const position = index.get(item.id);
|
|
@@ -550,7 +552,7 @@ export function createData(config) {
|
|
|
550
552
|
});
|
|
551
553
|
return;
|
|
552
554
|
}
|
|
553
|
-
case "session.permissions
|
|
555
|
+
case "session.permissions":
|
|
554
556
|
if (store.session.info[event.data.sessionID])
|
|
555
557
|
setStore("session", "info", event.data.sessionID, "permissions", event.data.permissions);
|
|
556
558
|
return;
|
|
@@ -583,8 +585,6 @@ export function createData(config) {
|
|
|
583
585
|
const explicit = event.data.adopted?.includes(info.projectID);
|
|
584
586
|
const directory = explicit ? store.project.info[info.projectID]?.canonical : info.location.directory;
|
|
585
587
|
if (!directory) {
|
|
586
|
-
if (info.location.workspaceID)
|
|
587
|
-
continue;
|
|
588
588
|
result.session.invalidate(sessionID);
|
|
589
589
|
refresh(() => result.session.sync(sessionID));
|
|
590
590
|
continue;
|
|
@@ -592,7 +592,6 @@ export function createData(config) {
|
|
|
592
592
|
const adopted = Worktree.adopt({
|
|
593
593
|
projectID: info.projectID,
|
|
594
594
|
directory,
|
|
595
|
-
workspaceID: info.location.workspaceID,
|
|
596
595
|
}, event.data);
|
|
597
596
|
if (!adopted)
|
|
598
597
|
continue;
|
|
@@ -629,12 +628,14 @@ export function createData(config) {
|
|
|
629
628
|
}
|
|
630
629
|
case "session.inbox.enqueued": {
|
|
631
630
|
outbox.delete(event.data.inboxID);
|
|
632
|
-
|
|
631
|
+
const item = {
|
|
633
632
|
id: event.data.inboxID,
|
|
634
633
|
sessionID: event.data.sessionID,
|
|
635
|
-
|
|
634
|
+
time: { created: event.created },
|
|
636
635
|
...event.data.item,
|
|
637
|
-
}
|
|
636
|
+
};
|
|
637
|
+
pendingUpdates.get(item.sessionID)?.set(item.id, item);
|
|
638
|
+
admitLocal(item);
|
|
638
639
|
if (event.data.item.type === "compaction") {
|
|
639
640
|
const active = compacting.get(event.data.sessionID);
|
|
640
641
|
active?.observed.add(event.data.inboxID);
|
|
@@ -1061,10 +1062,13 @@ export function createData(config) {
|
|
|
1061
1062
|
return;
|
|
1062
1063
|
const location = event.location;
|
|
1063
1064
|
switch (event.type) {
|
|
1064
|
-
case "
|
|
1065
|
-
result.location.model.invalidate(location);
|
|
1065
|
+
case "provider.updated":
|
|
1066
1066
|
result.location.provider.invalidate(location);
|
|
1067
|
-
refresh(() =>
|
|
1067
|
+
refresh(() => result.location.provider.sync(location));
|
|
1068
|
+
break;
|
|
1069
|
+
case "model.updated":
|
|
1070
|
+
result.location.model.invalidate(location);
|
|
1071
|
+
refresh(() => result.location.model.sync(location));
|
|
1068
1072
|
break;
|
|
1069
1073
|
case "agent.updated":
|
|
1070
1074
|
result.location.agent.invalidate(location);
|
|
@@ -1170,7 +1174,7 @@ export function createData(config) {
|
|
|
1170
1174
|
const vcs = locationResource("vcs", (location) => api().vcs.get({ location }));
|
|
1171
1175
|
const shells = locationResource("shell", async (location) => {
|
|
1172
1176
|
const response = await api().shell.list({ location });
|
|
1173
|
-
const ref = { directory: response.location.directory
|
|
1177
|
+
const ref = { directory: response.location.directory };
|
|
1174
1178
|
return {
|
|
1175
1179
|
location: response.location,
|
|
1176
1180
|
data: Object.fromEntries(response.data.map((info) => [info.id, { ...info, location: ref }])),
|
|
@@ -1239,23 +1243,46 @@ export function createData(config) {
|
|
|
1239
1243
|
},
|
|
1240
1244
|
sync(sessionID) {
|
|
1241
1245
|
return sync.run(`session.pending:${sessionID}`, async () => {
|
|
1242
|
-
const
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1246
|
+
const updates = new Map();
|
|
1247
|
+
pendingUpdates.set(sessionID, updates);
|
|
1248
|
+
try {
|
|
1249
|
+
const snapshot = await api().session.inbox.list({ sessionID });
|
|
1250
|
+
// Events can overtake this HTTP response on a remote connection.
|
|
1251
|
+
// Reconcile them before an older snapshot can resurrect delivered input.
|
|
1252
|
+
const current = new Map(snapshot.map((item) => [item.id, item]));
|
|
1253
|
+
updates.forEach((item, id) => {
|
|
1254
|
+
if (item === undefined)
|
|
1255
|
+
current.delete(id);
|
|
1256
|
+
else if (typeof item === "string") {
|
|
1257
|
+
const existing = current.get(id);
|
|
1258
|
+
if (existing)
|
|
1259
|
+
current.set(id, { ...existing, delivery: item });
|
|
1260
|
+
}
|
|
1261
|
+
else
|
|
1262
|
+
current.set(id, item);
|
|
1263
|
+
});
|
|
1264
|
+
const pending = [...current.values()];
|
|
1265
|
+
// A positive read acknowledges admission even when its SSE echo is delayed.
|
|
1266
|
+
pending.forEach((item) => outbox.delete(item.id));
|
|
1267
|
+
// Compactions also coalesce by Session, not just by the proposed ID.
|
|
1268
|
+
if (pending.some((item) => item.type === "compaction"))
|
|
1269
|
+
store.session.pending[sessionID]
|
|
1270
|
+
?.filter((item) => item.type === "compaction")
|
|
1271
|
+
.forEach((item) => outbox.delete(item.id));
|
|
1272
|
+
// Keep optimistic rows still awaiting their echo: this fetch may
|
|
1273
|
+
// have raced ahead of an in-flight admission the server does not
|
|
1274
|
+
// know about yet.
|
|
1275
|
+
const inflight = (store.session.pending[sessionID] ?? []).filter((item) => outbox.has(item.id));
|
|
1276
|
+
const merged = inflight.length === 0 ? pending : [...pending, ...inflight];
|
|
1277
|
+
batch(() => {
|
|
1278
|
+
setStore("session", "pending", sessionID, reconcile(merged));
|
|
1279
|
+
merged.forEach(materializeInboxMessage);
|
|
1280
|
+
});
|
|
1281
|
+
}
|
|
1282
|
+
finally {
|
|
1283
|
+
if (pendingUpdates.get(sessionID) === updates)
|
|
1284
|
+
pendingUpdates.delete(sessionID);
|
|
1285
|
+
}
|
|
1259
1286
|
});
|
|
1260
1287
|
},
|
|
1261
1288
|
invalidate(sessionID) {
|
|
@@ -1325,7 +1352,7 @@ export function createData(config) {
|
|
|
1325
1352
|
admitLocal({
|
|
1326
1353
|
id,
|
|
1327
1354
|
sessionID: input.sessionID,
|
|
1328
|
-
|
|
1355
|
+
time: { created: Date.now() },
|
|
1329
1356
|
type: "compaction",
|
|
1330
1357
|
delivery: "steer",
|
|
1331
1358
|
payload: {},
|
|
@@ -1380,7 +1407,7 @@ export function createData(config) {
|
|
|
1380
1407
|
admitLocal({
|
|
1381
1408
|
id,
|
|
1382
1409
|
sessionID: request.sessionID,
|
|
1383
|
-
|
|
1410
|
+
time: { created: Date.now() },
|
|
1384
1411
|
type: "user",
|
|
1385
1412
|
delivery: request.delivery ?? "steer",
|
|
1386
1413
|
// Files and skills stay off the optimistic row: their durable
|
|
@@ -1568,12 +1595,11 @@ export function createData(config) {
|
|
|
1568
1595
|
const key = `session.form:${sessionID}:${sessionID === "global" ? locationKey(ref ?? defaultLocation()) : ""}`;
|
|
1569
1596
|
return sync.run(key, async () => {
|
|
1570
1597
|
if (sessionID === "global") {
|
|
1571
|
-
const response = await api().form.
|
|
1598
|
+
const response = await api().form.list({
|
|
1572
1599
|
location: locationQuery(ref ?? defaultLocation()),
|
|
1573
1600
|
});
|
|
1574
1601
|
const location = {
|
|
1575
1602
|
directory: response.location.directory,
|
|
1576
|
-
workspaceID: response.location.workspaceID,
|
|
1577
1603
|
};
|
|
1578
1604
|
const locationID = locationKey(location);
|
|
1579
1605
|
setStore("session", "form", sessionID, [
|
|
@@ -1582,17 +1608,17 @@ export function createData(config) {
|
|
|
1582
1608
|
]);
|
|
1583
1609
|
return;
|
|
1584
1610
|
}
|
|
1585
|
-
setStore("session", "form", sessionID, await api().form.list({ sessionID }));
|
|
1611
|
+
setStore("session", "form", sessionID, await api().session.form.list({ sessionID }));
|
|
1586
1612
|
});
|
|
1587
1613
|
},
|
|
1588
1614
|
invalidate(sessionID, ref) {
|
|
1589
1615
|
sync.invalidate(`session.form:${sessionID}:${sessionID === "global" ? locationKey(ref ?? defaultLocation()) : ""}`);
|
|
1590
1616
|
},
|
|
1591
1617
|
reply(input, ref) {
|
|
1592
|
-
return settleForm(input, ref, api().form.reply(input, formRequestOptions(input.sessionID, ref)));
|
|
1618
|
+
return settleForm(input, ref, api().session.form.reply(input, formRequestOptions(input.sessionID, ref)));
|
|
1593
1619
|
},
|
|
1594
1620
|
cancel(input, ref) {
|
|
1595
|
-
return settleForm(input, ref, api().form.cancel(input, formRequestOptions(input.sessionID, ref)));
|
|
1621
|
+
return settleForm(input, ref, api().session.form.cancel(input, formRequestOptions(input.sessionID, ref)));
|
|
1596
1622
|
},
|
|
1597
1623
|
},
|
|
1598
1624
|
},
|
|
@@ -1659,7 +1685,7 @@ export function createData(config) {
|
|
|
1659
1685
|
setStore("location", key, {});
|
|
1660
1686
|
setStore("location", key, "info", location);
|
|
1661
1687
|
if (!ref) {
|
|
1662
|
-
setDefaultLocation({ directory: location.directory
|
|
1688
|
+
setDefaultLocation({ directory: location.directory });
|
|
1663
1689
|
}
|
|
1664
1690
|
});
|
|
1665
1691
|
},
|
|
@@ -1702,7 +1728,7 @@ export function createData(config) {
|
|
|
1702
1728
|
agent: locationResource("agent", (location) => api().agent.list({ location })),
|
|
1703
1729
|
command: locationResource("command", (location) => api().command.list({ location })),
|
|
1704
1730
|
config: locationResource("config", async (location) => ({
|
|
1705
|
-
location: { directory: location.directory
|
|
1731
|
+
location: { directory: location.directory },
|
|
1706
1732
|
data: await api().config.get({ location }),
|
|
1707
1733
|
})),
|
|
1708
1734
|
integration: locationResource("integration", (location) => api().integration.list({ location })),
|
package/dist/solid/pty.js
CHANGED
|
@@ -9,8 +9,6 @@ export function createPtyClient(api, options) {
|
|
|
9
9
|
const url = new URL(`/api/pty/${encodeURIComponent(input.ptyID)}/connect`, options.url);
|
|
10
10
|
if (input.location?.directory)
|
|
11
11
|
url.searchParams.set("location[directory]", input.location.directory);
|
|
12
|
-
if (input.location?.workspace)
|
|
13
|
-
url.searchParams.set("location[workspace]", input.location.workspace);
|
|
14
12
|
if (input.cursor !== undefined)
|
|
15
13
|
url.searchParams.set("cursor", String(input.cursor));
|
|
16
14
|
url.searchParams.set("ticket", result.data.ticket);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@opencode/client",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.5",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
"typecheck": "tsgo --noEmit"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@opencode/schema": "2.0.
|
|
61
|
-
"@opencode/protocol": "2.0.
|
|
60
|
+
"@opencode/schema": "2.0.5",
|
|
61
|
+
"@opencode/protocol": "2.0.5"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
64
|
"effect": "4.0.0-rc.112",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
76
|
"@effect/platform-node": "4.0.0-rc.112",
|
|
77
|
-
"@opencode/httpapi-codegen": "2.0.
|
|
77
|
+
"@opencode/httpapi-codegen": "2.0.5",
|
|
78
78
|
"@tsconfig/bun": "1.0.9",
|
|
79
79
|
"@types/bun": "1.4.0",
|
|
80
80
|
"@typescript/native-preview": "7.0.0-dev.20251207.1",
|