@dsh-workbench/shared 0.3.5 → 0.3.7

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.
Files changed (153) hide show
  1. package/dist/api/context-ref.d.ts +0 -12
  2. package/dist/api/context-ref.js +0 -40
  3. package/dist/api/facts.d.ts +0 -6
  4. package/dist/api/facts.js +0 -8
  5. package/dist/api/long-task.d.ts +33 -4
  6. package/dist/api/long-task.js +34 -2
  7. package/dist/components/ConfirmBar.css +26 -0
  8. package/dist/components/ConfirmBar.d.ts +36 -0
  9. package/dist/components/ConfirmBar.js +26 -0
  10. package/dist/components/Form.d.ts +7 -5
  11. package/dist/components/Form.js +5 -3
  12. package/dist/components/FormNodes.d.ts +17 -13
  13. package/dist/components/FormNodes.js +13 -5
  14. package/dist/components/FormRows.css +31 -0
  15. package/dist/components/FormTypes.d.ts +39 -14
  16. package/dist/components/LongTaskRow.css +52 -0
  17. package/dist/components/LongTaskRow.d.ts +18 -2
  18. package/dist/components/LongTaskRow.js +33 -5
  19. package/dist/components/MockStrip.css +11 -1
  20. package/dist/components/StateDot.d.ts +5 -0
  21. package/dist/components/StateDot.js +10 -0
  22. package/dist/config/constants.d.ts +2 -0
  23. package/dist/config/constants.js +2 -0
  24. package/dist/host/__tests__/fakes.d.ts +41 -0
  25. package/dist/host/__tests__/fakes.js +76 -0
  26. package/dist/host/__tests__/preflight-fixtures.d.ts +19 -0
  27. package/dist/host/__tests__/preflight-fixtures.js +47 -0
  28. package/dist/host/board-fact.d.ts +8 -0
  29. package/dist/host/board-fact.js +16 -0
  30. package/dist/host/browser-read.js +2 -1
  31. package/dist/host/context-inject.d.ts +24 -0
  32. package/dist/host/context-inject.js +74 -0
  33. package/dist/host/context-ref.d.ts +13 -0
  34. package/dist/host/context-ref.js +41 -0
  35. package/dist/host/diy-debug.d.ts +80 -0
  36. package/dist/host/diy-debug.js +88 -0
  37. package/dist/host/diy-record.d.ts +135 -0
  38. package/dist/host/diy-record.js +162 -0
  39. package/dist/host/events.d.ts +9 -0
  40. package/dist/host/events.js +70 -0
  41. package/dist/host/facts.d.ts +6 -0
  42. package/dist/host/facts.js +9 -0
  43. package/dist/host/git.js +1 -1
  44. package/dist/host/http.d.ts +2 -2
  45. package/dist/host/http.js +3 -3
  46. package/dist/host/long-task.d.ts +12 -0
  47. package/dist/host/long-task.js +34 -5
  48. package/dist/host/mount-units.d.ts +52 -0
  49. package/dist/host/mount-units.js +186 -0
  50. package/dist/host/opencli-runtime.js +1 -1
  51. package/dist/host/opencli-window.js +1 -1
  52. package/dist/host/opencli.js +2 -1
  53. package/dist/host/panel-state.d.ts +120 -0
  54. package/dist/host/panel-state.js +176 -0
  55. package/dist/host/plugin-source.js +1 -1
  56. package/dist/host/preflight.d.ts +58 -0
  57. package/dist/host/preflight.js +233 -0
  58. package/dist/host/probe-cache.d.ts +6 -0
  59. package/dist/host/probe-cache.js +19 -0
  60. package/dist/host/probe-libs.d.ts +45 -0
  61. package/dist/host/probe-libs.js +61 -0
  62. package/dist/host/probe-units.d.ts +17 -0
  63. package/dist/host/probe-units.js +102 -0
  64. package/dist/host/probe-verdict.d.ts +7 -0
  65. package/dist/host/probe-verdict.js +143 -0
  66. package/dist/host/shell-text.d.ts +13 -0
  67. package/dist/host/shell-text.js +20 -0
  68. package/dist/host/tool-approval.d.ts +1 -0
  69. package/dist/host/tool-scope.d.ts +32 -0
  70. package/dist/host/tool-scope.js +84 -0
  71. package/dist/host/unit-declaration.d.ts +65 -0
  72. package/dist/host/unit-declaration.js +213 -0
  73. package/dist/host/unit-face.d.ts +1 -0
  74. package/dist/host/unit-readiness.d.ts +7 -0
  75. package/dist/host/unit-readiness.js +5 -0
  76. package/dist/host/unit-registry.d.ts +9 -0
  77. package/dist/host/unit-registry.js +33 -0
  78. package/dist/host/version-range.d.ts +2 -0
  79. package/dist/host/version-range.js +73 -0
  80. package/dist/host.d.ts +7 -4
  81. package/dist/host.js +7 -4
  82. package/dist/i18n/en.js +6 -0
  83. package/dist/i18n/index.d.ts +7 -1
  84. package/dist/i18n/zh.d.ts +6 -0
  85. package/dist/i18n/zh.js +6 -0
  86. package/dist/index.d.ts +1 -4
  87. package/dist/index.js +1 -4
  88. package/dist/lib/board-fact.d.ts +0 -7
  89. package/dist/lib/board-fact.js +0 -15
  90. package/dist/lib/diy-record.d.ts +38 -1
  91. package/dist/lib/diy-record.js +66 -0
  92. package/dist/lib/text.d.ts +0 -13
  93. package/dist/lib/text.js +0 -20
  94. package/dist/testing/declaration.js +1 -1
  95. package/package.json +1 -1
  96. package/src/api/__tests__/facts.test.ts +0 -13
  97. package/src/api/__tests__/long-task.test.ts +41 -1
  98. package/src/api/context-ref.ts +0 -39
  99. package/src/api/facts.ts +0 -9
  100. package/src/api/long-task.ts +46 -4
  101. package/src/components/ConfirmBar.css +26 -0
  102. package/src/components/ConfirmBar.test.tsx +130 -0
  103. package/src/components/ConfirmBar.tsx +63 -0
  104. package/src/components/Form.test.tsx +15 -0
  105. package/src/components/Form.tsx +7 -5
  106. package/src/components/FormNodes.tsx +50 -26
  107. package/src/components/FormRows.css +31 -0
  108. package/src/components/FormRows.test.tsx +71 -1
  109. package/src/components/FormTypes.test.ts +31 -0
  110. package/src/components/FormTypes.ts +46 -15
  111. package/src/components/FormWiring.test.tsx +1 -0
  112. package/src/components/LongTaskRow.css +52 -0
  113. package/src/components/LongTaskRow.tsx +59 -4
  114. package/src/components/__tests__/long-task-row.test.ts +115 -0
  115. package/src/config/constants.ts +3 -0
  116. package/src/host/__tests__/board-fact.test.ts +47 -0
  117. package/src/{lib → host/__tests__}/diy-debug.test.ts +1 -1
  118. package/src/{lib → host/__tests__}/diy-record.test.ts +137 -1
  119. package/src/host/__tests__/facts.test.ts +13 -0
  120. package/src/host/__tests__/long-task.test.ts +306 -0
  121. package/src/{lib → host/__tests__}/panel-state.test.ts +1 -1
  122. package/src/host/__tests__/preflight-route.test.ts +33 -0
  123. package/src/host/__tests__/shell-text.test.ts +44 -0
  124. package/src/host/board-fact.ts +14 -0
  125. package/src/host/browser-read.ts +2 -1
  126. package/src/host/context-ref.ts +40 -0
  127. package/src/{lib → host}/diy-record.ts +95 -1
  128. package/src/host/facts.ts +10 -0
  129. package/src/host/git.ts +1 -1
  130. package/src/host/http.ts +4 -4
  131. package/src/host/long-task.ts +52 -7
  132. package/src/host/opencli-runtime.ts +1 -1
  133. package/src/host/opencli-window.ts +1 -1
  134. package/src/host/opencli.ts +2 -1
  135. package/src/host/plugin-source.ts +1 -1
  136. package/src/host/shell-text.ts +21 -0
  137. package/src/host/tool-approval.ts +1 -0
  138. package/src/{api → host}/unit-declaration.ts +1 -1
  139. package/src/host/unit-face.ts +1 -0
  140. package/src/host.ts +7 -4
  141. package/src/i18n/en.ts +7 -0
  142. package/src/i18n/zh.ts +6 -0
  143. package/src/index.ts +1 -4
  144. package/src/lib/board-fact.test.ts +1 -33
  145. package/src/lib/board-fact.ts +0 -13
  146. package/src/lib/text.test.ts +1 -43
  147. package/src/lib/text.ts +0 -22
  148. package/src/testing/declaration.ts +1 -1
  149. package/dist/lib/lint-probe.d.ts +0 -1
  150. package/dist/lib/lint-probe.js +0 -6
  151. /package/src/{api → host}/__tests__/unit-declaration.test.ts +0 -0
  152. /package/src/{lib → host}/diy-debug.ts +0 -0
  153. /package/src/{lib → host}/panel-state.ts +0 -0
@@ -0,0 +1,73 @@
1
+ import { compareVersions } from './release';
2
+ function readable(version) {
3
+ return compareVersions(version, '0.0.0') !== undefined;
4
+ }
5
+ function segmentsOf(version) {
6
+ if (!readable(version))
7
+ return undefined;
8
+ return version.split('.').map((part) => Number.parseInt(part, 10));
9
+ }
10
+ function caretUpper(base) {
11
+ const [major = 0, minor = 0, patch = 0] = base;
12
+ if (major > 0)
13
+ return `${major + 1}.0.0`;
14
+ return minor > 0 ? `0.${minor + 1}.0` : `0.0.${patch + 1}`;
15
+ }
16
+ function tildeUpper(base) {
17
+ const [major = 0, minor = 0] = base;
18
+ return `${major}.${minor + 1}.0`;
19
+ }
20
+ function comparator(token, version) {
21
+ const match = /^(>=|<=|>|<|=|\^|~)?\s*(.+)$/.exec(token.trim());
22
+ if (match === null)
23
+ return undefined;
24
+ const [, operator = '', raw = ''] = match;
25
+ const base = segmentsOf(raw.trim());
26
+ if (base === undefined)
27
+ return undefined;
28
+ const at = (other) => compareVersions(version, other);
29
+ switch (operator) {
30
+ case '^':
31
+ return (at(raw) ?? -1) >= 0 && (at(caretUpper(base)) ?? 1) < 0;
32
+ case '~':
33
+ return (at(raw) ?? -1) >= 0 && (at(tildeUpper(base)) ?? 1) < 0;
34
+ default:
35
+ break;
36
+ }
37
+ const compared = at(raw.trim());
38
+ if (compared === undefined)
39
+ return undefined;
40
+ switch (operator) {
41
+ case '>=':
42
+ return compared >= 0;
43
+ case '<=':
44
+ return compared <= 0;
45
+ case '>':
46
+ return compared > 0;
47
+ case '<':
48
+ return compared < 0;
49
+ case '=':
50
+ case '':
51
+ return compared === 0;
52
+ default:
53
+ return undefined;
54
+ }
55
+ }
56
+ export function checkVersionRange(contract, version) {
57
+ const spec = contract?.trim() ?? '';
58
+ if (spec === '')
59
+ return 'satisfied';
60
+ if (!readable(version))
61
+ return 'malformed';
62
+ const tokens = spec.split(/\s+/).filter((token) => token !== '');
63
+ if (tokens.length === 0)
64
+ return 'satisfied';
65
+ for (const token of tokens) {
66
+ const verdict = comparator(token, version);
67
+ if (verdict === undefined)
68
+ return 'malformed';
69
+ if (!verdict)
70
+ return 'unsatisfied';
71
+ }
72
+ return 'satisfied';
73
+ }
package/dist/host.d.ts CHANGED
@@ -1,20 +1,20 @@
1
1
  export * from './config/constants.js';
2
2
  export * from './api/context-ref.js';
3
3
  export * from './api/unit.js';
4
- export * from './api/unit-declaration.js';
5
4
  export * from './api/facts.js';
6
5
  export * from './api/long-task.js';
7
6
  export * from './lib/text.js';
8
7
  export * from './lib/ui.js';
9
- export * from './lib/panel-state.js';
10
8
  export * from './lib/board-fact.js';
11
- export * from './lib/diy-debug.js';
12
- export * from './lib/diy-record.js';
13
9
  export * from './api/blocker-table.js';
10
+ export * from './host/board-fact.js';
14
11
  export * from './host/browser-find.js';
15
12
  export * from './host/browser-read.js';
16
13
  export * from './host/cli-error.js';
14
+ export * from './host/context-ref.js';
17
15
  export * from './host/data-root.js';
16
+ export * from './host/diy-debug.js';
17
+ export * from './host/diy-record.js';
18
18
  export * from './host/facts.js';
19
19
  export * from './host/git.js';
20
20
  export * from './host/http.js';
@@ -22,12 +22,15 @@ export * from './host/long-task.js';
22
22
  export * from './host/opencli-runtime.js';
23
23
  export * from './host/opencli-window.js';
24
24
  export * from './host/opencli.js';
25
+ export * from './host/panel-state.js';
25
26
  export * from './host/plugin-ledger.js';
26
27
  export * from './host/plugin-source.js';
27
28
  export * from './host/provision.js';
29
+ export * from './host/shell-text.js';
28
30
  export * from './host/shell.js';
29
31
  export * from './host/tool-approval.js';
30
32
  export * from './host/tool-kit.js';
33
+ export * from './host/unit-declaration.js';
31
34
  export * from './host/unit-face.js';
32
35
  export * from './host/unit-libs.js';
33
36
  export * from './host/value-handoff.js';
package/dist/host.js CHANGED
@@ -1,20 +1,20 @@
1
1
  export * from './config/constants.js';
2
2
  export * from './api/context-ref.js';
3
3
  export * from './api/unit.js';
4
- export * from './api/unit-declaration.js';
5
4
  export * from './api/facts.js';
6
5
  export * from './api/long-task.js';
7
6
  export * from './lib/text.js';
8
7
  export * from './lib/ui.js';
9
- export * from './lib/panel-state.js';
10
8
  export * from './lib/board-fact.js';
11
- export * from './lib/diy-debug.js';
12
- export * from './lib/diy-record.js';
13
9
  export * from './api/blocker-table.js';
10
+ export * from './host/board-fact.js';
14
11
  export * from './host/browser-find.js';
15
12
  export * from './host/browser-read.js';
16
13
  export * from './host/cli-error.js';
14
+ export * from './host/context-ref.js';
17
15
  export * from './host/data-root.js';
16
+ export * from './host/diy-debug.js';
17
+ export * from './host/diy-record.js';
18
18
  export * from './host/facts.js';
19
19
  export * from './host/git.js';
20
20
  export * from './host/http.js';
@@ -22,12 +22,15 @@ export * from './host/long-task.js';
22
22
  export * from './host/opencli-runtime.js';
23
23
  export * from './host/opencli-window.js';
24
24
  export * from './host/opencli.js';
25
+ export * from './host/panel-state.js';
25
26
  export * from './host/plugin-ledger.js';
26
27
  export * from './host/plugin-source.js';
27
28
  export * from './host/provision.js';
29
+ export * from './host/shell-text.js';
28
30
  export * from './host/shell.js';
29
31
  export * from './host/tool-approval.js';
30
32
  export * from './host/tool-kit.js';
33
+ export * from './host/unit-declaration.js';
31
34
  export * from './host/unit-face.js';
32
35
  export * from './host/unit-libs.js';
33
36
  export * from './host/value-handoff.js';
package/dist/i18n/en.js CHANGED
@@ -37,6 +37,7 @@ export const en = {
37
37
  'session.actions': 'Actions for {name}',
38
38
  'status.idle': 'Idle',
39
39
  'status.running': 'Running',
40
+ 'status.longTask': 'Long task running',
40
41
  'status.waitingApproval': 'Waiting for approval',
41
42
  'status.planReview': 'Plan awaiting review',
42
43
  'status.waitingAnswer': 'Waiting for your answer',
@@ -50,6 +51,8 @@ export const en = {
50
51
  'project.attention.warning.other': '{n} sessions waiting for you',
51
52
  'project.attention.running.one': '1 session running',
52
53
  'project.attention.running.other': '{n} sessions running',
54
+ 'project.attention.longTask.one': '1 long task running',
55
+ 'project.attention.longTask.other': '{n} long tasks running',
53
56
  'project.attention.done.one': '1 session finished, unread',
54
57
  'project.attention.done.other': '{n} sessions finished, unread',
55
58
  'project.attention.state.warning': 'Approval',
@@ -426,6 +429,7 @@ export const en = {
426
429
  'record.waiting.note': 'Press "Start recording" on that page, then "Stop recording" when done (it will not switch you back)',
427
430
  'record.recording': 'Recording',
428
431
  'record.recording.note': 'Press "Stop recording" when done; if the bar is gone press Halt so the agent grabs it first',
432
+ 'record.recording.shots': '; to keep a shot of this moment press "Screenshot" on the bar ({n} taken)',
429
433
  'record.finished': 'Recording finished',
430
434
  'record.finished.note': 'This run is done — the agent will grab it and wrap up on its own',
431
435
  'record.act.cancel': 'Cancel',
@@ -436,4 +440,6 @@ export const en = {
436
440
  'approval.record.noUrl': 'no site given (this call gets refused)',
437
441
  'approval.record.oneAction': 'one action',
438
442
  'approval.record.noSwitch': 'it will not switch you back (the leftbar footer shows the state)',
443
+ 'approval.longTask.what': 'Stops',
444
+ 'approval.longTask.signal': 'stopping only sends an interrupt signal — how the platform-side run finishes is up to the module',
439
445
  };
@@ -39,6 +39,7 @@ export declare const dictionaries: {
39
39
  readonly 'session.actions': "{name} 的操作";
40
40
  readonly 'status.idle': "空闲";
41
41
  readonly 'status.running': "进行中";
42
+ readonly 'status.longTask': "长任务在跑";
42
43
  readonly 'status.waitingApproval': "等待审批";
43
44
  readonly 'status.planReview': "计划待审";
44
45
  readonly 'status.waitingAnswer': "等待回答";
@@ -52,6 +53,8 @@ export declare const dictionaries: {
52
53
  readonly 'project.attention.warning.other': "{n} 个会话在等你点头";
53
54
  readonly 'project.attention.running.one': "1 个会话在跑";
54
55
  readonly 'project.attention.running.other': "{n} 个会话在跑";
56
+ readonly 'project.attention.longTask.one': "1 个长任务在跑";
57
+ readonly 'project.attention.longTask.other': "{n} 个长任务在跑";
55
58
  readonly 'project.attention.done.one': "1 个会话跑完没看";
56
59
  readonly 'project.attention.done.other': "{n} 个会话跑完没看";
57
60
  readonly 'project.attention.state.warning': "待审批";
@@ -428,6 +431,7 @@ export declare const dictionaries: {
428
431
  readonly 'record.waiting.note': "请在那一页按「开始录制」,做完按「结束录制」(录完不替你切回来)";
429
432
  readonly 'record.recording': "录制中";
430
433
  readonly 'record.recording.note': "做完按「结束录制」;浮条没了按「停」,让 agent 先取再收";
434
+ readonly 'record.recording.shots': ";想留一张现场就按浮条上的「截图」(已拍 {n} 张)";
431
435
  readonly 'record.finished': "录制完成";
432
436
  readonly 'record.finished.note': "这一段录完了 —— agent 会自己来取并收工,不用你点";
433
437
  readonly 'record.act.cancel': "取消";
@@ -438,8 +442,10 @@ export declare const dictionaries: {
438
442
  readonly 'approval.record.noUrl': "没给站点地址(这次会被当场拒)";
439
443
  readonly 'approval.record.oneAction': "一次操作";
440
444
  readonly 'approval.record.noSwitch': "录完不会替你切回来(左栏底部会亮一条状态)";
445
+ readonly 'approval.longTask.what': "要停的那一趟";
446
+ readonly 'approval.longTask.signal': "停了只是让外壳发出中断信号 —— 平台侧那趟活儿的收尾看模块自己";
441
447
  };
442
- en: Record<"time.now" | "time.ago" | "time.minutes" | "time.hours" | "time.days" | "blocker.retry" | "blocker.copy" | "blocker.unknown.title" | "blocker.login.go" | "blocker.login.titleGeneric" | "blocker.login.title" | "blocker.login.manual" | "blocker.login.hint" | "blocker.forbidden.open" | "blocker.forbidden.titleGeneric" | "blocker.forbidden.title" | "blocker.forbidden.hint" | "blocker.timeout.hint" | "blocker.exec.hint" | "blocker.fix.install" | "blocker.fix.update" | "blocker.market.open" | "env.unit.failed" | "env.unit.failedHint" | "env.unit.missingPlugin" | "env.unit.hint" | "env.unit.missingCommands" | "env.unit.missingCommandsHint" | "env.unit.unchecked" | "env.unit.uncheckedHint" | "brand.name" | "toggle.open" | "toggle.collapse" | "project.label" | "workspace.section" | "project.none" | "project.empty" | "project.add" | "project.add.busy" | "project.add.failed" | "project.search.label" | "project.search.placeholder" | "project.search.empty" | "project.group.workspaces" | "project.group.defaultWorkspace" | "project.group.workshop" | "project.rename.row" | "project.rename.current" | "project.rename.title" | "project.rename.description" | "project.rename.field" | "project.rename.placeholder" | "project.rename.hint" | "project.rename.save" | "project.rename.saving" | "project.rename.cancel" | "project.rename.failed" | "session.new" | "session.new.label" | "session.empty" | "session.noProject" | "session.list.label" | "session.copy" | "session.pinned" | "session.actions" | "status.idle" | "status.running" | "status.waitingApproval" | "status.planReview" | "status.waitingAnswer" | "status.compact.approval" | "status.compact.planReview" | "status.compact.answer" | "status.completed" | "status.subagentsRunning.one" | "status.subagentsRunning.other" | "project.attention.warning.one" | "project.attention.warning.other" | "project.attention.running.one" | "project.attention.running.other" | "project.attention.done.one" | "project.attention.done.other" | "project.attention.state.warning" | "project.attention.state.running" | "project.attention.state.done" | "hover.copied" | "time.short.minutes" | "time.short.hours" | "time.short.days" | "time.short.months" | "time.short.years" | "panels.title" | "panels.groupBoardless" | "panels.groupPlugins" | "panels.market.defaultHint" | "panels.market.defaultLabel" | "panels.market.defaultLocked" | "panels.followAll" | "panels.followAllConfirmTitle" | "panels.followAllConfirmDetail" | "panels.followAllConfirmAck" | "panels.followAllConfirmYes" | "panels.followAllConfirmNo" | "panels.enabled" | "panels.disabled" | "panels.choose" | "panels.buildModule" | "panels.failed" | "panels.dragHint" | "panels.unknownStep" | "panels.labelWithHint" | "panels.hintJoin" | "panels.dep.failed" | "panels.dep.missingPlugin" | "panels.dep.missingCommands" | "panels.dep.unchecked" | "panels.tab.modules" | "panels.tab.market" | "panels.browseMarket" | "panels.noneInstalled" | "panels.noneInstalledHint" | "panels.market.installed" | "panels.market.notActive" | "panels.market.notUsable" | "panels.market.broken" | "panels.market.hasNew" | "panels.market.hasProblem" | "panels.market.missing" | "panels.market.unchecked" | "panels.market.checking" | "panels.market.sectionInstalled" | "panels.market.sectionPending" | "panels.market.sectionShared" | "panels.market.sharedUsedBy" | "panels.market.listSeparator" | "panels.market.sharedMissing" | "panels.market.sharedOutdated" | "panels.market.sharedUnsatisfied" | "panels.market.sharedOk" | "panels.market.versionArrow" | "panels.market.lead" | "panels.market.install" | "panels.market.update" | "panels.market.swapSlow" | "panels.market.uninstall" | "panels.market.uninstallLabel" | "panels.market.installing" | "panels.market.updating" | "panels.market.uninstalling" | "panels.market.confirmUninstallTitle" | "panels.market.confirmUninstallDetail" | "panels.market.confirmUninstallAck" | "panels.market.confirmYes" | "panels.market.confirmNo" | "panels.market.failed" | "panels.market.needEnv" | "panels.market.needCommands" | "panels.market.localMark" | "panels.market.localHint" | "panels.market.noSource" | "panels.market.badSource" | "panels.market.empty" | "panels.market.sectionPlugins" | "panels.market.moduleOutdated" | "panels.market.moduleRefused" | "panels.market.moduleRefusedDetail" | "panels.market.moduleRestartHint" | "panels.market.pendingRestart" | "panels.market.workbenchName" | "panels.market.workbenchLocal" | "panels.market.pluginKeptInUse" | "panels.market.pluginKeptUnsure" | "panels.market.pluginKeptHeld" | "panels.market.pluginKeptUnnamed" | "panels.market.pluginBroken" | "panels.market.restartNeeded" | "panels.market.foot" | "panels.market.recheck" | "panels.market.checkUpdates" | "panels.market.checkedAt" | "panels.market.justNow" | "panels.market.minutesAgo" | "panels.market.hoursAgo" | "panels.market.add.description" | "panels.market.add.specPlaceholder" | "panels.market.add.guideToggle" | "panels.market.add.guideHide" | "panels.market.add.guideIdTitle" | "panels.market.add.guideIdExample" | "panels.market.add.guideIdHint" | "panels.market.add.guideGitTitle" | "panels.market.add.guideGitExample" | "panels.market.add.guideGitHint" | "panels.market.add.guidePathTitle" | "panels.market.add.guidePathExample" | "panels.market.add.guidePathHint" | "panels.market.add.guideExampleLabel" | "panels.market.add.guideFill" | "panels.market.add.guideSafety" | "panels.market.add.registryLegend" | "panels.market.add.registryOfficial" | "panels.market.add.registryMirror" | "panels.market.add.registryWithHost" | "panels.market.add.registryToggle" | "panels.market.add.installVersion" | "panels.market.add.registryDefault" | "panels.market.add.registryCustom" | "panels.market.add.registryCustomPlaceholder" | "panels.market.add.registryCustomHint" | "panels.market.add.registryCustomInvalid" | "panels.market.add.run" | "panels.market.add.edit" | "panels.market.add.changeRegistry" | "panels.market.add.installingTitle" | "panels.market.add.installedTitle" | "panels.market.add.failedTitle" | "panels.market.add.cancelledTitle" | "panels.market.add.failureNetworkHost" | "panels.market.add.problemInvalid" | "panels.market.add.problemInstalled" | "panels.market.add.problemNotFound" | "panels.market.add.problemNotPackage" | "panels.market.add.problemNotBundle" | "panels.market.add.problemNotWorkbenchModule" | "panels.market.add.problemNotModuleOrPlugin" | "panels.market.add.failureNotModuleOrPlugin" | "panels.market.add.installedPlugin" | "panels.market.add.pluginPreview" | "panels.market.add.pluginAlias" | "panels.market.add.problemNetwork" | "panels.market.add.problemUnknown" | "panels.market.add.failureNetwork" | "panels.market.add.failureNotFound" | "panels.market.add.failureNoMatchingVersion" | "panels.market.add.failureDiskFull" | "panels.market.add.failurePermission" | "panels.market.add.failureBuildBlocked" | "panels.market.add.failureIntegrity" | "panels.market.add.failureTimeout" | "panels.market.add.failurePnpmMissing" | "panels.market.add.failureInstalled" | "panels.market.add.failureGeneric" | "panels.market.add.approveTitle" | "panels.market.add.approveCaution" | "panels.market.add.approveRun" | "panels.market.add.restart" | "panels.market.add.tookEffect" | "panels.market.add.details" | "panels.market.add.open" | "panels.market.add.title" | "panels.market.add.intro" | "panels.market.add.specLabel" | "panels.market.add.specHint" | "panels.market.add.exampleTitle" | "panels.market.add.exampleFill" | "panels.market.add.registryLabel" | "panels.market.add.registryProfile" | "panels.market.add.registryPnpm" | "panels.market.add.check" | "panels.market.add.checking" | "panels.market.add.classifying" | "panels.market.add.change" | "panels.market.add.previewTitle" | "panels.market.add.fieldName" | "panels.market.add.fieldVersion" | "panels.market.add.fieldDescription" | "panels.market.add.fieldSource" | "panels.market.add.install" | "panels.market.add.installing" | "panels.market.add.cancel" | "panels.market.add.close" | "panels.market.add.retry" | "panels.market.add.changeSource" | "panels.market.add.approveBuilds" | "panels.market.add.approveHint" | "panels.market.add.doneApplied" | "panels.market.add.doneRestart" | "panels.market.add.restartWhy" | "panels.market.add.restartWhy.no-hmr" | "panels.market.add.restartWhy.package-moved" | "panels.market.add.restartWhy.host-module" | "panels.market.add.restartWhy.unmanaged-plugin" | "panels.market.add.restartWhy.module-comparison" | "panels.market.add.cancelled" | "panels.market.add.failed" | "panels.market.add.removed" | "panels.market.add.supplyPending" | "panels.market.add.supplyFailed" | "panels.market.add.notModule" | "panels.market.add.removedRestart" | "panels.market.add.remove" | "panels.market.add.problem.invalidSpec" | "panels.market.add.problem.alreadyInstalled" | "panels.market.add.problem.notFound" | "panels.market.add.problem.notAPackage" | "panels.market.add.problem.notABundle" | "panels.market.add.problem.network" | "panels.market.add.problem.unknown" | "panels.market.add.reason.invalidSpec" | "panels.market.add.reason.incompatible" | "panels.market.add.reason.notBundle" | "panels.market.add.reason.notRemovable" | "panels.market.add.reason.bundleInUse" | "panels.market.add.reason.stopProfile" | "panels.market.add.reason.staleApproval" | "panels.market.add.reason.operationError" | "panels.market.add.reason.buildBlocked" | "panels.market.add.reason.pnpmMissing" | "panels.market.add.reason.noMatchingVersion" | "panels.market.add.reason.diskFull" | "panels.market.add.reason.permission" | "panels.market.add.reason.integrity" | "panels.market.add.reason.timeout" | "panels.market.add.reason.network" | "panels.market.add.reason.notFound" | "panels.market.add.reason.unknown" | "blocker.fix.running" | "blocker.fix.failed" | "blocker.retry.running" | "panels.reading" | "panels.cardBroken" | "panels.cardRetry" | "panels.empty" | "panels.emptyHint" | "env.title" | "env.checking" | "env.installing" | "env.failed" | "env.elapsed" | "env.stepFailed.install" | "env.stepFailed.path" | "env.stepFailed.shell" | "env.bridge.ok" | "env.bridge.short" | "env.bridge.why" | "env.bridge.daemon" | "env.bridge.extension" | "env.bridge.extensionLink" | "env.bridge.profile" | "env.bridge.stale" | "env.bridge.unknown" | "env.fix.title" | "env.fix.why" | "env.fix.whyPath" | "env.fix.whyShell" | "env.fix.step" | "env.fix.stepPath" | "env.fix.stepShell" | "env.fix.permission" | "env.fix.network" | "env.fix.details" | "env.retry" | "env.copyCommand" | "env.copied" | "env.step.opencli" | "env.step.codingPlugin" | "env.step.bridge" | "env.step.warm" | "env.warm.done" | "env.warm.short" | "rightbar.label" | "rightbar.expand" | "rightbar.collapse" | "rightbar.column.label" | "rightbar.column.workbench" | "rightbar.column.dsh" | "rightbar.refresh" | "rightbar.refreshing" | "rightbar.updatedAt" | "rightbar.noProject" | "rightbar.openPlatform" | "coding.notARepo.title" | "error.unknown" | "board.title" | "panel.conversation" | "panels.label" | "configSync.nav" | "configSync.lead" | "configSync.source" | "configSync.sourceBroken" | "configSync.sourceRows" | "configSync.sourceDead" | "configSync.refresh" | "configSync.loading" | "configSync.readHint" | "configSync.tag.new" | "configSync.tag.differs" | "configSync.conflictNote" | "configSync.code.lang" | "configSync.code.copy" | "configSync.code.copied" | "configSync.code.wrap" | "configSync.code.unwrap" | "configSync.code.collapse" | "configSync.code.collapseAria" | "configSync.code.expandAria" | "configSync.code.expand" | "configSync.missing" | "configSync.apply" | "configSync.applyNone" | "configSync.applying" | "configSync.applied" | "configSync.appliedIds" | "configSync.skippedIds" | "configSync.nothing" | "configSync.unreadable" | "configSync.noSource" | "configSync.emptyProviders" | "configSync.failed" | "debug.workspace" | "debug.status" | "debug.status.trouble" | "debug.stalled" | "debug.act.pause" | "debug.act.resume" | "debug.act.stop" | "debug.act.stop.ask" | "debug.card.here.title" | "debug.card.here.note" | "debug.card.away.note" | "debug.card.paused.note" | "debug.card.hidden.note" | "record.waiting" | "record.waiting.note" | "record.recording" | "record.recording.note" | "record.finished" | "record.finished.note" | "record.act.cancel" | "record.act.halt" | "approval.record.site" | "approval.record.what" | "approval.record.lands" | "approval.record.noUrl" | "approval.record.oneAction" | "approval.record.noSwitch", string>;
448
+ en: Record<"time.now" | "time.ago" | "time.minutes" | "time.hours" | "time.days" | "blocker.retry" | "blocker.copy" | "blocker.unknown.title" | "blocker.login.go" | "blocker.login.titleGeneric" | "blocker.login.title" | "blocker.login.manual" | "blocker.login.hint" | "blocker.forbidden.open" | "blocker.forbidden.titleGeneric" | "blocker.forbidden.title" | "blocker.forbidden.hint" | "blocker.timeout.hint" | "blocker.exec.hint" | "blocker.fix.install" | "blocker.fix.update" | "blocker.market.open" | "env.unit.failed" | "env.unit.failedHint" | "env.unit.missingPlugin" | "env.unit.hint" | "env.unit.missingCommands" | "env.unit.missingCommandsHint" | "env.unit.unchecked" | "env.unit.uncheckedHint" | "brand.name" | "toggle.open" | "toggle.collapse" | "project.label" | "workspace.section" | "project.none" | "project.empty" | "project.add" | "project.add.busy" | "project.add.failed" | "project.search.label" | "project.search.placeholder" | "project.search.empty" | "project.group.workspaces" | "project.group.defaultWorkspace" | "project.group.workshop" | "project.rename.row" | "project.rename.current" | "project.rename.title" | "project.rename.description" | "project.rename.field" | "project.rename.placeholder" | "project.rename.hint" | "project.rename.save" | "project.rename.saving" | "project.rename.cancel" | "project.rename.failed" | "session.new" | "session.new.label" | "session.empty" | "session.noProject" | "session.list.label" | "session.copy" | "session.pinned" | "session.actions" | "status.idle" | "status.running" | "status.longTask" | "status.waitingApproval" | "status.planReview" | "status.waitingAnswer" | "status.compact.approval" | "status.compact.planReview" | "status.compact.answer" | "status.completed" | "status.subagentsRunning.one" | "status.subagentsRunning.other" | "project.attention.warning.one" | "project.attention.warning.other" | "project.attention.running.one" | "project.attention.running.other" | "project.attention.longTask.one" | "project.attention.longTask.other" | "project.attention.done.one" | "project.attention.done.other" | "project.attention.state.warning" | "project.attention.state.running" | "project.attention.state.done" | "hover.copied" | "time.short.minutes" | "time.short.hours" | "time.short.days" | "time.short.months" | "time.short.years" | "panels.title" | "panels.groupBoardless" | "panels.groupPlugins" | "panels.market.defaultHint" | "panels.market.defaultLabel" | "panels.market.defaultLocked" | "panels.followAll" | "panels.followAllConfirmTitle" | "panels.followAllConfirmDetail" | "panels.followAllConfirmAck" | "panels.followAllConfirmYes" | "panels.followAllConfirmNo" | "panels.enabled" | "panels.disabled" | "panels.choose" | "panels.buildModule" | "panels.failed" | "panels.dragHint" | "panels.unknownStep" | "panels.labelWithHint" | "panels.hintJoin" | "panels.dep.failed" | "panels.dep.missingPlugin" | "panels.dep.missingCommands" | "panels.dep.unchecked" | "panels.tab.modules" | "panels.tab.market" | "panels.browseMarket" | "panels.noneInstalled" | "panels.noneInstalledHint" | "panels.market.installed" | "panels.market.notActive" | "panels.market.notUsable" | "panels.market.broken" | "panels.market.hasNew" | "panels.market.hasProblem" | "panels.market.missing" | "panels.market.unchecked" | "panels.market.checking" | "panels.market.sectionInstalled" | "panels.market.sectionPending" | "panels.market.sectionShared" | "panels.market.sharedUsedBy" | "panels.market.listSeparator" | "panels.market.sharedMissing" | "panels.market.sharedOutdated" | "panels.market.sharedUnsatisfied" | "panels.market.sharedOk" | "panels.market.versionArrow" | "panels.market.lead" | "panels.market.install" | "panels.market.update" | "panels.market.swapSlow" | "panels.market.uninstall" | "panels.market.uninstallLabel" | "panels.market.installing" | "panels.market.updating" | "panels.market.uninstalling" | "panels.market.confirmUninstallTitle" | "panels.market.confirmUninstallDetail" | "panels.market.confirmUninstallAck" | "panels.market.confirmYes" | "panels.market.confirmNo" | "panels.market.failed" | "panels.market.needEnv" | "panels.market.needCommands" | "panels.market.localMark" | "panels.market.localHint" | "panels.market.noSource" | "panels.market.badSource" | "panels.market.empty" | "panels.market.sectionPlugins" | "panels.market.moduleOutdated" | "panels.market.moduleRefused" | "panels.market.moduleRefusedDetail" | "panels.market.moduleRestartHint" | "panels.market.pendingRestart" | "panels.market.workbenchName" | "panels.market.workbenchLocal" | "panels.market.pluginKeptInUse" | "panels.market.pluginKeptUnsure" | "panels.market.pluginKeptHeld" | "panels.market.pluginKeptUnnamed" | "panels.market.pluginBroken" | "panels.market.restartNeeded" | "panels.market.foot" | "panels.market.recheck" | "panels.market.checkUpdates" | "panels.market.checkedAt" | "panels.market.justNow" | "panels.market.minutesAgo" | "panels.market.hoursAgo" | "panels.market.add.description" | "panels.market.add.specPlaceholder" | "panels.market.add.guideToggle" | "panels.market.add.guideHide" | "panels.market.add.guideIdTitle" | "panels.market.add.guideIdExample" | "panels.market.add.guideIdHint" | "panels.market.add.guideGitTitle" | "panels.market.add.guideGitExample" | "panels.market.add.guideGitHint" | "panels.market.add.guidePathTitle" | "panels.market.add.guidePathExample" | "panels.market.add.guidePathHint" | "panels.market.add.guideExampleLabel" | "panels.market.add.guideFill" | "panels.market.add.guideSafety" | "panels.market.add.registryLegend" | "panels.market.add.registryOfficial" | "panels.market.add.registryMirror" | "panels.market.add.registryWithHost" | "panels.market.add.registryToggle" | "panels.market.add.installVersion" | "panels.market.add.registryDefault" | "panels.market.add.registryCustom" | "panels.market.add.registryCustomPlaceholder" | "panels.market.add.registryCustomHint" | "panels.market.add.registryCustomInvalid" | "panels.market.add.run" | "panels.market.add.edit" | "panels.market.add.changeRegistry" | "panels.market.add.installingTitle" | "panels.market.add.installedTitle" | "panels.market.add.failedTitle" | "panels.market.add.cancelledTitle" | "panels.market.add.failureNetworkHost" | "panels.market.add.problemInvalid" | "panels.market.add.problemInstalled" | "panels.market.add.problemNotFound" | "panels.market.add.problemNotPackage" | "panels.market.add.problemNotBundle" | "panels.market.add.problemNotWorkbenchModule" | "panels.market.add.problemNotModuleOrPlugin" | "panels.market.add.failureNotModuleOrPlugin" | "panels.market.add.installedPlugin" | "panels.market.add.pluginPreview" | "panels.market.add.pluginAlias" | "panels.market.add.problemNetwork" | "panels.market.add.problemUnknown" | "panels.market.add.failureNetwork" | "panels.market.add.failureNotFound" | "panels.market.add.failureNoMatchingVersion" | "panels.market.add.failureDiskFull" | "panels.market.add.failurePermission" | "panels.market.add.failureBuildBlocked" | "panels.market.add.failureIntegrity" | "panels.market.add.failureTimeout" | "panels.market.add.failurePnpmMissing" | "panels.market.add.failureInstalled" | "panels.market.add.failureGeneric" | "panels.market.add.approveTitle" | "panels.market.add.approveCaution" | "panels.market.add.approveRun" | "panels.market.add.restart" | "panels.market.add.tookEffect" | "panels.market.add.details" | "panels.market.add.open" | "panels.market.add.title" | "panels.market.add.intro" | "panels.market.add.specLabel" | "panels.market.add.specHint" | "panels.market.add.exampleTitle" | "panels.market.add.exampleFill" | "panels.market.add.registryLabel" | "panels.market.add.registryProfile" | "panels.market.add.registryPnpm" | "panels.market.add.check" | "panels.market.add.checking" | "panels.market.add.classifying" | "panels.market.add.change" | "panels.market.add.previewTitle" | "panels.market.add.fieldName" | "panels.market.add.fieldVersion" | "panels.market.add.fieldDescription" | "panels.market.add.fieldSource" | "panels.market.add.install" | "panels.market.add.installing" | "panels.market.add.cancel" | "panels.market.add.close" | "panels.market.add.retry" | "panels.market.add.changeSource" | "panels.market.add.approveBuilds" | "panels.market.add.approveHint" | "panels.market.add.doneApplied" | "panels.market.add.doneRestart" | "panels.market.add.restartWhy" | "panels.market.add.restartWhy.no-hmr" | "panels.market.add.restartWhy.package-moved" | "panels.market.add.restartWhy.host-module" | "panels.market.add.restartWhy.unmanaged-plugin" | "panels.market.add.restartWhy.module-comparison" | "panels.market.add.cancelled" | "panels.market.add.failed" | "panels.market.add.removed" | "panels.market.add.supplyPending" | "panels.market.add.supplyFailed" | "panels.market.add.notModule" | "panels.market.add.removedRestart" | "panels.market.add.remove" | "panels.market.add.problem.invalidSpec" | "panels.market.add.problem.alreadyInstalled" | "panels.market.add.problem.notFound" | "panels.market.add.problem.notAPackage" | "panels.market.add.problem.notABundle" | "panels.market.add.problem.network" | "panels.market.add.problem.unknown" | "panels.market.add.reason.invalidSpec" | "panels.market.add.reason.incompatible" | "panels.market.add.reason.notBundle" | "panels.market.add.reason.notRemovable" | "panels.market.add.reason.bundleInUse" | "panels.market.add.reason.stopProfile" | "panels.market.add.reason.staleApproval" | "panels.market.add.reason.operationError" | "panels.market.add.reason.buildBlocked" | "panels.market.add.reason.pnpmMissing" | "panels.market.add.reason.noMatchingVersion" | "panels.market.add.reason.diskFull" | "panels.market.add.reason.permission" | "panels.market.add.reason.integrity" | "panels.market.add.reason.timeout" | "panels.market.add.reason.network" | "panels.market.add.reason.notFound" | "panels.market.add.reason.unknown" | "blocker.fix.running" | "blocker.fix.failed" | "blocker.retry.running" | "panels.reading" | "panels.cardBroken" | "panels.cardRetry" | "panels.empty" | "panels.emptyHint" | "env.title" | "env.checking" | "env.installing" | "env.failed" | "env.elapsed" | "env.stepFailed.install" | "env.stepFailed.path" | "env.stepFailed.shell" | "env.bridge.ok" | "env.bridge.short" | "env.bridge.why" | "env.bridge.daemon" | "env.bridge.extension" | "env.bridge.extensionLink" | "env.bridge.profile" | "env.bridge.stale" | "env.bridge.unknown" | "env.fix.title" | "env.fix.why" | "env.fix.whyPath" | "env.fix.whyShell" | "env.fix.step" | "env.fix.stepPath" | "env.fix.stepShell" | "env.fix.permission" | "env.fix.network" | "env.fix.details" | "env.retry" | "env.copyCommand" | "env.copied" | "env.step.opencli" | "env.step.codingPlugin" | "env.step.bridge" | "env.step.warm" | "env.warm.done" | "env.warm.short" | "rightbar.label" | "rightbar.expand" | "rightbar.collapse" | "rightbar.column.label" | "rightbar.column.workbench" | "rightbar.column.dsh" | "rightbar.refresh" | "rightbar.refreshing" | "rightbar.updatedAt" | "rightbar.noProject" | "rightbar.openPlatform" | "coding.notARepo.title" | "error.unknown" | "board.title" | "panel.conversation" | "panels.label" | "configSync.nav" | "configSync.lead" | "configSync.source" | "configSync.sourceBroken" | "configSync.sourceRows" | "configSync.sourceDead" | "configSync.refresh" | "configSync.loading" | "configSync.readHint" | "configSync.tag.new" | "configSync.tag.differs" | "configSync.conflictNote" | "configSync.code.lang" | "configSync.code.copy" | "configSync.code.copied" | "configSync.code.wrap" | "configSync.code.unwrap" | "configSync.code.collapse" | "configSync.code.collapseAria" | "configSync.code.expandAria" | "configSync.code.expand" | "configSync.missing" | "configSync.apply" | "configSync.applyNone" | "configSync.applying" | "configSync.applied" | "configSync.appliedIds" | "configSync.skippedIds" | "configSync.nothing" | "configSync.unreadable" | "configSync.noSource" | "configSync.emptyProviders" | "configSync.failed" | "debug.workspace" | "debug.status" | "debug.status.trouble" | "debug.stalled" | "debug.act.pause" | "debug.act.resume" | "debug.act.stop" | "debug.act.stop.ask" | "debug.card.here.title" | "debug.card.here.note" | "debug.card.away.note" | "debug.card.paused.note" | "debug.card.hidden.note" | "record.waiting" | "record.waiting.note" | "record.recording" | "record.recording.note" | "record.recording.shots" | "record.finished" | "record.finished.note" | "record.act.cancel" | "record.act.halt" | "approval.record.site" | "approval.record.what" | "approval.record.lands" | "approval.record.noUrl" | "approval.record.oneAction" | "approval.record.noSwitch" | "approval.longTask.what" | "approval.longTask.signal", string>;
443
449
  };
444
450
  /** 中文词表的键类型(从 `zh.ts` 转出):`en` 与模块词表都得覆盖同一批键。 */
445
451
  export type { WorkbenchMessages };
package/dist/i18n/zh.d.ts CHANGED
@@ -37,6 +37,7 @@ export declare const zh: {
37
37
  readonly 'session.actions': "{name} 的操作";
38
38
  readonly 'status.idle': "空闲";
39
39
  readonly 'status.running': "进行中";
40
+ readonly 'status.longTask': "长任务在跑";
40
41
  readonly 'status.waitingApproval': "等待审批";
41
42
  readonly 'status.planReview': "计划待审";
42
43
  readonly 'status.waitingAnswer': "等待回答";
@@ -50,6 +51,8 @@ export declare const zh: {
50
51
  readonly 'project.attention.warning.other': "{n} 个会话在等你点头";
51
52
  readonly 'project.attention.running.one': "1 个会话在跑";
52
53
  readonly 'project.attention.running.other': "{n} 个会话在跑";
54
+ readonly 'project.attention.longTask.one': "1 个长任务在跑";
55
+ readonly 'project.attention.longTask.other': "{n} 个长任务在跑";
53
56
  readonly 'project.attention.done.one': "1 个会话跑完没看";
54
57
  readonly 'project.attention.done.other': "{n} 个会话跑完没看";
55
58
  readonly 'project.attention.state.warning': "待审批";
@@ -426,6 +429,7 @@ export declare const zh: {
426
429
  readonly 'record.waiting.note': "请在那一页按「开始录制」,做完按「结束录制」(录完不替你切回来)";
427
430
  readonly 'record.recording': "录制中";
428
431
  readonly 'record.recording.note': "做完按「结束录制」;浮条没了按「停」,让 agent 先取再收";
432
+ readonly 'record.recording.shots': ";想留一张现场就按浮条上的「截图」(已拍 {n} 张)";
429
433
  readonly 'record.finished': "录制完成";
430
434
  readonly 'record.finished.note': "这一段录完了 —— agent 会自己来取并收工,不用你点";
431
435
  readonly 'record.act.cancel': "取消";
@@ -436,6 +440,8 @@ export declare const zh: {
436
440
  readonly 'approval.record.noUrl': "没给站点地址(这次会被当场拒)";
437
441
  readonly 'approval.record.oneAction': "一次操作";
438
442
  readonly 'approval.record.noSwitch': "录完不会替你切回来(左栏底部会亮一条状态)";
443
+ readonly 'approval.longTask.what': "要停的那一趟";
444
+ readonly 'approval.longTask.signal': "停了只是让外壳发出中断信号 —— 平台侧那趟活儿的收尾看模块自己";
439
445
  };
440
446
  /** 中文词表的键类型:`en` 与模块词表都得覆盖同一批键。 */
441
447
  export type WorkbenchMessages = typeof zh;
package/dist/i18n/zh.js CHANGED
@@ -37,6 +37,7 @@ export const zh = {
37
37
  'session.actions': '{name} 的操作',
38
38
  'status.idle': '空闲',
39
39
  'status.running': '进行中',
40
+ 'status.longTask': '长任务在跑',
40
41
  'status.waitingApproval': '等待审批',
41
42
  'status.planReview': '计划待审',
42
43
  'status.waitingAnswer': '等待回答',
@@ -50,6 +51,8 @@ export const zh = {
50
51
  'project.attention.warning.other': '{n} 个会话在等你点头',
51
52
  'project.attention.running.one': '1 个会话在跑',
52
53
  'project.attention.running.other': '{n} 个会话在跑',
54
+ 'project.attention.longTask.one': '1 个长任务在跑',
55
+ 'project.attention.longTask.other': '{n} 个长任务在跑',
53
56
  'project.attention.done.one': '1 个会话跑完没看',
54
57
  'project.attention.done.other': '{n} 个会话跑完没看',
55
58
  'project.attention.state.warning': '待审批',
@@ -426,6 +429,7 @@ export const zh = {
426
429
  'record.waiting.note': '请在那一页按「开始录制」,做完按「结束录制」(录完不替你切回来)',
427
430
  'record.recording': '录制中',
428
431
  'record.recording.note': '做完按「结束录制」;浮条没了按「停」,让 agent 先取再收',
432
+ 'record.recording.shots': ';想留一张现场就按浮条上的「截图」(已拍 {n} 张)',
429
433
  'record.finished': '录制完成',
430
434
  'record.finished.note': '这一段录完了 —— agent 会自己来取并收工,不用你点',
431
435
  'record.act.cancel': '取消',
@@ -436,4 +440,6 @@ export const zh = {
436
440
  'approval.record.noUrl': '没给站点地址(这次会被当场拒)',
437
441
  'approval.record.oneAction': '一次操作',
438
442
  'approval.record.noSwitch': '录完不会替你切回来(左栏底部会亮一条状态)',
443
+ 'approval.longTask.what': '要停的那一趟',
444
+ 'approval.longTask.signal': '停了只是让外壳发出中断信号 —— 平台侧那趟活儿的收尾看模块自己',
439
445
  };
package/dist/index.d.ts CHANGED
@@ -7,7 +7,6 @@ export * from './api/facts.js';
7
7
  export * from './api/host-write.js';
8
8
  export * from './api/long-task.js';
9
9
  export * from './api/unit-board.js';
10
- export * from './api/unit-declaration.js';
11
10
  export * from './api/unit.js';
12
11
  export * from './api/workbench-client.js';
13
12
  export * from './api/workbench-contract.js';
@@ -19,6 +18,7 @@ export * from './components/CardAnchor.js';
19
18
  export * from './components/CardBoundary.js';
20
19
  export * from './components/CardHead.js';
21
20
  export * from './components/ChoiceGroup.js';
21
+ export * from './components/ConfirmBar.js';
22
22
  export * from './components/Field.js';
23
23
  export * from './components/Form.js';
24
24
  export * from './components/FormActions.js';
@@ -49,10 +49,7 @@ export * from './i18n/zh.js';
49
49
  export * from './lib/blocker-action.js';
50
50
  export * from './lib/board-fact.js';
51
51
  export * from './lib/busy.js';
52
- export * from './lib/diy-debug.js';
53
- export * from './lib/diy-record.js';
54
52
  export * from './lib/form-problem.js';
55
- export * from './lib/panel-state.js';
56
53
  export * from './lib/react.js';
57
54
  export * from './lib/text.js';
58
55
  export * from './lib/ui.js';
package/dist/index.js CHANGED
@@ -7,7 +7,6 @@ export * from './api/facts.js';
7
7
  export * from './api/host-write.js';
8
8
  export * from './api/long-task.js';
9
9
  export * from './api/unit-board.js';
10
- export * from './api/unit-declaration.js';
11
10
  export * from './api/unit.js';
12
11
  export * from './api/workbench-client.js';
13
12
  export * from './api/workbench-contract.js';
@@ -19,6 +18,7 @@ export * from './components/CardAnchor.js';
19
18
  export * from './components/CardBoundary.js';
20
19
  export * from './components/CardHead.js';
21
20
  export * from './components/ChoiceGroup.js';
21
+ export * from './components/ConfirmBar.js';
22
22
  export * from './components/Field.js';
23
23
  export * from './components/Form.js';
24
24
  export * from './components/FormActions.js';
@@ -49,10 +49,7 @@ export * from './i18n/zh.js';
49
49
  export * from './lib/blocker-action.js';
50
50
  export * from './lib/board-fact.js';
51
51
  export * from './lib/busy.js';
52
- export * from './lib/diy-debug.js';
53
- export * from './lib/diy-record.js';
54
52
  export * from './lib/form-problem.js';
55
- export * from './lib/panel-state.js';
56
53
  export * from './lib/react.js';
57
54
  export * from './lib/text.js';
58
55
  export * from './lib/ui.js';
@@ -24,13 +24,6 @@ export interface BoardProbe {
24
24
  * @returns 同一个路径或在其下给 `true`;`root` 末尾带不带斜杠都认(`/a` 不匹配 `/ab`)。
25
25
  */
26
26
  export declare function insideWorkshop(root: string, target: string): boolean;
27
- /**
28
- * 把一次探针读数归成椅面归属。
29
- * @param probe - 探针读数。
30
- * @param workshop - 当前工作区根路径;`null` 表示还不知道当前是哪个工作区。
31
- * @returns 外壳不在、或板路径与工作区缺一 → `unknown`;右栏没开或没画出来 → `hidden`;板在本工作区 → `workshop`,否则 `other`。
32
- */
33
- export declare function boardFactOf(probe: BoardProbe, workshop: string | null): BoardFactState;
34
27
  /**
35
28
  * 把探针读数归成左栏那句人话的档位。
36
29
  * @param probe - 探针读数。
@@ -10,21 +10,6 @@ export function insideWorkshop(root, target) {
10
10
  const base = root.endsWith('/') ? root : `${root}/`;
11
11
  return target.startsWith(base);
12
12
  }
13
- /**
14
- * 把一次探针读数归成椅面归属。
15
- * @param probe - 探针读数。
16
- * @param workshop - 当前工作区根路径;`null` 表示还不知道当前是哪个工作区。
17
- * @returns 外壳不在、或板路径与工作区缺一 → `unknown`;右栏没开或没画出来 → `hidden`;板在本工作区 → `workshop`,否则 `other`。
18
- */
19
- export function boardFactOf(probe, workshop) {
20
- if (!probe.workbench)
21
- return 'unknown';
22
- if (!probe.bar || !probe.open || !probe.drawn)
23
- return 'hidden';
24
- if (probe.board === '' || workshop === null)
25
- return 'unknown';
26
- return insideWorkshop(workshop, probe.board) ? 'workshop' : 'other';
27
- }
28
13
  /**
29
14
  * 把探针读数归成左栏那句人话的档位。
30
15
  * @param probe - 探针读数。
@@ -14,7 +14,29 @@ export interface RecordExpect {
14
14
  readonly urlContains: string;
15
15
  }
16
16
  /**
17
- * 一份活着的录制约定:相位 + 谁的会话 + 哪个工作区 / 单元 + 页面 URL 与标题 + 要找的那一次写 + 落盘文件 + 三个时间戳。
17
+ * 一次「截图」在宿主台账里的那一行:页面上的计数、落图那一刻、落盘路径;没落下来时带 `error` 原文(落成的那条没有它)。
18
+ */
19
+ export interface RecordShot {
20
+ readonly n: number;
21
+ readonly at: number;
22
+ readonly path: string;
23
+ readonly error?: string;
24
+ }
25
+ /**
26
+ * 某个页面计数已经试过几次:初拍算一次,失败再试一次;计数一换就从头数。
27
+ */
28
+ export interface RecordShotTries {
29
+ readonly n: number;
30
+ readonly tries: number;
31
+ }
32
+ /**
33
+ * 一张图最多试几次(初拍 + 一次重试):失败如实报过就停,不每拍重试到底。
34
+ */
35
+ export declare const RECORD_SHOT_TRIES = 2;
36
+ /**
37
+ * 一份活着的录制约定:相位 + 谁的会话 + 哪个工作区 / 单元 + 页面 URL 与标题 + 要找的那一次写 +
38
+ * 落盘文件 + 三个时间戳,以及两份台账:按计数落图的 `shots`(`shotsSeen` 只记落成的那个计数)
39
+ * 与门铃的 `beats` / `beatMs`(命中几次、最近一次等了多久)。
18
40
  */
19
41
  export interface RecordState {
20
42
  readonly phase: RecordPhase;
@@ -30,6 +52,11 @@ export interface RecordState {
30
52
  readonly startedAt: number;
31
53
  readonly t0: number | null;
32
54
  readonly t1: number | null;
55
+ readonly shots: readonly RecordShot[];
56
+ readonly shotsSeen: number;
57
+ readonly shotTries: RecordShotTries | null;
58
+ readonly beats: number;
59
+ readonly beatMs: number;
33
60
  readonly at: number;
34
61
  }
35
62
  /**
@@ -83,8 +110,18 @@ export interface RecordStore {
83
110
  begin(pact: RecordPact): RecordMove;
84
111
  started(sessionId: string, at: number, now: number): RecordMove;
85
112
  finished(sessionId: string, at: number, now: number): RecordMove;
113
+ shotTaken(sessionId: string, shot: RecordShot, now: number): RecordMove;
114
+ shotFailed(sessionId: string, shot: RecordShot, now: number): RecordMove;
115
+ beat(sessionId: string, ms: number, now: number): RecordMove;
86
116
  stop(sessionId: string, now: number): RecordMove;
87
117
  }
118
+ /**
119
+ * 这一拍该不该落图:页面计数涨过 `shotsSeen` 才算;同一个计数已经试满就先放下,等他自己再按。
120
+ * @param state - 当前有效的那份约定。
121
+ * @param pageShots - 页面浮条上那个「已拍」计数。
122
+ * @returns 该落的那个计数;不该落给 `null`(没涨 / 试满了 / 不是个正经数)。
123
+ */
124
+ export declare function shotDueOf(state: RecordState, pageShots: number): number | null;
88
125
  /**
89
126
  * 造一份新的录制约定存储(进程内存,同一时刻只可能有一份有效约定)。
90
127
  * @returns 存取口;动作成不成都在返回的 `RecordMove` 里,不抛异常。
@@ -2,6 +2,10 @@
2
2
  * 录制约定的有效期(15 分钟,毫秒):超过它没动静的约定算过期、当场让人。
3
3
  */
4
4
  export const RECORD_STALE_MS = 15 * 60 * 1000;
5
+ /**
6
+ * 一张图最多试几次(初拍 + 一次重试):失败如实报过就停,不每拍重试到底。
7
+ */
8
+ export const RECORD_SHOT_TRIES = 2;
5
9
  /**
6
10
  * 把工具入参收成人话动作。
7
11
  * @param raw - 任意入参值。
@@ -10,6 +14,22 @@ export const RECORD_STALE_MS = 15 * 60 * 1000;
10
14
  export function parseRecordIntent(raw) {
11
15
  return raw === 'peek' || raw === 'halt' || raw === 'stop' ? raw : null;
12
16
  }
17
+ /**
18
+ * 这一拍该不该落图:页面计数涨过 `shotsSeen` 才算;同一个计数已经试满就先放下,等他自己再按。
19
+ * @param state - 当前有效的那份约定。
20
+ * @param pageShots - 页面浮条上那个「已拍」计数。
21
+ * @returns 该落的那个计数;不该落给 `null`(没涨 / 试满了 / 不是个正经数)。
22
+ */
23
+ export function shotDueOf(state, pageShots) {
24
+ if (!Number.isFinite(pageShots))
25
+ return null;
26
+ const n = Math.floor(pageShots);
27
+ if (n <= state.shotsSeen)
28
+ return null;
29
+ if (state.shotTries !== null && state.shotTries.n === n && state.shotTries.tries >= RECORD_SHOT_TRIES)
30
+ return null;
31
+ return n;
32
+ }
13
33
  function alive(state, now) {
14
34
  if (state === null)
15
35
  return null;
@@ -28,6 +48,18 @@ function ownerOf(state, sessionId, now) {
28
48
  export function createRecordStore() {
29
49
  let held = null;
30
50
  const live = (now) => alive(held, now);
51
+ const withShot = (found, shot, now, error) => {
52
+ const row = error === undefined ? shot : { n: shot.n, at: shot.at, path: shot.path, error };
53
+ const kept = found.shots.filter((one) => one.n !== shot.n);
54
+ const tries = found.shotTries !== null && found.shotTries.n === shot.n ? found.shotTries.tries : 0;
55
+ return {
56
+ ...found,
57
+ shots: [...kept, row].sort((one, two) => one.n - two.n),
58
+ shotsSeen: error === undefined ? Math.max(found.shotsSeen, shot.n) : found.shotsSeen,
59
+ shotTries: error === undefined ? null : { n: shot.n, tries: tries + 1 },
60
+ at: now,
61
+ };
62
+ };
31
63
  return {
32
64
  live,
33
65
  begin(pact) {
@@ -49,6 +81,11 @@ export function createRecordStore() {
49
81
  startedAt: pact.now,
50
82
  t0: null,
51
83
  t1: null,
84
+ shots: [],
85
+ shotsSeen: 0,
86
+ shotTries: null,
87
+ beats: 0,
88
+ beatMs: 0,
52
89
  at: pact.now,
53
90
  };
54
91
  held = state;
@@ -76,6 +113,35 @@ export function createRecordStore() {
76
113
  held = state;
77
114
  return { ok: true, state };
78
115
  },
116
+ shotTaken(sessionId, shot, now) {
117
+ const found = ownerOf(held, sessionId, now);
118
+ if (typeof found === 'string')
119
+ return { ok: false, code: found };
120
+ const state = withShot(found, shot, now, undefined);
121
+ held = state;
122
+ return { ok: true, state };
123
+ },
124
+ shotFailed(sessionId, shot, now) {
125
+ const found = ownerOf(held, sessionId, now);
126
+ if (typeof found === 'string')
127
+ return { ok: false, code: found };
128
+ const state = withShot(found, shot, now, shot.error === undefined ? '落图失败' : shot.error);
129
+ held = state;
130
+ return { ok: true, state };
131
+ },
132
+ beat(sessionId, ms, now) {
133
+ const found = ownerOf(held, sessionId, now);
134
+ if (typeof found === 'string')
135
+ return { ok: false, code: found };
136
+ const state = {
137
+ ...found,
138
+ beats: found.beats + 1,
139
+ beatMs: Math.max(0, Math.floor(ms)),
140
+ at: now,
141
+ };
142
+ held = state;
143
+ return { ok: true, state };
144
+ },
79
145
  stop(sessionId, now) {
80
146
  const found = ownerOf(held, sessionId, now);
81
147
  if (typeof found === 'string')
@@ -1,16 +1,3 @@
1
- /**
2
- * 把一个值裹成 shell 里的单引号字面量(值里的单引号一并转义),保证元字符按字面量传递。
3
- * @param value - 任意值;不是字符串的先 `String()`。
4
- * @returns 可安全拼进 `/bin/sh -c` 的一段文本 —— 含空格 / `$()` / `;` / 通配符的值都不会被当成语法。
5
- */
6
- export declare function quoteShellArg(value: unknown): string;
7
- /**
8
- * 取一段文本的末尾若干行(如命令输出),顺带去掉首尾空白。
9
- * @param text - 原文;`null` / `undefined` 当空串。
10
- * @param lines - 最多留几行,默认 6;0 给全篇、负数从开头砍掉那么多行(都是 `slice` 语义),调用方传正数。
11
- * @returns 末尾若干行、去首尾空行后的文本;原文行数不够就全给,空输入给空串。
12
- */
13
- export declare function tailLines(text: string | null | undefined, lines?: number): string;
14
1
  /**
15
2
  * 宽松解析一段前后可能夹着人话的 JSON:整段不通就从行首的 `[` / `{` 起、截到最后一个闭合符再试。
16
3
  * @param text - 原文;`null` / `undefined` 当空串。