@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.
- package/README.md +15 -1
- package/dist/artifacts/artifactCapability.js +39 -10
- package/dist/artifacts/imageMetadata.js +120 -0
- package/dist/artifacts/managedGit.js +7 -4
- package/dist/artifacts/taskArtifactRepository.js +6 -0
- package/dist/cli/commandCatalog.js +18 -9
- package/dist/cli/invocationAuthority.js +1 -1
- package/dist/commands/executionAuditCommands.js +5 -0
- package/dist/commands/globalRoleCommands.js +41 -3
- package/dist/commands/projectCommands.js +89 -94
- package/dist/commands/roleSkillValidation.js +4 -8
- package/dist/commands/taskCommands.js +65 -14
- package/dist/commands/taskUsageCommand.js +38 -0
- package/dist/context/roleSessionContext.js +18 -2
- package/dist/context/runContextPack.js +5 -1
- package/dist/context/sessionBootstrapManifest.js +18 -3
- package/dist/context/skillCatalog.js +108 -0
- package/dist/context/skillPackage.js +161 -0
- package/dist/context/taskContext.js +3 -2
- package/dist/context/taskSearch.js +127 -0
- package/dist/controlPlaneCli.js +25 -20
- package/dist/controller/fileSchedulerStoreAdapter.js +39 -8
- package/dist/controller/globalInputDelivery.js +2 -4
- package/dist/controller/jobControl.js +2 -0
- package/dist/controller/nativeHostInput.js +37 -0
- package/dist/controller/providerRetryDelivery.js +4 -2
- package/dist/controller/runtime.js +93 -2
- package/dist/controller/runtimeEventInbox.js +2 -2
- package/dist/controller/runtimeEventProcessor.js +3 -3
- package/dist/doctor/doctor.js +10 -0
- package/dist/execution/reviewMainRun.js +1 -0
- package/dist/execution/workItemMainRun.js +1 -0
- package/dist/executor/agentAdapter.js +3 -5
- package/dist/executor/codexConfigConflict.js +6 -4
- package/dist/executor/effectiveLaunch.js +24 -1
- package/dist/executor/fileRoleLaunchPlanner.js +15 -7
- package/dist/integration/gitIntegrationService.js +7 -12
- package/dist/integration/integrationSourceApplication.js +4 -2
- package/dist/interaction/notificationPresentation.js +85 -0
- package/dist/interaction/operatorPresentation.js +1 -2
- package/dist/job/httpPreview.js +61 -0
- package/dist/job/jobRunner.js +12 -2
- package/dist/kernel/builtinCapabilities.js +3 -1
- package/dist/message/message.js +15 -1
- package/dist/output/rolePresentation.js +4 -1
- package/dist/repository/executionLaneGitSnapshot.js +2 -1
- package/dist/repository/gitCompatibility.js +62 -0
- package/dist/repository/gitWorkspace.js +48 -71
- package/dist/repository/gitWorktreeInventory.js +121 -0
- package/dist/repository/project.js +74 -25
- package/dist/resources/resourceDiscovery.js +2 -2
- package/dist/resources/resourceGc.js +7 -4
- package/dist/resources/resourceRegistrar.js +2 -1
- package/dist/runtime/agentEndpoint.js +8 -0
- package/dist/runtime/agentHost.js +170 -3
- package/dist/runtime/codexAppServerRuntime.js +1 -1
- package/dist/runtime/codexNativeAccess.js +175 -0
- package/dist/runtime/controlledCodexTui.js +116 -0
- package/dist/runtime/publicReply.js +23 -0
- package/dist/runtime/runtimeObservation.js +48 -0
- package/dist/runtime/structuredProviderHost.js +16 -7
- package/dist/runtime/taskCostMetrics.js +133 -0
- package/dist/runtime/taskUsageMetrics.js +11 -2
- package/dist/runtime/taskUsageQuery.js +38 -0
- package/dist/scheduler/leaderWakeupProcessor.js +1 -9
- package/dist/scheduler/taskExecutionProjection.js +2 -0
- package/dist/scheduler/taskObservabilityProjection.js +9 -1
- package/dist/storage/homeLayout.js +13 -0
- package/dist/storage/sqliteSchema.js +44 -0
- package/dist/storage/sqliteStore.js +53 -0
- package/dist/storage/storageVersions.js +1 -1
- package/dist/storage/storeRpc.js +2 -0
- package/dist/storage/taskSearch.js +35 -0
- package/dist/storage/upgrade/projectKnowledgeMigration.js +52 -0
- package/dist/task/ordinaryArchive.js +42 -0
- package/dist/tmux/tmuxManager.js +8 -8
- package/dist/web/assets/assetManifest.js +11 -51
- package/dist/web/assets/client/app/catalog.js +215 -0
- package/dist/web/assets/client/app/main.js +148 -0
- package/dist/web/assets/client/app/selection.js +139 -0
- package/dist/web/assets/client/app/settings.js +326 -0
- package/dist/web/assets/client/app/taskView.js +280 -0
- package/dist/web/assets/client/domain/context.js +96 -0
- package/dist/web/assets/client/domain/records.js +126 -0
- package/dist/web/assets/client/domain/runs.js +119 -0
- package/dist/web/assets/client/domain/taskForms.js +197 -0
- package/dist/web/assets/client/domain/vocab.js +69 -0
- package/dist/web/assets/client/domain/work.js +116 -0
- package/dist/web/assets/client/i18n/en.js +900 -0
- package/dist/web/assets/client/i18n/zh-CN.js +898 -0
- package/dist/web/assets/client/index.js +114 -0
- package/dist/web/assets/client/layout/resizer.js +37 -0
- package/dist/web/assets/client/layout/router.js +35 -0
- package/dist/web/assets/client/layout/shortcuts.js +45 -0
- package/dist/web/assets/client/layout/sizing.js +95 -0
- package/dist/web/assets/client/layout/workspace.js +247 -0
- package/dist/web/assets/client/{api.js → lib/api.js} +20 -4
- package/dist/web/assets/client/{dom.js → lib/dom.js} +24 -12
- package/dist/web/assets/client/{format.js → lib/format.js} +7 -0
- package/dist/web/assets/client/lib/i18n.js +54 -0
- package/dist/web/assets/client/lib/markdown.js +167 -0
- package/dist/web/assets/client/lib/prefs.js +28 -0
- package/dist/web/assets/client/lib/theme.js +68 -0
- package/dist/web/assets/client/ui/containers.js +101 -0
- package/dist/web/assets/client/ui/controls.js +51 -0
- package/dist/web/assets/client/ui/forms.js +48 -0
- package/dist/web/assets/client/ui/metrics.js +137 -0
- package/dist/web/assets/client/ui/primitives.js +92 -0
- package/dist/web/assets/client/ui/text.js +33 -0
- package/dist/web/assets/client/ui/toast.js +12 -0
- package/dist/web/assets/client/views/bodySearch.js +172 -0
- package/dist/web/assets/client/views/createTask.js +85 -0
- package/dist/web/assets/client/views/dock/conversation.js +612 -0
- package/dist/web/assets/client/views/dock/discussion.js +173 -0
- package/dist/web/assets/client/views/dock/preview.js +129 -0
- package/dist/web/assets/client/views/dock/terminal.js +199 -0
- package/dist/web/assets/client/views/globalInput.js +67 -0
- package/dist/web/assets/client/{overview.js → views/overview.js} +61 -51
- package/dist/web/assets/client/{sidebar.js → views/sidebar.js} +56 -62
- package/dist/web/assets/client/views/skills.js +152 -0
- package/dist/web/assets/client/views/task/actions.js +36 -0
- package/dist/web/assets/client/views/task/delivery.js +185 -0
- package/dist/web/assets/client/views/task/deliveryResults.js +159 -0
- package/dist/web/assets/client/views/task/files.js +272 -0
- package/dist/web/assets/client/views/task/observation.js +153 -0
- package/dist/web/assets/client/views/task/overview.js +161 -0
- package/dist/web/assets/client/views/task/page.js +131 -0
- package/dist/web/assets/client/views/task/records.js +163 -0
- package/dist/web/assets/client/views/task/runtime.js +130 -0
- package/dist/web/assets/client/views/task/timeline.js +190 -0
- package/dist/web/assets/shared/geometry.js +19 -0
- package/dist/web/assets/shared/taskTabs.js +8 -0
- package/dist/web/assets/shared/themes.js +93 -0
- package/dist/web/assets/shell/dialogs.js +63 -0
- package/dist/web/assets/shell/dock.js +40 -0
- package/dist/web/assets/shell/index.js +40 -0
- package/dist/web/assets/shell/settings.js +34 -0
- package/dist/web/assets/shell/sidebar.js +45 -0
- package/dist/web/assets/styles/index.js +41 -0
- package/dist/web/assets/styles/{responsive.js → layout/responsive.js} +10 -10
- package/dist/web/assets/styles/{layout.js → layout/workspace.js} +17 -24
- package/dist/web/assets/styles/markdown.js +22 -3
- package/dist/web/assets/styles/tokens.js +10 -63
- package/dist/web/assets/styles/ui/controls.js +76 -0
- package/dist/web/assets/styles/ui/forms.js +46 -0
- package/dist/web/assets/styles/ui/surfaces.js +122 -0
- package/dist/web/assets/styles/views/delivery.js +29 -0
- package/dist/web/assets/styles/views/dock.js +71 -0
- package/dist/web/assets/styles/views/page.js +32 -0
- package/dist/web/assets/styles/views/records.js +70 -0
- package/dist/web/assets/styles/views/settings.js +26 -0
- package/dist/web/assets/styles/views/sidebar.js +74 -0
- package/dist/web/assets/styles/views/task.js +80 -0
- package/dist/web/assets/styles/views/terminal.js +38 -0
- package/dist/web/taskPreviews.js +205 -0
- package/dist/web/tmuxWebTerminal.js +16 -9
- package/dist/web/webConversation.js +373 -0
- package/dist/web/webMaterials.js +155 -0
- package/dist/web/webServer.js +295 -18
- package/dist/web/webSettings.js +331 -0
- package/dist/web/webSkills.js +86 -0
- package/dist/web/webSnapshot.js +40 -8
- package/dist/web/webTaskSurface.js +106 -8
- package/dist/workspace/gitChangeSetCapture.js +3 -1
- package/docs/cli-information-contract.md +1 -1
- package/docs/cli-information-contract.zh-CN.md +1 -1
- package/docs/managed-turn-and-session-runtime.md +31 -0
- package/docs/managed-turn-and-session-runtime.zh-CN.md +22 -0
- package/docs/release-workflow.md +54 -0
- package/docs/release-workflow.zh-CN.md +39 -0
- package/docs/storage-baseline.md +38 -1
- package/docs/storage-baseline.zh-CN.md +22 -0
- package/docs/task-discovery.md +28 -0
- package/docs/testing/verification-levels.md +2 -2
- package/i18n/README.zh-CN.md +1 -1
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +5 -4
- package/skills/yui-leader/references/execution.md +2 -1
- package/skills/yui-operator/SKILL.md +3 -0
- package/skills/yui-reviewer/SKILL.md +4 -2
- package/skills/yui-runtime/SKILL.md +43 -2
- package/skills/yui-worker/SKILL.md +3 -2
- package/dist/web/assets/client/app.js +0 -808
- package/dist/web/assets/client/components.js +0 -477
- package/dist/web/assets/client/detail.js +0 -379
- package/dist/web/assets/client/dock.js +0 -309
- package/dist/web/assets/client/evidence.js +0 -364
- package/dist/web/assets/client/forms.js +0 -230
- package/dist/web/assets/client/i18n.js +0 -1277
- package/dist/web/assets/client/markdown.js +0 -114
- package/dist/web/assets/client/records.js +0 -198
- package/dist/web/assets/client/sections.js +0 -349
- package/dist/web/assets/client/theme.js +0 -71
- package/dist/web/assets/shell.js +0 -161
- package/dist/web/assets/styles/components.js +0 -216
- package/dist/web/assets/styles/views.js +0 -309
- /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
|
+
`;
|