@ai-ecoverse/slicc-spectrum 1.27.3 → 1.28.1

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
@@ -9582,7 +9582,7 @@ var SliccAgents = class extends ModelElement {
9582
9582
  if (!port?.drop) return;
9583
9583
  const ok = await confirm({
9584
9584
  title: `Drop scoop ${agent.name}?`,
9585
- body: "It stops working. Its files stay.",
9585
+ body: "It stops, and its working folder is deleted. Its conversation and reports are kept. You can\u2019t undo this.",
9586
9586
  action: "Drop",
9587
9587
  variant: "destructive",
9588
9588
  trigger: trigger2
@@ -13953,8 +13953,8 @@ function hint(port) {
13953
13953
  return "Preparing your agent. You can keep working; this panel closes when the agent is ready.";
13954
13954
  }
13955
13955
  function updatesStatus(items) {
13956
- const failed = items.filter((item2) => item2.state === "failed").length;
13957
- if (failed) return `${failed} failed`;
13956
+ const failed2 = items.filter((item2) => item2.state === "failed").length;
13957
+ if (failed2) return `${failed2} failed`;
13958
13958
  const busy = items.filter((item2) => running.has(item2.state)).length;
13959
13959
  if (busy) return `updating ${busy}`;
13960
13960
  if (items.some((item2) => item2.state === "ready" || item2.state === "available")) {
@@ -13970,13 +13970,13 @@ var UpdateVisibility = class {
13970
13970
  this.#boot = !ready;
13971
13971
  }
13972
13972
  change(port, layout = false) {
13973
- const failed = new Set(
13973
+ const failed2 = new Set(
13974
13974
  port.list().filter((item2) => item2.state === "failed").map((item2) => item2.id)
13975
13975
  );
13976
- const open = (this.#initial || layout) && this.#boot || [...failed].some((id) => !this.#failed.has(id));
13976
+ const open = (this.#initial || layout) && this.#boot || [...failed2].some((id) => !this.#failed.has(id));
13977
13977
  this.#initial = false;
13978
- this.#failed = failed;
13979
- if (this.#boot && port.ready() && failed.size === 0) {
13978
+ this.#failed = failed2;
13979
+ if (this.#boot && port.ready() && failed2.size === 0) {
13980
13980
  this.#boot = false;
13981
13981
  return "close";
13982
13982
  }
@@ -18807,6 +18807,10 @@ var actionLabels = {
18807
18807
  login: "Log in",
18808
18808
  "drop-turn": "Drop the last turn"
18809
18809
  };
18810
+ function actionLabel(action, handlers, messageId) {
18811
+ const count = action === "drop-turn" ? handlers.dropping(messageId) : 1;
18812
+ return count > 1 ? `Drop ${count} failed turns` : actionLabels[action];
18813
+ }
18810
18814
  function time(at) {
18811
18815
  return new Date(at).toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit" });
18812
18816
  }
@@ -18858,14 +18862,14 @@ function tool(call, color = "light") {
18858
18862
  </details>`;
18859
18863
  }
18860
18864
  function cluster(calls, open, color) {
18861
- const failed = calls.filter((call) => call.status === "error").length;
18865
+ const failed2 = calls.filter((call) => call.status === "error").length;
18862
18866
  const running2 = calls.some((call) => call.status === "running");
18863
18867
  return b`<details class="cluster" ?open=${open || running2}>
18864
18868
  <summary>
18865
18869
  <span class="chevron" aria-hidden="true">▸</span>
18866
18870
  <span class="title">${calls.length} steps</span>
18867
18871
  <span class="names">${[...new Set(calls.map((call) => call.name))].join(" \xB7 ")}</span>
18868
- ${failed ? b`<span class="state failed">${toolStates.error[1]}${failed} failed</span>` : A}
18872
+ ${failed2 ? b`<span class="state failed">${toolStates.error[1]}${failed2} failed</span>` : A}
18869
18873
  </summary>
18870
18874
  ${calls.map((call) => tool(call, color))}
18871
18875
  </details>`;
@@ -18987,7 +18991,7 @@ function part(entry, handlers, showThinking) {
18987
18991
  default:
18988
18992
  return b`<div class="error-card" role="alert">
18989
18993
  <div class="error-text"><span class="lead">${entry.message}</span>${entry.detail ? b`<span class="detail">${entry.detail}</span>` : A}</div>
18990
- ${entry.action ? b`<swc-button size="s" variant="secondary" fill-style="outline" data-action=${entry.action} ?disabled=${handlers.readOnly} @click=${() => handlers.action(entry.action)}>${actionLabels[entry.action]}</swc-button>` : A}
18994
+ ${entry.action ? b`<swc-button size="s" variant="secondary" fill-style="outline" data-action=${entry.action} ?disabled=${handlers.readOnly} @click=${() => handlers.action(entry.action)}>${actionLabel(entry.action, handlers, "")}</swc-button>` : A}
18991
18995
  </div>`;
18992
18996
  }
18993
18997
  }
@@ -19083,7 +19087,11 @@ function assistant(message, name, model, handlers, showThinking, suggestion = nu
19083
19087
  ${status(message)}
19084
19088
  ${parts(
19085
19089
  message.parts,
19086
- { ...handlers, action: (action) => handlers.action(action, message.id) },
19090
+ {
19091
+ ...handlers,
19092
+ action: (action) => handlers.action(action, message.id),
19093
+ dropping: () => handlers.dropping(message.id)
19094
+ },
19087
19095
  showThinking,
19088
19096
  message.status === "streaming"
19089
19097
  )}
@@ -19126,7 +19134,7 @@ function system(message, handlers) {
19126
19134
  "Error",
19127
19135
  b`<div class="error-card system-error" role="alert" data-id=${message.id}>
19128
19136
  <div class="error-text"><strong>${message.title}</strong><span>${message.text}</span></div>
19129
- ${message.action ? b`<swc-button size="s" variant="secondary" fill-style="outline" data-action=${message.action} ?disabled=${handlers.readOnly} @click=${() => handlers.action(message.action, message.id)}>${actionLabels[message.action]}</swc-button>` : A}
19137
+ ${message.action ? b`<swc-button size="s" variant="secondary" fill-style="outline" data-action=${message.action} ?disabled=${handlers.readOnly} @click=${() => handlers.action(message.action, message.id)}>${actionLabel(message.action, handlers, message.id)}</swc-button>` : A}
19130
19138
  </div>`
19131
19139
  );
19132
19140
  }
@@ -19699,6 +19707,20 @@ var navigation = /* @__PURE__ */ new Set([
19699
19707
  "PageUp",
19700
19708
  "PageDown"
19701
19709
  ]);
19710
+ var failed = (message) => message.role === "assistant" ? message.status === "error" : message.role === "system" && message.kind === "error";
19711
+ function failedTurns(messages, messageId) {
19712
+ const at = messages.findIndex((message) => message.id === messageId);
19713
+ const turns = messages.flatMap(
19714
+ (message, index) => message.role === "user" && index < at ? [index] : []
19715
+ );
19716
+ const ids = [messageId];
19717
+ for (let turn = turns.length - 1; turn > 0; turn--) {
19718
+ const error = messages.slice(turns[turn - 1], turns[turn]).find(failed);
19719
+ if (!error) break;
19720
+ ids.push(error.id);
19721
+ }
19722
+ return ids;
19723
+ }
19702
19724
  var touched = false;
19703
19725
  document.addEventListener(
19704
19726
  "pointerdown",
@@ -19791,6 +19813,7 @@ var SliccChat = class extends ThemedElement {
19791
19813
  answer: (questionId, answer) => this.model?.agent.answer(this.#id(), questionId, answer),
19792
19814
  resolve: (messageId, state) => this.model?.agent.resolveLick(this.#id(), messageId, state),
19793
19815
  action: (action, messageId) => this.#action(action, messageId),
19816
+ dropping: (messageId) => failedTurns(this.model.agent.messages(this.#id()), messageId).length,
19794
19817
  open: (path) => this.dispatchEvent(
19795
19818
  new CustomEvent("open-file", { detail: { path }, bubbles: true, composed: true })
19796
19819
  ),
@@ -19880,9 +19903,15 @@ var SliccChat = class extends ThemedElement {
19880
19903
  return this.model?.agent.list().find((agent) => agent.id === id);
19881
19904
  }
19882
19905
  async #rewind(id, messageId) {
19883
- const restored = await this.model?.agent.rewind?.(id, messageId);
19906
+ const messages = this.model?.agent.messages(id) ?? [];
19907
+ const at = messages.findIndex((message) => message.id === messageId);
19908
+ const latest = messages.findLast(
19909
+ (message, index) => index < at && message.role === "user"
19910
+ );
19911
+ const first2 = failedTurns(messages, messageId).at(-1);
19912
+ const restored = await this.model?.agent.rewind?.(id, first2);
19884
19913
  if (!restored) return;
19885
- this.renderRoot.querySelector("slicc-composer")?.restore(restored);
19914
+ this.renderRoot.querySelector("slicc-composer")?.restore(latest ? { text: latest.text, attachments: latest.attachments } : restored);
19886
19915
  }
19887
19916
  #action(action, messageId = "") {
19888
19917
  const model = this.model;
@@ -21826,6 +21855,7 @@ function visible(memories, scope, tag3, query) {
21826
21855
  (memory) => memory.scope === scope && (tag3 === "all" || (tag3 === "untagged" ? memory.tag === null : memory.tag === tag3)) && (!needle || `${memory.title} ${memory.body} ${memory.section}`.toLowerCase().includes(needle))
21827
21856
  );
21828
21857
  }
21858
+ var scopeGroups = { cones: "Cones", roles: "Roles" };
21829
21859
  var tagLabels = {
21830
21860
  user: "User",
21831
21861
  feedback: "Feedback",
@@ -21918,6 +21948,12 @@ var SliccMemory = class extends ModelElement {
21918
21948
  font-weight: var(--swc-bold-font-weight);
21919
21949
  line-height: var(--swc-line-height-100);
21920
21950
  }
21951
+ .from {
21952
+ grid-column: 1 / -1;
21953
+ margin-top: var(--swc-spacing-50);
21954
+ font-size: var(--swc-font-size-75);
21955
+ color: var(--swc-neutral-subdued-content-color-default);
21956
+ }
21921
21957
  .summary {
21922
21958
  grid-column: 1 / -1;
21923
21959
  color: var(--swc-neutral-subdued-content-color-default);
@@ -22008,6 +22044,7 @@ var SliccMemory = class extends ModelElement {
22008
22044
  <span class="title">${memory.title}</span>
22009
22045
  ${memory.tag ? b`<swc-badge size="s" variant="neutral" subtle>${tagLabels[memory.tag]}</swc-badge>` : A}
22010
22046
  ${open ? A : b`<span class="summary">${memory.body}</span>`}
22047
+ ${memory.source === "notes" ? b`<span class="from">From MEMORY.md</span>` : A}
22011
22048
  </button>
22012
22049
  ${open ? b`<div class="body">${markdown(memory.body)}</div>
22013
22050
  <div class="actions">
@@ -22020,19 +22057,33 @@ var SliccMemory = class extends ModelElement {
22020
22057
  </div>` : A}
22021
22058
  </div>`;
22022
22059
  }
22023
- render() {
22060
+ #scopes = [];
22061
+ willUpdate(changed) {
22062
+ super.willUpdate(changed);
22024
22063
  const model = this.model;
22025
- const all2 = model?.memory.list() ?? [];
22026
- const shown = visible(all2, this.scope, this.tag, this.query);
22027
- const cones = (model?.agent.list() ?? []).filter((agent) => agent.kind === "cone");
22028
- return b`<div class="bar"><span>${shown.length} of ${all2.filter((memory) => memory.scope === this.scope).length} memories</span><span class="spacer"></span>
22064
+ this.#scopes = model?.memory.scopes?.() ?? [
22065
+ { id: "global", label: "Everyone" },
22066
+ ...(model?.agent.list() ?? []).filter((agent) => agent.kind === "cone").map((cone) => ({ id: cone.id, label: cone.name }))
22067
+ ];
22068
+ if (!this.#scopes.some((item2) => item2.id === this.scope)) this.scope = "global";
22069
+ }
22070
+ render() {
22071
+ const all2 = this.model?.memory.list() ?? [];
22072
+ const scopes = this.#scopes;
22073
+ const scope = this.scope;
22074
+ const option2 = (item2) => b`<sp-menu-item value=${item2.id}>${item2.label}</sp-menu-item>`;
22075
+ const shown = visible(all2, scope, this.tag, this.query);
22076
+ return b`<div class="bar"><span>${shown.length} of ${all2.filter((memory) => memory.scope === scope).length} memories</span><span class="spacer"></span>
22029
22077
  <swc-action-button size="s" quiet @click=${() => this.editing = "new"}><swc-icon-add slot="icon"></swc-icon-add>Remember</swc-action-button>
22030
22078
  </div>
22031
22079
  <div class="tools">
22032
22080
  <sp-search size="s" label="Search memories" placeholder="Search memories" .value=${this.query} @input=${(event2) => this.query = event2.target.value} @submit=${(event2) => event2.preventDefault()}></sp-search>
22033
- <sp-picker size="s" label="Scope" value=${this.scope} @change=${(event2) => this.scope = event2.target.value}>
22034
- <sp-menu-item value="global">Everyone</sp-menu-item>
22035
- ${cones.map((cone) => b`<sp-menu-item value=${cone.id}>${cone.name}</sp-menu-item>`)}
22081
+ <sp-picker size="s" label="Scope" value=${scope} @change=${(event2) => this.scope = event2.target.value}>
22082
+ ${scopes.filter((item2) => !item2.group).map(option2)}
22083
+ ${["cones", "roles"].map((group) => {
22084
+ const items = scopes.filter((item2) => item2.group === group);
22085
+ return items.length ? b`<sp-menu-group size="s"><span slot="header">${scopeGroups[group]}</span>${items.map(option2)}</sp-menu-group>` : A;
22086
+ })}
22036
22087
  </sp-picker>
22037
22088
  <sp-picker size="s" label="Tag" value=${this.tag} @change=${(event2) => this.tag = event2.target.value}>
22038
22089
  <sp-menu-item value="all">All tags</sp-menu-item>
@@ -22043,7 +22094,7 @@ var SliccMemory = class extends ModelElement {
22043
22094
  </sp-picker>
22044
22095
  </div>
22045
22096
  <div class="list">
22046
- ${this.editing === "new" ? b`<div class="row">${this.#form({ scope: this.scope })}</div>` : A}
22097
+ ${this.editing === "new" ? b`<div class="row">${this.#form({ scope })}</div>` : A}
22047
22098
  ${shown.length ? sections(shown).map(
22048
22099
  ([section, items]) => b`<h3>${section}</h3>${items.map((memory) => this.#row(memory))}`
22049
22100
  ) : b`<div class="note">${all2.length ? "No memories match." : "No memories yet."}</div>`}
@@ -40675,7 +40726,7 @@ var File = class {
40675
40726
  if (this.editor != null) throw new Error("File.__completeEditSession: detach the editor before completing the session");
40676
40727
  const sessionAnnotationsCurrent = editSessionAnnotations?.current;
40677
40728
  let acceptedFile;
40678
- let failed = false;
40729
+ let failed2 = false;
40679
40730
  let failure2;
40680
40731
  if (editor == null) throw new Error("File.__completeEditSession: editor is required for completion");
40681
40732
  const completedFile = { ...editSessionFile };
@@ -40694,7 +40745,7 @@ var File = class {
40694
40745
  acceptedFile = completedFile;
40695
40746
  }
40696
40747
  } catch (error) {
40697
- failed = true;
40748
+ failed2 = true;
40698
40749
  failure2 = error;
40699
40750
  }
40700
40751
  if (installResult && acceptedFile != null) {
@@ -40706,7 +40757,7 @@ var File = class {
40706
40757
  this.fileRenderer.endEditSession(settledFile);
40707
40758
  if (renderedFile != null && settledFile != null && renderedFile !== settledFile && areFileTargetsEqual(renderedFile, settledFile)) this.renderedFile = settledFile;
40708
40759
  if (installResult && this.fileContainer != null) this.rerender();
40709
- if (failed) throw failure2;
40760
+ if (failed2) throw failure2;
40710
40761
  }
40711
40762
  applyDocumentChange(textDocument, newLineAnnotations) {
40712
40763
  const editSessionFile = this.editSession?.file;
@@ -46960,7 +47011,7 @@ var FileDiff = class {
46960
47011
  let acceptedDiff;
46961
47012
  let acceptedOldFile = null;
46962
47013
  let acceptedNewFile = null;
46963
- let failed = false;
47014
+ let failed2 = false;
46964
47015
  let failure2;
46965
47016
  if (editor == null) throw new Error("FileDiff.__completeEditSession: editor is required for completion");
46966
47017
  const completedDiff = cloneFileDiffMetadata(editSessionDiff);
@@ -46991,7 +47042,7 @@ var FileDiff = class {
46991
47042
  acceptedNewFile = event2.newFile;
46992
47043
  }
46993
47044
  } catch (error) {
46994
- failed = true;
47045
+ failed2 = true;
46995
47046
  failure2 = error;
46996
47047
  }
46997
47048
  if (installResult && acceptedDiff != null) {
@@ -47004,7 +47055,7 @@ var FileDiff = class {
47004
47055
  }
47005
47056
  this.editSession = void 0;
47006
47057
  if (installResult && this.fileContainer != null) this.rerender();
47007
- if (failed) throw failure2;
47058
+ if (failed2) throw failure2;
47008
47059
  }
47009
47060
  /**
47010
47061
  * Run the session-end recompute: restore recompute-shaped hunks (a