@mirasoth/soothe-client 0.2.1 → 0.4.1
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 +81 -47
- package/dist/{chunk-AQZACDIC.js → chunk-YYUVHZ3W.js} +607 -31
- package/dist/chunk-YYUVHZ3W.js.map +1 -0
- package/dist/client-SOJZSF7C.js +7 -0
- package/dist/index.cjs +1568 -298
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +355 -136
- package/dist/index.d.ts +355 -136
- package/dist/index.js +988 -258
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
- package/dist/chunk-AQZACDIC.js.map +0 -1
- package/dist/client-CB6WKQYW.js +0 -7
- /package/dist/{client-CB6WKQYW.js.map → client-SOJZSF7C.js.map} +0 -0
|
@@ -63,7 +63,7 @@ var ConnectionError = class extends Error {
|
|
|
63
63
|
}
|
|
64
64
|
};
|
|
65
65
|
var DaemonError = class extends Error {
|
|
66
|
-
/** Numeric error code from the
|
|
66
|
+
/** Numeric error code from the daemon error registry. */
|
|
67
67
|
code;
|
|
68
68
|
/** The daemon's error message text. */
|
|
69
69
|
daemonMessage;
|
|
@@ -293,11 +293,335 @@ var DEFAULT_DELIVERABLE_PHASES = /* @__PURE__ */ new Set([
|
|
|
293
293
|
"embed"
|
|
294
294
|
]);
|
|
295
295
|
|
|
296
|
+
// src/verbosity.ts
|
|
297
|
+
var VerbosityTier = /* @__PURE__ */ ((VerbosityTier2) => {
|
|
298
|
+
VerbosityTier2[VerbosityTier2["Quiet"] = 0] = "Quiet";
|
|
299
|
+
VerbosityTier2[VerbosityTier2["Normal"] = 1] = "Normal";
|
|
300
|
+
VerbosityTier2[VerbosityTier2["Detailed"] = 2] = "Detailed";
|
|
301
|
+
VerbosityTier2[VerbosityTier2["Debug"] = 3] = "Debug";
|
|
302
|
+
VerbosityTier2[VerbosityTier2["Internal"] = 99] = "Internal";
|
|
303
|
+
return VerbosityTier2;
|
|
304
|
+
})(VerbosityTier || {});
|
|
305
|
+
var verbosityLevelValues = {
|
|
306
|
+
quiet: 0,
|
|
307
|
+
normal: 1,
|
|
308
|
+
debug: 3
|
|
309
|
+
};
|
|
310
|
+
function shouldShow(tier, verbosity) {
|
|
311
|
+
if (tier === 99 /* Internal */) {
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
const level = verbosityLevelValues[verbosity] ?? 1;
|
|
315
|
+
return tier <= level;
|
|
316
|
+
}
|
|
317
|
+
function isValidVerbosityLevel(s) {
|
|
318
|
+
return s in verbosityLevelValues;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// src/events.ts
|
|
322
|
+
var EventPlanCreated = "soothe.cognition.plan.created";
|
|
323
|
+
var EventExploreStarted = "soothe.subagent.explore.started";
|
|
324
|
+
var EventExploreMilestone = "soothe.subagent.explore.milestone";
|
|
325
|
+
var EventExploreStepCompleted = "soothe.subagent.explore.step.completed";
|
|
326
|
+
var EventExploreCompleted = "soothe.subagent.explore.completed";
|
|
327
|
+
var EventTacitusStarted = "soothe.subagent.tacitus.started";
|
|
328
|
+
var EventTacitusGatherSummary = "soothe.subagent.tacitus.gather.summary";
|
|
329
|
+
var EventTacitusCompleted = "soothe.subagent.tacitus.completed";
|
|
330
|
+
var EventReplayComplete = "replay_complete";
|
|
331
|
+
var EventLoopReattachedWire = "loop_reattached";
|
|
332
|
+
var EventCardReplayBegin = "card.replay_begin";
|
|
333
|
+
var EventCardCreated = "card.created";
|
|
334
|
+
var EventCardReplayEnd = "card.replay_end";
|
|
335
|
+
var EventToolStarted = "soothe.tool.execution.started";
|
|
336
|
+
var EventToolCompleted = "soothe.tool.execution.completed";
|
|
337
|
+
var EventToolError = "soothe.tool.execution.error";
|
|
338
|
+
var EventStreamToolCallUpdate = "soothe.stream.tool_call.update";
|
|
339
|
+
var EventToolCallUpdatesBatch = "tool_call_updates_batch";
|
|
340
|
+
var EventStrangeLoopStarted = "soothe.cognition.strange_loop.started";
|
|
341
|
+
var EventStrangeLoopCompleted = "soothe.cognition.strange_loop.completed";
|
|
342
|
+
var EventStrangeLoopPlanDecision = "soothe.cognition.strange_loop.plan.decision";
|
|
343
|
+
var EventStrangeLoopReasoned = "soothe.cognition.strange_loop.reasoned";
|
|
344
|
+
var EventStrangeLoopStepStarted = "soothe.cognition.strange_loop.step.started";
|
|
345
|
+
var EventStrangeLoopStepQueued = "soothe.cognition.strange_loop.step.queued";
|
|
346
|
+
var EventStrangeLoopStepCompleted = "soothe.cognition.strange_loop.step.completed";
|
|
347
|
+
var EventStrangeLoopContextCompacted = "soothe.cognition.strange_loop.context.compacted";
|
|
348
|
+
var EventMessageReceived = "soothe.protocol.message.received";
|
|
349
|
+
var EventMessageSent = "soothe.protocol.message.sent";
|
|
350
|
+
var EventFinalReport = "soothe.output.autonomous.final_report.reported";
|
|
351
|
+
var EventAutopilotGoalStatus = "soothe.autopilot.goal.status";
|
|
352
|
+
var EventAutopilotGoalProgress = "soothe.autopilot.goal.progress";
|
|
353
|
+
var EventAutopilotGoalCreated = "soothe.autopilot.goal.created";
|
|
354
|
+
var EventAutopilotGoalCompleted = "soothe.autopilot.goal.completed";
|
|
355
|
+
var EventAutopilotWorkerAssigned = "soothe.autopilot.worker.assigned";
|
|
356
|
+
var EventAutopilotWorkerUnassigned = "soothe.autopilot.worker.unassigned";
|
|
357
|
+
var EventGeneralFailed = "soothe.error.general.failed";
|
|
358
|
+
function parseNamespace(ns) {
|
|
359
|
+
const parts = splitNamespace(ns);
|
|
360
|
+
if (parts.length < 4 || parts[0] !== "soothe") {
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
if (parts[1] === "internal") {
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
return { domain: parts[1], component: parts[2], action: parts[3] };
|
|
367
|
+
}
|
|
368
|
+
function splitNamespace(ns) {
|
|
369
|
+
const parts = [];
|
|
370
|
+
let start = 0;
|
|
371
|
+
for (let i = 0; i < ns.length; i++) {
|
|
372
|
+
if (ns[i] === ".") {
|
|
373
|
+
parts.push(ns.slice(start, i));
|
|
374
|
+
start = i + 1;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
parts.push(ns.slice(start));
|
|
378
|
+
return parts;
|
|
379
|
+
}
|
|
380
|
+
function classifyEventVerbosity(eventTypeOrNamespace) {
|
|
381
|
+
const parsed = parseNamespace(eventTypeOrNamespace);
|
|
382
|
+
if (!parsed) {
|
|
383
|
+
return classifyByEventTypeString(eventTypeOrNamespace);
|
|
384
|
+
}
|
|
385
|
+
return classifyByDomainAndComponent(parsed.domain, parsed.component, eventTypeOrNamespace);
|
|
386
|
+
}
|
|
387
|
+
function classifyByDomainAndComponent(domain, _component, full) {
|
|
388
|
+
switch (domain) {
|
|
389
|
+
case "cognition":
|
|
390
|
+
return 1 /* Normal */;
|
|
391
|
+
case "protocol":
|
|
392
|
+
return 2 /* Detailed */;
|
|
393
|
+
case "tool":
|
|
394
|
+
return 99 /* Internal */;
|
|
395
|
+
case "subagent":
|
|
396
|
+
return classifySubagentEvent(full);
|
|
397
|
+
case "autopilot":
|
|
398
|
+
return 1 /* Normal */;
|
|
399
|
+
case "output":
|
|
400
|
+
case "error":
|
|
401
|
+
return 0 /* Quiet */;
|
|
402
|
+
default:
|
|
403
|
+
return 1 /* Normal */;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
function classifySubagentEvent(full) {
|
|
407
|
+
const parsed = parseNamespace(full);
|
|
408
|
+
if (!parsed) return 1 /* Normal */;
|
|
409
|
+
switch (parsed.action) {
|
|
410
|
+
case "started":
|
|
411
|
+
case "completed":
|
|
412
|
+
return 1 /* Normal */;
|
|
413
|
+
default:
|
|
414
|
+
return 2 /* Detailed */;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
function classifyByEventTypeString(eventType) {
|
|
418
|
+
if (eventType === EventFinalReport || eventType === EventGeneralFailed) {
|
|
419
|
+
return 0 /* Quiet */;
|
|
420
|
+
}
|
|
421
|
+
if (eventType === EventToolStarted) {
|
|
422
|
+
return 99 /* Internal */;
|
|
423
|
+
}
|
|
424
|
+
return 1 /* Normal */;
|
|
425
|
+
}
|
|
426
|
+
function isCompletionEvent(eventType) {
|
|
427
|
+
return eventType.endsWith(".completed") || eventType.endsWith(".failed") || eventType === EventGeneralFailed;
|
|
428
|
+
}
|
|
429
|
+
function isSubagentProgressEvent(eventType) {
|
|
430
|
+
const parsed = parseNamespace(eventType);
|
|
431
|
+
if (!parsed || parsed.domain !== "subagent") {
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
return parsed.action === "started" || parsed.action === "completed";
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// src/stream_terminal.ts
|
|
438
|
+
var STREAM_END = "soothe.stream.end";
|
|
439
|
+
var TURN_END_CUSTOM_TYPES = /* @__PURE__ */ new Set([
|
|
440
|
+
STREAM_END,
|
|
441
|
+
EventStrangeLoopCompleted
|
|
442
|
+
]);
|
|
443
|
+
var TURN_PROGRESS_CUSTOM_TYPES = /* @__PURE__ */ new Set([
|
|
444
|
+
EventPlanCreated,
|
|
445
|
+
EventStrangeLoopStepStarted,
|
|
446
|
+
EventStrangeLoopStepQueued,
|
|
447
|
+
EventStrangeLoopStepCompleted
|
|
448
|
+
]);
|
|
449
|
+
var STALE_TURN_PENDING_TYPES = /* @__PURE__ */ new Set([
|
|
450
|
+
"connection_ack",
|
|
451
|
+
EventCardReplayBegin,
|
|
452
|
+
EventCardReplayEnd,
|
|
453
|
+
EventCardCreated,
|
|
454
|
+
"complete"
|
|
455
|
+
]);
|
|
456
|
+
function isTurnEndCustomData(data) {
|
|
457
|
+
if (!data || typeof data !== "object") return false;
|
|
458
|
+
const customType = String(data.type ?? "").trim();
|
|
459
|
+
if (!TURN_END_CUSTOM_TYPES.has(customType)) return false;
|
|
460
|
+
if (customType === STREAM_END) {
|
|
461
|
+
const scope = String(data.scope ?? "turn").trim().toLowerCase();
|
|
462
|
+
return scope === "" || scope === "turn";
|
|
463
|
+
}
|
|
464
|
+
return true;
|
|
465
|
+
}
|
|
466
|
+
function isTurnProgressChunk(mode, data) {
|
|
467
|
+
if (mode === "messages" || mode === "updates") return true;
|
|
468
|
+
if (mode !== "custom" || !data || typeof data !== "object") return false;
|
|
469
|
+
if (isTurnEndCustomData(data)) return false;
|
|
470
|
+
const customType = String(data.type ?? "").trim();
|
|
471
|
+
if (TURN_PROGRESS_CUSTOM_TYPES.has(customType)) return true;
|
|
472
|
+
if (customType.startsWith("soothe.cognition.strange_loop.step")) return true;
|
|
473
|
+
return false;
|
|
474
|
+
}
|
|
475
|
+
function stalePendingFrameLabel(event) {
|
|
476
|
+
const eventType = String(event.type ?? "");
|
|
477
|
+
if (STALE_TURN_PENDING_TYPES.has(eventType)) return eventType;
|
|
478
|
+
if (eventType === "next") {
|
|
479
|
+
const payload = event.payload;
|
|
480
|
+
if (!payload || typeof payload !== "object") return null;
|
|
481
|
+
const p = payload;
|
|
482
|
+
const staleMode = String(p.mode ?? "");
|
|
483
|
+
if (STALE_TURN_PENDING_TYPES.has(staleMode)) return staleMode;
|
|
484
|
+
const inner = p.data;
|
|
485
|
+
if (inner && typeof inner === "object") {
|
|
486
|
+
return stalePendingFrameLabel(inner);
|
|
487
|
+
}
|
|
488
|
+
return null;
|
|
489
|
+
}
|
|
490
|
+
if (eventType === "event") {
|
|
491
|
+
const mode = String(event.mode ?? "");
|
|
492
|
+
const data = event.data;
|
|
493
|
+
if (mode === "custom" && isTurnEndCustomData(data)) {
|
|
494
|
+
return String(data.type ?? "").trim();
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return null;
|
|
498
|
+
}
|
|
499
|
+
function inboundNeedsDeliveryAck(event) {
|
|
500
|
+
const eventType = String(event.type ?? "");
|
|
501
|
+
if (eventType === "complete") return true;
|
|
502
|
+
if (eventType === "next") {
|
|
503
|
+
const payload = event.payload;
|
|
504
|
+
if (!payload || typeof payload !== "object") return false;
|
|
505
|
+
const p = payload;
|
|
506
|
+
const inner = p.data;
|
|
507
|
+
if (!inner || typeof inner !== "object") return false;
|
|
508
|
+
if (String(p.mode ?? "") === "event") {
|
|
509
|
+
return inboundNeedsAckFromEventShape(inner);
|
|
510
|
+
}
|
|
511
|
+
return false;
|
|
512
|
+
}
|
|
513
|
+
if (eventType === "event") return inboundNeedsAckFromEventShape(event);
|
|
514
|
+
return false;
|
|
515
|
+
}
|
|
516
|
+
function inboundNeedsAckFromEventShape(event) {
|
|
517
|
+
const mode = String(event.mode ?? "");
|
|
518
|
+
const data = event.data;
|
|
519
|
+
if (mode === "custom" && isTurnEndCustomData(data)) return true;
|
|
520
|
+
if (mode === "messages" && Array.isArray(data) && data.length > 0) {
|
|
521
|
+
const body = data[0];
|
|
522
|
+
if (!body || typeof body !== "object") return false;
|
|
523
|
+
const t = String(body.type ?? "");
|
|
524
|
+
return t === STREAM_END || t.includes("stream.end");
|
|
525
|
+
}
|
|
526
|
+
return false;
|
|
527
|
+
}
|
|
528
|
+
function extractLoopIdFromInbound(event) {
|
|
529
|
+
const direct = String(event.loop_id ?? "").trim();
|
|
530
|
+
if (direct) return direct;
|
|
531
|
+
if (String(event.type ?? "") !== "next") return "";
|
|
532
|
+
const payload = event.payload;
|
|
533
|
+
if (!payload || typeof payload !== "object") return "";
|
|
534
|
+
const p = payload;
|
|
535
|
+
const fromPayload = String(p.loop_id ?? "").trim();
|
|
536
|
+
if (fromPayload) return fromPayload;
|
|
537
|
+
const inner = p.data;
|
|
538
|
+
if (inner && typeof inner === "object") {
|
|
539
|
+
return String(inner.loop_id ?? "").trim();
|
|
540
|
+
}
|
|
541
|
+
return "";
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// src/inbound_priority.ts
|
|
545
|
+
var DROP_PRIORITY_CRITICAL = 0;
|
|
546
|
+
var DROP_PRIORITY_HIGH = 1;
|
|
547
|
+
var DROP_PRIORITY_NORMAL = 2;
|
|
548
|
+
var DEFAULT_INBOUND_MAX_SIZE = 2e4;
|
|
549
|
+
function inboundFrameDropPriority(event) {
|
|
550
|
+
if (!event) return DROP_PRIORITY_CRITICAL;
|
|
551
|
+
let eventType = String(event.type ?? "");
|
|
552
|
+
if (eventType === "event_batch" || eventType === "tool_call_updates_batch") {
|
|
553
|
+
return DROP_PRIORITY_HIGH;
|
|
554
|
+
}
|
|
555
|
+
if (eventType === "next") {
|
|
556
|
+
const payload = event.payload;
|
|
557
|
+
if (payload && typeof payload === "object") {
|
|
558
|
+
const p = payload;
|
|
559
|
+
const innerMode = String(p.mode ?? "");
|
|
560
|
+
const innerData = p.data;
|
|
561
|
+
if (innerMode === "messages") {
|
|
562
|
+
if (messagesWireTerminal(innerData)) return DROP_PRIORITY_CRITICAL;
|
|
563
|
+
if (Array.isArray(innerData) && innerData[0] && typeof innerData[0] === "object") {
|
|
564
|
+
if (String(innerData[0].phase ?? "") === "goal_completion") {
|
|
565
|
+
return DROP_PRIORITY_CRITICAL;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
if (String(p.type ?? "") === "complete") return DROP_PRIORITY_CRITICAL;
|
|
570
|
+
if (innerData && typeof innerData === "object") {
|
|
571
|
+
return inboundFrameDropPriority(innerData);
|
|
572
|
+
}
|
|
573
|
+
eventType = String(p.type ?? "");
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
if (eventType === "complete" || eventType === "error" || eventType === "connection_ack") {
|
|
577
|
+
return DROP_PRIORITY_CRITICAL;
|
|
578
|
+
}
|
|
579
|
+
if (eventType === "status") {
|
|
580
|
+
const state = String(event.state ?? "");
|
|
581
|
+
if (["idle", "running", "stopped", "detached"].includes(state)) {
|
|
582
|
+
return DROP_PRIORITY_CRITICAL;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
if (eventType === "event") {
|
|
586
|
+
const mode = String(event.mode ?? "");
|
|
587
|
+
const data = event.data;
|
|
588
|
+
if (mode === "custom") {
|
|
589
|
+
if (isTurnEndCustomData(data)) return DROP_PRIORITY_CRITICAL;
|
|
590
|
+
if (data && typeof data === "object") {
|
|
591
|
+
const customType = String(data.type ?? "");
|
|
592
|
+
if (customType.startsWith("soothe.cognition.")) return DROP_PRIORITY_HIGH;
|
|
593
|
+
if (customType.startsWith("soothe.error.") || customType === "stream_degraded") {
|
|
594
|
+
return DROP_PRIORITY_CRITICAL;
|
|
595
|
+
}
|
|
596
|
+
if (customType === "soothe.ux.stream_tool_wire.tool_call_updates_batch") {
|
|
597
|
+
return DROP_PRIORITY_HIGH;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
if (mode === "messages") {
|
|
602
|
+
if (messagesWireTerminal(data)) return DROP_PRIORITY_CRITICAL;
|
|
603
|
+
if (Array.isArray(data) && data[0] && typeof data[0] === "object") {
|
|
604
|
+
if (String(data[0].phase ?? "") === "goal_completion") {
|
|
605
|
+
return DROP_PRIORITY_CRITICAL;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
return DROP_PRIORITY_NORMAL;
|
|
611
|
+
}
|
|
612
|
+
function messagesWireTerminal(data) {
|
|
613
|
+
if (!Array.isArray(data) || data.length === 0) return false;
|
|
614
|
+
const body = data[0];
|
|
615
|
+
if (!body || typeof body !== "object") return false;
|
|
616
|
+
const t = String(body.type ?? "");
|
|
617
|
+
return t === STREAM_END || t.includes("stream.end");
|
|
618
|
+
}
|
|
619
|
+
|
|
296
620
|
// src/protocol.ts
|
|
297
621
|
import { randomUUID } from "crypto";
|
|
298
622
|
var PROTO_VERSION = "1";
|
|
299
623
|
var DEFAULT_CLIENT_CAPABILITIES = ["streaming", "batch", "heartbeat", "receipts"];
|
|
300
|
-
var CLIENT_VERSION = "0.1
|
|
624
|
+
var CLIENT_VERSION = "0.4.1";
|
|
301
625
|
function encodeMessage(msg) {
|
|
302
626
|
return JSON.stringify(msg) + "\n";
|
|
303
627
|
}
|
|
@@ -465,8 +789,11 @@ var Client = class extends EventEmitter {
|
|
|
465
789
|
config;
|
|
466
790
|
ws = null;
|
|
467
791
|
messageBuffer = [];
|
|
792
|
+
inboundMaxSize = DEFAULT_INBOUND_MAX_SIZE;
|
|
793
|
+
inboundDroppedCount = 0;
|
|
794
|
+
onStreamDegraded = null;
|
|
468
795
|
resolvers = [];
|
|
469
|
-
// Protocol-1 handshake state
|
|
796
|
+
// Protocol-1 handshake state
|
|
470
797
|
handshakeComplete = false;
|
|
471
798
|
negotiatedCapabilities = /* @__PURE__ */ new Set();
|
|
472
799
|
protocolVersion = null;
|
|
@@ -474,14 +801,16 @@ var Client = class extends EventEmitter {
|
|
|
474
801
|
heartbeatIntervalMs = 0;
|
|
475
802
|
heartbeatTimer = null;
|
|
476
803
|
lastPongMonotonic = 0;
|
|
477
|
-
// Mid-session drop signal
|
|
804
|
+
// Mid-session drop signal. The 'disconnected' event is
|
|
478
805
|
// emitted exactly once when the connection drops, carrying a DisconnectCause
|
|
479
806
|
// that distinguishes clean (peer `disconnect`) from unclean (read/write
|
|
480
807
|
// error or missed pong). `disconnFired` guards the once-only delivery.
|
|
481
808
|
disconnFired = false;
|
|
482
|
-
// Pending-request/subscription multiplexer
|
|
809
|
+
// Pending-request/subscription multiplexer. Routes
|
|
483
810
|
// inbound frames by (type, id) instead of discarding non-matching events.
|
|
484
811
|
mux = new Multiplexer();
|
|
812
|
+
deliveryRecvSeq = /* @__PURE__ */ new Map();
|
|
813
|
+
deliveryAckedSeq = /* @__PURE__ */ new Map();
|
|
485
814
|
constructor(url, config) {
|
|
486
815
|
super();
|
|
487
816
|
this.url = url;
|
|
@@ -549,13 +878,15 @@ var Client = class extends EventEmitter {
|
|
|
549
878
|
this._signalDisconnect(1 /* Clean */);
|
|
550
879
|
}
|
|
551
880
|
if (this.mux.route(m)) {
|
|
881
|
+
this._trackInboundDeliveryAck(m);
|
|
552
882
|
continue;
|
|
553
883
|
}
|
|
884
|
+
this._trackInboundDeliveryAck(m);
|
|
554
885
|
const resolver = this.resolvers.shift();
|
|
555
886
|
if (resolver) {
|
|
556
887
|
resolver(msg);
|
|
557
888
|
} else {
|
|
558
|
-
this.
|
|
889
|
+
this.enqueueMessageBuffer(msg);
|
|
559
890
|
}
|
|
560
891
|
this.emit("message", msg);
|
|
561
892
|
}
|
|
@@ -592,7 +923,7 @@ var Client = class extends EventEmitter {
|
|
|
592
923
|
return this.ws !== null && this.ws.readyState === WebSocket.OPEN && this.handshakeComplete;
|
|
593
924
|
}
|
|
594
925
|
// ---------------------------------------------------------------------------
|
|
595
|
-
// Mid-session drop signal + reconnect/reattach
|
|
926
|
+
// Mid-session drop signal + reconnect/reattach
|
|
596
927
|
// ---------------------------------------------------------------------------
|
|
597
928
|
/**
|
|
598
929
|
* Returns whether the connection has dropped (the `'disconnected'` event has
|
|
@@ -627,8 +958,8 @@ var Client = class extends EventEmitter {
|
|
|
627
958
|
}
|
|
628
959
|
}
|
|
629
960
|
/**
|
|
630
|
-
* Re-dials the daemon and re-handshakes after a connection drop
|
|
631
|
-
*
|
|
961
|
+
* Re-dials the daemon and re-handshakes after a connection drop.
|
|
962
|
+
* Does not re-establish loop subscriptions; follow with
|
|
632
963
|
* `reattachAndProbe()` to resume a loop session. The caller should invoke
|
|
633
964
|
* this after the `'disconnected'` event fires. Reuses the same Client,
|
|
634
965
|
* resetting the drop signal and multiplexer.
|
|
@@ -662,7 +993,7 @@ var Client = class extends EventEmitter {
|
|
|
662
993
|
* Returns a `StaleLoopError` when the probe fails; callers should fall back
|
|
663
994
|
* to a fresh `loop_new` bootstrap.
|
|
664
995
|
*
|
|
665
|
-
*
|
|
996
|
+
* Note: connection-level readiness is the handshake's readiness_state
|
|
666
997
|
* (+ daemon_status); loop_get is a loop-scoped probe only, not a readiness
|
|
667
998
|
* probe.
|
|
668
999
|
*/
|
|
@@ -703,7 +1034,7 @@ var Client = class extends EventEmitter {
|
|
|
703
1034
|
}
|
|
704
1035
|
}
|
|
705
1036
|
// ---------------------------------------------------------------------------
|
|
706
|
-
// Protocol-1 handshake
|
|
1037
|
+
// Protocol-1 handshake
|
|
707
1038
|
// ---------------------------------------------------------------------------
|
|
708
1039
|
/** Send connection_init and wait for connection_ack with readiness "ready". */
|
|
709
1040
|
async _performHandshake() {
|
|
@@ -752,7 +1083,7 @@ var Client = class extends EventEmitter {
|
|
|
752
1083
|
throw new Error(`timeout after ${this.config.daemonReadyTimeout}ms waiting for connection_ack`);
|
|
753
1084
|
}
|
|
754
1085
|
// ---------------------------------------------------------------------------
|
|
755
|
-
// Heartbeat
|
|
1086
|
+
// Heartbeat
|
|
756
1087
|
// ---------------------------------------------------------------------------
|
|
757
1088
|
_startHeartbeat() {
|
|
758
1089
|
if (!this.negotiatedCapabilities.has("heartbeat")) return;
|
|
@@ -868,8 +1199,86 @@ var Client = class extends EventEmitter {
|
|
|
868
1199
|
this.resolvers.push(resolver);
|
|
869
1200
|
});
|
|
870
1201
|
}
|
|
1202
|
+
/**
|
|
1203
|
+
* Remove stale handshake/terminal frames left in `messageBuffer` before a turn.
|
|
1204
|
+
* Returns labels of removed frames (in order).
|
|
1205
|
+
*/
|
|
1206
|
+
peelStalePendingControlEvents() {
|
|
1207
|
+
if (this.messageBuffer.length === 0) return [];
|
|
1208
|
+
const kept = [];
|
|
1209
|
+
const removed = [];
|
|
1210
|
+
while (this.messageBuffer.length > 0) {
|
|
1211
|
+
const event = this.messageBuffer.shift();
|
|
1212
|
+
const label = stalePendingFrameLabel(event);
|
|
1213
|
+
if (label !== null) {
|
|
1214
|
+
removed.push(label);
|
|
1215
|
+
continue;
|
|
1216
|
+
}
|
|
1217
|
+
kept.push(event);
|
|
1218
|
+
}
|
|
1219
|
+
this.messageBuffer = kept;
|
|
1220
|
+
return removed;
|
|
1221
|
+
}
|
|
1222
|
+
/** True when the underlying socket is still open (may not be handshaked). */
|
|
1223
|
+
isConnectionAlive() {
|
|
1224
|
+
return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
|
|
1225
|
+
}
|
|
1226
|
+
/** Override pending buffer cap (tests / tuning). */
|
|
1227
|
+
setInboundMaxSize(n) {
|
|
1228
|
+
if (n > 0) this.inboundMaxSize = n;
|
|
1229
|
+
}
|
|
1230
|
+
/** How many NORMAL-priority frames were dropped under backpressure. */
|
|
1231
|
+
inboundDropped() {
|
|
1232
|
+
return this.inboundDroppedCount;
|
|
1233
|
+
}
|
|
1234
|
+
/** Hook invoked on the first inbound overflow drop. */
|
|
1235
|
+
setStreamDegradedCallback(fn) {
|
|
1236
|
+
this.onStreamDegraded = fn;
|
|
1237
|
+
}
|
|
1238
|
+
enqueueMessageBuffer(msg) {
|
|
1239
|
+
const max = this.inboundMaxSize > 0 ? this.inboundMaxSize : DEFAULT_INBOUND_MAX_SIZE;
|
|
1240
|
+
if (this.messageBuffer.length < max) {
|
|
1241
|
+
this.messageBuffer.push(msg);
|
|
1242
|
+
return;
|
|
1243
|
+
}
|
|
1244
|
+
const ev = msg;
|
|
1245
|
+
let dropIdx = -1;
|
|
1246
|
+
let dropPri = -1;
|
|
1247
|
+
for (let i = 0; i < this.messageBuffer.length; i++) {
|
|
1248
|
+
const p = inboundFrameDropPriority(this.messageBuffer[i]);
|
|
1249
|
+
if (p > dropPri) {
|
|
1250
|
+
dropPri = p;
|
|
1251
|
+
dropIdx = i;
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
const incomingPri = inboundFrameDropPriority(ev);
|
|
1255
|
+
if (dropIdx >= 0 && dropPri >= DROP_PRIORITY_NORMAL) {
|
|
1256
|
+
this.messageBuffer.splice(dropIdx, 1);
|
|
1257
|
+
this.messageBuffer.push(msg);
|
|
1258
|
+
this.noteInboundDrop();
|
|
1259
|
+
return;
|
|
1260
|
+
}
|
|
1261
|
+
if (incomingPri >= DROP_PRIORITY_NORMAL) {
|
|
1262
|
+
this.noteInboundDrop();
|
|
1263
|
+
return;
|
|
1264
|
+
}
|
|
1265
|
+
if (this.messageBuffer.length > 0) {
|
|
1266
|
+
this.messageBuffer.shift();
|
|
1267
|
+
this.noteInboundDrop();
|
|
1268
|
+
}
|
|
1269
|
+
this.messageBuffer.push(msg);
|
|
1270
|
+
}
|
|
1271
|
+
noteInboundDrop() {
|
|
1272
|
+
this.inboundDroppedCount += 1;
|
|
1273
|
+
if (this.onStreamDegraded && this.inboundDroppedCount === 1) {
|
|
1274
|
+
try {
|
|
1275
|
+
this.onStreamDegraded(1, "inbound_queue_overflow");
|
|
1276
|
+
} catch {
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
871
1280
|
// ---------------------------------------------------------------------------
|
|
872
|
-
// Protocol-1 RPC primitives
|
|
1281
|
+
// Protocol-1 RPC primitives
|
|
873
1282
|
// ---------------------------------------------------------------------------
|
|
874
1283
|
/**
|
|
875
1284
|
* Reads the next frame directly from the live socket (via a resolver),
|
|
@@ -895,16 +1304,16 @@ var Client = class extends EventEmitter {
|
|
|
895
1304
|
});
|
|
896
1305
|
}
|
|
897
1306
|
/**
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
1307
|
+
* Sends a `request` envelope and waits for the matching `response` (or
|
|
1308
|
+
* `error`) correlated by `id`. Returns the `result` object.
|
|
1309
|
+
*
|
|
1310
|
+
* Multiplexer-aware: registers a pending RPC wait
|
|
1311
|
+
* keyed by the request id so that, even when a `receiveMessages()` reader
|
|
1312
|
+
* is concurrently active, the matching `response`/`error` is routed to
|
|
1313
|
+
* this caller instead of being discarded or buffered behind a stream.
|
|
1314
|
+
* Non-matching frames are routed to their own waiters by the multiplexer
|
|
1315
|
+
* or flow on to the resolver queue for stream readers.
|
|
1316
|
+
*/
|
|
908
1317
|
async requestResponse(method, params, responseType, timeout = 15e3) {
|
|
909
1318
|
const req = requestEnvelope(method, params);
|
|
910
1319
|
const rid = req.id;
|
|
@@ -972,6 +1381,35 @@ var Client = class extends EventEmitter {
|
|
|
972
1381
|
notify(method, params) {
|
|
973
1382
|
return this.sendMessage(notificationEnvelope(method, params));
|
|
974
1383
|
}
|
|
1384
|
+
_trackInboundDeliveryAck(event) {
|
|
1385
|
+
if (String(event.type ?? "") === "event_batch") {
|
|
1386
|
+
const events = event.events;
|
|
1387
|
+
if (Array.isArray(events)) {
|
|
1388
|
+
for (const sub of events) {
|
|
1389
|
+
if (sub && typeof sub === "object") {
|
|
1390
|
+
this._trackInboundDeliveryAck(sub);
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
return;
|
|
1395
|
+
}
|
|
1396
|
+
if (!inboundNeedsDeliveryAck(event)) return;
|
|
1397
|
+
const loopId = extractLoopIdFromInbound(event);
|
|
1398
|
+
if (!loopId) return;
|
|
1399
|
+
const next = (this.deliveryRecvSeq.get(loopId) ?? 0) + 1;
|
|
1400
|
+
this.deliveryRecvSeq.set(loopId, next);
|
|
1401
|
+
void this._sendDeliveryAck(loopId, next);
|
|
1402
|
+
}
|
|
1403
|
+
async _sendDeliveryAck(loopId, seq) {
|
|
1404
|
+
const acked = this.deliveryAckedSeq.get(loopId) ?? 0;
|
|
1405
|
+
if (seq <= acked) return;
|
|
1406
|
+
this.deliveryAckedSeq.set(loopId, seq);
|
|
1407
|
+
if (!this.isConnected()) return;
|
|
1408
|
+
try {
|
|
1409
|
+
await this.notify("delivery_ack", { loop_id: loopId, seq });
|
|
1410
|
+
} catch {
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
975
1413
|
/**
|
|
976
1414
|
* Starts a subscription stream. Returns the subscription `id` for later
|
|
977
1415
|
* correlation and `unsubscribe()`. Stream events arrive as `next` frames
|
|
@@ -989,7 +1427,7 @@ var Client = class extends EventEmitter {
|
|
|
989
1427
|
if (ev === null) break;
|
|
990
1428
|
const evId = ev.id;
|
|
991
1429
|
if (evId !== subId) {
|
|
992
|
-
this.
|
|
1430
|
+
this.enqueueMessageBuffer(ev);
|
|
993
1431
|
continue;
|
|
994
1432
|
}
|
|
995
1433
|
const typ = ev.type;
|
|
@@ -1026,7 +1464,7 @@ var Client = class extends EventEmitter {
|
|
|
1026
1464
|
return ev;
|
|
1027
1465
|
}
|
|
1028
1466
|
// ---------------------------------------------------------------------------
|
|
1029
|
-
// High-level API methods
|
|
1467
|
+
// High-level API methods
|
|
1030
1468
|
// ---------------------------------------------------------------------------
|
|
1031
1469
|
/** Sends user input to the daemon (loop_input notification; requires loopID). */
|
|
1032
1470
|
sendInput(text, options) {
|
|
@@ -1065,7 +1503,7 @@ var Client = class extends EventEmitter {
|
|
|
1065
1503
|
return this.notify("slash_command", { cmd });
|
|
1066
1504
|
}
|
|
1067
1505
|
// ---------------------------------------------------------------------------
|
|
1068
|
-
// Loop lifecycle methods
|
|
1506
|
+
// Loop lifecycle methods
|
|
1069
1507
|
// ---------------------------------------------------------------------------
|
|
1070
1508
|
/** Requests the daemon to create a new StrangeLoop and waits for the response. */
|
|
1071
1509
|
sendLoopNew(opts) {
|
|
@@ -1160,7 +1598,7 @@ var Client = class extends EventEmitter {
|
|
|
1160
1598
|
sendLoopCardsFetch(loopID) {
|
|
1161
1599
|
return this.sendMessage(requestEnvelope("loop_cards_fetch", { loop_id: loopID }));
|
|
1162
1600
|
}
|
|
1163
|
-
/** Requests the full loop history
|
|
1601
|
+
/** Requests the full loop history. */
|
|
1164
1602
|
sendLoopHistoryFetch(loopID) {
|
|
1165
1603
|
return this.sendMessage(requestEnvelope("loop_history_fetch", { loop_id: loopID }));
|
|
1166
1604
|
}
|
|
@@ -1255,7 +1693,7 @@ var Client = class extends EventEmitter {
|
|
|
1255
1693
|
);
|
|
1256
1694
|
}
|
|
1257
1695
|
// ---------------------------------------------------------------------------
|
|
1258
|
-
//
|
|
1696
|
+
// Job IPC methods
|
|
1259
1697
|
// ---------------------------------------------------------------------------
|
|
1260
1698
|
/** Creates an autopilot job and waits for the response. */
|
|
1261
1699
|
createJob(goal, verificationRules, workspace, timeout) {
|
|
@@ -1290,6 +1728,98 @@ var Client = class extends EventEmitter {
|
|
|
1290
1728
|
if (goalId) params.goal_id = goalId;
|
|
1291
1729
|
return this.requestResponse("job_guidance", params, "job_guidance", timeout ?? 3e4);
|
|
1292
1730
|
}
|
|
1731
|
+
// ---------------------------------------------------------------------------
|
|
1732
|
+
// Autopilot goal RPCs (protocol-1 request methods)
|
|
1733
|
+
// ---------------------------------------------------------------------------
|
|
1734
|
+
/** Return autopilot scheduler status (running / dreaming / pool). */
|
|
1735
|
+
autopilotStatus(timeout) {
|
|
1736
|
+
return this.requestResponse("autopilot_status", {}, "autopilot_status", timeout ?? 15e3);
|
|
1737
|
+
}
|
|
1738
|
+
/** Submit a new autopilot goal (returns goal_id). */
|
|
1739
|
+
autopilotSubmit(description, opts) {
|
|
1740
|
+
const params = {
|
|
1741
|
+
description,
|
|
1742
|
+
priority: opts?.priority ?? 50
|
|
1743
|
+
};
|
|
1744
|
+
if (opts?.workspace) params.workspace = opts.workspace;
|
|
1745
|
+
return this.requestResponse(
|
|
1746
|
+
"autopilot_submit",
|
|
1747
|
+
params,
|
|
1748
|
+
"autopilot_submit",
|
|
1749
|
+
opts?.timeout ?? 15e3
|
|
1750
|
+
);
|
|
1751
|
+
}
|
|
1752
|
+
/** List all goals (including non-root children). */
|
|
1753
|
+
autopilotListGoals(timeout) {
|
|
1754
|
+
return this.requestResponse(
|
|
1755
|
+
"autopilot_list_goals",
|
|
1756
|
+
{},
|
|
1757
|
+
"autopilot_list_goals",
|
|
1758
|
+
timeout ?? 15e3
|
|
1759
|
+
);
|
|
1760
|
+
}
|
|
1761
|
+
/** Fetch one goal by id. */
|
|
1762
|
+
autopilotGetGoal(goalId, timeout) {
|
|
1763
|
+
return this.requestResponse(
|
|
1764
|
+
"autopilot_get_goal",
|
|
1765
|
+
{ goal_id: goalId },
|
|
1766
|
+
"autopilot_get_goal",
|
|
1767
|
+
timeout ?? 15e3
|
|
1768
|
+
);
|
|
1769
|
+
}
|
|
1770
|
+
/** Cancel a goal and its non-terminal descendants. */
|
|
1771
|
+
autopilotCancelGoal(goalId, timeout) {
|
|
1772
|
+
return this.requestResponse(
|
|
1773
|
+
"autopilot_cancel_goal",
|
|
1774
|
+
{ goal_id: goalId },
|
|
1775
|
+
"autopilot_cancel_goal",
|
|
1776
|
+
timeout ?? 15e3
|
|
1777
|
+
);
|
|
1778
|
+
}
|
|
1779
|
+
/** Cancel every open (non-terminal) goal. */
|
|
1780
|
+
autopilotCancelAll(timeout) {
|
|
1781
|
+
return this.requestResponse(
|
|
1782
|
+
"autopilot_cancel_all",
|
|
1783
|
+
{},
|
|
1784
|
+
"autopilot_cancel_all",
|
|
1785
|
+
timeout ?? 15e3
|
|
1786
|
+
);
|
|
1787
|
+
}
|
|
1788
|
+
/** Exit dreaming mode and resume scheduling. */
|
|
1789
|
+
autopilotWake(timeout) {
|
|
1790
|
+
return this.requestResponse("autopilot_wake", {}, "autopilot_wake", timeout ?? 15e3);
|
|
1791
|
+
}
|
|
1792
|
+
/** Force dreaming mode. */
|
|
1793
|
+
autopilotDream(timeout) {
|
|
1794
|
+
return this.requestResponse("autopilot_dream", {}, "autopilot_dream", timeout ?? 15e3);
|
|
1795
|
+
}
|
|
1796
|
+
/** Resume a suspended or blocked goal. */
|
|
1797
|
+
autopilotResume(goalId, timeout) {
|
|
1798
|
+
return this.requestResponse(
|
|
1799
|
+
"autopilot_resume",
|
|
1800
|
+
{ goal_id: goalId },
|
|
1801
|
+
"autopilot_resume",
|
|
1802
|
+
timeout ?? 15e3
|
|
1803
|
+
);
|
|
1804
|
+
}
|
|
1805
|
+
/** List root goals only (jobs). Prefer createJob / getJobStatus for job control. */
|
|
1806
|
+
autopilotListJobs(timeout) {
|
|
1807
|
+
return this.requestResponse(
|
|
1808
|
+
"autopilot_list_jobs",
|
|
1809
|
+
{},
|
|
1810
|
+
"autopilot_list_jobs",
|
|
1811
|
+
timeout ?? 15e3
|
|
1812
|
+
);
|
|
1813
|
+
}
|
|
1814
|
+
/** Get a root job with DAG snapshot. Prefer getJobStatus / getJobDag. */
|
|
1815
|
+
autopilotGetJob(jobId, timeout) {
|
|
1816
|
+
return this.requestResponse(
|
|
1817
|
+
"autopilot_get_job",
|
|
1818
|
+
{ job_id: jobId },
|
|
1819
|
+
"autopilot_get_job",
|
|
1820
|
+
timeout ?? 15e3
|
|
1821
|
+
);
|
|
1822
|
+
}
|
|
1293
1823
|
/** Subscribes to autopilot worker events. */
|
|
1294
1824
|
autopilotSubscribe(timeout) {
|
|
1295
1825
|
return this.subscribe("autopilot_events", {}, timeout ?? 15e3);
|
|
@@ -1300,7 +1830,7 @@ var Client = class extends EventEmitter {
|
|
|
1300
1830
|
return this._requestResponseForEnvelope(req, "autopilot_unsubscribe", timeout ?? 15e3);
|
|
1301
1831
|
}
|
|
1302
1832
|
// ---------------------------------------------------------------------------
|
|
1303
|
-
//
|
|
1833
|
+
// Cron IPC methods
|
|
1304
1834
|
// ---------------------------------------------------------------------------
|
|
1305
1835
|
/** Creates a scheduled job from natural language. */
|
|
1306
1836
|
cronAdd(text, priority, timeout) {
|
|
@@ -1364,6 +1894,9 @@ export {
|
|
|
1364
1894
|
disconnectCauseName,
|
|
1365
1895
|
ReconnectError,
|
|
1366
1896
|
StaleLoopError,
|
|
1897
|
+
VerbosityTier,
|
|
1898
|
+
shouldShow,
|
|
1899
|
+
isValidVerbosityLevel,
|
|
1367
1900
|
defaultConfig,
|
|
1368
1901
|
loadConfigFromEnv,
|
|
1369
1902
|
PROTO_VERSION,
|
|
@@ -1393,7 +1926,50 @@ export {
|
|
|
1393
1926
|
validateLoopInputIntentHint,
|
|
1394
1927
|
LOOP_ASSISTANT_OUTPUT_PHASES,
|
|
1395
1928
|
DEFAULT_DELIVERABLE_PHASES,
|
|
1396
|
-
|
|
1929
|
+
EventPlanCreated,
|
|
1930
|
+
EventExploreStarted,
|
|
1931
|
+
EventExploreMilestone,
|
|
1932
|
+
EventExploreStepCompleted,
|
|
1933
|
+
EventExploreCompleted,
|
|
1934
|
+
EventTacitusStarted,
|
|
1935
|
+
EventTacitusGatherSummary,
|
|
1936
|
+
EventTacitusCompleted,
|
|
1937
|
+
EventReplayComplete,
|
|
1938
|
+
EventLoopReattachedWire,
|
|
1939
|
+
EventCardReplayBegin,
|
|
1940
|
+
EventCardCreated,
|
|
1941
|
+
EventCardReplayEnd,
|
|
1942
|
+
EventToolStarted,
|
|
1943
|
+
EventToolCompleted,
|
|
1944
|
+
EventToolError,
|
|
1945
|
+
EventStreamToolCallUpdate,
|
|
1946
|
+
EventToolCallUpdatesBatch,
|
|
1947
|
+
EventStrangeLoopStarted,
|
|
1948
|
+
EventStrangeLoopCompleted,
|
|
1949
|
+
EventStrangeLoopPlanDecision,
|
|
1950
|
+
EventStrangeLoopReasoned,
|
|
1951
|
+
EventStrangeLoopStepStarted,
|
|
1952
|
+
EventStrangeLoopStepQueued,
|
|
1953
|
+
EventStrangeLoopStepCompleted,
|
|
1954
|
+
EventStrangeLoopContextCompacted,
|
|
1955
|
+
EventMessageReceived,
|
|
1956
|
+
EventMessageSent,
|
|
1957
|
+
EventFinalReport,
|
|
1958
|
+
EventAutopilotGoalStatus,
|
|
1959
|
+
EventAutopilotGoalProgress,
|
|
1960
|
+
EventAutopilotGoalCreated,
|
|
1961
|
+
EventAutopilotGoalCompleted,
|
|
1962
|
+
EventAutopilotWorkerAssigned,
|
|
1963
|
+
EventAutopilotWorkerUnassigned,
|
|
1964
|
+
EventGeneralFailed,
|
|
1965
|
+
parseNamespace,
|
|
1966
|
+
classifyEventVerbosity,
|
|
1967
|
+
isCompletionEvent,
|
|
1968
|
+
isSubagentProgressEvent,
|
|
1969
|
+
STREAM_END,
|
|
1970
|
+
isTurnEndCustomData,
|
|
1971
|
+
isTurnProgressChunk,
|
|
1972
|
+
inboundNeedsDeliveryAck,
|
|
1397
1973
|
Client
|
|
1398
1974
|
};
|
|
1399
|
-
//# sourceMappingURL=chunk-
|
|
1975
|
+
//# sourceMappingURL=chunk-YYUVHZ3W.js.map
|