heyquilt 0.3.116 → 0.3.118
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/RELEASES.md +17 -0
- package/package.json +1 -1
- package/src/account.js +3 -3
- package/src/ai-vm.js +26 -2
- package/src/api/memory-store.js +2 -2
- package/src/api/routes/ai-vm.js +70 -4
- package/src/api/server.js +4 -4
- package/src/api/supabase-store.js +3 -3
- package/src/autowork.js +54 -6
- package/src/hooks.js +9 -4
- package/src/integrations.js +6 -4
- package/src/quilts/AGENTS.md +1 -0
- package/src/quilts/CLAUDE.md +1 -0
- package/src/quilts/tools.js +0 -2
- package/src/relay-ai-vm.js +5 -3
- package/src/runner.js +3 -2
- package/src/session.js +16 -4
- package/src/setup.js +9 -4
- package/src/ui/app.css +162 -31
- package/src/ui/cloud-ai.js +371 -153
- package/src/ui/home.js +29 -16
- package/src/ui/session.js +12 -1
- package/src/ui-server.js +21 -4
package/src/session.js
CHANGED
|
@@ -391,6 +391,9 @@ export class Session extends EventEmitter {
|
|
|
391
391
|
// A person's cloud AI: its pass names its person, and it is one of their AI sessions.
|
|
392
392
|
const aiOf = kind === 'agent' && typeof p.of === 'string' && p.of && typeof p.ofName === 'string' && p.ofName.trim() ? p.ofName.trim() : null
|
|
393
393
|
if (name === this.name && kind === this.kind && aiOf === this.aiOf) return
|
|
394
|
+
// An agent renamed while connected (a cloud AI its person renamed) keeps the name this connection
|
|
395
|
+
// joined with: the relay drops a presence under another. It takes the new one when it joins again.
|
|
396
|
+
if (this.conn && this.conn.connected && this.kind === 'agent' && kind === 'agent' && aiOf === this.aiOf && name !== this.name) return
|
|
394
397
|
this.name = name
|
|
395
398
|
this.kind = kind
|
|
396
399
|
this.aiOf = aiOf
|
|
@@ -6275,9 +6278,18 @@ export class Session extends EventEmitter {
|
|
|
6275
6278
|
/** Whether a name the history gives is this person's: theirs, one of their AI sessions', or their cloud AI's. */
|
|
6276
6279
|
ownName (name) {
|
|
6277
6280
|
if (this.isMine(name)) return true
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
+
return !this.aiOf && this.myCloudAiNames().has(name)
|
|
6282
|
+
}
|
|
6283
|
+
|
|
6284
|
+
/**
|
|
6285
|
+
* The names this person's cloud AI has had here ("Juniper", or "<me>'s AI"): seen in the room,
|
|
6286
|
+
* and remembered while it sleeps, so what is written to it stays theirs to read.
|
|
6287
|
+
*/
|
|
6288
|
+
myCloudAiNames () {
|
|
6289
|
+
this.cloudNames ||= new Set()
|
|
6290
|
+
if (this.aiOf || !this.conn || !this.conn.awareness) return this.cloudNames
|
|
6291
|
+
for (const [id, st] of this.conn.awareness.getStates()) if (id !== this.doc.clientID && isCloudAi(st) && st.aiOf === this.name && typeof st.name === 'string') this.cloudNames.add(st.name)
|
|
6292
|
+
return this.cloudNames
|
|
6281
6293
|
}
|
|
6282
6294
|
|
|
6283
6295
|
/**
|
|
@@ -6909,7 +6921,7 @@ export class Session extends EventEmitter {
|
|
|
6909
6921
|
/** Whether a message is meant for me: a well-formed one that is public, mine, or addressed to me. */
|
|
6910
6922
|
canSee (msg) {
|
|
6911
6923
|
// A person also sees what is written to and by their cloud AI ("<me>'s AI"): it is theirs.
|
|
6912
|
-
const mineOrMyAi = (n) => this.isMine(n) || (this.kind !== 'agent' && n === aiName(this.name))
|
|
6924
|
+
const mineOrMyAi = (n) => this.isMine(n) || (this.kind !== 'agent' && (n === aiName(this.name) || this.myCloudAiNames().has(n)))
|
|
6913
6925
|
return validMessage(msg) && (!msg.to || mineOrMyAi(msg.to) || mineOrMyAi(msg.by))
|
|
6914
6926
|
}
|
|
6915
6927
|
|
package/src/setup.js
CHANGED
|
@@ -133,9 +133,11 @@ export const HOOKS_FILE = '.claude/settings.local.json'
|
|
|
133
133
|
|
|
134
134
|
/**
|
|
135
135
|
* Puts Quilt's hooks into the project's .claude/settings.local.json, replacing earlier
|
|
136
|
-
* Quilt entries and leaving other hooks and settings alone.
|
|
136
|
+
* Quilt entries and leaving other hooks and settings alone. `stop` (an agent of its own) adds the
|
|
137
|
+
* hook as the AI finishes a turn; without it, a Quilt one left there is taken out (hooks.js
|
|
138
|
+
* hookSettings). Returns true when the file changed.
|
|
137
139
|
*/
|
|
138
|
-
export function installHooks (root) {
|
|
140
|
+
export function installHooks (root, { stop = false } = {}) {
|
|
139
141
|
const file = path.join(root, HOOKS_FILE)
|
|
140
142
|
let prev = ''
|
|
141
143
|
try { prev = fs.readFileSync(file, 'utf8') } catch {}
|
|
@@ -144,11 +146,14 @@ export function installHooks (root) {
|
|
|
144
146
|
if (typeof json !== 'object' || Array.isArray(json)) json = {}
|
|
145
147
|
const hooks = (json.hooks && typeof json.hooks === 'object' && !Array.isArray(json.hooks)) ? json.hooks : {}
|
|
146
148
|
const ours = isQuiltHook
|
|
147
|
-
|
|
149
|
+
const ourEvents = hookSettings(undefined, { stop })
|
|
150
|
+
if (!stop) ourEvents.Stop = []
|
|
151
|
+
for (const [event, entries] of Object.entries(ourEvents)) {
|
|
148
152
|
const kept = (Array.isArray(hooks[event]) ? hooks[event] : [])
|
|
149
153
|
.map((e) => (e && Array.isArray(e.hooks) ? { ...e, hooks: e.hooks.filter((h) => !ours(h)) } : e))
|
|
150
154
|
.filter((e) => e && (!Array.isArray(e.hooks) || e.hooks.length))
|
|
151
|
-
hooks[event] = [...kept, ...entries]
|
|
155
|
+
if (kept.length || entries.length) hooks[event] = [...kept, ...entries]
|
|
156
|
+
else delete hooks[event]
|
|
152
157
|
}
|
|
153
158
|
json.hooks = hooks
|
|
154
159
|
const text = JSON.stringify(json, null, 2) + '\n'
|
package/src/ui/app.css
CHANGED
|
@@ -2417,21 +2417,14 @@ details.mw + .cp-commit, .mw-head + .cp-commit { margin-top: 8px; }
|
|
|
2417
2417
|
.theme-switch button.on, .choice-card:has(input:checked) { background: var(--panel); }
|
|
2418
2418
|
}
|
|
2419
2419
|
|
|
2420
|
-
/* ---------- Settings →
|
|
2420
|
+
/* ---------- Settings → Agents: your cloud AI (cloud-ai.js) ---------- */
|
|
2421
|
+
/* Before setup an invite card; setting it up takes over the Settings panel (the pop-up's right side, or
|
|
2422
|
+
the page's tab panel) with its own header, steps and footer; set up, its card with what it does. */
|
|
2421
2423
|
/* The later .pill rule makes pills inline-block, which hides their dot: this one keeps the first rule's shape. */
|
|
2422
2424
|
.pill.cai-pill { flex: none; white-space: nowrap; display: inline-flex; align-items: center; gap: 6px; height: 24px; padding: 0 10px; font-size: 12px; letter-spacing: 0; vertical-align: middle; background: var(--panel-2); border: 1px solid var(--border); }
|
|
2423
2425
|
.cai-pill .dot { flex: none; }
|
|
2424
|
-
.cloud-ai .sec-intro .cai-pill { margin-left: auto; }
|
|
2425
|
-
.cai-body { display: grid; gap: 14px; }
|
|
2426
|
-
.cai-body > p { margin: 0; }
|
|
2427
|
-
.cai-body .error { margin: 0; }
|
|
2428
2426
|
.pill.bad { color: var(--bad); } .pill.bad .dot { background: var(--bad); }
|
|
2429
2427
|
.pill.sleep { color: var(--edit); } .pill.sleep .dot { background: var(--edit); }
|
|
2430
|
-
.cai-tools { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
|
|
2431
|
-
.cai-tool { display: grid; gap: 6px; justify-items: center; align-content: start; padding: 16px 12px 12px; border: 1px solid var(--border-strong); border-radius: var(--radius); background: var(--panel); text-align: center; }
|
|
2432
|
-
.cai-tool b { font-weight: 600; }
|
|
2433
|
-
.cai-tool .hint { font-size: 12px; }
|
|
2434
|
-
.cai-tool .btn { width: 100%; margin-top: 6px; }
|
|
2435
2428
|
.cai-logo { width: 34px; height: 34px; border-radius: 8px; display: grid; place-items: center; background: var(--panel-2); border: 1px solid var(--border); }
|
|
2436
2429
|
.cai-logo .tool-mark { width: 20px; height: 20px; }
|
|
2437
2430
|
.cai-two { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
|
|
@@ -2447,30 +2440,166 @@ details.mw + .cp-commit, .mw-head + .cp-commit { margin-top: 8px; }
|
|
|
2447
2440
|
.cai-code { font-family: var(--mono); font-size: 26px; letter-spacing: .12em; text-align: center; padding: 10px; border-radius: var(--radius); background: var(--panel-2); border: 1px dashed var(--border-strong); user-select: all; }
|
|
2448
2441
|
.cai-link { font-family: var(--mono); font-size: 12px; color: var(--edit); overflow-wrap: anywhere; padding: 8px 10px; border-radius: 4px; background: var(--panel-2); user-select: all; }
|
|
2449
2442
|
.cai-paste .input:disabled, .cai-paste .btn:disabled { opacity: .55; }
|
|
2450
|
-
.cai-who { display: flex; align-items: center; gap: 12px; }
|
|
2451
|
-
.cai-who .grow { flex: 1; min-width: 0; display: grid; }
|
|
2452
|
-
.cai-who .grow b { font-weight: 600; }
|
|
2453
|
-
.cai-sessions { display: grid; gap: 6px; }
|
|
2454
|
-
.cai-sess { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 4px; background: var(--panel-2); font-size: 13px; }
|
|
2455
|
-
.cai-sess .grow { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2456
|
-
.cai-kv { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
|
|
2457
|
-
.cai-kv > div { padding: 10px 12px; border-radius: var(--radius); background: var(--panel-2); min-width: 0; }
|
|
2458
|
-
.cai-kv b { display: block; font-size: 18px; font-weight: 600; }
|
|
2459
|
-
.cai-kv span { font-size: 12px; color: var(--muted); }
|
|
2460
|
-
.cai-meter { height: 8px; border-radius: 999px; background: var(--panel-2); overflow: hidden; }
|
|
2461
|
-
.cai-meter i { display: block; height: 100%; background: var(--ok); border-radius: 999px; }
|
|
2462
|
-
.cai-meter.over i { background: var(--warn); }
|
|
2463
|
-
.cai-sep { border: 0; border-top: 1px dashed var(--border); margin: 0; }
|
|
2464
|
-
.cai-form { display: grid; gap: 14px; }
|
|
2465
|
-
.cai-form > .field { margin-bottom: 0; }
|
|
2466
2443
|
.cai-confirm { display: grid; gap: 10px; padding: 12px; border-radius: var(--radius); border: 1px dashed color-mix(in srgb, var(--bad) 55%, var(--border)); background: color-mix(in srgb, var(--bad) 6%, var(--panel)); }
|
|
2467
2444
|
.cai-confirm p { margin: 0; font-size: 13px; }
|
|
2445
|
+
.cloud-ai .sec-intro .cai-pill { margin-left: auto; }
|
|
2446
|
+
|
|
2447
|
+
/* before setup: the invite (stitched patch, three facts that stack when the card is narrow) */
|
|
2448
|
+
.settings-sec.cloud-ai:has(> .ai-invite) { padding: 0; }
|
|
2449
|
+
.ai-invite { container-type: inline-size; display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 22px; align-items: center; padding: 26px 26px 24px; }
|
|
2450
|
+
.ai-patch { width: 76px; height: 76px; border-radius: 16px; display: grid; place-items: center; position: relative; color: var(--muted); background: repeating-linear-gradient(45deg, transparent 0 7px, color-mix(in srgb, var(--text) 4%, transparent) 7px 8px), var(--panel-2); }
|
|
2451
|
+
.ai-patch::after { content: ""; position: absolute; inset: 6px; border: 1.5px dashed var(--border-strong); border-radius: 11px; }
|
|
2452
|
+
.ai-patch svg { width: 26px; height: 26px; }
|
|
2453
|
+
.ai-invite h2 { margin: 0 0 4px; font-size: 18px; letter-spacing: -0.015em; }
|
|
2454
|
+
.ai-invite p { margin: 0; color: var(--muted); font-size: 13.5px; }
|
|
2455
|
+
.ai-invite > .error { grid-column: 1 / -1; }
|
|
2456
|
+
.ai-facts { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
|
|
2457
|
+
.ai-fact { display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 10px; align-items: start; padding: 14px 16px; background: var(--panel); }
|
|
2458
|
+
.ai-fact + .ai-fact { border-left: 1px solid var(--border); }
|
|
2459
|
+
.ai-fact i, .ai-row > i { display: grid; place-items: center; background: var(--panel-2); color: var(--text); font-style: normal; }
|
|
2460
|
+
.ai-fact i { width: 28px; height: 28px; border-radius: 8px; }
|
|
2461
|
+
.ai-fact i svg, .ai-row > i svg { width: 16px; height: 16px; }
|
|
2462
|
+
.ai-fact b { display: block; font-size: 13px; font-weight: 600; }
|
|
2463
|
+
.ai-fact span { font-size: 12px; color: var(--muted); line-height: 1.45; }
|
|
2464
|
+
.ai-invite-foot { grid-column: 1 / -1; display: flex; align-items: center; gap: 14px; }
|
|
2465
|
+
.ai-invite-foot .grow { flex: 1; color: var(--muted); font-size: 12.5px; }
|
|
2466
|
+
@container (max-width: 620px) {
|
|
2467
|
+
.ai-facts { grid-template-columns: minmax(0, 1fr); }
|
|
2468
|
+
.ai-fact { align-items: center; padding: 11px 14px; }
|
|
2469
|
+
.ai-fact + .ai-fact { border-left: 0; border-top: 1px solid var(--border); }
|
|
2470
|
+
.ai-fact b { display: inline; margin-right: 6px; }
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
/* the setup: header (back, title, step count, step bar), body, footer */
|
|
2474
|
+
.ai-flow-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
|
|
2475
|
+
.ai-flow-head .back { display: inline-flex; align-items: center; gap: 6px; font: inherit; font-size: 13px; color: var(--muted); background: none; border: 0; padding: 4px 6px; margin-left: -6px; border-radius: 6px; cursor: pointer; }
|
|
2476
|
+
.ai-flow-head .back:hover { color: var(--text); background: color-mix(in srgb, var(--text) 6%, transparent); }
|
|
2477
|
+
.ai-flow-head .back svg { width: 14px; height: 14px; }
|
|
2478
|
+
.ai-flow-head .sep { width: 1px; height: 16px; background: var(--border-strong); flex: none; }
|
|
2479
|
+
.ai-flow-head h4 { margin: 0; font-size: 15px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2480
|
+
.ai-flow-head .count { margin-left: auto; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
2481
|
+
.ss-main.ai-flow .ai-flow-head .count { margin-right: 34px; }
|
|
2482
|
+
.ai-steps { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; margin: 14px 0 0; padding: 0; list-style: none; }
|
|
2483
|
+
.ai-steps li { display: grid; gap: 7px; font-size: 12px; color: var(--faint); min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
2484
|
+
.ai-steps li::before { content: ""; height: 3px; border-radius: 3px; background: var(--border); }
|
|
2485
|
+
.ai-steps li.done { color: var(--muted); }
|
|
2486
|
+
.ai-steps li.done::before { background: var(--text); opacity: .55; }
|
|
2487
|
+
.ai-steps li.now { color: var(--text); font-weight: 600; }
|
|
2488
|
+
.ai-steps li.now::before { background: var(--accent); }
|
|
2489
|
+
.ss-main.ai-flow #settings-body { padding: 0; }
|
|
2490
|
+
.ai-flow-body { display: grid; gap: 26px; padding: 26px 28px 28px; align-content: start; }
|
|
2491
|
+
.ai-flow-foot { flex: none; display: flex; align-items: center; gap: 12px; padding: 14px 24px; border-top: 1px solid var(--border); background: var(--canvas); }
|
|
2492
|
+
.ai-flow-foot .grow { flex: 1; min-width: 0; font-size: 12.5px; color: var(--muted); }
|
|
2493
|
+
.ai-flow-foot .grow .error { margin: 0; }
|
|
2494
|
+
.ai-flow-foot .btn.primary { min-width: 132px; }
|
|
2495
|
+
.ai-page-flow { border: 1px solid var(--border); border-radius: 14px; background: var(--canvas); }
|
|
2496
|
+
.ai-page-flow > .ss-head { padding: 18px 24px 14px; }
|
|
2497
|
+
.ai-page-flow > .ai-flow-foot { border-radius: 0 0 14px 14px; }
|
|
2498
|
+
|
|
2499
|
+
/* the AI as people will see it, filling in as it is set up */
|
|
2500
|
+
.ai-card { display: flex; align-items: center; gap: 16px; padding: 18px 20px; border-radius: 12px; border: 1px solid var(--border); background: var(--panel); box-shadow: var(--shadow); min-width: 0; }
|
|
2501
|
+
.ai-card .avatar { width: 56px; height: 56px; font-size: 22px; box-shadow: 0 0 0 4px var(--panel), 0 0 0 5px var(--border); }
|
|
2502
|
+
.ai-card .who { flex: 1; min-width: 0; display: grid; gap: 3px; }
|
|
2503
|
+
.ai-card .name { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; min-width: 0; }
|
|
2504
|
+
.ai-card .name b { font-size: 20px; font-weight: 650; letter-spacing: -0.015em; overflow-wrap: anywhere; }
|
|
2505
|
+
.ai-tag { font-size: 11.5px; font-weight: 600; color: var(--muted); background: var(--panel-2); border: 1px solid var(--border); border-radius: 999px; padding: 1px 9px; white-space: nowrap; }
|
|
2506
|
+
.ai-card .sub { font-size: 13px; color: var(--muted); }
|
|
2507
|
+
.ai-card .sub.now { color: var(--text); margin-top: 4px; }
|
|
2508
|
+
.ai-card .at { font-family: var(--mono); font-size: 12px; color: var(--accent); }
|
|
2509
|
+
.ai-card.compact { padding: 12px 16px; gap: 12px; box-shadow: none; }
|
|
2510
|
+
.ai-card.compact .avatar { width: 38px; height: 38px; font-size: 15px; box-shadow: none; }
|
|
2511
|
+
.ai-card.compact .who { grid-template-columns: auto minmax(0, 1fr); align-items: baseline; column-gap: 14px; }
|
|
2512
|
+
.ai-card.compact .name { flex-wrap: nowrap; }
|
|
2513
|
+
.ai-card.compact .name b { font-size: 16px; }
|
|
2514
|
+
.ai-card.compact .sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
2515
|
+
|
|
2516
|
+
/* a question */
|
|
2517
|
+
.ai-q { display: grid; gap: 16px; min-width: 0; }
|
|
2518
|
+
.ai-q > header h3 { margin: 0 0 4px; font-size: 19px; letter-spacing: -0.015em; }
|
|
2519
|
+
.ai-q > header p { margin: 0; color: var(--muted); font-size: 13.5px; }
|
|
2520
|
+
.ai-sub { font-size: 11.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--faint); margin-bottom: -6px; }
|
|
2521
|
+
.ai-q .input.ai-name { font-size: 22px; font-weight: 600; letter-spacing: -0.01em; padding: 12px 14px; }
|
|
2522
|
+
.ai-chips { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
2523
|
+
.ai-chip { font: inherit; font-size: 13px; padding: 6px 13px; border-radius: 999px; border: 1px solid var(--border-strong); background: var(--panel); color: var(--text); cursor: pointer; }
|
|
2524
|
+
.ai-chip:hover { border-color: var(--text); }
|
|
2525
|
+
.ai-chip.on { background: var(--text); color: var(--bg); border-color: var(--text); }
|
|
2526
|
+
.ai-colors { display: flex; flex-wrap: wrap; gap: 10px; }
|
|
2527
|
+
.ai-color { width: 34px; height: 34px; border-radius: 50%; border: 0; padding: 0; cursor: pointer; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .15); }
|
|
2528
|
+
.ai-color.on { box-shadow: 0 0 0 3px var(--canvas), 0 0 0 5px var(--text); }
|
|
2529
|
+
.ai-color:focus-visible, .ai-chip:focus-visible, .ai-tool:focus-visible, .ai-switch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
2530
|
+
.ai-tools { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
|
|
2531
|
+
.ai-tool { position: relative; display: grid; gap: 10px; justify-items: start; padding: 18px 18px 16px; border-radius: 12px; border: 1px solid var(--border-strong); background: var(--panel); cursor: pointer; text-align: left; font: inherit; color: var(--text); min-width: 0; }
|
|
2532
|
+
.ai-tool:hover { border-color: var(--text); }
|
|
2533
|
+
.ai-tool .cai-logo { width: 42px; height: 42px; border-radius: 10px; }
|
|
2534
|
+
.ai-tool .cai-logo .tool-mark { width: 22px; height: 22px; }
|
|
2535
|
+
.ai-tool b { font-size: 15px; font-weight: 600; }
|
|
2536
|
+
.ai-tool .hint { font-size: 12.5px; margin-top: -6px; }
|
|
2537
|
+
.ai-tool .tick { position: absolute; top: 14px; right: 14px; width: 20px; height: 20px; border-radius: 50%; border: 1.5px solid var(--border-strong); display: grid; place-items: center; color: var(--bg); }
|
|
2538
|
+
.ai-tool .tick svg { width: 12px; height: 12px; }
|
|
2539
|
+
.ai-tool.on { border-color: var(--text); box-shadow: inset 0 0 0 1px var(--text); }
|
|
2540
|
+
.ai-tool.on .tick { background: var(--text); border-color: var(--text); }
|
|
2541
|
+
.ai-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
|
|
2542
|
+
.ai-pair .field, .ai-q .field.ai-rules { margin: 0; }
|
|
2543
|
+
|
|
2544
|
+
/* what it does: a grouped list (setup and the card) */
|
|
2545
|
+
.ai-list { border: 1px solid var(--border); border-radius: 12px; background: var(--panel); overflow: hidden; }
|
|
2546
|
+
.ai-row { display: grid; grid-template-columns: 34px minmax(0, 1fr) auto; gap: 14px; align-items: center; padding: 15px 18px; }
|
|
2547
|
+
.ai-row + .ai-row { border-top: 1px solid var(--border); }
|
|
2548
|
+
.ai-row > i { width: 34px; height: 34px; border-radius: 9px; }
|
|
2549
|
+
.ai-row b { display: block; font-size: 13.5px; font-weight: 600; }
|
|
2550
|
+
.ai-row .hint { display: block; font-size: 12.5px; line-height: 1.45; }
|
|
2551
|
+
.ai-row.wide { grid-template-columns: 34px minmax(0, 1fr); }
|
|
2552
|
+
.ai-row.wide .ctl { grid-column: 2; }
|
|
2553
|
+
.ai-row.wide .seg { width: 100%; }
|
|
2554
|
+
.ai-always { font-size: 12px; font-weight: 600; color: var(--ok); background: color-mix(in srgb, var(--ok) 13%, transparent); border-radius: 999px; padding: 3px 10px; white-space: nowrap; }
|
|
2555
|
+
.ai-switch { position: relative; width: 40px; height: 24px; border-radius: 999px; background: var(--border-strong); border: 0; padding: 0; flex: none; cursor: pointer; }
|
|
2556
|
+
.ai-switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: var(--panel); box-shadow: 0 1px 2px rgba(0, 0, 0, .25); transition: transform .15s; }
|
|
2557
|
+
.ai-switch.on { background: var(--ok); }
|
|
2558
|
+
.ai-switch.on::after { transform: translateX(16px); }
|
|
2559
|
+
|
|
2560
|
+
/* sessions */
|
|
2561
|
+
.ai-sess { display: grid; grid-template-columns: 20px minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 13px 18px; cursor: pointer; }
|
|
2562
|
+
.ai-sess + .ai-sess { border-top: 1px solid var(--border); }
|
|
2563
|
+
.ai-sess.off { cursor: default; }
|
|
2564
|
+
.ai-sess.off b, .ai-sess.off .hint { opacity: .75; }
|
|
2565
|
+
.ai-sess input { width: 17px; height: 17px; margin: 0; accent-color: var(--text); }
|
|
2566
|
+
.ai-sess b { display: block; font-size: 13.5px; font-weight: 600; }
|
|
2567
|
+
.ai-sess .hint { font-size: 12.5px; }
|
|
2568
|
+
.ai-sess.static { grid-template-columns: 8px minmax(0, 1fr) auto; cursor: default; padding: 11px 18px; }
|
|
2569
|
+
.ai-on { width: 8px; height: 8px; border-radius: 50%; background: var(--ok); }
|
|
2570
|
+
.ai-faces { display: flex; }
|
|
2571
|
+
.ai-faces .avatar { width: 24px; height: 24px; font-size: 10px; background: var(--border-strong); color: var(--text); box-shadow: 0 0 0 2px var(--panel); }
|
|
2572
|
+
.ai-faces .avatar + .avatar { margin-left: -6px; }
|
|
2573
|
+
|
|
2574
|
+
/* the sign-in, and what was chosen */
|
|
2575
|
+
.ai-signin { display: grid; gap: 16px; padding: 20px; border: 1px solid var(--border); border-radius: 12px; background: var(--panel); }
|
|
2576
|
+
.ai-signin-again { display: flex; }
|
|
2577
|
+
.ai-review { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); border: 1px solid var(--border); border-radius: 12px; background: var(--panel); overflow: hidden; }
|
|
2578
|
+
.ai-review > div { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 10px; padding: 13px 18px; min-width: 0; }
|
|
2579
|
+
.ai-review > div:nth-child(odd) { border-right: 1px solid var(--border); }
|
|
2580
|
+
.ai-review > div:nth-child(n+3) { border-top: 1px solid var(--border); }
|
|
2581
|
+
.ai-review span { font-size: 11.5px; color: var(--faint); text-transform: uppercase; letter-spacing: .05em; font-weight: 600; }
|
|
2582
|
+
.ai-review b { grid-column: 1; font-size: 13.5px; font-weight: 500; }
|
|
2583
|
+
.ai-change { grid-row: 1 / span 2; grid-column: 2; align-self: center; font: inherit; font-size: 12.5px; color: var(--muted); background: none; border: 0; padding: 2px 4px; text-decoration: underline; cursor: pointer; }
|
|
2584
|
+
.ai-change:hover { color: var(--text); }
|
|
2585
|
+
|
|
2586
|
+
/* set up: its card */
|
|
2587
|
+
.ai-run { display: grid; gap: 18px; }
|
|
2588
|
+
.ai-run > p, .ai-run .error { margin: 0; }
|
|
2589
|
+
.ai-asleep { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-radius: 10px; background: var(--panel-2); }
|
|
2590
|
+
.ai-asleep .hint { flex: 1; }
|
|
2591
|
+
.ai-meters { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
|
|
2592
|
+
.ai-meters > div { padding: 12px 16px; background: var(--panel); display: grid; gap: 2px; min-width: 0; }
|
|
2593
|
+
.ai-meters > div + div { border-left: 1px solid var(--border); }
|
|
2594
|
+
.ai-meters b { font-size: 18px; font-weight: 650; font-variant-numeric: tabular-nums; }
|
|
2595
|
+
.ai-meters span { font-size: 12px; color: var(--muted); }
|
|
2468
2596
|
@media (max-width: 640px) {
|
|
2469
|
-
.
|
|
2470
|
-
.
|
|
2471
|
-
.
|
|
2472
|
-
.
|
|
2473
|
-
.
|
|
2597
|
+
.ai-tools, .ai-pair, .ai-review, .cai-two { grid-template-columns: minmax(0, 1fr); }
|
|
2598
|
+
.ai-review > div:nth-child(odd) { border-right: 0; }
|
|
2599
|
+
.ai-review > div + div { border-top: 1px solid var(--border); }
|
|
2600
|
+
.ai-steps li { font-size: 0; gap: 0; }
|
|
2601
|
+
.ai-flow-body { padding: 18px 16px 20px; }
|
|
2602
|
+
.ai-invite { grid-template-columns: minmax(0, 1fr); }
|
|
2474
2603
|
}
|
|
2475
2604
|
|
|
2476
2605
|
/* Sandbox keys: an agent's Keys table (sandbox-keys.js, mockup option A), opened from its card in Settings › Agents. */
|
|
@@ -2748,3 +2877,5 @@ body.has-asks .ws { height: calc(100vh - var(--update-bar, 0px) - var(--asks-bar
|
|
|
2748
2877
|
.task-nopickup-x { margin-left: 2px; opacity: .55; font-weight: 700; }
|
|
2749
2878
|
.task-nopickup:hover .task-nopickup-x, .task-nopickup:focus-visible .task-nopickup-x { opacity: 1; }
|
|
2750
2879
|
.task-nopickup:hover, .task-nopickup:focus-visible { background: color-mix(in srgb, var(--warn) 20%, transparent); outline: none; }
|
|
2880
|
+
/* A cloud AI's own name in chat, then whose AI it is ("Juniper Daniel's AI"). */
|
|
2881
|
+
.msg .head .ai-tag { font-size: 10.5px; padding: 0 7px; }
|