@ai-ecoverse/slicc-spectrum 1.80.0 → 1.82.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/slicc-ui.js CHANGED
@@ -12142,7 +12142,7 @@ function fallbackModel(options) {
12142
12142
  return offered.find((option2) => option2.default) ?? offered[0];
12143
12143
  }
12144
12144
  function controls(model) {
12145
- if (model.agent.readOnly?.()) return false;
12145
+ if (model.seat || model.agent.readOnly?.()) return false;
12146
12146
  const state2 = model.follow?.state();
12147
12147
  return !state2 || !!state2.access.control && state2.link === "connected";
12148
12148
  }
@@ -14685,7 +14685,7 @@ var SliccNetwork = class extends ModelElement {
14685
14685
  render() {
14686
14686
  const port = this.model?.network;
14687
14687
  if (!port) {
14688
- return b`<div class="page" tabindex="-1"><p class="muted">Network information is not connected.</p></div>`;
14688
+ return b`<div class="page" tabindex="-1">${this.model?.guests ? this.#guestsSection() : b`<p class="muted">Network information is not connected.</p>`}</div>`;
14689
14689
  }
14690
14690
  const status2 = networkStatus(port);
14691
14691
  return b`<div class="page" tabindex="-1">
@@ -31229,7 +31229,8 @@ function actionLabel(action, handlers, messageId) {
31229
31229
  }
31230
31230
  function errorCard(item2, handlers) {
31231
31231
  const id = item2.id ?? "";
31232
- const action = item2.action ? b`<swc-button size="s" variant="secondary" fill-style="outline" data-action=${item2.action} ?disabled=${handlers.readOnly} @click=${() => handlers.action(item2.action, item2.id)}>${actionLabel(item2.action, handlers, id)}</swc-button>` : A;
31232
+ const fix = handlers.seat === void 0 ? item2.action : void 0;
31233
+ const action = fix ? b`<swc-button size="s" variant="secondary" fill-style="outline" data-action=${fix} ?disabled=${handlers.readOnly} @click=${() => handlers.action(fix, item2.id)}>${actionLabel(fix, handlers, id)}</swc-button>` : A;
31233
31234
  return b`<div class="error-card" role="alert" data-id=${id || A}>
31234
31235
  <swc-icon-alert-diamond class="icon" size="s" aria-hidden="true"></swc-icon-alert-diamond>
31235
31236
  <span class="sr">Error: </span><span class="lead">${item2.title}</span>
@@ -31364,10 +31365,14 @@ function check2(items) {
31364
31365
  ${items.map((entry) => b`<li data-tone=${entry.tone ?? "positive"}><span class="mark" aria-hidden="true">✓</span>${entry.text}</li>`)}
31365
31366
  </ul>`;
31366
31367
  }
31368
+ var hostAnswers = b`<div class="hint" data-host-answers>The host answers this.</div>`;
31367
31369
  function question(item2, handlers) {
31368
31370
  const answer = (value) => handlers.answer(item2.id, value);
31371
+ const guest = handlers.seat !== void 0 && item2.state === "open";
31369
31372
  let body4;
31370
- if (item2.state === "answered") {
31373
+ if (guest) {
31374
+ body4 = hostAnswers;
31375
+ } else if (item2.state === "answered") {
31371
31376
  body4 = b`<div class="answer">✓ ${item2.answer}</div>`;
31372
31377
  } else if (item2.state === "inert") {
31373
31378
  body4 = b`<div class="hint">Only the latest question can be answered here.</div>`;
@@ -31387,13 +31392,13 @@ function question(item2, handlers) {
31387
31392
  <swc-button size="s" variant="accent" data-action="answer" ?disabled=${handlers.readOnly} @click=${(event2) => event2.currentTarget.closest("form")?.requestSubmit()}>Answer</swc-button>
31388
31393
  </form>`;
31389
31394
  }
31390
- return b`<div class="question decision" data-state=${item2.state} data-kind=${item2.kind}>
31395
+ return b`<div class="question decision" data-state=${item2.state} data-kind=${item2.kind} data-guest=${guest ? "" : A}>
31391
31396
  <div class="q">${item2.question}</div>
31392
31397
  ${body4}
31393
31398
  </div>`;
31394
31399
  }
31395
31400
  function questionTurn(item2, handlers, pile) {
31396
- return b`<swc-conversation-turn type="system" class="message decision-turn" data-id=${item2.id} data-state=${item2.state} data-pending=${item2.state === "open" ? "" : A} accessible-label=${`Question: ${item2.question}`} style=${pileStyle(pile)} @click=${reveal} @keydown=${reveal}>${question(item2, handlers)}</swc-conversation-turn>`;
31401
+ return b`<swc-conversation-turn type="system" class="message decision-turn" data-id=${item2.id} data-state=${item2.state} data-pending=${item2.state === "open" && handlers.seat === void 0 ? "" : A} accessible-label=${`Question: ${item2.question}`} style=${pileStyle(pile)} @click=${reveal} @keydown=${reveal}>${question(item2, handlers)}</swc-conversation-turn>`;
31397
31402
  }
31398
31403
  var delegationVerbs = {
31399
31404
  feed: "fed",
@@ -31505,12 +31510,22 @@ function when(at, title = "") {
31505
31510
  function unseen(at) {
31506
31511
  return b`<time class="sr" datetime=${new Date(at).toISOString()}>${time(at)}</time>`;
31507
31512
  }
31508
- function user(message, stamp = true) {
31513
+ function mine(message, seat) {
31514
+ if (message.origin !== "guest") return false;
31515
+ return message.seat === void 0 ? message.from === seat.label : message.seat === seat.id;
31516
+ }
31517
+ function sender(message, seat) {
31518
+ if (seat === void 0) return message.from;
31519
+ if (mine(message, seat)) return void 0;
31520
+ return message.from ?? (message.origin === "agent" ? void 0 : "the host");
31521
+ }
31522
+ function user(message, stamp = true, seat) {
31509
31523
  const delivered = message.delivered ?? (message.mode === "steer" ? "steer" : void 0);
31510
31524
  const agent = message.origin === "agent";
31511
- const name = message.from ?? "an agent";
31512
- const who2 = agent ? name : message.from ? `From ${message.from}` : "";
31513
- const label = agent ? `Request from ${name}` : message.from ? `Message from ${message.from}` : "Your message";
31525
+ const from = sender(message, seat);
31526
+ const name = from ?? "an agent";
31527
+ const who2 = agent ? name : from ? `From ${from}` : "";
31528
+ const label = agent ? `Request from ${name}` : from ? `Message from ${from}` : "Your message";
31514
31529
  const remote = agent || !!message.from && !people.has(message.origin ?? "user");
31515
31530
  return b`<swc-conversation-turn type="user" class="message user" accessible-label=${label} data-id=${message.id} data-mode=${message.mode ?? "send"} data-delivered=${delivered ?? "run"} data-origin=${message.origin ?? "user"} data-remote=${remote ? "" : A}>
31516
31531
  <div class="bubble">
@@ -31618,6 +31633,7 @@ function event(label, content) {
31618
31633
  function outside(label, byline2, content) {
31619
31634
  return b`<swc-conversation-turn type="user" class="event lick-turn" accessible-label=${label}><div class="bubble">${byline2}${content}</div></swc-conversation-turn>`;
31620
31635
  }
31636
+ var ended2 = /* @__PURE__ */ new Set(["Nobody approved this in time.", "It was declined.", "It was withdrawn."]);
31621
31637
  function system(message, handlers) {
31622
31638
  if (message.kind === "compaction") {
31623
31639
  const failed2 = message.state === "fallback" || message.state === "discarded";
@@ -31631,6 +31647,16 @@ function system(message, handlers) {
31631
31647
  </div>`
31632
31648
  );
31633
31649
  }
31650
+ if (message.kind === "notice" && handlers.seat !== void 0 && ended2.has(message.title ?? "")) {
31651
+ return event(
31652
+ "Notice",
31653
+ b`<div class="marker notice" role="note" data-id=${message.id} data-ended>
31654
+ <span class="line"></span>
31655
+ <span class="marker-text"><span class="said" title=${message.text}>“${message.text}”</span> <span class="outcome">${message.title}</span></span>
31656
+ <span class="line"></span>
31657
+ </div>`
31658
+ );
31659
+ }
31634
31660
  if (message.kind === "notice") {
31635
31661
  return event(
31636
31662
  "Notice",
@@ -31728,12 +31754,14 @@ function decision(message, handlers, pile) {
31728
31754
  const at = message.expiresAt;
31729
31755
  const left = at === void 0 ? null : at - Date.now();
31730
31756
  const expired = left !== null && left <= 0;
31731
- const timer = left === null ? A : b`<span class="timer" data-timer aria-hidden="true">${expired ? "Timed out" : clock(left)}</span><span class="sr">${spokenLeft(left, at)}</span>`;
31732
- const actions2 = expired ? A : b`<div class="decide">
31757
+ const guest = handlers.seat !== void 0;
31758
+ const timer = left === null || guest && !expired ? A : b`<span class="timer" data-timer aria-hidden="true">${expired ? "Timed out" : clock(left)}</span><span class="sr">${spokenLeft(left, at)}</span>`;
31759
+ const settled3 = expired || guest;
31760
+ const actions2 = expired ? A : guest ? hostAnswers : b`<div class="decide">
31733
31761
  <swc-button size="s" variant="secondary" fill-style="outline" data-action="deny" ?disabled=${handlers.readOnly} @click=${() => handlers.resolve(message.id, "dismissed")}>Deny</swc-button>
31734
31762
  <swc-button size="s" variant="accent" data-action="allow" ?disabled=${handlers.readOnly} @click=${() => handlers.resolve(message.id, "confirmed")}>Allow</swc-button>
31735
31763
  </div>`;
31736
- return b`<swc-conversation-turn type="system" class="message decision-turn" accessible-label=${`Permission request from ${message.title}`} data-id=${message.id} data-pending=${expired ? A : ""} data-expired=${expired ? "" : A} style=${pileStyle(pile)} @click=${reveal} @keydown=${reveal}>
31764
+ return b`<swc-conversation-turn type="system" class="message decision-turn" accessible-label=${`Permission request from ${message.title}`} data-id=${message.id} data-pending=${settled3 ? A : ""} data-expired=${expired ? "" : A} style=${pileStyle(pile)} @click=${reveal} @keydown=${reveal}>
31737
31765
  <div class="decision" data-kind="approval">
31738
31766
  <div class="decision-head"><span class="who">${message.title}</span>${timer}</div>
31739
31767
  <p class="decision-text">${message.text}</p>
@@ -32396,7 +32424,7 @@ var messageCss = i`
32396
32424
  border-radius: var(--swc-corner-radius-100);
32397
32425
  padding: var(--swc-spacing-200) var(--swc-spacing-300);
32398
32426
  }
32399
- .question[data-state='open'] {
32427
+ .question[data-state='open']:not([data-guest]) {
32400
32428
  border-color: var(--swc-accent-visual-color);
32401
32429
  }
32402
32430
  .question[data-state='inert'] {
@@ -32508,6 +32536,19 @@ var messageCss = i`
32508
32536
  .marker-text .fault {
32509
32537
  color: var(--swc-negative-visual-color);
32510
32538
  }
32539
+ .marker[data-ended] .marker-text {
32540
+ min-inline-size: 0;
32541
+ max-inline-size: 80%;
32542
+ }
32543
+ .marker[data-ended] .said {
32544
+ min-inline-size: 0;
32545
+ overflow: hidden;
32546
+ text-overflow: ellipsis;
32547
+ white-space: nowrap;
32548
+ }
32549
+ .marker[data-ended] .outcome {
32550
+ flex: none;
32551
+ }
32511
32552
  .marker .line {
32512
32553
  min-inline-size: var(--swc-spacing-300);
32513
32554
  }
@@ -33775,7 +33816,7 @@ var SliccApp = class extends ThemedElement {
33775
33816
  const element2 = dock.content(panel.id);
33776
33817
  if (element2 && "model" in element2) element2.model = model;
33777
33818
  }
33778
- if (!model.network && dock.has("network")) dock.close("network");
33819
+ if (!model.network && !model.guests && dock.has("network")) dock.close("network");
33779
33820
  this.#prune();
33780
33821
  const agent = this.#active();
33781
33822
  if (agent && this.#offers("chat")) openChat(dock, agent, this.screen, false, false);
@@ -34088,7 +34129,7 @@ var SliccApp = class extends ThemedElement {
34088
34129
  #available(model = this.model) {
34089
34130
  const terminals = terminalsAllowed(model);
34090
34131
  return this.surfaces.filter(
34091
- (item2) => (item2.id !== "network" || model?.network) && (item2.id !== "terminal" || terminals)
34132
+ (item2) => (item2.id !== "network" || model?.network || model?.guests) && (item2.id !== "terminal" || terminals)
34092
34133
  );
34093
34134
  }
34094
34135
  #updatesIndicator() {
@@ -34159,7 +34200,7 @@ var SliccApp = class extends ThemedElement {
34159
34200
  ${this.#updatesIndicator()}
34160
34201
  ${this.#remoteIndicator()}
34161
34202
  ${this.#networkIndicator()}
34162
- ${this.#offers("chat") ? b`<slicc-tray .model=${this.model} .panels=${["network", "monitor"].filter((id) => this.#offers(id))} ?compact=${this.screen === "phone"} @show-surface=${this.#showSurface}></slicc-tray>` : A}
34203
+ ${this.#offers("chat") ? b`<slicc-tray .model=${this.model} .panels=${["network", "monitor"].filter((id) => this.#offers(id) && (id !== "network" || this.model?.network))} ?compact=${this.screen === "phone"} @show-surface=${this.#showSurface}></slicc-tray>` : A}
34163
34204
  <sp-action-menu size="s" quiet label="View" @change=${this.#view}>
34164
34205
  <swc-icon-view-grid slot="icon"></swc-icon-view-grid>
34165
34206
  <span slot="label" class="view-label">View</span>
@@ -36903,6 +36944,10 @@ function pendingPiles(messages) {
36903
36944
  return new Map(keys.map((key2, stack) => [key2, { stack }]));
36904
36945
  }
36905
36946
  var failed = (message) => message.role === "assistant" ? message.status === "error" : message.role === "system" && message.kind === "error";
36947
+ function empty(watch, seat, name) {
36948
+ if (watch) return "No messages yet.";
36949
+ return seat ? `No messages yet. Say hello to ${name}.` : `No messages yet. Ask ${name} something.`;
36950
+ }
36906
36951
  function carriesFiles(event2) {
36907
36952
  const types = [...event2.dataTransfer?.types ?? []];
36908
36953
  return types.includes("Files") && !types.includes(dipType);
@@ -36956,7 +37001,7 @@ var SliccChat = class extends ThemedElement {
36956
37001
  return this.renderRoot.querySelector("slicc-composer");
36957
37002
  }
36958
37003
  #over = (event2) => {
36959
- if (!(carriesFiles(event2) && this.#composer())) return;
37004
+ if (!(carriesFiles(event2) && this.#composer()) || this.model?.seat) return;
36960
37005
  event2.preventDefault();
36961
37006
  event2.dataTransfer.dropEffect = "copy";
36962
37007
  if (this.dropping) return;
@@ -37031,6 +37076,10 @@ var SliccChat = class extends ThemedElement {
37031
37076
  min-width: calc(var(--swc-spacing-400) * 4.5);
37032
37077
  margin-inline-start: auto;
37033
37078
  }
37079
+ header .cone {
37080
+ color: var(--swc-neutral-content-color-default);
37081
+ font-weight: var(--swc-bold-font-weight);
37082
+ }
37034
37083
  header .frozen,
37035
37084
  header .model {
37036
37085
  color: var(--swc-neutral-content-color-default);
@@ -37173,7 +37222,9 @@ var SliccChat = class extends ThemedElement {
37173
37222
  }
37174
37223
  #sent(agentId) {
37175
37224
  const last = this.model?.agent.messages(agentId).at(-1);
37176
- return last?.role === "user" && last.id !== this.#tail && (last.origin ?? "user") === "user";
37225
+ if (last?.role !== "user" || last.id === this.#tail) return false;
37226
+ const seat = this.model?.seat;
37227
+ return seat ? mine(last, seat) : (last.origin ?? "user") === "user";
37177
37228
  }
37178
37229
  #resize = new ResizeObserver(() => this.#pin());
37179
37230
  #fitted = null;
@@ -37384,7 +37435,7 @@ var SliccChat = class extends ThemedElement {
37384
37435
  );
37385
37436
  }
37386
37437
  case "user":
37387
- return user(message, stamp);
37438
+ return user(message, stamp, model.seat);
37388
37439
  case "tool":
37389
37440
  return toolMessage(message, handlers, extra, suggestion, stamp);
37390
37441
  case "system":
@@ -37399,7 +37450,7 @@ var SliccChat = class extends ThemedElement {
37399
37450
  let shown4;
37400
37451
  const model = this.model;
37401
37452
  const last = messages.at(-1);
37402
- const suggestion = last?.role === "assistant" && !agent.frozen && !watchOnly(model) && !model.agent.busy(agent.id) ? model.agent.suggestion(agent.id) : null;
37453
+ const suggestion = last?.role === "assistant" && !agent.frozen && !watchOnly(model) && !model.seat && !model.agent.busy(agent.id) ? model.agent.suggestion(agent.id) : null;
37403
37454
  const showThinking = model.settings.get().showThinking;
37404
37455
  const extra = /* @__PURE__ */ new Map();
37405
37456
  const owners = /* @__PURE__ */ new Map();
@@ -37468,9 +37519,11 @@ var SliccChat = class extends ThemedElement {
37468
37519
  this.model.agent.clear(agent.id);
37469
37520
  this.renderRoot.querySelector("slicc-composer")?.focus();
37470
37521
  }
37471
- #meta(agent, empty2) {
37522
+ #meta(agent, empty3) {
37472
37523
  const model = this.model;
37473
37524
  const fill2 = Math.round(agent.contextFill * 100);
37525
+ if (model.seat)
37526
+ return b`<span class="cone" data-seat-cone>${agent.name}</span>${statusLight(agent.status)}`;
37474
37527
  const meter = b`<swc-meter size="s" label-position="side" value=${fill2} variant=${meterVariant(fill2)}><span slot="label">Context</span></swc-meter>`;
37475
37528
  if (agent.frozen) {
37476
37529
  return b`<swc-badge size="s" variant="informative" subtle>Frozen</swc-badge>
@@ -37496,7 +37549,7 @@ var SliccChat = class extends ThemedElement {
37496
37549
  <sp-menu-item value="high">Think hard</sp-menu-item>
37497
37550
  </sp-picker>
37498
37551
  ${meter}
37499
- <swc-action-button id="new-chat" size="s" quiet data-action="new-chat" accessible-label=${this.compact ? "New conversation" : A} ?disabled=${empty2} @click=${() => this.#newChat(agent)}><swc-icon-new slot="icon"></swc-icon-new>${this.compact ? A : "New conversation"}</swc-action-button>
37552
+ <swc-action-button id="new-chat" size="s" quiet data-action="new-chat" accessible-label=${this.compact ? "New conversation" : A} ?disabled=${empty3} @click=${() => this.#newChat(agent)}><swc-icon-new slot="icon"></swc-icon-new>${this.compact ? A : "New conversation"}</swc-action-button>
37500
37553
  <swc-tooltip for="new-chat" placement="bottom">${agent.kind === "cone" && model.agent.freeze ? "Start a new conversation. This one stays in the Freezer." : "Start a new conversation"}</swc-tooltip>`;
37501
37554
  }
37502
37555
  render() {
@@ -37504,8 +37557,10 @@ var SliccChat = class extends ThemedElement {
37504
37557
  this.#handlers.model = this.model ?? null;
37505
37558
  const agent = this.#agent();
37506
37559
  const watch = watchOnly(this.model);
37507
- this.#handlers.readOnly = !!agent?.frozen || !!watch;
37560
+ const seat = this.model?.seat;
37561
+ this.#handlers.readOnly = !!agent?.frozen || !!watch || !!seat;
37508
37562
  this.#handlers.agentId = agent?.id;
37563
+ this.#handlers.seat = seat?.label;
37509
37564
  const messages = agent ? this.model?.agent.messages(agent.id) ?? [] : [];
37510
37565
  this.#tail = messages.at(-1)?.id ?? "";
37511
37566
  return b`
@@ -37532,7 +37587,7 @@ var SliccChat = class extends ThemedElement {
37532
37587
  this.#items(messages, agent),
37533
37588
  ([key2]) => key2,
37534
37589
  ([, item2]) => item2
37535
- )}</swc-conversation-thread>` : this.model?.tabs?.state().role === "connecting" ? b`<div class="empty" data-connecting>${connecting}</div>` : b`<div class="empty">${watch ? "No messages yet." : `No messages yet. Ask ${agent?.name ?? "the agent"} something.`}</div>`}
37590
+ )}</swc-conversation-thread>` : this.model?.tabs?.state().role === "connecting" ? b`<div class="empty" data-connecting>${connecting}</div>` : b`<div class="empty" data-empty>${empty(watch, seat, agent?.name ?? "the agent")}</div>`}
37536
37591
  </div>
37537
37592
  </div>
37538
37593
  ${this.dropping ? b`<swc-dropzone dragged size="l" aria-label="Attach files" dragged-message="Drop to attach"><p>Drop to attach</p></swc-dropzone>` : A}
@@ -38769,6 +38824,20 @@ function trigger(text2, caret) {
38769
38824
  return { kind: "mention", start: before.length - mention[2].length - 1, query: mention[2] };
38770
38825
  return null;
38771
38826
  }
38827
+ var day3 = 24 * 60 * 60 * 1e3;
38828
+ function reviewer(seat, cone) {
38829
+ const gate = seat.gates.messages;
38830
+ if (gate === "off") return null;
38831
+ if (gate === "user") return "The host";
38832
+ if (gate === "agent") return "An automatic check";
38833
+ return cone;
38834
+ }
38835
+ function seatNote(seat, cone, now = Date.now()) {
38836
+ const who2 = reviewer(seat, cone);
38837
+ const note = who2 ? `${who2} reviews what you send before it reaches the agent.` : `You\u2019re chatting with ${cone} as ${seat.label}.`;
38838
+ const at = seat.expiresAt;
38839
+ return at !== null && at - now < day3 ? `${note} Your link expires at ${deadline(at)}.` : note;
38840
+ }
38772
38841
  function blocked(vault) {
38773
38842
  if (away(vault)) return "Waiting for the vault";
38774
38843
  return vault.status()?.locked ? "Unlock the vault first" : null;
@@ -38785,6 +38854,7 @@ var SliccComposer = class extends ThemedElement {
38785
38854
  sharing: { state: true },
38786
38855
  secretError: { state: true },
38787
38856
  secretField: { state: true },
38857
+ failure: { state: true },
38788
38858
  agent: {}
38789
38859
  };
38790
38860
  #drafts = /* @__PURE__ */ new Map();
@@ -38811,6 +38881,7 @@ var SliccComposer = class extends ThemedElement {
38811
38881
  this.sharing = false;
38812
38882
  this.secretError = null;
38813
38883
  this.secretField = null;
38884
+ this.failure = null;
38814
38885
  this.agent = "";
38815
38886
  }
38816
38887
  static styles = [
@@ -38960,6 +39031,28 @@ var SliccComposer = class extends ThemedElement {
38960
39031
  .failed {
38961
39032
  color: var(--swc-negative-content-color-default);
38962
39033
  }
39034
+ .send-error {
39035
+ display: flex;
39036
+ align-items: flex-start;
39037
+ gap: var(--swc-spacing-75);
39038
+ margin: 0 0 var(--swc-spacing-100);
39039
+ padding: var(--swc-spacing-75) var(--swc-spacing-200);
39040
+ border-radius: var(--swc-corner-radius-medium-default);
39041
+ background: var(--swc-negative-subtle-background-color-default);
39042
+ color: var(--swc-neutral-content-color-default);
39043
+ --swc-icon-color: var(--swc-negative-content-color-default);
39044
+ }
39045
+ .send-error swc-icon-alert-triangle {
39046
+ flex: none;
39047
+ margin-block-start: var(--swc-spacing-50);
39048
+ }
39049
+ .seat-note {
39050
+ margin: var(--swc-spacing-100) 0 0;
39051
+ padding-inline: var(--swc-spacing-200);
39052
+ font-size: var(--swc-font-size-75);
39053
+ color: var(--swc-neutral-subdued-content-color-default);
39054
+ text-align: center;
39055
+ }
38963
39056
  .popup {
38964
39057
  position: absolute;
38965
39058
  left: 0;
@@ -39094,19 +39187,22 @@ var SliccComposer = class extends ThemedElement {
39094
39187
  const field = this.#field;
39095
39188
  void field.updateComplete.then(() => {
39096
39189
  const popover = this.renderRoot.querySelector("swc-popover");
39097
- popover.triggerElement = null;
39098
- popover.triggerElement = field.shadowRoot.querySelector(
39099
- ".swc-PromptField-upload"
39100
- );
39190
+ if (popover) {
39191
+ popover.triggerElement = null;
39192
+ popover.triggerElement = field.shadowRoot.querySelector(
39193
+ ".swc-PromptField-upload"
39194
+ );
39195
+ }
39101
39196
  const area = this.#textarea;
39102
39197
  area.ariaDescribedByElements = [this.renderRoot.querySelector("#keys")];
39103
39198
  });
39104
39199
  }
39105
39200
  subscribe(model) {
39106
39201
  this.#switch(this.agent || model.agent.active());
39107
- void model.files.list().then((entries) => {
39108
- this.#paths = entries.filter((entry) => entry.kind === "file").map((entry) => entry.path);
39109
- });
39202
+ if (!model.seat)
39203
+ void model.files.list().then((entries) => {
39204
+ this.#paths = entries.filter((entry) => entry.kind === "file").map((entry) => entry.path);
39205
+ });
39110
39206
  const update = () => this.requestUpdate();
39111
39207
  return [
39112
39208
  ...super.subscribe(model),
@@ -39162,6 +39258,10 @@ var SliccComposer = class extends ThemedElement {
39162
39258
  const text2 = this.value.trim();
39163
39259
  const attachments = this.attachments.filter((attachment2) => !attachment2.error);
39164
39260
  if (!model || !text2 && attachments.length === 0 || this.#held()) return;
39261
+ if (model.seat) {
39262
+ this.#propose(model, text2);
39263
+ return;
39264
+ }
39165
39265
  const command3 = text2.match(/^\/(\w+)(?:\s+(.*))?$/);
39166
39266
  const known = command3 && available(model).find((candidate) => candidate.name === command3[1]);
39167
39267
  this.value = "";
@@ -39179,6 +39279,17 @@ var SliccComposer = class extends ThemedElement {
39179
39279
  const done2 = () => retire(model.agent, id, attachments);
39180
39280
  model.agent.send(id, { text: text2, attachments, mode: resolved }).then(done2, done2);
39181
39281
  }
39282
+ #propose(model, text2) {
39283
+ this.value = "";
39284
+ this.failure = null;
39285
+ this.#history = -1;
39286
+ model.agent.send(this.#agent, text2).catch((error) => {
39287
+ const draft = this.value.trim();
39288
+ this.value = draft && draft !== text2 ? `${text2}
39289
+ ${this.value}` : text2;
39290
+ this.failure = error instanceof Error ? error.message : String(error);
39291
+ });
39292
+ }
39182
39293
  #id() {
39183
39294
  return `a-${Date.now().toString(36)}-${this.#next++}`;
39184
39295
  }
@@ -39285,7 +39396,7 @@ var SliccComposer = class extends ThemedElement {
39285
39396
  this.#refuse(problem, bad ? "name" : "value", true);
39286
39397
  if (problem) return false;
39287
39398
  const agent = this.#agent;
39288
- const mine = () => this.#agent === agent && this.model?.vault === vault;
39399
+ const mine2 = () => this.#agent === agent && this.model?.vault === vault;
39289
39400
  this.sharing = true;
39290
39401
  try {
39291
39402
  if (exists) {
@@ -39295,16 +39406,16 @@ var SliccComposer = class extends ThemedElement {
39295
39406
  action: "Replace",
39296
39407
  variant: "confirmation"
39297
39408
  });
39298
- if (!sure || !mine()) return false;
39409
+ if (!sure || !mine2()) return false;
39299
39410
  if (blocked(vault)) {
39300
39411
  this.#refuse(blocked(vault));
39301
39412
  return false;
39302
39413
  }
39303
39414
  }
39304
39415
  await vault.put?.(clean, value);
39305
- return mine();
39416
+ return mine2();
39306
39417
  } catch (error) {
39307
- if (mine()) this.#refuse(failureText(error), fieldOf(error, "value"));
39418
+ if (mine2()) this.#refuse(failureText(error), fieldOf(error, "value"));
39308
39419
  return false;
39309
39420
  } finally {
39310
39421
  this.sharing = false;
@@ -39345,7 +39456,7 @@ var SliccComposer = class extends ThemedElement {
39345
39456
  }
39346
39457
  #refresh() {
39347
39458
  const area = this.#textarea;
39348
- if (!area) return;
39459
+ if (!area || this.model?.seat) return;
39349
39460
  if (this.popup?.kind === "file" || this.popup?.kind === "secret") return;
39350
39461
  const found = trigger(this.value, area.selectionStart ?? this.value.length);
39351
39462
  const name = this.value.match(/^\/(\w+)/)?.[1];
@@ -39385,8 +39496,9 @@ var SliccComposer = class extends ThemedElement {
39385
39496
  });
39386
39497
  }
39387
39498
  #recall(delta) {
39499
+ const seat = this.model?.seat;
39388
39500
  const own4 = (this.model?.agent.messages(this.#agent) ?? []).filter(
39389
- (message) => message.role === "user" && !message.from
39501
+ (message) => message.role === "user" && (seat ? mine(message, seat) : !message.from)
39390
39502
  );
39391
39503
  const texts = own4.map((message) => message.text).reverse();
39392
39504
  const next = this.#history + delta;
@@ -39422,7 +39534,7 @@ var SliccComposer = class extends ThemedElement {
39422
39534
  return false;
39423
39535
  }
39424
39536
  #talking() {
39425
- return !!this.model?.settings.get().pushToTalk && !!speech();
39537
+ return !this.model?.seat && !!this.model?.settings.get().pushToTalk && !!speech();
39426
39538
  }
39427
39539
  #shortcut(event2) {
39428
39540
  if (event2.key === "Backspace" || event2.key === "Delete") this.#flash();
@@ -39436,6 +39548,10 @@ var SliccComposer = class extends ThemedElement {
39436
39548
  const area = this.#textarea;
39437
39549
  if (event2.isComposing || !area || event2.composedPath()[0] !== area) return;
39438
39550
  if (this.#shortcut(event2)) return;
39551
+ if (this.model?.seat) {
39552
+ this.#guestKey(event2, area);
39553
+ return;
39554
+ }
39439
39555
  const sendOnEnter = this.model?.settings.get().sendOnEnter ?? true;
39440
39556
  let handled = this.#popupKey(event2) || this.#historyKey(event2, area);
39441
39557
  if (!handled && event2.key === "Tab" && !event2.shiftKey && !this.value) {
@@ -39456,6 +39572,12 @@ var SliccComposer = class extends ThemedElement {
39456
39572
  if (handled) event2.preventDefault();
39457
39573
  if (handled || event2.key === "Enter") event2.stopPropagation();
39458
39574
  }
39575
+ #guestKey(event2, area) {
39576
+ const send = event2.key === "Enter" && !event2.shiftKey;
39577
+ if (send) this.send();
39578
+ if (send || this.#historyKey(event2, area)) event2.preventDefault();
39579
+ if (event2.key === "Enter") event2.stopPropagation();
39580
+ }
39459
39581
  #flash() {
39460
39582
  if (!this.value) return;
39461
39583
  this.erasing = true;
@@ -39469,6 +39591,7 @@ var SliccComposer = class extends ThemedElement {
39469
39591
  return this.value ? "pencil" : "aiLogo";
39470
39592
  }
39471
39593
  #instructions(busy) {
39594
+ if (this.model?.seat) return "Enter sends, Shift+Enter adds a new line.";
39472
39595
  const enter = this.model?.settings.get().sendOnEnter ?? true;
39473
39596
  const keys = enter ? [`Enter ${busy ? "steers" : "sends"}`, ...busy ? ["Ctrl+Enter queues"] : []] : [`Ctrl+Enter ${busy ? "queues" : "sends"}`];
39474
39597
  if (busy) keys.push("Escape stops");
@@ -39667,7 +39790,44 @@ var SliccComposer = class extends ThemedElement {
39667
39790
  )}
39668
39791
  </ul>`;
39669
39792
  }
39793
+ #waiting() {
39794
+ const queued = this.model?.agent.queue(this.#agent) ?? [];
39795
+ if (queued.length === 0) return A;
39796
+ return b`<ul class="queue" aria-label="Waiting for review">
39797
+ ${queued.map(
39798
+ (message) => b`<li class="queued" data-id=${message.id} data-mode="review">
39799
+ <swc-icon-clock size="s" aria-hidden="true"></swc-icon-clock>
39800
+ <span class="text">${message.text}</span>
39801
+ <span class="next">Waiting for review</span>
39802
+ </li>`
39803
+ )}
39804
+ </ul>`;
39805
+ }
39806
+ #guest(seat) {
39807
+ const agent = this.model?.agent.list().find((candidate) => candidate.id === this.#agent);
39808
+ const cone = agent?.name ?? "the agent";
39809
+ return b`<div class="column">
39810
+ <span id="keys" class="sr" aria-hidden="true">${this.#instructions(false)}</span>
39811
+ ${this.#waiting()}
39812
+ ${this.failure ? b`<p class="send-error" role="alert" data-send-error><swc-icon-alert-triangle size="s" aria-hidden="true"></swc-icon-alert-triangle><span>${this.failure}</span></p>` : A}
39813
+ <swc-prompt-field
39814
+ label="Message"
39815
+ collapsed
39816
+ loader=${this.#loader(false)}
39817
+ send-label="Send"
39818
+ max-rows="10"
39819
+ placeholder=${`Message ${cone}`}
39820
+ .value=${l(this.value)}
39821
+ @keydown=${this.#keys}
39822
+ @swc-prompt-field-input=${this.#input}
39823
+ @swc-prompt-field-submit=${() => this.send()}
39824
+ ></swc-prompt-field>
39825
+ <p class="seat-note" data-seat-note>${seatNote(seat, cone)}</p>
39826
+ </div>`;
39827
+ }
39670
39828
  render() {
39829
+ const seat = this.model?.seat;
39830
+ if (seat) return this.#guest(seat);
39671
39831
  const busy = this.#busy();
39672
39832
  const agent = this.model?.agent.list().find((candidate) => candidate.id === this.#agent);
39673
39833
  const suggestion = this.model?.agent.suggestion(this.#agent);
@@ -39729,7 +39889,7 @@ var SliccComposer = class extends ThemedElement {
39729
39889
  // src/app/lucide.ts
39730
39890
  var library = null;
39731
39891
  function load() {
39732
- library ??= import("./chunk-VN3QD44H.js");
39892
+ library ??= import("./chunk-CTTFVKOY.js");
39733
39893
  return library;
39734
39894
  }
39735
39895
  function pascal(name) {
@@ -40444,8 +40604,8 @@ function replaceable(secret) {
40444
40604
  }
40445
40605
  function filename(now = Date.now()) {
40446
40606
  const date = new Date(now);
40447
- const day3 = [date.getFullYear(), date.getMonth() + 1, date.getDate()].map((part2) => String(part2).padStart(2, "0")).join("-");
40448
- return `slicc-secrets-${day3}.slicc-vault`;
40607
+ const day4 = [date.getFullYear(), date.getMonth() + 1, date.getDate()].map((part2) => String(part2).padStart(2, "0")).join("-");
40608
+ return `slicc-secrets-${day4}.slicc-vault`;
40449
40609
  }
40450
40610
  function download(bytes, name, root2) {
40451
40611
  const url = URL.createObjectURL(
@@ -42397,7 +42557,7 @@ var SliccSprinkle = class extends ThemedElement {
42397
42557
  }
42398
42558
  };
42399
42559
  #readOnly() {
42400
- return this.readonly || this.#frozen() || !!watchOnly(this.model);
42560
+ return this.readonly || !!this.model?.seat || this.#frozen() || !!watchOnly(this.model);
42401
42561
  }
42402
42562
  #seen = /* @__PURE__ */ new Set();
42403
42563
  #frozen() {
@@ -42521,7 +42681,7 @@ ${data.html}`;
42521
42681
  const bridged = !!this.model?.sprinkles.call;
42522
42682
  if (bridged && !this.#held.ready) return b``;
42523
42683
  const state2 = bridged ? this.#held : void 0;
42524
- const watch = !!watchOnly(this.model);
42684
+ const watch = !!watchOnly(this.model) || !!this.model?.seat;
42525
42685
  const caption = watch ? b`<span class="view-only" data-view-only>View only on this device</span>` : A;
42526
42686
  const style = `color-scheme:${this.color};${this.inline ? `height:${this.height}px;` : ""}`;
42527
42687
  const frame = b`${i17(
@@ -50991,9 +51151,9 @@ function stringify2(values) {
50991
51151
  // node_modules/hast-util-whitespace/lib/index.js
50992
51152
  var re = /[ \t\n\f\r]/g;
50993
51153
  function whitespace(thing) {
50994
- return typeof thing === "object" ? thing.type === "text" ? empty(thing.value) : false : empty(thing);
51154
+ return typeof thing === "object" ? thing.type === "text" ? empty2(thing.value) : false : empty2(thing);
50995
51155
  }
50996
- function empty(value) {
51156
+ function empty2(value) {
50997
51157
  return value.replace(re, "") === "";
50998
51158
  }
50999
51159
 
@@ -85145,11 +85305,11 @@ var SliccFileTree = class extends HTMLElement {
85145
85305
  return this.hasAttribute("data-empty");
85146
85306
  }
85147
85307
  #matched() {
85148
- const empty2 = !!this.#query && !!this.#tree && this.#tree.getSearchMatchingPaths().length === 0;
85149
- if (empty2 === this.empty) return;
85150
- this.toggleAttribute("data-empty", empty2);
85308
+ const empty3 = !!this.#query && !!this.#tree && this.#tree.getSearchMatchingPaths().length === 0;
85309
+ if (empty3 === this.empty) return;
85310
+ this.toggleAttribute("data-empty", empty3);
85151
85311
  this.dispatchEvent(
85152
- new CustomEvent("tree-matches", { detail: { empty: empty2 }, bubbles: true, composed: true })
85312
+ new CustomEvent("tree-matches", { detail: { empty: empty3 }, bubbles: true, composed: true })
85153
85313
  );
85154
85314
  }
85155
85315
  #searched(value) {