@opencode/client 2.0.8 → 2.0.9
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/chunks/pty-handoff-1tbj6z39.js +81 -0
- package/dist/chunks/pty-handoff-4tveyqeh.js +34 -0
- package/dist/chunks/pty-handoff-65kht65h.js +62 -0
- package/dist/chunks/pty-handoff-6mptkzbc.js +0 -0
- package/dist/chunks/pty-handoff-9rqn6x4v.js +16 -0
- package/dist/chunks/pty-handoff-atpwm825.js +1638 -0
- package/dist/chunks/pty-handoff-bssvn03b.js +594 -0
- package/dist/chunks/pty-handoff-frbwqjmf.js +145 -0
- package/dist/chunks/pty-handoff-m2eywc8w.js +0 -0
- package/dist/chunks/pty-handoff-n3c99vt5.js +11 -0
- package/dist/chunks/pty-handoff-nqd0dnpk.js +112 -0
- package/dist/chunks/pty-handoff-qav6mfdz.js +0 -0
- package/dist/chunks/pty-handoff-radw39tv.js +1402 -0
- package/dist/chunks/pty-handoff-sxt88q69.js +12 -0
- package/dist/chunks/pty-handoff-t1xa31vm.js +39 -0
- package/dist/chunks/pty-handoff-txckps9j.js +57 -0
- package/dist/chunks/pty-handoff-vgxtr9hm.js +30 -0
- package/dist/chunks/pty-handoff-vmytr4q8.js +4 -0
- package/dist/chunks/pty-handoff-vyas3vgt.js +0 -0
- package/dist/chunks/pty-handoff-xgnj2w4v.js +20 -0
- package/dist/chunks/pty-handoff-y2etg5bs.js +9 -0
- package/dist/chunks/pty-handoff-ydhz1zrh.js +238 -0
- package/dist/chunks/pty-handoff-yepdgb80.js +44 -0
- package/dist/chunks/pty-handoff-zadn5mwr.js +52 -0
- package/dist/contract.js +12 -1
- package/dist/effect/client.d.ts +4 -4
- package/dist/effect/client.js +15 -29
- package/dist/effect/generated/client-error.js +6 -5
- package/dist/effect/generated/client.d.ts +4 -4
- package/dist/effect/generated/client.js +8 -582
- package/dist/effect/generated/index.js +12 -2
- package/dist/effect/index.js +75 -30
- package/dist/effect/rpc.js +11 -49
- package/dist/effect/service.js +238 -245
- package/dist/promise/client.js +14 -13
- package/dist/promise/generated/client-error.js +6 -8
- package/dist/promise/generated/client.js +7 -1396
- package/dist/promise/generated/index.js +75 -3
- package/dist/promise/generated/types.d.ts +90 -88
- package/dist/promise/generated/types.js +66 -34
- package/dist/promise/index.js +79 -2
- package/dist/promise/rpc.js +7 -86
- package/dist/promise/service.js +230 -227
- package/dist/pty-handoff.js +14 -121
- package/dist/rpc-runtime.js +14 -32
- package/dist/service-contender.js +10 -56
- package/dist/service-timing.d.ts +0 -1
- package/dist/service-timing.js +9 -18
- package/dist/service-version.js +6 -9
- package/dist/service.js +1 -0
- package/dist/shared-events.js +8 -137
- package/dist/solid/connection.js +10 -246
- package/dist/solid/data.js +18 -1774
- package/dist/solid/index.js +32 -3
- package/dist/solid/pty.js +8 -41
- package/package.json +4 -4
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__export
|
|
3
|
+
} from "./pty-handoff-9rqn6x4v.js";
|
|
4
|
+
|
|
5
|
+
// src/shared-events.ts
|
|
6
|
+
var exports_shared_events = {};
|
|
7
|
+
__export(exports_shared_events, {
|
|
8
|
+
SharedEvents: () => exports_shared_events,
|
|
9
|
+
make: () => make7
|
|
10
|
+
});
|
|
11
|
+
function make7(connect) {
|
|
12
|
+
let current;
|
|
13
|
+
const capacity = 4096;
|
|
14
|
+
function stop(connection) {
|
|
15
|
+
connection.connected = undefined;
|
|
16
|
+
connection.controller.abort();
|
|
17
|
+
if (current === connection)
|
|
18
|
+
current = undefined;
|
|
19
|
+
}
|
|
20
|
+
async function run(connection) {
|
|
21
|
+
let iterator;
|
|
22
|
+
let completion = {};
|
|
23
|
+
try {
|
|
24
|
+
if (connection.controller.signal.aborted)
|
|
25
|
+
return;
|
|
26
|
+
iterator = connect(connection.controller.signal, () => {
|
|
27
|
+
connection.subscribers.forEach((subscriber) => subscriber.activity?.());
|
|
28
|
+
})[Symbol.asyncIterator]();
|
|
29
|
+
while (!connection.controller.signal.aborted) {
|
|
30
|
+
const item = await iterator.next();
|
|
31
|
+
if (item.done || connection.controller.signal.aborted)
|
|
32
|
+
break;
|
|
33
|
+
if (item.value.type === "server.connected")
|
|
34
|
+
connection.connected = item.value;
|
|
35
|
+
connection.subscribers.forEach((subscriber) => subscriber.push(item.value));
|
|
36
|
+
}
|
|
37
|
+
} catch (error) {
|
|
38
|
+
completion = { error };
|
|
39
|
+
} finally {
|
|
40
|
+
stop(connection);
|
|
41
|
+
try {
|
|
42
|
+
await iterator?.return?.();
|
|
43
|
+
} catch (error) {
|
|
44
|
+
if (!("error" in completion))
|
|
45
|
+
completion = { error };
|
|
46
|
+
}
|
|
47
|
+
connection.subscribers.forEach((subscriber) => subscriber.finish(completion));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
subscribe(options) {
|
|
52
|
+
return {
|
|
53
|
+
[Symbol.asyncIterator]() {
|
|
54
|
+
const pending = [];
|
|
55
|
+
const queued = [];
|
|
56
|
+
let started = false;
|
|
57
|
+
let completion;
|
|
58
|
+
let connection;
|
|
59
|
+
function finish(result, discard = true) {
|
|
60
|
+
completion = result;
|
|
61
|
+
if (discard)
|
|
62
|
+
queued.length = 0;
|
|
63
|
+
options?.signal?.removeEventListener("abort", abort);
|
|
64
|
+
if (connection?.subscribers.delete(subscriber) && !connection.subscribers.size)
|
|
65
|
+
stop(connection);
|
|
66
|
+
pending.splice(0).forEach((request) => {
|
|
67
|
+
if ("error" in result)
|
|
68
|
+
request.reject(result.error);
|
|
69
|
+
else
|
|
70
|
+
request.resolve({ done: true, value: undefined });
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function abort() {
|
|
74
|
+
finish({});
|
|
75
|
+
}
|
|
76
|
+
const subscriber = {
|
|
77
|
+
activity: options?.onActivity,
|
|
78
|
+
finish(result) {
|
|
79
|
+
finish(result, false);
|
|
80
|
+
},
|
|
81
|
+
push(value) {
|
|
82
|
+
if (completion)
|
|
83
|
+
return;
|
|
84
|
+
const request = pending.shift();
|
|
85
|
+
if (request) {
|
|
86
|
+
request.resolve({ done: false, value });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (queued.length === capacity) {
|
|
90
|
+
finish({ error: new Error(`Event subscriber exceeded its ${capacity}-event capacity`) });
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
queued.push(value);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
function start() {
|
|
97
|
+
if (completion)
|
|
98
|
+
return;
|
|
99
|
+
const fresh = !current;
|
|
100
|
+
connection = current ?? {
|
|
101
|
+
controller: new AbortController,
|
|
102
|
+
subscribers: new Set
|
|
103
|
+
};
|
|
104
|
+
current = connection;
|
|
105
|
+
connection.subscribers.add(subscriber);
|
|
106
|
+
if (connection.connected)
|
|
107
|
+
subscriber.push(connection.connected);
|
|
108
|
+
if (fresh)
|
|
109
|
+
run(connection);
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
next() {
|
|
113
|
+
const value = queued.shift();
|
|
114
|
+
if (value)
|
|
115
|
+
return Promise.resolve({ done: false, value });
|
|
116
|
+
if (completion) {
|
|
117
|
+
if ("error" in completion)
|
|
118
|
+
return Promise.reject(completion.error);
|
|
119
|
+
return Promise.resolve({ done: true, value: undefined });
|
|
120
|
+
}
|
|
121
|
+
if (options?.signal?.aborted) {
|
|
122
|
+
abort();
|
|
123
|
+
return Promise.resolve({ done: true, value: undefined });
|
|
124
|
+
}
|
|
125
|
+
const request = Promise.withResolvers();
|
|
126
|
+
pending.push(request);
|
|
127
|
+
if (!started) {
|
|
128
|
+
started = true;
|
|
129
|
+
options?.signal?.addEventListener("abort", abort, { once: true });
|
|
130
|
+
start();
|
|
131
|
+
}
|
|
132
|
+
return request.promise;
|
|
133
|
+
},
|
|
134
|
+
return() {
|
|
135
|
+
finish({});
|
|
136
|
+
return Promise.resolve({ done: true, value: undefined });
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export { make7, exports_shared_events };
|
|
File without changes
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__export
|
|
3
|
+
} from "./pty-handoff-9rqn6x4v.js";
|
|
4
|
+
|
|
5
|
+
// src/pty-handoff.ts
|
|
6
|
+
var exports_pty_handoff = {};
|
|
7
|
+
__export(exports_pty_handoff, {
|
|
8
|
+
PtyHandoff: () => exports_pty_handoff,
|
|
9
|
+
clear: () => clear2,
|
|
10
|
+
complete: () => complete2,
|
|
11
|
+
environment: () => environment2,
|
|
12
|
+
prepare: () => prepare2
|
|
13
|
+
});
|
|
14
|
+
import { readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
15
|
+
async function prepare2(file, info, timeout) {
|
|
16
|
+
const existing = await read(file);
|
|
17
|
+
if (existing !== undefined && existing.expiresAt > Date.now() && same(existing.source, info))
|
|
18
|
+
return;
|
|
19
|
+
const { ClientError, OpenCode } = await import("../promise/index.js");
|
|
20
|
+
const client = OpenCode.make({
|
|
21
|
+
baseUrl: info.url,
|
|
22
|
+
headers: info.password === undefined ? undefined : { authorization: "Basic " + Buffer.from(`opencode:${info.password}`).toString("base64") }
|
|
23
|
+
});
|
|
24
|
+
const missing = (error) => error instanceof ClientError && error.reason === "UnexpectedStatus" && typeof error.cause === "object" && error.cause !== null && ("status" in error.cause) && error.cause.status === 404;
|
|
25
|
+
const result = await client.experimental.persistentPty.handoff({ signal: AbortSignal.timeout(timeout) }).then((value) => ({ value }), (cause) => ({ cause }));
|
|
26
|
+
if ("cause" in result) {
|
|
27
|
+
const concurrent = await read(file);
|
|
28
|
+
if (concurrent !== undefined && concurrent.expiresAt > Date.now() && same(concurrent.source, info))
|
|
29
|
+
return;
|
|
30
|
+
if (!missing(result.cause))
|
|
31
|
+
throw new Error("Failed to prepare persistent terminals for service replacement", { cause: result.cause });
|
|
32
|
+
console.warn("Background service cannot hand off persistent terminals; shutting them down before replacement");
|
|
33
|
+
await client.experimental.persistentPty.shutdown({ signal: AbortSignal.timeout(timeout) }).catch((cause) => {
|
|
34
|
+
if (missing(cause))
|
|
35
|
+
return;
|
|
36
|
+
throw new Error("Failed to shut down persistent terminals before service replacement", { cause });
|
|
37
|
+
});
|
|
38
|
+
await publish(file, info, null);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const body = result.value;
|
|
42
|
+
if (typeof body !== "object" || body === null || !("handoff" in body))
|
|
43
|
+
throw new Error("Invalid persistent terminal handoff response");
|
|
44
|
+
if (body.handoff === null) {
|
|
45
|
+
await publish(file, info, null);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (!isHandoff(body.handoff) || body.handoff.expiresAt <= Date.now())
|
|
49
|
+
throw new Error("Invalid or expired persistent terminal handoff");
|
|
50
|
+
await publish(file, info, body.handoff);
|
|
51
|
+
}
|
|
52
|
+
async function publish(file, info, handoff) {
|
|
53
|
+
const temporary = `${file}.pty-handoff.${crypto.randomUUID()}.tmp`;
|
|
54
|
+
await writeFile(temporary, JSON.stringify({
|
|
55
|
+
source: { id: info.id, pid: info.pid, url: info.url },
|
|
56
|
+
handoff,
|
|
57
|
+
expiresAt: handoff?.expiresAt ?? Date.now() + 30000
|
|
58
|
+
}), { mode: 384, flag: "wx" });
|
|
59
|
+
await rename(temporary, file + ".pty-handoff").finally(() => rm(temporary, { force: true }));
|
|
60
|
+
}
|
|
61
|
+
async function environment2(file, env) {
|
|
62
|
+
const record = await read(file);
|
|
63
|
+
const current = await readFile(file, "utf8").then((text) => JSON.parse(text)).catch(() => {
|
|
64
|
+
return;
|
|
65
|
+
});
|
|
66
|
+
const handoff = record !== undefined && record.expiresAt > Date.now() && (current === undefined || same(record.source, current)) ? record.handoff : undefined;
|
|
67
|
+
return { ...env, OPENCODE_PTY_HANDOFF: handoff == null ? undefined : JSON.stringify(handoff) };
|
|
68
|
+
}
|
|
69
|
+
async function complete2(file, info) {
|
|
70
|
+
const record = await read(file);
|
|
71
|
+
if (record !== undefined && !same(record.source, info))
|
|
72
|
+
await clear2(file);
|
|
73
|
+
}
|
|
74
|
+
async function clear2(file) {
|
|
75
|
+
await rm(file + ".pty-handoff", { force: true });
|
|
76
|
+
}
|
|
77
|
+
async function read(file) {
|
|
78
|
+
const value = await readFile(file + ".pty-handoff", "utf8").then((text) => JSON.parse(text)).catch(() => {
|
|
79
|
+
return;
|
|
80
|
+
});
|
|
81
|
+
if (typeof value !== "object" || value === null || !("source" in value) || !("handoff" in value))
|
|
82
|
+
return;
|
|
83
|
+
if (typeof value.source !== "object" || value.source === null)
|
|
84
|
+
return;
|
|
85
|
+
if (!("pid" in value.source) || typeof value.source.pid !== "number")
|
|
86
|
+
return;
|
|
87
|
+
if (!("url" in value.source) || typeof value.source.url !== "string")
|
|
88
|
+
return;
|
|
89
|
+
if ("id" in value.source && typeof value.source.id !== "string")
|
|
90
|
+
return;
|
|
91
|
+
if (value.handoff !== null && !isHandoff(value.handoff))
|
|
92
|
+
return;
|
|
93
|
+
if (!("expiresAt" in value) || typeof value.expiresAt !== "number" || !Number.isFinite(value.expiresAt))
|
|
94
|
+
return;
|
|
95
|
+
return {
|
|
96
|
+
source: {
|
|
97
|
+
id: "id" in value.source && typeof value.source.id === "string" ? value.source.id : undefined,
|
|
98
|
+
pid: value.source.pid,
|
|
99
|
+
url: value.source.url
|
|
100
|
+
},
|
|
101
|
+
handoff: value.handoff,
|
|
102
|
+
expiresAt: value.expiresAt
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function same(left, right) {
|
|
106
|
+
return left.id === right.id && left.pid === right.pid && left.url === right.url;
|
|
107
|
+
}
|
|
108
|
+
function isHandoff(value) {
|
|
109
|
+
return typeof value === "object" && value !== null && "directory" in value && typeof value.directory === "string" && "instanceID" in value && typeof value.instanceID === "string" && "ticket" in value && typeof value.ticket === "string" && "expiresAt" in value && typeof value.expiresAt === "number" && Number.isFinite(value.expiresAt);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export { prepare2, environment2, complete2, clear2, exports_pty_handoff };
|
|
File without changes
|