dsh-working-activity 0.3.2 → 0.4.0
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.i18n.yaml +2 -2
- package/README.md +4 -0
- package/README.zh.md +4 -0
- package/lib/client.js +2 -2
- package/lib/types/lang.d.ts +5 -0
- package/lib/types/lang.d.ts.map +1 -1
- package/lib/types/lang.js +2 -0
- package/lib/types/status.d.ts.map +1 -1
- package/lib/types/status.js +53 -15
- package/package.json +128 -127
- package/src/lang.ts +2 -0
- package/src/status.ts +66 -14
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/activity/working-activity/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 5ec920a3514e566f80d36b7952c1f9b6f9a06a5a
|
|
6
|
+
README.zh.md: 71f191268687d26345371877e54571950f17367b
|
package/README.md
CHANGED
|
@@ -38,6 +38,10 @@ inserting a second same-id row:
|
|
|
38
38
|
publishIntervalMs: 500
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
+
Host and TUI integration supports the DSH `0.1.0-rc.6` and `0.1.1-rc` lines,
|
|
42
|
+
plus `0.1.2-alpha.2`. The optional Web client still uses the rc client-runtime
|
|
43
|
+
contract and is not covered by alpha.2 compatibility.
|
|
44
|
+
|
|
41
45
|
## TUI usage
|
|
42
46
|
|
|
43
47
|
Install the plugin into a profile that composes the official `dsh-tui`, then
|
package/README.zh.md
CHANGED
package/lib/client.js
CHANGED
|
@@ -16,11 +16,11 @@ window.__ModuleLoader__.load({
|
|
|
16
16
|
document.head.appendChild(tag);
|
|
17
17
|
}
|
|
18
18
|
var WorkingLine_module_css_default = {
|
|
19
|
-
"working-pulse": "TG_uoa_working-pulse",
|
|
20
19
|
"tools": "TG_uoa_tools",
|
|
21
20
|
"line": "TG_uoa_line",
|
|
22
21
|
"text": "TG_uoa_text",
|
|
23
|
-
"marker": "TG_uoa_marker"
|
|
22
|
+
"marker": "TG_uoa_marker",
|
|
23
|
+
"working-pulse": "TG_uoa_working-pulse"
|
|
24
24
|
};
|
|
25
25
|
//#endregion
|
|
26
26
|
//#region src/client/WorkingLine.tsx
|
package/lib/types/lang.d.ts
CHANGED
|
@@ -62,6 +62,11 @@ declare const dict: {
|
|
|
62
62
|
readonly zh: "{{count}} 工具";
|
|
63
63
|
readonly en: "{{count}} tools";
|
|
64
64
|
};
|
|
65
|
+
/** Consecutive-tool streak badge (replaces the old flame emoji). */
|
|
66
|
+
readonly 'tool-streak': {
|
|
67
|
+
readonly zh: "工具x{{count}}";
|
|
68
|
+
readonly en: "tool x{{count}}";
|
|
69
|
+
};
|
|
65
70
|
/** Subagent count in the done summary. */
|
|
66
71
|
readonly 'subagent-count': {
|
|
67
72
|
readonly zh: "子代理 {{count}} 个";
|
package/lib/types/lang.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lang.d.ts","sourceRoot":"","sources":["../../src/lang.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAMH,MAAM,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAE9B,+DAA+D;AAC/D,eAAO,MAAM,KAAK,uBAAwB,CAAA;AAK1C,QAAA,MAAM,IAAI;;;;;IAQR,wCAAwC;;;;;;;;;IAGxC,2DAA2D;;;;;IAE3D,mEAAmE;;;;;IAEnE,+BAA+B;;;;;;;;;;;;;IAO/B,0CAA0C;;;;;IAE1C,0DAA0D;;;;;CAElD,CAAA;AAEV,MAAM,MAAM,OAAO,GAAG,MAAM,OAAO,IAAI,CAAA;AACvC,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;AAKxD,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAEzD;AAED,qCAAqC;AACrC,wBAAgB,OAAO,IAAI,IAAI,CAK9B;AAED,wEAAwE;AACxE,wBAAgB,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,UAAe,GAAG,MAAM,CAM/D;AAED,gDAAgD;AAChD,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,IAAI,GAAG,SAAS,CAmB/C;AAKD;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAWvC"}
|
|
1
|
+
{"version":3,"file":"lang.d.ts","sourceRoot":"","sources":["../../src/lang.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAMH,MAAM,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAE9B,+DAA+D;AAC/D,eAAO,MAAM,KAAK,uBAAwB,CAAA;AAK1C,QAAA,MAAM,IAAI;;;;;IAQR,wCAAwC;;;;;;;;;IAGxC,2DAA2D;;;;;IAE3D,mEAAmE;;;;;IAEnE,+BAA+B;;;;;;;;;;;;;IAO/B,oEAAoE;;;;;IAEpE,0CAA0C;;;;;IAE1C,0DAA0D;;;;;CAElD,CAAA;AAEV,MAAM,MAAM,OAAO,GAAG,MAAM,OAAO,IAAI,CAAA;AACvC,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;AAKxD,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAEzD;AAED,qCAAqC;AACrC,wBAAgB,OAAO,IAAI,IAAI,CAK9B;AAED,wEAAwE;AACxE,wBAAgB,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,UAAe,GAAG,MAAM,CAM/D;AAED,gDAAgD;AAChD,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,IAAI,GAAG,SAAS,CAmB/C;AAKD;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAWvC"}
|
package/lib/types/lang.js
CHANGED
|
@@ -50,6 +50,8 @@ const dict = {
|
|
|
50
50
|
},
|
|
51
51
|
'tool-count-one': { zh: '{{count}} 工具', en: '{{count}} tool' },
|
|
52
52
|
'tool-count-many': { zh: '{{count}} 工具', en: '{{count}} tools' },
|
|
53
|
+
/** Consecutive-tool streak badge (replaces the old flame emoji). */
|
|
54
|
+
'tool-streak': { zh: '工具x{{count}}', en: 'tool x{{count}}' },
|
|
53
55
|
/** Subagent count in the done summary. */
|
|
54
56
|
'subagent-count': { zh: '子代理 {{count}} 个', en: '{{count}} subagents' },
|
|
55
57
|
/** Work-reminder copy after `workRemindAt` turn-hours. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/status.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAQ5D,4CAA4C;AAC5C,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;AAE7E,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAA;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,wEAAwE;IACxE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,mEAAmE;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,2CAA2C;IAC3C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,4EAA4E;IAC5E,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,iEAAiE;IACjE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAChC;AAED,6EAA6E;AAC7E,MAAM,WAAW,SAAS;IACxB,0FAA0F;IAC1F,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,mCAAmC;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,oCAAoC;IACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,8CAA8C;IAC9C,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAChC;AAED,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,gEAAgE;IAChE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAA;IACnC,8DAA8D;IAC9D,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1C,qEAAqE;IACrE,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAA;IAChC,0DAA0D;IAC1D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAC/B;AAoCD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CA+BtH;AAED;;;;;GAKG;AACH,qBAAa,eAAe;IAmDxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;IApDjC,OAAO,CAAC,KAAK,CAAwB;IACrC,OAAO,CAAC,cAAc,CAAI;IAC1B,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,iBAAiB,CAAI;IAC7B,OAAO,CAAC,UAAU,CAAI;IACtB,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,SAAS,CAAI;IACrB,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,cAAc,CAAoB;IAC1C,OAAO,CAAC,eAAe,CAAI;IAC3B,OAAO,CAAC,iBAAiB,CAAQ;IACjC,yEAAyE;IACzE,OAAO,CAAC,YAAY,CAAsB;IAC1C,6EAA6E;IAC7E,OAAO,CAAC,WAAW,CAAI;IACvB,0EAA0E;IAC1E,OAAO,CAAC,YAAY,CAAK;IACzB,kEAAkE;IAClE,OAAO,CAAC,UAAU,CAAI;IACtB,8EAA8E;IAC9E,OAAO,CAAC,UAAU,CAAmB;IACrC,kEAAkE;IAClE,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,YAAY,CAAQ;IAC5B;+DAC2D;IAC3D,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,YAAY,CAAI;IACxB,oEAAoE;IACpE,OAAO,CAAC,SAAS,CAAoB;IACrC,4CAA4C;IAC5C,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,SAAS,CAAI;IACrB,uDAAuD;IACvD,OAAO,CAAC,aAAa,CAAI;IACzB,yCAAyC;IACzC,OAAO,CAAC,QAAQ,CAAQ;IACxB,mDAAmD;IACnD,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,cAAc,CAAI;IAE1B;;;;OAIG;gBAEgB,MAAM,EAAE,aAAa,EACrB,GAAG,GAAE,MAAM,MAAiB,EAC5B,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,YAAA;IAG9E,0CAA0C;IAC1C,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAc/C,wEAAwE;IACxE,aAAa,IAAI,IAAI;IAMrB,yDAAyD;IACzD,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IASpC,oEAAoE;IACpE,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAM1C,sEAAsE;IACtE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAI7C,iEAAiE;IACjE,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAgJzC,kEAAkE;IAClE,MAAM,CAAC,KAAK,GAAE,MAAmB,GAAG,aAAa;IA0DjD,2DAA2D;IAC3D,KAAK,IAAI,SAAS;IAQlB,OAAO,CAAC,cAAc;IA8DtB;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IA0BpB;oEACgE;IAChE,OAAO,CAAC,eAAe;IAgBvB,yEAAyE;IACzE,OAAO,CAAC,YAAY;IAIpB,wEAAwE;IACxE,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,WAAW;IAsBnB,6EAA6E;IAC7E,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,QAAQ;CAIjB;
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/status.ts"],"names":[],"mappings":"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"}
|
package/lib/types/status.js
CHANGED
|
@@ -353,7 +353,7 @@ export class ActivityTracker {
|
|
|
353
353
|
const git = tool.isGit
|
|
354
354
|
? (this.gitBranch !== undefined ? ` · git ${this.gitBranch}` : ' · git')
|
|
355
355
|
: '';
|
|
356
|
-
const combo = this.streak >= COMBO_SHOW_AT ? ` ·
|
|
356
|
+
const combo = this.streak >= COMBO_SHOW_AT ? ` · ${t('tool-streak', { count: this.streak })}` : '';
|
|
357
357
|
const narration = this.freshNarration(nowMs);
|
|
358
358
|
const line = narration === null
|
|
359
359
|
? `${fragment} · ${elapsed}${git}${combo}`
|
|
@@ -427,12 +427,12 @@ export class ActivityTracker {
|
|
|
427
427
|
const phrase = this.previousPhrase ?? (this.phase === 'waiting'
|
|
428
428
|
? waitingPhrase()
|
|
429
429
|
: this.livelyPhrase(thinkingMs, nowMs));
|
|
430
|
-
//
|
|
431
|
-
|
|
430
|
+
// The indicator animation (whale etc.) already signals activity, so the
|
|
431
|
+
// pi DOT_FRAMES ellipsis breathing is dropped for the DSH line.
|
|
432
432
|
const tps = this.tpsPrefix(nowMs);
|
|
433
433
|
return {
|
|
434
434
|
phase: this.phase,
|
|
435
|
-
line: `${tps}${phrase}
|
|
435
|
+
line: `${tps}${phrase} · ${elapsedLine}`,
|
|
436
436
|
phrase,
|
|
437
437
|
toolCount: this.toolCount,
|
|
438
438
|
turnElapsedMs: this.turnElapsedMs(nowMs),
|
|
@@ -511,7 +511,7 @@ export class ActivityTracker {
|
|
|
511
511
|
const { thinkingMs, toolMs, toolCount } = this.stats();
|
|
512
512
|
const tokens = this.turnTokens > 0 ? ` · 🔥 ${fmtTokens(this.turnTokens)}` : '';
|
|
513
513
|
const sub = this.subagentCount > 0 ? ` · ${t('subagent-count', { count: this.subagentCount })}` : '';
|
|
514
|
-
const combo = this.maxStreak >= COMBO_SHOW_AT ? ` ·
|
|
514
|
+
const combo = this.maxStreak >= COMBO_SHOW_AT ? ` · ${t('tool-streak', { count: this.maxStreak })}` : '';
|
|
515
515
|
const tools = t(toolCount === 1 ? 'tool-count-one' : 'tool-count-many', { count: toolCount });
|
|
516
516
|
const summary = t('done-summary', {
|
|
517
517
|
tools,
|
|
@@ -564,10 +564,6 @@ const COMBO_GAP_MS = 10_000;
|
|
|
564
564
|
const COMBO_SHOW_AT = 2;
|
|
565
565
|
/** The tps estimate stays fresh this long after the last chunk. */
|
|
566
566
|
const TPS_WINDOW_MS = 3500;
|
|
567
|
-
/** Render tick cadence (matches the TUI's 500ms activity timer). */
|
|
568
|
-
const TICK_MS = 500;
|
|
569
|
-
/** Ellipsis breathing frames appended to thinking lines (pi parity). */
|
|
570
|
-
const DOT_FRAMES = ['', ' ·', ' ··', ' ···', ' ··', ' ·'];
|
|
571
567
|
/** Cap on replayed done cards; older entries drop. */
|
|
572
568
|
const DONE_QUEUE_MAX = 6;
|
|
573
569
|
/** Show the last tool's fragment in the done line for this long after it ends. */
|
|
@@ -576,15 +572,57 @@ const DONE_FRAGMENT_MS = 3000;
|
|
|
576
572
|
const STREAM_BUFFER_CHARS = 300;
|
|
577
573
|
/** A narration stays visible this long after the stream went quiet. */
|
|
578
574
|
const NARRATE_GRACE_MS = 5000;
|
|
575
|
+
/** Narration budget in display columns: 40 CJK chars ≈ 12 English words. */
|
|
576
|
+
const NARRATION_MAX_COLUMNS = 80;
|
|
577
|
+
/** A CJK/full-width code point renders 2 terminal columns; the rest render 1. */
|
|
578
|
+
function isWide(cp) {
|
|
579
|
+
return ((cp >= 0x1100 && cp <= 0x115f) || // Hangul Jamo
|
|
580
|
+
(cp >= 0x2e80 && cp <= 0xa4cf) || // CJK radicals, kana, Yi
|
|
581
|
+
(cp >= 0xac00 && cp <= 0xd7a3) || // Hangul syllables
|
|
582
|
+
(cp >= 0xf900 && cp <= 0xfaff) || // CJK compatibility ideographs
|
|
583
|
+
(cp >= 0xfe30 && cp <= 0xfe4f) || // CJK compatibility forms
|
|
584
|
+
(cp >= 0xff00 && cp <= 0xff60) || // full-width forms
|
|
585
|
+
(cp >= 0xffe0 && cp <= 0xffe6) || // full-width signs
|
|
586
|
+
(cp >= 0x20000 && cp <= 0x3fffd) // CJK extensions
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
/** Cut before `max` columns, backing off to the last word or clause boundary. */
|
|
590
|
+
function cutToWidth(text, max) {
|
|
591
|
+
let width = 0;
|
|
592
|
+
let cut = text.length;
|
|
593
|
+
const chars = [...text];
|
|
594
|
+
for (let i = 0; i < chars.length; i++) {
|
|
595
|
+
const w = isWide(chars[i].codePointAt(0)) ? 2 : 1;
|
|
596
|
+
if (width + w > max) {
|
|
597
|
+
cut = chars.slice(0, i).join('').length;
|
|
598
|
+
break;
|
|
599
|
+
}
|
|
600
|
+
width += w;
|
|
601
|
+
}
|
|
602
|
+
if (cut === text.length)
|
|
603
|
+
return text;
|
|
604
|
+
// Back off to a soft boundary so English words survive intact; dense CJK has
|
|
605
|
+
// none and hard-cuts at the budget like the original fixed 40-char capture.
|
|
606
|
+
const head = text.slice(0, cut);
|
|
607
|
+
const soft = Math.max(head.lastIndexOf(' '), head.lastIndexOf('\t'), head.lastIndexOf(','), head.lastIndexOf('、'), head.lastIndexOf(';'), head.lastIndexOf(';'), head.lastIndexOf(','));
|
|
608
|
+
return soft > 0 ? head.slice(0, soft) : head;
|
|
609
|
+
}
|
|
579
610
|
/** Extract the latest `⏵` self-narration line from a stream buffer. */
|
|
580
611
|
export function extractNarration(buffer) {
|
|
581
|
-
const matches = [...buffer.matchAll(
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
const latest = matches[matches.length - 1]?.[1];
|
|
585
|
-
if (latest === undefined)
|
|
612
|
+
const matches = [...buffer.matchAll(/⏵[ \t]*([^\n⏵]*)/g)];
|
|
613
|
+
const latest = matches[matches.length - 1]?.[1]?.trim();
|
|
614
|
+
if (!latest)
|
|
586
615
|
return null;
|
|
587
|
-
|
|
616
|
+
// A missing newline must not turn the rest of the response into status text.
|
|
617
|
+
// Stop at sentence ends and clause delimiters, while leaving dotted
|
|
618
|
+
// identifiers such as `ink.tsx`, `agent.ctx` and `README.MD` intact. A dot
|
|
619
|
+
// ends a sentence only before whitespace, the end, or a Title-case word
|
|
620
|
+
// (`safely.The`); dot-uppercase-uppercase stays an extension (`.MD`).
|
|
621
|
+
const boundary = latest.search(/[。.!?!?;;]|\.(?=\s|$|[A-Z][a-z])/);
|
|
622
|
+
const sentence = boundary < 0 ? latest : latest.slice(0, boundary + 1);
|
|
623
|
+
// The budget is display width, so English and Chinese render equally long:
|
|
624
|
+
// 40 CJK characters and ~12 English words share the same line budget.
|
|
625
|
+
const text = cutToWidth(sentence, NARRATION_MAX_COLUMNS).replace(/[。..!!,,、;;]+$/, '').trim();
|
|
588
626
|
return text.length === 0 ? null : text;
|
|
589
627
|
}
|
|
590
628
|
/** Format a token count compactly (`12.3k`, `1.2M`). */
|
package/package.json
CHANGED
|
@@ -1,127 +1,128 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dsh-working-activity",
|
|
3
|
-
"description": "Live model working-status line: playful copy, running tool, turn elapsed — for TUI prompt and Web UI",
|
|
4
|
-
"version": "0.
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "lib/types/index.js",
|
|
7
|
-
"types": "lib/types/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"types": "./lib/types/index.d.ts",
|
|
11
|
-
"default": "./lib/types/index.js"
|
|
12
|
-
},
|
|
13
|
-
"./client": {
|
|
14
|
-
"types": "./lib/types/client/index.d.ts",
|
|
15
|
-
"default": "./lib/client.js"
|
|
16
|
-
},
|
|
17
|
-
"./config": {
|
|
18
|
-
"types": "./lib/types/config.d.ts",
|
|
19
|
-
"default": "./lib/types/config.js"
|
|
20
|
-
},
|
|
21
|
-
"./events": {
|
|
22
|
-
"types": "./lib/types/events.d.ts",
|
|
23
|
-
"default": "./lib/types/events.js"
|
|
24
|
-
},
|
|
25
|
-
"./frames": {
|
|
26
|
-
"types": "./lib/types/frames.d.ts",
|
|
27
|
-
"default": "./lib/types/frames.js"
|
|
28
|
-
},
|
|
29
|
-
"./invariant": {
|
|
30
|
-
"types": "./lib/types/invariant.d.ts",
|
|
31
|
-
"default": "./lib/types/invariant.js"
|
|
32
|
-
},
|
|
33
|
-
"./status": {
|
|
34
|
-
"types": "./lib/types/status.d.ts",
|
|
35
|
-
"default": "./lib/types/status.js"
|
|
36
|
-
},
|
|
37
|
-
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
38
|
-
"./src/*": "./src/*",
|
|
39
|
-
"./package.json": "./package.json"
|
|
40
|
-
},
|
|
41
|
-
"files": [
|
|
42
|
-
"lib",
|
|
43
|
-
"src",
|
|
44
|
-
"cordis.patch.yml"
|
|
45
|
-
],
|
|
46
|
-
"engines": {
|
|
47
|
-
"node": "^22.19 || >=24"
|
|
48
|
-
},
|
|
49
|
-
"scripts": {
|
|
50
|
-
"build": "tsc -p tsconfig.json && tsc -p tsconfig.client.json",
|
|
51
|
-
"build:client": "tsdown -c tsdown.config.ts",
|
|
52
|
-
"test": "vitest run",
|
|
53
|
-
"
|
|
54
|
-
"verify:
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
"
|
|
73
|
-
|
|
74
|
-
"@deepseek-ai/dsh-client-
|
|
75
|
-
"@deepseek-ai/dsh-client-ui-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
"@deepseek-ai/
|
|
82
|
-
"@deepseek-ai/dsh-
|
|
83
|
-
"@deepseek-ai/dsh-client-
|
|
84
|
-
"@deepseek-ai/dsh-client-ui-
|
|
85
|
-
"@deepseek-ai/dsh-
|
|
86
|
-
"@deepseek-ai/dsh-
|
|
87
|
-
"@deepseek-ai/dsh-
|
|
88
|
-
"@deepseek-ai/
|
|
89
|
-
"
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"@deepseek-ai/
|
|
94
|
-
"@deepseek-ai/dsh-agent
|
|
95
|
-
"@deepseek-ai/dsh-agent-loop
|
|
96
|
-
"@deepseek-ai/dsh-
|
|
97
|
-
"@deepseek-ai/dsh-client-
|
|
98
|
-
"@deepseek-ai/dsh-client-ui-
|
|
99
|
-
"@deepseek-ai/dsh-
|
|
100
|
-
"@deepseek-ai/dsh-
|
|
101
|
-
"@deepseek-ai/dsh-
|
|
102
|
-
"@deepseek-ai/dsh-
|
|
103
|
-
"@deepseek-ai/dsh-
|
|
104
|
-
"@deepseek-ai/
|
|
105
|
-
"@
|
|
106
|
-
"@types/
|
|
107
|
-
"
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"
|
|
111
|
-
"
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-working-activity",
|
|
3
|
+
"description": "Live model working-status line: playful copy, running tool, turn elapsed — for TUI prompt and Web UI",
|
|
4
|
+
"version": "0.4.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/types/index.js",
|
|
7
|
+
"types": "lib/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/types/index.d.ts",
|
|
11
|
+
"default": "./lib/types/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./client": {
|
|
14
|
+
"types": "./lib/types/client/index.d.ts",
|
|
15
|
+
"default": "./lib/client.js"
|
|
16
|
+
},
|
|
17
|
+
"./config": {
|
|
18
|
+
"types": "./lib/types/config.d.ts",
|
|
19
|
+
"default": "./lib/types/config.js"
|
|
20
|
+
},
|
|
21
|
+
"./events": {
|
|
22
|
+
"types": "./lib/types/events.d.ts",
|
|
23
|
+
"default": "./lib/types/events.js"
|
|
24
|
+
},
|
|
25
|
+
"./frames": {
|
|
26
|
+
"types": "./lib/types/frames.d.ts",
|
|
27
|
+
"default": "./lib/types/frames.js"
|
|
28
|
+
},
|
|
29
|
+
"./invariant": {
|
|
30
|
+
"types": "./lib/types/invariant.d.ts",
|
|
31
|
+
"default": "./lib/types/invariant.js"
|
|
32
|
+
},
|
|
33
|
+
"./status": {
|
|
34
|
+
"types": "./lib/types/status.d.ts",
|
|
35
|
+
"default": "./lib/types/status.js"
|
|
36
|
+
},
|
|
37
|
+
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
38
|
+
"./src/*": "./src/*",
|
|
39
|
+
"./package.json": "./package.json"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"lib",
|
|
43
|
+
"src",
|
|
44
|
+
"cordis.patch.yml"
|
|
45
|
+
],
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": "^22.19 || >=24"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "tsc -p tsconfig.json && tsc -p tsconfig.client.json",
|
|
51
|
+
"build:client": "tsdown -c tsdown.config.ts",
|
|
52
|
+
"test": "vitest run",
|
|
53
|
+
"test:alpha2": "pnpm run build && pnpm --dir ../working-activity-alpha2-compat install --frozen-lockfile --strict-peer-dependencies && pnpm --dir ../working-activity-alpha2-compat test",
|
|
54
|
+
"verify:deps": "node scripts/verify-manifest-deps.mjs",
|
|
55
|
+
"verify:lockfiles": "node scripts/verify-lockfiles.mjs",
|
|
56
|
+
"prepublishOnly": "npm run verify:deps && npm run verify:lockfiles && npm run build && npm run build:client"
|
|
57
|
+
},
|
|
58
|
+
"license": "BSD-3-Clause",
|
|
59
|
+
"repository": {
|
|
60
|
+
"type": "git",
|
|
61
|
+
"url": "git+https://github.com/ccch1mneyyy/working-activity.git"
|
|
62
|
+
},
|
|
63
|
+
"bugs": {
|
|
64
|
+
"url": "https://github.com/ccch1mneyyy/working-activity/issues"
|
|
65
|
+
},
|
|
66
|
+
"homepage": "https://github.com/ccch1mneyyy/working-activity#readme",
|
|
67
|
+
"dsh": {
|
|
68
|
+
"bundle": {
|
|
69
|
+
"patch": "./cordis.patch.yml"
|
|
70
|
+
},
|
|
71
|
+
"client": {
|
|
72
|
+
"platform": "web",
|
|
73
|
+
"inject": [
|
|
74
|
+
"@deepseek-ai/dsh-client-runtime",
|
|
75
|
+
"@deepseek-ai/dsh-client-ui-conversation",
|
|
76
|
+
"@deepseek-ai/dsh-client-ui-slots"
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"peerDependencies": {
|
|
81
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
82
|
+
"@deepseek-ai/dsh-agent": "^0.1.0-rc.6 || ^0.1.1-rc.1 || ^0.1.2-alpha.2",
|
|
83
|
+
"@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
|
|
84
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6",
|
|
85
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
|
|
86
|
+
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.6 || ^0.1.1-rc.1 || ^0.1.2-alpha.2",
|
|
87
|
+
"@deepseek-ai/dsh-session": "^0.1.0-rc.6 || ^0.1.1-rc.1 || ^0.1.2-alpha.2",
|
|
88
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6 || ^0.1.1-rc.1 || ^0.1.2-alpha.2",
|
|
89
|
+
"@deepseek-ai/schemastery": "^3.18.1",
|
|
90
|
+
"react": "^18.2.0"
|
|
91
|
+
},
|
|
92
|
+
"devDependencies": {
|
|
93
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
94
|
+
"@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
|
|
95
|
+
"@deepseek-ai/dsh-agent-loop": "^0.1.0-rc.6",
|
|
96
|
+
"@deepseek-ai/dsh-agent-loop-testkit": "^0.1.0-rc.6",
|
|
97
|
+
"@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
|
|
98
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6",
|
|
99
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
|
|
100
|
+
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.6",
|
|
101
|
+
"@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
|
|
102
|
+
"@deepseek-ai/dsh-session": "^0.1.0-rc.6",
|
|
103
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
|
|
104
|
+
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
|
|
105
|
+
"@deepseek-ai/schemastery": "^3.18.1",
|
|
106
|
+
"@types/node": "^22.0.0",
|
|
107
|
+
"@types/react": "~18.3.1",
|
|
108
|
+
"lightningcss": "^1.32.0",
|
|
109
|
+
"react": "^18.2.0",
|
|
110
|
+
"tsdown": "^0.22.2",
|
|
111
|
+
"typescript": "^6.0.3",
|
|
112
|
+
"vitest": "^3.2.4"
|
|
113
|
+
},
|
|
114
|
+
"peerDependenciesMeta": {
|
|
115
|
+
"@deepseek-ai/dsh-client-runtime": {
|
|
116
|
+
"optional": true
|
|
117
|
+
},
|
|
118
|
+
"@deepseek-ai/dsh-client-ui-conversation": {
|
|
119
|
+
"optional": true
|
|
120
|
+
},
|
|
121
|
+
"@deepseek-ai/dsh-client-ui-slots": {
|
|
122
|
+
"optional": true
|
|
123
|
+
},
|
|
124
|
+
"react": {
|
|
125
|
+
"optional": true
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
package/src/lang.ts
CHANGED
|
@@ -57,6 +57,8 @@ const dict = {
|
|
|
57
57
|
},
|
|
58
58
|
'tool-count-one': { zh: '{{count}} 工具', en: '{{count}} tool' },
|
|
59
59
|
'tool-count-many': { zh: '{{count}} 工具', en: '{{count}} tools' },
|
|
60
|
+
/** Consecutive-tool streak badge (replaces the old flame emoji). */
|
|
61
|
+
'tool-streak': { zh: '工具x{{count}}', en: 'tool x{{count}}' },
|
|
60
62
|
/** Subagent count in the done summary. */
|
|
61
63
|
'subagent-count': { zh: '子代理 {{count}} 个', en: '{{count}} subagents' },
|
|
62
64
|
/** Work-reminder copy after `workRemindAt` turn-hours. */
|
package/src/status.ts
CHANGED
|
@@ -432,7 +432,7 @@ export class ActivityTracker {
|
|
|
432
432
|
const git = tool.isGit
|
|
433
433
|
? (this.gitBranch !== undefined ? ` · git ${this.gitBranch}` : ' · git')
|
|
434
434
|
: ''
|
|
435
|
-
const combo = this.streak >= COMBO_SHOW_AT ? ` ·
|
|
435
|
+
const combo = this.streak >= COMBO_SHOW_AT ? ` · ${t('tool-streak', { count: this.streak })}` : ''
|
|
436
436
|
const narration = this.freshNarration(nowMs)
|
|
437
437
|
const line = narration === null
|
|
438
438
|
? `${fragment} · ${elapsed}${git}${combo}`
|
|
@@ -507,12 +507,12 @@ export class ActivityTracker {
|
|
|
507
507
|
const phrase = this.previousPhrase ?? (this.phase === 'waiting'
|
|
508
508
|
? waitingPhrase()
|
|
509
509
|
: this.livelyPhrase(thinkingMs, nowMs))
|
|
510
|
-
//
|
|
511
|
-
|
|
510
|
+
// The indicator animation (whale etc.) already signals activity, so the
|
|
511
|
+
// pi DOT_FRAMES ellipsis breathing is dropped for the DSH line.
|
|
512
512
|
const tps = this.tpsPrefix(nowMs)
|
|
513
513
|
return {
|
|
514
514
|
phase: this.phase,
|
|
515
|
-
line: `${tps}${phrase}
|
|
515
|
+
line: `${tps}${phrase} · ${elapsedLine}`,
|
|
516
516
|
phrase,
|
|
517
517
|
toolCount: this.toolCount,
|
|
518
518
|
turnElapsedMs: this.turnElapsedMs(nowMs),
|
|
@@ -598,7 +598,7 @@ export class ActivityTracker {
|
|
|
598
598
|
const { thinkingMs, toolMs, toolCount } = this.stats()
|
|
599
599
|
const tokens = this.turnTokens > 0 ? ` · 🔥 ${fmtTokens(this.turnTokens)}` : ''
|
|
600
600
|
const sub = this.subagentCount > 0 ? ` · ${t('subagent-count', { count: this.subagentCount })}` : ''
|
|
601
|
-
const combo = this.maxStreak >= COMBO_SHOW_AT ? ` ·
|
|
601
|
+
const combo = this.maxStreak >= COMBO_SHOW_AT ? ` · ${t('tool-streak', { count: this.maxStreak })}` : ''
|
|
602
602
|
const tools = t(toolCount === 1 ? 'tool-count-one' : 'tool-count-many', { count: toolCount })
|
|
603
603
|
const summary = t('done-summary', {
|
|
604
604
|
tools,
|
|
@@ -653,10 +653,6 @@ const COMBO_GAP_MS = 10_000
|
|
|
653
653
|
const COMBO_SHOW_AT = 2
|
|
654
654
|
/** The tps estimate stays fresh this long after the last chunk. */
|
|
655
655
|
const TPS_WINDOW_MS = 3500
|
|
656
|
-
/** Render tick cadence (matches the TUI's 500ms activity timer). */
|
|
657
|
-
const TICK_MS = 500
|
|
658
|
-
/** Ellipsis breathing frames appended to thinking lines (pi parity). */
|
|
659
|
-
const DOT_FRAMES = ['', ' ·', ' ··', ' ···', ' ··', ' ·']
|
|
660
656
|
/** Cap on replayed done cards; older entries drop. */
|
|
661
657
|
const DONE_QUEUE_MAX = 6
|
|
662
658
|
/** Show the last tool's fragment in the done line for this long after it ends. */
|
|
@@ -666,13 +662,69 @@ const STREAM_BUFFER_CHARS = 300
|
|
|
666
662
|
/** A narration stays visible this long after the stream went quiet. */
|
|
667
663
|
const NARRATE_GRACE_MS = 5000
|
|
668
664
|
|
|
665
|
+
/** Narration budget in display columns: 40 CJK chars ≈ 12 English words. */
|
|
666
|
+
const NARRATION_MAX_COLUMNS = 80
|
|
667
|
+
|
|
668
|
+
/** A CJK/full-width code point renders 2 terminal columns; the rest render 1. */
|
|
669
|
+
function isWide(cp: number): boolean {
|
|
670
|
+
return (
|
|
671
|
+
(cp >= 0x1100 && cp <= 0x115f) || // Hangul Jamo
|
|
672
|
+
(cp >= 0x2e80 && cp <= 0xa4cf) || // CJK radicals, kana, Yi
|
|
673
|
+
(cp >= 0xac00 && cp <= 0xd7a3) || // Hangul syllables
|
|
674
|
+
(cp >= 0xf900 && cp <= 0xfaff) || // CJK compatibility ideographs
|
|
675
|
+
(cp >= 0xfe30 && cp <= 0xfe4f) || // CJK compatibility forms
|
|
676
|
+
(cp >= 0xff00 && cp <= 0xff60) || // full-width forms
|
|
677
|
+
(cp >= 0xffe0 && cp <= 0xffe6) || // full-width signs
|
|
678
|
+
(cp >= 0x20000 && cp <= 0x3fffd) // CJK extensions
|
|
679
|
+
)
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/** Cut before `max` columns, backing off to the last word or clause boundary. */
|
|
683
|
+
function cutToWidth(text: string, max: number): string {
|
|
684
|
+
let width = 0
|
|
685
|
+
let cut = text.length
|
|
686
|
+
const chars = [...text]
|
|
687
|
+
for (let i = 0; i < chars.length; i++) {
|
|
688
|
+
const w = isWide(chars[i]!.codePointAt(0)!) ? 2 : 1
|
|
689
|
+
if (width + w > max) {
|
|
690
|
+
cut = chars.slice(0, i).join('').length
|
|
691
|
+
break
|
|
692
|
+
}
|
|
693
|
+
width += w
|
|
694
|
+
}
|
|
695
|
+
if (cut === text.length) return text
|
|
696
|
+
// Back off to a soft boundary so English words survive intact; dense CJK has
|
|
697
|
+
// none and hard-cuts at the budget like the original fixed 40-char capture.
|
|
698
|
+
const head = text.slice(0, cut)
|
|
699
|
+
const soft = Math.max(
|
|
700
|
+
head.lastIndexOf(' '),
|
|
701
|
+
head.lastIndexOf('\t'),
|
|
702
|
+
head.lastIndexOf(','),
|
|
703
|
+
head.lastIndexOf('、'),
|
|
704
|
+
head.lastIndexOf(';'),
|
|
705
|
+
head.lastIndexOf(';'),
|
|
706
|
+
head.lastIndexOf(','),
|
|
707
|
+
)
|
|
708
|
+
return soft > 0 ? head.slice(0, soft) : head
|
|
709
|
+
}
|
|
710
|
+
|
|
669
711
|
/** Extract the latest `⏵` self-narration line from a stream buffer. */
|
|
670
712
|
export function extractNarration(buffer: string): string | null {
|
|
671
|
-
const matches = [...buffer.matchAll(
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
713
|
+
const matches = [...buffer.matchAll(/⏵[ \t]*([^\n⏵]*)/g)]
|
|
714
|
+
const latest = matches[matches.length - 1]?.[1]?.trim()
|
|
715
|
+
if (!latest) return null
|
|
716
|
+
|
|
717
|
+
// A missing newline must not turn the rest of the response into status text.
|
|
718
|
+
// Stop at sentence ends and clause delimiters, while leaving dotted
|
|
719
|
+
// identifiers such as `ink.tsx`, `agent.ctx` and `README.MD` intact. A dot
|
|
720
|
+
// ends a sentence only before whitespace, the end, or a Title-case word
|
|
721
|
+
// (`safely.The`); dot-uppercase-uppercase stays an extension (`.MD`).
|
|
722
|
+
const boundary = latest.search(/[。.!?!?;;]|\.(?=\s|$|[A-Z][a-z])/)
|
|
723
|
+
const sentence = boundary < 0 ? latest : latest.slice(0, boundary + 1)
|
|
724
|
+
|
|
725
|
+
// The budget is display width, so English and Chinese render equally long:
|
|
726
|
+
// 40 CJK characters and ~12 English words share the same line budget.
|
|
727
|
+
const text = cutToWidth(sentence, NARRATION_MAX_COLUMNS).replace(/[。..!!,,、;;]+$/, '').trim()
|
|
676
728
|
return text.length === 0 ? null : text
|
|
677
729
|
}
|
|
678
730
|
|