@opencode/client 2.0.7 → 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.
Files changed (56) hide show
  1. package/dist/chunks/pty-handoff-1tbj6z39.js +81 -0
  2. package/dist/chunks/pty-handoff-4tveyqeh.js +34 -0
  3. package/dist/chunks/pty-handoff-65kht65h.js +62 -0
  4. package/dist/chunks/pty-handoff-6mptkzbc.js +0 -0
  5. package/dist/chunks/pty-handoff-9rqn6x4v.js +16 -0
  6. package/dist/chunks/pty-handoff-atpwm825.js +1638 -0
  7. package/dist/chunks/pty-handoff-bssvn03b.js +594 -0
  8. package/dist/chunks/pty-handoff-frbwqjmf.js +145 -0
  9. package/dist/chunks/pty-handoff-m2eywc8w.js +0 -0
  10. package/dist/chunks/pty-handoff-n3c99vt5.js +11 -0
  11. package/dist/chunks/pty-handoff-nqd0dnpk.js +112 -0
  12. package/dist/chunks/pty-handoff-qav6mfdz.js +0 -0
  13. package/dist/chunks/pty-handoff-radw39tv.js +1402 -0
  14. package/dist/chunks/pty-handoff-sxt88q69.js +12 -0
  15. package/dist/chunks/pty-handoff-t1xa31vm.js +39 -0
  16. package/dist/chunks/pty-handoff-txckps9j.js +57 -0
  17. package/dist/chunks/pty-handoff-vgxtr9hm.js +30 -0
  18. package/dist/chunks/pty-handoff-vmytr4q8.js +4 -0
  19. package/dist/chunks/pty-handoff-vyas3vgt.js +0 -0
  20. package/dist/chunks/pty-handoff-xgnj2w4v.js +20 -0
  21. package/dist/chunks/pty-handoff-y2etg5bs.js +9 -0
  22. package/dist/chunks/pty-handoff-ydhz1zrh.js +238 -0
  23. package/dist/chunks/pty-handoff-yepdgb80.js +44 -0
  24. package/dist/chunks/pty-handoff-zadn5mwr.js +52 -0
  25. package/dist/contract.js +12 -1
  26. package/dist/effect/client.d.ts +4 -4
  27. package/dist/effect/client.js +15 -29
  28. package/dist/effect/generated/client-error.js +6 -5
  29. package/dist/effect/generated/client.d.ts +4 -4
  30. package/dist/effect/generated/client.js +8 -582
  31. package/dist/effect/generated/index.js +12 -2
  32. package/dist/effect/index.js +75 -30
  33. package/dist/effect/rpc.js +11 -49
  34. package/dist/effect/service.js +238 -245
  35. package/dist/promise/client.js +14 -13
  36. package/dist/promise/generated/client-error.js +6 -8
  37. package/dist/promise/generated/client.js +7 -1396
  38. package/dist/promise/generated/index.js +75 -3
  39. package/dist/promise/generated/types.d.ts +91 -89
  40. package/dist/promise/generated/types.js +66 -34
  41. package/dist/promise/index.js +79 -2
  42. package/dist/promise/rpc.js +7 -86
  43. package/dist/promise/service.js +230 -227
  44. package/dist/pty-handoff.js +14 -121
  45. package/dist/rpc-runtime.js +14 -32
  46. package/dist/service-contender.js +10 -56
  47. package/dist/service-timing.d.ts +0 -1
  48. package/dist/service-timing.js +9 -18
  49. package/dist/service-version.js +6 -9
  50. package/dist/service.js +1 -0
  51. package/dist/shared-events.js +8 -137
  52. package/dist/solid/connection.js +10 -246
  53. package/dist/solid/data.js +18 -1769
  54. package/dist/solid/index.js +32 -3
  55. package/dist/solid/pty.js +8 -41
  56. package/package.json +4 -4
@@ -1,270 +1,263 @@
1
+ import {
2
+ spawnServiceContender2,
3
+ contenderFailure2,
4
+ contenderFinished2
5
+ } from "../chunks/pty-handoff-txckps9j.js";
6
+ import {
7
+ defaultEnsureTiming2,
8
+ ensureTiming2
9
+ } from "../chunks/pty-handoff-xgnj2w4v.js";
10
+ import {
11
+ matchesVersion2
12
+ } from "../chunks/pty-handoff-sxt88q69.js";
13
+ import {
14
+ prepare2,
15
+ environment2,
16
+ complete2,
17
+ clear2
18
+ } from "../chunks/pty-handoff-nqd0dnpk.js";
19
+ import"../chunks/pty-handoff-qav6mfdz.js";
20
+
21
+ // src/effect/service.ts
1
22
  import { Effect, FileSystem, Option, Schedule, Schema } from "effect";
2
23
  import { homedir } from "node:os";
3
24
  import { join } from "node:path";
4
- import { contenderFailure, contenderFinished, spawnServiceContender, } from "../service-contender.js";
5
- import { defaultEnsureTiming, ensureTiming } from "../service-timing.js";
6
- import { matchesVersion } from "../service-version.js";
7
- import { PtyHandoff } from "../pty-handoff.js";
8
- export * from "../service.js";
9
- // Find, start, and stop the local opencode background service.
10
- //
11
- // The service daemon advertises itself through a registration file in the
12
- // user's state directory: url, pid, version, and the private password, with
13
- // 0600 permissions. That file is the complete discovery contract — reading it
14
- // is all a client needs to connect. The daemon's own configuration (port,
15
- // persisted password) is CLI-owned and never read here.
16
- // Read-only lookup: registration file plus health check and version gate.
17
- // Never spawns; escalation to ensure() is the caller's policy.
18
- /** Discover a healthy, compatible local service without starting one. */
19
- export const discover = Effect.fn("service.discover")(function* (options = {}) {
20
- const found = (yield* registered(options.file)).service;
21
- if (found?.state !== "ready")
22
- return undefined;
23
- if (!found.compatible)
24
- return undefined;
25
- if (!matchesVersion(found.version, options))
26
- return undefined;
27
- return found.endpoint;
25
+ var discover = Effect.fn("service.discover")(function* (options = {}) {
26
+ const found = (yield* registered(options.file)).service;
27
+ if (found?.state !== "ready")
28
+ return;
29
+ if (!found.compatible)
30
+ return;
31
+ if (!matchesVersion2(found.version, options))
32
+ return;
33
+ return found.endpoint;
28
34
  });
29
- /** Recognize an authenticated compatible service bound to an expected URL, including while it starts or fails. */
30
- export const incumbent = Effect.fn("service.incumbent")(function* (options) {
31
- const info = yield* read(options.file);
32
- const found = info === undefined ? undefined : yield* probe({ ...info, url: options.url });
33
- if (found === undefined)
34
- return undefined;
35
- if (!found.compatible)
36
- return undefined;
37
- if (!matchesVersion(found.version, options))
38
- return undefined;
39
- return { endpoint: found.endpoint, state: found.state };
35
+ var incumbent = Effect.fn("service.incumbent")(function* (options) {
36
+ const info = yield* read(options.file);
37
+ const found = info === undefined ? undefined : yield* probe({ ...info, url: options.url });
38
+ if (found === undefined)
39
+ return;
40
+ if (!found.compatible)
41
+ return;
42
+ if (!matchesVersion2(found.version, options))
43
+ return;
44
+ return { endpoint: found.endpoint, state: found.state };
40
45
  });
41
- // Idempotent ensure-running: reuses a healthy compatible server, replaces a
42
- // version-mismatched one, and otherwise spawns small contenders until a server
43
- // becomes discoverable. A contender is never killed merely for slow startup.
44
- /** Ensure a healthy, compatible local service is running. */
45
- export const ensure = Effect.fn("service.ensure")(function* (options = {}) {
46
- const timing = ensureTiming(options);
47
- const contenders = new Set();
48
- let timeouts;
49
- let announced = false;
50
- let lastSpawn = 0;
51
- let spawnDelay = timing.spawnDelay;
52
- const announce = (reason, previousVersion) => Effect.sync(() => {
53
- if (announced)
54
- return;
55
- announced = true;
56
- options.onStart?.(reason, previousVersion);
46
+ var ensure = Effect.fn("service.ensure")(function* (options = {}) {
47
+ const timing = ensureTiming2(options);
48
+ const contenders = new Set;
49
+ let timeouts;
50
+ let announced = false;
51
+ let lastSpawn = 0;
52
+ let spawnDelay = timing.spawnDelay;
53
+ const announce = (reason, previousVersion) => Effect.sync(() => {
54
+ if (announced)
55
+ return;
56
+ announced = true;
57
+ options.onStart?.(reason, previousVersion);
58
+ });
59
+ const spawnContender = Effect.gen(function* () {
60
+ const [command, ...args] = options.command ?? ["opencode", "serve", "--service"];
61
+ if (command === undefined)
62
+ return yield* Effect.fail(new Error("Missing service command"));
63
+ const env = yield* Effect.tryPromise(() => environment2(options.file ?? fallback(), options.env));
64
+ return yield* Effect.try({
65
+ try: () => {
66
+ return spawnServiceContender2(command, args, env);
67
+ },
68
+ catch: (cause) => new Error("Failed to start server", { cause })
57
69
  });
58
- const spawnContender = Effect.gen(function* () {
59
- const [command, ...args] = options.command ?? ["opencode", "serve", "--service"];
60
- if (command === undefined)
61
- return yield* Effect.fail(new Error("Missing service command"));
62
- const env = yield* Effect.tryPromise(() => PtyHandoff.environment(options.file ?? fallback(), options.env));
63
- return yield* Effect.try({
64
- try: () => {
65
- return spawnServiceContender(command, args, env);
66
- },
67
- catch: (cause) => new Error("Failed to start server", { cause }),
68
- });
69
- });
70
- const found = yield* Effect.gen(function* () {
71
- const registration = yield* registered(options.file, timing.requestTimeout);
72
- const info = registration.info;
73
- const service = registration.service;
74
- if (registration.timedOut && info !== undefined) {
75
- timeouts = {
76
- info,
77
- count: timeouts !== undefined && same(timeouts.info, info) ? timeouts.count + 1 : 1,
78
- };
79
- if (timeouts.count >= 3) {
80
- yield* announce("missing");
81
- yield* Effect.logWarning("Background service is unresponsive; recovery cannot preserve persistent terminals");
82
- yield* Effect.tryPromise(() => PtyHandoff.clear(options.file ?? fallback()));
83
- yield* terminate(info, options, timing);
84
- timeouts = undefined;
85
- lastSpawn = Date.now() - spawnDelay;
86
- }
87
- }
88
- else
89
- timeouts = undefined;
90
- if (service !== undefined) {
91
- spawnDelay = timing.spawnDelay;
92
- const compatible = service.compatible && matchesVersion(service.version, options);
93
- if (compatible && service.state === "ready") {
94
- yield* Effect.tryPromise(() => PtyHandoff.complete(options.file ?? fallback(), service.info));
95
- return Option.some(service);
96
- }
97
- if (compatible && service.state === "failed")
98
- return yield* Effect.fail(new Error("Background service failed to start"));
99
- if (compatible)
100
- return Option.none();
101
- yield* announce("version-mismatch", service.version);
102
- if (service.state !== "ready")
103
- yield* Effect.logWarning("Background service is not ready; replacement cannot preserve persistent terminals");
104
- yield* stop({
105
- file: options.file,
106
- pty: service.state === "ready" ? "handoff" : "clear",
107
- }).pipe(Effect.ignore);
108
- lastSpawn = 0;
109
- return Option.none();
110
- }
111
- else if (lastSpawn === 0 && info !== undefined)
112
- lastSpawn = Date.now();
113
- const finished = [...contenders].filter(contenderFinished);
114
- const failure = finished.map(contenderFailure).find((error) => error !== undefined);
115
- if (finished.some((item) => item.child.exitCode === 0)) {
116
- spawnDelay = Math.min(spawnDelay * 2, timing.maxSpawnDelay);
117
- }
118
- finished.forEach((item) => contenders.delete(item));
119
- if (failure !== undefined && contenders.size === 0)
120
- return yield* Effect.fail(failure);
121
- // Keep one candidate plus one lock probe so a pre-lock stall cannot block recovery.
122
- if (contenders.size < 2 && Date.now() - lastSpawn >= spawnDelay) {
123
- yield* announce("missing");
124
- contenders.add(yield* spawnContender);
125
- lastSpawn = Date.now();
126
- }
70
+ });
71
+ const found = yield* Effect.gen(function* () {
72
+ const registration = yield* registered(options.file, timing.requestTimeout);
73
+ const info = registration.info;
74
+ const service2 = registration.service;
75
+ if (registration.timedOut && info !== undefined) {
76
+ timeouts = {
77
+ info,
78
+ count: timeouts !== undefined && same(timeouts.info, info) ? timeouts.count + 1 : 1
79
+ };
80
+ if (timeouts.count >= 3) {
81
+ yield* announce("missing");
82
+ yield* Effect.logWarning("Background service is unresponsive; recovery cannot preserve persistent terminals");
83
+ yield* Effect.tryPromise(() => clear2(options.file ?? fallback()));
84
+ yield* terminate(info, options, timing);
85
+ timeouts = undefined;
86
+ lastSpawn = Date.now() - spawnDelay;
87
+ }
88
+ } else
89
+ timeouts = undefined;
90
+ if (service2 !== undefined) {
91
+ spawnDelay = timing.spawnDelay;
92
+ const compatible = service2.compatible && matchesVersion2(service2.version, options);
93
+ if (compatible && service2.state === "ready") {
94
+ yield* Effect.tryPromise(() => complete2(options.file ?? fallback(), service2.info));
95
+ return Option.some(service2);
96
+ }
97
+ if (compatible && service2.state === "failed")
98
+ return yield* Effect.fail(new Error("Background service failed to start"));
99
+ if (compatible)
127
100
  return Option.none();
128
- }).pipe(Effect.repeat({
129
- until: Option.isSome,
130
- schedule: Schedule.max([Schedule.spaced(timing.pollInterval), Schedule.recurs(timing.attempts)]),
131
- }), Effect.ensuring(Effect.sync(() => contenders.forEach((contender) => contender.release()))));
132
- if (Option.isNone(found))
133
- return yield* Effect.fail(new Error("Timed out waiting for the background service to start"));
134
- return found.value.endpoint;
101
+ yield* announce("version-mismatch", service2.version);
102
+ if (service2.state !== "ready")
103
+ yield* Effect.logWarning("Background service is not ready; replacement cannot preserve persistent terminals");
104
+ yield* stop({
105
+ file: options.file,
106
+ pty: service2.state === "ready" ? "handoff" : "clear"
107
+ }).pipe(Effect.ignore);
108
+ lastSpawn = 0;
109
+ return Option.none();
110
+ } else if (lastSpawn === 0 && info !== undefined)
111
+ lastSpawn = Date.now();
112
+ const finished = [...contenders].filter(contenderFinished2);
113
+ const failure = finished.map(contenderFailure2).find((error) => error !== undefined);
114
+ if (finished.some((item) => item.child.exitCode === 0)) {
115
+ spawnDelay = Math.min(spawnDelay * 2, timing.maxSpawnDelay);
116
+ }
117
+ finished.forEach((item) => contenders.delete(item));
118
+ if (failure !== undefined && contenders.size === 0)
119
+ return yield* Effect.fail(failure);
120
+ if (contenders.size < 2 && Date.now() - lastSpawn >= spawnDelay) {
121
+ yield* announce("missing");
122
+ contenders.add(yield* spawnContender);
123
+ lastSpawn = Date.now();
124
+ }
125
+ return Option.none();
126
+ }).pipe(Effect.repeat({
127
+ until: Option.isSome,
128
+ schedule: Schedule.spaced(timing.pollInterval).pipe(Schedule.upTo({ duration: timing.promiseTimeout }))
129
+ }), Effect.ensuring(Effect.sync(() => contenders.forEach((contender) => contender.release()))));
130
+ if (Option.isNone(found))
131
+ return yield* Effect.fail(new Error("Timed out waiting for the background service to start"));
132
+ return found.value.endpoint;
135
133
  });
136
- /** Stop the registered local service. */
137
- export const stop = Effect.fn("service.stop")(function* (options = {}) {
138
- const info = yield* read(options.file);
139
- if (options.pty === "handoff" && info !== undefined)
140
- yield* Effect.tryPromise(() => PtyHandoff.prepare(options.file ?? fallback(), info, defaultEnsureTiming.requestTimeout));
141
- else
142
- yield* Effect.tryPromise(() => PtyHandoff.clear(options.file ?? fallback()));
143
- if (info !== undefined)
144
- yield* terminate(info, options, defaultEnsureTiming);
134
+ var stop = Effect.fn("service.stop")(function* (options = {}) {
135
+ const info = yield* read(options.file);
136
+ if (options.pty === "handoff" && info !== undefined)
137
+ yield* Effect.tryPromise(() => prepare2(options.file ?? fallback(), info, defaultEnsureTiming2.requestTimeout));
138
+ else
139
+ yield* Effect.tryPromise(() => clear2(options.file ?? fallback()));
140
+ if (info !== undefined)
141
+ yield* terminate(info, options, defaultEnsureTiming2);
145
142
  });
146
143
  function fallback() {
147
- const state = process.env["XDG_STATE_HOME"] ?? join(homedir(), ".local", "state");
148
- return join(state, "opencode", "service.json");
144
+ const state = process.env["XDG_STATE_HOME"] ?? join(homedir(), ".local", "state");
145
+ return join(state, "opencode", "service.json");
149
146
  }
150
- /** Create HTTP authentication headers for a service endpoint. */
151
- export function headers(endpoint) {
152
- if (endpoint.auth === undefined)
153
- return undefined;
154
- return { authorization: "Basic " + btoa(endpoint.auth.username + ":" + endpoint.auth.password) };
147
+ function headers(endpoint) {
148
+ if (endpoint.auth === undefined)
149
+ return;
150
+ return { authorization: "Basic " + btoa(endpoint.auth.username + ":" + endpoint.auth.password) };
155
151
  }
156
- /** Schema for the local service registration file. */
157
- export const Info = Schema.Struct({
158
- id: Schema.optional(Schema.String),
159
- version: Schema.optional(Schema.String),
160
- url: Schema.String,
161
- pid: Schema.Int.check(Schema.isGreaterThan(0)),
162
- password: Schema.optional(Schema.String),
152
+ var Info = Schema.Struct({
153
+ id: Schema.optional(Schema.String),
154
+ version: Schema.optional(Schema.String),
155
+ url: Schema.String,
156
+ pid: Schema.Int.check(Schema.isGreaterThan(0)),
157
+ password: Schema.optional(Schema.String)
163
158
  });
164
- const decode = Schema.decodeUnknownEffect(Schema.fromJsonString(Info));
165
- const decodeInfo = Schema.decodeUnknownOption(Schema.Struct({
166
- version: Schema.String,
167
- pid: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),
159
+ var decode = Schema.decodeUnknownEffect(Schema.fromJsonString(Info));
160
+ var decodeInfo = Schema.decodeUnknownOption(Schema.Struct({
161
+ version: Schema.String,
162
+ pid: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))
168
163
  }));
169
- // A missing or corrupt file means no valid info; callers treat both
170
- // the same (the registering server self-evicts, clients rediscover).
171
- const read = Effect.fnUntraced(function* (file) {
172
- const fs = yield* FileSystem.FileSystem;
173
- const text = yield* fs.readFileString(file ?? fallback()).pipe(Effect.option);
174
- if (Option.isNone(text))
175
- return undefined;
176
- return yield* decode(text.value).pipe(Effect.option, Effect.map(Option.getOrUndefined));
164
+ var read = Effect.fnUntraced(function* (file) {
165
+ const fs = yield* FileSystem.FileSystem;
166
+ const text = yield* fs.readFileString(file ?? fallback()).pipe(Effect.option);
167
+ if (Option.isNone(text))
168
+ return;
169
+ return yield* decode(text.value).pipe(Effect.option, Effect.map(Option.getOrUndefined));
177
170
  });
178
- const probe = Effect.fnUntraced(function* (info) {
179
- return (yield* probeResult(info)).service;
171
+ var probe = Effect.fnUntraced(function* (info) {
172
+ return (yield* probeResult(info)).service;
180
173
  });
181
- const probeResult = Effect.fnUntraced(function* (info, timeout = defaultEnsureTiming.requestTimeout) {
182
- const endpoint = {
183
- url: info.url,
184
- auth: info.password === undefined
185
- ? undefined
186
- : { type: "basic", username: "opencode", password: info.password },
174
+ var probeResult = Effect.fnUntraced(function* (info, timeout = defaultEnsureTiming2.requestTimeout) {
175
+ const endpoint = {
176
+ url: info.url,
177
+ auth: info.password === undefined ? undefined : { type: "basic", username: "opencode", password: info.password }
178
+ };
179
+ const signal = AbortSignal.timeout(timeout);
180
+ const result = yield* Effect.promise(() => fetch(new URL("/api/info", info.url), { headers: headers(endpoint), signal }).then(async (response) => ({
181
+ response,
182
+ body: response.status === 404 ? undefined : await response.json()
183
+ })).then((value) => ({ value }), (cause) => ({ cause })));
184
+ if ("cause" in result)
185
+ return { service: undefined, timedOut: signal.aborted };
186
+ const response = result.value.response;
187
+ if (response.status === 404)
188
+ return {
189
+ service: {
190
+ info,
191
+ endpoint,
192
+ version: info.version,
193
+ state: "ready",
194
+ compatible: false
195
+ },
196
+ timedOut: false
187
197
  };
188
- const signal = AbortSignal.timeout(timeout);
189
- const result = yield* Effect.promise(() => fetch(new URL("/api/info", info.url), { headers: headers(endpoint), signal })
190
- .then(async (response) => ({
191
- response,
192
- body: response.status === 404 ? undefined : (await response.json()),
193
- }))
194
- .then((value) => ({ value }), (cause) => ({ cause })));
195
- if ("cause" in result)
196
- return { service: undefined, timedOut: signal.aborted };
197
- const response = result.value.response;
198
- // The previous V2 service exposes /api/status instead. Its authenticated 404 is enough
199
- // to recognize the registered daemon as incompatible and route it through replacement.
200
- if (response.status === 404)
201
- return {
202
- service: {
203
- info,
204
- endpoint,
205
- version: info.version,
206
- state: "ready",
207
- compatible: false,
208
- },
209
- timedOut: false,
210
- };
211
- const body = result.value.body;
212
- const serverInfo = decodeInfo(body);
213
- if (Option.isSome(serverInfo)) {
214
- if (serverInfo.value.pid !== info.pid)
215
- return { service: undefined, timedOut: false };
216
- if (info.version !== undefined && serverInfo.value.version !== info.version)
217
- return { service: undefined, timedOut: false };
218
- return {
219
- service: {
220
- info,
221
- endpoint,
222
- version: serverInfo.value.version,
223
- state: response.ok ? "ready" : response.status === 500 ? "failed" : "waiting",
224
- compatible: true,
225
- },
226
- timedOut: false,
227
- };
228
- }
229
- return { service: undefined, timedOut: false };
198
+ const body = result.value.body;
199
+ const serverInfo = decodeInfo(body);
200
+ if (Option.isSome(serverInfo)) {
201
+ if (serverInfo.value.pid !== info.pid)
202
+ return { service: undefined, timedOut: false };
203
+ if (info.version !== undefined && serverInfo.value.version !== info.version)
204
+ return { service: undefined, timedOut: false };
205
+ return {
206
+ service: {
207
+ info,
208
+ endpoint,
209
+ version: serverInfo.value.version,
210
+ state: response.ok ? "ready" : response.status === 500 ? "failed" : "waiting",
211
+ compatible: true
212
+ },
213
+ timedOut: false
214
+ };
215
+ }
216
+ return { service: undefined, timedOut: false };
230
217
  });
231
- const registered = Effect.fnUntraced(function* (file, timeout) {
232
- const info = yield* read(file);
233
- if (info === undefined)
234
- return { info: undefined, service: undefined, timedOut: false };
235
- return { info, ...(yield* probeResult(info, timeout)) };
218
+ var registered = Effect.fnUntraced(function* (file, timeout) {
219
+ const info = yield* read(file);
220
+ if (info === undefined)
221
+ return { info: undefined, service: undefined, timedOut: false };
222
+ return { info, ...yield* probeResult(info, timeout) };
236
223
  });
237
- // 50ms cadence bounded at ~5s, shared by stop escalation and each ensure
238
- // discovery window.
239
- const poll = (timing) => Schedule.max([Schedule.spaced(timing.stopPollInterval), Schedule.recurs(timing.stopPollAttempts)]);
240
- const signal = (pid, name) => Effect.try({ try: () => process.kill(pid, name), catch: (cause) => cause }).pipe(Effect.ignore);
241
- const stopped = Effect.fnUntraced(function* (pid) {
242
- const running = yield* Effect.try({ try: () => process.kill(pid, 0), catch: () => false }).pipe(Effect.orElseSucceed(() => false));
243
- if (!running)
244
- return true;
245
- return yield* Effect.fail(new Error(`Server process ${pid} is still running`));
224
+ var poll = (timing) => Schedule.max([Schedule.spaced(timing.stopPollInterval), Schedule.recurs(timing.stopPollAttempts)]);
225
+ var signal = (pid, name) => Effect.try({ try: () => process.kill(pid, name), catch: (cause) => cause }).pipe(Effect.ignore);
226
+ var stopped = Effect.fnUntraced(function* (pid) {
227
+ const running = yield* Effect.try({ try: () => process.kill(pid, 0), catch: () => false }).pipe(Effect.orElseSucceed(() => false));
228
+ if (!running)
229
+ return true;
230
+ return yield* Effect.fail(new Error(`Server process ${pid} is still running`));
246
231
  });
247
232
  function same(left, right) {
248
- return left.id === right.id && left.version === right.version && left.url === right.url && left.pid === right.pid;
233
+ return left.id === right.id && left.version === right.version && left.url === right.url && left.pid === right.pid;
249
234
  }
250
- const terminate = Effect.fnUntraced(function* (info, options, timing) {
251
- const current = yield* read(options.file);
252
- if (current === undefined || !same(current, info))
253
- return;
254
- yield* signal(info.pid, "SIGTERM");
255
- const done = yield* stopped(info.pid).pipe(Effect.retry(poll(timing)), Effect.option);
256
- if (Option.isNone(done)) {
257
- const latest = yield* read(options.file);
258
- if (latest === undefined || !same(latest, info))
259
- return;
260
- yield* signal(info.pid, "SIGKILL");
261
- yield* stopped(info.pid).pipe(Effect.retry(poll(timing)));
262
- }
235
+ var terminate = Effect.fnUntraced(function* (info, options, timing) {
236
+ const current = yield* read(options.file);
237
+ if (current === undefined || !same(current, info))
238
+ return;
239
+ yield* signal(info.pid, "SIGTERM");
240
+ const done = yield* stopped(info.pid).pipe(Effect.retry(poll(timing)), Effect.option);
241
+ if (Option.isNone(done)) {
263
242
  const latest = yield* read(options.file);
264
243
  if (latest === undefined || !same(latest, info))
265
- return;
266
- const fs = yield* FileSystem.FileSystem;
267
- yield* fs.remove(options.file ?? fallback()).pipe(Effect.ignore);
244
+ return;
245
+ yield* signal(info.pid, "SIGKILL");
246
+ yield* stopped(info.pid).pipe(Effect.retry(poll(timing)));
247
+ }
248
+ const latest = yield* read(options.file);
249
+ if (latest === undefined || !same(latest, info))
250
+ return;
251
+ const fs = yield* FileSystem.FileSystem;
252
+ yield* fs.remove(options.file ?? fallback()).pipe(Effect.ignore);
268
253
  });
269
- /** Effect-based local service lifecycle operations. */
270
- export const Service = { discover, incumbent, ensure, stop, headers, Info };
254
+ var Service = { discover, incumbent, ensure, stop, headers, Info };
255
+ export {
256
+ Info,
257
+ Service,
258
+ discover,
259
+ ensure,
260
+ headers,
261
+ incumbent,
262
+ stop
263
+ };
@@ -1,13 +1,14 @@
1
- export * as OpenCode from "./client.js";
2
- import { SharedEvents } from "../shared-events.js";
3
- import { OpenCode } from "./generated/index.js";
4
- import { makeRpc } from "./rpc.js";
5
- export function make(options) {
6
- const raw = OpenCode.make(options);
7
- const events = SharedEvents.make((signal, onActivity) => raw.event.subscribe({ signal, onActivity }));
8
- return {
9
- ...raw,
10
- rpc: Object.assign(makeRpc(raw, events), raw.rpc),
11
- event: events,
12
- };
13
- }
1
+ import {
2
+ make5,
3
+ exports_client3
4
+ } from "../chunks/pty-handoff-vgxtr9hm.js";
5
+ import"../chunks/pty-handoff-1tbj6z39.js";
6
+ import"../chunks/pty-handoff-vyas3vgt.js";
7
+ import"../chunks/pty-handoff-radw39tv.js";
8
+ import"../chunks/pty-handoff-4tveyqeh.js";
9
+ import"../chunks/pty-handoff-n3c99vt5.js";
10
+ import"../chunks/pty-handoff-frbwqjmf.js";
11
+ export {
12
+ exports_client3 as OpenCode,
13
+ make5 as make
14
+ };
@@ -1,8 +1,6 @@
1
- export class ClientError extends Error {
2
- reason;
3
- name = "ClientError";
4
- constructor(reason, options) {
5
- super(reason, options);
6
- this.reason = reason;
7
- }
8
- }
1
+ import {
2
+ ClientError3
3
+ } from "../../chunks/pty-handoff-n3c99vt5.js";
4
+ export {
5
+ ClientError3 as ClientError
6
+ };