@bivy/bivy 0.20.9-staging.3 → 0.20.9-staging.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -5
- package/bin/bivy.mjs +13 -56
- package/bin/cli-commands.mjs +2 -4
- package/bin/guides/talk-to-the-user.md +13 -24
- package/dist/agent-instructions.js +18 -14
- package/dist/apps/remote-preview.js +3 -0
- package/dist/apps/service.js +6 -1
- package/dist/apps/styles.css +67 -102
- package/dist/automation-reseal.js +30 -0
- package/dist/device-registry.js +27 -0
- package/dist/ephemeral-teardown.js +11 -1
- package/dist/exec.js +4 -1
- package/dist/harness/checkpoint.js +0 -0
- package/dist/runtime/model-catalog.js +16 -0
- package/dist/runtime/tool-call-map.js +1 -1
- package/dist/runtime/tool-trace.js +1 -1
- package/dist/server.js +73 -62
- package/dist/session/event-log.js +98 -41
- package/dist/session/inline-image-fetch.js +24 -33
- package/dist/session/message-components.js +429 -0
- package/dist/session/run-terminal.js +9 -7
- package/dist/session/session-tokens.js +1 -1
- package/dist/session/transcript-persistence.js +135 -10
- package/package.json +4 -4
- package/web/assets/AutomationsView-gbs-ep1i.js +51 -0
- package/web/assets/{ChangesCard-DXjxLEst.js → ChangesCard-CgK5QOLe.js} +3 -3
- package/web/assets/LibraryView-Bg5d4ThT.js +2 -0
- package/web/assets/{ProviderConnect-B2hZMuSZ.js → ProviderConnect-Y4994tEn.js} +1 -1
- package/web/assets/SessionList-Cs_3duRM.js +1 -0
- package/web/assets/Settings-OqGxSHw6.js +10 -0
- package/web/assets/{Sheet-C-R7BpHA.js → Sheet-DrALxQ86.js} +1 -1
- package/web/assets/{Terminal-s-bwzQA8.js → Terminal-cuOdvAep.js} +1 -1
- package/web/assets/{VoiceSettings-BekZp6jH.js → VoiceSettings-1hBtZtEH.js} +1 -1
- package/web/assets/{abnfDiagram-VCTEODGH-DhkySh1W.js → abnfDiagram-VCTEODGH-Cu7kjltw.js} +1 -1
- package/web/assets/arc-BNLueWOY.js +1 -0
- package/web/assets/architecture-7GRP2DOG-DVcA26wE.js +1 -0
- package/web/assets/{architectureDiagram-5GKGNRK7-B6YZgexE.js → architectureDiagram-5GKGNRK7-CdDHhYu6.js} +1 -1
- package/web/assets/{blockDiagram-I7D4REHJ-CWfczmzB.js → blockDiagram-I7D4REHJ-OwUc5uZF.js} +1 -1
- package/web/assets/{c4Diagram-7LVT6UL2-DBiwqaqH.js → c4Diagram-7LVT6UL2-CZ4H4vp1.js} +1 -1
- package/web/assets/channel-Bs6VKos2.js +1 -0
- package/web/assets/{chunk-4HAMMTFA-CZjUt8ep.js → chunk-4HAMMTFA-CcPONDa2.js} +1 -1
- package/web/assets/chunk-75Z2AOVW-BnAQasK8.js +2 -0
- package/web/assets/{chunk-DU6HZSFF-CHGL1NRh.js → chunk-DU6HZSFF-B2nWFPfo.js} +15 -15
- package/web/assets/chunk-F27PBJKO-B9SGusmO.js +1 -0
- package/web/assets/{chunk-GMAD6QVW-WXyfwEM4.js → chunk-GMAD6QVW-KEsMhKRw.js} +1 -1
- package/web/assets/{chunk-GVQU2GXP-B8UNdfp9.js → chunk-GVQU2GXP-DErg9Byu.js} +1 -1
- package/web/assets/{chunk-IMKFNOWR-BG5qIjIb.js → chunk-IMKFNOWR-DE16j-co.js} +1 -1
- package/web/assets/{chunk-L3NEJ4N5-D-oR2QmC.js → chunk-L3NEJ4N5-CdJCd1PC.js} +1 -1
- package/web/assets/{chunk-OSK3NFVY-jMhFN6yh.js → chunk-OSK3NFVY-unQ_QDO6.js} +2 -2
- package/web/assets/{chunk-P2QGCYS3-0lzCtZiI.js → chunk-P2QGCYS3-CxzGiRaF.js} +1 -1
- package/web/assets/{chunk-POPQ4Y6H-BvOJSdVX.js → chunk-POPQ4Y6H-DVq_ld9s.js} +1 -1
- package/web/assets/{chunk-PWAF6VOD-CtZVUGm9.js → chunk-PWAF6VOD-D-1iOFy0.js} +1 -1
- package/web/assets/{chunk-SHT3W25Y-C4ZLKBsF.js → chunk-SHT3W25Y-XCNJ3hEM.js} +1 -1
- package/web/assets/{chunk-SVP7TREG-CeXFjEeT.js → chunk-SVP7TREG-BTlTcuf7.js} +1 -1
- package/web/assets/{chunk-TICWLB2K-Bbs2_VrR.js → chunk-TICWLB2K-BDvyVo0o.js} +1 -1
- package/web/assets/chunk-XXDRQBXY-CjF14Z7v.js +1 -0
- package/web/assets/classDiagram-ZZMXUADV-mYgzdlHM.js +1 -0
- package/web/assets/classDiagram-v2-VYDZK3BY-mYgzdlHM.js +1 -0
- package/web/assets/colors-Cg5Vh3br.js +1 -0
- package/web/assets/{cose-bilkent-JH36ORCC-BIqBF2fY.js → cose-bilkent-JH36ORCC-CEUD3V3W.js} +1 -1
- package/web/assets/{cynefin-OW5HDTMX-C2hkVrsd.js → cynefin-OW5HDTMX-BwEg8WHP.js} +1 -1
- package/web/assets/cynefinDiagram-5FMLGOSQ-D4BMkVZ5.js +62 -0
- package/web/assets/{dagre-GXQ25YYZ-Cntbvh3d.js → dagre-GXQ25YYZ-CLFcSYPz.js} +1 -1
- package/web/assets/{defaultLocale-BFoDCU3G.js → defaultLocale-CNPGWpMu.js} +1 -1
- package/web/assets/{diagram-S7CK7UJ4-DzSmCqdG.js → diagram-S7CK7UJ4-DskfG6OO.js} +1 -1
- package/web/assets/diagram-UQ7AKVKN-CLfCWFib.js +41 -0
- package/web/assets/{diagram-VSXAHHWV-KNhID9By.js → diagram-VSXAHHWV-DZGXIgTB.js} +1 -1
- package/web/assets/diagram-VX7I27RA-CJZDlnxU.js +24 -0
- package/web/assets/diagram-Z3DM3KII-C2xMX2PJ.js +24 -0
- package/web/assets/dist-kYfyPZP9.js +1 -0
- package/web/assets/{ebnfDiagram-PWID7BFC-Op76kV6m.js → ebnfDiagram-PWID7BFC-CGtieAai.js} +1 -1
- package/web/assets/embed-BXV41wg7.js +201 -0
- package/web/assets/{erDiagram-RLTQ6QDP-BhslbiA0.js → erDiagram-RLTQ6QDP-DJZUby9w.js} +1 -1
- package/web/assets/eventmodeling-NTZA5JFV-D8ULSBhn.js +1 -0
- package/web/assets/flowDiagram-HODETNUW-BsmxdUzM.js +1 -0
- package/web/assets/ganttDiagram-EL5Y4UJY-BRH3unPE.js +292 -0
- package/web/assets/{gitGraph-4MIJSDKK-DXYutwGi.js → gitGraph-4MIJSDKK-BtjrQMIw.js} +1 -1
- package/web/assets/gitGraphDiagram-WWUBYQGX-jMdg80Ov.js +106 -0
- package/web/assets/{index-QZ00qaDb.js → index-C7RpJ756.js} +2 -2
- package/web/assets/index-DtEJd4mp.css +1 -0
- package/web/assets/{info-A6RAGUB7-CqqtawTw.js → info-A6RAGUB7-BaKu5_rT.js} +1 -1
- package/web/assets/infoDiagram-27XIBGKW-sWsXFMfE.js +2 -0
- package/web/assets/init-ZlXS9mIS.js +1 -0
- package/web/assets/{ishikawaDiagram-5VMMS53U-CWCrZmgU.js → ishikawaDiagram-5VMMS53U-DM_pB7OI.js} +1 -1
- package/web/assets/{journeyDiagram-3NMN7TZE-CCNprc0j.js → journeyDiagram-3NMN7TZE-DrTYbsug.js} +1 -1
- package/web/assets/{kanban-definition-UXKFOSKX-DhrHf7Wi.js → kanban-definition-UXKFOSKX-DQsAOYV0.js} +1 -1
- package/web/assets/linear-CeYXFQza.js +1 -0
- package/web/assets/{mermaid-parser.core-Ci2knVhk.js → mermaid-parser.core-Z-pCgTdy.js} +3 -3
- package/web/assets/{mermaid.core-BH-NC80l.js → mermaid.core-NP5S0Kz5.js} +6 -6
- package/web/assets/{mindmap-definition-YA3MSWOX-DhBlMHRQ.js → mindmap-definition-YA3MSWOX-DfPPF4lC.js} +1 -1
- package/web/assets/mount-Ge5TnRI2.js +36 -0
- package/web/assets/ordinal-BdBDtYTt.js +1 -0
- package/web/assets/{packet-AYTQ26CC-Cya3_Zkp.js → packet-AYTQ26CC-oRUu4UOk.js} +1 -1
- package/web/assets/{pegDiagram-XKGWAZYB-D0xWILcg.js → pegDiagram-XKGWAZYB-CqQPDwah.js} +1 -1
- package/web/assets/{pie-WAS4IAKB-ChVSjn4Q.js → pie-WAS4IAKB-DaBU-bFv.js} +1 -1
- package/web/assets/{pieDiagram-E7YTZNPT-wnTcfYll.js → pieDiagram-E7YTZNPT-GCMFMvUW.js} +2 -2
- package/web/assets/{quadrantDiagram-AXDQQJYC-Bxarivu1.js → quadrantDiagram-AXDQQJYC-i0SAZxHb.js} +1 -1
- package/web/assets/{radar-RG4KPBEZ-SrDcXd7Y.js → radar-RG4KPBEZ-DN12zbe9.js} +1 -1
- package/web/assets/{railroad-74A4TZTK-BBS1E8ym.js → railroad-74A4TZTK-BSGtWcA8.js} +1 -1
- package/web/assets/railroad-abnf-HS5TGJTU-DWAtDzt4.js +1 -0
- package/web/assets/railroad-ebnf-LZEXJU2U-ClLwllwK.js +1 -0
- package/web/assets/railroad-peg-WCYAUIDC-oT90tK0O.js +1 -0
- package/web/assets/{railroadDiagram-O6MQD6OU-qkhso-Lf.js → railroadDiagram-O6MQD6OU-e5Sdmws9.js} +1 -1
- package/web/assets/range-EplFIxc7.js +1 -0
- package/web/assets/{requirementDiagram-BXWQKSXE-DxgG6o06.js → requirementDiagram-BXWQKSXE-D0Dm95ua.js} +1 -1
- package/web/assets/{sankeyDiagram-P5KCCOFB-DjA3HS_S.js → sankeyDiagram-P5KCCOFB-D1w-6Ds5.js} +1 -1
- package/web/assets/{sequenceDiagram-WJ2MYXX4-Ct4L-7gL.js → sequenceDiagram-WJ2MYXX4-Dy4XJ-Pj.js} +3 -3
- package/web/assets/{settingsRoute-Dg0Hlv-E.js → settingsRoute-yGnTbjHU.js} +1 -1
- package/web/assets/src-CFHfg5gg.js +1 -0
- package/web/assets/stateDiagram-D77RDMKH-Dr1eI_sW.js +1 -0
- package/web/assets/stateDiagram-v2-MP3YSRHH-DlPkWaca.js +1 -0
- package/web/assets/step-BDqHAzds.js +1 -0
- package/web/assets/{swimlanes-42K2YHIH-CeYPO5Gf.js → swimlanes-42K2YHIH-CU4zEyNx.js} +1 -1
- package/web/assets/swimlanesDiagram-VR7AAH4N-BEVzbpvq.js +8 -0
- package/web/assets/time-Dzw-YSCF.js +1 -0
- package/web/assets/{timeline-definition-24CTP7MA-DDlYmyUb.js → timeline-definition-24CTP7MA-DMXMVpap.js} +1 -1
- package/web/assets/{treeView-Q6P3EWNA-BC9T9k65.js → treeView-Q6P3EWNA-DppDmgmx.js} +1 -1
- package/web/assets/treemap-BfjIY-m6.js +1 -0
- package/web/assets/{treemap-WGGIJYW6-Pho14fih.js → treemap-WGGIJYW6-D0M8t6Vl.js} +1 -1
- package/web/assets/useStore-BdqzpGk2.js +16 -0
- package/web/assets/{vennDiagram-4TSXK5OY-B2ua-DuO.js → vennDiagram-4TSXK5OY-DpgoR5R5.js} +1 -1
- package/web/assets/{wardley-WFR3VGLG-k9ON3mH7.js → wardley-WFR3VGLG-Dala8bda.js} +1 -1
- package/web/assets/{wardleyDiagram-VM6X3IG4-DYN4uK8-.js → wardleyDiagram-VM6X3IG4-Dmb16yFT.js} +1 -1
- package/web/assets/{xychartDiagram-S5SC5T6Z-CkhCfM7v.js → xychartDiagram-S5SC5T6Z-C617DPo9.js} +3 -3
- package/web/index.html +2 -2
- package/web/sw.js +1 -1
- package/dist/ephemeral-exec.js +0 -108
- package/dist/session/suggestions.js +0 -17
- package/web/assets/AutomationsView-B3IlMZMF.js +0 -51
- package/web/assets/LibraryView-DehJ6l7n.js +0 -2
- package/web/assets/Settings-DCAYOtjP.js +0 -10
- package/web/assets/arc-Pry-7G1_.js +0 -1
- package/web/assets/architecture-7GRP2DOG-CdWO14QC.js +0 -1
- package/web/assets/array-BifhSqXX.js +0 -1
- package/web/assets/channel-laHd0Jat.js +0 -1
- package/web/assets/chunk-75Z2AOVW-C8z-duh4.js +0 -2
- package/web/assets/chunk-F27PBJKO-vZCWYOo_.js +0 -1
- package/web/assets/chunk-XXDRQBXY-DqAYeljN.js +0 -1
- package/web/assets/classDiagram-ZZMXUADV-C4JnGfpM.js +0 -1
- package/web/assets/classDiagram-v2-VYDZK3BY-C4JnGfpM.js +0 -1
- package/web/assets/cynefinDiagram-5FMLGOSQ-BP2eGjBA.js +0 -62
- package/web/assets/diagram-UQ7AKVKN-BWYA-Rqm.js +0 -41
- package/web/assets/diagram-VX7I27RA-BD2YiSg9.js +0 -24
- package/web/assets/diagram-Z3DM3KII-CziybeZ0.js +0 -24
- package/web/assets/dist-v5Q1xZ2K.js +0 -1
- package/web/assets/eventmodeling-NTZA5JFV-ZZkYEG3i.js +0 -1
- package/web/assets/flowDiagram-HODETNUW-CdXVJEqz.js +0 -1
- package/web/assets/ganttDiagram-EL5Y4UJY-BmEZoYvR.js +0 -292
- package/web/assets/gitGraphDiagram-WWUBYQGX-jNAGg6N6.js +0 -106
- package/web/assets/index-D76QD5dl.css +0 -1
- package/web/assets/infoDiagram-27XIBGKW-CCvmyFCz.js +0 -2
- package/web/assets/init-C-OQMol4.js +0 -1
- package/web/assets/line-C9815hsz.js +0 -1
- package/web/assets/linear-SzVmGSw4.js +0 -1
- package/web/assets/mount-BkxTsONG.js +0 -33
- package/web/assets/ordinal-BDEzSJ7C.js +0 -1
- package/web/assets/path-fybaL0A-.js +0 -1
- package/web/assets/railroad-abnf-HS5TGJTU-DrUDHVSL.js +0 -1
- package/web/assets/railroad-ebnf-LZEXJU2U-pBCkrJwp.js +0 -1
- package/web/assets/railroad-peg-WCYAUIDC-DPW7i1VT.js +0 -1
- package/web/assets/src-B6xuSHsQ.js +0 -1
- package/web/assets/stateDiagram-D77RDMKH-DFQ4MMB4.js +0 -1
- package/web/assets/stateDiagram-v2-MP3YSRHH-BbqkM72i.js +0 -1
- package/web/assets/swimlanesDiagram-VR7AAH4N-BQC7deJv.js +0 -8
- package/web/assets/useStore-DcLTLjj8.js +0 -29
package/README.md
CHANGED
|
@@ -285,10 +285,9 @@ Every session gets the `bivy` CLI, so any agent with a shell can talk back
|
|
|
285
285
|
through the app, not only agents with their own built-in tools:
|
|
286
286
|
|
|
287
287
|
```bash
|
|
288
|
-
bivy notify
|
|
288
|
+
bivy notify # push to your phone so you come back
|
|
289
289
|
bivy ask "Ship to staging?" --option Yes --option No # waits for your answer
|
|
290
290
|
bivy attach report.png --caption "Before/after" # show a file in the chat
|
|
291
|
-
bivy suggest "Add a dark theme to settings" # a next task you start in one tap
|
|
292
291
|
bivy context --json # session, workspace, machine, apps
|
|
293
292
|
```
|
|
294
293
|
|
|
@@ -527,6 +526,8 @@ use, modify, and self-host it under that license. If users interact with your
|
|
|
527
526
|
modified version over a network, section 13 requires you to offer its
|
|
528
527
|
corresponding source. See [LICENSE](LICENSE).
|
|
529
528
|
|
|
530
|
-
Bivy Cloud is the hosted operation of that stack
|
|
531
|
-
separate private
|
|
532
|
-
|
|
529
|
+
Bivy Cloud is the hosted operation of that stack. Its plans, billing and
|
|
530
|
+
managed-compute operations live in a separate private service behind Core's
|
|
531
|
+
deployment extension. Contributions are made under the
|
|
532
|
+
[Contributor License Agreement](CLA.md). The Bivy name and logo are covered by
|
|
533
|
+
the [trademark policy](TRADEMARKS.md).
|
package/bin/bivy.mjs
CHANGED
|
@@ -2595,38 +2595,6 @@ async function cmdContext(args = []) {
|
|
|
2595
2595
|
console.log(`\nEverything else: ${c.cyan("bivy help")} (or ${c.cyan("bivy help --json")}).`);
|
|
2596
2596
|
}
|
|
2597
2597
|
|
|
2598
|
-
// `bivy suggest "<task>" [--title "…"] [--run here|subagents|new] [--session <id>]`
|
|
2599
|
-
// — propose a task the user can start in one tap, in this session or beside it. For an agent
|
|
2600
|
-
// offering next steps: write the task as a complete instruction.
|
|
2601
|
-
async function cmdSuggest(args = []) {
|
|
2602
|
-
const usage = 'Usage: bivy suggest "<task>" [--title "short label"] [--run here|subagents|new] [--session <id>] [--json]';
|
|
2603
|
-
if (args.includes("-h") || args.includes("--help")) {
|
|
2604
|
-
console.log(`${usage}\n\nPost a task the user can start in one tap: in this session, through your sub-agents, or in a parallel session that works in its own copy of the project. Write it as a complete instruction, with paths relative to the project root.\n\n--run says where you recommend running it, which becomes the card's main button: here (builds on this conversation), subagents (independent tasks you can split across your own sub-agents; only if you have them), or new (bigger independent work the user will want to follow in its own session). Without it, one card recommends here and several recommend new.\n\n--json prints {"ok","id"}.`);
|
|
2605
|
-
return;
|
|
2606
|
-
}
|
|
2607
|
-
const json = wantsJson(args);
|
|
2608
|
-
const fail = (error) => cliError(error, { json, paint: c.red });
|
|
2609
|
-
const flagsWithValue = new Set(["--session", "--title", "--run"]);
|
|
2610
|
-
const flag = (name) => {
|
|
2611
|
-
const i = args.indexOf(name);
|
|
2612
|
-
return i >= 0 && i + 1 < args.length ? args[i + 1] : undefined;
|
|
2613
|
-
};
|
|
2614
|
-
const text = args.filter((a, i) => !a.startsWith("-") && !(i > 0 && flagsWithValue.has(args[i - 1]))).join(" ").trim();
|
|
2615
|
-
const sessionId = resolveAttachSessionId({ sessionFlag: flag("--session"), env: process.env });
|
|
2616
|
-
if (!text) return fail({ code: "usage", message: usage, exit: EXIT.usage });
|
|
2617
|
-
const run = flag("--run");
|
|
2618
|
-
if (run !== undefined && !["here", "subagents", "new"].includes(run)) return fail({ code: "usage", message: `--run is here, subagents or new (got "${run}").`, exit: EXIT.usage });
|
|
2619
|
-
if (!sessionId) return fail({ code: "no_session", message: "No session id.", hint: "Run inside an agent session ($BIVY_SESSION_ID) or pass --session <id>.", next: "bivy sessions --json", exit: EXIT.usage });
|
|
2620
|
-
const config = loadConfig();
|
|
2621
|
-
if (!(await ensureNodeRunning(config))) return fail({ code: "node_unreachable", message: `Could not reach the Bivy node at ${url(config)}.`, next: "bivy status", exit: EXIT.unavailable });
|
|
2622
|
-
const res = await sessionPost(config, sessionId, "suggest", { text, title: flag("--title"), run }).catch((error) => error);
|
|
2623
|
-
if (res instanceof Error) return fail({ code: "node_unreachable", message: `Could not reach the Bivy node: ${res.message}`, next: "bivy status", exit: EXIT.unavailable });
|
|
2624
|
-
const body = await res.json().catch(() => ({}));
|
|
2625
|
-
if (!res.ok) return fail(sessionHttpError("Suggest", res.status, body));
|
|
2626
|
-
if (json) { console.log(JSON.stringify(body)); return; }
|
|
2627
|
-
console.log(c.green("Suggested in the chat. The user can start it in one tap."));
|
|
2628
|
-
}
|
|
2629
|
-
|
|
2630
2598
|
// `bivy title "<title>" [--session <id>]` — rename the session the agent runs in.
|
|
2631
2599
|
async function cmdTitle(args = []) {
|
|
2632
2600
|
const usage = 'Usage: bivy title "<title>" [--session <id>] [--json]';
|
|
@@ -2674,45 +2642,37 @@ function durationSeconds(text) {
|
|
|
2674
2642
|
return m ? Number(m[1]) * (m[2] === "h" ? 3600 : m[2] === "m" ? 60 : 1) : NaN;
|
|
2675
2643
|
}
|
|
2676
2644
|
|
|
2677
|
-
// `bivy notify
|
|
2678
|
-
//
|
|
2645
|
+
// `bivy notify [--urgent]` — bring the user back: a push naming the session
|
|
2646
|
+
// (never any text) when nobody has the app open. Nothing is posted in the chat.
|
|
2679
2647
|
async function cmdNotify(args = []) {
|
|
2680
|
-
const usage =
|
|
2648
|
+
const usage = "Usage: bivy notify [--urgent] [--session <id>] [--json]";
|
|
2681
2649
|
if (args.includes("-h") || args.includes("--help")) {
|
|
2682
2650
|
console.log(`${usage}
|
|
2683
2651
|
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
{"ok","
|
|
2652
|
+
Push to the user's devices so they come back to this session. The push names the
|
|
2653
|
+
session, nothing else, and nothing is posted in the chat: say what you need in
|
|
2654
|
+
your reply. It is sent only when nobody has the app open; --urgent pushes even
|
|
2655
|
+
while they do. At most one push a minute per session. You don't need it when you
|
|
2656
|
+
finish: Bivy already pushes when a turn ends while the user is away. --json prints
|
|
2657
|
+
{"ok","push":"sent"|"user_watching"|"rate_limited"|"unavailable","userWatching"}.`);
|
|
2690
2658
|
return;
|
|
2691
2659
|
}
|
|
2692
2660
|
const json = wantsJson(args);
|
|
2693
2661
|
const fail = (error) => cliError(error, { json, paint: c.red });
|
|
2694
2662
|
const parsed = parseSessionArgs(args, ["--session"]);
|
|
2695
2663
|
if (parsed.error) return fail({ code: "usage", message: parsed.error, exit: EXIT.usage });
|
|
2696
|
-
const text = parsed.positional.join(" ").trim();
|
|
2697
|
-
if (!text) return fail({ code: "usage", message: usage, exit: EXIT.usage });
|
|
2698
2664
|
const sessionId = resolveAttachSessionId({ sessionFlag: parsed.one("--session"), env: process.env });
|
|
2699
2665
|
if (!sessionId) return fail({ code: "no_session", message: "No session id.", hint: "Run inside an agent session ($BIVY_SESSION_ID) or pass --session <id>.", next: "bivy sessions --json", exit: EXIT.usage });
|
|
2700
2666
|
const config = loadConfig();
|
|
2701
2667
|
if (!(await ensureNodeRunning(config))) return fail({ code: "node_unreachable", message: `Could not reach the Bivy node at ${url(config)}.`, next: "bivy status", exit: EXIT.unavailable });
|
|
2702
|
-
const res = await sessionPost(config, sessionId, "notify", {
|
|
2668
|
+
const res = await sessionPost(config, sessionId, "notify", { urgent: parsed.has("--urgent") }).catch((error) => error);
|
|
2703
2669
|
if (res instanceof Error) return fail({ code: "node_unreachable", message: `Could not reach the Bivy node: ${res.message}`, next: "bivy status", exit: EXIT.unavailable });
|
|
2704
2670
|
const body = await res.json().catch(() => ({}));
|
|
2705
2671
|
if (!res.ok) return fail(sessionHttpError("Notify", res.status, body));
|
|
2706
2672
|
if (json) { console.log(JSON.stringify(body)); return; }
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
if (body.push === "sent") console.log(c.green("Pushed to the user's devices."));
|
|
2711
|
-
else console.log(c.yellow(`Not delivered: a terminal run has no chat to post in, and no push was sent (${noPush ?? body.push}).`));
|
|
2712
|
-
return;
|
|
2713
|
-
}
|
|
2714
|
-
const pushed = body.push === "sent" ? "and pushed to the user's devices" : noPush ? `(no push: ${noPush})` : "";
|
|
2715
|
-
console.log(c.green(`Posted in the chat ${pushed}.`.replace(" .", ".")));
|
|
2673
|
+
if (body.push === "sent") { console.log(c.green("Pushed to the user's devices.")); return; }
|
|
2674
|
+
const noPush = { user_watching: "the user has the app open, so they see your reply; add --urgent to push anyway", rate_limited: "this session pushed less than a minute ago", unavailable: "this machine isn't signed in to a Bivy account" }[body.push];
|
|
2675
|
+
console.log(c.yellow(`No push sent: ${noPush ?? body.push}.`));
|
|
2716
2676
|
}
|
|
2717
2677
|
|
|
2718
2678
|
// `bivy ask "<question>" [--option …]` — the question card, for any agent.
|
|
@@ -6515,9 +6475,6 @@ An agent's own --help passes through, e.g. 'bivy run claude --help'.`);
|
|
|
6515
6475
|
case "attach":
|
|
6516
6476
|
await cmdAttach(args);
|
|
6517
6477
|
break;
|
|
6518
|
-
case "suggest":
|
|
6519
|
-
await cmdSuggest(args);
|
|
6520
|
-
break;
|
|
6521
6478
|
case "title":
|
|
6522
6479
|
await cmdTitle(args);
|
|
6523
6480
|
break;
|
package/bin/cli-commands.mjs
CHANGED
|
@@ -44,14 +44,12 @@ export const COMMANDS = [
|
|
|
44
44
|
{ name: "context", group: "session", scope: "session", json: true, usage: "context [--json]", summary: "Where this agent is running: session, workspace, machine, apps, and what to run next",
|
|
45
45
|
tools: [{ name: "bivy_context", description: "Where you are running inside Bivy: your session, agent, workspace and git branch, the machine, apps you have published, whether the user has the app open, and the commands that reach them.", input: {}, argv: ["context"] }] },
|
|
46
46
|
{ name: "attach", group: "session", scope: "session", json: true, usage: 'attach <file> [--caption "…"] [--artifact]', summary: "Show a local file or image to the user in the chat" },
|
|
47
|
-
{ name: "notify", group: "session", scope: "session", json: true, usage:
|
|
48
|
-
tools: [{ name: "notify_user", description: "
|
|
47
|
+
{ name: "notify", group: "session", scope: "session", json: true, usage: "notify [--urgent]", summary: "Push to the user's phone so they come back (nothing posted in the chat)",
|
|
48
|
+
tools: [{ name: "notify_user", description: "Push to the user's phone so they come back to this session, e.g. when you are blocked on them while still working. The push names the session only and nothing is posted in the chat, so say what you need in your reply. Not needed when you finish: Bivy already pushes when a turn ends while they are away. Sent only when nobody has the app open, at most one a minute per session.", input: { urgent: { type: "boolean", description: "Push even while the user has the app open." } }, argv: ["notify", { when: "urgent", flag: "--urgent" }] }] },
|
|
49
49
|
{ name: "ask", group: "session", scope: "session", json: true, usage: 'ask "<question>" [--option A --option B] [--async]', summary: "Ask the user a question and wait for the answer", subcommands: ["status", "wait"],
|
|
50
50
|
tools: [{ name: "ask_user", description: "Ask the user a question in the chat and wait for their answer (their phone gets a push). Offer 2-8 options, or none for a free-text answer; they can always write their own. Returns {status, answer}: status is answered, dismissed (decide yourself) or expired.", input: { question: { type: "string", description: "The question.", required: true }, options: { type: "array", items: { type: "string" }, description: "Choices to pick from (2-8)." }, multiple: { type: "boolean", description: "Allow several choices." }, header: { type: "string", description: "A short label for the card." }, timeout_seconds: { type: "number", description: "How long to wait (default 600)." } }, argv: ["ask", { arg: "question" }, { flag: "--option", from: "options" }, { when: "multiple", flag: "--multi" }, { flag: "--header", from: "header" }, { flag: "--timeout", from: "timeout_seconds" }] }] },
|
|
51
51
|
{ name: "title", group: "session", scope: "session", json: true, usage: 'title "<title>"', summary: "Rename this session",
|
|
52
52
|
tools: [{ name: "set_session_title", description: "Rename this session in the user's session list. Use a short title (under 60 characters) that says what the work is, when the first message made a poor title or the work changed direction.", input: { title: { type: "string", description: "The new title.", required: true } }, argv: ["title", { arg: "title" }] }] },
|
|
53
|
-
{ name: "suggest", group: "session", scope: "session", json: true, usage: 'suggest "<task>" [--title "label"] [--run here|subagents|new]', summary: "Propose a task the user can start in one tap",
|
|
54
|
-
tools: [{ name: "suggest_task", description: "Propose a next step the user can start in one tap: in this session, through your sub-agents, or in a parallel session with its own copy of the project. Write the task as a complete instruction with paths relative to the project root. Post one per idea instead of listing them.", input: { task: { type: "string", description: "The complete instruction.", required: true }, title: { type: "string", description: "A short label for the card." }, run: { type: "string", enum: ["here", "subagents", "new"], description: "Where you recommend running it: here (builds on this conversation), subagents (independent tasks you can split across your own sub-agents; only if you have them), or new (bigger independent work in its own session). Defaults: here for one card, new for several." } }, argv: ["suggest", { arg: "task" }, { flag: "--title", from: "title" }, { flag: "--run", from: "run" }] }] },
|
|
55
53
|
{ name: "app", group: "session", scope: "session", json: true, usage: "app <publish|shot|present|share|run|…>", summary: "Live previews: publish a web/terminal/desktop app, screenshot it, present it", subcommands: ["publish", "list", "remove", "shot", "present", "share", "notes", "run", "click", "type", "key", "scroll", "drag", "move", "menu"],
|
|
56
54
|
tools: [
|
|
57
55
|
{ name: "app_publish", description: "Give the user a live preview of something with a UI, from an app manifest file (web server port, static build, terminal, or desktop app). Run `bivy app --help` for the manifest format.", input: { manifest_path: { type: "string", description: "Path to the manifest JSON.", required: true } }, argv: ["app", "publish", { arg: "manifest_path" }] },
|
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
# Talk to the user
|
|
2
2
|
|
|
3
|
-
Summary: When to answer in chat, when to notify, when to ask and wait
|
|
3
|
+
Summary: When to answer in chat, when to notify, and when to ask and wait.
|
|
4
4
|
|
|
5
5
|
Your chat reply is the default. Reach for these when the chat alone won't do.
|
|
6
6
|
|
|
7
7
|
## They may be away: notify
|
|
8
8
|
|
|
9
|
-
bivy notify
|
|
10
|
-
bivy notify --urgent
|
|
9
|
+
bivy notify
|
|
10
|
+
bivy notify --urgent
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
Pushes to their devices so they come back to this session. The push names the
|
|
13
|
+
session only and nothing is posted in the chat, so say what you need in your
|
|
14
|
+
reply. It goes out only when nobody has the app open; `--urgent` pushes even
|
|
15
|
+
while they are looking. One push a minute per session.
|
|
16
|
+
|
|
17
|
+
You don't need it when you finish: Bivy already pushes when a turn ends while
|
|
18
|
+
they are away. Use it while you keep working and need them, for example when a
|
|
19
|
+
long run is blocked on something only they can do.
|
|
20
|
+
|
|
21
|
+
Next steps and options go in your reply as plain text.
|
|
16
22
|
|
|
17
23
|
## You need a decision: ask
|
|
18
24
|
|
|
@@ -24,23 +30,6 @@ dismissed it (use your judgment), exit 5 that `--timeout` (default 10m) passed.
|
|
|
24
30
|
For long waits use `--async`, keep working, and later `bivy ask wait <id>`.
|
|
25
31
|
Ask only when you can't reasonably decide yourself.
|
|
26
32
|
|
|
27
|
-
## Offer next steps: suggest
|
|
28
|
-
|
|
29
|
-
bivy suggest "Add a GET /version endpoint that returns the package version." --title "Add /version"
|
|
30
|
-
|
|
31
|
-
Each suggestion is a card the user can start in one tap: here, through your
|
|
32
|
-
sub-agents, or in a parallel session with its own copy of the project. Write it as
|
|
33
|
-
a complete instruction with paths relative to the project root. Post one per idea
|
|
34
|
-
instead of a bulleted list.
|
|
35
|
-
|
|
36
|
-
`--run` picks the card's main button; the others stay one tap away:
|
|
37
|
-
|
|
38
|
-
| `--run` | When |
|
|
39
|
-
|---|---|
|
|
40
|
-
| `here` | It builds on this conversation, or it's small. Default for a single card. |
|
|
41
|
-
| `subagents` | Independent tasks you can split across your own sub-agents and report back on. Only if you have sub-agents. |
|
|
42
|
-
| `new` | Bigger independent work the user will want to follow, review or merge on its own. Default for several cards. |
|
|
43
|
-
|
|
44
33
|
## Name the session: title
|
|
45
34
|
|
|
46
35
|
bivy title "Fix login redirect loop"
|
|
@@ -30,27 +30,31 @@ export const MAX_AGENT_INSTRUCTIONS_BYTES = 16 * 1024;
|
|
|
30
30
|
export const BIVY_AGENT_NOTE = [
|
|
31
31
|
"You are running inside Bivy. The user follows this session in a chat app (web or phone): they cannot see your " +
|
|
32
32
|
"terminal or files you only write to disk. $BIVY_SESSION_ID identifies this session; the `bivy` commands below use it.",
|
|
33
|
-
"- Show a
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
|
|
33
|
+
"- Show an IMAGE (a screenshot, or a picture you rendered to a file) inside your reply: write it as markdown, " +
|
|
34
|
+
"``, where you want it to appear. The path must be inside the session " +
|
|
35
|
+
"workspace; a remote `https://` image works too. No tool call needed.",
|
|
36
|
+
"- Show a FILE (a report, a log, data they asked for) inside your reply: put " +
|
|
37
|
+
'`::view{src=relative/path.pdf caption="what it is"}` on its own line, where you want it. Same workspace-only ' +
|
|
38
|
+
"rule. A `.csv`/`.tsv` renders as a table; anything else arrives as a download.",
|
|
39
|
+
"- Show a NUMBER or a CHART inside your reply: fence a spec as ```bivy. A number is " +
|
|
40
|
+
'`{"type":"metric","value":"4 650 kWh","label":"per year"}`; a chart is a plain Vega-Lite spec with its data ' +
|
|
41
|
+
"inline, or pointing at a workspace data file with `\"data\":{\"url\":\"data/use.csv\"}` (.csv/.tsv/.json). " +
|
|
42
|
+
"A chart cannot fetch a remote URL.",
|
|
43
|
+
"- Send a file WITHOUT writing a reply (or from a script): run " +
|
|
44
|
+
'`bivy attach <path> [--caption "short note"]`, or call the `attach_to_chat` tool if you have it.',
|
|
45
|
+
"- Put a published app's preview INSIDE your reply: `::view{app=<app id>}` on its own line. It frames the app " +
|
|
46
|
+
"where you wrote it, and still opens full screen on demand.",
|
|
37
47
|
"- Something with a UI: `bivy app publish <manifest.json>` (a web server's port, a static build, a terminal) or " +
|
|
38
48
|
"`bivy app run -- <command>` (a desktop app) gives the user a live preview; `bivy app shot` screenshots it so you " +
|
|
39
49
|
"can check your work; `bivy app present` tells the user a visible change is ready to look at, and " +
|
|
40
50
|
"`.bivy/scenarios/*.json` files let them open it in the states that matter (errors, empty, slow) with `--try`. " +
|
|
41
51
|
"`bivy app --help` has the details.",
|
|
42
|
-
"- Proposing tasks the user could hand you (next steps, ideas, options): post each with " +
|
|
43
|
-
'`bivy suggest "<complete instruction>" [--title "short label"] [--run here|subagents|new]` instead of only ' +
|
|
44
|
-
"listing them. The user can start each in one tap, in this session, through your sub-agents, or in a parallel " +
|
|
45
|
-
"one that works in its own copy of the project, so write it to stand on its own, with paths relative to the " +
|
|
46
|
-
"project root. `--run` is the one you recommend: here when it builds on this conversation, subagents for " +
|
|
47
|
-
"independent tasks you can split and supervise (only if you have sub-agents), new for bigger work worth its " +
|
|
48
|
-
"own session.",
|
|
49
52
|
'- If this session\'s title (taken from the first message) doesn\'t say what the work is, or the work changes ' +
|
|
50
53
|
'direction: `bivy title "<short title>"`.',
|
|
51
|
-
"-
|
|
52
|
-
'`bivy notify
|
|
53
|
-
'an answer: `bivy ask "<question>" [--option A --option B]` prints their answer (or use your own
|
|
54
|
+
"- Your chat reply is what the user reads; when you finish while they are away, Bivy pushes to their phone for you. " +
|
|
55
|
+
'To bring them back while you keep working: `bivy notify` (a push only; say what you need in the chat). To ask ' +
|
|
56
|
+
'and wait for an answer: `bivy ask "<question>" [--option A --option B]` prints their answer (or use your own ' +
|
|
57
|
+
"ask-the-user tool).",
|
|
54
58
|
"- Only when the user asks for another agent or another of their machines to take part: " +
|
|
55
59
|
'`bivy delegate "<self-contained task>" --agent <id> [--machine <name>] --wait` runs it there and prints ' +
|
|
56
60
|
"its answer and any branch/PR; `--to codex,grok@<machine>` asks several to compare, `bivy delegate machines` " +
|
|
@@ -24,6 +24,9 @@ export class RemotePreview {
|
|
|
24
24
|
this.badge = badge;
|
|
25
25
|
}
|
|
26
26
|
get available() { return this.online && Boolean(this.gateway); }
|
|
27
|
+
/** Someone is loading or holding open a preview (pooled streams close after a
|
|
28
|
+
* few idle seconds; a dev server's live-reload socket stays open). */
|
|
29
|
+
get inUse() { return this.sockets.size > 0; }
|
|
27
30
|
ready(origin, relayUrl) {
|
|
28
31
|
this.disconnect();
|
|
29
32
|
if (!origin)
|
package/dist/apps/service.js
CHANGED
|
@@ -814,8 +814,13 @@ export class AppService {
|
|
|
814
814
|
return;
|
|
815
815
|
const now = Date.now();
|
|
816
816
|
server.restarts = server.restarts.filter((at) => now - at < RESTART_WINDOW);
|
|
817
|
-
|
|
817
|
+
// A crash loop stays down until the view is opened again, rather than
|
|
818
|
+
// retrying every time the window rolls over.
|
|
819
|
+
if (server.restarts.length >= MAX_RESTARTS) {
|
|
820
|
+
clearInterval(server.timer);
|
|
821
|
+
server.timer = undefined;
|
|
818
822
|
return;
|
|
823
|
+
}
|
|
819
824
|
server.restarts.push(now);
|
|
820
825
|
server.termId = undefined;
|
|
821
826
|
void this.ensureServer(current).catch(() => { });
|
package/dist/apps/styles.css
CHANGED
|
@@ -485,6 +485,12 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
|
|
|
485
485
|
}
|
|
486
486
|
.transcript-turn { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
|
|
487
487
|
.transcript-standalone { display: flex; justify-content: center; min-width: 0; }
|
|
488
|
+
/* A centered flex row lets a child grow past the column on one long unbroken
|
|
489
|
+
token (a path in an error); cap every standalone item to the column. */
|
|
490
|
+
.transcript-standalone > * { min-width: 0; max-width: 100%; }
|
|
491
|
+
/* Errors span the column so their edges line up with the turn content. */
|
|
492
|
+
.transcript-error { flex: 1; display: flex; flex-direction: column; gap: var(--space-2); overflow-wrap: anywhere; }
|
|
493
|
+
.transcript-error .settings-disclosure-body { margin: 0; padding: 0; white-space: pre-wrap; font-size: var(--text-xs); color: var(--muted); }
|
|
488
494
|
.turn-response-body { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
|
|
489
495
|
.jump-latest {
|
|
490
496
|
position: absolute; left: 50%; bottom: 16px; transform: translateX(-50%);
|
|
@@ -633,6 +639,29 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
|
|
|
633
639
|
.msg.assistant .mermaid-diagram:first-child { margin-top: 0; }
|
|
634
640
|
.msg.assistant .mermaid-diagram:last-child { margin-bottom: 0; }
|
|
635
641
|
.msg.assistant .mermaid-diagram svg { display: inline-block; max-width: none; height: auto; vertical-align: top; }
|
|
642
|
+
/* Mount point for a component the agent placed in its message (::view{…}, a
|
|
643
|
+
```bivy fence). Layout only: what renders inside is an existing component
|
|
644
|
+
(.msg-attachment, .card), so this must not restyle its shell — it only gives
|
|
645
|
+
it the same vertical rhythm as a paragraph. Empty until the portal mounts,
|
|
646
|
+
and empty forever if a reference never resolves, so it carries no border or
|
|
647
|
+
background of its own that would leave a visible hole. */
|
|
648
|
+
.msg.assistant .md-component { margin: 0.75em 0; }
|
|
649
|
+
.msg.assistant .md-component:first-child { margin-top: 0; }
|
|
650
|
+
.msg.assistant .md-component:last-child { margin-bottom: 0; }
|
|
651
|
+
.msg.assistant .md-component:empty { margin: 0; }
|
|
652
|
+
/* A placed component is a block in the reading column, not a tile in a row: it
|
|
653
|
+
fills the message width so every kind lines up with every other one and with
|
|
654
|
+
the prose around it. The fixed chip width belongs to the composer's wrapping
|
|
655
|
+
attachment list, where several chips share a line. */
|
|
656
|
+
.msg.assistant .md-component > * { width: 100%; }
|
|
657
|
+
/* A single number the agent wants read at a glance. Inherits .card's shell;
|
|
658
|
+
only the value's type scale is its own. */
|
|
659
|
+
.metric-component { text-align: center; }
|
|
660
|
+
.metric-value { font-size: var(--text-3xl); line-height: var(--lh-3xl); font-weight: var(--weight-semibold); }
|
|
661
|
+
/* A table from a CSV or a spec reuses .markdown-table-wrap, so it reads exactly
|
|
662
|
+
like a table the agent wrote as markdown. The caption is the only addition. */
|
|
663
|
+
.table-component { margin: 0; }
|
|
664
|
+
.table-component figcaption { margin-top: var(--space-2); }
|
|
636
665
|
/* Syntax highlighting for fenced code blocks (highlight.js token classes).
|
|
637
666
|
Colors use light-dark() so one rule set tracks the app's light/dark scheme
|
|
638
667
|
(color-scheme is set on :root). A GitHub-flavored palette that sits well on
|
|
@@ -655,20 +684,6 @@ input, textarea, select { font-family: inherit; font-size: 16px; }
|
|
|
655
684
|
.entry-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); font-style: normal; }
|
|
656
685
|
.msg.system .entry-actions { justify-content: center; }
|
|
657
686
|
.msg.thinking { align-self: flex-start; color: var(--muted); font-size: 13px; border-left: 2px solid var(--line-strong); padding-left: 10px; }
|
|
658
|
-
.msg.error {
|
|
659
|
-
align-self: stretch; display: flex; gap: 8px; align-items: flex-start;
|
|
660
|
-
background: var(--danger-soft); border: 1px solid color-mix(in srgb, var(--danger) 45%, transparent);
|
|
661
|
-
border-left: 3px solid var(--danger); border-radius: var(--radius-sm); padding: 10px 12px;
|
|
662
|
-
}
|
|
663
|
-
.msg-error-icon {
|
|
664
|
-
flex: none; width: 18px; height: 18px; margin-top: 1px; border-radius: var(--radius-full);
|
|
665
|
-
background: var(--danger); color: var(--danger-contrast); font-weight: 700; font-size: 12px;
|
|
666
|
-
display: grid; place-items: center;
|
|
667
|
-
}
|
|
668
|
-
.msg-error-text {
|
|
669
|
-
flex: 1; min-width: 0; font-size: 13px; line-height: 1.45; color: var(--ink);
|
|
670
|
-
white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word;
|
|
671
|
-
}
|
|
672
687
|
.msg.streaming { position: relative; }
|
|
673
688
|
.msg.streaming::after { content: "▍"; color: var(--accent); animation: blink 1s steps(2) infinite; }
|
|
674
689
|
@keyframes blink { 50% { opacity: 0; } }
|
|
@@ -1477,10 +1492,8 @@ button.sheet-action:last-child { border-bottom: 0; }
|
|
|
1477
1492
|
}
|
|
1478
1493
|
/* Password-manager-style provider credential vault. Saved items are the primary
|
|
1479
1494
|
list; the provider catalog appears only inside Add. */
|
|
1480
|
-
/*
|
|
1481
|
-
|
|
1482
|
-
.credential-vault, .machine-profiles { gap: 14px; max-width: 680px; width: 100%; }
|
|
1483
|
-
.credential-vault { overflow-wrap: anywhere; }
|
|
1495
|
+
/* The credential vault: a wide settings panel that reads as a shallow "vault". */
|
|
1496
|
+
.credential-vault { gap: 14px; max-width: 680px; width: 100%; overflow-wrap: anywhere; }
|
|
1484
1497
|
.vault-title-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
|
|
1485
1498
|
.vault-title-row > div { min-width: 0; }
|
|
1486
1499
|
/* The header action (e.g. "+ Add profile") never shrinks or wraps — the title
|
|
@@ -1865,21 +1878,8 @@ button.template-card.is-featured .template-card-icon {
|
|
|
1865
1878
|
}
|
|
1866
1879
|
.automation-row .row-menu-btn { opacity: 0.72; }
|
|
1867
1880
|
.automation-row:hover .row-menu-btn { opacity: 1; }
|
|
1868
|
-
.run-row { align-items: center; }
|
|
1869
|
-
.run-row-open {
|
|
1870
|
-
appearance: none; border: 0; background: transparent; color: inherit; font: inherit;
|
|
1871
|
-
text-align: left; padding: 0; cursor: pointer;
|
|
1872
|
-
}
|
|
1873
|
-
.run-row-open:disabled { cursor: default; }
|
|
1874
|
-
.run-row-open:not(:disabled):hover .automation-row-title strong { color: var(--accent); }
|
|
1875
|
-
.run-row-chevron {
|
|
1876
|
-
display: grid; place-items: center; flex: none; width: 40px; min-height: 40px;
|
|
1877
|
-
border: 0; border-radius: var(--radius-md); padding: 0; background: transparent;
|
|
1878
|
-
color: var(--muted); font: inherit; font-size: 24px; line-height: 1; cursor: pointer;
|
|
1879
|
-
}
|
|
1880
|
-
.run-row-chevron:hover { color: var(--ink); background: var(--surface-2); }
|
|
1881
1881
|
.runs-setup {
|
|
1882
|
-
margin-top:
|
|
1882
|
+
margin-top: var(--space-6); border: 1px solid var(--line); border-radius: var(--radius-md);
|
|
1883
1883
|
background: var(--surface); overflow: hidden;
|
|
1884
1884
|
}
|
|
1885
1885
|
.runs-setup > summary {
|
|
@@ -1894,16 +1894,13 @@ button.template-card.is-featured .template-card-icon {
|
|
|
1894
1894
|
.runs-setup[open] .runs-setup-chevron { transform: rotate(90deg); }
|
|
1895
1895
|
.runs-setup-body { display: flex; flex-direction: column; gap: 12px; padding: 14px; border-top: 1px solid var(--line); }
|
|
1896
1896
|
.runs-setup-body .picker-search { max-width: 100%; box-sizing: border-box; }
|
|
1897
|
-
|
|
1898
|
-
.
|
|
1899
|
-
.
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
.
|
|
1903
|
-
.
|
|
1904
|
-
.incoming-work { margin-top: 22px; }
|
|
1905
|
-
.incoming-work > .autom-section-label { margin-bottom: 8px; }
|
|
1906
|
-
.incoming-work > .settings-form { gap: 14px; }
|
|
1897
|
+
/* Runs feed: grouped like the session list (attention, in progress, by day). */
|
|
1898
|
+
.run-history { margin-top: var(--space-2); }
|
|
1899
|
+
.run-history .session-group-label { margin: 0; padding-inline: 0; }
|
|
1900
|
+
.run-history > .settings-form { gap: var(--space-2); padding: 0 0 var(--space-3); border-bottom: 1px solid var(--line); }
|
|
1901
|
+
.run-history > .settings-form:empty { display: none; }
|
|
1902
|
+
.run-history-failure { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1903
|
+
.automation-history-row:disabled { cursor: default; }
|
|
1907
1904
|
|
|
1908
1905
|
/* A runner is a first-class requirement, not a tiny select hidden under the
|
|
1909
1906
|
prompt. Pairing/key readiness is visible before Save can become disabled. */
|
|
@@ -1955,14 +1952,6 @@ button.template-card.is-featured .template-card-icon {
|
|
|
1955
1952
|
.run-timeline li span { color: var(--muted); font-size: 12px; }
|
|
1956
1953
|
.run-timeline p { grid-column: 1 / -1; margin: 0; color: var(--muted); font-size: 12px; line-height: 1.4; }
|
|
1957
1954
|
.run-timeline code { grid-column: 1 / -1; overflow-wrap: anywhere; font-size: 11px; }
|
|
1958
|
-
.run-history-filters {
|
|
1959
|
-
display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0;
|
|
1960
|
-
}
|
|
1961
|
-
.run-history-filters .btn { white-space: nowrap; }
|
|
1962
|
-
@media (max-width: 479px) {
|
|
1963
|
-
.run-history-filters { flex-wrap: nowrap; overflow-x: auto; margin-inline: -4px; padding-inline: 4px; scrollbar-width: none; }
|
|
1964
|
-
.run-history-filters::-webkit-scrollbar { display: none; }
|
|
1965
|
-
}
|
|
1966
1955
|
.run-details .run-sheet-failure { margin-top: 14px; border: 1px solid color-mix(in srgb, var(--danger) 35%, var(--line)); border-radius: var(--radius-md); }
|
|
1967
1956
|
.run-details-receipt { margin-top: 18px !important; }
|
|
1968
1957
|
.run-details-state {
|
|
@@ -2147,7 +2136,7 @@ button.template-card.is-featured .template-card-icon {
|
|
|
2147
2136
|
.automation-detail-head .icon { flex-shrink: 0; }
|
|
2148
2137
|
.automation-detail-head svg { width: var(--space-5); height: var(--space-5); }
|
|
2149
2138
|
.automations-view.is-history .automations-view-body { flex: 1; padding: var(--space-5) var(--space-4); }
|
|
2150
|
-
.automation-history-view
|
|
2139
|
+
.automation-history-view { margin-top: 0; }
|
|
2151
2140
|
.automation-history-row {
|
|
2152
2141
|
display: flex; align-items: center; gap: var(--space-3); width: 100%;
|
|
2153
2142
|
padding: var(--space-4) 0; border: 0; border-bottom: 1px solid var(--line);
|
|
@@ -2507,16 +2496,6 @@ a.queue-item:hover { border-color: var(--line-strong); background: var(--surface
|
|
|
2507
2496
|
.automation-row-actions { width: auto; justify-content: flex-end; border-top: 0; padding-top: 0; }
|
|
2508
2497
|
.automation-row-actions .btn { min-height: 40px; }
|
|
2509
2498
|
.automation-row .row-menu-btn { min-width: 40px; min-height: 40px; opacity: 1; }
|
|
2510
|
-
.run-row { align-items: flex-start; flex-wrap: wrap; }
|
|
2511
|
-
.run-row .automation-row-main { flex-basis: 100%; }
|
|
2512
|
-
.run-row .automation-row-actions { width: 100%; padding-top: 6px; }
|
|
2513
|
-
.run-row-chevron { margin-left: auto; }
|
|
2514
|
-
.runs-overview .autom-section-head { align-items: stretch; flex-direction: column; }
|
|
2515
|
-
.runs-overview .autom-section-actions { display: grid; grid-template-columns: 1fr 1fr; width: 100%; }
|
|
2516
|
-
/* Keep two actions balanced when needed, but don't make a lone Refresh button
|
|
2517
|
-
occupy half the screen. */
|
|
2518
|
-
.runs-overview .autom-section-actions:has(> :only-child) { display: flex; justify-content: flex-start; }
|
|
2519
|
-
.runs-overview .autom-section-actions .btn { min-width: 96px; width: auto; }
|
|
2520
2499
|
.queue-head { align-items: flex-start; gap: 10px; }
|
|
2521
2500
|
.queue-head-actions { justify-content: flex-end; gap: 8px; min-width: 0; text-align: right; }
|
|
2522
2501
|
.queue-head-actions .btn.link { overflow-wrap: anywhere; }
|
|
@@ -2617,15 +2596,6 @@ a.queue-item:hover { border-color: var(--line-strong); background: var(--surface
|
|
|
2617
2596
|
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
|
2618
2597
|
}
|
|
2619
2598
|
.connect-option:hover { border-color: var(--line-strong); box-shadow: var(--shadow-md); }
|
|
2620
|
-
.connect-option-head { display: flex; align-items: flex-start; gap: 12px; }
|
|
2621
|
-
.connect-option-badge {
|
|
2622
|
-
flex: none; width: 36px; height: 36px; display: grid; place-items: center;
|
|
2623
|
-
border-radius: var(--radius-md); color: var(--accent);
|
|
2624
|
-
background: color-mix(in srgb, var(--accent) 12%, transparent);
|
|
2625
|
-
}
|
|
2626
|
-
.connect-option-copy { min-width: 0; }
|
|
2627
|
-
.connect-option-copy h3 { margin: 1px 0 3px; font-size: 15px; }
|
|
2628
|
-
.connect-option-copy p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.45; }
|
|
2629
2599
|
|
|
2630
2600
|
.connect-command {
|
|
2631
2601
|
display: flex; align-items: center; gap: 8px; padding: 4px 4px 4px 12px;
|
|
@@ -2645,9 +2615,8 @@ a.queue-item:hover { border-color: var(--line-strong); background: var(--surface
|
|
|
2645
2615
|
.connect-option-links { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
|
|
2646
2616
|
.connect-option-link { align-self: flex-start; color: var(--accent); font-size: 12.5px; font-weight: 600; text-decoration: none; }
|
|
2647
2617
|
.connect-option-link:hover { text-decoration: underline; }
|
|
2648
|
-
.connect-option-cta { align-self: flex-start; }
|
|
2649
2618
|
/* A one-time "next step" card above the composer (automations, notifications). */
|
|
2650
|
-
.next-step {
|
|
2619
|
+
.next-step { box-sizing: border-box; width: min(100% - 2 * var(--space-3), 800px - 2 * var(--space-3)); margin: 0 auto var(--space-3); display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
|
|
2651
2620
|
.next-step p { margin: var(--space-1) 0 0; color: var(--muted); font-size: var(--text-sm); }
|
|
2652
2621
|
.next-step .banner { margin-top: var(--space-2); }
|
|
2653
2622
|
.next-step .next-step-ok { margin: 0; color: var(--ok); font-weight: var(--weight-medium); }
|
|
@@ -3000,7 +2969,7 @@ textarea.picker-search { resize: vertical; font-family: ui-monospace, monospace;
|
|
|
3000
2969
|
.node-switcher-btn.locked { cursor: default; }
|
|
3001
2970
|
.node-switcher-name { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3002
2971
|
.node-switcher-caret { color: var(--muted); font-size: 9px; }
|
|
3003
|
-
.node-menu { position: absolute; left: 0; top: calc(100% + 6px); min-width: 220px; z-index: var(--z-dropdown); }
|
|
2972
|
+
.node-menu { position: absolute; left: 0; top: calc(100% + 6px); min-width: 220px; width: max-content; max-width: calc(100vw - var(--space-6)); z-index: var(--z-dropdown); }
|
|
3004
2973
|
/* "Reconnecting…" line at the top of the open switcher, under the node the
|
|
3005
2974
|
button shows — the dropdown's spelled-out counterpart to the spinner dot. */
|
|
3006
2975
|
.node-menu-status { display: flex; align-items: center; gap: 8px; padding: 10px 14px; font-size: 13px; color: var(--muted); border-bottom: 1px solid var(--line); }
|
|
@@ -3015,6 +2984,8 @@ textarea.picker-search { resize: vertical; font-family: ui-monospace, monospace;
|
|
|
3015
2984
|
.node-menu-item.active { font-weight: 600; }
|
|
3016
2985
|
.node-menu-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
3017
2986
|
.node-menu-check { color: var(--accent); }
|
|
2987
|
+
/* Quiet trailing hint on a cloud row, e.g. "starts when you send". */
|
|
2988
|
+
.node-menu-meta { flex: none; color: var(--muted); font-size: var(--text-xs); }
|
|
3018
2989
|
.node-menu-glyph { color: var(--accent); flex: none; }
|
|
3019
2990
|
.eph-steps { margin: 4px 0; padding-left: 18px; color: var(--muted); font-size: 13px; display: grid; gap: 4px; }
|
|
3020
2991
|
.code-snippet { margin: 6px 0 0; overflow: auto; border: 1px solid var(--line); border-radius: var(--radius-md); padding: 10px; background: var(--surface); font-size: 12px; }
|
|
@@ -3247,24 +3218,9 @@ p.setup-note .btn.link { min-height: 44px; margin-block: calc((1lh - 44px) / 2);
|
|
|
3247
3218
|
.app-row-meta { color: var(--muted); font-size: var(--text-xs); line-height: var(--lh-xs); }
|
|
3248
3219
|
.app-row-action { flex: none; display: flex; align-items: center; gap: var(--space-1); }
|
|
3249
3220
|
.app-message { margin-block: var(--space-2); }
|
|
3250
|
-
/* Suggested task (SuggestionCard.tsx): a task the agent proposed, one tap to
|
|
3251
|
-
start in its own session. Shell from .card; layout only here. */
|
|
3252
|
-
.suggestion-card { max-inline-size: 440px; display: flex; flex-direction: column; gap: var(--space-1); }
|
|
3253
3221
|
/* The small label above a chat card's content, shared by every agent-posted card. */
|
|
3254
|
-
.
|
|
3255
|
-
|
|
3256
|
-
.suggestion-text { margin: 0; color: var(--muted); font-size: var(--text-sm); white-space: pre-wrap; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
|
|
3257
|
-
.suggestion-text[data-expanded="true"] { display: block; overflow: visible; }
|
|
3258
|
-
.suggestion-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2); }
|
|
3259
|
-
.suggestion-bar, .suggestion-all { display: flex; flex-direction: column; gap: var(--space-1); margin-top: var(--space-2); }
|
|
3260
|
-
.suggestion-all { padding-top: var(--space-2); border-top: 1px solid var(--line); }
|
|
3261
|
-
.suggestion-bar .suggestion-actions, .suggestion-all .suggestion-actions { margin-top: 0; }
|
|
3262
|
-
.suggestion-hint { margin: 0; color: var(--muted); font-size: var(--text-xs); }
|
|
3263
|
-
/* In a set, the title is the checkbox's label, so the whole line is the tap target. */
|
|
3264
|
-
.suggestion-pick { display: flex; align-items: flex-start; gap: var(--space-2); cursor: pointer; }
|
|
3265
|
-
.suggestion-pick input { flex: none; inline-size: 18px; block-size: 18px; margin: 2px 0 0; accent-color: var(--accent); }
|
|
3266
|
-
.suggestion-status { margin: var(--space-2) 0 0; display: flex; align-items: center; gap: var(--space-2); color: var(--ok); font-size: var(--text-sm); font-weight: var(--weight-medium); }
|
|
3267
|
-
/* Notice (NoticeCard.tsx): a message the agent sent with `bivy notify`.
|
|
3222
|
+
.delegation-eyebrow, .notice-eyebrow { margin: 0; color: var(--muted); font-size: var(--text-xs); font-weight: var(--weight-semibold); }
|
|
3223
|
+
/* Notice (NoticeCard.tsx): a message from Bivy, e.g. applied automations.
|
|
3268
3224
|
Shell and tone from .card, the urgent marker from .badge. */
|
|
3269
3225
|
.notice-card { max-inline-size: 440px; display: flex; flex-direction: column; gap: var(--space-1); }
|
|
3270
3226
|
.notice-eyebrow { display: flex; align-items: center; gap: var(--space-2); }
|
|
@@ -3629,21 +3585,13 @@ p.setup-note .btn.link { min-height: 44px; margin-block: calc((1lh - 44px) / 2);
|
|
|
3629
3585
|
|
|
3630
3586
|
/* Compact, thumb-friendly automation list: the row is the editor link. */
|
|
3631
3587
|
.automation-list { gap: var(--space-2); border: 0; }
|
|
3632
|
-
.automation-row
|
|
3588
|
+
.automation-row {
|
|
3633
3589
|
min-height: 0; padding: var(--space-3); border: 1px solid var(--line);
|
|
3634
3590
|
border-radius: var(--radius-lg); background: var(--surface-2);
|
|
3635
3591
|
grid-template-columns: 36px minmax(0, 1fr) auto; gap: var(--space-3);
|
|
3636
3592
|
align-items: center;
|
|
3637
3593
|
}
|
|
3638
|
-
.
|
|
3639
|
-
display: flex; flex-wrap: wrap; align-items: flex-start;
|
|
3640
|
-
gap: var(--space-3); padding: var(--space-4);
|
|
3641
|
-
}
|
|
3642
|
-
.run-row-open { flex: 1 1 100%; min-width: 0; }
|
|
3643
|
-
.run-row .automation-row-main { width: 100%; }
|
|
3644
|
-
.run-row .automation-row-actions { width: 100%; justify-content: flex-start; flex-wrap: wrap; }
|
|
3645
|
-
.run-row .run-row-chevron { margin-left: auto; }
|
|
3646
|
-
.automation-row:not(.run-row):hover { background: var(--surface-3); }
|
|
3594
|
+
.automation-row:hover { background: var(--surface-3); }
|
|
3647
3595
|
.automation-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
3648
3596
|
.automation-row-icon { width: 36px; height: 36px; }
|
|
3649
3597
|
.automation-row-icon svg { width: 18px; height: 18px; }
|
|
@@ -3670,8 +3618,6 @@ p.setup-note .btn.link { min-height: 44px; margin-block: calc((1lh - 44px) / 2);
|
|
|
3670
3618
|
.automation-history-view .autom-section-head { margin-bottom: var(--space-3); }
|
|
3671
3619
|
.automation-history-view .automation-list { gap: var(--space-2); }
|
|
3672
3620
|
.automation-history-view .automation-row { padding: var(--space-3); }
|
|
3673
|
-
.automation-history-view .run-history-filters { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding-bottom: var(--space-1); }
|
|
3674
|
-
.automation-history-view .run-history-filters::-webkit-scrollbar { display: none; }
|
|
3675
3621
|
.automations-view.is-history .automations-view-head-actions > .btn.primary { display: none; }
|
|
3676
3622
|
.automation-history-view .autom-section-head { align-items: flex-start; gap: var(--space-3); }
|
|
3677
3623
|
.automation-history-view .autom-section-head > strong { min-width: 0; line-height: var(--lh-lg); }
|
|
@@ -3687,3 +3633,22 @@ p.setup-note .btn.link { min-height: 44px; margin-block: calc((1lh - 44px) / 2);
|
|
|
3687
3633
|
font-family: var(--font-serif);
|
|
3688
3634
|
font-weight: var(--weight-medium);
|
|
3689
3635
|
}
|
|
3636
|
+
/* A Vega-Lite chart an agent placed in a message. Vega owns the SVG inside
|
|
3637
|
+
.chart-host, so nothing here styles its internals — colors come from the
|
|
3638
|
+
tokens read in vega.ts, which is how the chart tracks light/dark. */
|
|
3639
|
+
.chart-component { margin: 0; }
|
|
3640
|
+
.chart-component .chart-host {
|
|
3641
|
+
width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; padding: 10px;
|
|
3642
|
+
border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface);
|
|
3643
|
+
}
|
|
3644
|
+
.chart-component figcaption { margin-top: var(--space-2); }
|
|
3645
|
+
/* An app preview framed inside a message. Same bordered surface as a chart or
|
|
3646
|
+
a mermaid diagram — all three are a figure in the prose, and should not read
|
|
3647
|
+
as three different things. */
|
|
3648
|
+
.inline-app { margin: 0; }
|
|
3649
|
+
.inline-app-frame {
|
|
3650
|
+
display: block; width: 100%; height: 420px; border: 1px solid var(--line);
|
|
3651
|
+
border-radius: var(--radius-sm); background: var(--surface);
|
|
3652
|
+
}
|
|
3653
|
+
.inline-app figcaption { display: flex; gap: var(--space-2); align-items: baseline; justify-content: space-between; margin-top: var(--space-2); }
|
|
3654
|
+
.inline-app-open { flex: none; }
|