@ai-ecoverse/slicc-spectrum 1.89.0 → 1.89.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/README.md CHANGED
@@ -449,6 +449,7 @@ It closes, clearing the field, when the request leaves `waiting` or while the va
449
449
  #### `<slicc-updates>`
450
450
 
451
451
  Install / Update: component states, version changes, last checks, download and link counts, action buttons, failures with Retry, and collapsible install logs behind a quiet chevron, which stay open across a layout switch.
452
+ An install shows one bar for update rows and package rows alike: it fills 0–50% while downloading and 50–100% while linking (`value` against `max-value="100"`). While the row runs it never goes back, not when pnpm's total grows and not when progress drops out between passes. Its value label stays the phase's "n of m" count, and it starts at 0 again once the row settles.
452
453
  Opens at boot until the agent is ready without failures.
453
454
  Background updates stay in the header's update status; new failures reopen the panel, and after a reload into a boot that isn't ready yet such a panel closes once the agent is ready.
454
455
  Every automatic close is saved to the layout.
@@ -485,8 +486,8 @@ A thawed scoop or agent run keeps its row, which says what it was thawed as.
485
486
  Either way its conversation stays here, and a row without a `kind` counts as a cone.
486
487
  A title longer than two lines ends in an ellipsis and carries its full text as a `title`; the dummy's titles are the whole first line of the first message, so only the card cuts them.
487
488
  A row with `v6: true` came from SLICC 6 and carries a neutral outline **SLICC 6** badge (`data-badge="v6"`, `data-v6` on the row), set apart from the gray model badge.
488
- When the agent port has `importProfile` and `importCancel` and the page is neither watch-only nor a guest seat, the bar offers **Import** with an import icon (`data-action="import-v6"`; its accessible name and tooltip say "Import from SLICC 6"), on the bar's first row at the default width, which picks a `.zip`; dropping a zip on the Freezer (with a "Drop to import" dropzone while dragging) does the same.
489
- A zip is a `.zip` name or an `application/zip` or `application/x-zip-compressed` type; deeper checks are left to the preview. Dropping or picking anything else shows an inline error under the bar (`data-error="not-zip"`, a polite status): "That’s not a SLICC 6 export. Drop the .zip from Export for SLICC 7.", which clears on the next drop or pick, or with its dismiss button (`data-action="dismiss-not-zip"`, which puts focus back on Import).
489
+ When the agent port has `importProfile` and `importCancel` and the page is neither watch-only nor a guest seat, the bar offers **Import from SLICC 6** with an import icon (`data-action="import-v6"`), shortened to **Import** when the Freezer is narrower than 26rem (its accessible name and tooltip always say "Import from SLICC 6"), on the bar's first row, which picks a `.zip`; dropping a zip on the Freezer (with a "Drop to import" dropzone while dragging) does the same.
490
+ A zip is a `.zip` name or an `application/zip` or `application/x-zip-compressed` type; deeper checks are left to the preview. Dropping or picking anything else shows an inline error under the bar (`data-error="not-zip"`, a polite status): "That’s not a SLICC 6 export. Use the .zip from Export for SLICC 7.", which clears on the next drop or pick, or with its dismiss button (`data-action="dismiss-not-zip"`, which puts focus back on Import).
490
491
  Either opens `<slicc-freezer-import>`, a modal (`dialog[data-import]` set to `checking`, `preview`, `importing`, `done` or `failed`): `importProfile(file, { preview: true })` runs behind a progress circle and "Checking the profile…"; then **Import from SLICC 6?** shows the agent's `text`, a summary (cones, scoops, frozen, skills, crons, webhooks, size, on one row when the dialog is wide and in four equal columns when it's narrow, so no cell sits alone on a row) and its notes (`[data-note]`): "You imported this export on {day}." when `already` is set, "Sign in again in Settings: {providers}." (named by their accounts), a **Warning:** with an icon for credential-like files, which are imported for review afterwards (their zip paths as code; more than three fold under a quiet chevron), and a muted "Not imported: {n} mounted folders." behind a folder icon, so every note's text starts at the same edge.
491
492
  **Import** (`data-action="import-confirm"`, **Import again** with `again: true` after an earlier import) runs the import with a progress bar from the `importing` event, announced only when it starts and ends; **Done** (`data-action="import-done"`) after "Imported {n} cones." and the report path with **Copy** (`data-action="copy-report"`) closes it and focuses the first imported row.
492
493
  A rejection shows the error card with its sentence (a check without a `preview` shows "Couldn’t read this export. Try another zip."), **Try again** (`data-action="import-retry"`, picks again) and **Close**; **Cancel** or <kbd>Escape</kbd> while checking or importing calls `importCancel`.
package/dist/slicc-ui.js CHANGED
@@ -26671,7 +26671,7 @@ var frozenKinds = {
26671
26671
  agent: ["purple", "Agent run"]
26672
26672
  };
26673
26673
  var zipTypes = ["application/zip", "application/x-zip-compressed"];
26674
- var notZip = "That\u2019s not a SLICC 6 export. Drop the .zip from Export for SLICC 7.";
26674
+ var notZip = "That\u2019s not a SLICC 6 export. Use the .zip from Export for SLICC 7.";
26675
26675
  function isZip(file) {
26676
26676
  return /\.zip$/i.test(file.name) || zipTypes.includes(file.type);
26677
26677
  }
@@ -26704,6 +26704,18 @@ var SliccFreezer = class extends ModelElement {
26704
26704
  i`
26705
26705
  :host {
26706
26706
  position: relative;
26707
+ container: freezer / inline-size;
26708
+ }
26709
+ .bar .long {
26710
+ display: none;
26711
+ }
26712
+ @container freezer (min-width: 26rem) {
26713
+ .bar .long {
26714
+ display: inline;
26715
+ }
26716
+ .bar .short {
26717
+ display: none;
26718
+ }
26707
26719
  }
26708
26720
  .bar {
26709
26721
  flex-wrap: wrap;
@@ -26928,7 +26940,7 @@ var SliccFreezer = class extends ModelElement {
26928
26940
  const rows2 = freezerOrder(this.model?.agent.frozen() ?? []);
26929
26941
  return b`<div class="bar">
26930
26942
  <span>${rows2.length} ${rows2.length === 1 ? "conversation" : "conversations"}</span>
26931
- ${this.importable ? b`<swc-action-button id="import-v6" size="s" quiet data-action="import-v6" accessible-label="Import from SLICC 6" @click=${() => this.#pick()}><swc-icon-import slot="icon"></swc-icon-import>Import</swc-action-button><swc-tooltip for="import-v6" placement="bottom">Import from SLICC 6</swc-tooltip><input type="file" accept=${[".zip", ...zipTypes].join(",")} hidden data-action="import-file" @change=${this.#picked} />` : A}
26943
+ ${this.importable ? b`<swc-action-button id="import-v6" size="s" quiet data-action="import-v6" accessible-label="Import from SLICC 6" @click=${() => this.#pick()}><swc-icon-import slot="icon"></swc-icon-import><span class="long">Import from SLICC 6</span><span class="short">Import</span></swc-action-button><swc-tooltip for="import-v6" placement="bottom">Import from SLICC 6</swc-tooltip><input type="file" accept=${[".zip", ...zipTypes].join(",")} hidden data-action="import-file" @change=${this.#picked} />` : A}
26932
26944
  </div>
26933
26945
  <div class="error" role="status" aria-live="polite" data-error="not-zip">${this.refused && this.importable ? b`<swc-icon-alert-diamond size="s" aria-hidden="true"></swc-icon-alert-diamond><span>${notZip}</span><swc-action-button size="s" quiet data-action="dismiss-not-zip" accessible-label="Dismiss" @click=${() => this.#dismiss()}><swc-icon-close slot="icon"></swc-icon-close></swc-action-button>` : A}</div>
26934
26946
  <div class="list">
@@ -34894,6 +34906,9 @@ function requiresText(item2, all2) {
34894
34906
  ].filter(Boolean);
34895
34907
  return parts2.length ? parts2.join("; ") : null;
34896
34908
  }
34909
+ var phased = ({ phase, done: done2, total }) => Math.round(((phase === "link" ? 1 : 0) + (total ? Math.min(done2 / total, 1) : 0)) * 50);
34910
+ var itemBusy = (item2) => running.has(item2.state) || item2.state === "starting" || item2.progress !== null;
34911
+ var packageBusy = (item2) => packageRunning.has(item2.state) || item2.progress !== null;
34897
34912
  var snapshot = (items) => new Map(items.map(({ id, state: state2, error }) => [id, { state: state2, error }]));
34898
34913
  function settled2(failures, before, after) {
34899
34914
  return new Map(
@@ -34951,6 +34966,7 @@ var SliccUpdates = class extends ModelElement {
34951
34966
  problems: { state: true }
34952
34967
  };
34953
34968
  #logs = new ViewSet(this, "updates");
34969
+ #reached = /* @__PURE__ */ new Map();
34954
34970
  constructor() {
34955
34971
  super();
34956
34972
  this.pending = /* @__PURE__ */ new Set();
@@ -35187,6 +35203,7 @@ var SliccUpdates = class extends ModelElement {
35187
35203
  this.failures = /* @__PURE__ */ new Map();
35188
35204
  this.busy = /* @__PURE__ */ new Map();
35189
35205
  this.problems = /* @__PURE__ */ new Map();
35206
+ this.#reached.clear();
35190
35207
  const port = model.updates;
35191
35208
  if (!port) return [];
35192
35209
  let previous = snapshot(port.list());
@@ -35195,6 +35212,7 @@ var SliccUpdates = class extends ModelElement {
35195
35212
  const next = snapshot(items);
35196
35213
  this.failures = settled2(this.failures, previous, next);
35197
35214
  previous = next;
35215
+ this.#prune("item", items, itemBusy);
35198
35216
  this.requestUpdate();
35199
35217
  })
35200
35218
  ];
@@ -35206,6 +35224,7 @@ var SliccUpdates = class extends ModelElement {
35206
35224
  const next = snapshot(items);
35207
35225
  this.problems = settled2(this.problems, packages, next);
35208
35226
  packages = next;
35227
+ this.#prune("package", items, packageBusy);
35209
35228
  this.requestUpdate();
35210
35229
  })
35211
35230
  ];
@@ -35259,25 +35278,43 @@ var SliccUpdates = class extends ModelElement {
35259
35278
  }
35260
35279
  }
35261
35280
  }
35262
- #progress(item2) {
35263
- const progress = item2.progress;
35264
- if (progress) {
35265
- return b`<swc-progress-bar
35266
- size="s"
35267
- min-value="0"
35268
- max-value=${progress.total}
35269
- value=${progress.done}
35270
- value-label=${`${progress.done} of ${progress.total}`}
35271
- accessible-label=${`${item2.label}: ${progress.phase === "download" ? "downloading" : "linking"}`}
35272
- ></swc-progress-bar>`;
35273
- }
35274
- if (!running.has(item2.state) && item2.state !== "starting") return A;
35281
+ #prune(kind, items, busy) {
35282
+ const live = new Set(items.filter(busy).map((item2) => `${kind}:${item2.id}`));
35283
+ for (const key2 of this.#reached.keys()) {
35284
+ if (key2.startsWith(`${kind}:`) && !live.has(key2)) this.#reached.delete(key2);
35285
+ }
35286
+ }
35287
+ #bar(key2, busy, progress, count2, accessible) {
35288
+ if (!busy) {
35289
+ this.#reached.delete(key2);
35290
+ return A;
35291
+ }
35292
+ const before = this.#reached.get(key2);
35293
+ const shown4 = progress ? { value: Math.max(before?.value ?? 0, phased(progress)), label: count2 } : before;
35294
+ if (!shown4) {
35295
+ return b`<swc-progress-bar size="s" indeterminate accessible-label=${accessible}></swc-progress-bar>`;
35296
+ }
35297
+ this.#reached.set(key2, shown4);
35275
35298
  return b`<swc-progress-bar
35276
35299
  size="s"
35277
- indeterminate
35278
- accessible-label=${`${item2.label}: ${states[item2.state][1].toLowerCase()}`}
35300
+ min-value="0"
35301
+ max-value="100"
35302
+ value=${shown4.value}
35303
+ value-label=${shown4.label}
35304
+ accessible-label=${accessible}
35279
35305
  ></swc-progress-bar>`;
35280
35306
  }
35307
+ #progress(item2) {
35308
+ const progress = item2.progress;
35309
+ const phase = progress ? progress.phase === "download" ? "downloading" : "linking" : null;
35310
+ return this.#bar(
35311
+ `item:${item2.id}`,
35312
+ itemBusy(item2),
35313
+ progress,
35314
+ progress ? `${progress.done} of ${progress.total}` : "",
35315
+ `${item2.label}: ${phase ?? states[item2.state][1].toLowerCase()}`
35316
+ );
35317
+ }
35281
35318
  #actions(item2) {
35282
35319
  if (!item2.actions.length) return A;
35283
35320
  const busy = this.pending.has(item2.id);
@@ -35341,22 +35378,14 @@ var SliccUpdates = class extends ModelElement {
35341
35378
  }
35342
35379
  #packageProgress(item2) {
35343
35380
  const progress = item2.progress;
35344
- if (progress) {
35345
- return b`<swc-progress-bar
35346
- size="s"
35347
- min-value="0"
35348
- max-value=${progress.total}
35349
- value=${progress.done}
35350
- value-label=${`${progress.done} of ${progress.total} packages`}
35351
- accessible-label=${`${item2.label}: ${progress.phase === "download" ? "downloading" : "linking"}`}
35352
- ></swc-progress-bar>`;
35353
- }
35354
- if (!packageRunning.has(item2.state)) return A;
35355
- return b`<swc-progress-bar
35356
- size="s"
35357
- indeterminate
35358
- accessible-label=${`${item2.label}: ${packageLight(item2)?.[1].toLowerCase()}`}
35359
- ></swc-progress-bar>`;
35381
+ const phase = progress ? progress.phase === "download" ? "downloading" : "linking" : null;
35382
+ return this.#bar(
35383
+ `package:${item2.id}`,
35384
+ packageBusy(item2),
35385
+ progress,
35386
+ progress ? `${progress.done} of ${progress.total} packages` : "",
35387
+ `${item2.label}: ${phase ?? packageLight(item2)?.[1].toLowerCase()}`
35388
+ );
35360
35389
  }
35361
35390
  #package(item2, all2, act2) {
35362
35391
  const light = packageLight(item2);