@pikiloom/kernel 0.3.3 → 0.3.5
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/drivers/claude.d.ts +1 -1
- package/dist/drivers/claude.js +33 -9
- package/package.json +1 -1
package/dist/drivers/claude.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export declare function claudeBgAgentHoldCapMs(): number;
|
|
|
24
24
|
export declare function claudeTurnHasAgentBackground(s: any): boolean;
|
|
25
25
|
export declare function claudeBgHoldRecheckMs(): number;
|
|
26
26
|
export declare function claudeBgSettleQuietMs(): number;
|
|
27
|
-
export declare function claudeModelStallMs(): number;
|
|
27
|
+
export declare function claudeModelStallMs(effort?: string | null): number;
|
|
28
28
|
export declare const CLAUDE_TRUNCATED_RECOVERY_PROMPT: string;
|
|
29
29
|
export declare function claudeTruncatedRecoveryEnabled(): boolean;
|
|
30
30
|
export declare function isClaudeSyntheticResumeNoise(text: string): boolean;
|
package/dist/drivers/claude.js
CHANGED
|
@@ -193,7 +193,7 @@ export class ClaudeDriver {
|
|
|
193
193
|
return;
|
|
194
194
|
}
|
|
195
195
|
settleResult({ stopReason: 'stalled', kill: false, ok: false });
|
|
196
|
-
}, claudeModelStallMs());
|
|
196
|
+
}, claudeModelStallMs(input.effort));
|
|
197
197
|
unref(modelStallTimer);
|
|
198
198
|
};
|
|
199
199
|
try {
|
|
@@ -540,6 +540,23 @@ export function handleClaudeEvent(ev, s, emit) {
|
|
|
540
540
|
// as the reply nor counts as real output (the no-op-resume recovery keys off that emptiness).
|
|
541
541
|
if (ev.message?.model === '<synthetic>' && isClaudeSyntheticResumeNoise(claudeContentText(ev.message?.content)))
|
|
542
542
|
return;
|
|
543
|
+
// API-error message: Claude surfaces a failed model call (401 auth, overloaded, quota, …) not as a
|
|
544
|
+
// result code but as a synthetic assistant message — model '<synthetic>', a lone text block carrying
|
|
545
|
+
// the human-readable error ("Failed to authenticate. API Error: 401 …"), and a TOP-LEVEL `error` tag
|
|
546
|
+
// on the event (e.g. "authentication_failed"; the persisted transcript also stamps `isApiErrorMessage`).
|
|
547
|
+
// It is NOT model output. Routing its text through the normal path below would make the error render
|
|
548
|
+
// as the assistant's reply body (原文). Send it to `s.error` — the run-end notice, same slot as the
|
|
549
|
+
// `result{is_error}` branch below — and never to `s.text`. The trailing `result` also flags the error
|
|
550
|
+
// (and would set `s.error` too), but claiming it here keeps a narration-less turn from double-rendering
|
|
551
|
+
// (body + notice), and preserves any real narration already streamed before the call failed.
|
|
552
|
+
const apiErrorTag = typeof ev.error === 'string' ? ev.error.trim() : (ev.isApiErrorMessage ? 'api_error' : '');
|
|
553
|
+
if (apiErrorTag) {
|
|
554
|
+
if (!s.error) {
|
|
555
|
+
const msg = claudeContentText(ev.message?.content).trim();
|
|
556
|
+
s.error = msg || `Claude reported an API error (${apiErrorTag})`;
|
|
557
|
+
}
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
543
560
|
const contents = ev.message?.content || [];
|
|
544
561
|
for (const b of contents) {
|
|
545
562
|
if (b?.type !== 'tool_use')
|
|
@@ -784,15 +801,22 @@ export function claudeBgSettleQuietMs() {
|
|
|
784
801
|
return Number.isFinite(raw) && raw > 0 ? raw : CLAUDE_BG_SETTLE_QUIET_DEFAULT_MS;
|
|
785
802
|
}
|
|
786
803
|
// How long the model may stay COMPLETELY silent after a tool_result (control handed back to it,
|
|
787
|
-
// no background pending) before the driver gives up and settles the turn as 'stalled'.
|
|
788
|
-
// generous:
|
|
789
|
-
//
|
|
790
|
-
//
|
|
791
|
-
//
|
|
792
|
-
|
|
793
|
-
|
|
804
|
+
// no background pending) before the driver gives up and settles the turn as 'stalled'. Must be
|
|
805
|
+
// generous: subscription accounts stream NO events during extended thinking, and at the reasoning
|
|
806
|
+
// rungs a legitimate silent think regularly exceeds two minutes — the original 120s default
|
|
807
|
+
// misfired on exactly that (settling a LIVE turn as 'stalled' and then killing its still-running
|
|
808
|
+
// tool via the leak-guard; mirasim#111). A too-long window only means a truly hung turn shows its
|
|
809
|
+
// dead spinner longer, so the costs are asymmetric — err long. Effort-laddered: the deep-reasoning
|
|
810
|
+
// rungs (high and up) think the longest. A still-running tool never trips this (it has no
|
|
811
|
+
// tool_result yet). Override with PIKILOOM_CLAUDE_MODEL_STALL_MS (wins over the ladder).
|
|
812
|
+
const CLAUDE_MODEL_STALL_DEFAULT_MS = 300_000;
|
|
813
|
+
const CLAUDE_MODEL_STALL_DEEP_MS = 600_000;
|
|
814
|
+
const CLAUDE_DEEP_REASONING_EFFORTS = new Set(['high', 'xhigh', 'max', 'ultra']);
|
|
815
|
+
export function claudeModelStallMs(effort) {
|
|
794
816
|
const raw = Number(process.env.PIKILOOM_CLAUDE_MODEL_STALL_MS);
|
|
795
|
-
|
|
817
|
+
if (Number.isFinite(raw) && raw > 0)
|
|
818
|
+
return raw;
|
|
819
|
+
return effort && CLAUDE_DEEP_REASONING_EFFORTS.has(effort) ? CLAUDE_MODEL_STALL_DEEP_MS : CLAUDE_MODEL_STALL_DEFAULT_MS;
|
|
796
820
|
}
|
|
797
821
|
// In-process self-heal for a truncated turn: when a clean result lands while the tool loop is
|
|
798
822
|
// still dangling (the model's closing round came back empty), the stdin is still open — inject
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikiloom/kernel",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"description": "Heterogeneous coding agents (Claude / Codex / Gemini / ACP) -> an interaction-friendly, accumulating session snapshot + control handle, over pluggable surfaces (IM, Web, tunnel, TUI). The reusable core pikiloom itself is built on.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|