@soimy/dingtalk 3.6.11 → 3.7.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.
Files changed (161) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +11684 -10583
  3. package/dist/src/{ack-reaction-service.d.ts → ack-reaction/ack-reaction-service.d.ts} +1 -1
  4. package/dist/src/ack-reaction/dynamic-ack-reaction-controller.d.ts +3 -3
  5. package/dist/src/card/ask-user-question-context.d.ts +1 -1
  6. package/dist/src/card/ask-user-question-store.d.ts +1 -1
  7. package/dist/src/card/ask-user-question.d.ts +1 -1
  8. package/dist/src/card/card-action-handler.d.ts +2 -2
  9. package/dist/src/{card-draft-controller.d.ts → card/card-draft-controller.d.ts} +5 -1
  10. package/dist/src/card/card-run-registry.d.ts +2 -2
  11. package/dist/src/{card-service.d.ts → card/card-service.d.ts} +1 -1
  12. package/dist/src/card/card-stop-handler.d.ts +1 -1
  13. package/dist/src/card/card-streaming-mode.d.ts +1 -1
  14. package/dist/src/card/card-task-progress.d.ts +60 -0
  15. package/dist/src/channel.d.ts +6 -6
  16. package/dist/src/command/card-stop-command.d.ts +1 -1
  17. package/dist/src/{feedback-learning-service.d.ts → command/feedback-learning-service.d.ts} +1 -1
  18. package/dist/src/command/inbound-command-dispatch-service.d.ts +2 -2
  19. package/dist/src/{learning-command-service.d.ts → command/learning-command-service.d.ts} +1 -1
  20. package/dist/src/gateway/channel-gateway.d.ts +1 -1
  21. package/dist/src/{connection-manager.d.ts → gateway/connection-manager.d.ts} +1 -1
  22. package/dist/src/{docs-service.d.ts → gateway/docs-service.d.ts} +1 -1
  23. package/dist/src/{inbound-handler.d.ts → gateway/inbound-handler.d.ts} +1 -1
  24. package/dist/src/gateway/inbound-session-queue-dispatcher.d.ts +1 -1
  25. package/dist/src/messaging/attachment-text-extractor.d.ts +1 -1
  26. package/dist/src/messaging/btw-deliver.d.ts +1 -1
  27. package/dist/src/messaging/channel-outbound.d.ts +1 -1
  28. package/dist/src/{media-utils.d.ts → messaging/media-utils.d.ts} +1 -1
  29. package/dist/src/{message-context-store.d.ts → messaging/message-context-store.d.ts} +7 -1
  30. package/dist/src/{message-utils.d.ts → messaging/message-utils.d.ts} +1 -1
  31. package/dist/src/messaging/quoted-context.d.ts +2 -2
  32. package/dist/src/messaging/quoted-file-service.d.ts +1 -1
  33. package/dist/src/messaging/quoted-ref.d.ts +2 -2
  34. package/dist/src/{reply-strategy-card.d.ts → messaging/reply-strategy-card.d.ts} +1 -1
  35. package/dist/src/{reply-strategy-types.d.ts → messaging/reply-strategy-types.d.ts} +10 -1
  36. package/dist/src/{reply-strategy-with-reaction.d.ts → messaging/reply-strategy-with-reaction.d.ts} +1 -1
  37. package/dist/src/{reply-strategy.d.ts → messaging/reply-strategy.d.ts} +1 -1
  38. package/dist/src/{send-service.d.ts → messaging/send-service.d.ts} +1 -1
  39. package/dist/src/platform/channel-status.d.ts +1 -1
  40. package/dist/src/platform/config.d.ts +110 -0
  41. package/dist/src/platform/runtime-events.d.ts +67 -0
  42. package/dist/src/{types.d.ts → platform/types.d.ts} +74 -1
  43. package/dist/src/{persistence-store.d.ts → shared/persistence-store.d.ts} +1 -1
  44. package/dist/src/{utils.d.ts → shared/utils.d.ts} +1 -1
  45. package/dist/src/targeting/agent-name-matcher.d.ts +1 -1
  46. package/dist/src/targeting/agent-routing.d.ts +3 -3
  47. package/dist/src/{session-routing.d.ts → targeting/session-routing.d.ts} +1 -1
  48. package/index.ts +193 -69
  49. package/openclaw.plugin.json +158 -2
  50. package/package.json +16 -16
  51. package/src/{ack-reaction-classifier.ts → ack-reaction/ack-reaction-classifier.ts} +85 -13
  52. package/src/{ack-reaction-service.ts → ack-reaction/ack-reaction-service.ts} +13 -7
  53. package/src/ack-reaction/dynamic-ack-reaction-controller.ts +46 -31
  54. package/src/ack-reaction/dynamic-ack-reaction-progress.ts +4 -1
  55. package/src/card/ask-user-question-context.ts +1 -1
  56. package/src/card/ask-user-question-store.ts +2 -2
  57. package/src/card/ask-user-question.ts +11 -7
  58. package/src/card/card-action-handler.ts +2 -2
  59. package/src/{card-callback-service.ts → card/card-callback-service.ts} +7 -9
  60. package/src/card/card-draft-controller.ts +770 -0
  61. package/src/card/card-markdown-image-reroute.ts +8 -2
  62. package/src/card/card-run-registry.ts +17 -7
  63. package/src/{card-service.ts → card/card-service.ts} +91 -61
  64. package/src/card/card-stop-handler.ts +12 -8
  65. package/src/card/card-streaming-mode.ts +1 -1
  66. package/src/card/card-task-progress.ts +330 -0
  67. package/src/card/draft-stream-loop.ts +119 -0
  68. package/src/card/reasoning-answer-split.ts +125 -121
  69. package/src/card/reasoning-block-assembler.ts +122 -123
  70. package/src/{run-usage-store.ts → card/run-usage-store.ts} +18 -6
  71. package/src/card/statusline-renderer.ts +14 -5
  72. package/src/card/task-model-metadata.ts +8 -3
  73. package/src/channel.ts +14 -16
  74. package/src/command/card-stop-command.ts +2 -2
  75. package/src/{feedback-learning-service.ts → command/feedback-learning-service.ts} +36 -16
  76. package/src/{feedback-learning-store.ts → command/feedback-learning-store.ts} +133 -81
  77. package/src/command/inbound-command-dispatch-service.ts +12 -6
  78. package/src/{learning-command-service.ts → command/learning-command-service.ts} +36 -29
  79. package/src/{session-command-service.ts → command/session-command-service.ts} +3 -1
  80. package/src/gateway/channel-gateway.ts +106 -28
  81. package/src/{connection-manager.ts → gateway/connection-manager.ts} +45 -30
  82. package/src/{docs-service.ts → gateway/docs-service.ts} +5 -5
  83. package/src/{inbound-handler.ts → gateway/inbound-handler.ts} +139 -84
  84. package/src/gateway/inbound-session-queue-dispatcher.ts +18 -14
  85. package/src/{session-lock.ts → gateway/session-lock.ts} +14 -14
  86. package/src/messaging/attachment-text-extractor.ts +21 -7
  87. package/src/messaging/btw-deliver.ts +2 -2
  88. package/src/messaging/channel-actions.ts +15 -7
  89. package/src/messaging/channel-outbound.ts +16 -11
  90. package/src/{media-utils.ts → messaging/media-utils.ts} +276 -72
  91. package/src/{message-context-store.ts → messaging/message-context-store.ts} +11 -2
  92. package/src/{message-utils.ts → messaging/message-utils.ts} +46 -11
  93. package/src/messaging/quoted-context.ts +2 -2
  94. package/src/messaging/quoted-file-service.ts +311 -294
  95. package/src/messaging/quoted-ref.ts +11 -7
  96. package/src/{reply-strategy-card.ts → messaging/reply-strategy-card.ts} +178 -101
  97. package/src/{reply-strategy-markdown.ts → messaging/reply-strategy-markdown.ts} +8 -2
  98. package/src/{reply-strategy-types.ts → messaging/reply-strategy-types.ts} +11 -1
  99. package/src/{reply-strategy-with-reaction.ts → messaging/reply-strategy-with-reaction.ts} +6 -1
  100. package/src/{reply-strategy.ts → messaging/reply-strategy.ts} +2 -2
  101. package/src/{send-service.ts → messaging/send-service.ts} +100 -65
  102. package/src/{auth.ts → platform/auth.ts} +2 -2
  103. package/src/platform/channel-status.ts +3 -3
  104. package/src/{config-schema.ts → platform/config-schema.ts} +81 -4
  105. package/src/{config.ts → platform/config.ts} +167 -19
  106. package/src/{device-registration.ts → platform/device-registration.ts} +5 -4
  107. package/src/{onboarding.ts → platform/onboarding.ts} +1 -4
  108. package/src/{plugin-sdk-channel-actions-augment.ts → platform/plugin-sdk-channel-actions-augment.ts} +6 -5
  109. package/src/platform/runtime-events.ts +202 -0
  110. package/src/{secret-input.ts → platform/secret-input.ts} +117 -11
  111. package/src/{types.ts → platform/types.ts} +76 -1
  112. package/src/{http-client.ts → shared/http-client.ts} +1 -3
  113. package/src/{persistence-store.ts → shared/persistence-store.ts} +6 -6
  114. package/src/{utils.ts → shared/utils.ts} +30 -13
  115. package/src/targeting/agent-name-matcher.ts +1 -1
  116. package/src/targeting/agent-routing.ts +7 -7
  117. package/src/targeting/group-members-store.ts +1 -1
  118. package/src/{session-peer-store.ts → targeting/session-peer-store.ts} +9 -4
  119. package/src/{session-routing.ts → targeting/session-routing.ts} +1 -1
  120. package/src/targeting/target-directory-adapter.ts +3 -3
  121. package/src/targeting/target-directory-store.ts +1 -1
  122. package/src/targeting/target-input.ts +1 -1
  123. package/dist/src/ack-reaction/dynamic-ack-reaction-events.d.ts +0 -35
  124. package/dist/src/config.d.ts +0 -59
  125. package/src/ack-reaction/dynamic-ack-reaction-events.ts +0 -123
  126. package/src/card-draft-controller.ts +0 -637
  127. package/src/draft-stream-loop.ts +0 -119
  128. /package/dist/src/{ack-reaction-classifier.d.ts → ack-reaction/ack-reaction-classifier.d.ts} +0 -0
  129. /package/dist/src/{card-callback-service.d.ts → card/card-callback-service.d.ts} +0 -0
  130. /package/dist/src/{draft-stream-loop.d.ts → card/draft-stream-loop.d.ts} +0 -0
  131. /package/dist/src/{run-usage-store.d.ts → card/run-usage-store.d.ts} +0 -0
  132. /package/dist/src/{feedback-learning-store.d.ts → command/feedback-learning-store.d.ts} +0 -0
  133. /package/dist/src/{session-command-service.d.ts → command/session-command-service.d.ts} +0 -0
  134. /package/dist/src/{session-lock.d.ts → gateway/session-lock.d.ts} +0 -0
  135. /package/dist/src/{proactive-risk-registry.d.ts → messaging/proactive-risk-registry.d.ts} +0 -0
  136. /package/dist/src/{reply-strategy-markdown.d.ts → messaging/reply-strategy-markdown.d.ts} +0 -0
  137. /package/dist/src/{access-control.d.ts → platform/access-control.d.ts} +0 -0
  138. /package/dist/src/{auth.d.ts → platform/auth.d.ts} +0 -0
  139. /package/dist/src/{config-schema.d.ts → platform/config-schema.d.ts} +0 -0
  140. /package/dist/src/{device-registration.d.ts → platform/device-registration.d.ts} +0 -0
  141. /package/dist/src/{logger-context.d.ts → platform/logger-context.d.ts} +0 -0
  142. /package/dist/src/{onboarding.d.ts → platform/onboarding.d.ts} +0 -0
  143. /package/dist/src/{plugin-sdk-channel-actions-augment.d.ts → platform/plugin-sdk-channel-actions-augment.d.ts} +0 -0
  144. /package/dist/src/{runtime.d.ts → platform/runtime.d.ts} +0 -0
  145. /package/dist/src/{secret-input.d.ts → platform/secret-input.d.ts} +0 -0
  146. /package/dist/src/{session-state.d.ts → platform/session-state.d.ts} +0 -0
  147. /package/dist/src/{signature.d.ts → platform/signature.d.ts} +0 -0
  148. /package/dist/src/{dedup.d.ts → shared/dedup.d.ts} +0 -0
  149. /package/dist/src/{http-client.d.ts → shared/http-client.d.ts} +0 -0
  150. /package/dist/src/{path-utils.d.ts → shared/path-utils.d.ts} +0 -0
  151. /package/dist/src/{peer-id-registry.d.ts → targeting/peer-id-registry.d.ts} +0 -0
  152. /package/dist/src/{session-peer-store.d.ts → targeting/session-peer-store.d.ts} +0 -0
  153. /package/src/{proactive-risk-registry.ts → messaging/proactive-risk-registry.ts} +0 -0
  154. /package/src/{access-control.ts → platform/access-control.ts} +0 -0
  155. /package/src/{logger-context.ts → platform/logger-context.ts} +0 -0
  156. /package/src/{runtime.ts → platform/runtime.ts} +0 -0
  157. /package/src/{session-state.ts → platform/session-state.ts} +0 -0
  158. /package/src/{signature.ts → platform/signature.ts} +0 -0
  159. /package/src/{dedup.ts → shared/dedup.ts} +0 -0
  160. /package/src/{path-utils.ts → shared/path-utils.ts} +0 -0
  161. /package/src/{peer-id-registry.ts → targeting/peer-id-registry.ts} +0 -0
@@ -1,162 +1,166 @@
1
1
  export interface CardReasoningAnswerSplit {
2
- reasoningText?: string;
3
- answerText?: string;
2
+ reasoningText?: string;
3
+ answerText?: string;
4
4
  }
5
5
 
6
6
  const THINKING_TAG_RE = /<\s*(\/?)\s*(?:think(?:ing)?|thought|antthinking)\b[^<>]*>/gi;
7
7
 
8
8
  function isWrappedReasoningLine(line: string): boolean {
9
- const trimmed = line.trim();
10
- return trimmed.startsWith("_") && trimmed.endsWith("_") && trimmed.length >= 3;
9
+ const trimmed = line.trim();
10
+ return trimmed.startsWith("_") && trimmed.endsWith("_") && trimmed.length >= 3;
11
11
  }
12
12
 
13
13
  function cleanReasoningLine(line: string): string {
14
- const trimmed = line.trim();
15
- if (!trimmed) {
16
- return "";
17
- }
18
- return trimmed.replace(/^_/, "").replace(/_$/, "").trim();
14
+ const trimmed = line.trim();
15
+ if (!trimmed) {
16
+ return "";
17
+ }
18
+ return trimmed.replace(/^_/, "").replace(/_$/, "").trim();
19
19
  }
20
20
 
21
21
  function joinAnswerParts(parts: string[]): string | undefined {
22
- const joined = parts.map((part) => part.trim()).filter(Boolean).join("\n\n").trim();
23
- return joined || undefined;
22
+ const joined = parts
23
+ .map((part) => part.trim())
24
+ .filter(Boolean)
25
+ .join("\n\n")
26
+ .trim();
27
+ return joined || undefined;
24
28
  }
25
29
 
26
30
  function hasStructuredMarkdown(text: string): boolean {
27
- const trimmed = text.trim();
28
- if (!trimmed) {
29
- return false;
30
- }
31
- return (
32
- trimmed.includes("**")
33
- || trimmed.includes("```")
34
- || /(^|\n)\s*(?:[-*+]\s|#{1,6}\s|>\s|\d+\.\s)/.test(trimmed)
35
- );
31
+ const trimmed = text.trim();
32
+ if (!trimmed) {
33
+ return false;
34
+ }
35
+ return (
36
+ trimmed.includes("**") ||
37
+ trimmed.includes("```") ||
38
+ /(^|\n)\s*(?:[-*+]\s|#{1,6}\s|>\s|\d+\.\s)/.test(trimmed)
39
+ );
36
40
  }
37
41
 
38
42
  function splitTopLevelReasoningPrefix(text: string): CardReasoningAnswerSplit | null {
39
- const markerIndex = text.indexOf("Reasoning:");
40
- if (markerIndex < 0) {
41
- return null;
42
- }
43
+ const markerIndex = text.indexOf("Reasoning:");
44
+ if (markerIndex < 0) {
45
+ return null;
46
+ }
47
+
48
+ const before = text.slice(0, markerIndex).trim();
49
+ if (before && hasStructuredMarkdown(before)) {
50
+ return {
51
+ answerText: text,
52
+ };
53
+ }
54
+
55
+ const trailing = text.slice(markerIndex + "Reasoning:".length);
56
+ const lines = trailing.split("\n");
57
+ const reasoningLines: string[] = [];
58
+ let started = false;
59
+ let remainderIndex = -1;
43
60
 
44
- const before = text.slice(0, markerIndex).trim();
45
- if (before && hasStructuredMarkdown(before)) {
61
+ for (let index = 0; index < lines.length; index += 1) {
62
+ const line = lines[index];
63
+ const trimmed = line.trim();
64
+
65
+ if (!started) {
66
+ if (!trimmed) {
67
+ continue;
68
+ }
69
+ if (!isWrappedReasoningLine(trimmed)) {
46
70
  return {
47
- answerText: text,
71
+ answerText: text,
48
72
  };
73
+ }
74
+ started = true;
75
+ reasoningLines.push(cleanReasoningLine(trimmed));
76
+ continue;
49
77
  }
50
78
 
51
- const trailing = text.slice(markerIndex + "Reasoning:".length);
52
- const lines = trailing.split("\n");
53
- const reasoningLines: string[] = [];
54
- let started = false;
55
- let remainderIndex = -1;
56
-
57
- for (let index = 0; index < lines.length; index += 1) {
58
- const line = lines[index];
59
- const trimmed = line.trim();
60
-
61
- if (!started) {
62
- if (!trimmed) {
63
- continue;
64
- }
65
- if (!isWrappedReasoningLine(trimmed)) {
66
- return {
67
- answerText: text,
68
- };
69
- }
70
- started = true;
71
- reasoningLines.push(cleanReasoningLine(trimmed));
72
- continue;
73
- }
74
-
75
- if (!trimmed) {
76
- continue;
77
- }
78
-
79
- if (isWrappedReasoningLine(trimmed)) {
80
- reasoningLines.push(cleanReasoningLine(trimmed));
81
- continue;
82
- }
83
-
84
- remainderIndex = index;
85
- break;
79
+ if (!trimmed) {
80
+ continue;
86
81
  }
87
82
 
88
- if (reasoningLines.length === 0) {
89
- return {
90
- answerText: text,
91
- };
83
+ if (isWrappedReasoningLine(trimmed)) {
84
+ reasoningLines.push(cleanReasoningLine(trimmed));
85
+ continue;
92
86
  }
93
87
 
94
- const after = remainderIndex >= 0 ? lines.slice(remainderIndex).join("\n").trim() : "";
88
+ remainderIndex = index;
89
+ break;
90
+ }
91
+
92
+ if (reasoningLines.length === 0) {
95
93
  return {
96
- reasoningText: reasoningLines.join("\n").trim() || undefined,
97
- answerText: joinAnswerParts([before, after]),
94
+ answerText: text,
98
95
  };
96
+ }
97
+
98
+ const after = remainderIndex >= 0 ? lines.slice(remainderIndex).join("\n").trim() : "";
99
+ return {
100
+ reasoningText: reasoningLines.join("\n").trim() || undefined,
101
+ answerText: joinAnswerParts([before, after]),
102
+ };
99
103
  }
100
104
 
101
105
  function splitTopLevelThinkingTags(text: string): CardReasoningAnswerSplit | null {
102
- if (!THINKING_TAG_RE.test(text)) {
103
- return null;
104
- }
105
- THINKING_TAG_RE.lastIndex = 0;
106
-
107
- let reasoning = "";
108
- let answer = "";
109
- let lastIndex = 0;
110
- let inThinking = false;
111
-
112
- for (const match of text.matchAll(THINKING_TAG_RE)) {
113
- const matchIndex = match.index ?? 0;
114
- const segment = text.slice(lastIndex, matchIndex);
115
- if (inThinking) {
116
- reasoning += segment;
117
- } else {
118
- answer += segment;
119
- }
120
- inThinking = match[1] !== "/";
121
- lastIndex = matchIndex + match[0].length;
122
- }
123
-
124
- const tail = text.slice(lastIndex);
106
+ if (!THINKING_TAG_RE.test(text)) {
107
+ return null;
108
+ }
109
+ THINKING_TAG_RE.lastIndex = 0;
110
+
111
+ let reasoning = "";
112
+ let answer = "";
113
+ let lastIndex = 0;
114
+ let inThinking = false;
115
+
116
+ for (const match of text.matchAll(THINKING_TAG_RE)) {
117
+ const matchIndex = match.index ?? 0;
118
+ const segment = text.slice(lastIndex, matchIndex);
125
119
  if (inThinking) {
126
- reasoning += tail;
120
+ reasoning += segment;
127
121
  } else {
128
- answer += tail;
122
+ answer += segment;
129
123
  }
130
-
131
- const cleanedReasoning = reasoning.trim();
132
- if (!cleanedReasoning) {
133
- return {
134
- answerText: text,
135
- };
136
- }
137
-
124
+ inThinking = match[1] !== "/";
125
+ lastIndex = matchIndex + match[0].length;
126
+ }
127
+
128
+ const tail = text.slice(lastIndex);
129
+ if (inThinking) {
130
+ reasoning += tail;
131
+ } else {
132
+ answer += tail;
133
+ }
134
+
135
+ const cleanedReasoning = reasoning.trim();
136
+ if (!cleanedReasoning) {
138
137
  return {
139
- reasoningText: cleanedReasoning,
140
- answerText: answer.trim() || undefined,
138
+ answerText: text,
141
139
  };
140
+ }
141
+
142
+ return {
143
+ reasoningText: cleanedReasoning,
144
+ answerText: answer.trim() || undefined,
145
+ };
142
146
  }
143
147
 
144
148
  export function splitCardReasoningAnswerText(text?: string): CardReasoningAnswerSplit {
145
- if (typeof text !== "string") {
146
- return {};
147
- }
148
-
149
- const prefixed = splitTopLevelReasoningPrefix(text);
150
- if (prefixed) {
151
- return prefixed;
152
- }
153
-
154
- const tagged = splitTopLevelThinkingTags(text);
155
- if (tagged) {
156
- return tagged;
157
- }
158
-
159
- return {
160
- answerText: text,
161
- };
149
+ if (typeof text !== "string") {
150
+ return {};
151
+ }
152
+
153
+ const prefixed = splitTopLevelReasoningPrefix(text);
154
+ if (prefixed) {
155
+ return prefixed;
156
+ }
157
+
158
+ const tagged = splitTopLevelThinkingTags(text);
159
+ if (tagged) {
160
+ return tagged;
161
+ }
162
+
163
+ return {
164
+ answerText: text,
165
+ };
162
166
  }
@@ -1,157 +1,156 @@
1
1
  export interface ReasoningBlockAssembler {
2
- ingestSnapshot: (text: string | undefined) => string[];
3
- flushPendingAtBoundary: () => string[];
4
- reset: () => void;
2
+ ingestSnapshot: (text: string | undefined) => string[];
3
+ flushPendingAtBoundary: () => string[];
4
+ reset: () => void;
5
5
  }
6
6
 
7
7
  function stripReasoningPrefix(text: string): string {
8
- const trimmed = text.trim();
9
- if (trimmed.startsWith("Reasoning:")) {
10
- return trimmed.slice("Reasoning:".length).trimStart();
11
- }
12
- return trimmed;
8
+ const trimmed = text.trim();
9
+ if (trimmed.startsWith("Reasoning:")) {
10
+ return trimmed.slice("Reasoning:".length).trimStart();
11
+ }
12
+ return trimmed;
13
13
  }
14
14
 
15
15
  function cleanReasoningLine(line: string): string {
16
- return line.trim().replace(/^_/, "").replace(/_$/, "").trim();
16
+ return line.trim().replace(/^_/, "").replace(/_$/, "").trim();
17
17
  }
18
18
 
19
19
  function isClosedReasoningLine(line: string): boolean {
20
- const trimmed = line.trim();
21
- return trimmed.startsWith("_") && trimmed.endsWith("_") && trimmed.length >= 2;
20
+ const trimmed = line.trim();
21
+ return trimmed.startsWith("_") && trimmed.endsWith("_") && trimmed.length >= 2;
22
22
  }
23
23
 
24
24
  function startsReasonBlock(line: string): boolean {
25
- return cleanReasoningLine(line).startsWith("Reason:");
25
+ return cleanReasoningLine(line).startsWith("Reason:");
26
26
  }
27
27
 
28
28
  function blocksStartWithPrefix(blocks: string[], prefix: string[]): boolean {
29
- if (prefix.length > blocks.length) {
30
- return false;
31
- }
32
- return prefix.every((entry, index) => blocks[index] === entry);
29
+ if (prefix.length > blocks.length) {
30
+ return false;
31
+ }
32
+ return prefix.every((entry, index) => blocks[index] === entry);
33
33
  }
34
34
 
35
35
  function parseReasoningSnapshot(text: string | undefined): {
36
- completeBlocks: string[];
37
- pendingBlock: string;
36
+ completeBlocks: string[];
37
+ pendingBlock: string;
38
38
  } {
39
- const normalized = typeof text === "string" ? stripReasoningPrefix(text) : "";
40
- if (!normalized.trim()) {
41
- return {
42
- completeBlocks: [],
43
- pendingBlock: "",
44
- };
45
- }
46
-
47
- const lines = normalized
48
- .split("\n")
49
- .map((line) => line.trim())
50
- .filter((line) => line.length > 0);
51
-
52
- const completeBlocks: string[] = [];
53
- let currentLines: string[] = [];
54
- let currentMode: "explicit" | "implicit" | null = null;
55
- let currentComplete = true;
56
-
57
- const finalizeCurrent = () => {
58
- if (currentLines.length === 0) {
59
- return;
60
- }
61
- if (currentMode === "explicit" && currentComplete) {
62
- completeBlocks.push(currentLines.join("\n"));
63
- }
39
+ const normalized = typeof text === "string" ? stripReasoningPrefix(text) : "";
40
+ if (!normalized.trim()) {
41
+ return {
42
+ completeBlocks: [],
43
+ pendingBlock: "",
64
44
  };
45
+ }
65
46
 
66
- for (const line of lines) {
67
- if (startsReasonBlock(line)) {
68
- finalizeCurrent();
69
- currentLines = [cleanReasoningLine(line)];
70
- currentMode = "explicit";
71
- currentComplete = isClosedReasoningLine(line);
72
- continue;
73
- }
74
-
75
- if (currentLines.length === 0) {
76
- const trimmedLine = line.trim();
77
- const cleanedLine = cleanReasoningLine(line);
78
- if (!cleanedLine) {
79
- continue;
80
- }
81
- if (!trimmedLine.startsWith("_")) {
82
- continue;
83
- }
84
- currentLines = [cleanedLine];
85
- currentMode = "implicit";
86
- currentComplete = false;
87
- continue;
88
- }
89
-
90
- currentLines.push(cleanReasoningLine(line));
91
- currentComplete = currentMode === "explicit"
92
- ? currentComplete && isClosedReasoningLine(line)
93
- : false;
94
- }
47
+ const lines = normalized
48
+ .split("\n")
49
+ .map((line) => line.trim())
50
+ .filter((line) => line.length > 0);
51
+
52
+ const completeBlocks: string[] = [];
53
+ let currentLines: string[] = [];
54
+ let currentMode: "explicit" | "implicit" | null = null;
55
+ let currentComplete = true;
95
56
 
57
+ const finalizeCurrent = () => {
96
58
  if (currentLines.length === 0) {
97
- return {
98
- completeBlocks,
99
- pendingBlock: "",
100
- };
59
+ return;
101
60
  }
102
-
103
61
  if (currentMode === "explicit" && currentComplete) {
104
- completeBlocks.push(currentLines.join("\n"));
105
- return {
106
- completeBlocks,
107
- pendingBlock: "",
108
- };
62
+ completeBlocks.push(currentLines.join("\n"));
63
+ }
64
+ };
65
+
66
+ for (const line of lines) {
67
+ if (startsReasonBlock(line)) {
68
+ finalizeCurrent();
69
+ currentLines = [cleanReasoningLine(line)];
70
+ currentMode = "explicit";
71
+ currentComplete = isClosedReasoningLine(line);
72
+ continue;
73
+ }
74
+
75
+ if (currentLines.length === 0) {
76
+ const trimmedLine = line.trim();
77
+ const cleanedLine = cleanReasoningLine(line);
78
+ if (!cleanedLine) {
79
+ continue;
80
+ }
81
+ if (!trimmedLine.startsWith("_")) {
82
+ continue;
83
+ }
84
+ currentLines = [cleanedLine];
85
+ currentMode = "implicit";
86
+ currentComplete = false;
87
+ continue;
109
88
  }
110
89
 
90
+ currentLines.push(cleanReasoningLine(line));
91
+ currentComplete =
92
+ currentMode === "explicit" ? currentComplete && isClosedReasoningLine(line) : false;
93
+ }
94
+
95
+ if (currentLines.length === 0) {
111
96
  return {
112
- completeBlocks,
113
- pendingBlock: currentLines.join("\n").trim(),
97
+ completeBlocks,
98
+ pendingBlock: "",
114
99
  };
115
- }
116
-
117
- export function createReasoningBlockAssembler(): ReasoningBlockAssembler {
118
- let emittedBlocks: string[] = [];
119
- let pendingBlock = "";
100
+ }
120
101
 
102
+ if (currentMode === "explicit" && currentComplete) {
103
+ completeBlocks.push(currentLines.join("\n"));
121
104
  return {
122
- ingestSnapshot(text: string | undefined): string[] {
123
- const parsed = parseReasoningSnapshot(text);
124
- pendingBlock = parsed.pendingBlock;
125
-
126
- if (parsed.completeBlocks.length === 0) {
127
- return [];
128
- }
129
-
130
- if (blocksStartWithPrefix(parsed.completeBlocks, emittedBlocks)) {
131
- const nextBlocks = parsed.completeBlocks.slice(emittedBlocks.length);
132
- emittedBlocks = [...parsed.completeBlocks];
133
- return nextBlocks;
134
- }
135
-
136
- if (blocksStartWithPrefix(emittedBlocks, parsed.completeBlocks)) {
137
- return [];
138
- }
139
-
140
- return [];
141
- },
142
-
143
- flushPendingAtBoundary(): string[] {
144
- if (!pendingBlock.trim()) {
145
- return [];
146
- }
147
- const flushed = pendingBlock;
148
- pendingBlock = "";
149
- return [flushed];
150
- },
151
-
152
- reset(): void {
153
- emittedBlocks = [];
154
- pendingBlock = "";
155
- },
105
+ completeBlocks,
106
+ pendingBlock: "",
156
107
  };
108
+ }
109
+
110
+ return {
111
+ completeBlocks,
112
+ pendingBlock: currentLines.join("\n").trim(),
113
+ };
114
+ }
115
+
116
+ export function createReasoningBlockAssembler(): ReasoningBlockAssembler {
117
+ let emittedBlocks: string[] = [];
118
+ let pendingBlock = "";
119
+
120
+ return {
121
+ ingestSnapshot(text: string | undefined): string[] {
122
+ const parsed = parseReasoningSnapshot(text);
123
+ pendingBlock = parsed.pendingBlock;
124
+
125
+ if (parsed.completeBlocks.length === 0) {
126
+ return [];
127
+ }
128
+
129
+ if (blocksStartWithPrefix(parsed.completeBlocks, emittedBlocks)) {
130
+ const nextBlocks = parsed.completeBlocks.slice(emittedBlocks.length);
131
+ emittedBlocks = [...parsed.completeBlocks];
132
+ return nextBlocks;
133
+ }
134
+
135
+ if (blocksStartWithPrefix(emittedBlocks, parsed.completeBlocks)) {
136
+ return [];
137
+ }
138
+
139
+ return [];
140
+ },
141
+
142
+ flushPendingAtBoundary(): string[] {
143
+ if (!pendingBlock.trim()) {
144
+ return [];
145
+ }
146
+ const flushed = pendingBlock;
147
+ pendingBlock = "";
148
+ return [flushed];
149
+ },
150
+
151
+ reset(): void {
152
+ emittedBlocks = [];
153
+ pendingBlock = "";
154
+ },
155
+ };
157
156
  }
@@ -16,7 +16,9 @@ export function recordRunStart(runId: string): void {
16
16
 
17
17
  export function accumulateUsage(runId: string, usage: UsageAccumulation): void {
18
18
  const existing = usageStore.get(runId);
19
- if (!existing) { return; }
19
+ if (!existing) {
20
+ return;
21
+ }
20
22
 
21
23
  for (const field of ["input", "output", "cacheRead", "cacheWrite", "total"] as const) {
22
24
  const value = usage[field];
@@ -32,10 +34,14 @@ export function getUsageByRunId(runId: string): UsageAccumulation | undefined {
32
34
 
33
35
  export function getAggregatedUsage(runIds: Set<string> | undefined): UsageAccumulation {
34
36
  const result: UsageAccumulation = {};
35
- if (!runIds) { return result; }
37
+ if (!runIds) {
38
+ return result;
39
+ }
36
40
  for (const runId of runIds) {
37
41
  const usage = usageStore.get(runId);
38
- if (!usage) { continue; }
42
+ if (!usage) {
43
+ continue;
44
+ }
39
45
  for (const field of ["input", "output", "cacheRead", "cacheWrite", "total"] as const) {
40
46
  if (typeof usage[field] === "number") {
41
47
  result[field] = (result[field] ?? 0) + usage[field];
@@ -46,12 +52,18 @@ export function getAggregatedUsage(runIds: Set<string> | undefined): UsageAccumu
46
52
  }
47
53
 
48
54
  export function clearRun(runId: string | undefined): void {
49
- if (runId) { usageStore.delete(runId); }
55
+ if (runId) {
56
+ usageStore.delete(runId);
57
+ }
50
58
  }
51
59
 
52
60
  export function clearRuns(runIds: Set<string> | undefined): void {
53
- if (!runIds) { return; }
54
- for (const runId of runIds) { usageStore.delete(runId); }
61
+ if (!runIds) {
62
+ return;
63
+ }
64
+ for (const runId of runIds) {
65
+ usageStore.delete(runId);
66
+ }
55
67
  }
56
68
 
57
69
  export function clearAllForTest(): void {
@@ -67,8 +67,16 @@ const SEGMENTS: Segment[] = [
67
67
  { key: "effort", defaultOn: true, render: (d) => d.effort || undefined },
68
68
  { key: "agent", defaultOn: true, render: (d) => d.agent || undefined },
69
69
  { key: "tokens", defaultOn: false, render: renderTokenSegment },
70
- { key: "taskTime", defaultOn: false, render: (d) => typeof d.taskTime === "number" ? formatDuration(d.taskTime) : undefined },
71
- { key: "dapiUsage", defaultOn: false, render: (d) => typeof d.dapi_usage === "number" ? `DAPI+${d.dapi_usage}` : undefined },
70
+ {
71
+ key: "taskTime",
72
+ defaultOn: false,
73
+ render: (d) => (typeof d.taskTime === "number" ? formatDuration(d.taskTime) : undefined),
74
+ },
75
+ {
76
+ key: "dapiUsage",
77
+ defaultOn: false,
78
+ render: (d) => (typeof d.dapi_usage === "number" ? `DAPI+${d.dapi_usage}` : undefined),
79
+ },
72
80
  ];
73
81
 
74
82
  const SEGMENTS_PER_LINE = 3;
@@ -79,12 +87,13 @@ function resolveSegmentEnabled(seg: Segment, config: StatusLineConfig): boolean
79
87
  }
80
88
 
81
89
  export function renderStatusLine(data: StatusLineData, config: StatusLineConfig): string {
82
- const rendered = SEGMENTS
83
- .filter((seg) => resolveSegmentEnabled(seg, config))
90
+ const rendered = SEGMENTS.filter((seg) => resolveSegmentEnabled(seg, config))
84
91
  .map((seg) => seg.render(data))
85
92
  .filter(Boolean) as string[];
86
93
 
87
- if (rendered.length === 0) { return ""; }
94
+ if (rendered.length === 0) {
95
+ return "";
96
+ }
88
97
 
89
98
  const lines: string[] = [];
90
99
  for (let i = 0; i < rendered.length; i += SEGMENTS_PER_LINE) {
@@ -22,7 +22,10 @@ export function normalizeModelDisplayName(modelRef: string | undefined): string
22
22
  if (!trimmed) {
23
23
  return undefined;
24
24
  }
25
- const parts = trimmed.split("/").map((part) => part.trim()).filter(Boolean);
25
+ const parts = trimmed
26
+ .split("/")
27
+ .map((part) => part.trim())
28
+ .filter(Boolean);
26
29
  return parts.at(-1) || undefined;
27
30
  }
28
31
 
@@ -36,11 +39,13 @@ export function resolveConfiguredTaskModelMetadata(params: {
36
39
  ? agents.list.find((entry) => String(entry.id || "").trim() === agentId)
37
40
  : undefined;
38
41
 
39
- const modelRef = readPrimaryModelRef(agent?.model) ?? readPrimaryModelRef(agents?.defaults?.model);
42
+ const modelRef =
43
+ readPrimaryModelRef(agent?.model) ?? readPrimaryModelRef(agents?.defaults?.model);
40
44
  const effort =
41
45
  typeof agent?.thinkingDefault === "string" && agent.thinkingDefault.trim()
42
46
  ? agent.thinkingDefault.trim()
43
- : typeof agents?.defaults?.thinkingDefault === "string" && agents.defaults.thinkingDefault.trim()
47
+ : typeof agents?.defaults?.thinkingDefault === "string" &&
48
+ agents.defaults.thinkingDefault.trim()
44
49
  ? agents.defaults.thinkingDefault.trim()
45
50
  : undefined;
46
51