lark-remote 0.5.19 → 0.5.20
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/CHANGELOG.md +19 -0
- package/dist/bridge/approval-actions.d.ts +1 -1
- package/dist/bridge/approval-actions.js +1 -1
- package/dist/bridge/bash-run.d.ts +71 -0
- package/dist/bridge/bash-run.js +217 -0
- package/dist/bridge/compact.d.ts +155 -0
- package/dist/bridge/compact.js +450 -0
- package/dist/bridge/final-usage.js +4 -4
- package/dist/bridge/inbound-media.js +1 -1
- package/dist/bridge/index.d.ts +97 -153
- package/dist/bridge/index.js +182 -809
- package/dist/bridge/job-watch.d.ts +68 -0
- package/dist/bridge/job-watch.js +146 -0
- package/dist/bridge/queue-manager.d.ts +3 -3
- package/dist/bridge/queue-manager.js +10 -29
- package/dist/card/approval-render.d.ts +2 -2
- package/dist/card/approval-render.js +109 -97
- package/dist/card/card-budget.js +1 -1
- package/dist/card/card-helpers.d.ts +3 -3
- package/dist/card/card-helpers.js +6 -6
- package/dist/card/final-answer-file.js +1 -1
- package/dist/card/run-renderer.d.ts +3 -3
- package/dist/card/run-renderer.js +34 -93
- package/dist/card/run-state.d.ts +1 -1
- package/dist/card/run-state.js +28 -90
- package/dist/card/tool-render.d.ts +1 -1
- package/dist/card/tool-render.js +1 -1
- package/dist/card/usage-format.d.ts +12 -0
- package/dist/card/usage-format.js +8 -3
- package/dist/cli.js +15 -3
- package/dist/clone.js +2 -2
- package/dist/config/codex-config.js +130 -106
- package/dist/config/index.d.ts +16 -2
- package/dist/config/index.js +23 -8
- package/dist/connector/index.js +6 -6
- package/dist/error-classification.js +3 -2
- package/dist/inbound/placeholder.d.ts +1 -1
- package/dist/inbound/placeholder.js +1 -1
- package/dist/index.js +203 -133
- package/dist/logger/index.js +6 -6
- package/dist/message-handlers.d.ts +0 -5
- package/dist/message-handlers.js +1 -1
- package/dist/model-catalog.d.ts +2 -2
- package/dist/model-catalog.js +3 -8
- package/dist/platform/identity.js +1 -1
- package/dist/platform/path.d.ts +1 -1
- package/dist/platform/path.js +1 -1
- package/dist/platform/sleep-blocker.js +1 -1
- package/dist/platform/terminator-win32.js +2 -1
- package/dist/router/commands/resume.js +2 -20
- package/dist/router/config/dsh.d.ts +4 -8
- package/dist/router/config/dsh.js +3 -10
- package/dist/router/config/kimi.js +1 -1
- package/dist/router/config/types.d.ts +1 -1
- package/dist/router/config-diff.js +1 -1
- package/dist/router/index.d.ts +56 -11
- package/dist/router/index.js +219 -200
- package/dist/runner/claude/session.d.ts +1 -1
- package/dist/runner/claude/session.js +6 -4
- package/dist/runner/codex/app-server/runner.d.ts +9 -2
- package/dist/runner/codex/app-server/runner.js +30 -25
- package/dist/runner/codex/app-server/translator.d.ts +0 -5
- package/dist/runner/codex/app-server/translator.js +4 -17
- package/dist/runner/common/acp/acp-approval.d.ts +1 -1
- package/dist/runner/common/acp/acp-approval.js +1 -1
- package/dist/runner/common/acp/base-acp-runner.d.ts +5 -2
- package/dist/runner/common/acp/base-acp-runner.js +26 -65
- package/dist/runner/common/acp/base-translator.d.ts +12 -2
- package/dist/runner/common/acp/base-translator.js +31 -9
- package/dist/runner/common/acp/protocol-types.d.ts +1 -1
- package/dist/runner/common/acp/protocol-types.js +2 -2
- package/dist/runner/common/connection-based-runner.d.ts +32 -1
- package/dist/runner/common/connection-based-runner.js +32 -2
- package/dist/runner/common/jsonrpc/connection-manager.d.ts +2 -2
- package/dist/runner/common/jsonrpc/connection-manager.js +4 -4
- package/dist/runner/common/spawning-runner.d.ts +1 -1
- package/dist/runner/common/spawning-runner.js +1 -1
- package/dist/runner/dsh/catalog-probe.d.ts +17 -0
- package/dist/runner/dsh/catalog-probe.js +10 -0
- package/dist/runner/dsh/client.d.ts +1 -3
- package/dist/runner/dsh/client.js +2 -4
- package/dist/runner/dsh/exit-cancel.d.ts +2 -2
- package/dist/runner/dsh/exit-cancel.js +2 -2
- package/dist/runner/dsh/inflight.d.ts +1 -1
- package/dist/runner/dsh/inflight.js +1 -1
- package/dist/runner/dsh/runner.d.ts +40 -1
- package/dist/runner/dsh/runner.js +272 -199
- package/dist/runner/dsh/translator.d.ts +1 -1
- package/dist/runner/dsh/translator.js +1 -1
- package/dist/runner/index.d.ts +1 -1
- package/dist/runner/kimi/acp/runner.d.ts +1 -2
- package/dist/runner/kimi/acp/runner.js +1 -2
- package/dist/runner/kimi/acp/translator.d.ts +1 -1
- package/dist/runner/kimi/acp/translator.js +3 -4
- package/dist/runner/opencode/acp/runner.d.ts +2 -2
- package/dist/runner/opencode/acp/runner.js +4 -4
- package/dist/runner/pi/rpc/protocol-types.d.ts +1 -1
- package/dist/runner/pi/rpc/protocol-types.js +1 -1
- package/dist/runner/pi/rpc/runner.d.ts +3 -0
- package/dist/runner/pi/rpc/runner.js +27 -42
- package/dist/runner/types.d.ts +2 -2
- package/dist/runner/types.js +1 -1
- package/dist/session/claude/sessions.d.ts +45 -0
- package/dist/session/claude/sessions.js +97 -71
- package/dist/session/codex/rollout-reader.js +4 -4
- package/dist/session/common/throw-session-list-error.d.ts +10 -0
- package/dist/session/common/throw-session-list-error.js +16 -0
- package/dist/session/dsh/sessions.js +11 -5
- package/dist/session/kimi/sessions.d.ts +40 -1
- package/dist/session/kimi/sessions.js +244 -192
- package/dist/session/opencode/sessions.d.ts +153 -1
- package/dist/session/opencode/sessions.js +354 -321
- package/dist/session/pi/sessions.js +4 -5
- package/dist/session/session-store.d.ts +1 -1
- package/dist/session/session-store.js +1 -1
- package/dist/update/version-check.js +2 -1
- package/dist/workspace/index.d.ts +1 -1
- package/dist/workspace/index.js +1 -1
- package/package.json +1 -1
package/dist/card/run-state.js
CHANGED
|
@@ -125,8 +125,6 @@ function reduceRunStateInner(state, event) {
|
|
|
125
125
|
}
|
|
126
126
|
/** Handle app-server turn_started — records the operation kind (turn vs compact). */
|
|
127
127
|
function reduceTurnStartedEvent(state, event) {
|
|
128
|
-
if (event.type !== 'turn_started')
|
|
129
|
-
return state;
|
|
130
128
|
return {
|
|
131
129
|
...state,
|
|
132
130
|
operationKind: event.operationKind,
|
|
@@ -142,8 +140,6 @@ function reduceTurnStartedEvent(state, event) {
|
|
|
142
140
|
* the active streaming content sits at the bottom, like the exec path.
|
|
143
141
|
*/
|
|
144
142
|
function reduceTurnDiffEvent(state, event) {
|
|
145
|
-
if (event.type !== 'turn_diff')
|
|
146
|
-
return state;
|
|
147
143
|
let next = state;
|
|
148
144
|
const ts = event.timestamp;
|
|
149
145
|
const complete = event.complete === true;
|
|
@@ -170,12 +166,7 @@ function reduceTurnDiffEvent(state, event) {
|
|
|
170
166
|
...(complete ? { completedAt: ts } : {}),
|
|
171
167
|
};
|
|
172
168
|
}, !complete);
|
|
173
|
-
next =
|
|
174
|
-
...next,
|
|
175
|
-
blocks: keepLatestBlocks(capped),
|
|
176
|
-
omittedBlocks: (next.omittedBlocks ?? 0) + Math.max(0, capped.length - MAX_BLOCKS),
|
|
177
|
-
footer: 'streaming',
|
|
178
|
-
};
|
|
169
|
+
next = withCappedBlocks(next, capped, 'streaming');
|
|
179
170
|
}
|
|
180
171
|
if (event.reasoning !== undefined) {
|
|
181
172
|
const capped = upsertSnapshotBlock(next.blocks, (b) => b.kind === 'thinking' && b.itemId === event.itemId, () => ({
|
|
@@ -195,12 +186,7 @@ function reduceTurnDiffEvent(state, event) {
|
|
|
195
186
|
...(complete ? { completedAt: ts } : {}),
|
|
196
187
|
};
|
|
197
188
|
}, !complete);
|
|
198
|
-
next =
|
|
199
|
-
...next,
|
|
200
|
-
blocks: keepLatestBlocks(capped),
|
|
201
|
-
omittedBlocks: (next.omittedBlocks ?? 0) + Math.max(0, capped.length - MAX_BLOCKS),
|
|
202
|
-
footer: 'thinking',
|
|
203
|
-
};
|
|
189
|
+
next = withCappedBlocks(next, capped, 'thinking');
|
|
204
190
|
}
|
|
205
191
|
if (event.toolOutput !== undefined) {
|
|
206
192
|
const capped = upsertSnapshotBlock(next.blocks, (b) => b.kind === 'tool' && b.tool.id === event.itemId, () => {
|
|
@@ -231,12 +217,7 @@ function reduceTurnDiffEvent(state, event) {
|
|
|
231
217
|
...(complete ? { completedAt: ts } : {}),
|
|
232
218
|
},
|
|
233
219
|
}), !complete);
|
|
234
|
-
next =
|
|
235
|
-
...next,
|
|
236
|
-
blocks: keepLatestBlocks(capped),
|
|
237
|
-
omittedBlocks: (next.omittedBlocks ?? 0) + Math.max(0, capped.length - MAX_BLOCKS),
|
|
238
|
-
footer: 'tool_running',
|
|
239
|
-
};
|
|
220
|
+
next = withCappedBlocks(next, capped, 'tool_running');
|
|
240
221
|
}
|
|
241
222
|
if (event.plan !== undefined) {
|
|
242
223
|
const newPlan = keepTailMarked(event.plan, MAX_REASONING_CHARS * 2);
|
|
@@ -256,12 +237,7 @@ function reduceTurnDiffEvent(state, event) {
|
|
|
256
237
|
...(complete ? { completedAt: ts } : {}),
|
|
257
238
|
};
|
|
258
239
|
}, !complete);
|
|
259
|
-
next = {
|
|
260
|
-
...next,
|
|
261
|
-
plan: newPlan,
|
|
262
|
-
blocks: keepLatestBlocks(capped),
|
|
263
|
-
omittedBlocks: (next.omittedBlocks ?? 0) + Math.max(0, capped.length - MAX_BLOCKS),
|
|
264
|
-
};
|
|
240
|
+
next = withCappedBlocks({ ...next, plan: newPlan }, capped);
|
|
265
241
|
}
|
|
266
242
|
if (event.fileChanges !== undefined) {
|
|
267
243
|
let blocks = next.blocks;
|
|
@@ -278,12 +254,7 @@ function reduceTurnDiffEvent(state, event) {
|
|
|
278
254
|
// 同一 item 的同一路径原地替换(权威 diff 校正),新路径/新 item 追加。
|
|
279
255
|
blocks = upsertSnapshotBlock(blocks, (b) => b.kind === 'file_change' && b.itemId === event.itemId && b.path === fc.path, () => fileBlock, () => fileBlock, !complete);
|
|
280
256
|
}
|
|
281
|
-
|
|
282
|
-
next = {
|
|
283
|
-
...next,
|
|
284
|
-
blocks: keepLatestBlocks(capped),
|
|
285
|
-
omittedBlocks: (next.omittedBlocks ?? 0) + Math.max(0, capped.length - MAX_BLOCKS),
|
|
286
|
-
};
|
|
257
|
+
next = withCappedBlocks(next, blocks);
|
|
287
258
|
}
|
|
288
259
|
return next;
|
|
289
260
|
}
|
|
@@ -313,8 +284,6 @@ function upsertSnapshotBlock(blocks, predicate, fallback, update, moveToEndWhenN
|
|
|
313
284
|
}
|
|
314
285
|
/** Handle system init and compact_boundary events. */
|
|
315
286
|
function reduceSystemEvent(state, event) {
|
|
316
|
-
if (event.type !== 'system')
|
|
317
|
-
return state;
|
|
318
287
|
if (event.subtype === 'init') {
|
|
319
288
|
return { ...state, sessionId: event.session_id, model: event.model, footer: 'thinking' };
|
|
320
289
|
}
|
|
@@ -336,8 +305,6 @@ function reduceSystemEvent(state, event) {
|
|
|
336
305
|
* - errorMsg: 首个非 undefined 胜出(agent 的更具体)
|
|
337
306
|
*/
|
|
338
307
|
function reduceResultEvent(state, event) {
|
|
339
|
-
if (event.type !== 'result')
|
|
340
|
-
return state;
|
|
341
308
|
// Pre-init result guard: Claude CLI --resume emits a historical result (from
|
|
342
309
|
// the previous turn) before sending system.init for the new run. Without this
|
|
343
310
|
// guard, that stale result would prematurely transition to 'finalizing',
|
|
@@ -375,8 +342,6 @@ function reduceResultEvent(state, event) {
|
|
|
375
342
|
}
|
|
376
343
|
/** Record an authoritative protocol final answer and remove its progress copy. */
|
|
377
344
|
function reduceFinalAnswerEvent(state, event) {
|
|
378
|
-
if (event.type !== 'final_answer')
|
|
379
|
-
return state;
|
|
380
345
|
if (!event.text.trim() && !state.finalAnswer)
|
|
381
346
|
return state;
|
|
382
347
|
const blocks = event.itemId
|
|
@@ -443,8 +408,6 @@ function promoteFinalAnswer(state, source, authoritativeText) {
|
|
|
443
408
|
* 不再走事件(那时已经没有 run 在消费流了)。
|
|
444
409
|
*/
|
|
445
410
|
function reduceBackgroundJobsEvent(state, event) {
|
|
446
|
-
if (event.type !== 'background_jobs')
|
|
447
|
-
return state;
|
|
448
411
|
return { ...state, backgroundJobs: event.jobs };
|
|
449
412
|
}
|
|
450
413
|
/**
|
|
@@ -556,8 +519,6 @@ export function markBackgroundJobsUnknown(state) {
|
|
|
556
519
|
* 维度(上一步算出的上下文水位)擦掉。
|
|
557
520
|
*/
|
|
558
521
|
function reduceRunStatusEvent(state, event) {
|
|
559
|
-
if (event.type !== 'run_status')
|
|
560
|
-
return state;
|
|
561
522
|
const prev = state.liveStatus ?? {};
|
|
562
523
|
const live = {
|
|
563
524
|
...prev,
|
|
@@ -575,8 +536,6 @@ function reduceRunStatusEvent(state, event) {
|
|
|
575
536
|
}
|
|
576
537
|
/** Handle assistant thinking/text/tool_use content blocks. */
|
|
577
538
|
function reduceAssistantEvent(state, event) {
|
|
578
|
-
if (event.type !== 'assistant')
|
|
579
|
-
return state;
|
|
580
539
|
let next = state;
|
|
581
540
|
for (const content of event.message.content) {
|
|
582
541
|
if (content.type === 'thinking') {
|
|
@@ -605,12 +564,7 @@ function reduceAssistantEvent(state, event) {
|
|
|
605
564
|
timestamp: event.timestamp,
|
|
606
565
|
},
|
|
607
566
|
];
|
|
608
|
-
next =
|
|
609
|
-
...next,
|
|
610
|
-
blocks: keepLatestBlocks(newBlocks),
|
|
611
|
-
omittedBlocks: (next.omittedBlocks ?? 0) + Math.max(0, newBlocks.length - MAX_BLOCKS),
|
|
612
|
-
footer: 'thinking',
|
|
613
|
-
};
|
|
567
|
+
next = withCappedBlocks(next, newBlocks, 'thinking');
|
|
614
568
|
}
|
|
615
569
|
else if (content.type === 'text') {
|
|
616
570
|
const blocks = markThinkingInactive(next.blocks);
|
|
@@ -634,12 +588,7 @@ function reduceAssistantEvent(state, event) {
|
|
|
634
588
|
timestamp: event.timestamp,
|
|
635
589
|
},
|
|
636
590
|
];
|
|
637
|
-
next =
|
|
638
|
-
...next,
|
|
639
|
-
blocks: keepLatestBlocks(newBlocks),
|
|
640
|
-
omittedBlocks: (next.omittedBlocks ?? 0) + Math.max(0, newBlocks.length - MAX_BLOCKS),
|
|
641
|
-
footer: 'streaming',
|
|
642
|
-
};
|
|
591
|
+
next = withCappedBlocks(next, newBlocks, 'streaming');
|
|
643
592
|
}
|
|
644
593
|
else {
|
|
645
594
|
// parse the truncated stored string ONCE here (not on every render)
|
|
@@ -674,12 +623,7 @@ function reduceAssistantEvent(state, event) {
|
|
|
674
623
|
}
|
|
675
624
|
else {
|
|
676
625
|
const capped = [...blocks, { kind: 'tool', tool: incomingTool }];
|
|
677
|
-
next =
|
|
678
|
-
...next,
|
|
679
|
-
blocks: keepLatestBlocks(capped),
|
|
680
|
-
omittedBlocks: (next.omittedBlocks ?? 0) + Math.max(0, capped.length - MAX_BLOCKS),
|
|
681
|
-
footer: 'tool_running',
|
|
682
|
-
};
|
|
626
|
+
next = withCappedBlocks(next, capped, 'tool_running');
|
|
683
627
|
}
|
|
684
628
|
}
|
|
685
629
|
}
|
|
@@ -716,8 +660,6 @@ function mergeToolUse(existing, incoming) {
|
|
|
716
660
|
* advances to 'streaming' on every content block (parity with old behavior);
|
|
717
661
|
* only the blocks array is preserved by reference when nothing matches. */
|
|
718
662
|
function reduceToolResultEvent(state, event) {
|
|
719
|
-
if (event.type !== 'user')
|
|
720
|
-
return state;
|
|
721
663
|
let next = state;
|
|
722
664
|
for (const content of event.message.content) {
|
|
723
665
|
const targetId = content.tool_use_id;
|
|
@@ -745,8 +687,6 @@ function reduceToolResultEvent(state, event) {
|
|
|
745
687
|
}
|
|
746
688
|
/** Handle notice event — append a runtime notice (warning / reroute / compaction). */
|
|
747
689
|
function reduceNoticeEvent(state, event) {
|
|
748
|
-
if (event.type !== 'notice')
|
|
749
|
-
return state;
|
|
750
690
|
return {
|
|
751
691
|
...state,
|
|
752
692
|
notices: [
|
|
@@ -762,8 +702,6 @@ function reduceNoticeEvent(state, event) {
|
|
|
762
702
|
}
|
|
763
703
|
/** Handle session_info event — update sessionTitle / mode only when present. */
|
|
764
704
|
function reduceSessionInfoEvent(state, event) {
|
|
765
|
-
if (event.type !== 'session_info')
|
|
766
|
-
return state;
|
|
767
705
|
return {
|
|
768
706
|
...state,
|
|
769
707
|
...(event.title !== undefined ? { sessionTitle: event.title } : {}),
|
|
@@ -772,8 +710,6 @@ function reduceSessionInfoEvent(state, event) {
|
|
|
772
710
|
}
|
|
773
711
|
/** Handle plan event — accumulate plan text for Codex-style agents. */
|
|
774
712
|
function reducePlanEvent(state, event) {
|
|
775
|
-
if (event.type !== 'plan')
|
|
776
|
-
return state;
|
|
777
713
|
const currentPlan = state.plan ?? '';
|
|
778
714
|
const newPlan = keepTailMarked(currentPlan + '\n' + event.plan, MAX_REASONING_CHARS * 2);
|
|
779
715
|
// Plan is a single evolving document — replace the existing plan block
|
|
@@ -783,17 +719,10 @@ function reducePlanEvent(state, event) {
|
|
|
783
719
|
...withoutOldPlan,
|
|
784
720
|
{ kind: 'plan', content: newPlan, active: true, timestamp: event.timestamp },
|
|
785
721
|
];
|
|
786
|
-
return {
|
|
787
|
-
...state,
|
|
788
|
-
plan: newPlan,
|
|
789
|
-
blocks: keepLatestBlocks(newBlocks),
|
|
790
|
-
omittedBlocks: (state.omittedBlocks ?? 0) + Math.max(0, newBlocks.length - MAX_BLOCKS),
|
|
791
|
-
};
|
|
722
|
+
return withCappedBlocks({ ...state, plan: newPlan }, newBlocks);
|
|
792
723
|
}
|
|
793
724
|
/** Handle file_change event — emit a file_change block for rendering (Codex-style agents). */
|
|
794
725
|
function reduceFileChangeEvent(state, event) {
|
|
795
|
-
if (event.type !== 'file_change')
|
|
796
|
-
return state;
|
|
797
726
|
// Add file_change block for rendering (collapsed by default)
|
|
798
727
|
const newBlocks = [
|
|
799
728
|
...state.blocks,
|
|
@@ -805,11 +734,7 @@ function reduceFileChangeEvent(state, event) {
|
|
|
805
734
|
timestamp: event.timestamp,
|
|
806
735
|
},
|
|
807
736
|
];
|
|
808
|
-
return
|
|
809
|
-
...state,
|
|
810
|
-
blocks: keepLatestBlocks(newBlocks),
|
|
811
|
-
omittedBlocks: (state.omittedBlocks ?? 0) + Math.max(0, newBlocks.length - MAX_BLOCKS),
|
|
812
|
-
};
|
|
737
|
+
return withCappedBlocks(state, newBlocks);
|
|
813
738
|
}
|
|
814
739
|
export function finishRun(state, terminal, meta = {}) {
|
|
815
740
|
const withFinalAnswer = promoteFinalAnswer(state, 'inferred');
|
|
@@ -862,14 +787,27 @@ function stringifyUnknown(value) {
|
|
|
862
787
|
try {
|
|
863
788
|
// JSON.stringify(undefined) returns the value undefined, which would
|
|
864
789
|
// violate this function's string contract and crash callers that take
|
|
865
|
-
// .length on the result
|
|
866
|
-
// → truncateDetail TypeError). Normalize to ''.
|
|
790
|
+
// .length on the result. Normalize to ''.
|
|
867
791
|
return JSON.stringify(value) ?? '';
|
|
868
792
|
}
|
|
869
793
|
catch {
|
|
870
794
|
return String(value);
|
|
871
795
|
}
|
|
872
796
|
}
|
|
797
|
+
/**
|
|
798
|
+
* 尾块统一收口:keepLatestBlocks 截断 + omittedBlocks 计数 + footer 更新一步
|
|
799
|
+
* 完成。所有「追加/更新块后只保留最新 MAX_BLOCKS 块」的事件归约共用(此前
|
|
800
|
+
* 多处逐字重复);`blocks` 必须传截断前的数组,被丢出的最旧块才会计入
|
|
801
|
+
* omittedBlocks。`footer` 不传时保持原值(plan/file_change 归约不改 footer)。
|
|
802
|
+
*/
|
|
803
|
+
function withCappedBlocks(next, blocks, footer) {
|
|
804
|
+
return {
|
|
805
|
+
...next,
|
|
806
|
+
blocks: keepLatestBlocks(blocks),
|
|
807
|
+
omittedBlocks: (next.omittedBlocks ?? 0) + Math.max(0, blocks.length - MAX_BLOCKS),
|
|
808
|
+
...(footer === undefined ? {} : { footer }),
|
|
809
|
+
};
|
|
810
|
+
}
|
|
873
811
|
function keepLatestBlocks(blocks) {
|
|
874
812
|
return blocks.length <= MAX_BLOCKS ? blocks : blocks.slice(-MAX_BLOCKS);
|
|
875
813
|
}
|
|
@@ -879,8 +817,8 @@ const TRUNCATION_MARKER_RE = /^…(前 (\d+) 字符已省略)\n/;
|
|
|
879
817
|
* 给「已经不再是最新」的 text 块补上 `MAX_TEXT_CHARS` 存储窗口。
|
|
880
818
|
*
|
|
881
819
|
* 为什么最新一条不截:它就是卡片上的**输出**,终态还会被 `promoteFinalAnswer`
|
|
882
|
-
*
|
|
883
|
-
*
|
|
820
|
+
* 提成最终回答。提前按窗口切掉头部,渲染层再怎么回答优先也补不回来
|
|
821
|
+
* (16074 字符的回答只进到渲染层 12000 字符,且是从中间开始的)。
|
|
884
822
|
*
|
|
885
823
|
* 为什么其余 text 块仍然截:它们只是进度信息,卡片本来就只会展示最新几步;
|
|
886
824
|
* 存储层必须保持有界(`MAX_BLOCKS` × 窗口),否则长 run 的内存随历史线性增长。
|
|
@@ -915,7 +853,7 @@ function capStaleTextBlocks(blocks) {
|
|
|
915
853
|
* keepTail + 截断标记:被去头的存储内容以前缀如实标注(信息保真红线:禁止静默丢弃)。
|
|
916
854
|
* 标记计入 maxChars 预算(存储总量仍 ≤ maxChars,保持既有长度不变量)。
|
|
917
855
|
*
|
|
918
|
-
*
|
|
856
|
+
* 计数口径:只统计**真实丢弃的正文**,不含标记自身开销。
|
|
919
857
|
* 关键点是增量流下 `value` 往往已带上一次的标记(`marker + kept`);若直接
|
|
920
858
|
* 用 `value.length - kept.length` 计费,会把上一帧的标记文本也算进「已省略」,
|
|
921
859
|
* 造成每帧显示十几字符的虚高。这里先剥离旧标记,把 N 定义为**从该块起始累计
|
|
@@ -17,7 +17,7 @@ export { displayWidth, truncateMiddleToDisplayWidth, truncateToDisplayWidth, } f
|
|
|
17
17
|
* 手机(~390px 内容宽)上折叠面板的标题只有**一行**可用:减去图标与内边距约
|
|
18
18
|
* 320px,按 ~7.5px/半角算 ≈ 42 个半角宽度(iPhone SE 更窄,超出时按 `·`/空格
|
|
19
19
|
* 折行仍可读,但不能整段换行)。超过就折行,断点常常落在 URL 或命令
|
|
20
|
-
*
|
|
20
|
+
* 中间。完整参数在展开后的正文里,标题只负责"哪个工具、
|
|
21
21
|
* 动了什么",并带上 `HH:mm` 时间戳(一起计入预算)。
|
|
22
22
|
*/
|
|
23
23
|
export declare const HEADER_DISPLAY_MAX = 42;
|
package/dist/card/tool-render.js
CHANGED
|
@@ -20,7 +20,7 @@ export { displayWidth, truncateMiddleToDisplayWidth, truncateToDisplayWidth, } f
|
|
|
20
20
|
* 手机(~390px 内容宽)上折叠面板的标题只有**一行**可用:减去图标与内边距约
|
|
21
21
|
* 320px,按 ~7.5px/半角算 ≈ 42 个半角宽度(iPhone SE 更窄,超出时按 `·`/空格
|
|
22
22
|
* 折行仍可读,但不能整段换行)。超过就折行,断点常常落在 URL 或命令
|
|
23
|
-
*
|
|
23
|
+
* 中间。完整参数在展开后的正文里,标题只负责"哪个工具、
|
|
24
24
|
* 动了什么",并带上 `HH:mm` 时间戳(一起计入预算)。
|
|
25
25
|
*/
|
|
26
26
|
export const HEADER_DISPLAY_MAX = 42;
|
|
@@ -8,6 +8,18 @@
|
|
|
8
8
|
import type { UsageSnapshot } from '../session-contract.js';
|
|
9
9
|
/** `formatUsageStats` 只读这几项:会话/进度卡片上的紧凑用量行。 */
|
|
10
10
|
export type SessionDisplayUsage = Pick<UsageSnapshot, 'contextLength' | 'contextLimit' | 'compactCount' | 'cacheReadTokens' | 'cacheCreationTokens'>;
|
|
11
|
+
/**
|
|
12
|
+
* Format number to human-readable unit string.
|
|
13
|
+
* - >= 999_500: M with at most one decimal (e.g., 999_600 → 1M, 1200000 → 1.2M,
|
|
14
|
+
* 25000000 → 25M)
|
|
15
|
+
* - >= 1K: rounded to nearest integer K (e.g., 1500 → 2K, 120000 → 120K)
|
|
16
|
+
* - < 1K: as-is (e.g., 500 → "500")
|
|
17
|
+
*
|
|
18
|
+
* 千位边界取 M 档:999_500 起按 K 四舍五入会得到 "1000K",直接按 M 档展示。
|
|
19
|
+
* 此前 run-renderer 另有一份 formatTokens 只在这边带此边界护栏,两处已收敛
|
|
20
|
+
* 到本函数(run-renderer 的状态行 `📊 N` 也走这里)。
|
|
21
|
+
*/
|
|
22
|
+
export declare function formatTokenK(n: number): string;
|
|
11
23
|
/**
|
|
12
24
|
* Format usage stats (context length, compact count, cache tokens) into a display string.
|
|
13
25
|
* Each stat on its own line with blank lines between sections.
|
|
@@ -7,12 +7,17 @@
|
|
|
7
7
|
*/
|
|
8
8
|
/**
|
|
9
9
|
* Format number to human-readable unit string.
|
|
10
|
-
* - >=
|
|
10
|
+
* - >= 999_500: M with at most one decimal (e.g., 999_600 → 1M, 1200000 → 1.2M,
|
|
11
|
+
* 25000000 → 25M)
|
|
11
12
|
* - >= 1K: rounded to nearest integer K (e.g., 1500 → 2K, 120000 → 120K)
|
|
12
13
|
* - < 1K: as-is (e.g., 500 → "500")
|
|
14
|
+
*
|
|
15
|
+
* 千位边界取 M 档:999_500 起按 K 四舍五入会得到 "1000K",直接按 M 档展示。
|
|
16
|
+
* 此前 run-renderer 另有一份 formatTokens 只在这边带此边界护栏,两处已收敛
|
|
17
|
+
* 到本函数(run-renderer 的状态行 `📊 N` 也走这里)。
|
|
13
18
|
*/
|
|
14
|
-
function formatTokenK(n) {
|
|
15
|
-
if (n >=
|
|
19
|
+
export function formatTokenK(n) {
|
|
20
|
+
if (n >= 999_500) {
|
|
16
21
|
const m = n / 1_000_000;
|
|
17
22
|
const rounded = Math.round(m * 10) / 10;
|
|
18
23
|
// Drop unnecessary ".0" for whole numbers (2.0M → 2M)
|
package/dist/cli.js
CHANGED
|
@@ -92,10 +92,17 @@ export async function bootstrap(deps) {
|
|
|
92
92
|
forwarders.set(sig, forwarder);
|
|
93
93
|
onSignal(sig, forwarder);
|
|
94
94
|
}
|
|
95
|
-
child.on('error', () => {
|
|
95
|
+
child.on('error', (err) => {
|
|
96
|
+
// bun 拉起失败(ENOENT/EACCES)会静默切 node 兜底,但错误本身必须留痕,
|
|
97
|
+
// 否则「为什么跑在了 node 上」无从排查。logger 此时尚未初始化,console
|
|
98
|
+
// 是规则允许的启动期例外。
|
|
99
|
+
console.error('[lark-remote] bun spawn failed, falling back to node:', err);
|
|
96
100
|
for (const [sig, forwarder] of forwarders)
|
|
97
101
|
offSignal(sig, forwarder);
|
|
98
|
-
void importEntry().catch(() =>
|
|
102
|
+
void importEntry().catch((importErr) => {
|
|
103
|
+
console.error('[lark-remote] node fallback import failed:', importErr);
|
|
104
|
+
exit(1);
|
|
105
|
+
});
|
|
99
106
|
});
|
|
100
107
|
child.on('exit', (code, signal) => {
|
|
101
108
|
if (signal) {
|
|
@@ -146,7 +153,12 @@ function main() {
|
|
|
146
153
|
killSelf: (sig) => process.kill(process.pid, sig),
|
|
147
154
|
exit: (code) => process.exit(code),
|
|
148
155
|
};
|
|
149
|
-
|
|
156
|
+
// bootstrap 是第一接触面:静默 exit(1) 会让安装损坏/依赖缺失表现为零输出
|
|
157
|
+
// 退出,必须把根因打到 stderr(logger 未初始化,console 为规则允许的例外)。
|
|
158
|
+
void bootstrap(deps).catch((err) => {
|
|
159
|
+
console.error('[lark-remote] bootstrap failed:', err);
|
|
160
|
+
process.exit(1);
|
|
161
|
+
});
|
|
150
162
|
}
|
|
151
163
|
if (isDirectEntry()) {
|
|
152
164
|
main();
|
package/dist/clone.js
CHANGED
|
@@ -237,7 +237,7 @@ export class CloneSession {
|
|
|
237
237
|
// 图片发送失败不阻断流程:给出浏览器打开兜底。
|
|
238
238
|
await this.connector
|
|
239
239
|
.sendWithRetry(ctx.chatId, { text: `⚠️ 二维码图片发送失败,请在浏览器打开创建:${info.url}` }, { replyTo: ctx.messageId })
|
|
240
|
-
.catch(() =>
|
|
240
|
+
.catch((err) => getLogger().warn('[clone] fallback notice send failed:', err));
|
|
241
241
|
return;
|
|
242
242
|
}
|
|
243
243
|
finally {
|
|
@@ -336,7 +336,7 @@ export class CloneSession {
|
|
|
336
336
|
`新应用凭证(请妥善保管):App ID ${result.client_id}\n` +
|
|
337
337
|
'可修复本机问题后用 /clone 重新走一遍流程(会创建新应用)',
|
|
338
338
|
}, { replyTo: ctx.messageId })
|
|
339
|
-
.catch(() =>
|
|
339
|
+
.catch((sendErr) => getLogger().warn('[clone] finalize failure notice send failed:', sendErr));
|
|
340
340
|
}
|
|
341
341
|
finally {
|
|
342
342
|
this.state = 'idle';
|