@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
package/dist/effect/service.js
CHANGED
|
@@ -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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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
|
-
|
|
148
|
-
|
|
144
|
+
const state = process.env["XDG_STATE_HOME"] ?? join(homedir(), ".local", "state");
|
|
145
|
+
return join(state, "opencode", "service.json");
|
|
149
146
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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
|
-
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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
|
-
|
|
179
|
-
|
|
171
|
+
var probe = Effect.fnUntraced(function* (info) {
|
|
172
|
+
return (yield* probeResult(info)).service;
|
|
180
173
|
});
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
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
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
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
|
-
|
|
233
|
+
return left.id === right.id && left.version === right.version && left.url === right.url && left.pid === right.pid;
|
|
249
234
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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
|
-
|
|
266
|
-
|
|
267
|
-
yield*
|
|
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
|
-
|
|
270
|
-
export
|
|
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
|
+
};
|
package/dist/promise/client.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
ClientError3
|
|
3
|
+
} from "../../chunks/pty-handoff-n3c99vt5.js";
|
|
4
|
+
export {
|
|
5
|
+
ClientError3 as ClientError
|
|
6
|
+
};
|