@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.
- 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 +17 -8
- 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 +25 -2
- 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 +10 -1
- 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 +32 -6
- package/dist/controller/jobControl.js +2 -0
- package/dist/controller/nativeHostInput.js +37 -0
- 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/codexConfigConflict.js +6 -4
- package/dist/executor/effectiveLaunch.js +24 -1
- package/dist/executor/fileRoleLaunchPlanner.js +13 -5
- package/dist/integration/gitIntegrationService.js +7 -12
- package/dist/integration/integrationSourceApplication.js +4 -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/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/managed-turn-and-session-runtime.md +9 -0
- package/docs/managed-turn-and-session-runtime.zh-CN.md +7 -0
- package/docs/release-workflow.md +28 -0
- package/docs/release-workflow.zh-CN.md +21 -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/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
|
@@ -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
|
-
`;
|