@zq-silk/yui 2.16.0 → 2.18.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/dist/cli/commandCatalog.js +19 -12
- package/dist/cli/interactionCandidates.js +20 -5
- package/dist/cli/interactionPolicy.js +5 -4
- package/dist/cli/roleWizard.js +7 -0
- package/dist/commands/controllerCommands.js +13 -4
- package/dist/commands/durableJobCommands.js +50 -3
- package/dist/commands/globalRoleCommands.js +31 -14
- package/dist/commands/inboxCommands.js +1 -0
- package/dist/commands/operatorCommands.js +12 -2
- package/dist/commands/profileCommands.js +19 -2
- package/dist/commands/roleConfiguration.js +3 -0
- package/dist/commands/taskCommands.js +16 -0
- package/dist/commands/taskRoleRuntimeStatus.js +3 -0
- package/dist/controlPlaneCli.js +21 -4
- package/dist/controller/agentJobControl.js +9 -1
- package/dist/controller/clientRuntime.js +34 -13
- package/dist/controller/controller.js +35 -22
- package/dist/controller/diagnosticJournal.js +214 -0
- package/dist/controller/fileSchedulerStoreAdapter.js +174 -105
- package/dist/controller/globalInputDelivery.js +19 -9
- package/dist/controller/globalRuntimeAttention.js +11 -3
- package/dist/controller/jobControl.js +1 -1
- package/dist/controller/jobDefinitionControl.js +24 -13
- package/dist/controller/jobSupervisor.js +4 -0
- package/dist/controller/providerRetryAdmission.js +9 -0
- package/dist/controller/providerRetryDelivery.js +16 -0
- package/dist/controller/runtime.js +80 -4
- package/dist/controller/runtimeLaunchCoordinator.js +3 -1
- package/dist/controller/workerSchedulerStore.js +24 -0
- package/dist/core/boundedRpc.js +4 -0
- package/dist/core/controllerServer.js +1 -1
- package/dist/core/controllerTelemetry.js +92 -19
- package/dist/executor/fileRoleLaunchPlanner.js +3 -0
- package/dist/job/globalShell.js +51 -0
- package/dist/job/jobBusinessResult.js +4 -3
- package/dist/job/jobDefinition.js +6 -1
- package/dist/job/jobRunner.js +9 -0
- package/dist/job/scheduleService.js +2 -0
- package/dist/message/globalInboxRecovery.js +30 -19
- package/dist/message/globalProviderRetry.js +7 -1
- package/dist/message/messageContinuation.js +4 -0
- package/dist/output/rolePresentation.js +3 -0
- package/dist/profile/agentProfile.js +8 -0
- package/dist/profile/agentProfileRuntime.js +16 -1
- package/dist/review/reviewDecision.js +6 -0
- package/dist/role/availability.js +28 -0
- package/dist/role/role.js +6 -0
- package/dist/runtime/builtinAgentErrorMappers.js +4 -0
- package/dist/runtime/codexNativeAccess.js +21 -4
- package/dist/runtime/globalSessionHealth.js +39 -0
- package/dist/runtime/tmuxAdapters.js +5 -0
- package/dist/scheduler/activeRoleRunDelivery.js +9 -0
- package/dist/scheduler/leaderWakeupProcessor.js +8 -1
- package/dist/scheduler/roleRunLiveness.js +3 -0
- package/dist/scheduler/roleRunStall.js +10 -10
- package/dist/storage/persistenceWorker.js +41 -19
- package/dist/storage/sqliteSchema.js +43 -9
- package/dist/storage/sqliteStore.js +86 -8
- package/dist/storage/storageVersions.js +1 -1
- package/dist/storage/storeRpc.js +25 -11
- package/dist/storage/taskReadRevisionSchema.js +39 -0
- package/dist/web/assets/client/app/catalog.js +0 -29
- package/dist/web/assets/client/app/jobs.js +115 -0
- package/dist/web/assets/client/app/main.js +32 -28
- package/dist/web/assets/client/app/manage.js +1 -0
- package/dist/web/assets/client/app/settings.js +1 -5
- package/dist/web/assets/client/app/taskView.js +7 -11
- package/dist/web/assets/client/i18n/en.js +265 -36
- package/dist/web/assets/client/i18n/zh-CN.js +264 -35
- package/dist/web/assets/client/index.js +4 -0
- package/dist/web/assets/client/layout/manageShell.js +61 -15
- package/dist/web/assets/client/layout/router.js +2 -1
- package/dist/web/assets/client/layout/shortcuts.js +2 -2
- package/dist/web/assets/client/layout/workspace.js +99 -112
- package/dist/web/assets/client/lib/prefs.js +1 -1
- package/dist/web/assets/client/ui/primitives.js +15 -2
- package/dist/web/assets/client/views/dock/conversation.js +421 -123
- package/dist/web/assets/client/views/dock/session.js +229 -0
- package/dist/web/assets/client/views/dock/terminal.js +48 -39
- package/dist/web/assets/client/views/jobs.js +1042 -160
- package/dist/web/assets/client/views/overview.js +2 -2
- package/dist/web/assets/client/views/sidebar.js +3 -0
- package/dist/web/assets/client/views/task/page.js +2 -12
- package/dist/web/assets/shared/manageNav.js +3 -1
- package/dist/web/assets/shell/appRail.js +2 -1
- package/dist/web/assets/shell/dock.js +9 -27
- package/dist/web/assets/shell/manage.js +7 -2
- package/dist/web/assets/shell/models.js +4 -3
- package/dist/web/assets/shell/settingsContent.js +0 -3
- package/dist/web/assets/shell/sidebar.js +0 -1
- package/dist/web/assets/styles/views/conversation.js +96 -17
- package/dist/web/assets/styles/views/dock.js +17 -5
- package/dist/web/assets/styles/views/jobs.js +301 -12
- package/dist/web/assets/styles/views/sidebar.js +1 -2
- package/dist/web/assets/styles/views/task.js +1 -2
- package/dist/web/assets/styles/views/terminal.js +12 -8
- package/dist/web/webConversation.js +1 -0
- package/dist/web/webServer.js +28 -1
- package/dist/web/webSettings.js +10 -2
- package/docs/global-shell-jobs.md +78 -0
- package/docs/job-runs.md +6 -3
- package/docs/managed-turn-and-session-runtime.md +84 -0
- package/docs/managed-turn-and-session-runtime.zh-CN.md +57 -0
- package/docs/release-workflow.md +67 -0
- package/docs/release-workflow.zh-CN.md +48 -0
- package/docs/roles-and-configuration.md +45 -1
- package/docs/roles-and-configuration.zh-CN.md +35 -0
- package/docs/storage-baseline.md +19 -1
- package/docs/storage-baseline.zh-CN.md +10 -1
- package/docs/testing/review-evaluation.md +35 -1
- package/docs/testing/review-evaluation.zh-CN.md +25 -1
- package/docs/testing/verification-levels.md +2 -2
- package/docs/testing/verification-levels.zh-CN.md +2 -2
- package/package.json +1 -1
- package/skills/yui-leader/VERSION +1 -1
- package/skills/yui-leader/references/execution.md +19 -8
- package/skills/yui-reviewer/SKILL.md +13 -2
- package/skills/yui-reviewer/VERSION +1 -1
|
@@ -1,19 +1,308 @@
|
|
|
1
|
+
// Jobs: one calm, dense surface. Hairline separators instead of nested cards,
|
|
2
|
+
// the workbench's own list head and "new" action, a two-line index, a scannable Run table and a properties
|
|
3
|
+
// column. Only shared tokens (ink, line, surface, tone, radius, type scale).
|
|
1
4
|
export const JOBS_STYLES = `
|
|
2
|
-
.jobs-manager { min-width: 0; display: grid; gap:
|
|
3
|
-
.jobs-layout { display: grid; grid-template-columns: minmax(160px, 240px) minmax(0, 1fr); gap: 24px; align-items: start; }
|
|
4
|
-
.jobs-list, .jobs-detail, .jobs-runs { display: grid; gap: 12px; min-width: 0; }
|
|
5
|
-
.job-choice { display: grid; gap: 6px; text-align: left; padding: 14px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); color: inherit; cursor: pointer; overflow-wrap: anywhere; }
|
|
6
|
-
.job-choice[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); }
|
|
7
|
-
.job-choice:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
8
|
-
.jobs-manager .settings-actions { flex-wrap: wrap; }
|
|
9
|
-
.jobs-manager .settings-observation { max-width: 100%; max-height: 420px; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
10
|
-
.jobs-manager .btn, .job-fact { overflow-wrap: anywhere; white-space: normal; text-align: left; }
|
|
11
|
-
.jobs-runs .btn { font-family: var(--font-mono); font-size: 12px; }
|
|
12
|
-
.jobs-manager textarea { width: 100%; font-family: var(--font-mono); }
|
|
5
|
+
.jobs-manager { min-width: 0; display: grid; gap: 14px; container-type: inline-size; }
|
|
13
6
|
.jobs-manager [hidden] { display: none !important; }
|
|
7
|
+
.jobs-manager textarea { width: 100%; font-family: var(--font-mono); font-size: var(--fs-xs); }
|
|
8
|
+
.jobs-manager .settings-observation { max-width: 100%; max-height: 420px; margin: 0; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; font-size: var(--fs-xs); }
|
|
9
|
+
.jobs-manager .btn { height: 30px; padding: 0 11px; }
|
|
10
|
+
.jobs-layout { display: grid; grid-template-columns: minmax(180px, 240px) minmax(0, 1fr); gap: 20px; align-items: start; }
|
|
11
|
+
.jobs-list, .jobs-detail { display: grid; gap: 12px; min-width: 0; }
|
|
12
|
+
|
|
13
|
+
/* Page bar */
|
|
14
|
+
.jobs-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; min-width: 0; padding-bottom: 12px; border-bottom: 1px solid var(--line); }
|
|
15
|
+
.jobs-bar-title { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
|
|
16
|
+
.jobs-bar-title h1, .jobs-bar-title h2 { font-size: var(--fs-lg); font-weight: 650; letter-spacing: -.01em; }
|
|
17
|
+
.jobs-bar-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 6px; min-width: 0; }
|
|
18
|
+
.jobs-bar-actions .settings-receipt { margin: 0 6px 0 0; color: var(--ink-4); font-size: var(--fs-xs); white-space: pre-line; }
|
|
19
|
+
.jobs-bar-actions .settings-receipt:empty { display: none; }
|
|
20
|
+
.jobs-bar-actions .settings-receipt.settings-error { order: 9; flex-basis: 100%; margin: 4px 0 0; padding: 8px 10px; border-radius: var(--r-sm); background: var(--bad-soft); color: var(--bad); text-align: left; }
|
|
21
|
+
.jobs-receipt .settings-receipt { margin: 0; color: var(--ink-3); font-size: var(--fs-xs); white-space: pre-line; }
|
|
22
|
+
.jobs-receipt .settings-receipt:empty, .jobs-receipt:has(.settings-receipt:empty) { display: none; }
|
|
23
|
+
.jobs-receipt .settings-receipt.settings-error { padding: 8px 10px; border-radius: var(--r-sm); background: var(--bad-soft); color: var(--bad); }
|
|
24
|
+
.job-notice { margin: 0; padding: 8px 12px; border-radius: var(--r-sm); background: var(--surface-3); color: var(--ink-2); font-size: var(--fs-sm); }
|
|
25
|
+
|
|
26
|
+
/* Job index (left rail): two lines per Job, status at the right edge. */
|
|
27
|
+
.jobs-area .jobs-index { display: grid; gap: 10px; min-width: 0; padding-top: 2px; }
|
|
28
|
+
.jobs-area .side-create { margin-bottom: 2px; }
|
|
29
|
+
/* The area title stays whole beside the Jobs sync; a long clock gives way. */
|
|
30
|
+
.manage-rail .side-head:has(#jobs-sync:not([hidden])) .side-title { flex: none; }
|
|
31
|
+
#jobs-sync { min-width: 0; overflow: hidden; white-space: nowrap; }
|
|
32
|
+
#jobs-sync time { overflow: hidden; text-overflow: ellipsis; }
|
|
33
|
+
.jobs-scope { display: grid; gap: 4px; padding: 0 2px; }
|
|
34
|
+
.jobs-scope label { color: var(--ink-4); font-size: var(--fs-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: .07em; }
|
|
35
|
+
.jobs-scope select { width: 100%; min-width: 0; height: 32px; padding-top: 4px; padding-bottom: 4px; font-size: var(--fs-sm); }
|
|
36
|
+
.jobs-scope-help { margin: 0; color: var(--ink-4); font-size: var(--fs-2xs); line-height: 1.4; }
|
|
37
|
+
.jobs-scope-help.is-error, .jobs-index-empty.is-error { color: var(--bad); }
|
|
38
|
+
.jobs-index-body { display: grid; gap: 8px; min-width: 0; }
|
|
39
|
+
.jobs-index-tools { display: grid; gap: 6px; }
|
|
40
|
+
.jobs-index-tools .search-field input { width: 100%; height: 32px; font-size: var(--fs-sm); }
|
|
41
|
+
.jobs-index-count { margin: 0; padding: 0 2px; color: var(--ink-4); font-size: var(--fs-2xs); font-variant-numeric: tabular-nums; }
|
|
42
|
+
.jobs-index-empty { margin: 0; padding: 24px 12px; color: var(--ink-4); font-size: var(--fs-sm); text-align: center; }
|
|
43
|
+
.jobs-list { gap: 1px; }
|
|
44
|
+
.job-row { position: relative; display: flex; align-items: flex-start; gap: 9px; width: 100%; min-width: 0; padding: 7px 8px; border: 0; border-radius: var(--r-sm); background: transparent; color: inherit; text-align: left; cursor: pointer; transition: background var(--t-fast); }
|
|
45
|
+
.job-row > .dot { margin-top: 6px; }
|
|
46
|
+
.job-row:hover { background: var(--surface-3); }
|
|
47
|
+
.job-row[aria-current="true"] { background: var(--surface-3); }
|
|
48
|
+
.job-row[aria-current="true"] .job-row-name { font-weight: 600; }
|
|
49
|
+
.job-row-body { display: grid; gap: 1px; flex: 1; min-width: 0; }
|
|
50
|
+
.job-row-line { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
|
51
|
+
.job-row-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); font-size: var(--fs-sm); font-weight: 500; line-height: 1.45; }
|
|
52
|
+
.job-row-line > .badge { flex: none; height: 18px; padding: 0 6px; font-size: var(--fs-2xs); }
|
|
53
|
+
.job-row-sub { color: var(--ink-4); font-size: var(--fs-2xs); }
|
|
54
|
+
.job-row-sub > * { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
55
|
+
.job-row-type { flex: none; max-width: 50%; color: var(--ink-3); }
|
|
56
|
+
.job-row-plan { flex: 1; }
|
|
57
|
+
.job-row-plan::before { content: "·"; margin-right: 6px; color: var(--ink-4); }
|
|
58
|
+
.job-row-none { flex: none; color: var(--ink-4); font-size: var(--fs-2xs); }
|
|
59
|
+
|
|
60
|
+
/* Focus is always visible. */
|
|
61
|
+
.job-row:focus-visible, .job-run-row:focus-visible, .job-copy:focus-visible, .job-more:focus-visible,
|
|
62
|
+
.job-section-action:focus-visible, .job-raw > summary:focus-visible, .job-log > summary:focus-visible, .job-fold > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; box-shadow: none; }
|
|
63
|
+
|
|
64
|
+
/* Job header */
|
|
65
|
+
.job-page { display: grid; gap: 16px; min-width: 0; }
|
|
66
|
+
.job-header { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 10px 16px; min-width: 0; }
|
|
67
|
+
.job-title { display: grid; gap: 6px; flex: 1 1 360px; min-width: 0; }
|
|
68
|
+
.job-title h2 { font-size: var(--fs-xl); font-weight: 650; letter-spacing: -.015em; line-height: 1.25; overflow-wrap: anywhere; }
|
|
69
|
+
.job-badges { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
|
|
70
|
+
.job-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 0; color: var(--ink-3); font-size: var(--fs-xs); }
|
|
71
|
+
.job-meta-item { display: inline-flex; align-items: center; gap: 4px; min-width: 0; }
|
|
72
|
+
.job-meta-item + .job-meta-item::before { content: "·"; margin: 0 8px; color: var(--ink-4); }
|
|
73
|
+
.job-meta a { color: inherit; }
|
|
74
|
+
.job-actions { display: flex; flex-wrap: wrap; gap: 6px; flex: none; }
|
|
75
|
+
.job-note { margin: 0; color: var(--ink-4); font-size: var(--fs-xs); line-height: 1.5; }
|
|
76
|
+
.job-note.is-error { color: var(--bad); }
|
|
77
|
+
|
|
78
|
+
/* Overview strip: numbers first, the last 30 Runs as a status strip. */
|
|
79
|
+
.job-overview { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 24px; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
|
|
80
|
+
.job-stats { display: flex; flex-wrap: wrap; gap: 10px 0; min-width: 0; }
|
|
81
|
+
.job-stat { display: grid; align-content: start; gap: 2px; min-width: 0; padding: 0 18px; border-left: 1px solid var(--line); }
|
|
82
|
+
.job-stat:first-child { padding-left: 0; border-left: 0; }
|
|
83
|
+
.job-stat-label { color: var(--ink-4); font-size: var(--fs-2xs); white-space: nowrap; }
|
|
84
|
+
.job-stat-value { color: var(--ink); font-size: var(--fs-lg); font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1.3; }
|
|
85
|
+
.job-stat-sub { color: var(--ink-4); font-size: var(--fs-2xs); font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
86
|
+
.job-stat-run { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; min-height: 26px; }
|
|
87
|
+
.job-stat-run code { font-size: var(--fs-xs); color: var(--ink-2); }
|
|
88
|
+
.job-stat-run .badge { height: 20px; padding: 0 7px; font-size: var(--fs-2xs); }
|
|
89
|
+
.job-spark { display: flex; align-items: stretch; gap: 2px; height: 26px; }
|
|
90
|
+
.job-spark-bar { width: 6px; border-radius: 2px; background: var(--tone, var(--line-3)); opacity: .9; }
|
|
91
|
+
.job-spark-bar.tone-idle { background: var(--line-3); }
|
|
92
|
+
|
|
93
|
+
/* About the Job: description and configuration | plans and definition */
|
|
94
|
+
.job-purpose { display: flex; align-items: flex-start; gap: 4px; min-width: 0; padding: 10px 6px 10px 12px; border-left: 2px solid var(--line-3); border-radius: 0 var(--r-sm) var(--r-sm) 0; background: var(--surface-3); }
|
|
95
|
+
.job-purpose .job-prose { flex: 1; max-height: 180px; line-height: 1.6; }
|
|
96
|
+
.job-purpose.is-note { display: block; margin: 0; padding: 8px 12px; color: var(--ink-2); font-size: var(--fs-sm); }
|
|
97
|
+
.job-about { display: grid; grid-template-columns: minmax(0, 1fr) minmax(240px, 300px); gap: 24px; align-items: start; min-width: 0; }
|
|
98
|
+
.job-primary, .job-aside { display: grid; gap: 22px; min-width: 0; }
|
|
99
|
+
.job-section { display: grid; gap: 8px; min-width: 0; }
|
|
100
|
+
.job-section-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 26px; }
|
|
101
|
+
.job-section-head h4 { color: var(--ink-2); font-size: var(--fs-sm); font-weight: 600; }
|
|
102
|
+
.job-section-count { color: var(--ink-4); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
|
|
103
|
+
.job-section-title { margin: 6px 0 0; color: var(--ink-3); font-size: var(--fs-xs); font-weight: 600; }
|
|
104
|
+
.job-section-action { display: inline-flex; align-items: center; gap: 4px; height: 26px; padding: 0 8px; border: 0; border-radius: var(--r-sm); background: transparent; color: var(--ink-3); font-size: var(--fs-xs); font-weight: 500; }
|
|
105
|
+
.job-section-action:hover { background: var(--surface-3); color: var(--ink); }
|
|
106
|
+
.job-section-action .icon { width: 14px; height: 14px; }
|
|
107
|
+
.job-empty-block { margin: 0; padding: 14px 12px; border: 1px dashed var(--line-2); border-radius: var(--r-md); color: var(--ink-4); font-size: var(--fs-sm); text-align: center; }
|
|
108
|
+
.job-blank { display: grid; justify-items: center; gap: 10px; padding: 64px 16px; color: var(--ink-4); text-align: center; }
|
|
109
|
+
|
|
110
|
+
/* Run history: a table on wide containers, two lines on narrow ones. */
|
|
111
|
+
.job-history { display: grid; gap: 8px; min-width: 0; }
|
|
112
|
+
.job-filters { gap: 4px; }
|
|
113
|
+
.job-filters .chip-tab { height: 26px; padding: 0 9px; }
|
|
114
|
+
.job-filters .count { color: inherit; opacity: .7; font-variant-numeric: tabular-nums; }
|
|
115
|
+
.job-history-body { border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; background: var(--surface); }
|
|
116
|
+
.job-runs-head, .job-run-row { display: grid; grid-template-columns: 104px minmax(0, 1fr) 112px 72px 16px; align-items: center; gap: 12px; }
|
|
117
|
+
.job-runs-head { padding: 6px 12px; border-bottom: 1px solid var(--line); color: var(--ink-4); font-size: var(--fs-2xs); font-weight: 500; }
|
|
118
|
+
.job-runs-head > :nth-child(n+3), .job-run-when, .job-run-span { text-align: right; }
|
|
119
|
+
.jobs-runs { display: grid; }
|
|
120
|
+
.job-run-row { scroll-margin-top: calc(var(--header-h, 56px) + 12px); width: 100%; min-width: 0; padding: 7px 12px; border: 0; border-top: 1px solid var(--line); background: transparent; color: inherit; text-align: left; cursor: pointer; transition: background var(--t-fast); }
|
|
121
|
+
.jobs-runs > .job-run-row:first-child { border-top: 0; }
|
|
122
|
+
.job-run-row:hover { background: var(--surface-3); }
|
|
123
|
+
.job-run-row[aria-current="true"] { background: var(--surface-3); box-shadow: inset 2px 0 0 var(--accent); }
|
|
124
|
+
.job-run-caret { display: inline-grid; place-items: center; color: var(--ink-4); }
|
|
125
|
+
.job-run-caret .icon { width: 14px; height: 14px; transition: transform var(--t-fast); }
|
|
126
|
+
.job-run-row[aria-expanded="true"] .job-run-caret .icon { transform: rotate(90deg); color: var(--ink-2); }
|
|
127
|
+
.job-run-status .badge { height: 20px; padding: 0 7px; font-size: var(--fs-2xs); }
|
|
128
|
+
.job-run-main { display: grid; gap: 1px; min-width: 0; }
|
|
129
|
+
.job-run-summary { overflow: hidden; color: var(--ink); font-size: var(--fs-sm); text-overflow: ellipsis; white-space: nowrap; }
|
|
130
|
+
.job-run-sub { display: flex; gap: 8px; min-width: 0; color: var(--ink-4); font-size: var(--fs-2xs); white-space: nowrap; }
|
|
131
|
+
.job-run-sub code { color: var(--ink-3); }
|
|
132
|
+
.job-run-when, .job-run-span { color: var(--ink-3); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
133
|
+
.job-more { width: 100%; padding: 8px 12px; border: 0; border-top: 1px solid var(--line); background: transparent; color: var(--ink-3); font-size: var(--fs-xs); font-weight: 500; }
|
|
134
|
+
.job-more:hover { background: var(--surface-3); color: var(--ink); }
|
|
135
|
+
|
|
136
|
+
/* Selected Run: opened in place, directly under its row */
|
|
137
|
+
.job-run-inline { padding: 4px 12px 14px; border-top: 1px dashed var(--line); background: var(--surface-3); box-shadow: inset 2px 0 0 var(--accent); }
|
|
138
|
+
.jobs-runs > .job-run-inline:first-child { border-top: 0; }
|
|
139
|
+
.job-run-inline .job-run-panel { border-color: var(--line); box-shadow: var(--shadow-1); }
|
|
140
|
+
.job-run-inline:empty, .job-run-panel > section:empty, .job-run-artifacts > div:empty { display: none; }
|
|
141
|
+
.job-run-panel > .job-kv { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 24px; }
|
|
142
|
+
.job-run-panel > .job-kv > .job-kv-row:nth-child(2) { border-top: 0; }
|
|
143
|
+
.job-run-panel { display: grid; gap: 12px; min-width: 0; padding: 14px; border: 1px solid var(--line-2); border-radius: var(--r-md); background: var(--surface); }
|
|
144
|
+
.job-run-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
|
|
145
|
+
.job-run-head > .job-badges { flex: none; flex-wrap: nowrap; }
|
|
146
|
+
.job-run-title { display: flex; flex: 1; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; min-height: 28px; }
|
|
147
|
+
.job-run-title h4 { font-size: var(--fs-sm); font-weight: 600; }
|
|
148
|
+
.job-run-close { width: 28px; height: 28px; }
|
|
149
|
+
.job-result { margin: 0; padding: 8px 10px; border-left: 2px solid var(--tone, var(--line-3)); border-radius: 0 var(--r-sm) var(--r-sm) 0; background: var(--tone-soft, var(--surface-3)); color: var(--ink); font-size: var(--fs-sm); overflow-wrap: anywhere; }
|
|
150
|
+
.job-result-label { margin-right: 8px; color: var(--ink-3); font-size: var(--fs-xs); font-weight: 600; }
|
|
151
|
+
.job-run-steps { display: grid; margin: 0; padding: 0; list-style: none; border: 1px solid var(--line); border-radius: var(--r-sm); }
|
|
152
|
+
.job-run-step { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; padding: 6px 10px; border-top: 1px solid var(--line); font-size: var(--fs-xs); }
|
|
153
|
+
.job-run-step:first-child { border-top: 0; }
|
|
154
|
+
.job-run-step .badge { height: 20px; font-size: var(--fs-2xs); }
|
|
155
|
+
.job-run-step-meta { margin-left: auto; color: var(--ink-4); font-variant-numeric: tabular-nums; }
|
|
156
|
+
.job-logs { display: grid; gap: 6px; }
|
|
157
|
+
.job-log { border: 1px solid var(--line); border-radius: var(--r-sm); }
|
|
158
|
+
.job-log > summary { display: flex; align-items: center; gap: 8px; padding: 6px 10px; font-size: var(--fs-xs); cursor: pointer; }
|
|
159
|
+
.job-log-text { max-height: 320px; margin: 0; padding: 10px; overflow: auto; border-top: 1px solid var(--line); background: var(--sunken); font-size: var(--fs-2xs); line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
160
|
+
.job-artifact-list { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
161
|
+
.job-inline-action { justify-self: start; height: 26px !important; padding: 0 8px !important; color: var(--ink-3); font-size: var(--fs-xs); }
|
|
162
|
+
.job-run-evidence, .job-run-artifacts { display: grid; gap: 6px; min-width: 0; }
|
|
163
|
+
.job-advanced { display: grid; gap: 6px; }
|
|
164
|
+
|
|
165
|
+
/* Label/value lists (configuration, definition, Run facts) */
|
|
166
|
+
.job-kv { display: grid; margin: 0; min-width: 0; }
|
|
167
|
+
.job-kv-row { display: grid; grid-template-columns: 132px minmax(0, 1fr); gap: 12px; padding: 6px 0; border-top: 1px solid var(--line); font-size: var(--fs-sm); }
|
|
168
|
+
.job-kv-row:first-child { border-top: 0; }
|
|
169
|
+
.job-kv dt { color: var(--ink-4); font-size: var(--fs-xs); line-height: 1.7; overflow-wrap: anywhere; }
|
|
170
|
+
.job-kv dd { margin: 0; min-width: 0; color: var(--ink); overflow-wrap: anywhere; }
|
|
171
|
+
.job-kv.is-compact .job-kv-row { grid-template-columns: 84px minmax(0, 1fr); padding: 5px 0; }
|
|
172
|
+
.job-kv.is-nested { padding-left: 10px; border-left: 2px solid var(--line); }
|
|
173
|
+
.job-kv.is-nested .job-kv-row { grid-template-columns: minmax(80px, 120px) minmax(0, 1fr); padding: 3px 0; border-top: 0; }
|
|
174
|
+
.job-key { color: var(--ink-3); font-size: var(--fs-xs); }
|
|
175
|
+
.job-empty { color: var(--ink-4); }
|
|
176
|
+
.job-muted { color: var(--ink-4); font-size: var(--fs-xs); }
|
|
177
|
+
.job-text { white-space: pre-wrap; }
|
|
178
|
+
.job-kind { font-weight: 600; }
|
|
179
|
+
.job-prose { max-height: 240px; margin: 0; overflow: auto; color: var(--ink); font-family: inherit; font-size: var(--fs-sm); white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
180
|
+
.job-chips { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
181
|
+
.job-chip { padding: 1px 6px; border-radius: var(--r-xs); background: var(--surface-3); color: var(--ink-2); font-size: var(--fs-2xs); overflow-wrap: anywhere; }
|
|
182
|
+
.job-chip-key { color: var(--ink); font-weight: 600; }
|
|
183
|
+
.job-list { margin: 0; padding-left: 18px; }
|
|
184
|
+
.job-fold > summary { color: var(--ink-3); font-size: var(--fs-xs); cursor: pointer; }
|
|
185
|
+
.job-time { display: inline-flex; flex-wrap: wrap; gap: 0 8px; font-variant-numeric: tabular-nums; }
|
|
186
|
+
.job-time-ago { color: var(--ink-4); font-size: var(--fs-xs); }
|
|
187
|
+
.job-id, .job-path { display: inline-flex; align-items: center; gap: 2px; max-width: 100%; min-width: 0; }
|
|
188
|
+
.job-path code { min-width: 0; overflow-wrap: anywhere; font-size: var(--fs-xs); }
|
|
189
|
+
.job-copy { display: inline-grid; place-items: center; width: 22px; height: 22px; flex: none; padding: 0; border: 0; border-radius: var(--r-xs); background: transparent; color: var(--ink-4); }
|
|
190
|
+
.job-copy:hover { background: var(--surface-3); color: var(--ink); }
|
|
191
|
+
.job-copy .icon { width: 13px; height: 13px; }
|
|
192
|
+
.job-copy.is-copied { color: var(--ok); }
|
|
193
|
+
.job-copy-text { display: inline-flex; align-items: center; width: auto; gap: 4px; padding: 0 6px; font-size: var(--fs-2xs); white-space: nowrap; }
|
|
194
|
+
|
|
195
|
+
/* Configuration: steps as numbered rows with their command */
|
|
196
|
+
.job-config { display: grid; gap: 14px; min-width: 0; }
|
|
197
|
+
.job-steps { display: grid; margin: 0; padding: 0; list-style: none; border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
|
|
198
|
+
.job-step { display: grid; gap: 6px; padding: 10px 12px; border-top: 1px solid var(--line); min-width: 0; }
|
|
199
|
+
.job-step:first-child { border-top: 0; }
|
|
200
|
+
.job-step-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; min-width: 0; }
|
|
201
|
+
.job-step-index { display: inline-grid; place-items: center; width: 18px; height: 18px; border-radius: var(--r-pill); background: var(--surface-3); color: var(--ink-3); font-size: var(--fs-2xs); font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
202
|
+
.job-step-name { color: var(--ink); font-size: var(--fs-xs); font-weight: 600; }
|
|
203
|
+
.job-tag { max-width: 100%; padding: 0 6px; border: 1px solid var(--line-2); border-radius: var(--r-xs); color: var(--ink-3); font-size: var(--fs-2xs); line-height: 18px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
204
|
+
.job-command { display: flex; align-items: flex-start; gap: 4px; min-width: 0; padding: 6px 6px 6px 10px; border-radius: var(--r-sm); background: var(--sunken); }
|
|
205
|
+
.job-command pre { flex: 1; min-width: 0; margin: 0; padding-top: 2px; color: var(--ink); font-size: var(--fs-xs); line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
206
|
+
.job-command.is-prose pre { font-family: inherit; font-size: var(--fs-sm); }
|
|
207
|
+
.job-step-env { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0; }
|
|
208
|
+
.job-step-label { color: var(--ink-4); font-size: var(--fs-2xs); }
|
|
209
|
+
|
|
210
|
+
/* Exact JSON, one disclosure away */
|
|
211
|
+
.job-raw { position: relative; min-width: 0; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); overflow: hidden; }
|
|
212
|
+
.job-raw > summary { display: flex; align-items: center; gap: 8px; min-height: 34px; padding: 7px 110px 7px 12px; color: var(--ink-3); font-size: var(--fs-xs); cursor: pointer; list-style: none; }
|
|
213
|
+
.job-raw > summary::before { content: "›"; font-size: 16px; line-height: 1; transform-origin: center; }
|
|
214
|
+
.job-raw[open] > summary::before { transform: rotate(90deg); }
|
|
215
|
+
.job-raw > summary:hover { color: var(--ink); }
|
|
216
|
+
.job-raw-hint { padding: 0 5px; border: 1px solid var(--line-2); border-radius: var(--r-xs); color: var(--ink-4); font-family: var(--font-mono); font-size: 10px; line-height: 16px; }
|
|
217
|
+
.job-raw-body { min-width: 0; border-top: 1px solid var(--line); }
|
|
218
|
+
.job-raw-tools { position: absolute; right: 8px; top: 4px; display: flex; }
|
|
219
|
+
.job-raw .settings-observation { display: block; margin: 0; padding: 14px; max-height: 320px; overflow: auto; background: var(--sunken); color: var(--ink-2); font: var(--fs-xs)/1.65 var(--font-mono); white-space: pre; tab-size: 2; }
|
|
220
|
+
.job-form-advanced { min-width: 0; color: var(--ink-3); font-size: var(--fs-xs); }
|
|
221
|
+
.job-form-advanced > summary { cursor: pointer; padding: 8px 0; }
|
|
222
|
+
.job-form-advanced[open] > :not(summary) { margin-top: 8px; }
|
|
223
|
+
.job-form-advanced .job-raw { margin-top: 10px; }
|
|
224
|
+
.job-form-advanced:has(:focus-visible), .job-raw > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
225
|
+
|
|
226
|
+
/* Plans */
|
|
227
|
+
.job-plans { display: grid; margin: 0; padding: 0; list-style: none; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
|
|
228
|
+
.job-plan { display: grid; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--line); min-width: 0; }
|
|
229
|
+
.job-plan:first-child { border-top: 0; }
|
|
230
|
+
.job-plan-main { display: grid; gap: 4px; min-width: 0; }
|
|
231
|
+
.job-plan-line { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0; }
|
|
232
|
+
.job-plan-line .badge { height: 20px; padding: 0 7px; font-size: var(--fs-2xs); }
|
|
233
|
+
.job-plan-rule { font-size: var(--fs-sm); font-weight: 600; }
|
|
234
|
+
.job-plan-exact { color: var(--ink-4); font-family: var(--font-mono); font-size: var(--fs-2xs); overflow-wrap: anywhere; }
|
|
235
|
+
.job-plan-sub { color: var(--ink-4); font-size: var(--fs-2xs); }
|
|
236
|
+
.job-plan-sub code { color: var(--ink-3); overflow-wrap: anywhere; }
|
|
237
|
+
.job-plan-actions { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
238
|
+
.job-plan-actions .btn { height: 26px; padding: 0 8px; font-size: var(--fs-xs); }
|
|
239
|
+
|
|
240
|
+
/* Editor (a modal dialog, as the workbench's new Task) */
|
|
241
|
+
.job-dialog { width: min(760px, calc(100vw - 32px)); }
|
|
242
|
+
.job-dialog .job-form { gap: 14px; }
|
|
243
|
+
.job-dialog .dialog-actions { position: sticky; bottom: -20px; margin: 0 -20px -20px; padding: 12px 20px; border-top: 1px solid var(--line); background: var(--surface); }
|
|
244
|
+
.job-dialog-receipt { margin: 0; color: var(--ink-3); font-size: var(--fs-xs); white-space: pre-line; }
|
|
245
|
+
.job-dialog-receipt:empty { display: none; }
|
|
246
|
+
.job-dialog-receipt.settings-error { padding: 8px 10px; border-radius: var(--r-sm); background: var(--bad-soft); color: var(--bad); }
|
|
247
|
+
.job-fieldset { display: grid; gap: 10px; min-width: 0; margin: 0; padding: 12px 0 0; border: 0; border-top: 1px solid var(--line); }
|
|
248
|
+
.job-fieldset > legend { padding: 0 8px 0 0; color: var(--ink-2); font-size: var(--fs-sm); font-weight: 600; }
|
|
249
|
+
.job-field-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px 12px; }
|
|
250
|
+
.job-field-stack { display: grid; gap: 10px; }
|
|
251
|
+
.job-field-stack[hidden], .job-form [hidden] { display: none; }
|
|
252
|
+
.job-bound-target { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 10px 12px; border-radius: var(--r-sm); background: var(--sunken); color: var(--ink-3); font-size: var(--fs-sm); }
|
|
253
|
+
.job-bound-target strong { color: var(--ink); font-weight: 500; overflow-wrap: anywhere; }
|
|
254
|
+
.job-weekdays { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
255
|
+
.job-weekdays .btn { min-width: 38px; height: 34px; padding: 0 10px; }
|
|
256
|
+
.job-weekdays .btn[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--surface); }
|
|
257
|
+
.job-rule-preview { padding: 10px 12px; margin: 0; border-left: 2px solid var(--accent); background: var(--sunken); color: var(--ink-2); font-size: var(--fs-sm); overflow-wrap: anywhere; }
|
|
258
|
+
.job-rule-preview { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; border-radius: var(--r-sm); }
|
|
259
|
+
.job-rule-preview.is-error { border-color: var(--bad); color: var(--bad); background: var(--bad-soft); }
|
|
260
|
+
.job-plan-expression { color: var(--ink-3); font-size: var(--fs-xs); overflow-wrap: anywhere; }
|
|
261
|
+
.job-clock input { font-variant-numeric: tabular-nums; }
|
|
262
|
+
.job-time-shortcuts { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
263
|
+
.job-time-shortcuts .btn { height: 28px; padding: 0 10px; color: var(--ink-3); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
|
|
264
|
+
.job-cron-guide { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); margin: 0; padding: 12px; gap: 8px; border: 1px solid var(--line); border-radius: var(--r-sm); }
|
|
265
|
+
.job-cron-guide dt { color: var(--ink-3); font-size: var(--fs-xs); }
|
|
266
|
+
.job-cron-guide dd { display: grid; gap: 6px; margin: 6px 0 0; overflow-wrap: anywhere; }
|
|
267
|
+
.job-cron-guide dd span { color: var(--ink-4); font-size: var(--fs-2xs); }
|
|
268
|
+
@media (max-width: 480px) {
|
|
269
|
+
.job-cron-guide { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
270
|
+
}
|
|
271
|
+
.job-edit-row { display: grid; gap: 10px; padding: 12px; border: 1px solid var(--line); border-radius: var(--r-sm); min-width: 0; }
|
|
272
|
+
.job-edit-row > .btn, .job-field-stack > .btn { justify-self: start; }
|
|
273
|
+
.job-form textarea { width: 100%; resize: vertical; min-height: 88px; font-size: var(--fs-sm); }
|
|
274
|
+
.job-form input, .job-form select, .job-form textarea { min-width: 0; }
|
|
275
|
+
.jobs-manager form .field > span { color: var(--ink-3); font-size: var(--fs-xs); font-weight: 500; }
|
|
276
|
+
.jobs-manager form input, .jobs-manager form select { height: 32px; padding-top: 4px; padding-bottom: 4px; font-size: var(--fs-sm); }
|
|
277
|
+
.job-config-preview { display: grid; gap: 8px; padding: 12px; border: 1px dashed var(--line-2); border-radius: var(--r-md); }
|
|
278
|
+
.job-preview-label { color: var(--ink-4); font-size: var(--fs-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: .06em; }
|
|
279
|
+
|
|
14
280
|
@media (max-width: 720px) { .jobs-layout { grid-template-columns: minmax(0, 1fr); } }
|
|
281
|
+
@container (max-width: 860px) {
|
|
282
|
+
.job-about { grid-template-columns: minmax(0, 1fr); }
|
|
283
|
+
}
|
|
15
284
|
@container (max-width: 640px) {
|
|
16
285
|
.jobs-layout { grid-template-columns: minmax(0, 1fr); }
|
|
17
|
-
.jobs-
|
|
286
|
+
.jobs-bar-refresh > span { display: none; }
|
|
287
|
+
.job-actions { flex-wrap: wrap; }
|
|
288
|
+
.job-overview { padding: 10px 12px; }
|
|
289
|
+
.job-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 12px; width: 100%; }
|
|
290
|
+
.job-stat { padding: 0; border-left: 0; }
|
|
291
|
+
.job-spark { width: 100%; }
|
|
292
|
+
.job-spark-bar { flex: 1; width: auto; max-width: 8px; }
|
|
293
|
+
.job-runs-head { display: none; }
|
|
294
|
+
.job-run-row { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "main status" "main when"; gap: 2px 10px; padding: 8px 10px; }
|
|
295
|
+
.job-run-caret { display: none; }
|
|
296
|
+
.job-run-inline { padding: 2px 8px 10px; }
|
|
297
|
+
.job-run-status { grid-area: status; justify-self: end; }
|
|
298
|
+
.job-run-main { grid-area: main; }
|
|
299
|
+
.job-run-when { grid-area: when; }
|
|
300
|
+
.job-run-span { display: none; }
|
|
301
|
+
.job-run-summary { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
|
|
302
|
+
.job-kv-row, .job-kv.is-compact .job-kv-row { grid-template-columns: 92px minmax(0, 1fr); gap: 10px; }
|
|
303
|
+
.job-kv.is-nested .job-kv-row { grid-template-columns: minmax(0, 1fr); }
|
|
304
|
+
.job-run-panel { padding: 12px; }
|
|
305
|
+
.job-run-panel > .job-kv { grid-template-columns: minmax(0, 1fr); }
|
|
306
|
+
.job-run-panel > .job-kv > .job-kv-row:nth-child(2) { border-top: 1px solid var(--line); }
|
|
18
307
|
}
|
|
19
308
|
`;
|
|
@@ -30,8 +30,6 @@ export const SIDEBAR_STYLES = `
|
|
|
30
30
|
.search-field:focus-within kbd{opacity:0}
|
|
31
31
|
.side-search-body{width:34px;height:34px;border:1px solid var(--line-2);border-radius:var(--r-md);background:var(--surface-2)}
|
|
32
32
|
.side-search-body:hover:not(:disabled){border-color:var(--line-3)}
|
|
33
|
-
.source-seg{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));width:100%}
|
|
34
|
-
.source-seg .seg-btn{justify-content:center;min-width:0;overflow:hidden;text-overflow:ellipsis}
|
|
35
33
|
.attention-bar:empty{display:none}
|
|
36
34
|
.attention-list{display:flex;flex-wrap:wrap;gap:6px}
|
|
37
35
|
.attention-pill{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 9px;border:1px solid transparent;border-radius:var(--r-pill);background:var(--tone-soft);color:var(--tone);font-size:var(--fs-xs);font-weight:500}
|
|
@@ -63,6 +61,7 @@ export const SIDEBAR_STYLES = `
|
|
|
63
61
|
.task-time{flex:none;color:var(--ink-4);font-size:var(--fs-2xs);font-variant-numeric:tabular-nums}
|
|
64
62
|
.task-sub{gap:8px;height:18px;color:var(--ink-4);font-size:var(--fs-2xs)}
|
|
65
63
|
.task-id{font-size:var(--fs-2xs);line-height:1;color:var(--ink-3)}
|
|
64
|
+
.task-source{flex:none;padding:0 5px;border:1px solid var(--line-2);border-radius:var(--r-pill);color:var(--ink-3);font-size:10px;line-height:15px}
|
|
66
65
|
.task-count{display:inline-flex;align-items:center;gap:3px;line-height:1;white-space:nowrap}
|
|
67
66
|
.task-count .icon{width:11px;height:11px}
|
|
68
67
|
.task-signals{display:inline-flex;gap:4px;margin-left:auto}
|
|
@@ -9,8 +9,7 @@ export const TASK_STYLES = `
|
|
|
9
9
|
and frosting the content scrolling beneath them. */
|
|
10
10
|
.tabs-wrap{position:sticky;margin:0 calc(-1 * var(--gutter));padding:0 var(--gutter);background:var(--canvas)}
|
|
11
11
|
.dock-toggle{height:30px}
|
|
12
|
-
.
|
|
13
|
-
.operator-toggle[aria-pressed="true"]{background:var(--accent-soft);color:var(--accent)}
|
|
12
|
+
.operator-toggle[aria-pressed="true"],.panel-toggle[aria-expanded="true"]{background:var(--accent-soft);color:var(--accent)}
|
|
14
13
|
.task-hero{padding:28px 0 18px}
|
|
15
14
|
.task-title{font-size:var(--fs-2xl);font-weight:650;letter-spacing:-.025em;line-height:1.25;overflow-wrap:anywhere}
|
|
16
15
|
.task-meta{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:12px;color:var(--ink-3);font-size:var(--fs-xs)}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_DARK_THEME } from "../../shared/themes.js";
|
|
2
2
|
const SESSION_TONES = DEFAULT_DARK_THEME.tokens;
|
|
3
3
|
/*
|
|
4
|
-
* TERMINAL VIEW — the
|
|
4
|
+
* TERMINAL VIEW — the session page's terminal mode. It renders a native terminal, so it
|
|
5
5
|
* stays dark in every theme: its chrome uses a scoped palette (white alphas
|
|
6
6
|
* and the default dark theme's status colours) instead of theme tokens.
|
|
7
7
|
*/
|
|
@@ -9,13 +9,15 @@ export const TERMINAL_STYLES = `
|
|
|
9
9
|
.dock-session{background:var(--term-bg);color:#e6e6e8;--chrome-line:rgba(255,255,255,.07);--chrome-ok:${SESSION_TONES.ok};--chrome-info:${SESSION_TONES.info};--chrome-bad:${SESSION_TONES.bad}}
|
|
10
10
|
.dock-session .faint{color:rgba(255,255,255,.4)}
|
|
11
11
|
|
|
12
|
-
/*
|
|
12
|
+
/* Header row: the selected Session, the connection state, the mode switch */
|
|
13
13
|
.session-bar{flex:none;display:flex;align-items:center;gap:8px;min-height:44px;padding:6px 10px;border-bottom:1px solid var(--chrome-line)}
|
|
14
|
-
.session-
|
|
15
|
-
.
|
|
16
|
-
.
|
|
17
|
-
.
|
|
18
|
-
.
|
|
14
|
+
.session-bar .spacer{flex:1 1 0;min-width:0}
|
|
15
|
+
.sp-term-icon{width:14px;height:14px;flex:none;color:rgba(255,255,255,.45)}
|
|
16
|
+
.sp-term-name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#fff;font-size:var(--fs-sm);font-weight:600}
|
|
17
|
+
.dock-session .sp-modes{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.1)}
|
|
18
|
+
.dock-session .sp-modes .seg-btn{color:rgba(255,255,255,.62)}
|
|
19
|
+
.dock-session .sp-modes .seg-btn:hover{color:#fff}
|
|
20
|
+
.dock-session .sp-modes .seg-btn[aria-checked="true"]{background:rgba(255,255,255,.14);color:#fff;box-shadow:none}
|
|
19
21
|
.conn{display:inline-flex;align-items:center;gap:6px;flex:none;color:rgba(255,255,255,.6);font-size:var(--fs-xs);font-weight:500}
|
|
20
22
|
.conn i{width:7px;height:7px;border-radius:50%;background:rgba(255,255,255,.3)}
|
|
21
23
|
.conn[data-state="connecting"] i{background:var(--warn);animation:m-blink 1s infinite}
|
|
@@ -33,6 +35,8 @@ export const TERMINAL_STYLES = `
|
|
|
33
35
|
.terminal-empty .icon{color:rgba(255,255,255,.35)}
|
|
34
36
|
.terminal-empty-title{color:#fff;font-weight:600}
|
|
35
37
|
.terminal-empty-text{max-width:300px;font-size:var(--fs-xs);line-height:1.5}
|
|
38
|
+
.terminal-empty[hidden]{display:none}
|
|
39
|
+
.terminal-empty .btn{margin-top:4px}
|
|
36
40
|
.session-foot{flex:none;display:flex;align-items:center;gap:8px;padding:8px 12px;border-top:1px solid var(--chrome-line);color:rgba(255,255,255,.45);font-size:var(--fs-2xs)}
|
|
37
|
-
.session-foot code{color:rgba(255,255,255,.8);user-select:all}
|
|
41
|
+
.session-foot code{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:rgba(255,255,255,.8);user-select:all}
|
|
38
42
|
`;
|
|
@@ -91,6 +91,7 @@ export function conversationSessions(set) {
|
|
|
91
91
|
endReason: session.endReason, createdAt: session.createdAt,
|
|
92
92
|
executionAuthority: session.effective.executionAuthority,
|
|
93
93
|
launchModel: session.effective.model ?? null,
|
|
94
|
+
launchEffort: session.effective.effort ?? null,
|
|
94
95
|
current: set.sessions[set.activeAgentId] === session,
|
|
95
96
|
conversationEpoch: set.providerBinding?.conversations.find(c => c.conversationId === session.nativeSessionId)?.epoch ?? null }));
|
|
96
97
|
}
|
package/dist/web/webServer.js
CHANGED
|
@@ -720,7 +720,7 @@ async function handleHttpRequest(request, response, store, dependencies, token,
|
|
|
720
720
|
try {
|
|
721
721
|
const assetVersion = new URL(request.url, "http://localhost").searchParams.get("v");
|
|
722
722
|
const asset = findWebAsset(pathname, assetVersion);
|
|
723
|
-
const managementPage = /^\/(?:models(?:\/(?:providers|catalog|quota))?|settings(?:\/(?:preferences|skills|jobs|permissions|server|connection))
|
|
723
|
+
const managementPage = /^\/(?:models(?:\/(?:providers|catalog|quota))?|settings(?:\/(?:preferences|skills|jobs|permissions|server|connection))?|jobs)\/?$/.test(pathname);
|
|
724
724
|
if (pathname === "/" || pathname === "/index.html" || managementPage) {
|
|
725
725
|
sendText(response, 200, "text/html; charset=utf-8", prepareWebDocument(managementPage ? MODELS_HTML.replace("__YUI_WEB_TOKEN__", token) : dashboardHtml(token), managementPage ? "/assets/js/app/manage.js" : "/assets/app.js"), method === "HEAD");
|
|
726
726
|
}
|
|
@@ -735,6 +735,11 @@ async function handleHttpRequest(request, response, store, dependencies, token,
|
|
|
735
735
|
...[...query].filter(([key]) => key !== "query").flatMap(([key, value]) => [`--${key}`, value])]);
|
|
736
736
|
sendJson(response, 200, store.transaction(reader => searchTaskBodies(reader, options)), method === "HEAD");
|
|
737
737
|
}
|
|
738
|
+
else if (pathname === "/api/jobs/scopes") {
|
|
739
|
+
if (new URL(request.url, "http://localhost").search !== "")
|
|
740
|
+
throw usageError("Job scope discovery takes no options.");
|
|
741
|
+
sendJson(response, 200, store.readTransaction(reader => readWebJobScopes(reader)), method === "HEAD");
|
|
742
|
+
}
|
|
738
743
|
else if (pathname === "/api/dashboard" || pathname === "/api/dashboard/sessions") {
|
|
739
744
|
const query = new URL(request.url, "http://localhost").searchParams;
|
|
740
745
|
const options = parseTaskCatalogOptions([...query].flatMap(([key, value]) => key === "all"
|
|
@@ -1281,6 +1286,28 @@ function rejectUpgrade(socket, status, message) {
|
|
|
1281
1286
|
+ "Connection: close\r\n"
|
|
1282
1287
|
+ "Content-Length: 0\r\n\r\n");
|
|
1283
1288
|
}
|
|
1289
|
+
/** Bounded owner discovery for the Jobs entry: counts per owning scope only.
|
|
1290
|
+
* Records are still listed through the scope's own Job/Schedule reads, with
|
|
1291
|
+
* their existing authority checks; this never lists a definition itself. */
|
|
1292
|
+
const JOB_SCOPE_TASK_LIMIT = 200;
|
|
1293
|
+
export function readWebJobScopes(reader) {
|
|
1294
|
+
const empty = { definitions: 0, schedules: 0, enabledSchedules: 0 };
|
|
1295
|
+
let global = empty;
|
|
1296
|
+
const tasks = [];
|
|
1297
|
+
for (const summary of reader.listJobScopeSummaries()) {
|
|
1298
|
+
const counts = { definitions: summary.definitions, schedules: summary.schedules, enabledSchedules: summary.enabledSchedules };
|
|
1299
|
+
if (summary.scope.kind === "global") {
|
|
1300
|
+
global = counts;
|
|
1301
|
+
continue;
|
|
1302
|
+
}
|
|
1303
|
+
const task = reader.getTask(summary.scope.taskId);
|
|
1304
|
+
if (task !== null)
|
|
1305
|
+
tasks.push({ taskId: task.id, title: task.title, status: task.status, ...counts });
|
|
1306
|
+
}
|
|
1307
|
+
tasks.sort((a, b) => Number(b.taskId.slice(5)) - Number(a.taskId.slice(5)));
|
|
1308
|
+
return { global, tasks: tasks.slice(0, JOB_SCOPE_TASK_LIMIT), total: tasks.length,
|
|
1309
|
+
omitted: Math.max(0, tasks.length - JOB_SCOPE_TASK_LIMIT), scope: "owner-counts-only; records use each scope's authorized reads" };
|
|
1310
|
+
}
|
|
1284
1311
|
function dashboardHtml(token) {
|
|
1285
1312
|
return DASHBOARD_HTML.replace('content="__YUI_WEB_TOKEN__"', `content="${escapeHtmlAttribute(token)}"`);
|
|
1286
1313
|
}
|
package/dist/web/webSettings.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { isEnabled } from "../role/availability.js";
|
|
2
3
|
import { CONFIG_DOMAINS, configDefinitionsForDomain } from "../config/configCatalog.js";
|
|
3
4
|
import { effectiveConfigData, runConfigCommand } from "../commands/configCommands.js";
|
|
4
5
|
import { runAgentCommand } from "../commands/agentCommands.js";
|
|
@@ -9,8 +10,8 @@ import { staticAgentConfigurationFields } from "../executor/agentConfigurationFi
|
|
|
9
10
|
import { validateAgentLaunchConfiguration } from "../executor/agentConfigurationCatalog.js";
|
|
10
11
|
import { resolveAgentProfileView } from "../profile/agentProfileRuntime.js";
|
|
11
12
|
import { webLocalMutation, WebRequestRejected } from "./webMutation.js";
|
|
12
|
-
const ROLE_NOTICE = "
|
|
13
|
-
const PROFILE_NOTICE = "Profile
|
|
13
|
+
const ROLE_NOTICE = "Disabling blocks new execution and template selection, without stopping running Sessions or discarding input. Enable allows normal scheduling, not an immediate Session start. Existing Task bindings are unchanged. Launch settings apply to a subsequent launch; no Session is restarted here.";
|
|
14
|
+
const PROFILE_NOTICE = "Disabling prevents new Profile application. A Profile is a template, not a process. Existing Task Roles are not rebound or stopped. Inherited runtime requires an enabled global Worker when applied. Reset preserves enabled state.";
|
|
14
15
|
const AGENT_NOTICE = "Command, arguments and environment references apply to subsequent Host processes. Authentication remains with the native Agent. Only reference names and presence in the Controller environment are shown; no environment values are returned.";
|
|
15
16
|
/** A view adapter over existing commands, not another writable configuration store. */
|
|
16
17
|
export function createWebSettings(store, options) {
|
|
@@ -84,6 +85,7 @@ export function createWebSettings(store, options) {
|
|
|
84
85
|
notice = ROLE_NOTICE;
|
|
85
86
|
const specs = roleOptionSpecs({ update: true, includeWorkspace: true });
|
|
86
87
|
fields = [
|
|
88
|
+
{ ...field("enabled", isEnabled(role), "boolean"), summary: ROLE_NOTICE },
|
|
87
89
|
{ ...field("activeAgentId", role.activeAgentId), choices: store.listConfiguredAgents().map(a => a.id),
|
|
88
90
|
summary: "Explicit global Role Agent selection. Save this field alone, then edit the selected Agent's settings. Existing live-session and lifecycle guards apply; no Task is rebound." },
|
|
89
91
|
field("workspace", role.workspace),
|
|
@@ -109,6 +111,7 @@ export function createWebSettings(store, options) {
|
|
|
109
111
|
notice = PROFILE_NOTICE;
|
|
110
112
|
agentId = view.runtime.status === "resolved" ? view.runtime.binding.agentId : undefined;
|
|
111
113
|
fields = [
|
|
114
|
+
{ ...field("enabled", isEnabled(profile), "boolean"), summary: PROFILE_NOTICE },
|
|
112
115
|
{ ...field("access", profile.defaultAccess), choices: ["read", "write"] },
|
|
113
116
|
{ ...field("description", profile.description ?? "", "multiline"), reset: true },
|
|
114
117
|
{ ...field("instructions", profile.instructions ?? "", "multiline"), reset: true },
|
|
@@ -287,6 +290,11 @@ function objectArguments(id, changes) {
|
|
|
287
290
|
if (CONFIG_DOMAINS.includes(id))
|
|
288
291
|
return [];
|
|
289
292
|
return changes.flatMap(c => {
|
|
293
|
+
if ((id.startsWith("role/") || id.startsWith("profile/")) && c.key === "enabled") {
|
|
294
|
+
if (typeof c.value !== "boolean")
|
|
295
|
+
throw new WebRequestRejected("Enabled must be a boolean.");
|
|
296
|
+
return ["--enabled", String(c.value)];
|
|
297
|
+
}
|
|
290
298
|
if (id.startsWith("role/") && c.key === "activeAgentId")
|
|
291
299
|
return [];
|
|
292
300
|
if (id.startsWith("agent/")) {
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Global Shell Jobs
|
|
2
|
+
|
|
3
|
+
A global Shell Job owns its command steps, environment and text script files.
|
|
4
|
+
It needs neither a Task nor a Project. The Web Jobs editor and CLI edit the
|
|
5
|
+
same revisioned definition. Saving never starts a Run.
|
|
6
|
+
|
|
7
|
+
Commands execute as the local Yui user, **not in a security sandbox**. Do not
|
|
8
|
+
store credentials in commands, scripts or environment variables. Task-scoped
|
|
9
|
+
Shell Jobs retain their existing managed Project/workspace authority.
|
|
10
|
+
|
|
11
|
+
## CLI
|
|
12
|
+
|
|
13
|
+
Create a command-only Job:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
yui job define --global --job hello --title "Hello" --command 'printf "hello\n"'
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Import a local script into a Job-owned relative path (the file contents are
|
|
20
|
+
copied, not linked to the mutable source file):
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
yui job define --global --job check --title "Daily check" \
|
|
24
|
+
--command 'sh scripts/check.sh' --script scripts/check.sh=./check.sh
|
|
25
|
+
yui job show --global --job check --json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Edit the local script and upload a replacement using the revision returned by
|
|
29
|
+
`show`. Existing commands and other script files are preserved:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
yui job update --global --job check --revision 1 \
|
|
33
|
+
--script scripts/check.sh=./check.sh
|
|
34
|
+
yui job update --global --job hello --revision 1 --command 'printf "updated\n"'
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`--script` can be repeated for different paths. To edit multiple steps,
|
|
38
|
+
environment variables, or remove files, use `--input-file config.json` with
|
|
39
|
+
the complete configuration:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"kind": "shell",
|
|
44
|
+
"env": {},
|
|
45
|
+
"steps": [{"name": "check", "command": "sh scripts/check.sh", "timeoutMs": 60000}],
|
|
46
|
+
"files": [{"path": "scripts/check.sh", "content": "printf 'ok\\n'\n"}]
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Pass `--title` with complete-configuration define/update. Re-read the current
|
|
51
|
+
revision after a conflict instead of blindly retrying. A full configuration
|
|
52
|
+
replaces the previous one; shorthand edits preserve unrelated fields.
|
|
53
|
+
|
|
54
|
+
Run explicitly and inspect the exact returned Run:
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
yui job run --global --job check --request-id check-20261023-1
|
|
58
|
+
yui job runs --global --job check
|
|
59
|
+
yui job logs --global --job check --run <returned-run-id>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Files, history and schedules
|
|
63
|
+
|
|
64
|
+
Each admitted Run captures the exact configuration and script contents. The
|
|
65
|
+
runner materializes files in a fresh `artifacts/jobs/global/<run-id>/workspace`
|
|
66
|
+
directory inside the selected Yui Home. Earlier Runs are not changed by later
|
|
67
|
+
edits. Script paths are relative, cannot traverse directories, and are limited
|
|
68
|
+
to 64 files / 512 KiB total. Use `sh scripts/check.sh` or another installed
|
|
69
|
+
interpreter; script names do not choose an interpreter automatically.
|
|
70
|
+
|
|
71
|
+
Schedules use the existing explicit service authorization, bound to the Job's
|
|
72
|
+
revision. Editing commands or scripts invalidates the old schedule binding;
|
|
73
|
+
inspect and explicitly re-enable/re-authorize the schedule before future runs.
|
|
74
|
+
Saving a new script never silently changes an already authorized command.
|
|
75
|
+
|
|
76
|
+
Storage 1.23 declares this additive payload change. Upgrade an existing Home
|
|
77
|
+
through the normal authorized upgrade path; do not run a new build against an
|
|
78
|
+
older shared Home or rewrite its records by hand.
|
package/docs/job-runs.md
CHANGED
|
@@ -176,9 +176,12 @@ identities. Ordinary readers use only the current contract.
|
|
|
176
176
|
start is not confirmation. The snapshot is derived exclusively from the immutable
|
|
177
177
|
Run fields, never a mutable current Job definition. Scope, executor (`shell` or
|
|
178
178
|
controlled `builtin`, or `task`), target and trigger are separate concepts. Task
|
|
179
|
-
delegation is available in either management scope;
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
delegation is available in either management scope; builtin remains global-only.
|
|
180
|
+
Global Shell Jobs own revisioned command steps and script files, without a Task
|
|
181
|
+
or Project. Task Shell Jobs retain managed-workspace authority.
|
|
182
|
+
See [Global Shell Jobs](global-shell-jobs.md) for Web/CLI editing, per-Run file
|
|
183
|
+
snapshots and schedule reauthorization. There is no extensible empty executor
|
|
184
|
+
or plugin configuration.
|
|
182
185
|
|
|
183
186
|
## Delegating delivery to a Task
|
|
184
187
|
|