@cueloop/daemon 0.1.0-alpha.97 → 0.1.0-alpha.99
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/README.md +7 -0
- package/SDK.md +102 -0
- package/package.json +12 -8
- package/src/agent-tools.ts +98 -0
- package/src/agent-turn.test.ts +24 -0
- package/src/agent-turn.ts +34 -0
- package/src/api.ts +19 -1
- package/src/capabilities.ts +7 -0
- package/src/client-errors.ts +24 -0
- package/src/client-reliability.test.ts +189 -0
- package/src/client.test.ts +13 -0
- package/src/client.ts +179 -23
- package/src/daemon-sdk-effect.ts +113 -0
- package/src/daemon-sdk.test.ts +306 -0
- package/src/daemon-sdk.ts +397 -0
- package/src/examples/daemon-sdk.ts +55 -0
- package/src/harness-delivery.test.ts +1 -0
- package/src/harness-diagnostics.test.ts +26 -0
- package/src/harness-diagnostics.ts +30 -0
- package/src/operation-receipts.test.ts +111 -0
- package/src/operation-receipts.ts +91 -0
- package/src/pr-poller.ts +1 -0
- package/src/sdk-identities.ts +35 -0
- package/src/server.ts +181 -2
- package/src/share-blob.ts +3 -1
- package/src/store.jsonl.test.ts +14 -0
- package/src/store.ts +11 -2
- package/src/thread-agent-validation.ts +119 -0
- package/src/thread-agent.test.ts +412 -0
- package/src/thread-agent.ts +714 -0
- package/src/thread-review.ts +1 -0
- package/src/thread-subscription.test.ts +174 -0
- package/src/thread-subscription.ts +127 -0
- package/src/validate.test.ts +1 -0
- package/src/validate.ts +26 -0
- package/src/vcs-source.ts +1 -0
- package/src/working-tree.ts +2 -0
package/src/client.ts
CHANGED
|
@@ -57,7 +57,11 @@ import {
|
|
|
57
57
|
PendingDeliverySchema,
|
|
58
58
|
} from "./validate";
|
|
59
59
|
import type { WorkingTreeDiff } from "./working-tree";
|
|
60
|
+
import { DaemonTransportError, type DaemonRequestOptions } from "./client-errors";
|
|
61
|
+
export { DaemonTransportError, type DaemonRequestOptions } from "./client-errors";
|
|
60
62
|
import { DAEMON_VERSION } from "./version";
|
|
63
|
+
import { ThreadAgentSchema } from "./thread-agent-validation";
|
|
64
|
+
import type { AgentComment, ThreadAgentState, AgentPromptRequest } from "@cueloop/schema";
|
|
61
65
|
|
|
62
66
|
export type { EventFrame } from "./protocol";
|
|
63
67
|
|
|
@@ -101,6 +105,8 @@ export interface ThreadClient {
|
|
|
101
105
|
onEvent(listener: (event: EventFrame) => void): () => void;
|
|
102
106
|
subscribe(): Promise<void>;
|
|
103
107
|
sessionGet(id: string): Promise<Thread>;
|
|
108
|
+
/** Create a local owner Thread; shared clients omit this capability. */
|
|
109
|
+
sessionCreate?(workspace: WorkspaceKey, artifact: Artifact): Promise<Thread>;
|
|
104
110
|
sessionList(filter?: { status?: "pending" | "resolved" }): Promise<Thread[]>;
|
|
105
111
|
/** Add a comment; the primary annotate method. `sessionAnnotate` is the retained alias. */
|
|
106
112
|
sessionComment(
|
|
@@ -222,7 +228,8 @@ export class DaemonClient implements ThreadClient {
|
|
|
222
228
|
private daemonVersion: string | undefined;
|
|
223
229
|
private nextId = 1;
|
|
224
230
|
private eventListeners = new Set<(event: EventFrame) => void>();
|
|
225
|
-
private disconnectListeners = new Set<() => void>();
|
|
231
|
+
private disconnectListeners = new Set<(reason: DaemonTransportError) => void>();
|
|
232
|
+
private disconnectReason: DaemonTransportError | undefined;
|
|
226
233
|
private closed = false;
|
|
227
234
|
private role: DaemonRole = "owner";
|
|
228
235
|
private author: string | undefined;
|
|
@@ -251,7 +258,15 @@ export class DaemonClient implements ThreadClient {
|
|
|
251
258
|
if (!options.autostart || err instanceof DaemonClientError) {
|
|
252
259
|
client.close();
|
|
253
260
|
|
|
254
|
-
throw err
|
|
261
|
+
throw err instanceof DaemonClientError || err instanceof DaemonTransportError
|
|
262
|
+
? err
|
|
263
|
+
: new DaemonTransportError(
|
|
264
|
+
"connection",
|
|
265
|
+
"Daemon connection failed",
|
|
266
|
+
"not_sent",
|
|
267
|
+
undefined,
|
|
268
|
+
{ cause: err },
|
|
269
|
+
);
|
|
255
270
|
}
|
|
256
271
|
}
|
|
257
272
|
|
|
@@ -266,7 +281,9 @@ export class DaemonClient implements ThreadClient {
|
|
|
266
281
|
this.writer = null;
|
|
267
282
|
this.closed = false;
|
|
268
283
|
for (const pendingRequest of this.pending.values())
|
|
269
|
-
pendingRequest.reject(
|
|
284
|
+
pendingRequest.reject(
|
|
285
|
+
new DaemonTransportError("connection", "daemon connection replaced", "unknown"),
|
|
286
|
+
);
|
|
270
287
|
this.pending.clear();
|
|
271
288
|
}
|
|
272
289
|
|
|
@@ -306,7 +323,11 @@ export class DaemonClient implements ThreadClient {
|
|
|
306
323
|
const output = readFileSync(startupLogPath, "utf8").trim();
|
|
307
324
|
const detail = output ? `\ndaemon startup output:\n${output.slice(-4_096)}` : "";
|
|
308
325
|
|
|
309
|
-
throw new
|
|
326
|
+
throw new DaemonTransportError(
|
|
327
|
+
"connection",
|
|
328
|
+
`Daemon startup failed at ${path}: ${String(lastError)}${detail}`,
|
|
329
|
+
"not_sent",
|
|
330
|
+
);
|
|
310
331
|
} finally {
|
|
311
332
|
rmSync(startupLogPath, { force: true });
|
|
312
333
|
}
|
|
@@ -314,15 +335,23 @@ export class DaemonClient implements ThreadClient {
|
|
|
314
335
|
|
|
315
336
|
private async dial(path: string): Promise<void> {
|
|
316
337
|
const buffer = new LineBuffer();
|
|
338
|
+
|
|
339
|
+
this.disconnectReason = undefined;
|
|
317
340
|
const epoch = ++this.connectionEpoch;
|
|
318
341
|
|
|
319
342
|
const close = () => {
|
|
320
343
|
if (this.connectionEpoch !== epoch) return;
|
|
321
344
|
this.closed = true;
|
|
322
345
|
for (const pendingRequest of this.pending.values())
|
|
323
|
-
pendingRequest.reject(
|
|
346
|
+
pendingRequest.reject(
|
|
347
|
+
new DaemonTransportError("connection", "daemon connection closed", "unknown"),
|
|
348
|
+
);
|
|
324
349
|
this.pending.clear();
|
|
325
|
-
|
|
350
|
+
const reason =
|
|
351
|
+
this.disconnectReason ??
|
|
352
|
+
new DaemonTransportError("connection", "daemon connection closed", "unknown");
|
|
353
|
+
|
|
354
|
+
for (const listener of this.disconnectListeners) listener(reason);
|
|
326
355
|
};
|
|
327
356
|
|
|
328
357
|
if (typeof Bun !== "undefined") {
|
|
@@ -395,7 +424,7 @@ export class DaemonClient implements ThreadClient {
|
|
|
395
424
|
}
|
|
396
425
|
|
|
397
426
|
/** Notify an adapter when its daemon socket closes so it can reconnect and replay Messages. */
|
|
398
|
-
onDisconnect(listener: () => void): () => void {
|
|
427
|
+
onDisconnect(listener: (reason: DaemonTransportError) => void): () => void {
|
|
399
428
|
this.disconnectListeners.add(listener);
|
|
400
429
|
|
|
401
430
|
return () => this.disconnectListeners.delete(listener);
|
|
@@ -406,7 +435,27 @@ export class DaemonClient implements ThreadClient {
|
|
|
406
435
|
|
|
407
436
|
try {
|
|
408
437
|
frame = parseInboundFrame(line);
|
|
409
|
-
} catch {
|
|
438
|
+
} catch (cause) {
|
|
439
|
+
this.disconnectReason = new DaemonTransportError(
|
|
440
|
+
"protocol",
|
|
441
|
+
"daemon sent a malformed frame",
|
|
442
|
+
"unknown",
|
|
443
|
+
undefined,
|
|
444
|
+
{ cause },
|
|
445
|
+
);
|
|
446
|
+
for (const pendingRequest of this.pending.values())
|
|
447
|
+
pendingRequest.reject(
|
|
448
|
+
new DaemonTransportError(
|
|
449
|
+
"protocol",
|
|
450
|
+
"daemon sent a malformed frame",
|
|
451
|
+
"unknown",
|
|
452
|
+
undefined,
|
|
453
|
+
{ cause },
|
|
454
|
+
),
|
|
455
|
+
);
|
|
456
|
+
this.pending.clear();
|
|
457
|
+
this.close();
|
|
458
|
+
|
|
410
459
|
return;
|
|
411
460
|
}
|
|
412
461
|
if ("event" in frame) {
|
|
@@ -427,37 +476,135 @@ export class DaemonClient implements ThreadClient {
|
|
|
427
476
|
method: string,
|
|
428
477
|
params: Request["params"],
|
|
429
478
|
resultSchema: v.GenericSchema<unknown, TOutput>,
|
|
430
|
-
|
|
479
|
+
options: number | DaemonRequestOptions = 30_000,
|
|
431
480
|
): Promise<TOutput> {
|
|
432
|
-
|
|
481
|
+
const { timeoutMs = 30_000, signal } = v.is(v.number(), options)
|
|
482
|
+
? { timeoutMs: options }
|
|
483
|
+
: options;
|
|
484
|
+
|
|
485
|
+
if (signal?.aborted)
|
|
486
|
+
return Promise.reject(
|
|
487
|
+
new DaemonTransportError("cancelled", `request ${method} cancelled`, "not_sent", method),
|
|
488
|
+
);
|
|
489
|
+
if (this.closed || !this.socket)
|
|
490
|
+
return Promise.reject(
|
|
491
|
+
new DaemonTransportError("connection", "not connected", "not_sent", method),
|
|
492
|
+
);
|
|
433
493
|
const id = this.nextId++;
|
|
434
494
|
|
|
435
495
|
return new Promise<TOutput>((resolve, reject) => {
|
|
436
|
-
const
|
|
496
|
+
const cleanup = () => {
|
|
497
|
+
clearTimeout(timer);
|
|
498
|
+
signal?.removeEventListener("abort", abort);
|
|
437
499
|
this.pending.delete(id);
|
|
438
|
-
|
|
500
|
+
};
|
|
501
|
+
const fail = (error: Error) => {
|
|
502
|
+
cleanup();
|
|
503
|
+
reject(error);
|
|
504
|
+
};
|
|
505
|
+
const abort = () =>
|
|
506
|
+
fail(
|
|
507
|
+
new DaemonTransportError("cancelled", `request ${method} cancelled`, "unknown", method),
|
|
508
|
+
);
|
|
509
|
+
const timer = setTimeout(() => {
|
|
510
|
+
fail(new DaemonTransportError("timeout", `request ${method} timed out`, "unknown", method));
|
|
439
511
|
}, timeoutMs);
|
|
440
512
|
|
|
441
513
|
this.pending.set(id, {
|
|
442
514
|
resolve: (value) => {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
515
|
+
cleanup();
|
|
516
|
+
try {
|
|
517
|
+
const parsed = v.safeParse(resultSchema, value);
|
|
518
|
+
|
|
519
|
+
if (!parsed.success)
|
|
520
|
+
throw new DaemonTransportError(
|
|
521
|
+
"protocol",
|
|
522
|
+
`request ${method} returned an invalid result`,
|
|
523
|
+
"unknown",
|
|
524
|
+
method,
|
|
525
|
+
{ cause: parsed.issues },
|
|
526
|
+
);
|
|
527
|
+
resolve(parsed.output);
|
|
528
|
+
} catch (cause) {
|
|
529
|
+
reject(
|
|
530
|
+
cause instanceof DaemonTransportError
|
|
531
|
+
? cause
|
|
532
|
+
: new DaemonTransportError(
|
|
533
|
+
"protocol",
|
|
534
|
+
`request ${method} returned an invalid result`,
|
|
535
|
+
"unknown",
|
|
536
|
+
method,
|
|
537
|
+
{ cause },
|
|
538
|
+
),
|
|
539
|
+
);
|
|
540
|
+
}
|
|
449
541
|
},
|
|
542
|
+
reject: fail,
|
|
450
543
|
});
|
|
451
|
-
|
|
544
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
545
|
+
try {
|
|
546
|
+
this.writer!.write(JSON.stringify({ id, method, params }) + "\n");
|
|
547
|
+
} catch (cause) {
|
|
548
|
+
fail(
|
|
549
|
+
new DaemonTransportError(
|
|
550
|
+
"connection",
|
|
551
|
+
`request ${method} could not be written`,
|
|
552
|
+
"unknown",
|
|
553
|
+
method,
|
|
554
|
+
{ cause },
|
|
555
|
+
),
|
|
556
|
+
);
|
|
557
|
+
}
|
|
452
558
|
});
|
|
453
559
|
}
|
|
454
560
|
|
|
455
561
|
close(): void {
|
|
456
562
|
this.closed = true;
|
|
563
|
+
for (const pendingRequest of this.pending.values())
|
|
564
|
+
pendingRequest.reject(
|
|
565
|
+
new DaemonTransportError("connection", "daemon connection closed", "unknown"),
|
|
566
|
+
);
|
|
567
|
+
this.pending.clear();
|
|
457
568
|
this.socket?.end();
|
|
458
569
|
}
|
|
459
570
|
|
|
460
571
|
// ── typed primitives ─────────────────────────────
|
|
572
|
+
/** Read the agent transcript without starting a model request. */
|
|
573
|
+
agentGet(id: string, options?: DaemonRequestOptions): Promise<ThreadAgentState> {
|
|
574
|
+
return this.request("agent.get", { id }, ThreadAgentSchema, options);
|
|
575
|
+
}
|
|
576
|
+
/** Submit a question and optional selected passage to the daemon-owned agent. */
|
|
577
|
+
agentPrompt(
|
|
578
|
+
params: AgentPromptRequest,
|
|
579
|
+
options?: DaemonRequestOptions,
|
|
580
|
+
): Promise<ThreadAgentState> {
|
|
581
|
+
return this.request("agent.prompt", params, ThreadAgentSchema, options);
|
|
582
|
+
}
|
|
583
|
+
/** Cancel the active turn; the daemon retains partial output. */
|
|
584
|
+
agentCancel(id: string): Promise<ThreadAgentState> {
|
|
585
|
+
return this.request("agent.cancel", { id }, ThreadAgentSchema);
|
|
586
|
+
}
|
|
587
|
+
/** Save quote-primary feedback on a finalized agent answer. */
|
|
588
|
+
agentComment(params: { id: string; comment: AgentComment }): Promise<ThreadAgentState> {
|
|
589
|
+
return this.request("agent.comment", params, ThreadAgentSchema);
|
|
590
|
+
}
|
|
591
|
+
/** Configure only an option advertised by the current harness. */
|
|
592
|
+
agentConfigure(params: {
|
|
593
|
+
id: string;
|
|
594
|
+
configId?: string;
|
|
595
|
+
value?: string;
|
|
596
|
+
}): Promise<ThreadAgentState> {
|
|
597
|
+
return this.request("agent.configure", params, ThreadAgentSchema);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/** Select an option from the active agent permission card. */
|
|
601
|
+
agentPermission(params: {
|
|
602
|
+
id: string;
|
|
603
|
+
requestId: string;
|
|
604
|
+
optionId: string;
|
|
605
|
+
}): Promise<ThreadAgentState> {
|
|
606
|
+
return this.request("agent.permission", params, ThreadAgentSchema);
|
|
607
|
+
}
|
|
461
608
|
ping(): Promise<{ pid: number }> {
|
|
462
609
|
return this.request("daemon.ping", {}, PingResultSchema);
|
|
463
610
|
}
|
|
@@ -639,11 +786,14 @@ export class DaemonClient implements ThreadClient {
|
|
|
639
786
|
outcome: MessageOutcome,
|
|
640
787
|
summary: string,
|
|
641
788
|
actionBodies?: Record<string, string>,
|
|
789
|
+
operationId?: string,
|
|
790
|
+
options?: DaemonRequestOptions,
|
|
642
791
|
): Promise<Thread> {
|
|
643
792
|
return this.request(
|
|
644
793
|
"session.sendMessage",
|
|
645
|
-
{ id, outcome, summary, actionBodies },
|
|
794
|
+
{ id, outcome, summary, actionBodies, operationId },
|
|
646
795
|
ThreadRecordSchema,
|
|
796
|
+
options,
|
|
647
797
|
);
|
|
648
798
|
}
|
|
649
799
|
harnessBind(
|
|
@@ -722,6 +872,7 @@ export class DaemonClient implements ThreadClient {
|
|
|
722
872
|
}
|
|
723
873
|
|
|
724
874
|
export class DaemonClientError extends Error {
|
|
875
|
+
readonly _tag = "DaemonClientError";
|
|
725
876
|
constructor(
|
|
726
877
|
readonly code: string,
|
|
727
878
|
message: string,
|
|
@@ -731,7 +882,7 @@ export class DaemonClientError extends Error {
|
|
|
731
882
|
}
|
|
732
883
|
|
|
733
884
|
// A compiled binary re-execs `cueloop daemon --autostart` (idle-exits like main.ts,
|
|
734
|
-
// unlike the never-exiting foreground daemon);
|
|
885
|
+
// unlike the never-exiting foreground daemon); source also uses the CLI composition root. In
|
|
735
886
|
// dev (CUELOOP_DEV_WATCH=1, source only) it runs under --watch so daemon-code edits
|
|
736
887
|
// reload the daemon without a manual restart - the version handshake only catches
|
|
737
888
|
// release upgrades, not same-version source changes.
|
|
@@ -739,14 +890,19 @@ export function daemonSpawnCommand(
|
|
|
739
890
|
execPath: string,
|
|
740
891
|
moduleUrl: string,
|
|
741
892
|
devWatch = process.env.CUELOOP_DEV_WATCH === "1",
|
|
893
|
+
entry = process.env.CUELOOP_DAEMON_ENTRY,
|
|
742
894
|
): string[] {
|
|
743
895
|
const compiled =
|
|
744
896
|
moduleUrl.includes("$bunfs") || moduleUrl.includes("~BUN") || moduleUrl.includes("%7EBUN");
|
|
745
897
|
|
|
746
898
|
if (compiled) return [execPath, "daemon", "--autostart"];
|
|
747
|
-
const mainPath = new URL("./main.ts", moduleUrl).pathname;
|
|
899
|
+
const mainPath = entry ?? new URL("./main.ts", moduleUrl).pathname;
|
|
900
|
+
|
|
901
|
+
const args = entry ? ["daemon", "--autostart"] : [];
|
|
748
902
|
|
|
749
|
-
return devWatch
|
|
903
|
+
return devWatch
|
|
904
|
+
? [execPath, "--watch", "run", mainPath, ...args]
|
|
905
|
+
: [execPath, "run", mainPath, ...args];
|
|
750
906
|
}
|
|
751
907
|
|
|
752
908
|
function spawnDaemon(home: string): string {
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Context, Effect, Layer, Stream, Queue, Cause, type Scope } from "effect";
|
|
2
|
+
import {
|
|
3
|
+
connectOwnerSdk,
|
|
4
|
+
normalizeSdkError,
|
|
5
|
+
type OwnerDaemonSdk,
|
|
6
|
+
type DaemonSdkError,
|
|
7
|
+
type SdkThread,
|
|
8
|
+
type SdkThreadId,
|
|
9
|
+
} from "./daemon-sdk";
|
|
10
|
+
import type { ConnectOptions } from "./client";
|
|
11
|
+
import type { DaemonRequestOptions } from "./client-errors";
|
|
12
|
+
|
|
13
|
+
type EffectMethods<Methods> = {
|
|
14
|
+
readonly [Key in keyof Methods]: Methods[Key] extends (
|
|
15
|
+
...args: infer Arguments
|
|
16
|
+
) => Promise<infer Result>
|
|
17
|
+
? (...args: Arguments) => Effect.Effect<Result, DaemonSdkError>
|
|
18
|
+
: never;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** The Effect service owns a scoped connection while daemon-owned work outlives local waits. */
|
|
22
|
+
export class CueloopSdk extends Context.Service<
|
|
23
|
+
CueloopSdk,
|
|
24
|
+
{
|
|
25
|
+
readonly ids: OwnerDaemonSdk["ids"];
|
|
26
|
+
readonly threads: EffectMethods<OwnerDaemonSdk["threads"]> & {
|
|
27
|
+
watch(threadId: SdkThreadId): Stream.Stream<SdkThread, DaemonSdkError>;
|
|
28
|
+
};
|
|
29
|
+
readonly comments: EffectMethods<OwnerDaemonSdk["comments"]>;
|
|
30
|
+
readonly sessions: EffectMethods<OwnerDaemonSdk["sessions"]>;
|
|
31
|
+
readonly agents: EffectMethods<OwnerDaemonSdk["agents"]>;
|
|
32
|
+
}
|
|
33
|
+
>()("@cueloop/daemon/CueloopSdk") {
|
|
34
|
+
static ownerLayer(
|
|
35
|
+
options: Omit<ConnectOptions, "role"> = {},
|
|
36
|
+
): Layer.Layer<CueloopSdk, DaemonSdkError> {
|
|
37
|
+
return Layer.effect(CueloopSdk, acquireOwnerSdk(options).pipe(Effect.map(effectSdkService)));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function acquireOwnerSdk(
|
|
42
|
+
options: Omit<ConnectOptions, "role">,
|
|
43
|
+
): Effect.Effect<OwnerDaemonSdk, DaemonSdkError, Scope.Scope> {
|
|
44
|
+
return Effect.acquireRelease(
|
|
45
|
+
Effect.tryPromise({ try: () => connectOwnerSdk(options), catch: normalizeSdkError }),
|
|
46
|
+
(sdk) => Effect.sync(() => sdk.close()),
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function sdkEffect<Result>(
|
|
51
|
+
request: (options: DaemonRequestOptions) => Promise<Result>,
|
|
52
|
+
options?: DaemonRequestOptions,
|
|
53
|
+
): Effect.Effect<Result, DaemonSdkError> {
|
|
54
|
+
return Effect.tryPromise({
|
|
55
|
+
try: (signal) =>
|
|
56
|
+
request({
|
|
57
|
+
...options,
|
|
58
|
+
signal: options?.signal ? AbortSignal.any([signal, options.signal]) : signal,
|
|
59
|
+
}),
|
|
60
|
+
catch: normalizeSdkError,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function effectSdkService(sdk: OwnerDaemonSdk): CueloopSdk["Service"] {
|
|
65
|
+
return {
|
|
66
|
+
ids: sdk.ids,
|
|
67
|
+
threads: {
|
|
68
|
+
watch: (threadId) =>
|
|
69
|
+
Stream.callback<SdkThread, DaemonSdkError>(
|
|
70
|
+
Effect.fn(function* (queue) {
|
|
71
|
+
yield* Effect.acquireRelease(
|
|
72
|
+
Effect.sync(() =>
|
|
73
|
+
sdk.observeThread({
|
|
74
|
+
threadId,
|
|
75
|
+
onValue: (thread) => {
|
|
76
|
+
Queue.offerUnsafe(queue, thread);
|
|
77
|
+
},
|
|
78
|
+
onError: (error) => {
|
|
79
|
+
if (error._tag === "DaemonClientError" || error.kind === "protocol")
|
|
80
|
+
Queue.failCauseUnsafe(queue, Cause.fail(error));
|
|
81
|
+
},
|
|
82
|
+
}),
|
|
83
|
+
),
|
|
84
|
+
(stop) => Effect.sync(stop),
|
|
85
|
+
);
|
|
86
|
+
}),
|
|
87
|
+
{ bufferSize: 1, strategy: "sliding" },
|
|
88
|
+
),
|
|
89
|
+
get: (id, options) => sdkEffect((request) => sdk.threads.get(id, request), options),
|
|
90
|
+
create: (input, options) =>
|
|
91
|
+
sdkEffect((request) => sdk.threads.create(input, request), options),
|
|
92
|
+
},
|
|
93
|
+
comments: {
|
|
94
|
+
add: (input, options) => sdkEffect((request) => sdk.comments.add(input, request), options),
|
|
95
|
+
list: (id, options) => sdkEffect((request) => sdk.comments.list(id, request), options),
|
|
96
|
+
reply: (input, options) =>
|
|
97
|
+
sdkEffect((request) => sdk.comments.reply(input, request), options),
|
|
98
|
+
},
|
|
99
|
+
sessions: {
|
|
100
|
+
sendMessage: (input, options) =>
|
|
101
|
+
sdkEffect((request) => sdk.sessions.sendMessage(input, request), options),
|
|
102
|
+
},
|
|
103
|
+
agents: {
|
|
104
|
+
get: (id, options) => sdkEffect((request) => sdk.agents.get(id, request), options),
|
|
105
|
+
prompt: (input, options) =>
|
|
106
|
+
sdkEffect((request) => sdk.agents.prompt(input, request), options),
|
|
107
|
+
replyToComment: (input, options) =>
|
|
108
|
+
sdkEffect((request) => sdk.agents.replyToComment(input, request), options),
|
|
109
|
+
wait: (input, options) => sdkEffect((request) => sdk.agents.wait(input, request), options),
|
|
110
|
+
cancel: (id, options) => sdkEffect((request) => sdk.agents.cancel(id, request), options),
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|