@mirasoth/soothe-client 0.5.0 → 0.5.2
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/{chunk-A6WGUBQE.js → chunk-NSWLUFSA.js} +8 -7
- package/dist/chunk-NSWLUFSA.js.map +1 -0
- package/dist/client-YTWVWNAN.js +7 -0
- package/dist/index.cjs +151 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -21
- package/dist/index.d.ts +45 -21
- package/dist/index.js +138 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-A6WGUBQE.js.map +0 -1
- package/dist/client-UEBVV6HI.js +0 -7
- /package/dist/{client-UEBVV6HI.js.map → client-YTWVWNAN.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -357,14 +357,14 @@ var init_protocol = __esm({
|
|
|
357
357
|
import_node_crypto = require("crypto");
|
|
358
358
|
PROTO_VERSION = "1";
|
|
359
359
|
DEFAULT_CLIENT_CAPABILITIES = ["streaming", "batch", "heartbeat", "receipts"];
|
|
360
|
-
CLIENT_VERSION = "0.5.
|
|
360
|
+
CLIENT_VERSION = "0.5.2";
|
|
361
361
|
}
|
|
362
362
|
});
|
|
363
363
|
|
|
364
364
|
// src/intent_hints.ts
|
|
365
365
|
function validateLoopInputIntentHint(hint) {
|
|
366
366
|
const key = hint.trim().toLowerCase();
|
|
367
|
-
if (key
|
|
367
|
+
if (key in REMOVED_INTENT_HINT_MESSAGES) {
|
|
368
368
|
return REMOVED_INTENT_HINT_MESSAGES[key];
|
|
369
369
|
}
|
|
370
370
|
return null;
|
|
@@ -377,16 +377,17 @@ var init_intent_hints = __esm({
|
|
|
377
377
|
INTENT_HINT_IMAGE_TO_TEXT = "image_to_text";
|
|
378
378
|
INTENT_HINT_OCR = "ocr";
|
|
379
379
|
INTENT_HINT_EMBED = "embed";
|
|
380
|
-
REMOVED_INTENT_HINTS = ["direct_llm", "quiz"];
|
|
380
|
+
REMOVED_INTENT_HINTS = ["direct_llm", "quiz", "direct_model"];
|
|
381
381
|
REMOVED_INTENT_HINT_MESSAGES = {
|
|
382
382
|
direct_llm: "intent_hint direct_llm is removed; use text_completion (text-only) or image_to_text (with attachments)",
|
|
383
|
-
quiz: "intent_hint quiz is removed; omit intent_hint and let intake classify the turn"
|
|
383
|
+
quiz: "intent_hint quiz is removed; omit intent_hint and let intake classify the turn",
|
|
384
|
+
direct_model: "intent_hint direct_model is removed; use text_completion, image_to_text, ocr, or embed"
|
|
384
385
|
};
|
|
385
386
|
LOOP_ASSISTANT_OUTPUT_PHASES = [
|
|
386
387
|
"goal_completion",
|
|
387
388
|
"quiz",
|
|
388
389
|
"autonomous_goal",
|
|
389
|
-
"
|
|
390
|
+
"chitchat",
|
|
390
391
|
"text_completion",
|
|
391
392
|
"image_to_text",
|
|
392
393
|
"ocr",
|
|
@@ -396,7 +397,7 @@ var init_intent_hints = __esm({
|
|
|
396
397
|
DEFAULT_DELIVERABLE_PHASES = /* @__PURE__ */ new Set([
|
|
397
398
|
"quiz",
|
|
398
399
|
"goal_completion",
|
|
399
|
-
"
|
|
400
|
+
"chitchat",
|
|
400
401
|
"text_completion",
|
|
401
402
|
"image_to_text",
|
|
402
403
|
"ocr",
|
|
@@ -2068,9 +2069,14 @@ __export(index_exports, {
|
|
|
2068
2069
|
StaleLoopError: () => StaleLoopError,
|
|
2069
2070
|
StreamCloseFail: () => StreamCloseFail,
|
|
2070
2071
|
StreamCloseSoftComplete: () => StreamCloseSoftComplete,
|
|
2072
|
+
TURN_END_IDLE: () => TURN_END_IDLE,
|
|
2073
|
+
TURN_END_STOPPED: () => TURN_END_STOPPED,
|
|
2074
|
+
TURN_END_STREAM_END: () => TURN_END_STREAM_END,
|
|
2071
2075
|
TimeoutError: () => TimeoutError,
|
|
2072
2076
|
TimeoutPolicy: () => TimeoutPolicy,
|
|
2077
|
+
TurnBoundary: () => TurnBoundary,
|
|
2073
2078
|
TurnEventStats: () => TurnEventStats,
|
|
2079
|
+
TurnLifecycleGate: () => TurnLifecycleGate,
|
|
2074
2080
|
TurnRunner: () => TurnRunner,
|
|
2075
2081
|
VerbosityTier: () => VerbosityTier,
|
|
2076
2082
|
authenticate: () => authenticate,
|
|
@@ -2100,6 +2106,7 @@ __export(index_exports, {
|
|
|
2100
2106
|
inputMessageForLoop: () => inputMessageForLoop,
|
|
2101
2107
|
isCompletionEvent: () => isCompletionEvent,
|
|
2102
2108
|
isDaemonLive: () => isDaemonLive,
|
|
2109
|
+
isDaemonTurnEndEvent: () => isDaemonTurnEndEvent,
|
|
2103
2110
|
isSubagentProgressEvent: () => isSubagentProgressEvent,
|
|
2104
2111
|
isTurnEndCustomData: () => isTurnEndCustomData,
|
|
2105
2112
|
isTurnProgressChunk: () => isTurnProgressChunk,
|
|
@@ -2742,6 +2749,8 @@ var EventClassifier = class {
|
|
|
2742
2749
|
if (!eventType) return false;
|
|
2743
2750
|
switch (eventType) {
|
|
2744
2751
|
case "status.idle":
|
|
2752
|
+
case "status.stopped":
|
|
2753
|
+
case "soothe.stream.end":
|
|
2745
2754
|
case "idle_timeout":
|
|
2746
2755
|
case "query_timeout":
|
|
2747
2756
|
case "stream_closed":
|
|
@@ -2935,9 +2944,9 @@ var EventClassifier = class {
|
|
|
2935
2944
|
return this.continueResult(content);
|
|
2936
2945
|
}
|
|
2937
2946
|
}
|
|
2938
|
-
const [
|
|
2939
|
-
if (
|
|
2940
|
-
return this.
|
|
2947
|
+
const [unphasedContent, unphasedOk] = this.messagesModeAssistantContent(data);
|
|
2948
|
+
if (unphasedOk) {
|
|
2949
|
+
return this.continueResult(unphasedContent);
|
|
2941
2950
|
}
|
|
2942
2951
|
if (hasPayload && rawContent) {
|
|
2943
2952
|
if (isTerminalMessageType(msgType) || msgType === "") {
|
|
@@ -2952,8 +2961,8 @@ var EventClassifier = class {
|
|
|
2952
2961
|
}
|
|
2953
2962
|
/**
|
|
2954
2963
|
* Extracts plain assistant text from mode="messages" events that carry a
|
|
2955
|
-
* terminal AIMessage without loop-tagged phase metadata (
|
|
2956
|
-
*
|
|
2964
|
+
* terminal AIMessage without loop-tagged phase metadata (prefer named
|
|
2965
|
+
* deliverablePhases such as text_completion).
|
|
2957
2966
|
*/
|
|
2958
2967
|
messagesModeAssistantContent(data) {
|
|
2959
2968
|
if (!Array.isArray(data) || data.length === 0) return ["", false];
|
|
@@ -3452,6 +3461,110 @@ async function compactAttachments(atts, opts) {
|
|
|
3452
3461
|
|
|
3453
3462
|
// src/appkit/turn_runner.ts
|
|
3454
3463
|
init_intent_hints();
|
|
3464
|
+
|
|
3465
|
+
// src/appkit/turn_boundary.ts
|
|
3466
|
+
init_stream_terminal();
|
|
3467
|
+
var TURN_END_STREAM_END = STREAM_END;
|
|
3468
|
+
var TURN_END_IDLE = "status.idle";
|
|
3469
|
+
var TURN_END_STOPPED = "status.stopped";
|
|
3470
|
+
var TurnLifecycleGate = class {
|
|
3471
|
+
sawRunning = false;
|
|
3472
|
+
sawStreamPayload = false;
|
|
3473
|
+
sawTurnProgress = false;
|
|
3474
|
+
observe(msg) {
|
|
3475
|
+
const frame = normalizeFrame(msg);
|
|
3476
|
+
if (!frame) return;
|
|
3477
|
+
const typ = String(frame.type ?? "");
|
|
3478
|
+
if (typ === "status") {
|
|
3479
|
+
if (String(frame.state ?? "").trim().toLowerCase() === "running") {
|
|
3480
|
+
this.sawRunning = true;
|
|
3481
|
+
}
|
|
3482
|
+
return;
|
|
3483
|
+
}
|
|
3484
|
+
if (typ === "event") {
|
|
3485
|
+
this.sawStreamPayload = true;
|
|
3486
|
+
const mode = String(frame.mode ?? "");
|
|
3487
|
+
if (isTurnProgressChunk(mode, frame.data)) {
|
|
3488
|
+
this.sawTurnProgress = true;
|
|
3489
|
+
}
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3492
|
+
allowStreamEnd() {
|
|
3493
|
+
return this.sawRunning && this.sawTurnProgress;
|
|
3494
|
+
}
|
|
3495
|
+
allowIdleComplete() {
|
|
3496
|
+
return this.sawRunning && this.sawStreamPayload;
|
|
3497
|
+
}
|
|
3498
|
+
};
|
|
3499
|
+
var TurnBoundary = class {
|
|
3500
|
+
gate = new TurnLifecycleGate();
|
|
3501
|
+
ended = false;
|
|
3502
|
+
reason = "";
|
|
3503
|
+
feed(msg) {
|
|
3504
|
+
if (this.ended) return [true, this.reason];
|
|
3505
|
+
this.gate.observe(msg);
|
|
3506
|
+
const frame = normalizeFrame(msg);
|
|
3507
|
+
if (!frame) return [false, ""];
|
|
3508
|
+
const typ = String(frame.type ?? "");
|
|
3509
|
+
if (typ === "status") {
|
|
3510
|
+
const state = String(frame.state ?? "").trim().toLowerCase();
|
|
3511
|
+
if (state === "stopped" && this.gate.sawRunning) {
|
|
3512
|
+
return this.mark(TURN_END_STOPPED);
|
|
3513
|
+
}
|
|
3514
|
+
if (state === "idle" && this.gate.allowIdleComplete()) {
|
|
3515
|
+
return this.mark(TURN_END_IDLE);
|
|
3516
|
+
}
|
|
3517
|
+
return [false, ""];
|
|
3518
|
+
}
|
|
3519
|
+
if (typ === "event") {
|
|
3520
|
+
const mode = String(frame.mode ?? "");
|
|
3521
|
+
if (mode === "custom" && isTurnEndCustomData(frame.data) && this.gate.allowStreamEnd()) {
|
|
3522
|
+
return this.mark(TURN_END_STREAM_END);
|
|
3523
|
+
}
|
|
3524
|
+
}
|
|
3525
|
+
return [false, ""];
|
|
3526
|
+
}
|
|
3527
|
+
mark(reason) {
|
|
3528
|
+
this.ended = true;
|
|
3529
|
+
this.reason = reason;
|
|
3530
|
+
return [true, reason];
|
|
3531
|
+
}
|
|
3532
|
+
};
|
|
3533
|
+
function isDaemonTurnEndEvent(completionEvent) {
|
|
3534
|
+
const e = (completionEvent ?? "").trim();
|
|
3535
|
+
return e === TURN_END_STREAM_END || e === TURN_END_IDLE || e === TURN_END_STOPPED;
|
|
3536
|
+
}
|
|
3537
|
+
function normalizeFrame(msg) {
|
|
3538
|
+
if (!msg || typeof msg !== "object") return null;
|
|
3539
|
+
const m = msg;
|
|
3540
|
+
if (m.type === "next") {
|
|
3541
|
+
const payload = m.payload ?? {};
|
|
3542
|
+
const inner = payload.data;
|
|
3543
|
+
if (inner && typeof inner === "object" && inner.type === "status") {
|
|
3544
|
+
return inner;
|
|
3545
|
+
}
|
|
3546
|
+
if (inner && typeof inner === "object" && inner.mode) {
|
|
3547
|
+
return {
|
|
3548
|
+
type: "event",
|
|
3549
|
+
mode: inner.mode,
|
|
3550
|
+
data: inner.data,
|
|
3551
|
+
namespace: inner.namespace ?? payload.namespace
|
|
3552
|
+
};
|
|
3553
|
+
}
|
|
3554
|
+
if (payload.mode) {
|
|
3555
|
+
return {
|
|
3556
|
+
type: "event",
|
|
3557
|
+
mode: payload.mode,
|
|
3558
|
+
data: payload.data,
|
|
3559
|
+
namespace: payload.namespace
|
|
3560
|
+
};
|
|
3561
|
+
}
|
|
3562
|
+
return null;
|
|
3563
|
+
}
|
|
3564
|
+
return m;
|
|
3565
|
+
}
|
|
3566
|
+
|
|
3567
|
+
// src/appkit/turn_runner.ts
|
|
3455
3568
|
var ErrQueryTimeout = class extends Error {
|
|
3456
3569
|
constructor() {
|
|
3457
3570
|
super("appkit: query timeout");
|
|
@@ -3591,6 +3704,7 @@ var TurnRunner = class {
|
|
|
3591
3704
|
}
|
|
3592
3705
|
let assistantContent = "";
|
|
3593
3706
|
const startedAt = Date.now();
|
|
3707
|
+
const boundary = new TurnBoundary();
|
|
3594
3708
|
const idleForTurn = idleTimeoutForTurn(this.cfg, (attachments?.length ?? 0) > 0);
|
|
3595
3709
|
let idleReject = null;
|
|
3596
3710
|
const armIdle = () => {
|
|
@@ -3683,6 +3797,7 @@ var TurnRunner = class {
|
|
|
3683
3797
|
}
|
|
3684
3798
|
idleRace = armIdle();
|
|
3685
3799
|
const msg = res.value;
|
|
3800
|
+
const [ended, endReason] = boundary.feed(msg);
|
|
3686
3801
|
const eventResult = this.classifier.classify(msg, assistantContent);
|
|
3687
3802
|
if (eventResult.err && eventResult.terminal === 2 /* FailedComplete */) {
|
|
3688
3803
|
clearIdle();
|
|
@@ -3704,7 +3819,7 @@ var TurnRunner = class {
|
|
|
3704
3819
|
eventResult,
|
|
3705
3820
|
assistantContent
|
|
3706
3821
|
);
|
|
3707
|
-
if (deliverable) {
|
|
3822
|
+
if (deliverable && !isDaemonTurnEndEvent(eventResult.completionEvent ?? "")) {
|
|
3708
3823
|
clearIdle();
|
|
3709
3824
|
await this.completeTurn(
|
|
3710
3825
|
sessionID,
|
|
@@ -3715,6 +3830,24 @@ var TurnRunner = class {
|
|
|
3715
3830
|
);
|
|
3716
3831
|
return;
|
|
3717
3832
|
}
|
|
3833
|
+
if (ended) {
|
|
3834
|
+
clearIdle();
|
|
3835
|
+
if (this.classifier.isSubstantiveAssistantReply(assistantContent)) {
|
|
3836
|
+
await this.completeTurn(
|
|
3837
|
+
sessionID,
|
|
3838
|
+
loopID,
|
|
3839
|
+
assistantContent.trim(),
|
|
3840
|
+
startedAt,
|
|
3841
|
+
endReason
|
|
3842
|
+
);
|
|
3843
|
+
return;
|
|
3844
|
+
}
|
|
3845
|
+
const err = new Error(`turn ended (${endReason}) with no assistant content`);
|
|
3846
|
+
await this.persistFailed(sessionID, loopID, err);
|
|
3847
|
+
this.broadcastError(sessionID, err);
|
|
3848
|
+
this.onError?.(sessionID, loopID, err);
|
|
3849
|
+
throw err;
|
|
3850
|
+
}
|
|
3718
3851
|
}
|
|
3719
3852
|
} finally {
|
|
3720
3853
|
clearIdle();
|
|
@@ -4308,9 +4441,14 @@ var DaemonSession = class {
|
|
|
4308
4441
|
StaleLoopError,
|
|
4309
4442
|
StreamCloseFail,
|
|
4310
4443
|
StreamCloseSoftComplete,
|
|
4444
|
+
TURN_END_IDLE,
|
|
4445
|
+
TURN_END_STOPPED,
|
|
4446
|
+
TURN_END_STREAM_END,
|
|
4311
4447
|
TimeoutError,
|
|
4312
4448
|
TimeoutPolicy,
|
|
4449
|
+
TurnBoundary,
|
|
4313
4450
|
TurnEventStats,
|
|
4451
|
+
TurnLifecycleGate,
|
|
4314
4452
|
TurnRunner,
|
|
4315
4453
|
VerbosityTier,
|
|
4316
4454
|
authenticate,
|
|
@@ -4340,6 +4478,7 @@ var DaemonSession = class {
|
|
|
4340
4478
|
inputMessageForLoop,
|
|
4341
4479
|
isCompletionEvent,
|
|
4342
4480
|
isDaemonLive,
|
|
4481
|
+
isDaemonTurnEndEvent,
|
|
4343
4482
|
isSubagentProgressEvent,
|
|
4344
4483
|
isTurnEndCustomData,
|
|
4345
4484
|
isTurnProgressChunk,
|