@zq-silk/yui 2.3.0 → 2.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.
Files changed (183) hide show
  1. package/README.md +15 -1
  2. package/dist/artifacts/artifactCapability.js +39 -10
  3. package/dist/artifacts/imageMetadata.js +120 -0
  4. package/dist/artifacts/managedGit.js +7 -4
  5. package/dist/artifacts/taskArtifactRepository.js +6 -0
  6. package/dist/cli/commandCatalog.js +17 -8
  7. package/dist/cli/invocationAuthority.js +1 -1
  8. package/dist/commands/executionAuditCommands.js +5 -0
  9. package/dist/commands/globalRoleCommands.js +41 -3
  10. package/dist/commands/projectCommands.js +89 -94
  11. package/dist/commands/roleSkillValidation.js +4 -8
  12. package/dist/commands/taskCommands.js +25 -2
  13. package/dist/commands/taskUsageCommand.js +38 -0
  14. package/dist/context/roleSessionContext.js +18 -2
  15. package/dist/context/runContextPack.js +5 -1
  16. package/dist/context/sessionBootstrapManifest.js +10 -1
  17. package/dist/context/skillCatalog.js +108 -0
  18. package/dist/context/skillPackage.js +161 -0
  19. package/dist/context/taskContext.js +3 -2
  20. package/dist/context/taskSearch.js +127 -0
  21. package/dist/controlPlaneCli.js +25 -20
  22. package/dist/controller/fileSchedulerStoreAdapter.js +32 -6
  23. package/dist/controller/jobControl.js +2 -0
  24. package/dist/controller/nativeHostInput.js +37 -0
  25. package/dist/controller/runtime.js +93 -2
  26. package/dist/controller/runtimeEventInbox.js +2 -2
  27. package/dist/controller/runtimeEventProcessor.js +3 -3
  28. package/dist/doctor/doctor.js +10 -0
  29. package/dist/execution/reviewMainRun.js +1 -0
  30. package/dist/execution/workItemMainRun.js +1 -0
  31. package/dist/executor/codexConfigConflict.js +6 -4
  32. package/dist/executor/effectiveLaunch.js +24 -1
  33. package/dist/executor/fileRoleLaunchPlanner.js +13 -5
  34. package/dist/integration/gitIntegrationService.js +7 -12
  35. package/dist/integration/integrationSourceApplication.js +4 -2
  36. package/dist/job/httpPreview.js +61 -0
  37. package/dist/job/jobRunner.js +12 -2
  38. package/dist/kernel/builtinCapabilities.js +3 -1
  39. package/dist/message/message.js +15 -1
  40. package/dist/output/rolePresentation.js +4 -1
  41. package/dist/repository/executionLaneGitSnapshot.js +2 -1
  42. package/dist/repository/gitCompatibility.js +62 -0
  43. package/dist/repository/gitWorkspace.js +48 -71
  44. package/dist/repository/gitWorktreeInventory.js +121 -0
  45. package/dist/repository/project.js +74 -25
  46. package/dist/resources/resourceDiscovery.js +2 -2
  47. package/dist/resources/resourceGc.js +7 -4
  48. package/dist/resources/resourceRegistrar.js +2 -1
  49. package/dist/runtime/agentEndpoint.js +8 -0
  50. package/dist/runtime/agentHost.js +170 -3
  51. package/dist/runtime/codexAppServerRuntime.js +1 -1
  52. package/dist/runtime/codexNativeAccess.js +175 -0
  53. package/dist/runtime/controlledCodexTui.js +116 -0
  54. package/dist/runtime/publicReply.js +23 -0
  55. package/dist/runtime/runtimeObservation.js +48 -0
  56. package/dist/runtime/structuredProviderHost.js +16 -7
  57. package/dist/runtime/taskCostMetrics.js +133 -0
  58. package/dist/runtime/taskUsageMetrics.js +11 -2
  59. package/dist/runtime/taskUsageQuery.js +38 -0
  60. package/dist/scheduler/taskExecutionProjection.js +2 -0
  61. package/dist/scheduler/taskObservabilityProjection.js +9 -1
  62. package/dist/storage/homeLayout.js +13 -0
  63. package/dist/storage/sqliteSchema.js +44 -0
  64. package/dist/storage/sqliteStore.js +53 -0
  65. package/dist/storage/storageVersions.js +1 -1
  66. package/dist/storage/storeRpc.js +2 -0
  67. package/dist/storage/taskSearch.js +35 -0
  68. package/dist/storage/upgrade/projectKnowledgeMigration.js +52 -0
  69. package/dist/task/ordinaryArchive.js +42 -0
  70. package/dist/tmux/tmuxManager.js +8 -8
  71. package/dist/web/assets/assetManifest.js +11 -51
  72. package/dist/web/assets/client/app/catalog.js +215 -0
  73. package/dist/web/assets/client/app/main.js +148 -0
  74. package/dist/web/assets/client/app/selection.js +139 -0
  75. package/dist/web/assets/client/app/settings.js +326 -0
  76. package/dist/web/assets/client/app/taskView.js +280 -0
  77. package/dist/web/assets/client/domain/context.js +96 -0
  78. package/dist/web/assets/client/domain/records.js +126 -0
  79. package/dist/web/assets/client/domain/runs.js +119 -0
  80. package/dist/web/assets/client/domain/taskForms.js +197 -0
  81. package/dist/web/assets/client/domain/vocab.js +69 -0
  82. package/dist/web/assets/client/domain/work.js +116 -0
  83. package/dist/web/assets/client/i18n/en.js +900 -0
  84. package/dist/web/assets/client/i18n/zh-CN.js +898 -0
  85. package/dist/web/assets/client/index.js +114 -0
  86. package/dist/web/assets/client/layout/resizer.js +37 -0
  87. package/dist/web/assets/client/layout/router.js +35 -0
  88. package/dist/web/assets/client/layout/shortcuts.js +45 -0
  89. package/dist/web/assets/client/layout/sizing.js +95 -0
  90. package/dist/web/assets/client/layout/workspace.js +247 -0
  91. package/dist/web/assets/client/{api.js → lib/api.js} +20 -4
  92. package/dist/web/assets/client/{dom.js → lib/dom.js} +24 -12
  93. package/dist/web/assets/client/{format.js → lib/format.js} +7 -0
  94. package/dist/web/assets/client/lib/i18n.js +54 -0
  95. package/dist/web/assets/client/lib/markdown.js +167 -0
  96. package/dist/web/assets/client/lib/prefs.js +28 -0
  97. package/dist/web/assets/client/lib/theme.js +68 -0
  98. package/dist/web/assets/client/ui/containers.js +101 -0
  99. package/dist/web/assets/client/ui/controls.js +51 -0
  100. package/dist/web/assets/client/ui/forms.js +48 -0
  101. package/dist/web/assets/client/ui/metrics.js +137 -0
  102. package/dist/web/assets/client/ui/primitives.js +92 -0
  103. package/dist/web/assets/client/ui/text.js +33 -0
  104. package/dist/web/assets/client/ui/toast.js +12 -0
  105. package/dist/web/assets/client/views/bodySearch.js +172 -0
  106. package/dist/web/assets/client/views/createTask.js +85 -0
  107. package/dist/web/assets/client/views/dock/conversation.js +612 -0
  108. package/dist/web/assets/client/views/dock/discussion.js +173 -0
  109. package/dist/web/assets/client/views/dock/preview.js +129 -0
  110. package/dist/web/assets/client/views/dock/terminal.js +199 -0
  111. package/dist/web/assets/client/views/globalInput.js +67 -0
  112. package/dist/web/assets/client/{overview.js → views/overview.js} +61 -51
  113. package/dist/web/assets/client/{sidebar.js → views/sidebar.js} +56 -62
  114. package/dist/web/assets/client/views/skills.js +152 -0
  115. package/dist/web/assets/client/views/task/actions.js +36 -0
  116. package/dist/web/assets/client/views/task/delivery.js +185 -0
  117. package/dist/web/assets/client/views/task/deliveryResults.js +159 -0
  118. package/dist/web/assets/client/views/task/files.js +272 -0
  119. package/dist/web/assets/client/views/task/observation.js +153 -0
  120. package/dist/web/assets/client/views/task/overview.js +161 -0
  121. package/dist/web/assets/client/views/task/page.js +131 -0
  122. package/dist/web/assets/client/views/task/records.js +163 -0
  123. package/dist/web/assets/client/views/task/runtime.js +130 -0
  124. package/dist/web/assets/client/views/task/timeline.js +190 -0
  125. package/dist/web/assets/shared/geometry.js +19 -0
  126. package/dist/web/assets/shared/taskTabs.js +8 -0
  127. package/dist/web/assets/shared/themes.js +93 -0
  128. package/dist/web/assets/shell/dialogs.js +63 -0
  129. package/dist/web/assets/shell/dock.js +40 -0
  130. package/dist/web/assets/shell/index.js +40 -0
  131. package/dist/web/assets/shell/settings.js +34 -0
  132. package/dist/web/assets/shell/sidebar.js +45 -0
  133. package/dist/web/assets/styles/index.js +41 -0
  134. package/dist/web/assets/styles/{responsive.js → layout/responsive.js} +10 -10
  135. package/dist/web/assets/styles/{layout.js → layout/workspace.js} +17 -24
  136. package/dist/web/assets/styles/markdown.js +22 -3
  137. package/dist/web/assets/styles/tokens.js +10 -63
  138. package/dist/web/assets/styles/ui/controls.js +76 -0
  139. package/dist/web/assets/styles/ui/forms.js +46 -0
  140. package/dist/web/assets/styles/ui/surfaces.js +122 -0
  141. package/dist/web/assets/styles/views/delivery.js +29 -0
  142. package/dist/web/assets/styles/views/dock.js +71 -0
  143. package/dist/web/assets/styles/views/page.js +32 -0
  144. package/dist/web/assets/styles/views/records.js +70 -0
  145. package/dist/web/assets/styles/views/settings.js +26 -0
  146. package/dist/web/assets/styles/views/sidebar.js +74 -0
  147. package/dist/web/assets/styles/views/task.js +80 -0
  148. package/dist/web/assets/styles/views/terminal.js +38 -0
  149. package/dist/web/taskPreviews.js +205 -0
  150. package/dist/web/tmuxWebTerminal.js +16 -9
  151. package/dist/web/webConversation.js +373 -0
  152. package/dist/web/webMaterials.js +155 -0
  153. package/dist/web/webServer.js +295 -18
  154. package/dist/web/webSettings.js +331 -0
  155. package/dist/web/webSkills.js +86 -0
  156. package/dist/web/webSnapshot.js +40 -8
  157. package/dist/web/webTaskSurface.js +106 -8
  158. package/dist/workspace/gitChangeSetCapture.js +3 -1
  159. package/docs/managed-turn-and-session-runtime.md +9 -0
  160. package/docs/managed-turn-and-session-runtime.zh-CN.md +7 -0
  161. package/docs/release-workflow.md +28 -0
  162. package/docs/release-workflow.zh-CN.md +21 -0
  163. package/docs/storage-baseline.md +38 -1
  164. package/docs/storage-baseline.zh-CN.md +22 -0
  165. package/docs/task-discovery.md +28 -0
  166. package/docs/testing/verification-levels.md +2 -2
  167. package/i18n/README.zh-CN.md +1 -1
  168. package/package.json +1 -1
  169. package/dist/web/assets/client/app.js +0 -808
  170. package/dist/web/assets/client/components.js +0 -477
  171. package/dist/web/assets/client/detail.js +0 -379
  172. package/dist/web/assets/client/dock.js +0 -309
  173. package/dist/web/assets/client/evidence.js +0 -364
  174. package/dist/web/assets/client/forms.js +0 -230
  175. package/dist/web/assets/client/i18n.js +0 -1277
  176. package/dist/web/assets/client/markdown.js +0 -114
  177. package/dist/web/assets/client/records.js +0 -198
  178. package/dist/web/assets/client/sections.js +0 -349
  179. package/dist/web/assets/client/theme.js +0 -71
  180. package/dist/web/assets/shell.js +0 -161
  181. package/dist/web/assets/styles/components.js +0 -216
  182. package/dist/web/assets/styles/views.js +0 -309
  183. /package/dist/web/assets/{icons.js → shared/icons.js} +0 -0
@@ -1,477 +0,0 @@
1
- import { AGENT_ADAPTER_CATALOG } from "../../../agent/adapterCatalog.js";
2
- import { AGENT_EXECUTION_COMPONENT_CATALOG } from "../../../agent/executionComponents.js";
3
- export const COMPONENTS_SCRIPT = String.raw `
4
- // Pure builders: data + translator in, DOM out. Views compose these; nothing
5
- // here reads application state or performs a request.
6
- import { h, icon, node } from "/assets/js/dom.js";
7
- import { formatDateTime, relativeTime } from "/assets/js/format.js";
8
- import { renderMarkdown } from "/assets/js/markdown.js";
9
-
10
- // Generated from the server catalogs, not a second product registry.
11
- const adapterLabels = ${JSON.stringify(Object.fromEntries(AGENT_ADAPTER_CATALOG.map(({ id, label }) => [id, label])))};
12
- const componentLabels = ${JSON.stringify(Object.fromEntries(AGENT_EXECUTION_COMPONENT_CATALOG.map(({ id, label }) => [id, label])))};
13
- export function agentLabel(component, adapterId) {
14
- return component ? componentLabels[component] || component : adapterLabels[adapterId] || adapterId;
15
- }
16
-
17
- // --- Vocabulary ----------------------------------------------------------------
18
- // A translated label for a domain value; unknown values stay visible verbatim
19
- // instead of being hidden or guessed.
20
- export function label(t, prefix, value) {
21
- if (value === undefined || value === null || value === "") return "—";
22
- return t(prefix + "." + value, String(value).replace(/[-_]/g, " "));
23
- }
24
-
25
- const TONES = {
26
- task: { draft: "warn", active: "info", completed: "ok", cancelled: "idle", archived: "idle" },
27
- exec: {
28
- "needs-leader-action": "accent", "waiting-on-agents": "info", "waiting-user": "warn",
29
- recovering: "warn", attention: "bad", "progressing-with-attention": "warn", blocked: "bad",
30
- conflicted: "warn", working: "info", completed: "ok", retired: "idle", cancelled: "idle",
31
- accepted: "ok", open: "info", archived: "idle"
32
- },
33
- run: { active: "info", completed: "ok", failed: "bad" },
34
- work: { open: "info", accepted: "ok", retired: "idle" },
35
- review: { pending: "idle", running: "info", completed: "ok", failed: "bad" },
36
- job: { queued: "idle", running: "info", succeeded: "ok", failed: "bad", "timed-out": "bad",
37
- cancelled: "idle", "unknown-needs-attention": "warn" },
38
- session: { active: "ok", waiting: "warn", quiet: "idle", diagnostic: "bad", unknown: "idle",
39
- stopped: "bad", idle: "idle", background: "warn" },
40
- role: { running: "ok", waiting: "warn", idle: "idle", unknown: "idle", failed: "bad", exited: "idle", detached: "idle" },
41
- decision: { active: "ok", superseded: "idle" },
42
- input: { open: "warn", answered: "ok", cancelled: "idle", "auto-resolved": "ok" },
43
- integration: { running: "info", validating: "info", committed: "ok", conflicted: "warn", blocked: "bad",
44
- failed: "bad", superseded: "idle" }
45
- };
46
- export function tone(kind, value) {
47
- return (TONES[kind] && TONES[kind][value]) || "idle";
48
- }
49
-
50
- export function badge(text, toneName, options) {
51
- const element = h("span.badge.tone-" + (toneName || "idle"), null,
52
- options && options.dot ? h("i.badge-dot", { "aria-hidden": "true" }) : null, text);
53
- if (options && options.title) element.title = options.title;
54
- return element;
55
- }
56
-
57
- export function statusBadge(t, kind, prefix, value) {
58
- const element = badge(label(t, prefix, value), tone(kind, value), { dot: true });
59
- element.dataset.status = value;
60
- return element;
61
- }
62
-
63
- export function dot(toneName, title) {
64
- const element = h("span.dot.tone-" + (toneName || "idle"), { "aria-hidden": title ? null : "true" });
65
- if (title) { element.title = title; element.setAttribute("role", "img"); element.setAttribute("aria-label", title); }
66
- return element;
67
- }
68
-
69
- export function chip(text, extraClass) {
70
- return h("span.chip" + (extraClass ? "." + extraClass : ""), null, text);
71
- }
72
-
73
- export function mono(text, extraClass) {
74
- return h("code.id" + (extraClass ? "." + extraClass : ""), null, text);
75
- }
76
-
77
- export function timeTag(iso, locale, t, options) {
78
- if (!iso) return null;
79
- const element = h("time.when", { dateTime: iso }, options && options.absolute
80
- ? formatDateTime(iso, locale) : relativeTime(iso, locale, t));
81
- element.title = formatDateTime(iso, locale);
82
- return element;
83
- }
84
-
85
- // --- Containers -------------------------------------------------------------------
86
- // One panel of the single reading column: a heading (icon tile, title, count
87
- // and hint) with optional actions, then the body. A "list-card" body holds a
88
- // .row-stack whose rows are divided by hairlines instead of nested boxes.
89
- export function card(options) {
90
- const opts = options || {};
91
- const element = h("section.card" + (opts.className ? "." + opts.className.split(" ").join(".") : ""));
92
- if (opts.id) element.id = opts.id;
93
- if (opts.title || opts.actions) {
94
- const heading = h("div.card-heading", null,
95
- h("h3.card-title", null, opts.icon ? h("span.card-icon", null, icon(opts.icon)) : null, h("span", null, opts.title),
96
- opts.count !== undefined && opts.count !== null ? h("span.count", null, String(opts.count)) : null),
97
- opts.hint ? h("p.card-hint", null, opts.hint) : null);
98
- element.append(h("header.card-head", null, heading, opts.actions ? h("div.card-actions", null, opts.actions) : null));
99
- }
100
- const body = h("div.card-body");
101
- element.append(body);
102
- element.body = body;
103
- return element;
104
- }
105
-
106
- // A panel whose body is a divided list of rows.
107
- export function listCard(options) {
108
- const element = card({ ...options, className: "list-card" + (options.className ? " " + options.className : "") });
109
- element.list = h("div.row-stack");
110
- element.body.append(element.list);
111
- return element;
112
- }
113
-
114
- // Update a card heading count after a later read; null removes it.
115
- export function setCardCount(element, value) {
116
- const title = element.querySelector(".card-title");
117
- let count = title && title.querySelector(".count");
118
- if (value === undefined || value === null) { if (count) count.remove(); return; }
119
- if (!title) return;
120
- if (!count) { count = h("span.count"); title.append(count); }
121
- count.textContent = String(value);
122
- }
123
-
124
- // Local filter chips; selecting one redraws the list in place.
125
- export function filterChips(ariaLabel, options, selected, onSelect) {
126
- const row = h("div.chip-tabs", { role: "group", "aria-label": ariaLabel });
127
- options.forEach(function (option) {
128
- row.append(h("button.chip-tab", {
129
- type: "button", "aria-pressed": String(option.value === selected), dataset: { filter: option.value },
130
- onclick: function () {
131
- row.querySelectorAll(".chip-tab").forEach(function (b) { b.setAttribute("aria-pressed", String(b.dataset.filter === option.value)); });
132
- onSelect(option.value);
133
- }
134
- }, option.label, option.count === undefined || option.count === null ? null : h("span.count", null, String(option.count))));
135
- });
136
- return row;
137
- }
138
-
139
- export function disclosure(title, viewKey, options) {
140
- const opts = options || {};
141
- const element = h("details.disclosure" + (opts.className ? "." + opts.className : ""));
142
- if (viewKey) element.dataset.viewKey = viewKey;
143
- const summary = h("summary", null, icon("chevron", "disclosure-chevron"), h("span.disclosure-title", null, title));
144
- if (opts.meta) summary.append(h("span.disclosure-meta", null, opts.meta));
145
- element.append(summary);
146
- const body = h("div.disclosure-body");
147
- element.append(body);
148
- element.body = body;
149
- return element;
150
- }
151
-
152
- export function kv(rows) {
153
- const list = h("dl.kv");
154
- rows.forEach(function (row) {
155
- if (!row || row[1] === undefined || row[1] === null || row[1] === "") return;
156
- list.append(h("dt", null, row[0]), h("dd", null, row[1]));
157
- });
158
- return list;
159
- }
160
-
161
- export function emptyState(text, iconName, extra) {
162
- return h("div.empty", null, iconName ? icon(iconName) : null, h("p", null, text), extra || null);
163
- }
164
-
165
- export function note(text, toneName) {
166
- return h("p.note" + (toneName ? ".tone-" + toneName : ""), null, text);
167
- }
168
-
169
- export function button(text, options) {
170
- const opts = options || {};
171
- const element = h("button.btn" + (opts.variant ? ".btn-" + opts.variant : ""), {
172
- type: opts.type || "button", onclick: opts.onClick, disabled: !!opts.disabled, title: opts.title
173
- }, opts.icon ? icon(opts.icon) : null, text ? h("span", null, text) : null);
174
- if (opts.dataset) Object.assign(element.dataset, opts.dataset);
175
- return element;
176
- }
177
-
178
- // --- Rich text ---------------------------------------------------------------------
179
- function shouldCollapse(text, threshold) {
180
- const value = String(text);
181
- if (value.length > (threshold || 700)) return true;
182
- let lines = 0;
183
- for (let index = 0; index < value.length; index += 1) if (value[index] === "\n") lines += 1;
184
- return lines > 12;
185
- }
186
-
187
- export function richText(title, text, t, options) {
188
- if (!text) return null;
189
- const opts = options || {};
190
- const block = h("div.prose-block" + (opts.className ? "." + opts.className : ""));
191
- if (title) block.append(h("h4.prose-label", null, title));
192
- const body = h("div.md" + (opts.muted ? ".muted" : ""));
193
- body.innerHTML = renderMarkdown(text);
194
- block.append(body);
195
- if (shouldCollapse(text, opts.threshold)) {
196
- block.classList.add("is-collapsed");
197
- const toggle = h("button.link-btn", { type: "button" }, t("actions.showMore"));
198
- toggle.addEventListener("click", function () {
199
- const collapsed = block.classList.toggle("is-collapsed");
200
- toggle.textContent = t(collapsed ? "actions.showMore" : "actions.showLess");
201
- });
202
- block.append(toggle);
203
- }
204
- return block;
205
- }
206
-
207
- export function bulletList(items, className) {
208
- const list = (items || []).filter(Boolean);
209
- if (!list.length) return null;
210
- return h("ul.bullets" + (className ? "." + className : ""), null, list.map(function (item) { return h("li", null, item); }));
211
- }
212
-
213
- // First page of a long list plus an in-place "show more".
214
- export function pagedList(container, items, pageSize, renderItem, t) {
215
- let shown = 0;
216
- let more = null;
217
- function renderChunk() {
218
- items.slice(shown, shown + pageSize).forEach(function (item) { container.insertBefore(renderItem(item), more); });
219
- shown = Math.min(items.length, shown + pageSize);
220
- if (!more) return;
221
- const remaining = items.length - shown;
222
- if (remaining <= 0) { more.remove(); more = null; }
223
- else more.textContent = t("actions.showRemaining").replace("{count}", String(remaining));
224
- }
225
- if (items.length > pageSize) {
226
- more = h("button.show-more", { type: "button", onclick: renderChunk });
227
- container.append(more);
228
- }
229
- renderChunk();
230
- }
231
-
232
- // --- Metrics (DOM built with node() only; executed by the usage test) -------------
233
- export function metricTile(labelText, value, options) {
234
- const variant = options && options.tone ? " tone-" + options.tone : "";
235
- const tile = node("div", "metric" + variant);
236
- tile.append(node("span", "metric-label", labelText), node("strong", "metric-value", String(value)));
237
- return tile;
238
- }
239
-
240
- function pageLocale() { return typeof document === "undefined" ? undefined : document.documentElement.lang || undefined; }
241
-
242
- // Seconds as the largest whole unit plus the next one ("2d 22h", "2小时48分钟").
243
- const DURATION_UNITS = [["day", 86400], ["hour", 3600], ["minute", 60], ["second", 1]];
244
- function durationText(seconds) {
245
- const total = Math.max(0, Math.round(seconds));
246
- const found = DURATION_UNITS.findIndex(function (unit) { return total >= unit[1]; });
247
- const first = found < 0 ? DURATION_UNITS.length - 1 : found;
248
- return DURATION_UNITS.slice(first, first + 2).map(function (unit, index) {
249
- const count = index ? Math.floor((total % DURATION_UNITS[first][1]) / unit[1]) : Math.floor(total / unit[1]);
250
- return index && !count ? "" : new Intl.NumberFormat(pageLocale(), { style: "unit", unit: unit[0], unitDisplay: "narrow" }).format(count);
251
- }).filter(Boolean).join(" ");
252
- }
253
-
254
- export function usageMetricText(metric, t, suffix) {
255
- if (!metric || metric.value == null) return t("detail.unobserved");
256
- const value = suffix === "s" ? durationText(metric.value) : metric.value + (suffix || "");
257
- return value + (metric.status === "partial" ? " · " + t("detail.partial") : "");
258
- }
259
-
260
- function usageTile(labelText, metric, t, suffix) {
261
- const tile = metricTile(labelText, usageMetricText(metric, t, suffix));
262
- if (metric && metric.reasons && metric.reasons.length) {
263
- tile.append(node("small", "metric-note", metric.reasons.map(function (reason) {
264
- return t("usage.reason." + reason);
265
- }).join("; ")));
266
- }
267
- return tile;
268
- }
269
-
270
- export function observabilityMetricCard(observability, t) {
271
- if (!observability) return null;
272
- const wrap = node("div", "usage");
273
- const grid = node("div", "metric-grid");
274
- const cost = observability.cost || {};
275
- const context = observability.context || {};
276
- grid.append(usageTile(t("usage.tokens"), cost.tokens, t));
277
- grid.append(usageTile(t("usage.toolCalls"), cost.toolCalls, t));
278
- grid.append(usageTile(t("usage.elapsed"), cost.elapsedSeconds, t, "s"));
279
- grid.append(usageTile(t("usage.executionSum"), cost.executionSeconds, t, "s"));
280
- grid.append(metricTile(t("usage.ready"), ((observability.dag && observability.dag.readyIds) || []).length));
281
- grid.append(metricTile(t("usage.contextSnapshots"), context.snapshotCount == null ? t("detail.unobserved") : context.snapshotCount));
282
- wrap.append(grid);
283
- const meta = node("p", "usage-meta");
284
- meta.append(node("span", "", t("usage.scope")));
285
- meta.append(node("span", "", t("usage.observedThrough") + " "
286
- + (cost.observedThrough ? formatDateTime(cost.observedThrough, pageLocale()) : t("detail.unobserved"))));
287
- meta.append(node("span", "", t("usage.contextBytes") + " "
288
- + (context.totalBytes == null ? t("detail.partial") : context.totalBytes + " B")));
289
- wrap.append(meta);
290
- return wrap;
291
- }
292
-
293
- // --- Agent identity ------------------------------------------------------------------
294
- export function agentChips(agent) {
295
- if (!agent) return null;
296
- const chips = [];
297
- if (agent.adapterId || agent.component) chips.push(chip(agentLabel(agent.component, agent.adapterId), "chip-strong"));
298
- if (agent.model) chips.push(chip(agent.model));
299
- if (agent.effort) chips.push(chip(agent.effort));
300
- return chips.length ? h("span.chip-row", null, chips) : null;
301
- }
302
-
303
- // --- Input requests ----------------------------------------------------------------
304
- export function inputCard(input, t, locale, onAnswer) {
305
- const policy = input.policy && input.policy.kind;
306
- const element = h("article.input-card");
307
- element.append(h("div.input-head", null,
308
- h("span.input-kicker", null, icon("inbox", "icon-sm"), t("input.kicker")),
309
- policy ? badge(label(t, "input", policy), policy === "required" ? "bad" : "warn") : null,
310
- input.policy && input.policy.timeoutAt
311
- ? h("span.input-timeout", null, icon("clock", "icon-sm"),
312
- t("input.timeoutAt") + " " + relativeTime(input.policy.timeoutAt, locale, t)) : null,
313
- timeTag(input.createdAt, locale, t)));
314
- element.append(h("p.input-question", null, input.question));
315
- const facts = [];
316
- if (input.requester) facts.push(t("input.from") + " " + input.requester.roleName
317
- + " · " + (input.requester.runId || input.requester.nativeSessionId || ""));
318
- if (input.blockedRefs && input.blockedRefs.length) facts.push(t("input.blocks") + " "
319
- + input.blockedRefs.map(function (ref) { return ref.type + " " + ref.id; }).join(", "));
320
- if (facts.length) element.append(h("p.input-facts", null, facts.join(" · ")));
321
- const recommended = input.policy && input.policy.recommendedChoiceKey;
322
- if (input.choices && input.choices.length) {
323
- element.append(h("div.input-choices", null, input.choices.map(function (choice) {
324
- return h("button.choice" + (choice.key === recommended ? ".is-recommended" : ""), {
325
- type: "button",
326
- onclick: function (event) { onAnswer(input, { choiceKey: choice.key }, event.currentTarget); }
327
- }, h("span", null, choice.label), choice.key === recommended ? badge(t("input.recommended"), "accent") : null);
328
- })));
329
- } else {
330
- const field = h("input", { type: "text", required: true, placeholder: t("input.freeText"), maxLength: 8000 });
331
- const form = h("form.input-form", null, field,
332
- h("button.btn.btn-primary", { type: "submit" }, icon("send"), h("span", null, t("actions.answer"))));
333
- form.addEventListener("input", function () { form.dataset.unsent = field.value ? "true" : "false"; });
334
- form.addEventListener("submit", function (event) {
335
- event.preventDefault();
336
- const text = field.value.trim();
337
- if (text) onAnswer(input, { text: text }, form.querySelector("button"));
338
- });
339
- element.append(form);
340
- }
341
- return element;
342
- }
343
-
344
- // --- Records -----------------------------------------------------------------------
345
- export function workItemCard(item, t, locale, titles) {
346
- const settled = item.status !== "open";
347
- const element = h(settled ? "details.work-card.is-settled" : "article.work-card");
348
- element.dataset.viewKey = "work:" + item.id;
349
- element.append(h(settled ? "summary.work-head" : "header.work-head", null,
350
- settled ? icon("chevron", "disclosure-chevron") : null,
351
- dot(tone("work", item.status)),
352
- h("span.work-title", null, item.title),
353
- statusBadge(t, "work", "work", item.status)));
354
- element.append(h("div.work-body", null, workItemBody(item, t, locale, titles)));
355
- return element;
356
- }
357
-
358
- // The body of one work item, shared by the open card and a lazily read row.
359
- export function workItemBody(item, t, locale, titles) {
360
- const parts = [];
361
- parts.push(h("div.meta-line", null,
362
- item.assignee ? h("span.meta-strong", null, icon("user", "icon-sm"), item.assignee) : null,
363
- mono(item.id), timeTag(item.updatedAt, locale, t)));
364
- if (item.objective && item.objective !== item.title) parts.push(richText(t("work.objective"), item.objective, t));
365
- if (item.acceptance && item.acceptance.length) {
366
- parts.push(h("div.prose-block", null, h("h4.prose-label", null, t("work.acceptance")),
367
- h("ul.checklist", null, item.acceptance.map(function (entry) {
368
- return h("li" + (item.status === "accepted" ? ".is-done" : ""), null, icon(item.status === "accepted" ? "check" : "target", "icon-sm"), h("span", null, entry));
369
- }))));
370
- }
371
- const deps = (item.dependsOn || []).map(function (id) { return (titles && titles[id]) || id; });
372
- if (deps.length) parts.push(h("div.meta-line", null, h("span.meta-label", null, t("work.dependsOn")), deps.map(function (d) { return chip(d); })));
373
- if (item.writeProjectIds && item.writeProjectIds.length) {
374
- parts.push(h("div.meta-line", null, h("span.meta-label", null, t("work.writeProjects")), item.writeProjectIds.map(function (d) { return chip(d); })));
375
- }
376
- if (item.candidates && item.candidates.length) {
377
- parts.push(h("div.prose-block", null, h("h4.prose-label", null, t("work.candidates")),
378
- h("ol.candidates", null, item.candidates.slice().sort(function (a, b) { return b.sequence - a.sequence; }).map(function (candidate) {
379
- return h("li", null, h("span.candidate-seq", null, "#" + candidate.sequence), h("span", null, candidate.summary),
380
- h("span.faint", null, candidate.source && candidate.source.type === "run" ? candidate.source.runId : t("work.direct")),
381
- timeTag(candidate.createdAt, locale, t));
382
- }))));
383
- }
384
- if (item.disposition) {
385
- parts.push(note(t("work.disposition") + ": " + item.disposition.summary
386
- + (item.disposition.replacementWorkItemId ? " → " + item.disposition.replacementWorkItemId : "")));
387
- }
388
- if (item.outcome) parts.push(richText(t("work.outcome"), item.outcome, t, { className: "callout" }));
389
- return parts.filter(Boolean);
390
- }
391
-
392
- export function runCard(run, t, locale) {
393
- const element = h("article.run-card");
394
- element.dataset.status = run.status;
395
- element.append(h("header.run-head", null,
396
- dot(tone("run", run.status)),
397
- h("span.run-role", null, run.roleName),
398
- mono(run.id),
399
- run.purpose ? chip(label(t, "run.purpose", run.purpose)) : null,
400
- run.workItemId ? chip(run.workItemId) : null,
401
- h("span.spacer"),
402
- statusBadge(t, "run", "run", run.status)), runBody(run, t, locale));
403
- return element;
404
- }
405
-
406
- // What one execution record says: delivery, instruction, report, failure.
407
- export function runBody(run, t, locale) {
408
- const parts = [];
409
- const input = run.inputs && run.inputs.length ? run.inputs[0].input : null;
410
- parts.push(h("div.meta-line", null,
411
- h("span", null, t("run.delivery") + ": " + label(t, "run.delivery", (run.execution && run.execution.delivery) || "unobserved")),
412
- run.mode ? h("span", null, label(t, "mode", run.mode)) : null,
413
- timeTag((run.result && run.result.completedAt) || run.updatedAt, locale, t),
414
- agentChips(run.effective || (run.agentId ? run : null))));
415
- const directive = input && (input.directive || input.action);
416
- if (directive) parts.push(richText(t("run.instruction"), directive, t, { threshold: 320 }));
417
- if (run.result && run.result.output) parts.push(richText(t("run.output"), run.result.output, t, { threshold: 320, className: "callout" }));
418
- if (run.result && run.result.diagnostic) parts.push(richText(t("run.failure"), run.result.diagnostic, t, { threshold: 320, className: "callout.tone-bad" }));
419
- if (run.executionGroupId) {
420
- parts.push(h("p.faint.mono-line", null, t("run.lineage") + " " + run.executionGroupId + (run.executionLaneId ? "/" + run.executionLaneId : "")));
421
- }
422
- return parts.filter(Boolean);
423
- }
424
-
425
- export function reviewCard(round, t, locale) {
426
- const element = h("article.review-card");
427
- element.append(h("header.run-head", null,
428
- dot(tone("review", round.status)),
429
- h("span.run-role", null, round.reviewerRoleName || t("review.reviewer")),
430
- mono(round.id),
431
- round.scope ? chip(label(t, "review.scope", round.scope)) : null,
432
- h("span.spacer"),
433
- statusBadge(t, "review", "review", round.status)));
434
- element.append(h("div.meta-line", null,
435
- round.workItemId ? mono(round.workItemId + (round.candidateId ? " · " + round.candidateId : "")) : null,
436
- round.taskCandidate && round.taskCandidate.projects ? round.taskCandidate.projects.map(function (project) {
437
- return mono(project.projectId + " @ " + String(project.commit).slice(0, 12));
438
- }) : null,
439
- round.reviewBaseCommit ? h("span", null, t("review.base") + " ", mono(String(round.reviewBaseCommit).slice(0, 12))) : null,
440
- round.reviewerRunId ? h("span", null, t("review.run") + " ", mono(round.reviewerRunId)) : null,
441
- timeTag(round.createdAt, locale, t)));
442
- if (round.failure) element.append(note(round.failure.kind + ": " + round.failure.message, "bad"));
443
- return element;
444
- }
445
-
446
- export function roleCard(role, t, locale, options) {
447
- const opts = options || {};
448
- const session = opts.runtimeRole && opts.runtimeRole.runtimeSession;
449
- const element = h("article.role-card");
450
- const binding = role.agentBindings && role.agentBindings[role.activeAgentId];
451
- element.append(h("header.role-head", null,
452
- h("span.avatar", { "aria-hidden": "true" }, String(role.name || "?").slice(0, 1).toUpperCase()),
453
- h("div.role-title", null, h("strong", null, role.name),
454
- h("span.faint", null, role.activeAgentId || "")),
455
- opts.status ? statusBadge(t, "role", "role", opts.status) : null));
456
- if (binding) element.append(agentChips({
457
- adapterId: binding.adapterId, component: binding.component,
458
- model: binding.config && binding.config.model, effort: binding.config && binding.config.effort
459
- }));
460
- if (role.description) element.append(richText(null, role.description, t, { muted: true, threshold: 280 }));
461
- const rows = [];
462
- rows.push([t("role.session"), session && session.nativeSessionId ? mono(session.nativeSessionId) : t("role.noSession")]);
463
- if (role.launchRevision !== undefined) rows.push([t("role.desired"), "r" + role.launchRevision + (opts.launchDrift ? " · " + t("role.drift") : "")]);
464
- if (role.defaultAccess !== undefined) rows.push([t("role.access"), role.defaultAccess]);
465
- if (opts.retry) rows.push([t("role.providerRetry"), label(t, "retry", opts.retry.status) + " · "
466
- + opts.retry.attempts + "/" + opts.retry.limit
467
- + (opts.retry.status === "waiting" && opts.retry.nextEligibleAt ? " · " + formatDateTime(opts.retry.nextEligibleAt, locale) : "")]);
468
- if (role.skills && role.skills.length) rows.push([t("role.skills"), h("span.chip-row", null, role.skills.map(function (s) { return chip(s); }))]);
469
- element.append(kv(rows));
470
- if (opts.onOpen) {
471
- element.append(h("div.role-actions", null, button(t("role.openSession"), {
472
- icon: "terminal", variant: "ghost", onClick: function () { opts.onOpen(role.name); }
473
- })));
474
- }
475
- return element;
476
- }
477
- `;