toolroll 0.9.67 → 0.9.68
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/CHANGELOG.md +36 -0
- package/dist/acp-client.js +1 -3
- package/dist/agent-board.d.ts +0 -1
- package/dist/agent-board.js +0 -1
- package/dist/agent-fence.js +3 -0
- package/dist/browser/workspace.css +1 -1
- package/dist/browser/workspace.js +31 -29
- package/dist/builder.js +3 -26
- package/dist/canonical-json.d.ts +14 -0
- package/dist/canonical-json.js +36 -0
- package/dist/chat-actions.js +1 -2
- package/dist/chat-admission.d.ts +19 -0
- package/dist/chat-admission.js +22 -0
- package/dist/chat-channel.js +1 -1
- package/dist/chat-delivery.js +0 -1
- package/dist/chat-follow.d.ts +17 -0
- package/dist/chat-follow.js +32 -0
- package/dist/chat-messages.js +0 -1
- package/dist/chat-settings-page.d.ts +23 -0
- package/dist/chat-settings-page.js +41 -0
- package/dist/claim.js +3 -6
- package/dist/claude-print.d.ts +12 -0
- package/dist/claude-print.js +34 -0
- package/dist/cli-http.d.ts +0 -7
- package/dist/cli-http.js +0 -21
- package/dist/cli.d.ts +3 -10
- package/dist/cli.js +15 -24
- package/dist/coding-provider.js +2 -1
- package/dist/coding-workspace.js +1 -1
- package/dist/{team-cli.d.ts → connect-cli.d.ts} +5 -9
- package/dist/connect-cli.js +331 -0
- package/dist/containment.d.ts +0 -2
- package/dist/containment.js +2 -6
- package/dist/contracts/chat-actions.d.ts +0 -1
- package/dist/contracts/chat-content.d.ts +0 -4
- package/dist/contracts/chat-content.js +0 -2
- package/dist/contracts/chat-tables.d.ts +0 -1
- package/dist/contracts/cli.d.ts +0 -62
- package/dist/contracts/cli.js +0 -4
- package/dist/contracts/coding-workspace.js +1 -1
- package/dist/contracts/contract.js +1 -1
- package/dist/contracts/flow-card.d.ts +0 -1
- package/dist/contracts/flow-propose.d.ts +0 -1
- package/dist/contracts/flow-send.js +1 -1
- package/dist/contracts/gateway-tools.d.ts +0 -1
- package/dist/contracts/integration-metadata.js +1 -1
- package/dist/contracts/lead-tools.d.ts +0 -1
- package/dist/contracts/memory-pass.d.ts +0 -1
- package/dist/contracts/memory-pass.js +1 -1
- package/dist/contracts/plan.js +1 -1
- package/dist/contracts/project-knowledge.js +1 -1
- package/dist/contracts/project-skills.d.ts +0 -1
- package/dist/contracts/proof.js +1 -1
- package/dist/contracts/recipes.js +1 -1
- package/dist/contracts/scope.js +1 -1
- package/dist/contracts/scout-report.js +1 -1
- package/dist/contracts/teams-callback.d.ts +0 -1
- package/dist/converse.d.ts +0 -6
- package/dist/converse.js +0 -19
- package/dist/daemon.js +3 -2
- package/dist/decision.d.ts +1 -3
- package/dist/deprecations.d.ts +12 -4
- package/dist/deprecations.js +27 -4
- package/dist/desktop-update-recovery.js +1 -1
- package/dist/desktop-update.js +3 -2
- package/dist/discord-chat.js +4 -15
- package/dist/discord-settings.d.ts +2 -6
- package/dist/discord-settings.js +10 -38
- package/dist/discord.js +12 -23
- package/dist/evidence.d.ts +0 -1
- package/dist/evidence.js +0 -3
- package/dist/exec.d.ts +0 -9
- package/dist/exec.js +3 -81
- package/dist/flow-actions.js +0 -3
- package/dist/flow-draft.d.ts +1 -3
- package/dist/flow-draft.js +15 -28
- package/dist/flow-scripts.d.ts +1 -8
- package/dist/flow-scripts.js +0 -13
- package/dist/flow-send.js +1 -1
- package/dist/flow-share.d.ts +0 -2
- package/dist/flow-share.js +1 -6
- package/dist/flow-steps.js +1 -1
- package/dist/flow-triggers.d.ts +0 -1
- package/dist/flow-triggers.js +1 -2
- package/dist/flow-unattended.js +1 -12
- package/dist/flows.js +1 -1
- package/dist/health-cli.d.ts +2 -2
- package/dist/health-cli.js +1 -1
- package/dist/invoke.d.ts +0 -3
- package/dist/invoke.js +5 -3
- package/dist/is-record.d.ts +2 -0
- package/dist/is-record.js +2 -0
- package/dist/lead-doors.d.ts +1 -5
- package/dist/lead-doors.js +0 -4
- package/dist/lead-tools.js +3 -6
- package/dist/live-detail.d.ts +0 -1
- package/dist/live-detail.js +0 -6
- package/dist/live-terminal.js +2 -1
- package/dist/live.d.ts +0 -1
- package/dist/live.js +1 -2
- package/dist/mcp-core.js +0 -2
- package/dist/memory-pass.js +1 -1
- package/dist/model-catalog.js +1 -1
- package/dist/modes.js +1 -12
- package/dist/operate.js +383 -750
- package/dist/password-bearer.d.ts +0 -2
- package/dist/password-bearer.js +0 -4
- package/dist/peek-cli.js +2 -1
- package/dist/peek.d.ts +2 -26
- package/dist/peek.js +2 -168
- package/dist/phase-routing.d.ts +0 -4
- package/dist/phase-routing.js +2 -21
- package/dist/planner-source.d.ts +2 -1
- package/dist/planner-source.js +2 -12
- package/dist/planner.js +2 -14
- package/dist/process-tree.d.ts +0 -2
- package/dist/process-tree.js +0 -10
- package/dist/project-delete.d.ts +0 -2
- package/dist/project-delete.js +1 -3
- package/dist/project-learning.d.ts +0 -14
- package/dist/project-skills.d.ts +0 -1
- package/dist/project-skills.js +0 -14
- package/dist/project-tools.js +2 -10
- package/dist/provider.d.ts +0 -17
- package/dist/provider.js +0 -26
- package/dist/pulls.d.ts +0 -2
- package/dist/pulls.js +0 -9
- package/dist/release-adapters.d.ts +3 -0
- package/dist/release-adapters.js +15 -5
- package/dist/remote-exec.d.ts +3 -2
- package/dist/remote-exec.js +3 -2
- package/dist/repos.d.ts +0 -5
- package/dist/repos.js +2 -10
- package/dist/repository-context.d.ts +0 -2
- package/dist/repository-context.js +0 -4
- package/dist/restart-certification.d.ts +0 -2
- package/dist/restart-certification.js +1 -5
- package/dist/result-follow-ups.d.ts +1 -4
- package/dist/result-follow-ups.js +1 -6
- package/dist/result-review.d.ts +0 -2
- package/dist/result-review.js +0 -2
- package/dist/retention.d.ts +0 -1
- package/dist/retention.js +0 -1
- package/dist/review-context.d.ts +0 -1
- package/dist/review-context.js +1 -12
- package/dist/reviewer.d.ts +0 -16
- package/dist/reviewer.js +0 -18
- package/dist/run-closeout.js +2 -1
- package/dist/scope.js +1 -13
- package/dist/scout-browser.js +2 -1
- package/dist/serve.js +2 -2
- package/dist/server/console.css +5 -133
- package/dist/server/flows.js +2 -2
- package/dist/server/http.d.ts +2 -0
- package/dist/server/http.js +5 -0
- package/dist/server/pages.js +2 -2
- package/dist/server/people-tokens.js +3 -4
- package/dist/server/remote.js +1 -6
- package/dist/server/render-chat.d.ts +9 -2
- package/dist/server/render-chat.js +53 -7
- package/dist/server/render-results.d.ts +0 -6
- package/dist/server/render-results.js +3 -9
- package/dist/server/render-tasks.js +4 -5
- package/dist/server/route-table.d.ts +0 -4
- package/dist/server/route-table.js +0 -6
- package/dist/server/settings.js +23 -23
- package/dist/server/task-views.js +1 -1
- package/dist/server/tasks.js +3 -3
- package/dist/setup-guide.d.ts +2 -2
- package/dist/skills.d.ts +0 -6
- package/dist/skills.js +0 -8
- package/dist/slack-chat.d.ts +1 -7
- package/dist/slack-chat.js +5 -18
- package/dist/slack-settings.d.ts +2 -6
- package/dist/slack-settings.js +10 -38
- package/dist/slack.js +12 -23
- package/dist/sleep.d.ts +2 -0
- package/dist/sleep.js +2 -0
- package/dist/store.d.ts +0 -73
- package/dist/store.js +3 -177
- package/dist/structured-output.d.ts +0 -1
- package/dist/structured-output.js +0 -1
- package/dist/subagent-work.d.ts +0 -2
- package/dist/subagent-work.js +0 -2
- package/dist/subagents.d.ts +1 -3
- package/dist/subagents.js +20 -33
- package/dist/subscription-chat.d.ts +1 -3
- package/dist/subscription-chat.js +2 -3
- package/dist/task-sizing.d.ts +1 -4
- package/dist/task-sizing.js +3 -10
- package/dist/teams-chat.js +4 -11
- package/dist/teams.js +12 -19
- package/dist/telegram-lead.js +2 -2
- package/dist/telegram.js +1 -1
- package/dist/token-notices.d.ts +0 -11
- package/dist/token-notices.js +1 -5
- package/dist/tool-secret-store.d.ts +0 -3
- package/dist/tool-secret-store.js +2 -11
- package/dist/toolroll-update.d.ts +0 -2
- package/dist/toolroll-update.js +2 -2
- package/dist/verification-evidence.d.ts +0 -1
- package/dist/verification-evidence.js +0 -1
- package/dist/webhooks.d.ts +0 -1
- package/dist/webhooks.js +0 -1
- package/dist/workspace-ui.d.ts +0 -8
- package/dist/workspace-ui.js +1 -6
- package/package.json +1 -1
- package/dist/contracts/native-census.d.ts +0 -42
- package/dist/contracts/native-census.js +0 -36
- package/dist/process-recovery-anchor.d.ts +0 -75
- package/dist/process-recovery-anchor.js +0 -188
- package/dist/process-recovery-coalition.d.ts +0 -25
- package/dist/process-recovery-coalition.js +0 -105
- package/dist/process-recovery-eligibility.d.ts +0 -179
- package/dist/process-recovery-eligibility.js +0 -174
- package/dist/process-recovery-native.d.ts +0 -161
- package/dist/process-recovery-native.js +0 -595
- package/dist/process-recovery-provenance.d.ts +0 -163
- package/dist/process-recovery-provenance.js +0 -292
- package/dist/process-recovery-services.d.ts +0 -56
- package/dist/process-recovery-services.js +0 -191
- package/dist/process-recovery-settlement.d.ts +0 -32
- package/dist/process-recovery-settlement.js +0 -133
- package/dist/process-recovery.d.ts +0 -41
- package/dist/process-recovery.js +0 -91
- package/dist/session-brief.d.ts +0 -8
- package/dist/session-brief.js +0 -24
- package/dist/session-cli.d.ts +0 -42
- package/dist/session-cli.js +0 -271
- package/dist/session-contract.d.ts +0 -183
- package/dist/session-contract.js +0 -122
- package/dist/session-remote.d.ts +0 -19
- package/dist/session-remote.js +0 -86
- package/dist/session-service.d.ts +0 -22
- package/dist/session-service.js +0 -157
- package/dist/team-cli.js +0 -692
package/dist/server/console.css
CHANGED
|
@@ -39,14 +39,14 @@
|
|
|
39
39
|
:root {
|
|
40
40
|
--background: var(--so-ground); --foreground: var(--so-ink); --card: var(--so-paper);
|
|
41
41
|
--muted: var(--so-raised); --muted-foreground: var(--so-muted); --border: var(--so-line); --input: var(--so-input-line);
|
|
42
|
-
--primary: var(--so-accent); --primary-foreground: var(--so-on-accent); --secondary: var(--so-raised);
|
|
43
|
-
--accent: var(--so-soft); --destructive: var(--so-danger); --destructive-
|
|
42
|
+
--primary: var(--so-accent); --primary-foreground: var(--so-on-accent); --secondary: var(--so-raised);
|
|
43
|
+
--accent: var(--so-soft); --destructive: var(--so-danger); --destructive-soft: var(--so-danger-soft);
|
|
44
44
|
--success: var(--so-success); --success-soft: var(--so-success-soft); --warning: var(--so-warning); --warning-soft: var(--so-warning-soft);
|
|
45
45
|
--running: var(--so-info); --running-soft: var(--so-info-soft); --ring: var(--so-signal);
|
|
46
46
|
/* The accent means one thing: a person is needed (approve, answer, decide). */
|
|
47
47
|
--brand: var(--so-attention); --brand-foreground: var(--so-on-attention); --brand-soft: var(--so-attention-soft);
|
|
48
48
|
--glass: var(--so-paper); --glass-strong: var(--so-paper); --glass-border: var(--so-line); --glass-highlight: transparent;
|
|
49
|
-
--
|
|
49
|
+
--user-message: var(--so-user-bubble);
|
|
50
50
|
--surface: var(--so-paper); --ok: var(--so-success); --danger: var(--so-danger); --fg-muted: var(--so-muted);
|
|
51
51
|
--shadow: none; --shadow-overlay: var(--so-shadow-overlay);
|
|
52
52
|
--radius: 0.625rem;
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
and a long press never selects a control's label. Text stays selectable. */
|
|
59
59
|
html { -webkit-tap-highlight-color: transparent; }
|
|
60
60
|
a, button, summary, [role=button], [role=tab] { touch-action: manipulation; }
|
|
61
|
-
button, [role=button], [role=tab], .task-context-chip, .
|
|
61
|
+
button, [role=button], [role=tab], .task-context-chip, .verdict-chip { -webkit-user-select: none; user-select: none; }
|
|
62
62
|
::selection { background: var(--so-selection); color: var(--so-ink); }
|
|
63
63
|
::placeholder { color: var(--muted-foreground); }
|
|
64
64
|
body {
|
|
@@ -73,23 +73,9 @@
|
|
|
73
73
|
/* Scrollbars belong to the theme, not the platform default. */
|
|
74
74
|
* { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
|
|
75
75
|
|
|
76
|
-
.topbar {
|
|
77
|
-
position: sticky; top: 0; z-index: 10;
|
|
78
|
-
border-bottom: 1px solid var(--border); background: var(--background);
|
|
79
|
-
}
|
|
80
|
-
.topbar-inner {
|
|
81
|
-
max-width: 44rem; margin-inline: auto; padding: 0 1.25rem; height: 3.25rem;
|
|
82
|
-
display: flex; align-items: center; gap: 1.25rem;
|
|
83
|
-
}
|
|
84
76
|
.brand { font-weight: 600; letter-spacing: -0.01em; color: var(--foreground); text-decoration: none;
|
|
85
77
|
display: flex; align-items: center; height: 100%; }
|
|
86
78
|
.brand .dot { color: var(--muted-foreground); }
|
|
87
|
-
.topbar nav { display: flex; gap: .25rem; margin-left: auto; height: 100%; }
|
|
88
|
-
.topbar nav a {
|
|
89
|
-
color: var(--muted-foreground); text-decoration: none; font-size: 0.8125rem; font-weight: 500;
|
|
90
|
-
display: flex; align-items: center; padding: 0 .625rem; transition: color .15s;
|
|
91
|
-
}
|
|
92
|
-
@media (hover: hover) and (pointer: fine) { .topbar nav a:hover { color: var(--foreground); } }
|
|
93
79
|
main { max-width: 44rem; margin-inline: auto; padding: 1.75rem 1.25rem 4rem; }
|
|
94
80
|
h1 { font-size: 1.25rem; font-weight: 600; letter-spacing: -0.02em; margin: 0 0 .25rem; line-height: 1.3; }
|
|
95
81
|
h1 .meta { font-weight: 400; letter-spacing: 0; }
|
|
@@ -118,13 +104,6 @@
|
|
|
118
104
|
/* Utility classes replacing the old inline style= attributes. */
|
|
119
105
|
.tight { margin-top: 0; }
|
|
120
106
|
.card > h2:first-child, .card > h3:first-child { margin-top: 0; }
|
|
121
|
-
.w-xs { width: 4.5rem; } .w-sm { width: 8rem; } .w-md { width: 12rem; } .w-lg { width: 14rem; }
|
|
122
|
-
.field-cap { width: 100%; max-width: 28rem; }
|
|
123
|
-
.field-cap-sm { width: 100%; max-width: 22rem; }
|
|
124
|
-
.field-cap-lg { width: 100%; max-width: 34rem; }
|
|
125
|
-
.prewrap { white-space: pre-wrap; }
|
|
126
|
-
.wrap-any { overflow-wrap: anywhere; }
|
|
127
|
-
.grab { cursor: grab; user-select: none; }
|
|
128
107
|
|
|
129
108
|
.palette {
|
|
130
109
|
position: fixed; top: 18vh; left: 50%; transform: translateX(-50%); width: min(32rem, 90vw);
|
|
@@ -298,12 +277,6 @@
|
|
|
298
277
|
main:has(.task-intake) { max-width: 68rem; }
|
|
299
278
|
.task-intake { width: min(100%, 50rem); margin: clamp(1rem, 5vh, 4rem) auto 0; }
|
|
300
279
|
.task-intake-hero { text-align: center; margin: 0 auto 1.35rem; max-width: 38rem; }
|
|
301
|
-
.task-intake-mark {
|
|
302
|
-
display: grid; place-items: center; width: 3rem; height: 3rem; margin: 0 auto .85rem;
|
|
303
|
-
border: 1px solid var(--border); border-radius: .75rem;
|
|
304
|
-
background: var(--card); box-shadow: var(--so-pill-shadow);
|
|
305
|
-
font: 600 .72rem/1 var(--font-mono); letter-spacing: -.05em;
|
|
306
|
-
}
|
|
307
280
|
.task-intake-hero h1 { margin: 0; font-size: clamp(1.65rem, 4vw, 2.2rem); letter-spacing: -.045em; }
|
|
308
281
|
.task-intake-hero p { margin: .45rem 0 0; color: var(--muted-foreground); }
|
|
309
282
|
.task-composer { padding: .75rem; border-radius: 1.45rem; box-shadow: var(--shadow-overlay); }
|
|
@@ -461,8 +434,6 @@
|
|
|
461
434
|
.cockpit-row-meta { display: block; color: var(--muted-foreground); font-size: .68rem; overflow-wrap: anywhere; }
|
|
462
435
|
.cockpit-why { display: block; color: var(--muted-foreground); font-size: .7rem; line-height: 1.35; overflow-wrap: anywhere; }
|
|
463
436
|
.refusal-back a { display: inline-flex; align-items: center; min-height: 44px; min-width: 44px; }
|
|
464
|
-
.cockpit-primary { margin: .85rem 0 1rem; }
|
|
465
|
-
.cockpit-primary .button-link { white-space: nowrap; }
|
|
466
437
|
.cockpit-detail { min-width: 0; }
|
|
467
438
|
.cockpit-head h1 { margin: .2rem 0 .55rem; color: var(--foreground); font-size: clamp(1.2rem, 2vw, 1.45rem); font-weight: 600; line-height: 1.3; letter-spacing: -.025em; overflow-wrap: anywhere; }
|
|
468
439
|
.cockpit-chips { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; margin: 0 0 .35rem; }
|
|
@@ -500,22 +471,6 @@
|
|
|
500
471
|
.cockpit-proof-group { margin: .65rem 0; border: 1px solid var(--glass-border); border-radius: calc(var(--radius) - 3px); background: color-mix(in srgb, var(--glass-strong) 62%, transparent); }
|
|
501
472
|
.cockpit-proof-group > summary { padding: .65rem .75rem; cursor: pointer; font-weight: 550; }
|
|
502
473
|
.cockpit-proof-group .criterion-matrix { padding: 0 .75rem .7rem; }
|
|
503
|
-
.cockpit-proof-summary { display: grid; gap: .25rem; margin: .15rem 0 .75rem; line-height: 1.45; }
|
|
504
|
-
.cockpit-proof-summary strong { font-size: .88rem; }
|
|
505
|
-
.cockpit-evidence-group { margin: .65rem 0 0; scroll-margin-top: 6rem; border: 1px solid var(--glass-border); border-radius: calc(var(--radius) - 3px); overflow: hidden; }
|
|
506
|
-
.cockpit-evidence-group > summary { display: flex; align-items: center; justify-content: space-between; gap: .75rem; padding: .75rem; cursor: pointer; list-style: none; font-weight: 550; }
|
|
507
|
-
.cockpit-evidence-group > summary::-webkit-details-marker { display: none; }
|
|
508
|
-
.cockpit-evidence-group > summary > span { flex: none; white-space: nowrap; }
|
|
509
|
-
.cockpit-evidence-group > summary small { min-width: 0; color: var(--muted-foreground); font-size: .7rem; font-weight: 400; text-align: right; }
|
|
510
|
-
.cockpit-evidence-group [data-primary-evidence] { scroll-margin-top: 6rem; }
|
|
511
|
-
.cockpit-evidence-body { padding: 0 .75rem .75rem; border-top: 1px solid var(--glass-border); }
|
|
512
|
-
.cockpit-accept { margin-top: .65rem; padding-top: .65rem; border-top: 1px solid var(--glass-border); }
|
|
513
|
-
.cockpit-accept > summary { cursor: pointer; font-size: .78rem; font-weight: 600; }
|
|
514
|
-
.cockpit-accept[open] > summary { margin-bottom: .55rem; }
|
|
515
|
-
.cockpit-accept p { margin: 0 0 .55rem; }
|
|
516
|
-
.cockpit-accept-form { display: flex; gap: .5rem; margin: 0; }
|
|
517
|
-
.cockpit-accept-form input { margin: 0; min-width: 10rem; }
|
|
518
|
-
.cockpit-accept-form button { flex: none; background: var(--primary); color: var(--primary-foreground); border-color: var(--primary); font-weight: 600; }
|
|
519
474
|
.diff-review {
|
|
520
475
|
overflow: hidden; margin: .8rem 0 .5rem; border: 1px solid var(--glass-border);
|
|
521
476
|
border-radius: var(--radius); background: color-mix(in srgb, var(--card) 82%, transparent);
|
|
@@ -757,7 +712,6 @@
|
|
|
757
712
|
margin: 0; color: var(--foreground); font-size: 1.0625rem; line-height: 1.35;
|
|
758
713
|
letter-spacing: -.015em;
|
|
759
714
|
}
|
|
760
|
-
.project-add-intro { margin: .25rem 0 0; max-width: 36rem; }
|
|
761
715
|
.project-add-actions {
|
|
762
716
|
display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
763
717
|
gap: .625rem; margin-top: 1rem;
|
|
@@ -822,7 +776,6 @@
|
|
|
822
776
|
.nav-group > summary .chevron { width: .875rem; height: .875rem; flex: none; transition: transform .15s; }
|
|
823
777
|
.nav-group[open] > summary .chevron { transform: rotate(180deg); }
|
|
824
778
|
.nav-group .nav-group-items { display: flex; flex-direction: column; gap: .125rem; margin: .125rem 0 .25rem; }
|
|
825
|
-
.side .nav-settings { margin-top: .375rem; }
|
|
826
779
|
.side nav a {
|
|
827
780
|
position: relative;
|
|
828
781
|
display: flex; align-items: center; gap: .625rem; padding: .4375rem .625rem; min-height: 2.125rem;
|
|
@@ -1051,15 +1004,6 @@
|
|
|
1051
1004
|
.task-control[data-task-control="paused"] .eyebrow { color: var(--destructive); }
|
|
1052
1005
|
.resume-ceremony .row { margin: .3rem 0; }
|
|
1053
1006
|
@media (max-width: 480px) { .task-control { align-items: stretch; } .task-control-form, .task-control-button { width: 100%; } .task-control-form .task-control-button { width: 100%; } }
|
|
1054
|
-
.review-attempts { margin: .55rem 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: .2rem; font-size: .8125rem; }
|
|
1055
|
-
.review-attempts li { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .45rem; min-width: 0; }
|
|
1056
|
-
.review-attempts .review-attempt-ordinal { font-weight: 600; }
|
|
1057
|
-
.review-attempts .meta { min-width: 0; overflow-wrap: anywhere; }
|
|
1058
|
-
.review-retry-actions { display: flex; align-items: center; flex-wrap: wrap; gap: .55rem; margin-top: .65rem; }
|
|
1059
|
-
.review-retry-actions form.inline { margin: 0; }
|
|
1060
|
-
.review-retry-button { width: auto; max-width: 100%; white-space: normal; }
|
|
1061
|
-
.review-retry-form .review-retry-button { background: var(--primary); color: var(--primary-foreground); border-color: var(--primary); font-weight: 600; }
|
|
1062
|
-
.review-retry-button[disabled] { opacity: .65; cursor: not-allowed; }
|
|
1063
1007
|
.proof-review-actions { display: flex; align-items: center; flex-wrap: wrap; gap: .55rem; margin: .65rem 0; }
|
|
1064
1008
|
.proof-review-actions > .button-link { flex: none; }
|
|
1065
1009
|
details.proof-exception { margin: 0; }
|
|
@@ -1113,9 +1057,6 @@
|
|
|
1113
1057
|
.approve-form .recap { margin: .125rem 0 .5rem; }
|
|
1114
1058
|
.approval-card { padding: 1.2rem 1.3rem; border-radius: calc(var(--radius) + 3px); }
|
|
1115
1059
|
.approval-card .ceremony-head { align-items: flex-start; padding-bottom: .85rem; border-bottom: 1px solid var(--glass-border); }
|
|
1116
|
-
.approval-title { display: grid; gap: .15rem; }
|
|
1117
|
-
.approval-kicker { color: var(--muted-foreground); font: 500 .66rem/1.3 var(--font-mono); letter-spacing: .06em; text-transform: uppercase; }
|
|
1118
|
-
.approval-title strong { font-size: 1.05rem; letter-spacing: -.02em; }
|
|
1119
1060
|
.approval-label { display: block; margin: .9rem 0 .2rem; color: var(--muted-foreground); font: 500 12px/1.4 var(--font-sans); }
|
|
1120
1061
|
.approval-label::first-letter, .planner-plan .eyebrow::first-letter { text-transform: uppercase; }
|
|
1121
1062
|
.planner-plan .eyebrow { font: 500 12px/1.4 var(--font-sans); letter-spacing: 0; text-transform: none; }
|
|
@@ -1124,7 +1065,6 @@
|
|
|
1124
1065
|
.approval-boundary { padding: .7rem .8rem; border: 1px solid var(--glass-border); border-radius: calc(var(--radius) - 3px); background: color-mix(in srgb, var(--muted) 45%, transparent); }
|
|
1125
1066
|
.approval-boundary .approval-label { margin: 0 0 .2rem; }
|
|
1126
1067
|
.approval-boundary p { margin: 0; color: var(--muted-foreground); font-size: .8rem; overflow-wrap: anywhere; }
|
|
1127
|
-
.approval-chips { display: flex; flex-wrap: wrap; gap: .4rem; margin: .8rem 0 .3rem; }
|
|
1128
1068
|
/* The filed contract (contract handoff, task 1): preserved, amended, or
|
|
1129
1069
|
drafted from nothing — the same panel on the task page, in the
|
|
1130
1070
|
ceremony, and on /next, so an amendment is never a surprise after the
|
|
@@ -1189,7 +1129,6 @@
|
|
|
1189
1129
|
.task-chat-agents-aside .agents-summary { font-size: .74rem; }
|
|
1190
1130
|
.task-chat-agents-aside .agents-badges { margin-top: .35rem; }
|
|
1191
1131
|
.task-chat-agents-aside .agents-roles { grid-template-columns: 1fr; }
|
|
1192
|
-
.approval-chip { padding: .25rem .6rem; border: 1px solid var(--glass-border); border-radius: 999px; color: var(--muted-foreground); background: var(--glass); font-size: .7rem; }
|
|
1193
1132
|
.approval-confirm { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .75rem; align-items: end; margin-top: .9rem; padding-top: .8rem; border-top: 1px solid var(--glass-border); }
|
|
1194
1133
|
.approval-confirm label { margin: 0; }
|
|
1195
1134
|
.approval-card .approval-confirm button { min-height: 44px; white-space: nowrap; }
|
|
@@ -1508,7 +1447,6 @@
|
|
|
1508
1447
|
.result-facts dd form { margin: .35rem 0 0; }
|
|
1509
1448
|
.result-stat { margin: .2rem 0 .4rem; }
|
|
1510
1449
|
.result-files { margin: .4rem 0 .6rem; }
|
|
1511
|
-
.result-label { display: block; margin: .5rem 0 .25rem; font: 600 .6875rem/1.3 var(--font-mono); color: var(--muted-foreground); letter-spacing: .06em; text-transform: uppercase; }
|
|
1512
1450
|
.result-verdict { align-items: center; }
|
|
1513
1451
|
.result-verdict > .meta { min-width: 0; overflow-wrap: anywhere; }
|
|
1514
1452
|
.result-request { margin-top: 1.1rem; padding-top: .9rem; border-top: 1px solid var(--border); }
|
|
@@ -1532,7 +1470,6 @@
|
|
|
1532
1470
|
.result-links a { font-weight: 550; }
|
|
1533
1471
|
.result-links a + a::before { content: "·"; margin-right: .5rem; color: var(--muted-foreground); font-weight: 400; }
|
|
1534
1472
|
.cockpit-detail .result-panel { margin: .85rem 0; }
|
|
1535
|
-
.cockpit-accept { margin-top: .75rem; }
|
|
1536
1473
|
/* The result beside the conversation (package 3): with room, two
|
|
1537
1474
|
columns and no second auxiliary panel; without it, the dedicated
|
|
1538
1475
|
result view with Back to chat and the conversation out of the way. */
|
|
@@ -1572,29 +1509,17 @@
|
|
|
1572
1509
|
toggle share one wrapping line; an opened disclosure is wider than
|
|
1573
1510
|
its summary, so it wraps onto its own full-width line by itself. */
|
|
1574
1511
|
.work-row-status { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .875rem; }
|
|
1575
|
-
.work-details, .work-details[open] { max-width: 100%; margin: 0; padding: 0; border: 0; background: none; border-radius: 0; }
|
|
1576
|
-
.work-details > summary {
|
|
1577
|
-
list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: .25rem;
|
|
1578
|
-
min-height: 2.25rem; padding: 0 .25rem; margin: 0 -.25rem; border-radius: .375rem;
|
|
1579
|
-
font-size: .8125rem; font-weight: 500; color: var(--muted-foreground);
|
|
1580
|
-
}
|
|
1581
|
-
.work-details > summary::-webkit-details-marker { display: none; }
|
|
1582
|
-
.work-details > summary::before { content: "▸"; }
|
|
1583
|
-
.work-details[open] > summary::before { content: "▾"; }
|
|
1584
|
-
@media (hover: hover) and (pointer: fine) { .work-details > summary:hover { color: var(--foreground); } }
|
|
1585
1512
|
.work-title { display: block; font-weight: 600; font-size: .9375rem; line-height: 1.35; color: var(--foreground); text-decoration: none; overflow-wrap: anywhere; }
|
|
1586
1513
|
@media (hover: hover) and (pointer: fine) { .work-title:hover { text-decoration: underline; } }
|
|
1587
1514
|
.work-meta { display: flex; flex-wrap: wrap; gap: .25rem .625rem; margin: .25rem 0 0; font-size: .75rem; color: var(--muted-foreground); }
|
|
1588
1515
|
.work-meta .mono { overflow-wrap: anywhere; }
|
|
1589
1516
|
.project-label { display: inline-block; padding: 0 .4rem; border: 1px solid var(--border); border-radius: 999px; font-size: .6875rem; line-height: 1.5; color: var(--foreground); }
|
|
1590
1517
|
.work-detail { margin: 0 0 .25rem; font-size: .8125rem; line-height: 1.45; color: var(--muted-foreground); overflow-wrap: anywhere; }
|
|
1591
|
-
.work-details .work-id { margin: 0 0 .25rem; }
|
|
1592
1518
|
.work-action { display: inline-flex; align-items: center; min-height: 44px; font-size: .8125rem; font-weight: 500; }
|
|
1593
1519
|
.work-empty { padding: 2rem 0 1rem; max-width: 34rem; }
|
|
1594
1520
|
.work-empty p { margin: 0 0 .75rem; color: var(--muted-foreground); line-height: 1.5; }
|
|
1595
1521
|
.work-empty .row { display: flex; align-items: center; gap: 1rem; }
|
|
1596
1522
|
.work-empty .row > a { display: inline-flex; align-items: center; min-height: 44px; }
|
|
1597
|
-
.work-bound { margin-top: .75rem; }
|
|
1598
1523
|
.status-line { display: inline-flex; align-items: center; gap: .45rem; min-width: 0; font-size: .875rem; font-weight: 600; color: var(--foreground); }
|
|
1599
1524
|
.status-line .status-label { min-width: 0; overflow-wrap: anywhere; }
|
|
1600
1525
|
.status-line .status-dot { flex: none; width: .5rem; height: .5rem; border-radius: 50%; background: var(--muted-foreground); }
|
|
@@ -1629,7 +1554,7 @@
|
|
|
1629
1554
|
.work-row { grid-template-columns: minmax(0, 1fr); gap: .125rem; padding: .625rem 0; }
|
|
1630
1555
|
.work-head { align-items: center; }
|
|
1631
1556
|
.work-head h1 { margin-bottom: 0; }
|
|
1632
|
-
.work-
|
|
1557
|
+
.work-action { min-height: 44px; }
|
|
1633
1558
|
/* The tools control sits at the head's right edge on every width, so
|
|
1634
1559
|
its menu keeps the desk's right-aligned anchor here too. A phone
|
|
1635
1560
|
override once re-anchored it at left: 0, which pushed the opened
|
|
@@ -1771,7 +1696,6 @@
|
|
|
1771
1696
|
/* Caution without a claim on the operator: quiet, not magenta. */
|
|
1772
1697
|
.dot-warn { background: var(--muted-foreground); }
|
|
1773
1698
|
.dot-off { background: var(--muted-foreground); opacity: .5; }
|
|
1774
|
-
.dot-bad { background: var(--destructive); }
|
|
1775
1699
|
.pulse { animation: pulse 2s ease-in-out infinite; }
|
|
1776
1700
|
.dot-ok.pulse { background: var(--running); }
|
|
1777
1701
|
@keyframes pulse { 50% { opacity: .35; } }
|
|
@@ -1811,7 +1735,6 @@
|
|
|
1811
1735
|
|
|
1812
1736
|
@media (max-width: 640px) {
|
|
1813
1737
|
button, form.option button { min-height: 2.75rem; }
|
|
1814
|
-
.topbar nav a { padding: 0 .5rem; }
|
|
1815
1738
|
}
|
|
1816
1739
|
|
|
1817
1740
|
/* The board: lanes as columns, the pipeline left to right. */
|
|
@@ -1935,23 +1858,6 @@
|
|
|
1935
1858
|
.control-room-head h1 { font-size: 1.375rem; margin-top: .08rem; }
|
|
1936
1859
|
.control-room-head .actions { display: flex; gap: .45rem; flex-wrap: wrap; justify-content: flex-end; }
|
|
1937
1860
|
.control-room-head .actions a { text-decoration: none; }
|
|
1938
|
-
.command-metrics {
|
|
1939
|
-
display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
1940
|
-
gap: .625rem; margin: .85rem 0 1.5rem;
|
|
1941
|
-
}
|
|
1942
|
-
.command-metric {
|
|
1943
|
-
border: 1px solid var(--border); border-radius: calc(var(--radius) - 2px); background: var(--card);
|
|
1944
|
-
padding: .8rem .9rem; min-width: 0;
|
|
1945
|
-
}
|
|
1946
|
-
.command-metric .value { display: block; margin-top: .25rem; font-size: 1.5rem; font-weight: 600; line-height: 1.15; font-variant-numeric: tabular-nums; font-family: var(--font-mono); }
|
|
1947
|
-
.command-metric .label { display: flex; align-items: center; gap: .4rem; font-weight: 500; font-size: .8125rem; }
|
|
1948
|
-
.command-metric .label::before {
|
|
1949
|
-
content: ""; width: .375rem; height: .375rem; border-radius: var(--so-radius-full);
|
|
1950
|
-
background: var(--muted-foreground); flex: none;
|
|
1951
|
-
}
|
|
1952
|
-
.command-metric .detail { display: block; color: var(--muted-foreground); font-size: .6875rem; margin-top: .18rem; }
|
|
1953
|
-
.command-metric.attention .label::before { background: var(--brand); }
|
|
1954
|
-
.command-metric.live .label::before { background: var(--running); }
|
|
1955
1861
|
.workspace-pulse { margin: .4rem 0 1.5rem; display: grid; grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr)); gap: .625rem; }
|
|
1956
1862
|
/* The workspace card: name and status word, four counts, the same counts
|
|
1957
1863
|
as a bar, and the one tap to its board. Neutral border always; the
|
|
@@ -1980,17 +1886,8 @@
|
|
|
1980
1886
|
.task-chat-context-head { display: flex; align-items: center; justify-content: space-between; gap: .65rem; }
|
|
1981
1887
|
.task-chat-context h2 { margin: .7rem 0 .25rem; color: var(--foreground); font-size: 1rem; line-height: 1.35; letter-spacing: -.025em; }
|
|
1982
1888
|
.task-chat-context > .meta { margin: 0; overflow-wrap: anywhere; font-size: .65rem; }
|
|
1983
|
-
.task-chat-status { display: grid; gap: .2rem; margin-top: .85rem; padding: .7rem; border-radius: calc(var(--radius) - 3px); background: var(--warning-soft); }
|
|
1984
|
-
.task-chat-status.ready { background: var(--running-soft); }
|
|
1985
|
-
.task-chat-status strong { font-size: .75rem; }
|
|
1986
|
-
.task-chat-status span { color: var(--muted-foreground); font-size: .68rem; line-height: 1.45; }
|
|
1987
|
-
.task-chat-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .4rem; margin: .65rem 0; }
|
|
1988
|
-
.task-chat-facts div { min-width: 0; padding: .45rem .5rem; border-radius: calc(var(--radius) - 5px); background: color-mix(in srgb, var(--muted) 58%, transparent); }
|
|
1989
|
-
.task-chat-facts dt { color: var(--muted-foreground); font: 400 .58rem/1.2 var(--font-mono); text-transform: uppercase; letter-spacing: .04em; }
|
|
1990
|
-
.task-chat-facts dd { margin: .15rem 0 0; font-size: .68rem; overflow-wrap: anywhere; }
|
|
1991
1889
|
.task-chat-overview-actions { display: grid; justify-items: start; gap: .55rem; margin-top: .75rem; }
|
|
1992
1890
|
.task-chat-overview-link { display: block; font-size: .72rem; text-decoration: none; }
|
|
1993
|
-
.task-chat-recovery-link { min-height: 2rem; padding-inline: .7rem; font-size: .7rem; }
|
|
1994
1891
|
#task-chat-live { display: grid; gap: 1rem; margin-bottom: 1.1rem; }
|
|
1995
1892
|
.task-journey {
|
|
1996
1893
|
position: relative; overflow: hidden; padding: 1rem 1.05rem;
|
|
@@ -1998,7 +1895,6 @@
|
|
|
1998
1895
|
background: var(--card);
|
|
1999
1896
|
}
|
|
2000
1897
|
.task-journey::after { content: ""; position: absolute; width: 9rem; height: 9rem; right: -4rem; top: -5rem; border-radius: 50%; background: color-mix(in srgb, var(--accent) 8%, transparent); filter: blur(12px); pointer-events: none; }
|
|
2001
|
-
.task-journey-head { position: relative; z-index: 1; display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
|
|
2002
1898
|
.task-journey h2 { margin: .2rem 0 0; font-size: 1rem; letter-spacing: -.025em; }
|
|
2003
1899
|
.task-journey > ol { position: relative; z-index: 1; display: grid; grid-template-columns: repeat(5,minmax(0,1fr)); gap: 0; margin: 1rem 0 .75rem; padding: 0; list-style: none; }
|
|
2004
1900
|
.task-journey > ol::before { content: ""; position: absolute; top: .7rem; left: 10%; right: 10%; height: 1px; background: var(--border); }
|
|
@@ -2026,8 +1922,6 @@
|
|
|
2026
1922
|
.task-control-copy { min-width: 0; overflow-wrap: anywhere; }
|
|
2027
1923
|
[data-primary-action] { max-width: 100%; }
|
|
2028
1924
|
|
|
2029
|
-
.task-live-build { display: flex; align-items: center; flex-wrap: wrap; gap: .3rem; margin: .75rem 0 0; font-size: .72rem; }
|
|
2030
|
-
.task-live-build .live-dot { width: .45rem; height: .45rem; border-radius: 50%; background: var(--success); box-shadow: 0 0 0 4px color-mix(in srgb,var(--success) 10%,transparent); }
|
|
2031
1925
|
.chat-action-card { padding: 0; overflow: hidden; }
|
|
2032
1926
|
.chat-action-card:not(details) { padding: 1rem 1.05rem; }
|
|
2033
1927
|
.chat-action-card > summary { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1rem 1.05rem; cursor: pointer; list-style: none; }
|
|
@@ -2036,9 +1930,6 @@
|
|
|
2036
1930
|
.chat-action-card > summary strong { font-size: .92rem; }
|
|
2037
1931
|
.chat-action-card > summary small { color: var(--muted-foreground); font-size: .68rem; font-weight: 400; }
|
|
2038
1932
|
.chat-action-card[open] > summary { border-bottom: 1px solid var(--border); }
|
|
2039
|
-
.chat-run-details { padding: .65rem .75rem; border: 1px solid var(--border); border-radius: calc(var(--radius) - 3px); background: color-mix(in srgb,var(--muted) 45%,transparent); }
|
|
2040
|
-
.chat-run-details > summary { color: var(--muted-foreground); cursor: pointer; font-size: .68rem; }
|
|
2041
|
-
.chat-run-details > .meta { margin-bottom: 0; }
|
|
2042
1933
|
.chat-decisions { display: grid; gap: .7rem; }
|
|
2043
1934
|
.chat-section-head { margin: .15rem .15rem 0; }
|
|
2044
1935
|
.chat-section-head h2 { margin: .2rem 0 0; font-size: 1rem; }
|
|
@@ -2484,9 +2375,6 @@
|
|
|
2484
2375
|
.workspace-bar .seg.building { background: var(--running); }
|
|
2485
2376
|
.workspace-bar .seg.waiting { background: var(--muted-foreground); }
|
|
2486
2377
|
.workspace-bar .seg.queued { background: color-mix(in srgb, var(--muted-foreground) 45%, transparent); }
|
|
2487
|
-
.attention-stack { display: grid; gap: .55rem; }
|
|
2488
|
-
.attention-stack .decide-card { margin: 0; }
|
|
2489
|
-
.attention-stack .q { display: flex; gap: .5rem; align-items: center; justify-content: space-between; }
|
|
2490
2378
|
.wb-rail-head {
|
|
2491
2379
|
display: flex; align-items: flex-end; justify-content: space-between; gap: .75rem;
|
|
2492
2380
|
padding: 0 .15rem .6rem; border-bottom: 1px solid var(--border);
|
|
@@ -2512,13 +2400,11 @@
|
|
|
2512
2400
|
@media (max-width: 720px) {
|
|
2513
2401
|
.control-room-head { display: block; }
|
|
2514
2402
|
.control-room-head .actions { justify-content: flex-start; margin-top: .75rem; }
|
|
2515
|
-
.command-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
2516
2403
|
.workspace-pulse { grid-template-columns: 1fr; }
|
|
2517
2404
|
.workspace-stats .pulse-stat { padding: .375rem .125rem; font-size: .625rem; letter-spacing: -.01em; }
|
|
2518
2405
|
.permission-toggle { grid-template-columns: 1fr; }
|
|
2519
2406
|
.task-intake { margin-top: .25rem; }
|
|
2520
2407
|
.task-intake-hero { text-align: left; margin-bottom: .9rem; }
|
|
2521
|
-
.task-intake-mark { display: none; }
|
|
2522
2408
|
.task-composer { margin-inline: 0; padding: .55rem; border-radius: 1.15rem; }
|
|
2523
2409
|
.task-prompt textarea { min-height: 7.25rem; padding: .75rem; font-size: 1rem; }
|
|
2524
2410
|
.task-composer-footer { flex-wrap: wrap; }
|
|
@@ -2534,8 +2420,6 @@
|
|
|
2534
2420
|
.agents-roles { grid-template-columns: 1fr; }
|
|
2535
2421
|
.agents-role-row { grid-template-columns: 1fr; }
|
|
2536
2422
|
.approval-card { padding: 1rem; }
|
|
2537
|
-
/* The orientation block says the wait on a phone; the kicker would say it twice. */
|
|
2538
|
-
.approval-card .approval-kicker { display: none; }
|
|
2539
2423
|
.approval-boundaries, .approval-confirm { grid-template-columns: 1fr; }
|
|
2540
2424
|
/* The approval stays IN FLOW on phones: the password field comes
|
|
2541
2425
|
first and the button follows it — never a sticky control floating
|
|
@@ -2570,20 +2454,10 @@
|
|
|
2570
2454
|
.queue-card p.row { padding: 0; border-bottom: none; }
|
|
2571
2455
|
.tracks { margin-top: 1.5rem; }
|
|
2572
2456
|
.tracks > .hint { margin-bottom: .75rem; }
|
|
2573
|
-
.track-row { margin-bottom: .6rem; }
|
|
2574
|
-
.track-row p { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
|
|
2575
|
-
.track-row p .right { margin-left: auto; }
|
|
2576
|
-
.track-row a { text-decoration: none; }
|
|
2577
|
-
@media (hover: hover) and (pointer: fine) { .track-row a:hover { text-decoration: underline; } }
|
|
2578
|
-
.track-strip { display: inline-flex; gap: .3rem; align-items: center; vertical-align: middle; }
|
|
2579
2457
|
.fire {
|
|
2580
2458
|
display: inline-block; width: .65rem; height: .65rem; border-radius: 50%;
|
|
2581
2459
|
background: var(--muted);
|
|
2582
2460
|
}
|
|
2583
|
-
.fire-ok { background: var(--success); }
|
|
2584
|
-
.fire-bad { background: var(--destructive); }
|
|
2585
|
-
.fire-live { background: var(--running); animation: pulse 1.6s ease-in-out infinite; }
|
|
2586
|
-
.fire-skip { background: transparent; border: 1.5px solid var(--muted); }
|
|
2587
2461
|
|
|
2588
2462
|
/* the phone: fingers, not cursors — tested at 320/390px */
|
|
2589
2463
|
input, select, textarea { font-size: 16px; }
|
|
@@ -2646,8 +2520,6 @@ button { min-height: 44px; }
|
|
|
2646
2520
|
.cockpit-disclosure { padding: 0; }
|
|
2647
2521
|
.cockpit-disclosure > summary { padding: .8rem; }
|
|
2648
2522
|
.cockpit-disclosure-body { padding: 0 .8rem .85rem; }
|
|
2649
|
-
.cockpit-accept-form { display: grid; }
|
|
2650
|
-
.cockpit-accept-form button { width: 100%; }
|
|
2651
2523
|
.diff-review { margin-inline: -.1rem; }
|
|
2652
2524
|
.diff-review-bar { padding-left: .7rem; }
|
|
2653
2525
|
.diff-file > summary { padding-inline: .7rem; }
|
package/dist/server/flows.js
CHANGED
|
@@ -26,7 +26,7 @@ import { keyStatus } from "../keys.js";
|
|
|
26
26
|
import { kitPageHtml, kitsGalleryHtml } from "../kits-ui.js";
|
|
27
27
|
import { addKitGithubTrigger, addKitSample, kitOf, setUpKit } from "../kits.js";
|
|
28
28
|
import { connectionsOf } from "../mcp-connect.js";
|
|
29
|
-
import { authorizedProject, projectName,
|
|
29
|
+
import { authorizedProject, projectName, } from "../project.js";
|
|
30
30
|
import { recipeAnswersFromForm, recipeDefinitionPreviewHtml, recipeEditorHtml, recipeFromForm, recipeLibraryHtml, recipeRunHtml, recipeScript, workflowPreviewHtml } from "../recipe-ui.js";
|
|
31
31
|
import { createWorkflowPreview, exportRecipe, findRecipe, importRecipe, launchWorkflow, prepareRecipeRun, RecipeError, savedRecipes, saveWorkflowRecipe, starterRecipes, workflowPreview } from "../recipes.js";
|
|
32
32
|
import { isAlive as runnerAlive } from "../runner.js";
|
|
@@ -43,7 +43,7 @@ import { redirect, respond, SAFETY, taskHref } from "./http.js";
|
|
|
43
43
|
import { html } from "../html.js";
|
|
44
44
|
import {} from "./session.js";
|
|
45
45
|
export function createFlowsHandlers(runtime) {
|
|
46
|
-
const { store, clock, sendScreen, chromeFor, consoleProjects, options, visible,
|
|
46
|
+
const { store, clock, sendScreen, chromeFor, consoleProjects, options, visible, liveCeiling, providerHome, toolHome, restricted, evidenceRoot, authenticateApprover, authenticateCredential, projectOf, unscopedMode, ceiling, authorizeMutation } = runtime;
|
|
47
47
|
// ---- reads ---------------------------------------------------------------
|
|
48
48
|
/** A gallery template's page (Flows → New → Use this): its questions, the preview of these answers, and Create. */
|
|
49
49
|
function sendGalleryUse(response, who, template, projects, repo, given, name, notice, said = null) {
|
package/dist/server/http.d.ts
CHANGED
|
@@ -245,6 +245,8 @@ export declare function goOutside(response: ServerResponse, to: string, words: s
|
|
|
245
245
|
path: string;
|
|
246
246
|
secure: boolean;
|
|
247
247
|
}): void;
|
|
248
|
+
/** A form's answer: back to `page` (which may carry its own query) saying `said` or `problem` words, then an anchor. */
|
|
249
|
+
export declare function sayTo(response: ServerResponse, page: string, anchor?: string): (key: "said" | "problem", words: string, at?: string) => void;
|
|
248
250
|
export declare function redirect(response: ServerResponse, to: string): void;
|
|
249
251
|
export declare const taskChatHref: (taskId: string) => string;
|
|
250
252
|
/** A project's own lead thread (v77). */
|
package/dist/server/http.js
CHANGED
|
@@ -115,6 +115,11 @@ export function goOutside(response, to, words, bind) {
|
|
|
115
115
|
"content-security-policy": "default-src 'none'; style-src 'unsafe-inline'; frame-ancestors 'none'; base-uri 'none'; form-action 'none'" });
|
|
116
116
|
response.end(htmlString(html `<!doctype html><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta http-equiv="refresh" content="0;url=${to}"><title>Toolroll</title>${HANDOFF_STYLE}<p>${words} <a href="${to}">Continue</a></p>`));
|
|
117
117
|
}
|
|
118
|
+
/** A form's answer: back to `page` (which may carry its own query) saying `said` or `problem` words, then an anchor. */
|
|
119
|
+
export function sayTo(response, page, anchor = "") {
|
|
120
|
+
const join = page.includes("?") ? "&" : "?";
|
|
121
|
+
return (key, words, at = anchor) => redirect(response, `${page}${join}${key}=${encodeURIComponent(words)}${at}`);
|
|
122
|
+
}
|
|
118
123
|
export function redirect(response, to) {
|
|
119
124
|
// Set as a header (not only in writeHead) so the answer can be read back after: a refused act's redirect names it.
|
|
120
125
|
response.setHeader("Location", to);
|
package/dist/server/pages.js
CHANGED
|
@@ -38,7 +38,7 @@ import { healthWords } from "../server-telemetry.js";
|
|
|
38
38
|
import { tally } from "../summary.js";
|
|
39
39
|
import { serveInstallAsset } from "./pages-assets.js";
|
|
40
40
|
import { healthz } from "./remote-hooks.js";
|
|
41
|
-
import {
|
|
41
|
+
import { refuse, regionScript, screen, settingsRows, WORKSPACE_STYLE, workToolRows } from "./chrome.js";
|
|
42
42
|
import { redirect, respond, safeReturn, SAFETY, taskHref } from "./http.js";
|
|
43
43
|
import { assignmentOf } from "../assignment.js";
|
|
44
44
|
import { assignmentTaskStatusOf } from "../assignment-presentation.js";
|
|
@@ -500,7 +500,7 @@ export function createPagesHandlers(runtime) {
|
|
|
500
500
|
return sendScreen(response, 200, screen("Agents", fallback, { chrome: chromeFor(project, "runs"), workspace: { view } }));
|
|
501
501
|
}
|
|
502
502
|
async function fleetPage(ctx) {
|
|
503
|
-
const { url,
|
|
503
|
+
const { url, response, project } = ctx;
|
|
504
504
|
// Cross-project by design: which agent is on which project is the
|
|
505
505
|
// question, so this screen is a survey — reads are still filtered
|
|
506
506
|
// through the ceiling before a card renders. No project needed.
|
|
@@ -9,9 +9,8 @@ import { projectName } from "../project.js";
|
|
|
9
9
|
import { requestLimitsHtml, tokenLimitWords } from "../request-budget-ui.js";
|
|
10
10
|
import { authenticateAccount } from "../scope.js";
|
|
11
11
|
import { SSO_CALLBACK } from "../sso-settings.js";
|
|
12
|
-
import { requestContext } from "./request-context.js";
|
|
13
12
|
import { personChip, refuse, screen } from "./chrome.js";
|
|
14
|
-
import { redirect, respond } from "./http.js";
|
|
13
|
+
import { redirect, respond, sayTo } from "./http.js";
|
|
15
14
|
/** people handlers, moved without changing their route bodies. */
|
|
16
15
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
17
16
|
import {} from "node:http";
|
|
@@ -40,7 +39,7 @@ export function sameVisitCheck(authTime, startedAt, now) {
|
|
|
40
39
|
return Math.min(Math.max(at, startedAt), now);
|
|
41
40
|
}
|
|
42
41
|
export function createPeopleHandlers(runtime) {
|
|
43
|
-
const {
|
|
42
|
+
const { joinBySource, ssoOffer, ssoVisits, ssoSettings, options, clock, ssoHandoffs, managedRepos, store, visible, admissionList, sendScreen, chromeFor, restricted, sessions, consoleProjects, authenticateApprover, authenticateCredential, bustBadge, projectOf, signInLinks, linkKey, fromThisComputer, recordSignIn, passwordAllowed, arrival, defaultProject, cookieSecure, consoleOrigin, providerFor, joinSourceOf, signInBudget, signInActor, minutesWords } = runtime;
|
|
44
43
|
// v101: Settings → Sessions & tokens: where you're signed in, and your API tokens. An instance operator can see everyone's.
|
|
45
44
|
async function sessionsPage(ctx) {
|
|
46
45
|
const { url, who, response, project } = ctx;
|
|
@@ -167,7 +166,7 @@ ${reauth(html `<label>Password <input type="password" name="token" autocomplete=
|
|
|
167
166
|
if (who.via !== "cookie")
|
|
168
167
|
return refuse(response, who, 403, "Sign in in a browser to manage sessions and tokens.", "/settings");
|
|
169
168
|
const operator = store.isInstanceOperator(who.name);
|
|
170
|
-
const back = (
|
|
169
|
+
const back = sayTo(response, `/settings/sessions${body.get("everyone") === "1" && operator ? "?everyone=1" : ""}`);
|
|
171
170
|
const action = body.get("action") ?? "";
|
|
172
171
|
if (action === "end-session") {
|
|
173
172
|
const target = store.webSessions(null).find(one => one.idHash === (body.get("session") ?? ""));
|
package/dist/server/remote.js
CHANGED
|
@@ -7,9 +7,7 @@ import { CodingWorkspace } from '../coding-workspace.js';
|
|
|
7
7
|
import { createMcpHttp } from "../mcp-http.js";
|
|
8
8
|
import { createOAuthHttp, resourceMetadataUrl } from "../mcp-oauth.js";
|
|
9
9
|
import { reproveRemote } from "../operate-remote.js";
|
|
10
|
-
import { rowVisible } from "../project.js";
|
|
11
10
|
import { RequestBudget, SourceAdmission } from "../request-budget.js";
|
|
12
|
-
import { createSessionRunner } from '../session-remote.js';
|
|
13
11
|
import {} from "../store.js";
|
|
14
12
|
import { handleTeamHttp, TEAM_PASSWORD_REVERIFY_MS } from '../team-http.js';
|
|
15
13
|
import { handleTeamsHttp } from "../teams.js";
|
|
@@ -17,7 +15,7 @@ import { flowHook, telegramHook } from "./remote-hooks.js";
|
|
|
17
15
|
import { respond } from "./http.js";
|
|
18
16
|
import {} from "./session.js";
|
|
19
17
|
export function createRemoteHandlers(runtime) {
|
|
20
|
-
const { identify, store, admitPasswordSource, admitBearer, allowedHost, team, teamBrowserReply, requestBudget, options,
|
|
18
|
+
const { identify, store, admitPasswordSource, admitBearer, allowedHost, team, teamBrowserReply, requestBudget, options, clock, evidenceRoot, consoleOrigin, managedRepos, joinSourceOf, ssoSettings, oauthTokenBudget, hookContext, teamsSourceBudget, teamsTenantBudget } = runtime;
|
|
21
19
|
/**
|
|
22
20
|
* The full principal a live `so_` API token stands for: its person and their generation, the token's own read/act
|
|
23
21
|
* scope, its project limit narrowed by the person's current access, and its id. Every route that accepts an API token
|
|
@@ -97,15 +95,12 @@ export function createRemoteHandlers(runtime) {
|
|
|
97
95
|
return who?.via === 'cookie' ? teamBrowserReply(reply, actor, who.session.csrf) : reply;
|
|
98
96
|
},
|
|
99
97
|
});
|
|
100
|
-
// D7: native session operations are remote commands too (`session …` over /api/cli), run by the session owner.
|
|
101
|
-
const sessionRunner = createSessionRunner({ store, workspace: coding, projects: codingProjects, projectAllowed: repo => rowVisible(liveCeiling(), repo), clock });
|
|
102
98
|
// Remote CLI: one live API token names the person; the shared command boundary decides everything else.
|
|
103
99
|
const cliEndpoint = (request, response) => handleCliHttp(request, response, {
|
|
104
100
|
admit: principal => requestBudget.admit(principal.tokenId, "api"),
|
|
105
101
|
authenticate: tokenPrincipalOf,
|
|
106
102
|
run: async () => options.cliRunner ?? (await import("../operate.js")).runOperateAs ?? null,
|
|
107
103
|
modeOf: options.cliModeOf,
|
|
108
|
-
session: sessionRunner,
|
|
109
104
|
store,
|
|
110
105
|
});
|
|
111
106
|
const mcpHttp = createMcpHttp({ store, clock, evidenceRoot, ...(options.requestBudgetClock === undefined ? {} : { requestBudgetClock: options.requestBudgetClock }), signedIn: request => identify(request, true, true) !== null, admit: person => requestBudget.admit(person.principal.tokenId, "mcp"),
|
|
@@ -142,9 +142,16 @@ export declare function leadPromptStarters(focus?: TaskChatFocus | null): Html;
|
|
|
142
142
|
export declare function chatHeading(copy: string, projectCount: number, showProjectToggle?: boolean): Html;
|
|
143
143
|
/** A deliberately small rich-text grammar for model copy. The reply is shaped first (the lead's voice, enforced:
|
|
144
144
|
* no headers, at most three bold anchors, labelled links, no internal ids unless `asked` wanted them); input is
|
|
145
|
-
* escaped before tags are introduced: bullets, numbered steps, bold, inline code
|
|
146
|
-
* presentation only—never executable HTML. */
|
|
145
|
+
* escaped before tags are introduced: bullets, numbered steps, bold, inline code, fenced code blocks and labelled
|
|
146
|
+
* http(s) links are presentation only—never executable HTML. */
|
|
147
147
|
export declare function renderChatText(raw: string, asked?: string): Html;
|
|
148
|
+
/** A line comment from the chat Workbench (src/browser/line-steer.tsx steerMessage): On "<file, as a JSON string>":<line>
|
|
149
|
+
* [ (removed line)] (run #<n>): <comment>, then a blank line and "> <the line>" (just ">" for a blank line, once the
|
|
150
|
+
* chat POST has trimmed the message), always last.
|
|
151
|
+
* The words the lead reads stay exactly as sent; the thread shows them in three parts: a small reference line, the quoted
|
|
152
|
+
* code as written, and the comment. Null for any other message, which keeps its own plain rendering. Everything is
|
|
153
|
+
* escaped by the html template. */
|
|
154
|
+
export declare function steerCommentHtml(text: string): Html | null;
|
|
148
155
|
export declare function chatActivity(activity: string | null): Html;
|
|
149
156
|
export declare const CHAT_UI_SCRIPT: string;
|
|
150
157
|
/** Provider, model, and limits under ONE disclosure (UI polish
|
|
@@ -33,7 +33,6 @@ import { chatMoney, oneLineOf, relativeAge, safePrUrl, screen, sentenceCase, str
|
|
|
33
33
|
import { chatResultHref, projectChatHref, taskChatHref, taskHref } from "./http.js";
|
|
34
34
|
import {} from "./render-pages.js";
|
|
35
35
|
import { completionReceiptCard } from "./render-results.js";
|
|
36
|
-
import {} from "./render-settings.js";
|
|
37
36
|
import { agentsAvailabilityHtml, agentsBadgesHtml, agentsStripHtml, agentsSummaryWords, agentsWhyHtml, approvalSheetHtml, checkProgressHtml, consentClosedHtml, consentDoorOf, decisionAnswerCard, dispatchHeadline, milestoneProgressHtml, planRevisionLedgerHtml, profileWords, sizeConsequence, taskControlDetailsHtml, taskStatusCard, taskViewSwitch } from "./render-tasks.js";
|
|
38
37
|
/** The installation fact that the lead was turned on by default, once (its value: the provider). */
|
|
39
38
|
export const LEAD_BY_DEFAULT_FACT = "lead-on-by-default";
|
|
@@ -260,8 +259,8 @@ export function chatHeading(copy, projectCount, showProjectToggle = true) {
|
|
|
260
259
|
}
|
|
261
260
|
/** A deliberately small rich-text grammar for model copy. The reply is shaped first (the lead's voice, enforced:
|
|
262
261
|
* no headers, at most three bold anchors, labelled links, no internal ids unless `asked` wanted them); input is
|
|
263
|
-
* escaped before tags are introduced: bullets, numbered steps, bold, inline code
|
|
264
|
-
* presentation only—never executable HTML. */
|
|
262
|
+
* escaped before tags are introduced: bullets, numbered steps, bold, inline code, fenced code blocks and labelled
|
|
263
|
+
* http(s) links are presentation only—never executable HTML. */
|
|
265
264
|
export function renderChatText(raw, asked) {
|
|
266
265
|
const inline = replyHtmlInline;
|
|
267
266
|
const text = shapeReply(raw, { appOrigin: requestContext.getStore()?.appOrigins ?? null, ...(asked === undefined ? {} : { asked }) });
|
|
@@ -281,7 +280,31 @@ export function renderChatText(raw, asked) {
|
|
|
281
280
|
out.push(list.tag === "ul" ? html `<ul>${list.items}</ul>` : html `<ol>${list.items}</ol>`);
|
|
282
281
|
list = null;
|
|
283
282
|
};
|
|
283
|
+
// A fenced block (shaping leaves it exactly as written) is shown as written: escaped, never parsed.
|
|
284
|
+
let fence = null;
|
|
285
|
+
const closeFence = () => {
|
|
286
|
+
const open = fence;
|
|
287
|
+
if (open === null)
|
|
288
|
+
return;
|
|
289
|
+
out.push(html `<pre class="chat-code"${open.lang === "" ? "" : html ` data-lang="${open.lang}"`}><code>${open.lines.join("\n")}</code></pre>`);
|
|
290
|
+
fence = null;
|
|
291
|
+
};
|
|
284
292
|
for (const line of lines) {
|
|
293
|
+
const open = fence;
|
|
294
|
+
if (open !== null) {
|
|
295
|
+
if (/^\s{0,3}```\s*$/.test(line))
|
|
296
|
+
closeFence();
|
|
297
|
+
else
|
|
298
|
+
open.lines.push(line);
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
const fenceMark = /^\s{0,3}```\s*([A-Za-z0-9_+.#-]{0,24})\s*$/.exec(line);
|
|
302
|
+
if (fenceMark !== null) {
|
|
303
|
+
flushParagraph();
|
|
304
|
+
closeList();
|
|
305
|
+
fence = { lang: fenceMark[1], lines: [] };
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
285
308
|
const bullet = /^\s*[-*]\s+(.+)$/.exec(line);
|
|
286
309
|
const numbered = /^\s*(\d{1,9})[.)]\s+(.+)$/.exec(line);
|
|
287
310
|
if (bullet !== null || numbered !== null) {
|
|
@@ -304,10 +327,35 @@ export function renderChatText(raw, asked) {
|
|
|
304
327
|
paragraph.push(line);
|
|
305
328
|
}
|
|
306
329
|
}
|
|
330
|
+
// An unclosed fence still shows its lines as code: the reply may have been cut.
|
|
307
331
|
flushParagraph();
|
|
308
332
|
closeList();
|
|
333
|
+
closeFence();
|
|
309
334
|
return html `<div class="chat-copy">${out}</div>`;
|
|
310
335
|
}
|
|
336
|
+
/** A line comment from the chat Workbench (src/browser/line-steer.tsx steerMessage): On "<file, as a JSON string>":<line>
|
|
337
|
+
* [ (removed line)] (run #<n>): <comment>, then a blank line and "> <the line>" (just ">" for a blank line, once the
|
|
338
|
+
* chat POST has trimmed the message), always last.
|
|
339
|
+
* The words the lead reads stay exactly as sent; the thread shows them in three parts: a small reference line, the quoted
|
|
340
|
+
* code as written, and the comment. Null for any other message, which keeps its own plain rendering. Everything is
|
|
341
|
+
* escaped by the html template. */
|
|
342
|
+
export function steerCommentHtml(text) {
|
|
343
|
+
const steer = /^On ("(?:[^"\\\n]|\\.){1,1200}"):(\d{1,9})( \(removed line\))? \(run #(\d{1,12})\): ([\s\S]+)\n\n>(?: ([^\n]*))?$/.exec(text);
|
|
344
|
+
if (steer === null)
|
|
345
|
+
return null;
|
|
346
|
+
// A blank line's quote ("> ") reaches the store as ">": the chat POST trims the message (src/server/chat.ts).
|
|
347
|
+
const [, quoted, line, removed, run, comment, code = ""] = steer;
|
|
348
|
+
let path;
|
|
349
|
+
try {
|
|
350
|
+
path = JSON.parse(quoted);
|
|
351
|
+
}
|
|
352
|
+
catch {
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
if (typeof path !== "string" || path === "" || /[\u0000-\u001f]/.test(path) || comment.trim() === "")
|
|
356
|
+
return null;
|
|
357
|
+
return html `<div class="chat-steer" data-steer-comment><p class="chat-steer-ref">${path}:${line}${removed === undefined ? "" : " · removed line"} · run #${run}</p>${code === "" ? "" : html `<pre class="chat-steer-code"><code>${code}</code></pre>`}<p class="chat-steer-note" style="white-space:pre-wrap">${comment}</p></div>`;
|
|
358
|
+
}
|
|
311
359
|
export function chatActivity(activity) {
|
|
312
360
|
return chatActivityDetailsHtml(activity);
|
|
313
361
|
}
|
|
@@ -351,8 +399,6 @@ export function chatLimitsHtml(facts) {
|
|
|
351
399
|
return html `<details class="chat-limits"><summary>Model & limits<span class="meta">${facts.subscription ? "membership" : facts.provider}</span></summary><div class="chat-budget">${rows}</div></details>`;
|
|
352
400
|
}
|
|
353
401
|
export function chatPage(chrome, data) {
|
|
354
|
-
const formFacts = { keyFacts: data.keyFacts, openrouterModels: data.openrouterModels, ...(data.liveModels === undefined ? {} : { liveModels: data.liveModels }), csrf: data.csrf,
|
|
355
|
-
returnTo: data.focusTask === null ? "/chat" : taskChatHref(data.focusTask.id) };
|
|
356
402
|
const parts = [
|
|
357
403
|
data.focusTask === null
|
|
358
404
|
? chatHeading("", data.projects.length, data.enabled.ok)
|
|
@@ -803,7 +849,7 @@ export function leadBrowserMessages(rows, back, target = { task: null, project:
|
|
|
803
849
|
return rows.messages.map(message => ({
|
|
804
850
|
id: message.id, role: message.role, text: message.text,
|
|
805
851
|
html: htmlString(message.role === 'operator'
|
|
806
|
-
? (() => { const queued = rows.queue?.get(message.id); return html `${message.text === "" ? "" : html `<p>${message.text}</p>`}${queued === undefined ? "" : queuedStateHtml(queued, back)}`; })()
|
|
852
|
+
? (() => { const queued = rows.queue?.get(message.id); return html `${message.text === "" ? "" : steerCommentHtml(message.text) ?? html `<p>${message.text}</p>`}${queued === undefined ? "" : queuedStateHtml(queued, back)}`; })()
|
|
807
853
|
: html `${renderChatText(message.text, askedBy.get(message.id))}${asked(message.turn)}`),
|
|
808
854
|
activity: message.activity, createdAt: message.createdAt,
|
|
809
855
|
...(() => {
|
|
@@ -882,7 +928,7 @@ export function leadThreadHtml(data) {
|
|
|
882
928
|
asked = message.text;
|
|
883
929
|
// A message that waits its turn (the lead queue) says so, with Remove while it still waits — as in the React thread.
|
|
884
930
|
const queued = data.queue?.get(message.id);
|
|
885
|
-
thread.push(html `<div class="msg op" data-message-role="operator" data-key="m${message.id}">${message.text === "" ? "" : html `<p style="white-space:pre-wrap">${message.text}</p>`}${queued === undefined ? "" : queuedStateHtml(queued, returnTo)}</div>`);
|
|
931
|
+
thread.push(html `<div class="msg op" data-message-role="operator" data-key="m${message.id}">${message.text === "" ? "" : steerCommentHtml(message.text) ?? html `<p style="white-space:pre-wrap">${message.text}</p>`}${queued === undefined ? "" : queuedStateHtml(queued, returnTo)}</div>`);
|
|
886
932
|
continue;
|
|
887
933
|
}
|
|
888
934
|
const cards = message.turn === null ? [] : (byTurn.get(message.turn) ?? []);
|