@zq-silk/yui 2.3.0 → 2.5.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 (197) 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 +18 -9
  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 +65 -14
  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 +18 -3
  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 +39 -8
  23. package/dist/controller/globalInputDelivery.js +2 -4
  24. package/dist/controller/jobControl.js +2 -0
  25. package/dist/controller/nativeHostInput.js +37 -0
  26. package/dist/controller/providerRetryDelivery.js +4 -2
  27. package/dist/controller/runtime.js +93 -2
  28. package/dist/controller/runtimeEventInbox.js +2 -2
  29. package/dist/controller/runtimeEventProcessor.js +3 -3
  30. package/dist/doctor/doctor.js +10 -0
  31. package/dist/execution/reviewMainRun.js +1 -0
  32. package/dist/execution/workItemMainRun.js +1 -0
  33. package/dist/executor/agentAdapter.js +3 -5
  34. package/dist/executor/codexConfigConflict.js +6 -4
  35. package/dist/executor/effectiveLaunch.js +24 -1
  36. package/dist/executor/fileRoleLaunchPlanner.js +15 -7
  37. package/dist/integration/gitIntegrationService.js +7 -12
  38. package/dist/integration/integrationSourceApplication.js +4 -2
  39. package/dist/interaction/notificationPresentation.js +85 -0
  40. package/dist/interaction/operatorPresentation.js +1 -2
  41. package/dist/job/httpPreview.js +61 -0
  42. package/dist/job/jobRunner.js +12 -2
  43. package/dist/kernel/builtinCapabilities.js +3 -1
  44. package/dist/message/message.js +15 -1
  45. package/dist/output/rolePresentation.js +4 -1
  46. package/dist/repository/executionLaneGitSnapshot.js +2 -1
  47. package/dist/repository/gitCompatibility.js +62 -0
  48. package/dist/repository/gitWorkspace.js +48 -71
  49. package/dist/repository/gitWorktreeInventory.js +121 -0
  50. package/dist/repository/project.js +74 -25
  51. package/dist/resources/resourceDiscovery.js +2 -2
  52. package/dist/resources/resourceGc.js +7 -4
  53. package/dist/resources/resourceRegistrar.js +2 -1
  54. package/dist/runtime/agentEndpoint.js +8 -0
  55. package/dist/runtime/agentHost.js +170 -3
  56. package/dist/runtime/codexAppServerRuntime.js +1 -1
  57. package/dist/runtime/codexNativeAccess.js +175 -0
  58. package/dist/runtime/controlledCodexTui.js +116 -0
  59. package/dist/runtime/publicReply.js +23 -0
  60. package/dist/runtime/runtimeObservation.js +48 -0
  61. package/dist/runtime/structuredProviderHost.js +16 -7
  62. package/dist/runtime/taskCostMetrics.js +133 -0
  63. package/dist/runtime/taskUsageMetrics.js +11 -2
  64. package/dist/runtime/taskUsageQuery.js +38 -0
  65. package/dist/scheduler/leaderWakeupProcessor.js +1 -9
  66. package/dist/scheduler/taskExecutionProjection.js +2 -0
  67. package/dist/scheduler/taskObservabilityProjection.js +9 -1
  68. package/dist/storage/homeLayout.js +13 -0
  69. package/dist/storage/sqliteSchema.js +44 -0
  70. package/dist/storage/sqliteStore.js +53 -0
  71. package/dist/storage/storageVersions.js +1 -1
  72. package/dist/storage/storeRpc.js +2 -0
  73. package/dist/storage/taskSearch.js +35 -0
  74. package/dist/storage/upgrade/projectKnowledgeMigration.js +52 -0
  75. package/dist/task/ordinaryArchive.js +42 -0
  76. package/dist/tmux/tmuxManager.js +8 -8
  77. package/dist/web/assets/assetManifest.js +11 -51
  78. package/dist/web/assets/client/app/catalog.js +215 -0
  79. package/dist/web/assets/client/app/main.js +148 -0
  80. package/dist/web/assets/client/app/selection.js +139 -0
  81. package/dist/web/assets/client/app/settings.js +326 -0
  82. package/dist/web/assets/client/app/taskView.js +280 -0
  83. package/dist/web/assets/client/domain/context.js +96 -0
  84. package/dist/web/assets/client/domain/records.js +126 -0
  85. package/dist/web/assets/client/domain/runs.js +119 -0
  86. package/dist/web/assets/client/domain/taskForms.js +197 -0
  87. package/dist/web/assets/client/domain/vocab.js +69 -0
  88. package/dist/web/assets/client/domain/work.js +116 -0
  89. package/dist/web/assets/client/i18n/en.js +900 -0
  90. package/dist/web/assets/client/i18n/zh-CN.js +898 -0
  91. package/dist/web/assets/client/index.js +114 -0
  92. package/dist/web/assets/client/layout/resizer.js +37 -0
  93. package/dist/web/assets/client/layout/router.js +35 -0
  94. package/dist/web/assets/client/layout/shortcuts.js +45 -0
  95. package/dist/web/assets/client/layout/sizing.js +95 -0
  96. package/dist/web/assets/client/layout/workspace.js +247 -0
  97. package/dist/web/assets/client/{api.js → lib/api.js} +20 -4
  98. package/dist/web/assets/client/{dom.js → lib/dom.js} +24 -12
  99. package/dist/web/assets/client/{format.js → lib/format.js} +7 -0
  100. package/dist/web/assets/client/lib/i18n.js +54 -0
  101. package/dist/web/assets/client/lib/markdown.js +167 -0
  102. package/dist/web/assets/client/lib/prefs.js +28 -0
  103. package/dist/web/assets/client/lib/theme.js +68 -0
  104. package/dist/web/assets/client/ui/containers.js +101 -0
  105. package/dist/web/assets/client/ui/controls.js +51 -0
  106. package/dist/web/assets/client/ui/forms.js +48 -0
  107. package/dist/web/assets/client/ui/metrics.js +137 -0
  108. package/dist/web/assets/client/ui/primitives.js +92 -0
  109. package/dist/web/assets/client/ui/text.js +33 -0
  110. package/dist/web/assets/client/ui/toast.js +12 -0
  111. package/dist/web/assets/client/views/bodySearch.js +172 -0
  112. package/dist/web/assets/client/views/createTask.js +85 -0
  113. package/dist/web/assets/client/views/dock/conversation.js +612 -0
  114. package/dist/web/assets/client/views/dock/discussion.js +173 -0
  115. package/dist/web/assets/client/views/dock/preview.js +129 -0
  116. package/dist/web/assets/client/views/dock/terminal.js +199 -0
  117. package/dist/web/assets/client/views/globalInput.js +67 -0
  118. package/dist/web/assets/client/{overview.js → views/overview.js} +61 -51
  119. package/dist/web/assets/client/{sidebar.js → views/sidebar.js} +56 -62
  120. package/dist/web/assets/client/views/skills.js +152 -0
  121. package/dist/web/assets/client/views/task/actions.js +36 -0
  122. package/dist/web/assets/client/views/task/delivery.js +185 -0
  123. package/dist/web/assets/client/views/task/deliveryResults.js +159 -0
  124. package/dist/web/assets/client/views/task/files.js +272 -0
  125. package/dist/web/assets/client/views/task/observation.js +153 -0
  126. package/dist/web/assets/client/views/task/overview.js +161 -0
  127. package/dist/web/assets/client/views/task/page.js +131 -0
  128. package/dist/web/assets/client/views/task/records.js +163 -0
  129. package/dist/web/assets/client/views/task/runtime.js +130 -0
  130. package/dist/web/assets/client/views/task/timeline.js +190 -0
  131. package/dist/web/assets/shared/geometry.js +19 -0
  132. package/dist/web/assets/shared/taskTabs.js +8 -0
  133. package/dist/web/assets/shared/themes.js +93 -0
  134. package/dist/web/assets/shell/dialogs.js +63 -0
  135. package/dist/web/assets/shell/dock.js +40 -0
  136. package/dist/web/assets/shell/index.js +40 -0
  137. package/dist/web/assets/shell/settings.js +34 -0
  138. package/dist/web/assets/shell/sidebar.js +45 -0
  139. package/dist/web/assets/styles/index.js +41 -0
  140. package/dist/web/assets/styles/{responsive.js → layout/responsive.js} +10 -10
  141. package/dist/web/assets/styles/{layout.js → layout/workspace.js} +17 -24
  142. package/dist/web/assets/styles/markdown.js +22 -3
  143. package/dist/web/assets/styles/tokens.js +10 -63
  144. package/dist/web/assets/styles/ui/controls.js +76 -0
  145. package/dist/web/assets/styles/ui/forms.js +46 -0
  146. package/dist/web/assets/styles/ui/surfaces.js +122 -0
  147. package/dist/web/assets/styles/views/delivery.js +29 -0
  148. package/dist/web/assets/styles/views/dock.js +71 -0
  149. package/dist/web/assets/styles/views/page.js +32 -0
  150. package/dist/web/assets/styles/views/records.js +70 -0
  151. package/dist/web/assets/styles/views/settings.js +26 -0
  152. package/dist/web/assets/styles/views/sidebar.js +74 -0
  153. package/dist/web/assets/styles/views/task.js +80 -0
  154. package/dist/web/assets/styles/views/terminal.js +38 -0
  155. package/dist/web/taskPreviews.js +205 -0
  156. package/dist/web/tmuxWebTerminal.js +16 -9
  157. package/dist/web/webConversation.js +373 -0
  158. package/dist/web/webMaterials.js +155 -0
  159. package/dist/web/webServer.js +295 -18
  160. package/dist/web/webSettings.js +331 -0
  161. package/dist/web/webSkills.js +86 -0
  162. package/dist/web/webSnapshot.js +40 -8
  163. package/dist/web/webTaskSurface.js +106 -8
  164. package/dist/workspace/gitChangeSetCapture.js +3 -1
  165. package/docs/cli-information-contract.md +1 -1
  166. package/docs/cli-information-contract.zh-CN.md +1 -1
  167. package/docs/managed-turn-and-session-runtime.md +31 -0
  168. package/docs/managed-turn-and-session-runtime.zh-CN.md +22 -0
  169. package/docs/release-workflow.md +54 -0
  170. package/docs/release-workflow.zh-CN.md +39 -0
  171. package/docs/storage-baseline.md +38 -1
  172. package/docs/storage-baseline.zh-CN.md +22 -0
  173. package/docs/task-discovery.md +28 -0
  174. package/docs/testing/verification-levels.md +2 -2
  175. package/i18n/README.zh-CN.md +1 -1
  176. package/package.json +1 -1
  177. package/skills/yui-leader/SKILL.md +5 -4
  178. package/skills/yui-leader/references/execution.md +2 -1
  179. package/skills/yui-operator/SKILL.md +3 -0
  180. package/skills/yui-reviewer/SKILL.md +4 -2
  181. package/skills/yui-runtime/SKILL.md +43 -2
  182. package/skills/yui-worker/SKILL.md +3 -2
  183. package/dist/web/assets/client/app.js +0 -808
  184. package/dist/web/assets/client/components.js +0 -477
  185. package/dist/web/assets/client/detail.js +0 -379
  186. package/dist/web/assets/client/dock.js +0 -309
  187. package/dist/web/assets/client/evidence.js +0 -364
  188. package/dist/web/assets/client/forms.js +0 -230
  189. package/dist/web/assets/client/i18n.js +0 -1277
  190. package/dist/web/assets/client/markdown.js +0 -114
  191. package/dist/web/assets/client/records.js +0 -198
  192. package/dist/web/assets/client/sections.js +0 -349
  193. package/dist/web/assets/client/theme.js +0 -71
  194. package/dist/web/assets/shell.js +0 -161
  195. package/dist/web/assets/styles/components.js +0 -216
  196. package/dist/web/assets/styles/views.js +0 -309
  197. /package/dist/web/assets/{icons.js → shared/icons.js} +0 -0
@@ -0,0 +1,197 @@
1
+ export const TASK_FORMS_SCRIPT = String.raw `
2
+ // Task write forms: the discussion composer, queue / steer / interrupt and
3
+ // the title editor. Submission plumbing (requestId, unsent flag, receipts,
4
+ // never replaying an unknown outcome) lives in ui/forms submitWrite().
5
+ import { h, icon, clear } from "/assets/js/lib/dom.js";
6
+ import { fill } from "/assets/js/lib/format.js";
7
+ import { button } from "/assets/js/ui/primitives.js";
8
+ import { segmented } from "/assets/js/ui/controls.js";
9
+ import { field, receiptLine, setReceipt, submitWrite } from "/assets/js/ui/forms.js";
10
+
11
+ function isOpen(task) {
12
+ return ["active", "draft"].includes(task.status);
13
+ }
14
+
15
+ // --- Discussion composer -----------------------------------------------------
16
+ export function messageComposer(task, t, actions) {
17
+ let intent = "discuss";
18
+ const form = h("form.composer");
19
+ const message = h("textarea.composer-input", {
20
+ required: true, maxLength: 8000, rows: 3, placeholder: t("composer.placeholder"),
21
+ "aria-label": t("composer.label")
22
+ });
23
+ const open = isOpen(task);
24
+ const send = h("button.btn.btn-primary.composer-send", { type: "submit", disabled: !open, title: t("composer.sendHint") },
25
+ icon("send"), h("span", null, t("composer.send")));
26
+ const intents = segmented("intent", ["discuss", "record", "develop"].map(function (value) {
27
+ return { value: value, label: t("intent." + value), title: t("intent." + value + ".hint") };
28
+ }), intent, function (value) { intent = value; });
29
+ const receipt = receiptLine(open ? t("receipt.notSubmitted") : t("composer.closed"));
30
+ const facets = h("div.facets");
31
+ form.append(h("div.composer-box", null, message, h("div.composer-bar", null, intents, h("span.spacer"), send)), receipt, facets);
32
+ form.addEventListener("input", function () { form.dataset.unsent = message.value ? "true" : "false"; });
33
+ message.addEventListener("keydown", function (event) {
34
+ if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) { event.preventDefault(); form.requestSubmit(); }
35
+ });
36
+ form.addEventListener("submit", function (event) {
37
+ event.preventDefault();
38
+ if (send.disabled || !message.value.trim()) return;
39
+ clear(facets);
40
+ // requestId is the submission key: the same key retried returns the
41
+ // original Message and routing, never a second submission.
42
+ submitWrite({
43
+ control: send, receipt: receipt, form: form, t: t,
44
+ send: function (requestId) { return actions.sendMessage(task.id, message.value, requestId, intent); },
45
+ saved: function (result) {
46
+ setReceipt(receipt, t("receipt.saved") + " · " + result.record.id, "ok");
47
+ renderSubmissionFacets(facets, result.submission, t);
48
+ message.value = "";
49
+ },
50
+ rejectedKey: "receipt.notSubmittedBecause", unknownKey: "receipt.unknownMessage", afterWrite: actions.afterWrite
51
+ });
52
+ });
53
+ return form;
54
+ }
55
+
56
+ // Each submission facet is reported on its own line, never collapsed into a
57
+ // single "started". A missing facet block is a contract violation and is
58
+ // reported as such rather than reinterpreted.
59
+ export function renderSubmissionFacets(container, submission, t) {
60
+ clear(container);
61
+ if (!submission) { container.append(h("p.faint.small", null, t("facet.missing"))); return; }
62
+ const rows = [
63
+ ["facet.phase", "phase." + submission.phase, submission.phase],
64
+ ["facet.planning", "planningFacet." + submission.planning, submission.planning],
65
+ ["facet.activation", "activation." + submission.activation, submission.activation],
66
+ ["facet.delivery", "deliveryFacet." + submission.delivery, submission.delivery]
67
+ ];
68
+ container.append(h("dl.kv.kv-compact", null, rows.map(function (row) {
69
+ return [h("dt", null, t(row[0])), h("dd", null, t(row[1], row[2]))];
70
+ })));
71
+ const step = submission.nextStep;
72
+ const text = step ? nextStepText(step, t) : "";
73
+ if (text) container.append(h("p.next-step", { dataset: { nextStep: step.kind } }, icon("flag", "icon-sm"), h("span", null, text)));
74
+ }
75
+
76
+ function nextStepText(step, t) {
77
+ if (step.kind === "activate-manually") return fill(t("next.activateManually"), { task: step.taskId });
78
+ if (step.kind === "start-execution") return fill(t("next.startExecution"), { task: step.taskId });
79
+ if (step.kind === "await-pending-activation") return fill(t("next.awaitActivation"), { ref: step.activationRef });
80
+ if (step.kind === "resolve-failed-activation") return fill(t("next.resolveFailed"), { failure: step.failure, ref: step.activationRef });
81
+ return "";
82
+ }
83
+
84
+ // --- Queue / steer / interrupt ----------------------------------------------
85
+ // The same three application-layer actions the CLI drives. Steer and
86
+ // interrupt name an exact current Turn; a mismatch is a visible failure
87
+ // receipt, never a silent downgrade to a queue.
88
+ export function controlForm(task, t, actions, roleNames) {
89
+ let kind = "queue";
90
+ const form = h("form.stack");
91
+ const inputs = controlInputs(task, t, roleNames);
92
+ const fields = controlFields(inputs, t);
93
+ const submit = button(t("control.submit"), { type: "submit", variant: "primary", icon: "send", disabled: !isOpen(task) });
94
+ const receipt = receiptLine(t("receipt.notSubmitted"));
95
+ const apply = function () { applyControlKind(kind, inputs, fields); };
96
+ const actionsSeg = segmented("action", ["queue", "steer", "interrupt"].map(function (value) {
97
+ return { value: value, label: t("control." + value), title: t("control." + value + ".hint") };
98
+ }), kind, function (value) { kind = value; apply(); });
99
+ form.append(h("div.field", null, h("span", null, t("control.action")), actionsSeg),
100
+ h("div.field-row", null, fields.role, fields.workItem), inputs.roles, fields.body, fields.expected, fields.then,
101
+ h("div.form-actions", null, submit), receipt);
102
+ apply();
103
+ form.addEventListener("input", function () { form.dataset.unsent = "true"; });
104
+ form.addEventListener("submit", function (event) {
105
+ event.preventDefault();
106
+ if (submit.disabled) return;
107
+ submitWrite({
108
+ control: submit, receipt: receipt, form: form, t: t,
109
+ send: function (requestId) { return actions.control(task.id, controlPayload(kind, inputs, requestId)); },
110
+ // The receipt states exactly what settled; none of these states implies
111
+ // the Provider executed the input.
112
+ saved: function (result) { setReceipt(receipt, controlReceipt(result, t), "ok"); },
113
+ rejectedKey: "receipt.notSubmittedBecause", unknownKey: "receipt.unknownControl", afterWrite: actions.afterWrite
114
+ });
115
+ });
116
+ return form;
117
+ }
118
+
119
+ function controlInputs(task, t, roleNames) {
120
+ return {
121
+ role: h("input", { list: "control-roles-" + task.id, placeholder: t("control.rolePlaceholder") }),
122
+ roles: h("datalist", { id: "control-roles-" + task.id }, (roleNames || []).map(function (name) { return h("option", { value: name }); })),
123
+ body: h("textarea", { maxLength: 8000, rows: 3 }),
124
+ expected: h("input.mono", { placeholder: t("control.expectedPlaceholder") }),
125
+ workItem: h("input.mono"),
126
+ then: h("input.mono", { placeholder: t("control.thenPlaceholder") })
127
+ };
128
+ }
129
+
130
+ function controlFields(inputs, t) {
131
+ return {
132
+ role: field(t("control.role"), inputs.role),
133
+ body: field(t("control.message"), inputs.body),
134
+ expected: field(t("control.expectedTurn"), inputs.expected, t("control.expectedHint")),
135
+ workItem: field(t("control.workItem"), inputs.workItem),
136
+ then: field(t("control.then"), inputs.then)
137
+ };
138
+ }
139
+
140
+ function applyControlKind(kind, inputs, fields) {
141
+ fields.body.hidden = kind === "interrupt";
142
+ fields.expected.hidden = kind === "queue";
143
+ fields.then.hidden = kind !== "interrupt";
144
+ fields.workItem.hidden = kind === "interrupt";
145
+ inputs.role.required = kind !== "queue";
146
+ inputs.body.required = kind !== "interrupt";
147
+ inputs.expected.required = kind !== "queue";
148
+ }
149
+
150
+ function controlPayload(kind, inputs, requestId) {
151
+ const payload = { action: kind, requestId: requestId };
152
+ const role = inputs.role.value.trim();
153
+ if (kind === "interrupt") {
154
+ payload.role = role;
155
+ payload.expectedTarget = inputs.expected.value.trim();
156
+ if (inputs.then.value.trim()) payload.thenMessage = inputs.then.value.trim();
157
+ return payload;
158
+ }
159
+ payload.body = inputs.body.value;
160
+ if (kind === "steer") { payload.to = role; payload.expectedTarget = inputs.expected.value.trim(); }
161
+ else if (role) payload.to = role;
162
+ if (inputs.workItem.value.trim()) payload.workItem = inputs.workItem.value.trim();
163
+ return payload;
164
+ }
165
+
166
+ function controlReceipt(result, t) {
167
+ const settled = result.steer || result.interrupt || result.delivery || { state: result.disposition };
168
+ return t("receipt.receipt") + " " + result.action + " · " + settled.state
169
+ + (settled.outcome ? " · " + settled.outcome : "") + (settled.detail ? " · " + settled.detail : "")
170
+ + (result.record ? " · " + result.record.id : "");
171
+ }
172
+
173
+ // --- Title -------------------------------------------------------------------
174
+ export function titleForm(task, t, actions) {
175
+ const form = h("form.inline-form");
176
+ const archived = task.status === "archived";
177
+ const input = h("input", { value: task.title, required: true, maxLength: 500, disabled: archived, "aria-label": t("details.title") });
178
+ const save = button(t("actions.save"), { type: "submit", variant: "primary", disabled: archived });
179
+ const receipt = receiptLine(t("receipt.notSubmitted"));
180
+ form.append(h("div.inline-row", null, input, save), receipt);
181
+ form.addEventListener("input", function () { form.dataset.unsent = input.value !== task.title ? "true" : "false"; });
182
+ form.addEventListener("submit", function (event) {
183
+ event.preventDefault();
184
+ if (save.disabled) return;
185
+ submitWrite({
186
+ control: save, receipt: receipt, form: form, t: t,
187
+ send: function (requestId) { return actions.updateTask(task.id, { title: input.value }, requestId); },
188
+ saved: function (result) {
189
+ setReceipt(receipt, t("receipt.savedRevision") + " " + result.revision, "ok");
190
+ input.value = result.record.title;
191
+ },
192
+ rejectedKey: "receipt.notSavedBecause", unknownKey: "receipt.unknownSave", afterWrite: actions.afterWrite
193
+ });
194
+ });
195
+ return form;
196
+ }
197
+ `;
@@ -0,0 +1,69 @@
1
+ import { AGENT_ADAPTER_CATALOG } from "../../../../agent/adapterCatalog.js";
2
+ import { AGENT_EXECUTION_COMPONENT_CATALOG } from "../../../../agent/executionComponents.js";
3
+ export const VOCAB_SCRIPT = String.raw `
4
+ // Domain vocabulary: translated labels, semantic tones and the status badges
5
+ // built from them. Unknown values stay visible verbatim, never hidden or
6
+ // guessed.
7
+ import { h } from "/assets/js/lib/dom.js";
8
+ import { badge, chip } from "/assets/js/ui/primitives.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
+ export function label(t, prefix, value) {
18
+ if (value === undefined || value === null || value === "") return "—";
19
+ return t(prefix + "." + value, String(value).replace(/[-_]/g, " "));
20
+ }
21
+
22
+ const TONES = {
23
+ task: { draft: "warn", active: "info", completed: "ok", cancelled: "idle", archived: "idle" },
24
+ exec: {
25
+ "needs-leader-action": "accent", "waiting-on-agents": "info", "waiting-user": "warn",
26
+ recovering: "warn", attention: "bad", "progressing-with-attention": "warn", blocked: "bad",
27
+ conflicted: "warn", working: "info", completed: "ok", retired: "idle", cancelled: "idle",
28
+ accepted: "ok", open: "info", archived: "idle"
29
+ },
30
+ run: { active: "info", completed: "ok", failed: "bad" },
31
+ work: { open: "info", accepted: "ok", retired: "idle" },
32
+ review: { pending: "idle", running: "info", completed: "ok", failed: "bad" },
33
+ job: { queued: "idle", running: "info", succeeded: "ok", failed: "bad", "timed-out": "bad",
34
+ cancelled: "idle", "unknown-needs-attention": "warn" },
35
+ session: { active: "ok", waiting: "warn", quiet: "idle", diagnostic: "bad", unknown: "idle",
36
+ stopped: "bad", idle: "idle", background: "warn" },
37
+ role: { running: "ok", waiting: "warn", idle: "idle", unknown: "idle", failed: "bad", exited: "idle", detached: "idle" },
38
+ decision: { active: "ok", superseded: "idle" },
39
+ input: { open: "warn", answered: "ok", cancelled: "idle", "auto-resolved": "ok" },
40
+ integration: { running: "info", validating: "info", committed: "ok", conflicted: "warn", blocked: "bad",
41
+ failed: "bad", superseded: "idle" }
42
+ };
43
+ export function tone(kind, value) {
44
+ return (TONES[kind] && TONES[kind][value]) || "idle";
45
+ }
46
+
47
+ export function statusBadge(t, kind, prefix, value) {
48
+ const element = badge(label(t, prefix, value), tone(kind, value), { dot: true });
49
+ element.dataset.status = value;
50
+ return element;
51
+ }
52
+
53
+ // Native Session groups in display order, and one badge per non-empty group.
54
+ export const SESSION_GROUPS = ["active", "waiting", "background", "quiet", "diagnostic", "stopped", "unknown", "idle"];
55
+ export function sessionBadges(counts, t) {
56
+ return SESSION_GROUPS.filter(function (group) { return counts && counts[group]; }).map(function (group) {
57
+ return badge(counts[group] + " " + t("session." + group), tone("session", group), { dot: true });
58
+ });
59
+ }
60
+
61
+ export function agentChips(agent) {
62
+ if (!agent) return null;
63
+ const chips = [];
64
+ if (agent.adapterId || agent.component) chips.push(chip(agentLabel(agent.component, agent.adapterId), "chip-strong"));
65
+ if (agent.model) chips.push(chip(agent.model));
66
+ if (agent.effort) chips.push(chip(agent.effort));
67
+ return chips.length ? h("span.chip-row", null, chips) : null;
68
+ }
69
+ `;
@@ -0,0 +1,116 @@
1
+ export const WORK_SCRIPT = String.raw `
2
+ // Work items and input requests: what the Task is doing and what it is
3
+ // waiting on the user for.
4
+ import { h, icon } from "/assets/js/lib/dom.js";
5
+ import { relativeTime } from "/assets/js/lib/format.js";
6
+ import { badge, chip, dot, mono, note, timeTag } from "/assets/js/ui/primitives.js";
7
+ import { richText } from "/assets/js/ui/text.js";
8
+ import { label, statusBadge, tone } from "/assets/js/domain/vocab.js";
9
+
10
+ // --- Input requests ----------------------------------------------------------
11
+ export function inputCard(input, t, locale, onAnswer) {
12
+ const policy = input.policy && input.policy.kind;
13
+ const element = h("article.input-card");
14
+ element.append(h("div.input-head", null,
15
+ h("span.input-kicker", null, icon("inbox", "icon-sm"), t("input.kicker")),
16
+ policy ? badge(label(t, "input", policy), policy === "required" ? "bad" : "warn") : null,
17
+ input.policy && input.policy.timeoutAt
18
+ ? h("span.input-timeout", null, icon("clock", "icon-sm"),
19
+ t("input.timeoutAt") + " " + relativeTime(input.policy.timeoutAt, locale, t)) : null,
20
+ timeTag(input.createdAt, locale, t)));
21
+ element.append(h("p.input-question", null, input.question));
22
+ const facts = inputFacts(input, t);
23
+ if (facts.length) element.append(h("p.input-facts", null, facts.join(" · ")));
24
+ element.append(input.choices && input.choices.length ? inputChoices(input, t, onAnswer) : inputAnswerForm(input, t, onAnswer));
25
+ element.append(h("p.receipt", { role: "status", dataset: { inputReceipt: input.id } }));
26
+ return element;
27
+ }
28
+
29
+ function inputFacts(input, t) {
30
+ const facts = [];
31
+ if (input.requester) facts.push(t("input.from") + " " + input.requester.roleName
32
+ + " · " + (input.requester.runId || input.requester.nativeSessionId || ""));
33
+ if (input.blockedRefs && input.blockedRefs.length) facts.push(t("input.blocks") + " "
34
+ + input.blockedRefs.map(function (ref) { return ref.type + " " + ref.id; }).join(", "));
35
+ return facts;
36
+ }
37
+
38
+ function inputChoices(input, t, onAnswer) {
39
+ const recommended = input.policy && input.policy.recommendedChoiceKey;
40
+ return h("div.input-choices", null, input.choices.map(function (choice) {
41
+ return h("button.choice" + (choice.key === recommended ? ".is-recommended" : ""), {
42
+ type: "button",
43
+ onclick: function (event) { onAnswer(input, { choiceKey: choice.key }, event.currentTarget); }
44
+ }, h("span", null, choice.label), choice.key === recommended ? badge(t("input.recommended"), "accent") : null);
45
+ }));
46
+ }
47
+
48
+ function inputAnswerForm(input, t, onAnswer) {
49
+ const field = h("input", { type: "text", required: true, placeholder: t("input.freeText"), "aria-label": input.question, maxLength: 8000 });
50
+ const form = h("form.input-form", null, field,
51
+ h("button.btn.btn-primary", { type: "submit" }, icon("send"), h("span", null, t("actions.answer"))));
52
+ form.addEventListener("input", function () { form.dataset.unsent = field.value ? "true" : "false"; });
53
+ form.addEventListener("submit", function (event) {
54
+ event.preventDefault();
55
+ const text = field.value.trim();
56
+ if (text) onAnswer(input, { text: text }, form.querySelector("button"));
57
+ });
58
+ return form;
59
+ }
60
+
61
+ // --- Work items --------------------------------------------------------------
62
+ export function workItemCard(item, t, locale, titles) {
63
+ const settled = item.status !== "open";
64
+ const element = h(settled ? "details.work-card.is-settled" : "article.work-card");
65
+ element.dataset.viewKey = "work:" + item.id;
66
+ element.append(h(settled ? "summary.work-head" : "header.work-head", null,
67
+ settled ? icon("chevron", "disclosure-chevron") : null,
68
+ dot(tone("work", item.status)),
69
+ h("span.work-title", null, item.title),
70
+ statusBadge(t, "work", "work", item.status)));
71
+ element.append(h("div.work-body", null, workItemBody(item, t, locale, titles)));
72
+ return element;
73
+ }
74
+
75
+ // The body of one work item, shared by the open card and a lazily read row.
76
+ export function workItemBody(item, t, locale, titles) {
77
+ const parts = [];
78
+ parts.push(h("div.meta-line", null,
79
+ item.assignee ? h("span.meta-strong", null, icon("user", "icon-sm"), item.assignee) : null,
80
+ mono(item.id), timeTag(item.updatedAt, locale, t)));
81
+ if (item.objective && item.objective !== item.title) parts.push(richText(t("work.objective"), item.objective, t));
82
+ if (item.acceptance && item.acceptance.length) parts.push(acceptanceList(item, t));
83
+ const deps = (item.dependsOn || []).map(function (id) { return (titles && titles[id]) || id; });
84
+ if (deps.length) parts.push(chipLine(t("work.dependsOn"), deps));
85
+ if (item.writeProjectIds && item.writeProjectIds.length) parts.push(chipLine(t("work.writeProjects"), item.writeProjectIds));
86
+ if (item.candidates && item.candidates.length) parts.push(candidateList(item, t, locale));
87
+ if (item.disposition) {
88
+ parts.push(note(t("work.disposition") + ": " + item.disposition.summary
89
+ + (item.disposition.replacementWorkItemId ? " → " + item.disposition.replacementWorkItemId : "")));
90
+ }
91
+ if (item.outcome) parts.push(richText(t("work.outcome"), item.outcome, t, { className: "callout" }));
92
+ return parts.filter(Boolean);
93
+ }
94
+
95
+ function chipLine(title, values) {
96
+ return h("div.meta-line", null, h("span.meta-label", null, title), values.map(function (value) { return chip(value); }));
97
+ }
98
+
99
+ function acceptanceList(item, t) {
100
+ const done = item.status === "accepted";
101
+ return h("div.prose-block", null, h("h4.prose-label", null, t("work.acceptance")),
102
+ h("ul.checklist", null, item.acceptance.map(function (entry) {
103
+ return h("li" + (done ? ".is-done" : ""), null, icon(done ? "check" : "target", "icon-sm"), h("span", null, entry));
104
+ })));
105
+ }
106
+
107
+ function candidateList(item, t, locale) {
108
+ const newestFirst = item.candidates.slice().sort(function (a, b) { return b.sequence - a.sequence; });
109
+ return h("div.prose-block", null, h("h4.prose-label", null, t("work.candidates")),
110
+ h("ol.candidates", null, newestFirst.map(function (candidate) {
111
+ return h("li", null, h("span.candidate-seq", null, "#" + candidate.sequence), h("span", null, candidate.summary),
112
+ h("span.faint", null, candidate.source && candidate.source.type === "run" ? candidate.source.runId : t("work.direct")),
113
+ timeTag(candidate.createdAt, locale, t));
114
+ })));
115
+ }
116
+ `;