brane 0.3.1 → 0.3.2

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/AGENTS.md CHANGED
@@ -116,8 +116,8 @@ published GitHub release, and only by it. **Agents never run `npm publish`.**
116
116
  The shared web app ships with it: a release deploys its tarball's
117
117
  `expo/dist`, and a merge to `main` deploys nothing (staging is Isolate on a
118
118
  daemon running `main`). The version bump, tag rule, dist-tag choice, app
119
- deploy and rollback, and why 0.3.0 has no provenance attestation are in
120
- [docs/releasing.md](docs/releasing.md).
119
+ deploy and rollback, and why 0.3.0 and 0.3.1 have no provenance
120
+ attestation are in [docs/releasing.md](docs/releasing.md).
121
121
 
122
122
  ## CLI Commands
123
123
 
package/CHANGELOG.md CHANGED
@@ -6,6 +6,22 @@ page, which is also what triggers its publish (see
6
6
  [docs/releasing.md](docs/releasing.md)). This file is the summary that
7
7
  travels in the npm tarball.
8
8
 
9
+ ## 0.3.2 - 2026-10-13
10
+
11
+ - Archive is offered only once a narrative has ended, and the daemon
12
+ enforces it: `PATCH /api/narratives/:id/archive` answers 409 while the
13
+ narrative's status isn't `ended`, its agent is still connected, or its
14
+ tmux session is up. Unarchiving is never refused
15
+ ([#604](https://github.com/benjamn/brane/pull/604)).
16
+ - Archiving from a narrative's own 🦠 menu goes to the narrative list,
17
+ and Back returns to the archived narrative
18
+ ([#603](https://github.com/benjamn/brane/pull/603)).
19
+ - Swiping the narrative's header card down dismisses it to the list;
20
+ Back returns ([#604](https://github.com/benjamn/brane/pull/604)).
21
+
22
+ Published while the repository is private, so like 0.3.0 and 0.3.1 it
23
+ carries no npm provenance attestation.
24
+
9
25
  ## 0.3.1 - 2026-10-12
10
26
 
11
27
  - The shared web app ships with the release. It serves the `latest`
@@ -34,9 +50,12 @@ travels in the npm tarball.
34
50
  repoints the fold's hook config at the running daemon
35
51
  ([#594](https://github.com/benjamn/brane/pull/594)).
36
52
  - Vulnerabilities are reported through GitHub's private vulnerability
37
- reporting (see `SECURITY.md`). This is the first release published
38
- from the public repository, so it carries npm provenance; 0.3.0 has
39
- none ([#597](https://github.com/benjamn/brane/pull/597)).
53
+ reporting (see `SECURITY.md`)
54
+ ([#597](https://github.com/benjamn/brane/pull/597)).
55
+
56
+ Like 0.3.0, published while the repository was private, so it carries
57
+ no npm provenance attestation. The copy of this entry in the 0.3.1
58
+ tarball says otherwise; it is wrong.
40
59
 
41
60
  ## 0.3.0 - 2026-10-11
42
61
 
@@ -0,0 +1,11 @@
1
+ /** Why the narrative can't be archived yet, or null when it can. */
2
+ export function archiveRefusal({ status, mcpConnected, tmuxLive }) {
3
+ if (mcpConnected)
4
+ return "its agent is still connected";
5
+ if (tmuxLive)
6
+ return "its session is still running";
7
+ if (status !== "ended")
8
+ return `its status is ${status ?? "unset"}, not ended`;
9
+ return null;
10
+ }
11
+ //# sourceMappingURL=archive-gate.js.map
@@ -22,6 +22,7 @@ import { getBraneId, getPayloadsDir, getTokenFilePath, fromPortablePath, toPorta
22
22
  import { TokenRing } from "./token-ring.js";
23
23
  import { signalEventFields, signalStanding } from "./signal-source.js";
24
24
  import { AGENT_LOOPBACK_REFUSAL, AGENT_REVIVE_REFUSAL, agentRefusal, agentReviveRefusal } from "./agent-scope.js";
25
+ import { archiveRefusal } from "./archive-gate.js";
25
26
  import { DbTokenStore, bootstrapTokens, legacyTokenWarning, parseTokenHashes, liveAgentTokenId, mintAgentToken, recordLauncher, settleAgentLaunch, verifyAgentToken } from "../db/tokens.js";
26
27
  import { closeSocketsOf, listTokensRoute, socketOwners, retireTokens } from "./token-routes.js";
27
28
  import { getConfig, resolveAppHost } from "../commands/config.js";
@@ -1381,16 +1382,34 @@ export async function startServer(config) {
1381
1382
  const narrativeId = archiveMatch[1];
1382
1383
  parseBody(req).then((body) => {
1383
1384
  const { archived } = JSON.parse(body);
1385
+ // A running narrative can't be archived: hiding a live agent from the
1386
+ // list is exactly what a rogue one would want. See archive-gate.ts.
1387
+ if (archived) {
1388
+ const row = db.prepare("SELECT status FROM narratives WHERE id = ?").get(narrativeId);
1389
+ if (!row) {
1390
+ sendJson(res, 404, { error: `No narrative ${narrativeId}` });
1391
+ return;
1392
+ }
1393
+ const refusal = archiveRefusal({
1394
+ status: row.status,
1395
+ mcpConnected: mcpConnectedNids(mcpClients).has(narrativeId),
1396
+ tmuxLive: liveTmuxSessions().has(narrativeId),
1397
+ });
1398
+ if (refusal) {
1399
+ sendJson(res, 409, { error: `Can't archive ${narrativeId}: ${refusal}. End it first.` });
1400
+ return;
1401
+ }
1402
+ }
1384
1403
  db.prepare("UPDATE narratives SET archived = ? WHERE id = ?").run(archived ? 1 : 0, narrativeId);
1385
1404
  // An archived narrative's agent token is a credential nobody needs:
1386
- // revoke it, unless its session is still running (archiving is not a
1387
- // way to cut off a live agent; revoking from the Devices list is).
1388
- // Unarchiving brings nothing back; a revive mints a fresh token.
1389
- if (archived && !liveTmuxSessions().has(narrativeId)) {
1405
+ // revoke it. Its session is over, or the gate above would have
1406
+ // refused. Unarchiving brings nothing back; a revive mints a fresh
1407
+ // token.
1408
+ if (archived) {
1390
1409
  const agentRow = liveAgentTokenId(db, narrativeId);
1391
1410
  if (agentRow) {
1392
1411
  db.prepare("UPDATE tokens SET revoked_at = ? WHERE kind = 'agent' AND owner_nid = ? AND revoked_at IS NULL").run(Date.now(), narrativeId);
1393
- // A connected external's bridge goes now, not at its next redial.
1412
+ // Any socket still holding it goes now, not at its next redial.
1394
1413
  closeSocketsOf(viewerSockets, [agentRow]);
1395
1414
  }
1396
1415
  }
@@ -74,11 +74,14 @@ export function narrativeMenuItems({ role, status, mcpConnected, archived = fals
74
74
  ? { icon: "🐦‍🔥", label: "Revive", onPress: onRevive }
75
75
  : { icon: "🫠", label: "End", onPress: onEnd },
76
76
  ]),
77
- {
78
- icon: archived ? "📂" : "🗄️",
79
- label: archived ? "Unarchive" : "Archive",
80
- onPress: onArchiveToggle,
81
- },
77
+ // Archive puts away a narrative that is over, so it waits for the session
78
+ // to end, by the same test that offers Revive. Unarchive is offered on any
79
+ // archived narrative, whatever its state.
80
+ ...(archived
81
+ ? [{ icon: "📂", label: "Unarchive", onPress: onArchiveToggle }]
82
+ : isEnded
83
+ ? [{ icon: "🗄️", label: "Archive", onPress: onArchiveToggle }]
84
+ : []),
82
85
  ];
83
86
  }
84
87
  //# sourceMappingURL=narrative-menu.js.map
@@ -0,0 +1,22 @@
1
+ import { describe, it } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { archiveRefusal } from "../daemon/archive-gate.js";
4
+ const ended = { status: "ended", mcpConnected: false, tmuxLive: false };
5
+ describe("archiveRefusal", () => {
6
+ it("allows an ended narrative with nothing running", () => {
7
+ assert.equal(archiveRefusal(ended), null);
8
+ });
9
+ it("refuses a narrative whose status is not ended", () => {
10
+ assert.ok(archiveRefusal({ ...ended, status: "active" }));
11
+ assert.ok(archiveRefusal({ ...ended, status: null }));
12
+ });
13
+ it("refuses an ended row with an agent still on the bridge", () => {
14
+ // The stale row the menu also treats as running: hiding it would hide a
15
+ // live agent.
16
+ assert.match(archiveRefusal({ ...ended, mcpConnected: true }) ?? "", /connected/);
17
+ });
18
+ it("refuses an ended row whose tmux session is still up", () => {
19
+ assert.match(archiveRefusal({ ...ended, tmuxLive: true }) ?? "", /running/);
20
+ });
21
+ });
22
+ //# sourceMappingURL=archive-gate.test.js.map
@@ -69,7 +69,6 @@ describe("narrativeMenuItems", () => {
69
69
  "Recolor",
70
70
  "Twin",
71
71
  "End",
72
- "Archive",
73
72
  ]);
74
73
  });
75
74
  it("swaps End for Revive once the session is over", () => {
@@ -93,8 +92,23 @@ describe("narrativeMenuItems", () => {
93
92
  assert.ok(labels({ role: "absorbed", status: "ended" }).includes("Revive"));
94
93
  });
95
94
  it("flips the archive item both ways", () => {
96
- assert.ok(labels({ archived: false }).includes("Archive"));
97
- assert.ok(labels({ archived: true }).includes("Unarchive"));
95
+ assert.ok(labels({ status: "ended", archived: false }).includes("Archive"));
96
+ assert.ok(labels({ status: "ended", archived: true }).includes("Unarchive"));
97
+ });
98
+ it("offers Archive only once the session has ended", () => {
99
+ const running = labels({ status: "active", mcpConnected: true });
100
+ assert.ok(!running.includes("Archive") && !running.includes("Unarchive"));
101
+ // The same stale-row test as Revive: an ended row with an agent still on
102
+ // the bridge is running, and isn't archivable yet.
103
+ assert.ok(!labels({ status: "ended", mcpConnected: true }).includes("Archive"));
104
+ assert.ok(labels({ status: "ended" }).includes("Archive"));
105
+ });
106
+ it("always offers Unarchive on an archived narrative", () => {
107
+ for (const status of ["active", "ended", null]) {
108
+ for (const mcpConnected of [true, false]) {
109
+ assert.ok(labels({ archived: true, status, mcpConnected }).includes("Unarchive"), `status: ${status}, mcpConnected: ${mcpConnected}`);
110
+ }
111
+ }
98
112
  });
99
113
  it("flips isolate by where the app is served from", () => {
100
114
  assert.ok(labels({ isIsolated: false }).includes("Isolate"));
@@ -27,7 +27,7 @@ until someone lists it. An agent also may not revive or prompt a
27
27
  | `GET` | `/api/status` | Daemon status (brane_id, hostname, username, pid, port, uptime_ms, `tls: { state, expires_at, ... }`, `app_domain`: the shared app's host, where a daemon's own bundle hops out to on Isolate — see [View URLs](view-urls.md)) |
28
28
  | `GET` | `/api/narratives?archived=1` | List narratives (excludes archived by default) |
29
29
  | `GET` | `/api/narratives/recent?since=&search=&status=&fold=&limit=&archived=1&brane_ids=` | Recently active narratives — the browse half of the `narrative_info` MCP tool; every brane unless `brane_ids` scopes it |
30
- | `PATCH` | `/api/narratives/:id/archive` | Archive/unarchive a narrative |
30
+ | `PATCH` | `/api/narratives/:id/archive` | Archive/unarchive a narrative; archiving a running one is a 409 (`src/daemon/archive-gate.ts`) |
31
31
  | `GET` | `/api/narratives/:id/events?after=N&before=S&tail=T` | Fetch events with cursor-based query |
32
32
  | `POST` | `/api/narratives/:id/signal` | Send operator signal (supports payloads). `source` is stamped from the token (`web` for a device, `local` for this account); a `source` in the body is ignored, and an agent's token is refused (`src/daemon/signal-source.ts`) |
33
33
  | `GET` | `/api/narratives/:id/export?format=html[&palette=N][&seqs=A,B,C][&seqs_mode=except]` | Conversation as a standalone HTML document; `palette` is the device's 🎨 Recolor salt, so foreign speakers wear the hues the operator sees, `seqs` is the chat's message selection, and `seqs_mode=except` exports its complement — see [Export Scope](export-scope.md) |
package/docs/mcp.md CHANGED
@@ -66,4 +66,4 @@ Core tools available via MCP:
66
66
 
67
67
  Narratives have persistent `summary` and `title` columns. Agents set them via the `meta` parameter on `narrate`. The daemon broadcasts metadata changes over the control WebSocket as `type: "meta"` messages. The Expo app renders the summary as a subtitle below the narrative ID.
68
68
 
69
- Narratives can be **archived** via `PATCH /api/narratives/:id/archive`. Archived narratives are hidden from the default list but preserved in the database.
69
+ Narratives can be **archived** via `PATCH /api/narratives/:id/archive`. Archived narratives are hidden from the default list but preserved in the database. Only a narrative whose session is over can be archived: the daemon answers 409 while its status isn't `ended`, an agent is on its bridge, or its tmux session is up (`src/daemon/archive-gate.ts`), so archiving can't hide a running agent. Unarchiving is never refused.
package/docs/releasing.md CHANGED
@@ -9,10 +9,12 @@ publishing](https://docs.npmjs.com/trusted-publishers)). **Agents never run
9
9
  `npm publish` is not passed `--provenance`, and needs no flag for it.
10
10
  Trusted publishing attests a build by itself when the repository is public
11
11
  and leaves attestation out when it is private, where `--provenance` would
12
- fail the publish on a 422. 0.3.0 was published while the repository was still
13
- private, so it is the one release with **no provenance attestation**; every
14
- release since the repository went public carries it, with no workflow
15
- change.
12
+ fail the publish on a 422. 0.3.0 and 0.3.1 were published while the
13
+ repository was still private, so they carry **no provenance attestation**;
14
+ every release after the repository goes public will, with no workflow
15
+ change. Check `gh repo view --json visibility` before a release's notes
16
+ say which it is: the 0.3.1 CHANGELOG entry in its tarball claims
17
+ provenance it does not have.
16
18
 
17
19
  The trigger is a **published GitHub release**, not a tag push, so the release
18
20
  notes and the publish are one act and a stray tag cannot publish anything.
@@ -208,8 +208,10 @@ Cline's per-session files) meant no harness's plumbing had to change.
208
208
  nothing. A connected external client (no tmux session) is not adopted,
209
209
  and lands on a fresh `external-*` narrative once, at the upgrade.
210
210
  Adopted agent rows don't trigger the plaintext-token warning.
211
- - **Archiving revokes** a narrative's agent token when its session is not
212
- running. Unarchiving brings nothing back; a revive mints a new one.
211
+ - **Archiving revokes** a narrative's agent token. Only an ended narrative
212
+ can be archived (the daemon answers 409 otherwise; see
213
+ `src/daemon/archive-gate.ts`), so there is never a live session to cut
214
+ off. Unarchiving brings nothing back; a revive mints a new one.
213
215
  - **An external goes with its dialer, always.** An external's token
214
216
  records the token that dialed it (`minted_by`); it is that token's
215
217
  credential in another form, since one `/ws/mcp` dial mints it, so
package/docs/view-urls.md CHANGED
@@ -57,7 +57,12 @@ since the stack did not grow. So the URL keeps that state and Back returns to
57
57
  it, but it never costs an extra Back: browsing ten files is one entry, not ten.
58
58
  A bare link to the narrative you are in, with no seq, goes nowhere. The list
59
59
  is a jump too: **All narratives** in the switcher pushes it, so Back returns
60
- to the narrative, whether or not a list was already beneath. The header has no
60
+ to the narrative, whether or not a list was already beneath. So does a
61
+ swipe down on the narrative's header card, which dismisses it. So does
62
+ **Archive** in the narrative's 🦠 menu, once the daemon has confirmed it (the
63
+ pushed list fetches on mount, and nothing is broadcast to correct a fetch that
64
+ raced the archive); Back returns to the archived narrative. Archiving from the
65
+ list's own menu just drops the row and goes nowhere. The header has no
61
66
  ← of its own; Back is the browser's.
62
67
 
63
68
  Back is instant and complete because the Stack keeps the screens behind the
package/docs/web-app.md CHANGED
@@ -13,7 +13,7 @@ The Expo app runs as a web PWA served by the daemon (and optionally via Cloudfla
13
13
  - **Quick bar** — macros (via MacroMenu component) + quick keys
14
14
  - **Full software keyboard** — multitouch with sticky/held modifiers
15
15
  - **Live updates** — control WebSocket pushes `status`, `meta`, and `new_events` hints
16
- - **Archive/unarchive** — swipe or long-press to archive narratives
16
+ - **Archive/unarchive** — from the 🦠 menu, on a list card's status badge or in the narrative's header. Archive is offered only once the session has ended (the same test that swaps End for Revive); Unarchive on any archived narrative. Archiving from the header goes to the list as a jump, so Back returns — see [View URLs](view-urls.md)
17
17
  - **Payload rendering** — inline display of image payloads in chat
18
18
  - **Export** — download a narrative as standalone HTML via `/api/narratives/:id/export?format=html`. Foreign rows carry their speaker's hue inline, from the same `speakerColor` / `speakerBgColor` the chat uses, at the 🎨 Recolor salt the device sends as `&palette=` — the one place the salt leaves the browser. With messages selected, the menu offers both sides of the selection — **those messages only**, or the conversation with **those messages left out** — see [Export Scope](export-scope.md)
19
19
  - **Brane switcher** — dropdown to filter narratives by brane, add/switch daemons. Each brane row (and "All branes") shows its running metered cost as `$2441.72 (138) + 100.2 AIC (1)` — one total per unit with the number of sessions it covers, so a per-session figure can be read off without the line asserting one; the list screen re-reads `/api/branes` (debounced) when a cost `meta` arrives, since the total includes archived narratives the screen never loads. **Devices** lists every token on the active daemon (this device, this machine's CLI and agents, each melded device by browser, platform, address and when it was last seen, and any meld QR not yet scanned) with a Revoke on each other device; **Sign out other devices**, at the foot of that list, rotates instead — see [Token Rotation](token-rotation.md#the-devices-list)
@@ -23,7 +23,7 @@ __d(function(g,r,i,a,m,e,d){
23
23
  "use strict";var n=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function o(t,o,f){var l=null;if(void 0!==f&&(l=""+f),void 0!==o.key&&(l=""+o.key),"key"in o)for(var y in f={},o)"key"!==y&&(f[y]=o[y]);else f=o;return o=f.ref,{$$typeof:n,type:t,key:l,ref:void 0!==o?o:null,props:f}}e.Fragment=t,e.jsx=o,e.jsxs=o},7,[]);
24
24
  __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),Object.defineProperty(e,"ctx",{enumerable:!0,get:function(){return t}});const t=r(d[0])},8,[9]);
25
25
  __d(function(g,r,i,a,m,e,d){const t=Object.defineProperties({},{"./[nid].tsx":{enumerable:!0,get:()=>r(d[0])},"./_layout.tsx":{enumerable:!0,get:()=>r(d[1])},"./index.tsx":{enumerable:!0,get:()=>r(d[2])}});function n(n){return t[n]}n.keys=function(){return Object.keys(t)},n.resolve=function(t){throw new Error('Unimplemented Metro module context functionality')},m.exports=n},9,[10,736,981]);
26
- __d(function(g,r,_i,_a,_m,_e,_d){"use strict";function e(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(_e,'__esModule',{value:!0}),Object.defineProperty(_e,"default",{enumerable:!0,get:function(){return le}});var t=r(_d[0]),n=e(r(_d[1])),o=e(r(_d[2])),a=e(r(_d[3])),l=e(r(_d[4]));r(_d[5]);var s=e(r(_d[6])),i=e(r(_d[7])),c=e(r(_d[8])),u=e(r(_d[9]));r(_d[10]);var d=r(_d[11]),f=r(_d[12]),h=r(_d[13]),b=r(_d[14]),m=e(r(_d[15])),p=e(r(_d[16])),y=e(r(_d[17])),v=r(_d[18]),x=r(_d[19]),w=r(_d[20]),S=r(_d[21]),C=r(_d[22]),T=r(_d[23]),j=r(_d[24]),R=e(r(_d[25])),k=r(_d[26]),P=r(_d[27]),A=r(_d[28]),I=r(_d[29]),_=e(I),E=e(r(_d[30])),L=e(r(_d[31])),M=e(r(_d[32])),N=r(_d[33]),z=r(_d[34]),q=r(_d[35]),$=r(_d[36]),F=r(_d[37]),B=r(_d[38]),H=r(_d[39]),O=r(_d[40]);function D(e,t=!1){const n=new Date(e),o=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][n.getDay()],a=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"][n.getMonth()],l=n.getDate(),s=n.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"});if(t)return`${o} ${a} ${l}, ${n.getFullYear()} ${s}`;const i=new Date,c=n.getFullYear()===i.getFullYear();return c&&n.getMonth()===i.getMonth()&&n.getDate()===i.getDate()?`${o} ${s}`:c?`${o} ${a} ${l} ${s}`:`${o} ${a} ${l}, ${n.getFullYear()} ${s}`}function W(e){return"agent_signal"===e}const G=(0,t.memo)(function({uri:e,onPress:n}){const[o,l]=(0,t.useState)(null);(0,t.useEffect)(()=>{a.default.getSize(e,(e,t)=>l({w:e,h:t}),()=>l({w:200,h:150}))},[e]);const i=o?Math.min(200/o.w,150/o.h):1,c=o?Math.round(o.w*i):200,u=o?Math.round(o.h*i):150;return(0,O.jsx)(s.default,{onPress:n,children:(0,O.jsx)(a.default,{source:{uri:e},style:{width:c,height:u,borderRadius:8},resizeMode:"cover"})})}),U=(0,t.memo)(function({item:e,nid:t,agentType:a,foldPath:l,conn:i,selection:c,palette:u=0,onImagePress:d,onForeignPress:f,onFilePress:h,fileHref:m,onTimestampPress:p}){const y=(0,w.useIsSelected)(c,e.seq),v="human_signal"===e.type;const x=W(e.type),C=(0,z.isSystemEvent)(e.type),T=i&&e.payloads?e.payloads.filter(b.isInlinePayload):[],j=i&&e.payloads?e.payloads.filter(e=>!(0,b.isInlinePayload)(e)):[],R=(0,O.jsxs)(O.Fragment,{children:[(e.source||C)&&(0,O.jsxs)(n.default,{style:se.bubbleSourceRow,children:[x&&e.source&&(0,O.jsx)(s.default,{onPress:()=>f?.(e.source,e.time),style:se.bubbleSourcePress,children:(0,O.jsx)(o.default,{style:[se.bubbleSource,se.bubbleSourceLink,{color:(0,S.speakerColor)(e.source,u)}],children:e.source})}),(0,O.jsx)(s.default,{onPress:()=>p?.(e.seq),style:[se.bubbleSourcePress,x&&se.bubbleSourceAfterLink],children:(0,O.jsx)(o.default,{style:[se.bubbleSource,x&&e.source&&{color:(0,S.speakerColor)(e.source,u)},C&&se.bubbleSourceSystem],children:C?`system (${t}:${e.seq})`:v?`you (${t}:${e.seq})`:x?`(${t}:${e.seq})`:`${e.source}:${e.seq}`})}),(0,O.jsx)(L.default,{text:`${t}:${e.seq}`,size:9,padding:3,marginLeft:1,translateY:-1})]}),e.content?(0,O.jsx)(k.MarkdownContent,{content:C?(0,z.systemLine)({type:e.type,content:e.content},{agent:a??(0,z.agentTypeOf)(t),fold:l}):e.content,foreign:x,system:C,onFilePress:h,fileHref:m}):null,T.length>0&&i&&(0,O.jsx)(n.default,{style:se.payloadsContainer,children:T.map(e=>(0,O.jsx)(G,{uri:(0,b.payloadUrl)(i,e),onPress:()=>d?.((0,b.payloadUrl)(i,e))},e))}),j.length>0&&i&&(0,O.jsx)(n.default,{style:se.payloadsContainer,children:j.map(e=>{const t=(0,A.downloadNameFor)(e),n=(0,b.payloadUrl)(i,e);return(0,O.jsx)(s.default,{onPress:()=>{"undefined"!=typeof window&&(0,A.downloadUrl)(n,t).catch(e=>console.error("Payload download failed:",e))},style:se.filePayload,children:(0,O.jsx)(o.default,{style:se.filePayloadText,children:t})},e)})}),(0,O.jsx)(s.default,{onPress:()=>p?.(e.seq),style:se.bubbleTimePress,children:(0,O.jsx)(o.default,{style:se.bubbleTime,children:D(e.time)})})]}),P=[se.bubble,C?se.bubbleSystem:v?se.bubbleOperator:x?[se.bubbleForeign,{backgroundColor:(0,S.speakerBgColor)(e.source||"unknown",u)}]:se.bubbleAgent,y&&se.bubbleSelected];return(0,O.jsx)(n.default,{style:[se.bubbleRow,v?se.bubbleRowRight:x||C?se.bubbleRowCenter:se.bubbleRowLeft],children:(0,O.jsx)(n.default,{dataSet:{bubble:String(e.seq)},style:P,children:R})})}),X=(0,t.memo)(function({conn:e,nid:l,loadEvents:i,chatActive:c,selection:u,onDeselect:d}){const h=(0,w.useSelectedSeqs)(u),[m,p]=(0,t.useState)(!1),[y,v]=(0,t.useState)(!1),[x,S]=(0,t.useState)([]),C=(0,t.useRef)(null),T=(0,t.useRef)(null),j=(0,t.useRef)(!1),R=(0,t.useRef)(!1),k=(0,f.useIsFocused)(),P=c&&k;R.current=P;const A=(0,t.useRef)(""),I=(0,t.useRef)(null),_=`brane:draft:${l}`;(0,t.useEffect)(()=>{try{const e=localStorage.getItem(_);if(e&&(A.current=e,v(e.trim().length>0),T.current)){T.current.value=e}}catch{}return()=>{I.current&&clearTimeout(I.current);try{const e=A.current;e.trim()?localStorage.setItem(_,e):localStorage.removeItem(_)}catch{}}},[_]);const E=(0,t.useCallback)(e=>{A.current=e;const t=0===e.trim().length;v(e=>e===!t?e:!t),I.current&&clearTimeout(I.current),I.current=setTimeout(()=>{try{e.trim()?localStorage.setItem(_,e):localStorage.removeItem(_)}catch{}},300)},[_]);(0,t.useEffect)(()=>{const e=T.current;if(!e)return;if(!P)return void(document.activeElement===e&&e.blur());if(!window.matchMedia?.("(pointer: fine)").matches)return;const t=requestAnimationFrame(()=>{try{e.focus({preventScroll:!0})}catch{e.focus()}});return()=>cancelAnimationFrame(t)},[P]),(0,t.useEffect)(()=>{if(!P)return;const e=e=>{if(!R.current)return;const t=e.target,n=t?.tagName;if("INPUT"===n||"TEXTAREA"===n||t?.isContentEditable)return;if(e.metaKey||e.ctrlKey||e.altKey)return;if(e.isComposing)return;if(1!==e.key.length)return;const o=T.current;if(!o)return;e.preventDefault();const a=(o.value||"")+e.key;o.value=a,o.focus({preventScroll:!0});try{o.setSelectionRange(a.length,a.length)}catch{}E(a)};return document.addEventListener("keydown",e),()=>document.removeEventListener("keydown",e)},[P,E]),(0,t.useEffect)(()=>{if(!k)return;const e=e=>{const t=e.clipboardData?.items;if(t)for(const e of Array.from(t)){if(!e.type.startsWith("image/"))continue;const t=e.getAsFile();if(!t)continue;const n=new FileReader;n.onload=()=>{const e=n.result,o=e.split(",")[1],a=t.type.split("/")[1]||"png";S(t=>[...t,{id:`${Date.now()}_${Math.random().toString(36).slice(2,6)}`,filename:`paste_${Date.now()}.${a}`,data:o,uri:e}])},n.readAsDataURL(t)}};return document.addEventListener("paste",e),()=>document.removeEventListener("paste",e)},[k]);const L=(0,t.useCallback)(()=>{if(!C.current){const e=document.createElement("input");e.type="file",e.accept="*/*",e.multiple=!0,e.style.display="none",e.addEventListener("change",()=>{const t=e.files;if(t){for(const e of Array.from(t)){const t=new FileReader;t.onload=()=>{const n=t.result,o=n.split(",")[1];S(t=>[...t,{id:String(Date.now())+e.name,filename:e.name,data:o,uri:n}])},t.readAsDataURL(e)}e.value=""}}),document.body.appendChild(e),C.current=e}C.current.click()},[]);(0,t.useEffect)(()=>()=>{C.current&&(C.current.remove(),C.current=null)},[]);const M=(0,t.useCallback)(e=>{S(t=>t.filter(t=>t.id!==e))},[]),N=(0,t.useCallback)(async()=>{const t=A.current.trim();if(!e||!l||!t&&0===x.length)return;const n=x.length>0?x.map(e=>({filename:e.filename,data:e.data})):void 0;p(!0),S([]);try{await(0,b.sendSignal)(e,l,t||"(attachment)","web",n,[...h]),h.length>0&&d(),A.current="",v(!1);try{localStorage.removeItem(_)}catch{}if(T.current){const e=T.current;"function"==typeof e.clear?e.clear():e.value=""}j.current=!0,i()}catch{}finally{p(!1)}},[e,l,_,x,h,d,i]);return(0,t.useEffect)(()=>{if(m)return;if(!j.current)return;if(j.current=!1,!R.current)return;const e=T.current;if(e)try{e.focus({preventScroll:!0})}catch{e.focus()}},[m]),(0,O.jsxs)(O.Fragment,{children:[x.length>0&&(0,O.jsx)(n.default,{style:se.pendingPayloadsRow,dataSet:{composer:"1"},children:x.map(e=>(0,O.jsxs)(n.default,{style:se.pendingPayloadThumb,children:[(0,b.isInlinePayload)(e.filename)?(0,O.jsx)(a.default,{source:{uri:e.uri},style:se.pendingPayloadImage,resizeMode:"cover"}):(0,O.jsx)(n.default,{style:[se.pendingPayloadImage,{justifyContent:"center",alignItems:"center",backgroundColor:"rgba(255,255,255,0.1)"}],children:(0,O.jsx)(o.default,{style:{color:"#aaa",fontSize:10},numberOfLines:2,children:e.filename.split(".").pop()})}),(0,O.jsx)(s.default,{style:se.pendingPayloadRemove,onPress:()=>M(e.id),children:(0,O.jsx)(o.default,{style:se.pendingPayloadRemoveText,children:"\xd7"})})]},e.id))}),(0,O.jsxs)(n.default,{style:se.inputRow,dataSet:{composer:"1"},children:[(0,O.jsx)(s.default,{onPress:L,accessibilityLabel:"Attach file",style:({hovered:e,pressed:t})=>[se.attachButton,(e||t)&&se.circleGlowActive],children:(0,O.jsx)(o.default,{style:se.attachText,children:"\ud83e\uddeb"})}),(0,O.jsx)("textarea",{ref:T,style:{flex:1,backgroundColor:"#111",color:"#e0e0e0",borderRadius:20,paddingLeft:16,paddingRight:16,paddingTop:6,paddingBottom:6,fontSize:16,border:"1px solid #555",resize:"none",overflow:"auto",maxHeight:120,fieldSizing:"content",fontFamily:"system-ui, -apple-system, sans-serif",outline:"none",lineHeight:"22px",boxSizing:"border-box"},onChange:e=>E(e.target.value),placeholder:"Compose message...",disabled:m,autoComplete:"off",autoCorrect:"on",spellCheck:!0,inputMode:"text",rows:1}),(0,O.jsx)(s.default,{style:[se.sendButton,!m&&(y||x.length>0)&&se.circleGlowSend],onPress:N,disabled:m||!y&&0===x.length,children:(0,O.jsx)(o.default,{style:[se.sendText,(m||!y&&0===x.length)&&se.sendTextInactive],children:"\ud83e\udd8b"})})]})]})}),Y=(0,t.memo)(function({nid:e,narrativeSummary:a,narrativeFoldPath:l,narrativeRole:i,narrativeStatus:c,narrativeMcpConnected:u,narrativeAwaiting:d,palette:f,narrativeCreatedAt:h,narrativeLastActivity:b,cost:m,archived:p,selection:S,openSwitcher:C,onDownload:R,onTerminate:k,onRevive:P,onTwin:A,onArchiveToggle:I,onRecolor:_,onShowQr:E,onIsolateDaemon:L,isIsolated:M,canIsolate:N}){const[z,q]=(0,t.useState)(!1),$=(0,w.useSelectedSeqs)(S).length,F=!!(i||l||h),B=(0,x.isAwaiting)({mcpConnected:u,awaiting:d})?(0,x.awaitingGlow)((0,T.glowHueFor)(e)):void 0;return(0,O.jsxs)(n.default,{style:[se.header,se.glowTransition,B?{boxShadow:B}:null],children:[(0,O.jsxs)(s.default,{style:se.headerTitleContainer,onPress:C,children:[(0,O.jsx)(j.NarrativeIdentity,{id:e,foldPath:l,align:"center"}),F?(0,O.jsx)(j.NarrativeMetaLine,{role:i,cost:m,createdAt:h??void 0,lastActivity:b,status:c,mcpConnected:u,style:{marginTop:4}}):null,a?(0,O.jsx)("div",{style:{position:"relative",marginRight:8},children:(0,O.jsx)("div",{className:"no-scrollbar",style:{overflowX:"auto",overflowY:"hidden",scrollbarWidth:"none",WebkitOverflowScrolling:"touch",maskImage:"linear-gradient(to right, #000 calc(100% - 60px), transparent)",WebkitMaskImage:"linear-gradient(to right, #000 calc(100% - 60px), transparent)"},children:(0,O.jsx)(o.default,{style:se.headerSummary,children:a})})}):null]}),(0,O.jsxs)("div",{style:{position:"relative"},children:[(0,O.jsx)(s.default,{onPress:()=>q(e=>!e),style:se.reloadButton,hitSlop:8,children:(0,O.jsx)(o.default,{style:[se.reloadText,z&&se.reloadTextActive],children:"\ud83e\udda0"})}),z&&(0,O.jsx)(y.default,{items:(0,v.narrativeMenuItems)({role:i,status:c,mcpConnected:u,archived:p,isIsolated:M,canIsolate:N,selectedCount:$,onMeld:()=>{q(!1),E()},onIsolate:()=>{q(!1),L()},onExport:e=>{q(!1),R(e)},onRecolor:()=>{q(!1),_()},onTwin:()=>{q(!1),A()},onRevive:()=>{q(!1),P()},onEnd:()=>{q(!1),k()},onArchiveToggle:()=>{q(!1),I()}}),onClose:()=>q(!1)})]})]})}),V={headerShown:!1},J=new Map;function K(e){return null!=e.cost_amount&&e.cost_unit?{amount:e.cost_amount,unit:e.cost_unit}:null}const Q=300,Z={flex:1,minHeight:0,display:"flex",flexDirection:"column-reverse",overflowY:"auto",overflowX:"hidden"},ee={marginBottom:"auto"},te=.3;function ne(e,t){const n=e?.querySelector(`[data-seq="${t}"]`);if(!e||!n)return!1;const o=n.getBoundingClientRect().top-e.getBoundingClientRect().top;return e.scrollTop+=o-e.clientHeight*te,!0}const re='button, a[href], [role="button"], [role="link"], [role="menuitem"]';function oe(e){return e?J.get(e)??{}:{}}function ae(e,t){const n=J.get(e)??{};J.set(e,Object.assign({},n,t))}function le(){const e=(0,f.useIsFocused)(),{nid:y,scrollTo:S,scrollToSeq:k,tab:A,pinned:L,path:z,line:D}=(0,d.useLocalSearchParams)(),W=(0,d.useRouter)(),{conn:G,subscribe:J,unsubscribe:te,onHint:le,onMeta:ie,onStatus:ce,onToolUses:ue,narrativeIds:de}=(0,h.useBrane)(),[fe,he]=(0,t.useState)([]),[ge,be]=(0,t.useState)(()=>new Map),me=(0,t.useRef)(0),pe=(0,t.useRef)(Number.MAX_SAFE_INTEGER),[ye,ve]=(0,t.useState)(()=>z??""),[xe,we]=(0,t.useState)(()=>(0,F.parseLineSpec)(D).line),[Se,Ce]=(0,t.useState)(()=>(0,F.parseLineSpec)(D).lineEnd),Te=y?`brane:files:${y}`:null,je=y?`brane:tabs:${y}`:null,Re=(0,t.useRef)(null),[ke,Pe]=(0,t.useState)(()=>(0,F.parseActiveTab)(A)),[Ae,Ie]=(0,t.useState)(()=>(0,F.parsePinnedTabs)(L)),Ee=(0,t.useRef)(y??null);(0,t.useEffect)(()=>{if(!y)return;if(Ee.current===y)return;Ee.current=y;const e=(0,F.parseLineSpec)(D);ve(z??""),we(e.line),Ce(e.lineEnd)},[y]);const Le=(0,t.useRef)(null);(0,t.useEffect)(()=>{if(!Te||!y)return;if(Le.current===y)return;if(Le.current=y,z)return;let e=null;try{e=sessionStorage.getItem(Te)}catch{return}if(!e)return;let t=null;try{t=JSON.parse(e)}catch{}if(!t?.path)return;ve(t.path),we(t.line),Ce(t.lineEnd);const n=t.line?t.lineEnd&&t.lineEnd>t.line?`${t.line}-${t.lineEnd}`:String(t.line):void 0;W.setParams({path:t.path,line:n})},[y]),(0,t.useEffect)(()=>{if(Te)try{if(ye){const e={path:ye};xe&&(e.line=xe),Se&&(e.lineEnd=Se),sessionStorage.setItem(Te,JSON.stringify(e))}else sessionStorage.removeItem(Te)}catch{}},[Te,ye,xe,Se]),(0,t.useEffect)(()=>{if(je&&Re.current===y)try{sessionStorage.setItem(je,JSON.stringify({tab:ke,pinned:(0,F.serializePinned)(Ae)}))}catch{}},[je,y,ke,Ae]);const Me=(0,t.useMemo)(()=>(0,H.visiblePanes)(ke,Ae),[ke,Ae]),Ne=(0,t.useMemo)(()=>{const e=e=>{const t=Me.indexOf(e),n=Me.length;return t<0||1===n?{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:t<0?0:1,backgroundColor:"#111",pointerEvents:t<0?"none":"auto"}:{position:"absolute",top:0,bottom:0,left:t/n*100+"%",width:100/n+"%",zIndex:1,backgroundColor:"#111",borderLeftWidth:t>0?c.default.hairlineWidth:0,borderLeftColor:"#555"}};return{chat:e("chat"),terminal:e("terminal"),files:e("files")}},[Me]),ze=1===Me.length,[qe,$e]=(0,t.useState)(null),[Fe,Be]=(0,t.useState)(!1),[He,Oe]=(0,t.useState)(!1),[De,We]=(0,t.useState)(()=>oe(y).summary??null),[Ge,Ue]=(0,t.useState)(()=>oe(y).agent_type??null),[Xe,Ye]=(0,t.useState)(()=>oe(y).role??null),[Ve,Je]=(0,t.useState)(()=>oe(y).archived??!1),[Ke,Qe]=(0,t.useState)(()=>oe(y).fold_path??null),[Ze,et]=(0,t.useState)(()=>oe(y).status??null),[tt,nt]=(0,t.useState)(()=>oe(y).mcp_connected??!1),[rt,ot]=(0,t.useState)(!1),[at,lt]=(0,t.useState)(()=>oe(y).created_at??null),[st,it]=(0,t.useState)(()=>oe(y).last_activity??null),[ct,ut]=(0,t.useState)(()=>K(oe(y)));(0,t.useEffect)(()=>{const e=oe(y);We(e.summary??null),Ue(e.agent_type??null),Ye(e.role??null),Je(e.archived??!1),Qe(e.fold_path??null),et(e.status??null),nt(e.mcp_connected??!1),ot(!1),lt(e.created_at??null),it(e.last_activity??null),ut(K(e))},[y]);const[dt,ft]=(0,t.useState)(!1),[ht,gt]=(0,t.useState)([]),[bt,mt]=(0,t.useState)(!1),[pt,yt]=(0,t.useState)(null),vt=(0,t.useMemo)(()=>(0,q.collectKnownNids)({viewing:y,pushed:[...de].map(e=>({id:e})),listed:pt}),[y,de,pt]),xt=(0,w.useMessageSelection)(y),wt=(0,t.useRef)(0),[St,Ct]=(0,t.useState)(()=>(0,C.readRecolorSalt)(y));(0,t.useEffect)(()=>Ct((0,C.readRecolorSalt)(y)),[y]);const Tt=(0,t.useCallback)(()=>{(0,T.recolorGlowHue)(y),Ct((0,C.bumpRecolorSalt)(y))},[y]),jt=(0,t.useRef)(null),Rt=(0,t.useRef)(null),kt=(0,t.useRef)(!1),Pt=(0,t.useRef)(!0),[At,It]=(0,t.useState)(!0),[_t,Et]=(0,t.useState)(!0),[Lt,Mt]=(0,t.useState)(!0),Nt=(0,t.useRef)(null),zt=(0,t.useRef)(null),qt=(0,t.useRef)(!0);qt.current=Me.includes("chat");const $t=(0,t.useRef)(0),Ft=(0,t.useRef)(S?Number(S):0),Bt=(0,t.useRef)(k?Number(k):0),Ht=(0,t.useRef)(!1),[Ot,Dt]=(0,t.useState)(!1),[Wt,Gt]=(0,t.useState)(!0),Ut=(0,t.useRef)(!1),Xt=(0,t.useRef)(!1),Yt=(0,t.useRef)(null),Vt=(0,t.useRef)(!1),Jt=(0,t.useRef)(!1);(0,t.useEffect)(()=>{if(Me.includes("chat")&&!Vt.current){const e=Bt.current,t=Ft.current;if((e||t)&&0===fe.length)return;Vt.current=!0,$t.current=Date.now();let n=-1;if(e&&fe.length>0)n=fe.findIndex(t=>t.seq===e),n>=0&&xt.replace([e]),Bt.current=0;else if(t&&fe.length>0){let e=1/0;for(let o=0;o<fe.length;o++){const a=Math.abs(fe[o].time-t);a<e&&(e=a,n=o)}Ft.current=0}if(n>=0){Xt.current=!0;const e=setTimeout(()=>{Xt.current=!1},2e3);return ne(jt.current,fe[n].seq),()=>clearTimeout(e)}Pt.current=!0,It(!0)}Me.includes("terminal")&&(Jt.current=!0)},[Me,fe.length]);const Kt=(0,t.useCallback)(()=>{jt.current?.scrollTo({top:0})},[]),Qt=(0,t.useCallback)(()=>{const e=jt.current;e?.scrollTo({top:-e.scrollHeight,behavior:"smooth"})},[]),Zt=(0,t.useRef)(!1),en=(0,t.useRef)(!1),tn=(0,t.useCallback)(async()=>{if(G&&y)if(Zt.current)en.current=!0;else{Zt.current=!0;try{do{en.current=!1;const e=await(0,b.fetchEvents)(G,y,wt.current);e.events.length>0&&(he(t=>{const n=t.length>0?t[t.length-1].seq:0,o=e.events.filter(e=>e.seq>n);return o.length>0?[...t,...o]:t}),wt.current=e.events[e.events.length-1].seq)}while(en.current)}finally{Zt.current=!1}}},[G,y]),nn=(0,t.useCallback)(async()=>{if(G&&y&&!Ut.current&&Wt){Ut.current=!0;try{const e=fe.length>0?fe[0].seq:1/0,t=await(0,b.fetchEventsBefore)(G,y,e,50);t.events.length>0&&he(e=>{const n=e.length>0?e[0].seq:1/0,o=t.events.filter(e=>e.seq<n);return o.length>0?[...o,...e]:e}),(t.events.length<50||t.events.length>0&&t.events[0].seq<=t.min_seq)&&Gt(!1)}finally{Ut.current=!1}}},[G,y,fe,Wt]),rn=(0,t.useCallback)(e=>{0!==e.length&&be(t=>{let n=null;for(const o of e){const e=(n??t).get(o.dedup_key);e&&e.rev>=o.rev||(n||(n=new Map(t)),n.set(o.dedup_key,o),o.rev>me.current&&(me.current=o.rev))}return n??t})},[]);(0,t.useEffect)(()=>{if(!G||!y||0===fe.length)return;const e=Math.max(0,fe[0].seq-1),t=pe.current;e>=t||(pe.current=e,(0,b.fetchAllToolUseWindow)(G,y,{afterSeqGte:e,afterSeqLt:t===Number.MAX_SAFE_INTEGER?void 0:t},rn).catch(()=>{pe.current=Number.MAX_SAFE_INTEGER}))},[G,y,fe,rn]),(0,t.useEffect)(()=>{if(G&&y)return ue((e,t,n)=>{e===y&&(t?rn(t):(0,b.fetchAllToolUsesSince)(G,y,me.current,rn).catch(()=>{pe.current=Number.MAX_SAFE_INTEGER}))})},[G,y,ue,rn]),(0,t.useEffect)(()=>{if(!G||!y)return;const e=`${G.host}|${G.token}|${y}`;if(Yt.current===e)return;Yt.current=e,he([]),Gt(!0),wt.current=0,be(new Map),me.current=0,pe.current=Number.MAX_SAFE_INTEGER;const t=Bt.current;Ft.current;(async()=>{try{if(t){const e=Math.floor(25),n=Math.max(0,t-e-1),o=await(0,b.fetchEvents)(G,y,n,50);o.events.length>0?(he(o.events),wt.current=o.events[o.events.length-1].seq,Gt(o.events[0].seq>1)):(wt.current=o.seq,Gt(!1))}else{const e=await(0,b.fetchEventsBefore)(G,y,Number.MAX_SAFE_INTEGER,50);e.events.length>0?(he(e.events),wt.current=e.events[e.events.length-1].seq,(e.events.length<50||e.events[0].seq<=e.min_seq)&&Gt(!1)):(wt.current=0,Gt(!1))}}catch{tn()}})()},[G,y]);const on=(0,t.useCallback)(e=>{if(!y)return;e.summary&&(We(e.summary),ae(y,{summary:e.summary})),e.agent_type&&(Ue(e.agent_type),ae(y,{agent_type:e.agent_type})),e.role&&(Ye(e.role),ae(y,{role:e.role})),Qe(e.fold_path??null),ae(y,{fold_path:e.fold_path??null});const t=!!e.archived;Je(t),ae(y,{archived:t}),e.status&&(et(e.status),ae(y,{status:e.status}));const n=!!e.mcp_connected;nt(n),ae(y,{mcp_connected:n}),ot(!!e.awaiting),lt(e.created_at??null),ae(y,{created_at:e.created_at}),it(e.last_activity??null),ae(y,{last_activity:e.last_activity??null}),ut(K({cost_amount:e.cost_amount,cost_unit:e.cost_unit})),ae(y,{cost_amount:e.cost_amount??null,cost_unit:e.cost_unit??null})},[y]);(0,t.useEffect)(()=>{G&&y&&(0,b.fetchNarrative)(G,y).then(on).catch(()=>{})},[G,y,on]),(0,t.useEffect)(()=>{G&&y&&(0,b.fetchNarratives)(G,{archived:!0}).then(e=>{yt(e);const t=e.find(e=>e.id===y);t&&on(t)}).catch(e=>{console.warn("narrative list sweep failed; linkifying from pushed ids only",e)})},[G,y,on]),(0,t.useEffect)(()=>{if(!y)return;J(y,wt.current);const e=le((e,t)=>{if(e===y){tn();const e=Date.now();it(e),ae(y,{last_activity:e})}});return()=>{te(y),e()}},[y,J,te,le,tn]),(0,t.useEffect)(()=>{if(y)return ie((e,t,n,o)=>{e===y&&(n&&(We(n),ae(y,{summary:n})),null!=o&&(ut(o),ae(y,{cost_amount:o.amount,cost_unit:o.unit})))})},[y,ie]),(0,t.useEffect)(()=>{if(y)return ce((e,t)=>{e===y&&("mcp_connected"===t?(nt(!0),ae(y,{mcp_connected:!0})):"mcp_disconnected"===t?(nt(!1),ot(!1),ae(y,{mcp_connected:!1})):t===x.AWAITING_STATUS||t===x.NOT_AWAITING_STATUS?ot(t===x.AWAITING_STATUS):"active"!==t&&"ended"!==t||(et(t),ae(y,{status:t})))})},[y,ce]);const an=(0,t.useCallback)(async e=>{G&&y&&("all"!==e?await(0,v.openNarrativeExport)(G,y,[...xt.getSelected()],"excluded"===e?"except":"only"):await(0,v.openNarrativeExport)(G,y))},[G,y,xt]),ln=(0,t.useCallback)(async()=>{if(Pt.current)Ht.current=!0,Pt.current=!1,It(!1),Qt(),setTimeout(()=>{Ht.current=!1},600);else{const e=setTimeout(()=>Dt(!0),150);try{await tn()}finally{clearTimeout(e),Dt(!1)}Pt.current=!0,It(!0),Kt()}},[tn,Kt,Qt]),sn=(0,t.useCallback)(()=>{_t?Nt.current?.scrollToTop():Nt.current?.scrollToBottom()},[_t]),cn=(0,t.useCallback)(()=>{Lt?zt.current?.scrollToTop():zt.current?.scrollToBottom()},[Lt]),un=(0,t.useCallback)((e,t,n,o,a)=>{W.setParams((0,F.viewParams)(e,t,n,o,a))},[W]),dn=(0,t.useCallback)(e=>{Pe(t=>t===e?t:(un(e,Ae,ye,xe,Se),e))},[un,Ae,ye,xe,Se]),fn=(0,t.useCallback)(e=>{if(ke===e)return;const{pinned:t}=(0,H.selectPane)(ke,Ae,e);Pe(e),Ie(t),un(e,t,ye,xe,Se)},[un,ke,Ae,ye,xe,Se]),hn=(0,t.useCallback)(()=>{const{pinned:e}=(0,H.selectPane)(ke,Ae,"terminal");Pe("terminal"),Ie(e),un("terminal",e,ye,xe,Se),setTimeout(()=>Nt.current?.focus(),60)},[un,ke,Ae,ye,xe,Se]);(0,t.useEffect)(()=>{if(!e)return;if(Me.length<2)return;const t=e=>{const t=e.target;if(t?.closest?.(re))return;const n=t?.closest?.("[data-pane]"),o=n?.getAttribute("data-pane");"chat"!==o&&"terminal"!==o&&"files"!==o||(fn(o),"terminal"===o&&Nt.current?.focus())};return document.addEventListener("pointerdown",t,!0),()=>document.removeEventListener("pointerdown",t,!0)},[e,Me.length,fn]);const gn=(0,t.useCallback)(e=>{Ie(t=>{const n=new Set(t);return n.has(e)?n.delete(e):n.add(e),un(ke,n,ye,xe,Se),n})},[un,ke,ye,xe,Se]),[bn,mn]=(0,t.useState)(null),pn=(0,t.useCallback)((e,t)=>{(e!==y||t)&&W.push((0,P.narrativeHref)(e,t))},[W,y]),yn=(0,t.useCallback)((e,t)=>{W.push(`/${e}?scrollTo=${t}`)},[W]),vn=(0,t.useCallback)(e=>{const t=xt.toggle(e);W.setParams({scrollToSeq:t?String(e):void 0})},[W,xt]),xn=(0,t.useCallback)(()=>{0!==xt.clear().length&&W.setParams({scrollToSeq:void 0})},[W,xt]);(0,t.useEffect)(()=>{if(!e)return;const t=e=>{const t=e.target;t?.closest&&t.closest('[data-pane="chat"]')&&(t.closest("[data-bubble], [data-chrome]")||t.closest("input, textarea, [data-composer]")||window.getSelection()?.toString()||xn())};return document.addEventListener("click",t),()=>document.removeEventListener("click",t)},[e,xn]);const wn=(0,t.useCallback)((e,t,n)=>{ve(e),we(t),Ce(n);"files"===ke||Ae.has("files")?un(ke,Ae,e,t,n):(Pe("files"),un("files",Ae,e,t,n))},[un,ke,Ae]),Sn=(0,t.useCallback)(e=>{const{path:t,line:n,lineEnd:o}=(0,I.parseRelLink)(e);wn(t,n,o)},[wn]),Cn=(0,t.useCallback)(e=>{if(!y)return;const{path:t,line:n,lineEnd:o}=(0,I.parseRelLink)(e);return(0,P.fileHref)(y,t,n,o,(0,F.serializePinned)(Ae)||void 0)},[y,Ae]),Tn=(0,t.useRef)(ke);Tn.current=ke;const jn=(0,t.useRef)(Ae);jn.current=Ae,(0,t.useEffect)(()=>{const e=(0,F.parseActiveTab)(A);e!==Tn.current&&Pe(e);const t=(0,F.parsePinnedTabs)(L),n=jn.current;(t.size!==n.size||[...t].some(e=>!n.has(e)))&&Ie(t)},[A,L]),(0,t.useEffect)(()=>{if(!je||!y)return;if(Re.current===y)return;if(Re.current=y,A||L)return;let e=null;try{e=sessionStorage.getItem(je)}catch{return}if(!e)return;let t=null;try{t=JSON.parse(e)}catch{}t&&(Pe((0,F.parseActiveTab)(t.tab)),Ie((0,F.parsePinnedTabs)(t.pinned)))},[y]);const Rn=(0,t.useMemo)(()=>{const e=new Map;if(0===ge.size||0===fe.length)return e;const t=fe[0].seq,n=fe[fe.length-1].seq;for(const o of ge.values()){let a=Math.min(o.after_seq,n);if(0===a){if(1!==t)continue;a=0}else if(a<t)continue;const l=e.get(a);l?l.push(o):e.set(a,[o])}for(const t of e.values())t.sort((e,t)=>e.started_at-t.started_at||e.dedup_key.localeCompare(t.dedup_key));return e},[fe,ge]),kn=(0,t.useCallback)(e=>G&&y?(0,b.fetchToolUse)(G,y,e):Promise.reject(new Error("no connection")),[G,y]),Pn=(0,t.useCallback)(({item:e})=>{const t=1===e.seq?Rn.get(0):void 0,n=Rn.get(e.seq),o=(0,O.jsx)(U,{item:e,nid:y,agentType:Ge,foldPath:Ke,conn:G,selection:xt,palette:St,onImagePress:$e,onForeignPress:yn,onFilePress:Sn,fileHref:Cn,onTimestampPress:vn});return t||n?(0,O.jsxs)(O.Fragment,{children:[t&&(0,O.jsx)(m.default,{rows:t,onNarrativePress:pn,onFetchFull:kn}),o,n&&(0,O.jsx)(m.default,{rows:n,onNarrativePress:pn,onFetchFull:kn})]}):o},[y,Ge,Ke,G,xt,St,yn,pn,Sn,Cn,vn,Rn,kn]),An=(0,t.useMemo)(()=>(0,F.viewParams)(ke,Ae,ye,xe,Se),[ke,Ae,ye,xe,Se]),In="undefined"!=typeof window&&!!G&&(0,F.isIsolated)(window.location.host,G.host),_n=(0,B.useAppHost)(G,In),En=(0,t.useCallback)(()=>{if(!G||!y)return;if("undefined"==typeof window)return;const e=(0,F.buildIsolateUrl)({host:window.location.host,protocol:window.location.protocol,search:window.location.search,path:`/${y}`,conn:G,appHost:_n,view:An});e&&window.open(e,"_blank","noopener,noreferrer")},[G,y,An,_n]),Ln=(0,t.useCallback)(async()=>{if(!G||!y)return;const e=!Ve;Je(e),ae(y,{archived:e});try{await(0,b.archiveNarrative)(G,y,e)}catch{Je(!e),ae(y,{archived:!e})}},[G,y,Ve]),Mn=(0,t.useCallback)(()=>{G&&(ft(!0),mt(!0),(0,b.fetchNarratives)(G).then(e=>{const t=e.filter(e=>e.mcp_connected||"active"===e.status||e.id===y);gt((0,$.sortNarratives)(t))}).catch(()=>{}).finally(()=>mt(!1)))},[G,y]);return(0,O.jsx)(u.default,{style:se.container,behavior:void 0,keyboardVerticalOffset:90,children:(0,O.jsxs)(N.MarkdownLinksProvider,{knownNarrativeIds:vt,onNarrativePress:pn,onProtocolPress:mn,children:[(0,O.jsx)(d.Stack.Screen,{options:V}),(0,O.jsx)(Y,{nid:y,narrativeSummary:De,narrativeFoldPath:Ke,narrativeRole:Xe,narrativeStatus:Ze,narrativeMcpConnected:tt,narrativeAwaiting:rt,palette:St,narrativeCreatedAt:at,narrativeLastActivity:st,cost:(0,b.formatCost)(ct?.amount,ct?.unit),archived:Ve,selection:xt,openSwitcher:Mn,onDownload:an,onTerminate:()=>{hn(),Nt.current?.terminate()},onRevive:()=>{(0,v.revivesAsTwin)(Xe)||hn(),Nt.current?.revive()},onTwin:()=>Oe(!0),onArchiveToggle:Ln,onRecolor:Tt,onShowQr:()=>Be(!0),onIsolateDaemon:En,isIsolated:In,canIsolate:!In||!!_n}),(0,O.jsx)(n.default,{style:se.tabBar,children:F.CANONICAL_TABS.map((e,t)=>{const a=ke===e,l=Ae.has(e),i=a||l,c="chat"===e?"Chat":"terminal"===e?"Terminal":"Files",u="chat"===e?At:"terminal"===e?_t:Lt,d="chat"===e?ln:"terminal"===e?sn:cn;return(0,O.jsxs)(n.default,{style:[se.tab,t>0&&se.tabDivider,a&&se.tabActive],children:[(0,O.jsx)(s.default,{style:se.tabLabel,onPress:()=>dn(e),children:(0,O.jsx)(o.default,{style:[se.tabText,a&&se.tabTextActive],children:c})}),(0,O.jsx)(s.default,{style:se.tabPin,onPress:()=>gn(e),hitSlop:6,children:(0,O.jsx)(o.default,{style:[se.tabPinIcon,l?se.tabPinOn:se.tabPinOff],children:"\ud83d\udccc"})}),(0,O.jsx)(s.default,{style:se.tabArrowPress,onPress:d,disabled:!i,hitSlop:6,children:i?"chat"===e&&Ot?(0,O.jsx)(o.default,{style:se.tabArrowText,children:"\u267b\ufe0f"}):(0,O.jsx)(o.default,{style:se.tabArrowText,children:u?"\u2191":"\u2193"}):(0,O.jsx)(o.default,{style:se.tabArrowText})})]},e)})}),(0,O.jsxs)(n.default,Object.assign({style:{flex:1,overflow:"hidden",position:"relative"}},ze?{onTouchStart:e=>{const t=e.nativeEvent;Rt.current={x:t.pageX,y:t.pageY}},onTouchMove:e=>{if(!Rt.current)return;const t=e.nativeEvent,n=Math.abs(t.pageX-Rt.current.x),o=Math.abs(t.pageY-Rt.current.y);n>15&&n>1.5*o&&!kt.current&&(kt.current=!0)},onTouchEnd:e=>{if(!Rt.current)return;const t=e.nativeEvent,n=t.pageX-Rt.current.x,o=t.pageY-Rt.current.y;Rt.current=null,kt.current=!1;if(!("undefined"!=typeof window&&!!window.getSelection()?.toString())&&Math.abs(n)>60&&Math.abs(n)>1.5*Math.abs(o)){const e=Me[0],t=F.CANONICAL_TABS.indexOf(e),o=n<0?t+1:t-1;o>=0&&o<F.CANONICAL_TABS.length&&dn(F.CANONICAL_TABS[o])}}}:{},{children:[(0,O.jsxs)(n.default,{style:Ne.chat,dataSet:{pane:"chat"},children:[(0,O.jsx)("div",{ref:jt,style:Z,onScroll:e=>{const t=e.currentTarget,n=t.scrollTop>-50;n===Pt.current||Ht.current||(Pt.current=n,It(n));const o=t.scrollHeight-t.clientHeight+t.scrollTop,a=Date.now()-$t.current;o<200&&Wt&&!Ut.current&&!Xt.current&&qt.current&&$t.current>0&&a>Q&&nn()},children:(0,O.jsx)(n.default,{style:[se.list,ee],children:fe.map(e=>(0,O.jsx)("div",{"data-seq":e.seq,children:Pn({item:e})},e.seq))})}),(0,O.jsx)(X,{conn:G,nid:y,loadEvents:tn,chatActive:"chat"===ke,selection:xt,onDeselect:xn})]}),G&&y&&(0,O.jsx)(n.default,{style:Ne.terminal,dataSet:{pane:"terminal"},children:(0,O.jsx)(p.default,{ref:Nt,conn:G,nid:y,active:Me.includes("terminal"),keyboardActive:"terminal"===ke&&!dt&&!He&&null===qe,agentType:Ge,role:Xe,onAtBottomChange:Et,onTwin:()=>Oe(!0),onRevived:e=>W.push((0,F.terminalOnlyHref)(e))})}),G&&y&&(0,O.jsx)(n.default,{style:Ne.files,dataSet:{pane:"files"},children:(0,O.jsx)(_.default,{ref:zt,conn:G,nid:y,path:ye,line:xe,lineEnd:Se,active:Me.includes("files"),onPathChange:wn,onImagePress:$e,onAtBottomChange:Mt})})]})),(0,O.jsx)(i.default,{visible:dt,transparent:!0,animationType:"fade",onRequestClose:()=>ft(!1),children:(0,O.jsx)(s.default,{style:se.switcherOverlay,onPress:()=>ft(!1),children:(0,O.jsxs)(n.default,{style:se.switcherContent,children:[(0,O.jsxs)(n.default,{style:se.switcherTitleRow,children:[(0,O.jsx)(o.default,{style:se.switcherTitle,children:"Switch narrative"}),(0,O.jsx)(s.default,{hitSlop:8,onPress:()=>{ft(!1),W.push("/")},children:(0,O.jsx)(o.default,{style:se.switcherListLink,children:"All narratives"})})]}),(0,O.jsx)(l.default,{data:ht,keyExtractor:e=>e.id,style:se.switcherList,ListEmptyComponent:(0,O.jsx)(o.default,{style:se.switcherEmpty,children:bt?"Loading\u2026":"No active narratives"}),renderItem:({item:e})=>{const t="ended"===e.status&&!e.mcp_connected,n=(0,x.isAwaiting)({mcpConnected:e.mcp_connected,awaiting:e.awaiting})?(0,x.awaitingGlow)((0,T.glowHueFor)(e.id)):void 0;return(0,O.jsxs)(s.default,{style:[se.switcherItem,e.id===y&&se.switcherItemActive,t&&se.switcherItemEnded,n?{boxShadow:n}:null],onPress:()=>{ft(!1),e.id!==y&&W.push(`/${e.id}`)},children:[(0,O.jsx)(j.NarrativeIdentity,{id:e.id,foldPath:e.fold_path,titleStyle:t?{color:"#666"}:void 0,copyMarginLeft:5,dimmed:t}),(0,O.jsx)(j.NarrativeMetaLine,{role:e.role,cost:(0,b.formatCost)(e.cost_amount,e.cost_unit),createdAt:e.created_at,lastActivity:e.last_activity,status:e.status,mcpConnected:e.mcp_connected,dimmed:t,style:{marginTop:4}}),e.summary&&(0,O.jsx)("div",{style:{position:"relative"},children:(0,O.jsx)("div",{className:"no-scrollbar",style:{overflowX:"auto",overflowY:"hidden",scrollbarWidth:"none",WebkitOverflowScrolling:"touch",maskImage:"linear-gradient(to right, #000 calc(100% - 40px), transparent)",WebkitMaskImage:"linear-gradient(to right, #000 calc(100% - 40px), transparent)"},children:(0,O.jsx)(o.default,{style:[se.switcherItemSummary,t&&{color:"#555"}],children:e.summary})})})]})}}),(0,O.jsx)(s.default,{style:se.switcherCancel,onPress:()=>ft(!1),children:(0,O.jsx)(o.default,{style:se.switcherCancelText,children:"Cancel"})})]})})}),(0,O.jsx)(R.default,{visible:Fe,conn:G,path:`/${y}`,view:An,onClose:()=>Be(!1)}),(0,O.jsx)(E.default,{visible:He,conn:G,re:y,defaultFoldPath:Ke,onClose:()=>Oe(!1),onSpawned:e=>{Oe(!1),W.push(`/${e.id}`)}}),(0,O.jsx)(i.default,{visible:null!==qe,transparent:!0,animationType:"fade",onRequestClose:()=>$e(null),children:(0,O.jsxs)(s.default,{style:se.lightboxBackdrop,onPress:()=>$e(null),children:[qe&&(0,O.jsx)(a.default,{source:{uri:qe},style:se.lightboxImage,resizeMode:"contain"}),(0,O.jsx)(o.default,{style:se.lightboxHint,children:"Tap anywhere to close"})]})}),bn&&G&&(0,O.jsx)(N.MarkdownLinksProvider,{onNarrativePress:(e,t)=>{mn(null),pn(e,t)},children:(0,O.jsx)(M.default,{conn:G,target:{source:"protocols",slug:bn},onClose:()=>mn(null)})})]})})}const se=c.default.create({container:{flex:1},glowTransition:{transitionProperty:"box-shadow",transitionDuration:"400ms"},header:{flexDirection:"row",alignItems:"center",backgroundColor:"#1a1a1e",paddingHorizontal:4,paddingVertical:6,borderBottomWidth:c.default.hairlineWidth,borderBottomColor:"rgb(216, 216, 216)",position:"relative",zIndex:10},tabBar:{flexDirection:"row",borderBottomWidth:c.default.hairlineWidth,borderBottomColor:"#555",backgroundColor:"#111"},tab:{width:100/F.CANONICAL_TABS.length+"%",position:"relative"},tabDivider:{borderLeftWidth:c.default.hairlineWidth,borderLeftColor:"#555"},tabActive:{borderBottomWidth:2,borderBottomColor:"#4caf50"},tabLabel:{flex:1,paddingVertical:10,paddingHorizontal:36,alignItems:"center",justifyContent:"center"},tabPin:{position:"absolute",left:0,top:0,bottom:0,width:36,alignItems:"center",justifyContent:"center"},tabPinIcon:{fontSize:12},tabPinOn:{opacity:1},tabPinOff:{opacity:.25},tabArrowPress:{position:"absolute",right:0,top:0,bottom:0,width:36,alignItems:"center",justifyContent:"center"},tabText:{color:"#666",fontSize:14,fontWeight:"600"},tabTextActive:{color:"#4caf50"},tabArrowText:{color:"#8fd4b4",fontSize:16,fontWeight:"400"},headerTitleContainer:{flexDirection:"column",alignItems:"stretch",justifyContent:"center",flex:1,minWidth:0,paddingHorizontal:8},headerSubtitle:{color:"#888",fontSize:12,fontFamily:"monospace",marginTop:1},headerSummary:{color:"#9a9aa0",fontSize:12,lineHeight:12,whiteSpace:"nowrap"},list:{paddingHorizontal:12,paddingVertical:8},bubbleRow:{marginBottom:6,flexDirection:"row"},bubbleRowLeft:{justifyContent:"flex-start"},bubbleRowRight:{justifyContent:"flex-end"},bubbleRowCenter:{justifyContent:"center"},bubble:{maxWidth:"85%",borderRadius:16,paddingHorizontal:14,paddingVertical:10,borderWidth:1.5,borderColor:"transparent",borderStyle:"solid"},bubbleAgent:{backgroundColor:"#1c1c1e",borderBottomLeftRadius:4},bubbleOperator:{backgroundColor:"#1a4a7a",borderBottomRightRadius:4},bubbleForeign:{borderRadius:12},bubbleSystem:{backgroundColor:"transparent",borderWidth:1,borderStyle:"dashed",borderColor:"#3a3a3c",borderRadius:12},bubbleSelected:{borderColor:"#5b9bd5"},bubbleSourceRow:{flexDirection:"row",alignItems:"center",alignSelf:"flex-start",marginBottom:3},bubbleSourcePress:{alignSelf:"flex-start"},bubbleSource:{color:"#4caf50",fontSize:11,fontFamily:"monospace"},bubbleSourceLink:{textDecorationLine:"underline"},bubbleSourceAfterLink:{marginLeft:4},bubbleSourceSystem:{color:"#8a8a8e"},bubbleTimePress:{alignSelf:"flex-end",marginTop:4},bubbleTime:{color:"#666",fontSize:11,textAlign:"right"},inputRow:{flexDirection:"row",padding:8,paddingBottom:8,borderTopWidth:1,borderTopColor:"rgb(216, 216, 216)",backgroundColor:"#1a1a1a",alignItems:"flex-end"},input:{flex:1,backgroundColor:"#111",color:"#e0e0e0",borderRadius:20,paddingHorizontal:16,paddingVertical:8,fontSize:15,borderWidth:1,borderColor:"#555",maxHeight:120,minHeight:36},sendButton:Object.assign({marginLeft:8,width:36,height:36,borderRadius:18,backgroundColor:"#1c1c1e",borderWidth:1,borderColor:"#555",justifyContent:"center",alignItems:"center"},{transition:"box-shadow 160ms ease, border-color 160ms ease"}),sendText:{fontSize:20,lineHeight:20,transform:[{translateX:-1},{translateY:1},{rotate:"45deg"}]},sendTextInactive:{opacity:.35},attachButton:Object.assign({width:36,height:36,borderRadius:18,backgroundColor:"#1c1c1e",justifyContent:"center",alignItems:"center",marginRight:8,borderWidth:1,borderColor:"#555"},{transition:"box-shadow 160ms ease, border-color 160ms ease"}),attachText:{fontSize:20,lineHeight:20,marginTop:-3},circleGlowActive:Object.assign({borderColor:"rgba(255, 130, 180, 0.6)"},{boxShadow:["0 0 10px rgba(255, 130, 180, 0.9)","0 0 25px rgba(255, 110, 165, 0.7)","0 0 50px rgba(255, 100, 155, 0.4)"].join(", ")}),circleGlowSend:Object.assign({borderColor:"rgba(90, 230, 200, 0.6)"},{boxShadow:["0 0 10px rgba(90, 230, 200, 0.9)","0 0 25px rgba(70, 215, 190, 0.7)","0 0 50px rgba(60, 200, 180, 0.4)"].join(", ")}),payloadsContainer:{marginTop:6,gap:4},filePayload:{backgroundColor:"rgba(255,255,255,0.1)",borderRadius:6,paddingHorizontal:10,paddingVertical:6},filePayloadText:{color:"#6cf",fontSize:13},pendingPayloadsRow:{flexDirection:"row",paddingHorizontal:12,paddingTop:8,gap:8,backgroundColor:"#111"},pendingPayloadThumb:{position:"relative",width:60,height:60},pendingPayloadImage:{width:60,height:60,borderRadius:8,borderWidth:1,borderColor:"#555"},pendingPayloadRemove:{position:"absolute",top:-6,right:-6,width:20,height:20,borderRadius:10,backgroundColor:"#c00",justifyContent:"center",alignItems:"center"},pendingPayloadRemoveText:{color:"#fff",fontSize:14,fontWeight:"700",lineHeight:16},switcherOverlay:{flex:1,backgroundColor:"rgba(0,0,0,0.6)",justifyContent:"center",alignItems:"center",padding:24},switcherContent:{backgroundColor:"#1e1e1e",borderRadius:12,paddingTop:20,paddingHorizontal:20,paddingBottom:8,width:"100%",maxWidth:400,maxHeight:"70%"},switcherTitleRow:{flexDirection:"row",alignItems:"baseline",justifyContent:"space-between",marginBottom:16},switcherTitle:{color:"#e0e0e0",fontSize:18,fontWeight:"600"},switcherListLink:{color:"#8fd4b4",fontSize:14},switcherList:{flexGrow:0,padding:4,margin:-4},switcherItem:{paddingVertical:12,paddingHorizontal:12,borderRadius:8,backgroundColor:"#2a2a2a",marginBottom:8},switcherItemActive:{outlineWidth:2,outlineStyle:"solid",outlineColor:"#4caf50",outlineOffset:2},switcherItemEnded:{opacity:.5},switcherItemSummary:{color:"#9a9aa0",fontSize:12,lineHeight:12,whiteSpace:"nowrap"},switcherEmpty:{color:"#888",fontSize:14,textAlign:"center",paddingVertical:20},switcherCancel:{paddingVertical:12,alignItems:"center",marginTop:4},switcherCancelText:{color:"#888",fontSize:15},lightboxBackdrop:{flex:1,backgroundColor:"rgba(0, 0, 0, 0.95)",justifyContent:"center",alignItems:"center",padding:8},lightboxImage:{width:"100%",height:"92%"},lightboxHint:{color:"#888",fontSize:14,marginTop:20},reloadButton:{paddingHorizontal:8,paddingVertical:4,marginRight:4},reloadText:Object.assign({fontSize:20},{transition:"text-shadow 160ms ease"}),reloadTextActive:Object.assign({},{textShadow:["0 0 10px rgba(140, 230, 170, 0.9)","0 0 25px rgba(120, 215, 155, 0.7)","0 0 50px rgba(100, 200, 145, 0.4)","0 2px 15px rgba(130, 220, 165, 0.6)"].join(", ")})})},10,[11,13,105,106,113,145,146,153,26,160,116,161,165,736,745,759,762,773,769,754,774,771,770,776,778,780,786,761,958,959,972,779,973,950,751,976,977,747,978,980,6]);
26
+ __d(function(g,r,_i,_a,_m,_e,_d){"use strict";function e(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(_e,'__esModule',{value:!0}),Object.defineProperty(_e,"default",{enumerable:!0,get:function(){return se}});var t=r(_d[0]),n=e(r(_d[1])),o=e(r(_d[2])),a=e(r(_d[3])),s=e(r(_d[4]));r(_d[5]);var l=e(r(_d[6])),i=e(r(_d[7])),c=e(r(_d[8])),u=e(r(_d[9]));r(_d[10]);var d=r(_d[11]),f=r(_d[12]),h=r(_d[13]),b=r(_d[14]),m=e(r(_d[15])),p=e(r(_d[16])),y=e(r(_d[17])),v=r(_d[18]),x=r(_d[19]),w=r(_d[20]),S=r(_d[21]),C=r(_d[22]),T=r(_d[23]),j=r(_d[24]),R=e(r(_d[25])),k=r(_d[26]),P=r(_d[27]),A=r(_d[28]),I=r(_d[29]),E=e(I),_=e(r(_d[30])),L=e(r(_d[31])),M=e(r(_d[32])),N=r(_d[33]),z=r(_d[34]),q=r(_d[35]),$=r(_d[36]),F=r(_d[37]),B=r(_d[38]),H=r(_d[39]),O=r(_d[40]);function D(e,t=!1){const n=new Date(e),o=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][n.getDay()],a=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"][n.getMonth()],s=n.getDate(),l=n.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"});if(t)return`${o} ${a} ${s}, ${n.getFullYear()} ${l}`;const i=new Date,c=n.getFullYear()===i.getFullYear();return c&&n.getMonth()===i.getMonth()&&n.getDate()===i.getDate()?`${o} ${l}`:c?`${o} ${a} ${s} ${l}`:`${o} ${a} ${s}, ${n.getFullYear()} ${l}`}function W(e){return"agent_signal"===e}const G=(0,t.memo)(function({uri:e,onPress:n}){const[o,s]=(0,t.useState)(null);(0,t.useEffect)(()=>{a.default.getSize(e,(e,t)=>s({w:e,h:t}),()=>s({w:200,h:150}))},[e]);const i=o?Math.min(200/o.w,150/o.h):1,c=o?Math.round(o.w*i):200,u=o?Math.round(o.h*i):150;return(0,O.jsx)(l.default,{onPress:n,children:(0,O.jsx)(a.default,{source:{uri:e},style:{width:c,height:u,borderRadius:8},resizeMode:"cover"})})}),X=(0,t.memo)(function({item:e,nid:t,agentType:a,foldPath:s,conn:i,selection:c,palette:u=0,onImagePress:d,onForeignPress:f,onFilePress:h,fileHref:m,onTimestampPress:p}){const y=(0,w.useIsSelected)(c,e.seq),v="human_signal"===e.type;const x=W(e.type),C=(0,z.isSystemEvent)(e.type),T=i&&e.payloads?e.payloads.filter(b.isInlinePayload):[],j=i&&e.payloads?e.payloads.filter(e=>!(0,b.isInlinePayload)(e)):[],R=(0,O.jsxs)(O.Fragment,{children:[(e.source||C)&&(0,O.jsxs)(n.default,{style:le.bubbleSourceRow,children:[x&&e.source&&(0,O.jsx)(l.default,{onPress:()=>f?.(e.source,e.time),style:le.bubbleSourcePress,children:(0,O.jsx)(o.default,{style:[le.bubbleSource,le.bubbleSourceLink,{color:(0,S.speakerColor)(e.source,u)}],children:e.source})}),(0,O.jsx)(l.default,{onPress:()=>p?.(e.seq),style:[le.bubbleSourcePress,x&&le.bubbleSourceAfterLink],children:(0,O.jsx)(o.default,{style:[le.bubbleSource,x&&e.source&&{color:(0,S.speakerColor)(e.source,u)},C&&le.bubbleSourceSystem],children:C?`system (${t}:${e.seq})`:v?`you (${t}:${e.seq})`:x?`(${t}:${e.seq})`:`${e.source}:${e.seq}`})}),(0,O.jsx)(L.default,{text:`${t}:${e.seq}`,size:9,padding:3,marginLeft:1,translateY:-1})]}),e.content?(0,O.jsx)(k.MarkdownContent,{content:C?(0,z.systemLine)({type:e.type,content:e.content},{agent:a??(0,z.agentTypeOf)(t),fold:s}):e.content,foreign:x,system:C,onFilePress:h,fileHref:m}):null,T.length>0&&i&&(0,O.jsx)(n.default,{style:le.payloadsContainer,children:T.map(e=>(0,O.jsx)(G,{uri:(0,b.payloadUrl)(i,e),onPress:()=>d?.((0,b.payloadUrl)(i,e))},e))}),j.length>0&&i&&(0,O.jsx)(n.default,{style:le.payloadsContainer,children:j.map(e=>{const t=(0,A.downloadNameFor)(e),n=(0,b.payloadUrl)(i,e);return(0,O.jsx)(l.default,{onPress:()=>{"undefined"!=typeof window&&(0,A.downloadUrl)(n,t).catch(e=>console.error("Payload download failed:",e))},style:le.filePayload,children:(0,O.jsx)(o.default,{style:le.filePayloadText,children:t})},e)})}),(0,O.jsx)(l.default,{onPress:()=>p?.(e.seq),style:le.bubbleTimePress,children:(0,O.jsx)(o.default,{style:le.bubbleTime,children:D(e.time)})})]}),P=[le.bubble,C?le.bubbleSystem:v?le.bubbleOperator:x?[le.bubbleForeign,{backgroundColor:(0,S.speakerBgColor)(e.source||"unknown",u)}]:le.bubbleAgent,y&&le.bubbleSelected];return(0,O.jsx)(n.default,{style:[le.bubbleRow,v?le.bubbleRowRight:x||C?le.bubbleRowCenter:le.bubbleRowLeft],children:(0,O.jsx)(n.default,{dataSet:{bubble:String(e.seq)},style:P,children:R})})}),U=(0,t.memo)(function({conn:e,nid:s,loadEvents:i,chatActive:c,selection:u,onDeselect:d}){const h=(0,w.useSelectedSeqs)(u),[m,p]=(0,t.useState)(!1),[y,v]=(0,t.useState)(!1),[x,S]=(0,t.useState)([]),C=(0,t.useRef)(null),T=(0,t.useRef)(null),j=(0,t.useRef)(!1),R=(0,t.useRef)(!1),k=(0,f.useIsFocused)(),P=c&&k;R.current=P;const A=(0,t.useRef)(""),I=(0,t.useRef)(null),E=`brane:draft:${s}`;(0,t.useEffect)(()=>{try{const e=localStorage.getItem(E);if(e&&(A.current=e,v(e.trim().length>0),T.current)){T.current.value=e}}catch{}return()=>{I.current&&clearTimeout(I.current);try{const e=A.current;e.trim()?localStorage.setItem(E,e):localStorage.removeItem(E)}catch{}}},[E]);const _=(0,t.useCallback)(e=>{A.current=e;const t=0===e.trim().length;v(e=>e===!t?e:!t),I.current&&clearTimeout(I.current),I.current=setTimeout(()=>{try{e.trim()?localStorage.setItem(E,e):localStorage.removeItem(E)}catch{}},300)},[E]);(0,t.useEffect)(()=>{const e=T.current;if(!e)return;if(!P)return void(document.activeElement===e&&e.blur());if(!window.matchMedia?.("(pointer: fine)").matches)return;const t=requestAnimationFrame(()=>{try{e.focus({preventScroll:!0})}catch{e.focus()}});return()=>cancelAnimationFrame(t)},[P]),(0,t.useEffect)(()=>{if(!P)return;const e=e=>{if(!R.current)return;const t=e.target,n=t?.tagName;if("INPUT"===n||"TEXTAREA"===n||t?.isContentEditable)return;if(e.metaKey||e.ctrlKey||e.altKey)return;if(e.isComposing)return;if(1!==e.key.length)return;const o=T.current;if(!o)return;e.preventDefault();const a=(o.value||"")+e.key;o.value=a,o.focus({preventScroll:!0});try{o.setSelectionRange(a.length,a.length)}catch{}_(a)};return document.addEventListener("keydown",e),()=>document.removeEventListener("keydown",e)},[P,_]),(0,t.useEffect)(()=>{if(!k)return;const e=e=>{const t=e.clipboardData?.items;if(t)for(const e of Array.from(t)){if(!e.type.startsWith("image/"))continue;const t=e.getAsFile();if(!t)continue;const n=new FileReader;n.onload=()=>{const e=n.result,o=e.split(",")[1],a=t.type.split("/")[1]||"png";S(t=>[...t,{id:`${Date.now()}_${Math.random().toString(36).slice(2,6)}`,filename:`paste_${Date.now()}.${a}`,data:o,uri:e}])},n.readAsDataURL(t)}};return document.addEventListener("paste",e),()=>document.removeEventListener("paste",e)},[k]);const L=(0,t.useCallback)(()=>{if(!C.current){const e=document.createElement("input");e.type="file",e.accept="*/*",e.multiple=!0,e.style.display="none",e.addEventListener("change",()=>{const t=e.files;if(t){for(const e of Array.from(t)){const t=new FileReader;t.onload=()=>{const n=t.result,o=n.split(",")[1];S(t=>[...t,{id:String(Date.now())+e.name,filename:e.name,data:o,uri:n}])},t.readAsDataURL(e)}e.value=""}}),document.body.appendChild(e),C.current=e}C.current.click()},[]);(0,t.useEffect)(()=>()=>{C.current&&(C.current.remove(),C.current=null)},[]);const M=(0,t.useCallback)(e=>{S(t=>t.filter(t=>t.id!==e))},[]),N=(0,t.useCallback)(async()=>{const t=A.current.trim();if(!e||!s||!t&&0===x.length)return;const n=x.length>0?x.map(e=>({filename:e.filename,data:e.data})):void 0;p(!0),S([]);try{await(0,b.sendSignal)(e,s,t||"(attachment)","web",n,[...h]),h.length>0&&d(),A.current="",v(!1);try{localStorage.removeItem(E)}catch{}if(T.current){const e=T.current;"function"==typeof e.clear?e.clear():e.value=""}j.current=!0,i()}catch{}finally{p(!1)}},[e,s,E,x,h,d,i]);return(0,t.useEffect)(()=>{if(m)return;if(!j.current)return;if(j.current=!1,!R.current)return;const e=T.current;if(e)try{e.focus({preventScroll:!0})}catch{e.focus()}},[m]),(0,O.jsxs)(O.Fragment,{children:[x.length>0&&(0,O.jsx)(n.default,{style:le.pendingPayloadsRow,dataSet:{composer:"1"},children:x.map(e=>(0,O.jsxs)(n.default,{style:le.pendingPayloadThumb,children:[(0,b.isInlinePayload)(e.filename)?(0,O.jsx)(a.default,{source:{uri:e.uri},style:le.pendingPayloadImage,resizeMode:"cover"}):(0,O.jsx)(n.default,{style:[le.pendingPayloadImage,{justifyContent:"center",alignItems:"center",backgroundColor:"rgba(255,255,255,0.1)"}],children:(0,O.jsx)(o.default,{style:{color:"#aaa",fontSize:10},numberOfLines:2,children:e.filename.split(".").pop()})}),(0,O.jsx)(l.default,{style:le.pendingPayloadRemove,onPress:()=>M(e.id),children:(0,O.jsx)(o.default,{style:le.pendingPayloadRemoveText,children:"\xd7"})})]},e.id))}),(0,O.jsxs)(n.default,{style:le.inputRow,dataSet:{composer:"1"},children:[(0,O.jsx)(l.default,{onPress:L,accessibilityLabel:"Attach file",style:({hovered:e,pressed:t})=>[le.attachButton,(e||t)&&le.circleGlowActive],children:(0,O.jsx)(o.default,{style:le.attachText,children:"\ud83e\uddeb"})}),(0,O.jsx)("textarea",{ref:T,style:{flex:1,backgroundColor:"#111",color:"#e0e0e0",borderRadius:20,paddingLeft:16,paddingRight:16,paddingTop:6,paddingBottom:6,fontSize:16,border:"1px solid #555",resize:"none",overflow:"auto",maxHeight:120,fieldSizing:"content",fontFamily:"system-ui, -apple-system, sans-serif",outline:"none",lineHeight:"22px",boxSizing:"border-box"},onChange:e=>_(e.target.value),placeholder:"Compose message...",disabled:m,autoComplete:"off",autoCorrect:"on",spellCheck:!0,inputMode:"text",rows:1}),(0,O.jsx)(l.default,{style:[le.sendButton,!m&&(y||x.length>0)&&le.circleGlowSend],onPress:N,disabled:m||!y&&0===x.length,children:(0,O.jsx)(o.default,{style:[le.sendText,(m||!y&&0===x.length)&&le.sendTextInactive],children:"\ud83e\udd8b"})})]})]})}),Y=(0,t.memo)(function({nid:e,narrativeSummary:a,narrativeFoldPath:s,narrativeRole:i,narrativeStatus:c,narrativeMcpConnected:u,narrativeAwaiting:d,palette:f,narrativeCreatedAt:h,narrativeLastActivity:b,cost:m,archived:p,selection:S,openSwitcher:C,onDismiss:R,onDownload:k,onTerminate:P,onRevive:A,onTwin:I,onArchiveToggle:E,onRecolor:_,onShowQr:L,onIsolateDaemon:M,isIsolated:N,canIsolate:z}){const[q,$]=(0,t.useState)(!1),F=(0,w.useSelectedSeqs)(S).length,B=!!(i||s||h),H=(0,x.isAwaiting)({mcpConnected:u,awaiting:d})?(0,x.awaitingGlow)((0,T.glowHueFor)(e)):void 0,D=(0,t.useRef)(null),W=(0,t.useRef)(!1),G={onTouchStart:e=>{W.current=!1;const t=e.nativeEvent;D.current=q?null:{x:t.pageX,y:t.pageY}},onTouchEnd:e=>{const t=D.current;if(D.current=null,!t)return;const n=e.nativeEvent,o=n.pageX-t.x,a=n.pageY-t.y;a>60&&a>1.5*Math.abs(o)&&(W.current=!0,R())},onTouchCancel:()=>{D.current=null}};return(0,O.jsxs)(n.default,Object.assign({style:[le.header,le.glowTransition,H?{boxShadow:H}:null]},G,{children:[(0,O.jsxs)(l.default,{style:le.headerTitleContainer,onPress:()=>{W.current?W.current=!1:C()},children:[(0,O.jsx)(j.NarrativeIdentity,{id:e,foldPath:s,align:"center"}),B?(0,O.jsx)(j.NarrativeMetaLine,{role:i,cost:m,createdAt:h??void 0,lastActivity:b,status:c,mcpConnected:u,style:{marginTop:4}}):null,a?(0,O.jsx)("div",{style:{position:"relative",marginRight:8},children:(0,O.jsx)("div",{className:"no-scrollbar",style:{overflowX:"auto",overflowY:"hidden",scrollbarWidth:"none",WebkitOverflowScrolling:"touch",maskImage:"linear-gradient(to right, #000 calc(100% - 60px), transparent)",WebkitMaskImage:"linear-gradient(to right, #000 calc(100% - 60px), transparent)"},children:(0,O.jsx)(o.default,{style:le.headerSummary,children:a})})}):null]}),(0,O.jsxs)("div",{style:{position:"relative"},children:[(0,O.jsx)(l.default,{onPress:()=>$(e=>!e),style:le.reloadButton,hitSlop:8,children:(0,O.jsx)(o.default,{style:[le.reloadText,q&&le.reloadTextActive],children:"\ud83e\udda0"})}),q&&(0,O.jsx)(y.default,{items:(0,v.narrativeMenuItems)({role:i,status:c,mcpConnected:u,archived:p,isIsolated:N,canIsolate:z,selectedCount:F,onMeld:()=>{$(!1),L()},onIsolate:()=>{$(!1),M()},onExport:e=>{$(!1),k(e)},onRecolor:()=>{$(!1),_()},onTwin:()=>{$(!1),I()},onRevive:()=>{$(!1),A()},onEnd:()=>{$(!1),P()},onArchiveToggle:()=>{$(!1),E()}}),onClose:()=>$(!1)})]})]}))}),V={headerShown:!1},J=new Map;function K(e){return null!=e.cost_amount&&e.cost_unit?{amount:e.cost_amount,unit:e.cost_unit}:null}const Q=300,Z={flex:1,minHeight:0,display:"flex",flexDirection:"column-reverse",overflowY:"auto",overflowX:"hidden"},ee={marginBottom:"auto"},te=.3;function ne(e,t){const n=e?.querySelector(`[data-seq="${t}"]`);if(!e||!n)return!1;const o=n.getBoundingClientRect().top-e.getBoundingClientRect().top;return e.scrollTop+=o-e.clientHeight*te,!0}const re='button, a[href], [role="button"], [role="link"], [role="menuitem"]';function oe(e){return e?J.get(e)??{}:{}}function ae(e,t){const n=J.get(e)??{};J.set(e,Object.assign({},n,t))}function se(){const e=(0,f.useIsFocused)(),{nid:y,scrollTo:S,scrollToSeq:k,tab:A,pinned:L,path:z,line:D}=(0,d.useLocalSearchParams)(),W=(0,d.useRouter)(),{conn:G,subscribe:J,unsubscribe:te,onHint:se,onMeta:ie,onStatus:ce,onToolUses:ue,narrativeIds:de}=(0,h.useBrane)(),[fe,he]=(0,t.useState)([]),[ge,be]=(0,t.useState)(()=>new Map),me=(0,t.useRef)(0),pe=(0,t.useRef)(Number.MAX_SAFE_INTEGER),[ye,ve]=(0,t.useState)(()=>z??""),[xe,we]=(0,t.useState)(()=>(0,F.parseLineSpec)(D).line),[Se,Ce]=(0,t.useState)(()=>(0,F.parseLineSpec)(D).lineEnd),Te=y?`brane:files:${y}`:null,je=y?`brane:tabs:${y}`:null,Re=(0,t.useRef)(null),[ke,Pe]=(0,t.useState)(()=>(0,F.parseActiveTab)(A)),[Ae,Ie]=(0,t.useState)(()=>(0,F.parsePinnedTabs)(L)),Ee=(0,t.useRef)(y??null);(0,t.useEffect)(()=>{if(!y)return;if(Ee.current===y)return;Ee.current=y;const e=(0,F.parseLineSpec)(D);ve(z??""),we(e.line),Ce(e.lineEnd)},[y]);const Le=(0,t.useRef)(null);(0,t.useEffect)(()=>{if(!Te||!y)return;if(Le.current===y)return;if(Le.current=y,z)return;let e=null;try{e=sessionStorage.getItem(Te)}catch{return}if(!e)return;let t=null;try{t=JSON.parse(e)}catch{}if(!t?.path)return;ve(t.path),we(t.line),Ce(t.lineEnd);const n=t.line?t.lineEnd&&t.lineEnd>t.line?`${t.line}-${t.lineEnd}`:String(t.line):void 0;W.setParams({path:t.path,line:n})},[y]),(0,t.useEffect)(()=>{if(Te)try{if(ye){const e={path:ye};xe&&(e.line=xe),Se&&(e.lineEnd=Se),sessionStorage.setItem(Te,JSON.stringify(e))}else sessionStorage.removeItem(Te)}catch{}},[Te,ye,xe,Se]),(0,t.useEffect)(()=>{if(je&&Re.current===y)try{sessionStorage.setItem(je,JSON.stringify({tab:ke,pinned:(0,F.serializePinned)(Ae)}))}catch{}},[je,y,ke,Ae]);const Me=(0,t.useMemo)(()=>(0,H.visiblePanes)(ke,Ae),[ke,Ae]),Ne=(0,t.useMemo)(()=>{const e=e=>{const t=Me.indexOf(e),n=Me.length;return t<0||1===n?{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:t<0?0:1,backgroundColor:"#111",pointerEvents:t<0?"none":"auto"}:{position:"absolute",top:0,bottom:0,left:t/n*100+"%",width:100/n+"%",zIndex:1,backgroundColor:"#111",borderLeftWidth:t>0?c.default.hairlineWidth:0,borderLeftColor:"#555"}};return{chat:e("chat"),terminal:e("terminal"),files:e("files")}},[Me]),ze=1===Me.length,[qe,$e]=(0,t.useState)(null),[Fe,Be]=(0,t.useState)(!1),[He,Oe]=(0,t.useState)(!1),[De,We]=(0,t.useState)(()=>oe(y).summary??null),[Ge,Xe]=(0,t.useState)(()=>oe(y).agent_type??null),[Ue,Ye]=(0,t.useState)(()=>oe(y).role??null),[Ve,Je]=(0,t.useState)(()=>oe(y).archived??!1),[Ke,Qe]=(0,t.useState)(()=>oe(y).fold_path??null),[Ze,et]=(0,t.useState)(()=>oe(y).status??null),[tt,nt]=(0,t.useState)(()=>oe(y).mcp_connected??!1),[rt,ot]=(0,t.useState)(!1),[at,st]=(0,t.useState)(()=>oe(y).created_at??null),[lt,it]=(0,t.useState)(()=>oe(y).last_activity??null),[ct,ut]=(0,t.useState)(()=>K(oe(y)));(0,t.useEffect)(()=>{const e=oe(y);We(e.summary??null),Xe(e.agent_type??null),Ye(e.role??null),Je(e.archived??!1),Qe(e.fold_path??null),et(e.status??null),nt(e.mcp_connected??!1),ot(!1),st(e.created_at??null),it(e.last_activity??null),ut(K(e))},[y]);const[dt,ft]=(0,t.useState)(!1),[ht,gt]=(0,t.useState)([]),[bt,mt]=(0,t.useState)(!1),[pt,yt]=(0,t.useState)(null),vt=(0,t.useMemo)(()=>(0,q.collectKnownNids)({viewing:y,pushed:[...de].map(e=>({id:e})),listed:pt}),[y,de,pt]),xt=(0,w.useMessageSelection)(y),wt=(0,t.useRef)(0),[St,Ct]=(0,t.useState)(()=>(0,C.readRecolorSalt)(y));(0,t.useEffect)(()=>Ct((0,C.readRecolorSalt)(y)),[y]);const Tt=(0,t.useCallback)(()=>{(0,T.recolorGlowHue)(y),Ct((0,C.bumpRecolorSalt)(y))},[y]),jt=(0,t.useRef)(null),Rt=(0,t.useRef)(null),kt=(0,t.useRef)(!1),Pt=(0,t.useRef)(!0),[At,It]=(0,t.useState)(!0),[Et,_t]=(0,t.useState)(!0),[Lt,Mt]=(0,t.useState)(!0),Nt=(0,t.useRef)(null),zt=(0,t.useRef)(null),qt=(0,t.useRef)(!0);qt.current=Me.includes("chat");const $t=(0,t.useRef)(0),Ft=(0,t.useRef)(S?Number(S):0),Bt=(0,t.useRef)(k?Number(k):0),Ht=(0,t.useRef)(!1),[Ot,Dt]=(0,t.useState)(!1),[Wt,Gt]=(0,t.useState)(!0),Xt=(0,t.useRef)(!1),Ut=(0,t.useRef)(!1),Yt=(0,t.useRef)(null),Vt=(0,t.useRef)(!1),Jt=(0,t.useRef)(!1);(0,t.useEffect)(()=>{if(Me.includes("chat")&&!Vt.current){const e=Bt.current,t=Ft.current;if((e||t)&&0===fe.length)return;Vt.current=!0,$t.current=Date.now();let n=-1;if(e&&fe.length>0)n=fe.findIndex(t=>t.seq===e),n>=0&&xt.replace([e]),Bt.current=0;else if(t&&fe.length>0){let e=1/0;for(let o=0;o<fe.length;o++){const a=Math.abs(fe[o].time-t);a<e&&(e=a,n=o)}Ft.current=0}if(n>=0){Ut.current=!0;const e=setTimeout(()=>{Ut.current=!1},2e3);return ne(jt.current,fe[n].seq),()=>clearTimeout(e)}Pt.current=!0,It(!0)}Me.includes("terminal")&&(Jt.current=!0)},[Me,fe.length]);const Kt=(0,t.useCallback)(()=>{jt.current?.scrollTo({top:0})},[]),Qt=(0,t.useCallback)(()=>{const e=jt.current;e?.scrollTo({top:-e.scrollHeight,behavior:"smooth"})},[]),Zt=(0,t.useRef)(!1),en=(0,t.useRef)(!1),tn=(0,t.useCallback)(async()=>{if(G&&y)if(Zt.current)en.current=!0;else{Zt.current=!0;try{do{en.current=!1;const e=await(0,b.fetchEvents)(G,y,wt.current);e.events.length>0&&(he(t=>{const n=t.length>0?t[t.length-1].seq:0,o=e.events.filter(e=>e.seq>n);return o.length>0?[...t,...o]:t}),wt.current=e.events[e.events.length-1].seq)}while(en.current)}finally{Zt.current=!1}}},[G,y]),nn=(0,t.useCallback)(async()=>{if(G&&y&&!Xt.current&&Wt){Xt.current=!0;try{const e=fe.length>0?fe[0].seq:1/0,t=await(0,b.fetchEventsBefore)(G,y,e,50);t.events.length>0&&he(e=>{const n=e.length>0?e[0].seq:1/0,o=t.events.filter(e=>e.seq<n);return o.length>0?[...o,...e]:e}),(t.events.length<50||t.events.length>0&&t.events[0].seq<=t.min_seq)&&Gt(!1)}finally{Xt.current=!1}}},[G,y,fe,Wt]),rn=(0,t.useCallback)(e=>{0!==e.length&&be(t=>{let n=null;for(const o of e){const e=(n??t).get(o.dedup_key);e&&e.rev>=o.rev||(n||(n=new Map(t)),n.set(o.dedup_key,o),o.rev>me.current&&(me.current=o.rev))}return n??t})},[]);(0,t.useEffect)(()=>{if(!G||!y||0===fe.length)return;const e=Math.max(0,fe[0].seq-1),t=pe.current;e>=t||(pe.current=e,(0,b.fetchAllToolUseWindow)(G,y,{afterSeqGte:e,afterSeqLt:t===Number.MAX_SAFE_INTEGER?void 0:t},rn).catch(()=>{pe.current=Number.MAX_SAFE_INTEGER}))},[G,y,fe,rn]),(0,t.useEffect)(()=>{if(G&&y)return ue((e,t,n)=>{e===y&&(t?rn(t):(0,b.fetchAllToolUsesSince)(G,y,me.current,rn).catch(()=>{pe.current=Number.MAX_SAFE_INTEGER}))})},[G,y,ue,rn]),(0,t.useEffect)(()=>{if(!G||!y)return;const e=`${G.host}|${G.token}|${y}`;if(Yt.current===e)return;Yt.current=e,he([]),Gt(!0),wt.current=0,be(new Map),me.current=0,pe.current=Number.MAX_SAFE_INTEGER;const t=Bt.current;Ft.current;(async()=>{try{if(t){const e=Math.floor(25),n=Math.max(0,t-e-1),o=await(0,b.fetchEvents)(G,y,n,50);o.events.length>0?(he(o.events),wt.current=o.events[o.events.length-1].seq,Gt(o.events[0].seq>1)):(wt.current=o.seq,Gt(!1))}else{const e=await(0,b.fetchEventsBefore)(G,y,Number.MAX_SAFE_INTEGER,50);e.events.length>0?(he(e.events),wt.current=e.events[e.events.length-1].seq,(e.events.length<50||e.events[0].seq<=e.min_seq)&&Gt(!1)):(wt.current=0,Gt(!1))}}catch{tn()}})()},[G,y]);const on=(0,t.useCallback)(e=>{if(!y)return;e.summary&&(We(e.summary),ae(y,{summary:e.summary})),e.agent_type&&(Xe(e.agent_type),ae(y,{agent_type:e.agent_type})),e.role&&(Ye(e.role),ae(y,{role:e.role})),Qe(e.fold_path??null),ae(y,{fold_path:e.fold_path??null});const t=!!e.archived;Je(t),ae(y,{archived:t}),e.status&&(et(e.status),ae(y,{status:e.status}));const n=!!e.mcp_connected;nt(n),ae(y,{mcp_connected:n}),ot(!!e.awaiting),st(e.created_at??null),ae(y,{created_at:e.created_at}),it(e.last_activity??null),ae(y,{last_activity:e.last_activity??null}),ut(K({cost_amount:e.cost_amount,cost_unit:e.cost_unit})),ae(y,{cost_amount:e.cost_amount??null,cost_unit:e.cost_unit??null})},[y]);(0,t.useEffect)(()=>{G&&y&&(0,b.fetchNarrative)(G,y).then(on).catch(()=>{})},[G,y,on]),(0,t.useEffect)(()=>{G&&y&&(0,b.fetchNarratives)(G,{archived:!0}).then(e=>{yt(e);const t=e.find(e=>e.id===y);t&&on(t)}).catch(e=>{console.warn("narrative list sweep failed; linkifying from pushed ids only",e)})},[G,y,on]),(0,t.useEffect)(()=>{if(!y)return;J(y,wt.current);const e=se((e,t)=>{if(e===y){tn();const e=Date.now();it(e),ae(y,{last_activity:e})}});return()=>{te(y),e()}},[y,J,te,se,tn]),(0,t.useEffect)(()=>{if(y)return ie((e,t,n,o)=>{e===y&&(n&&(We(n),ae(y,{summary:n})),null!=o&&(ut(o),ae(y,{cost_amount:o.amount,cost_unit:o.unit})))})},[y,ie]),(0,t.useEffect)(()=>{if(y)return ce((e,t)=>{e===y&&("mcp_connected"===t?(nt(!0),ae(y,{mcp_connected:!0})):"mcp_disconnected"===t?(nt(!1),ot(!1),ae(y,{mcp_connected:!1})):t===x.AWAITING_STATUS||t===x.NOT_AWAITING_STATUS?ot(t===x.AWAITING_STATUS):"active"!==t&&"ended"!==t||(et(t),ae(y,{status:t})))})},[y,ce]);const an=(0,t.useCallback)(async e=>{G&&y&&("all"!==e?await(0,v.openNarrativeExport)(G,y,[...xt.getSelected()],"excluded"===e?"except":"only"):await(0,v.openNarrativeExport)(G,y))},[G,y,xt]),sn=(0,t.useCallback)(async()=>{if(Pt.current)Ht.current=!0,Pt.current=!1,It(!1),Qt(),setTimeout(()=>{Ht.current=!1},600);else{const e=setTimeout(()=>Dt(!0),150);try{await tn()}finally{clearTimeout(e),Dt(!1)}Pt.current=!0,It(!0),Kt()}},[tn,Kt,Qt]),ln=(0,t.useCallback)(()=>{Et?Nt.current?.scrollToTop():Nt.current?.scrollToBottom()},[Et]),cn=(0,t.useCallback)(()=>{Lt?zt.current?.scrollToTop():zt.current?.scrollToBottom()},[Lt]),un=(0,t.useCallback)((e,t,n,o,a)=>{W.setParams((0,F.viewParams)(e,t,n,o,a))},[W]),dn=(0,t.useCallback)(e=>{Pe(t=>t===e?t:(un(e,Ae,ye,xe,Se),e))},[un,Ae,ye,xe,Se]),fn=(0,t.useCallback)(e=>{if(ke===e)return;const{pinned:t}=(0,H.selectPane)(ke,Ae,e);Pe(e),Ie(t),un(e,t,ye,xe,Se)},[un,ke,Ae,ye,xe,Se]),hn=(0,t.useCallback)(()=>{const{pinned:e}=(0,H.selectPane)(ke,Ae,"terminal");Pe("terminal"),Ie(e),un("terminal",e,ye,xe,Se),setTimeout(()=>Nt.current?.focus(),60)},[un,ke,Ae,ye,xe,Se]);(0,t.useEffect)(()=>{if(!e)return;if(Me.length<2)return;const t=e=>{const t=e.target;if(t?.closest?.(re))return;const n=t?.closest?.("[data-pane]"),o=n?.getAttribute("data-pane");"chat"!==o&&"terminal"!==o&&"files"!==o||(fn(o),"terminal"===o&&Nt.current?.focus())};return document.addEventListener("pointerdown",t,!0),()=>document.removeEventListener("pointerdown",t,!0)},[e,Me.length,fn]);const gn=(0,t.useCallback)(e=>{Ie(t=>{const n=new Set(t);return n.has(e)?n.delete(e):n.add(e),un(ke,n,ye,xe,Se),n})},[un,ke,ye,xe,Se]),[bn,mn]=(0,t.useState)(null),pn=(0,t.useCallback)((e,t)=>{(e!==y||t)&&W.push((0,P.narrativeHref)(e,t))},[W,y]),yn=(0,t.useCallback)((e,t)=>{W.push(`/${e}?scrollTo=${t}`)},[W]),vn=(0,t.useCallback)(e=>{const t=xt.toggle(e);W.setParams({scrollToSeq:t?String(e):void 0})},[W,xt]),xn=(0,t.useCallback)(()=>{0!==xt.clear().length&&W.setParams({scrollToSeq:void 0})},[W,xt]);(0,t.useEffect)(()=>{if(!e)return;const t=e=>{const t=e.target;t?.closest&&t.closest('[data-pane="chat"]')&&(t.closest("[data-bubble], [data-chrome]")||t.closest("input, textarea, [data-composer]")||window.getSelection()?.toString()||xn())};return document.addEventListener("click",t),()=>document.removeEventListener("click",t)},[e,xn]);const wn=(0,t.useCallback)((e,t,n)=>{ve(e),we(t),Ce(n);"files"===ke||Ae.has("files")?un(ke,Ae,e,t,n):(Pe("files"),un("files",Ae,e,t,n))},[un,ke,Ae]),Sn=(0,t.useCallback)(e=>{const{path:t,line:n,lineEnd:o}=(0,I.parseRelLink)(e);wn(t,n,o)},[wn]),Cn=(0,t.useCallback)(e=>{if(!y)return;const{path:t,line:n,lineEnd:o}=(0,I.parseRelLink)(e);return(0,P.fileHref)(y,t,n,o,(0,F.serializePinned)(Ae)||void 0)},[y,Ae]),Tn=(0,t.useRef)(ke);Tn.current=ke;const jn=(0,t.useRef)(Ae);jn.current=Ae,(0,t.useEffect)(()=>{const e=(0,F.parseActiveTab)(A);e!==Tn.current&&Pe(e);const t=(0,F.parsePinnedTabs)(L),n=jn.current;(t.size!==n.size||[...t].some(e=>!n.has(e)))&&Ie(t)},[A,L]),(0,t.useEffect)(()=>{if(!je||!y)return;if(Re.current===y)return;if(Re.current=y,A||L)return;let e=null;try{e=sessionStorage.getItem(je)}catch{return}if(!e)return;let t=null;try{t=JSON.parse(e)}catch{}t&&(Pe((0,F.parseActiveTab)(t.tab)),Ie((0,F.parsePinnedTabs)(t.pinned)))},[y]);const Rn=(0,t.useMemo)(()=>{const e=new Map;if(0===ge.size||0===fe.length)return e;const t=fe[0].seq,n=fe[fe.length-1].seq;for(const o of ge.values()){let a=Math.min(o.after_seq,n);if(0===a){if(1!==t)continue;a=0}else if(a<t)continue;const s=e.get(a);s?s.push(o):e.set(a,[o])}for(const t of e.values())t.sort((e,t)=>e.started_at-t.started_at||e.dedup_key.localeCompare(t.dedup_key));return e},[fe,ge]),kn=(0,t.useCallback)(e=>G&&y?(0,b.fetchToolUse)(G,y,e):Promise.reject(new Error("no connection")),[G,y]),Pn=(0,t.useCallback)(({item:e})=>{const t=1===e.seq?Rn.get(0):void 0,n=Rn.get(e.seq),o=(0,O.jsx)(X,{item:e,nid:y,agentType:Ge,foldPath:Ke,conn:G,selection:xt,palette:St,onImagePress:$e,onForeignPress:yn,onFilePress:Sn,fileHref:Cn,onTimestampPress:vn});return t||n?(0,O.jsxs)(O.Fragment,{children:[t&&(0,O.jsx)(m.default,{rows:t,onNarrativePress:pn,onFetchFull:kn}),o,n&&(0,O.jsx)(m.default,{rows:n,onNarrativePress:pn,onFetchFull:kn})]}):o},[y,Ge,Ke,G,xt,St,yn,pn,Sn,Cn,vn,Rn,kn]),An=(0,t.useMemo)(()=>(0,F.viewParams)(ke,Ae,ye,xe,Se),[ke,Ae,ye,xe,Se]),In="undefined"!=typeof window&&!!G&&(0,F.isIsolated)(window.location.host,G.host),En=(0,B.useAppHost)(G,In),_n=(0,t.useCallback)(()=>{if(!G||!y)return;if("undefined"==typeof window)return;const e=(0,F.buildIsolateUrl)({host:window.location.host,protocol:window.location.protocol,search:window.location.search,path:`/${y}`,conn:G,appHost:En,view:An});e&&window.open(e,"_blank","noopener,noreferrer")},[G,y,An,En]),Ln=(0,t.useCallback)(async()=>{if(!G||!y)return;const e=!Ve;Je(e),ae(y,{archived:e});try{await(0,b.archiveNarrative)(G,y,e)}catch{return Je(!e),void ae(y,{archived:!e})}e&&W.push("/")},[G,y,Ve,W]),Mn=(0,t.useCallback)(()=>W.push("/"),[W]),Nn=(0,t.useCallback)(()=>{G&&(ft(!0),mt(!0),(0,b.fetchNarratives)(G).then(e=>{const t=e.filter(e=>e.mcp_connected||"active"===e.status||e.id===y);gt((0,$.sortNarratives)(t))}).catch(()=>{}).finally(()=>mt(!1)))},[G,y]);return(0,O.jsx)(u.default,{style:le.container,behavior:void 0,keyboardVerticalOffset:90,children:(0,O.jsxs)(N.MarkdownLinksProvider,{knownNarrativeIds:vt,onNarrativePress:pn,onProtocolPress:mn,children:[(0,O.jsx)(d.Stack.Screen,{options:V}),(0,O.jsx)(Y,{nid:y,narrativeSummary:De,narrativeFoldPath:Ke,narrativeRole:Ue,narrativeStatus:Ze,narrativeMcpConnected:tt,narrativeAwaiting:rt,palette:St,narrativeCreatedAt:at,narrativeLastActivity:lt,cost:(0,b.formatCost)(ct?.amount,ct?.unit),archived:Ve,selection:xt,openSwitcher:Nn,onDismiss:Mn,onDownload:an,onTerminate:()=>{hn(),Nt.current?.terminate()},onRevive:()=>{(0,v.revivesAsTwin)(Ue)||hn(),Nt.current?.revive()},onTwin:()=>Oe(!0),onArchiveToggle:Ln,onRecolor:Tt,onShowQr:()=>Be(!0),onIsolateDaemon:_n,isIsolated:In,canIsolate:!In||!!En}),(0,O.jsx)(n.default,{style:le.tabBar,children:F.CANONICAL_TABS.map((e,t)=>{const a=ke===e,s=Ae.has(e),i=a||s,c="chat"===e?"Chat":"terminal"===e?"Terminal":"Files",u="chat"===e?At:"terminal"===e?Et:Lt,d="chat"===e?sn:"terminal"===e?ln:cn;return(0,O.jsxs)(n.default,{style:[le.tab,t>0&&le.tabDivider,a&&le.tabActive],children:[(0,O.jsx)(l.default,{style:le.tabLabel,onPress:()=>dn(e),children:(0,O.jsx)(o.default,{style:[le.tabText,a&&le.tabTextActive],children:c})}),(0,O.jsx)(l.default,{style:le.tabPin,onPress:()=>gn(e),hitSlop:6,children:(0,O.jsx)(o.default,{style:[le.tabPinIcon,s?le.tabPinOn:le.tabPinOff],children:"\ud83d\udccc"})}),(0,O.jsx)(l.default,{style:le.tabArrowPress,onPress:d,disabled:!i,hitSlop:6,children:i?"chat"===e&&Ot?(0,O.jsx)(o.default,{style:le.tabArrowText,children:"\u267b\ufe0f"}):(0,O.jsx)(o.default,{style:le.tabArrowText,children:u?"\u2191":"\u2193"}):(0,O.jsx)(o.default,{style:le.tabArrowText})})]},e)})}),(0,O.jsxs)(n.default,Object.assign({style:{flex:1,overflow:"hidden",position:"relative"}},ze?{onTouchStart:e=>{const t=e.nativeEvent;Rt.current={x:t.pageX,y:t.pageY}},onTouchMove:e=>{if(!Rt.current)return;const t=e.nativeEvent,n=Math.abs(t.pageX-Rt.current.x),o=Math.abs(t.pageY-Rt.current.y);n>15&&n>1.5*o&&!kt.current&&(kt.current=!0)},onTouchEnd:e=>{if(!Rt.current)return;const t=e.nativeEvent,n=t.pageX-Rt.current.x,o=t.pageY-Rt.current.y;Rt.current=null,kt.current=!1;if(!("undefined"!=typeof window&&!!window.getSelection()?.toString())&&Math.abs(n)>60&&Math.abs(n)>1.5*Math.abs(o)){const e=Me[0],t=F.CANONICAL_TABS.indexOf(e),o=n<0?t+1:t-1;o>=0&&o<F.CANONICAL_TABS.length&&dn(F.CANONICAL_TABS[o])}}}:{},{children:[(0,O.jsxs)(n.default,{style:Ne.chat,dataSet:{pane:"chat"},children:[(0,O.jsx)("div",{ref:jt,style:Z,onScroll:e=>{const t=e.currentTarget,n=t.scrollTop>-50;n===Pt.current||Ht.current||(Pt.current=n,It(n));const o=t.scrollHeight-t.clientHeight+t.scrollTop,a=Date.now()-$t.current;o<200&&Wt&&!Xt.current&&!Ut.current&&qt.current&&$t.current>0&&a>Q&&nn()},children:(0,O.jsx)(n.default,{style:[le.list,ee],children:fe.map(e=>(0,O.jsx)("div",{"data-seq":e.seq,children:Pn({item:e})},e.seq))})}),(0,O.jsx)(U,{conn:G,nid:y,loadEvents:tn,chatActive:"chat"===ke,selection:xt,onDeselect:xn})]}),G&&y&&(0,O.jsx)(n.default,{style:Ne.terminal,dataSet:{pane:"terminal"},children:(0,O.jsx)(p.default,{ref:Nt,conn:G,nid:y,active:Me.includes("terminal"),keyboardActive:"terminal"===ke&&!dt&&!He&&null===qe,agentType:Ge,role:Ue,onAtBottomChange:_t,onTwin:()=>Oe(!0),onRevived:e=>W.push((0,F.terminalOnlyHref)(e))})}),G&&y&&(0,O.jsx)(n.default,{style:Ne.files,dataSet:{pane:"files"},children:(0,O.jsx)(E.default,{ref:zt,conn:G,nid:y,path:ye,line:xe,lineEnd:Se,active:Me.includes("files"),onPathChange:wn,onImagePress:$e,onAtBottomChange:Mt})})]})),(0,O.jsx)(i.default,{visible:dt,transparent:!0,animationType:"fade",onRequestClose:()=>ft(!1),children:(0,O.jsx)(l.default,{style:le.switcherOverlay,onPress:()=>ft(!1),children:(0,O.jsxs)(n.default,{style:le.switcherContent,children:[(0,O.jsxs)(n.default,{style:le.switcherTitleRow,children:[(0,O.jsx)(o.default,{style:le.switcherTitle,children:"Switch narrative"}),(0,O.jsx)(l.default,{hitSlop:8,onPress:()=>{ft(!1),W.push("/")},children:(0,O.jsx)(o.default,{style:le.switcherListLink,children:"All narratives"})})]}),(0,O.jsx)(s.default,{data:ht,keyExtractor:e=>e.id,style:le.switcherList,ListEmptyComponent:(0,O.jsx)(o.default,{style:le.switcherEmpty,children:bt?"Loading\u2026":"No active narratives"}),renderItem:({item:e})=>{const t="ended"===e.status&&!e.mcp_connected,n=(0,x.isAwaiting)({mcpConnected:e.mcp_connected,awaiting:e.awaiting})?(0,x.awaitingGlow)((0,T.glowHueFor)(e.id)):void 0;return(0,O.jsxs)(l.default,{style:[le.switcherItem,e.id===y&&le.switcherItemActive,t&&le.switcherItemEnded,n?{boxShadow:n}:null],onPress:()=>{ft(!1),e.id!==y&&W.push(`/${e.id}`)},children:[(0,O.jsx)(j.NarrativeIdentity,{id:e.id,foldPath:e.fold_path,titleStyle:t?{color:"#666"}:void 0,copyMarginLeft:5,dimmed:t}),(0,O.jsx)(j.NarrativeMetaLine,{role:e.role,cost:(0,b.formatCost)(e.cost_amount,e.cost_unit),createdAt:e.created_at,lastActivity:e.last_activity,status:e.status,mcpConnected:e.mcp_connected,dimmed:t,style:{marginTop:4}}),e.summary&&(0,O.jsx)("div",{style:{position:"relative"},children:(0,O.jsx)("div",{className:"no-scrollbar",style:{overflowX:"auto",overflowY:"hidden",scrollbarWidth:"none",WebkitOverflowScrolling:"touch",maskImage:"linear-gradient(to right, #000 calc(100% - 40px), transparent)",WebkitMaskImage:"linear-gradient(to right, #000 calc(100% - 40px), transparent)"},children:(0,O.jsx)(o.default,{style:[le.switcherItemSummary,t&&{color:"#555"}],children:e.summary})})})]})}}),(0,O.jsx)(l.default,{style:le.switcherCancel,onPress:()=>ft(!1),children:(0,O.jsx)(o.default,{style:le.switcherCancelText,children:"Cancel"})})]})})}),(0,O.jsx)(R.default,{visible:Fe,conn:G,path:`/${y}`,view:An,onClose:()=>Be(!1)}),(0,O.jsx)(_.default,{visible:He,conn:G,re:y,defaultFoldPath:Ke,onClose:()=>Oe(!1),onSpawned:e=>{Oe(!1),W.push(`/${e.id}`)}}),(0,O.jsx)(i.default,{visible:null!==qe,transparent:!0,animationType:"fade",onRequestClose:()=>$e(null),children:(0,O.jsxs)(l.default,{style:le.lightboxBackdrop,onPress:()=>$e(null),children:[qe&&(0,O.jsx)(a.default,{source:{uri:qe},style:le.lightboxImage,resizeMode:"contain"}),(0,O.jsx)(o.default,{style:le.lightboxHint,children:"Tap anywhere to close"})]})}),bn&&G&&(0,O.jsx)(N.MarkdownLinksProvider,{onNarrativePress:(e,t)=>{mn(null),pn(e,t)},children:(0,O.jsx)(M.default,{conn:G,target:{source:"protocols",slug:bn},onClose:()=>mn(null)})})]})})}const le=c.default.create({container:{flex:1},glowTransition:{transitionProperty:"box-shadow",transitionDuration:"400ms"},header:{flexDirection:"row",alignItems:"center",backgroundColor:"#1a1a1e",paddingHorizontal:4,paddingVertical:6,borderBottomWidth:c.default.hairlineWidth,borderBottomColor:"rgb(216, 216, 216)",position:"relative",zIndex:10},tabBar:{flexDirection:"row",borderBottomWidth:c.default.hairlineWidth,borderBottomColor:"#555",backgroundColor:"#111"},tab:{width:100/F.CANONICAL_TABS.length+"%",position:"relative"},tabDivider:{borderLeftWidth:c.default.hairlineWidth,borderLeftColor:"#555"},tabActive:{borderBottomWidth:2,borderBottomColor:"#4caf50"},tabLabel:{flex:1,paddingVertical:10,paddingHorizontal:36,alignItems:"center",justifyContent:"center"},tabPin:{position:"absolute",left:0,top:0,bottom:0,width:36,alignItems:"center",justifyContent:"center"},tabPinIcon:{fontSize:12},tabPinOn:{opacity:1},tabPinOff:{opacity:.25},tabArrowPress:{position:"absolute",right:0,top:0,bottom:0,width:36,alignItems:"center",justifyContent:"center"},tabText:{color:"#666",fontSize:14,fontWeight:"600"},tabTextActive:{color:"#4caf50"},tabArrowText:{color:"#8fd4b4",fontSize:16,fontWeight:"400"},headerTitleContainer:{flexDirection:"column",alignItems:"stretch",justifyContent:"center",flex:1,minWidth:0,paddingHorizontal:8},headerSubtitle:{color:"#888",fontSize:12,fontFamily:"monospace",marginTop:1},headerSummary:{color:"#9a9aa0",fontSize:12,lineHeight:12,whiteSpace:"nowrap"},list:{paddingHorizontal:12,paddingVertical:8},bubbleRow:{marginBottom:6,flexDirection:"row"},bubbleRowLeft:{justifyContent:"flex-start"},bubbleRowRight:{justifyContent:"flex-end"},bubbleRowCenter:{justifyContent:"center"},bubble:{maxWidth:"85%",borderRadius:16,paddingHorizontal:14,paddingVertical:10,borderWidth:1.5,borderColor:"transparent",borderStyle:"solid"},bubbleAgent:{backgroundColor:"#1c1c1e",borderBottomLeftRadius:4},bubbleOperator:{backgroundColor:"#1a4a7a",borderBottomRightRadius:4},bubbleForeign:{borderRadius:12},bubbleSystem:{backgroundColor:"transparent",borderWidth:1,borderStyle:"dashed",borderColor:"#3a3a3c",borderRadius:12},bubbleSelected:{borderColor:"#5b9bd5"},bubbleSourceRow:{flexDirection:"row",alignItems:"center",alignSelf:"flex-start",marginBottom:3},bubbleSourcePress:{alignSelf:"flex-start"},bubbleSource:{color:"#4caf50",fontSize:11,fontFamily:"monospace"},bubbleSourceLink:{textDecorationLine:"underline"},bubbleSourceAfterLink:{marginLeft:4},bubbleSourceSystem:{color:"#8a8a8e"},bubbleTimePress:{alignSelf:"flex-end",marginTop:4},bubbleTime:{color:"#666",fontSize:11,textAlign:"right"},inputRow:{flexDirection:"row",padding:8,paddingBottom:8,borderTopWidth:1,borderTopColor:"rgb(216, 216, 216)",backgroundColor:"#1a1a1a",alignItems:"flex-end"},input:{flex:1,backgroundColor:"#111",color:"#e0e0e0",borderRadius:20,paddingHorizontal:16,paddingVertical:8,fontSize:15,borderWidth:1,borderColor:"#555",maxHeight:120,minHeight:36},sendButton:Object.assign({marginLeft:8,width:36,height:36,borderRadius:18,backgroundColor:"#1c1c1e",borderWidth:1,borderColor:"#555",justifyContent:"center",alignItems:"center"},{transition:"box-shadow 160ms ease, border-color 160ms ease"}),sendText:{fontSize:20,lineHeight:20,transform:[{translateX:-1},{translateY:1},{rotate:"45deg"}]},sendTextInactive:{opacity:.35},attachButton:Object.assign({width:36,height:36,borderRadius:18,backgroundColor:"#1c1c1e",justifyContent:"center",alignItems:"center",marginRight:8,borderWidth:1,borderColor:"#555"},{transition:"box-shadow 160ms ease, border-color 160ms ease"}),attachText:{fontSize:20,lineHeight:20,marginTop:-3},circleGlowActive:Object.assign({borderColor:"rgba(255, 130, 180, 0.6)"},{boxShadow:["0 0 10px rgba(255, 130, 180, 0.9)","0 0 25px rgba(255, 110, 165, 0.7)","0 0 50px rgba(255, 100, 155, 0.4)"].join(", ")}),circleGlowSend:Object.assign({borderColor:"rgba(90, 230, 200, 0.6)"},{boxShadow:["0 0 10px rgba(90, 230, 200, 0.9)","0 0 25px rgba(70, 215, 190, 0.7)","0 0 50px rgba(60, 200, 180, 0.4)"].join(", ")}),payloadsContainer:{marginTop:6,gap:4},filePayload:{backgroundColor:"rgba(255,255,255,0.1)",borderRadius:6,paddingHorizontal:10,paddingVertical:6},filePayloadText:{color:"#6cf",fontSize:13},pendingPayloadsRow:{flexDirection:"row",paddingHorizontal:12,paddingTop:8,gap:8,backgroundColor:"#111"},pendingPayloadThumb:{position:"relative",width:60,height:60},pendingPayloadImage:{width:60,height:60,borderRadius:8,borderWidth:1,borderColor:"#555"},pendingPayloadRemove:{position:"absolute",top:-6,right:-6,width:20,height:20,borderRadius:10,backgroundColor:"#c00",justifyContent:"center",alignItems:"center"},pendingPayloadRemoveText:{color:"#fff",fontSize:14,fontWeight:"700",lineHeight:16},switcherOverlay:{flex:1,backgroundColor:"rgba(0,0,0,0.6)",justifyContent:"center",alignItems:"center",padding:24},switcherContent:{backgroundColor:"#1e1e1e",borderRadius:12,paddingTop:20,paddingHorizontal:20,paddingBottom:8,width:"100%",maxWidth:400,maxHeight:"70%"},switcherTitleRow:{flexDirection:"row",alignItems:"baseline",justifyContent:"space-between",marginBottom:16},switcherTitle:{color:"#e0e0e0",fontSize:18,fontWeight:"600"},switcherListLink:{color:"#8fd4b4",fontSize:14},switcherList:{flexGrow:0,padding:4,margin:-4},switcherItem:{paddingVertical:12,paddingHorizontal:12,borderRadius:8,backgroundColor:"#2a2a2a",marginBottom:8},switcherItemActive:{outlineWidth:2,outlineStyle:"solid",outlineColor:"#4caf50",outlineOffset:2},switcherItemEnded:{opacity:.5},switcherItemSummary:{color:"#9a9aa0",fontSize:12,lineHeight:12,whiteSpace:"nowrap"},switcherEmpty:{color:"#888",fontSize:14,textAlign:"center",paddingVertical:20},switcherCancel:{paddingVertical:12,alignItems:"center",marginTop:4},switcherCancelText:{color:"#888",fontSize:15},lightboxBackdrop:{flex:1,backgroundColor:"rgba(0, 0, 0, 0.95)",justifyContent:"center",alignItems:"center",padding:8},lightboxImage:{width:"100%",height:"92%"},lightboxHint:{color:"#888",fontSize:14,marginTop:20},reloadButton:{paddingHorizontal:8,paddingVertical:4,marginRight:4},reloadText:Object.assign({fontSize:20},{transition:"text-shadow 160ms ease"}),reloadTextActive:Object.assign({},{textShadow:["0 0 10px rgba(140, 230, 170, 0.9)","0 0 25px rgba(120, 215, 155, 0.7)","0 0 50px rgba(100, 200, 145, 0.4)","0 2px 15px rgba(130, 220, 165, 0.6)"].join(", ")})})},10,[11,13,105,106,113,145,146,153,26,160,116,161,165,736,745,759,762,773,769,754,774,771,770,776,778,780,786,761,958,959,972,779,973,950,751,976,977,747,978,980,6]);
27
27
  __d(function(g,r,i,a,m,e,d){'use strict';m.exports=r(d[0])},11,[12]);
28
28
  __d(function(g,r,_i,a,m,e,d){
29
29
  /**
@@ -872,7 +872,7 @@ __d(function(g,r,i,a,m,_e,d){"use strict";Object.defineProperty(_e,'__esModule',
872
872
  __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),Object.defineProperty(e,"revivesAsTwin",{enumerable:!0,get:function(){return o.revivesAsTwin}}),e.narrativeMenuItems=function(t){return(0,o.narrativeMenuItems)(t)},e.openNarrativeExport=async function(o,c,s,u="only"){try{const l=await(0,t.fetchNarrativeExportHtml)(o,c,(0,n.readRecolorSalt)(c),s,u);window.open(URL.createObjectURL(l),"_blank")}catch(t){console.error("Export failed:",t)}};var t=r(d[0]),n=r(d[1]),o=r(d[2])},769,[745,770,772]);
873
873
  __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.readRecolorSalt=o,e.bumpRecolorSalt=function(c){const l=o(c)+1;try{localStorage.setItem((0,t.recolorStorageKey)(c),String(l))}catch{}return l};var t=r(d[0]);function o(o){try{return(0,t.parseRecolorSalt)(localStorage.getItem((0,t.recolorStorageKey)(o)))}catch{return 0}}},770,[771]);
874
874
  __d(function(g,r,_i,a,m,e,d){"use strict";function t(t){let n=0;for(let o=0;o<t.length;o++)n=t.charCodeAt(o)+((n<<5)-n);return n}function n(n,o=0){let u=t(n);var l;return o&&(l=u^Math.imul(o,2654435761),l^=l>>>16,l=Math.imul(l,2246822507),l^=l>>>13,l=Math.imul(l,3266489909),u=0|(l^=l>>>16)),Math.abs(u)%360}Object.defineProperty(e,'__esModule',{value:!0}),e.speakerHue=n,e.speakerColor=function(t,o=0){return`hsl(${n(t,o)}, 60%, 80%)`},e.speakerBgColor=function(t,o=0){return`hsl(${n(t,o)}, 30%, 20%)`},e.recolorStorageKey=function(t){return`brane:recolor:${t}`},e.parseRecolorSalt=function(t){const n=Number(t);return Number.isInteger(n)&&n>0?n:0}},771,[]);
875
- __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.revivesAsTwin=function(n){return"external"===n||"absorbed"===n},e.narrativeMenuItems=function({role:n,status:o,mcpConnected:l,archived:s=!1,isIsolated:c=!1,canIsolate:t=!0,selectedCount:b=0,onMeld:u,onIsolate:v,onExport:P,onRecolor:x,onTwin:p,onRevive:E,onEnd:I,onArchiveToggle:f}){const h="ended"===o&&!l;return[{icon:"\ud83d\udd96",label:"Meld",onPress:u},...t?[{icon:c?"\ud83c\udfd8\ufe0f":"\ud83c\udfe0",label:c?"Unisolate":"Isolate",onPress:v}]:[],...b>0?[{icon:"\ud83d\udce8",label:`Export ${b} selected`,onPress:()=>P("selected")},{icon:"\ud83d\udce4",label:`Export ${b} excluded`,onPress:()=>P("excluded")}]:[{icon:"\ud83d\udce8",label:"Export",onPress:()=>P("all")}],{icon:"\ud83c\udfa8",label:"Recolor",onPress:x},{icon:"\ud83e\uddec",label:"Twin",onPress:p},..."external"===n?[]:[h?{icon:"\ud83d\udc26\u200d\ud83d\udd25",label:"Revive",onPress:E}:{icon:"\ud83e\udee0",label:"End",onPress:I}],{icon:s?"\ud83d\udcc2":"\ud83d\uddc4\ufe0f",label:s?"Unarchive":"Archive",onPress:f}]}},772,[]);
875
+ __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.revivesAsTwin=function(n){return"external"===n||"absorbed"===n},e.narrativeMenuItems=function({role:n,status:o,mcpConnected:l,archived:s=!1,isIsolated:c=!1,canIsolate:t=!0,selectedCount:b=0,onMeld:u,onIsolate:v,onExport:P,onRecolor:x,onTwin:p,onRevive:E,onEnd:I,onArchiveToggle:f}){const h="ended"===o&&!l;return[{icon:"\ud83d\udd96",label:"Meld",onPress:u},...t?[{icon:c?"\ud83c\udfd8\ufe0f":"\ud83c\udfe0",label:c?"Unisolate":"Isolate",onPress:v}]:[],...b>0?[{icon:"\ud83d\udce8",label:`Export ${b} selected`,onPress:()=>P("selected")},{icon:"\ud83d\udce4",label:`Export ${b} excluded`,onPress:()=>P("excluded")}]:[{icon:"\ud83d\udce8",label:"Export",onPress:()=>P("all")}],{icon:"\ud83c\udfa8",label:"Recolor",onPress:x},{icon:"\ud83e\uddec",label:"Twin",onPress:p},..."external"===n?[]:[h?{icon:"\ud83d\udc26\u200d\ud83d\udd25",label:"Revive",onPress:E}:{icon:"\ud83e\udee0",label:"End",onPress:I}],...s?[{icon:"\ud83d\udcc2",label:"Unarchive",onPress:f}]:h?[{icon:"\ud83d\uddc4\ufe0f",label:"Archive",onPress:f}]:[]]}},772,[]);
876
876
  __d(function(g,r,i,a,m,_e,d){"use strict";Object.defineProperty(_e,'__esModule',{value:!0}),Object.defineProperty(_e,"default",{enumerable:!0,get:function(){return s}});var e,n=r(d[0]),t=r(d[1]),o=(e=t)&&e.__esModule?e:{default:e},l=r(d[2]);function s({items:e,onClose:s,align:c="below",hue:u="green"}){const p=(0,n.useRef)(null);return(0,n.useEffect)(()=>{const e=e=>{p.current&&!p.current.contains(e.target)&&(e.preventDefault(),e.stopPropagation(),document.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation()},{capture:!0,once:!0}),s())};return document.addEventListener("mousedown",e,!0),()=>document.removeEventListener("mousedown",e,!0)},[s]),(0,l.jsx)(o.default,{ref:p,hue:u,style:{right:16,top:"beside"===c?"50%":"calc(100% + 4px)",transform:"beside"===c?"translateY(-50%)":void 0,padding:4,display:"flex",flexDirection:"column",gap:2,minWidth:120},children:e.map(e=>(0,l.jsxs)("button",{onClick:n=>{n.stopPropagation(),e.onPress()},style:{padding:"10px 14px",borderRadius:6,border:"none",backgroundColor:"transparent",color:"#ccc",fontSize:15,lineHeight:"21px",cursor:"pointer",textAlign:"left",whiteSpace:"nowrap",display:"flex",alignItems:"center",gap:10},onPointerEnter:e=>{e.currentTarget.style.backgroundColor=`rgba(${(0,t.menuHueRgb)(u)}, 0.18)`},onPointerLeave:e=>{e.currentTarget.style.backgroundColor="transparent"},children:[e.icon?(0,l.jsx)("span",{style:{fontSize:20,lineHeight:"20px"},children:e.icon}):null,(0,l.jsx)("span",{children:e.label})]},e.label))})}},773,[11,767,6]);
877
877
  __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),Object.defineProperty(e,"MessageSelection",{enumerable:!0,get:function(){return n.MessageSelection}}),e.useMessageSelection=function(s){return(0,t.useMemo)(()=>new n.MessageSelection,[s])},e.useIsSelected=function(n,s){const c=(0,t.useCallback)(t=>n.subscribeSeq(s,t),[n,s]),u=(0,t.useCallback)(()=>n.has(s),[n,s]);return(0,t.useSyncExternalStore)(c,u,u)},e.useSelectedSeqs=function(n){return(0,t.useSyncExternalStore)(n.subscribe,n.getSelected,n.getSelected)};var t=r(d[0]),n=r(d[1])},774,[11,775]);
878
878
  __d(function(g,r,i,_a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),Object.defineProperty(e,"MessageSelection",{enumerable:!0,get:function(){return s}});const t=Object.freeze([]);class s{selected=new Set;snapshot=t;perSeq=new Map;whole=new Set;has=t=>this.selected.has(t);get size(){return this.selected.size}getSelected=()=>this.snapshot;subscribe=t=>(this.whole.add(t),()=>{this.whole.delete(t)});subscribeSeq=(t,s)=>{let c=this.perSeq.get(t);return c||(c=new Set,this.perSeq.set(t,c)),c.add(s),()=>{const c=this.perSeq.get(t);c&&(c.delete(s),0===c.size&&this.perSeq.delete(t))}};toggle=t=>{const s=!this.selected.has(t);return s?this.selected.add(t):this.selected.delete(t),this.commit([t]),s};clear=()=>{if(0===this.selected.size)return[];const t=[...this.selected];return this.selected.clear(),this.commit(t),t};replace=t=>{const s=new Set;for(const c of t)Number.isInteger(c)&&c>0&&s.add(c);const c=[];for(const t of this.selected)s.has(t)||c.push(t);for(const t of s)this.selected.has(t)||c.push(t);0!==c.length&&(this.selected=s,this.commit(c))};commit(s){this.snapshot=0===this.selected.size?t:[...this.selected].sort((t,s)=>t-s);for(const t of s){const s=this.perSeq.get(t);if(s)for(const t of[...s])t()}for(const t of[...this.whole])t()}}},775,[]);
@@ -172,6 +172,6 @@
172
172
  </noscript>
173
173
  <!-- The root element for your Expo app. -->
174
174
  <div id="root"></div>
175
- <script src="/_expo/static/js/web/entry-e94247f119fdcd3b424a1764233a41d2.js" defer></script>
175
+ <script src="/_expo/static/js/web/entry-807575a48b8a2f18f8bffe53c8b35fbd.js" defer></script>
176
176
  </body>
177
177
  </html>
package/expo/dist/sw.js CHANGED
@@ -4,10 +4,10 @@
4
4
  // in `dist/sw.js` by scripts/gen-precache.mjs, which reads the export that was
5
5
  // actually produced. Editing them here has no effect on a build; see that script
6
6
  // for why the list is generated rather than maintained by hand.
7
- const CACHE_NAME = "brane-6ce22c4f8738";
7
+ const CACHE_NAME = "brane-632e51685feb";
8
8
  const PRECACHE = [
9
9
  "/",
10
- "/_expo/static/js/web/entry-e94247f119fdcd3b424a1764233a41d2.js",
10
+ "/_expo/static/js/web/entry-807575a48b8a2f18f8bffe53c8b35fbd.js",
11
11
  "/assets/node_modules/@react-navigation/elements/lib/module/assets/back-icon-mask.0a328cd9c1afd0afe8e3b1ec5165b1b4.png",
12
12
  "/assets/node_modules/@react-navigation/elements/lib/module/assets/back-icon.35ba0eaec5a4f5ed12ca16fabeae451d.png",
13
13
  "/assets/node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55.png",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brane",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Userspace daemon and CLI for narrative agent sessions",
5
5
  "keywords": [
6
6
  "agents",