@ai-ecoverse/slicc-spectrum 2.6.0 → 2.8.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.
@@ -794,6 +794,135 @@ var DummyBrowser = class extends Emitter {
794
794
  }
795
795
  };
796
796
 
797
+ // src/dummy/capture.ts
798
+ var PNG = Uint8Array.from(
799
+ atob(
800
+ "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="
801
+ ),
802
+ (char) => char.charCodeAt(0)
803
+ );
804
+ function denied(what) {
805
+ throw new DOMException(`${what} was denied`, "NotAllowedError");
806
+ }
807
+ function switchKey(kind) {
808
+ return kind === "audio" ? "microphone" : kind === "video" ? "camera" : "screen";
809
+ }
810
+ function allowed(switches, kind) {
811
+ const key = switchKey(kind);
812
+ const found = switches?.list().find((item) => item.key === key);
813
+ return !found || found.on;
814
+ }
815
+ var DummyCapture = class {
816
+ kinds;
817
+ still;
818
+ #live;
819
+ #switches;
820
+ #clock;
821
+ #deny;
822
+ #active = /* @__PURE__ */ new Map();
823
+ #prior = null;
824
+ constructor(scenario, clock2, live, switches) {
825
+ this.#clock = clock2;
826
+ this.#live = live;
827
+ this.#switches = switches;
828
+ this.#deny = scenario === "deny";
829
+ this.kinds = scenario === "audio" ? ["audio"] : ["audio", "video"];
830
+ this.still = () => this.#still();
831
+ if (live) {
832
+ this.#prior = live.act.bind(live);
833
+ live.act = (id) => {
834
+ const session2 = this.#active.get(id);
835
+ if (session2) session2.stop();
836
+ else this.#prior?.(id);
837
+ };
838
+ }
839
+ }
840
+ async record(kind) {
841
+ if (this.#deny || !allowed(this.#switches, kind))
842
+ denied(kind === "audio" ? "Microphone access" : "Camera access");
843
+ if (this.kinds && !this.kinds.includes(kind))
844
+ throw new DOMException(`Recording ${kind} isn\u2019t supported here`, "NotSupportedError");
845
+ const id = `capture-${kind}`;
846
+ if (this.#active.has(id)) throw new DOMException("Already recording", "InvalidStateError");
847
+ let settle;
848
+ let fail;
849
+ let done = false;
850
+ const finished = new Promise((resolve2, reject) => {
851
+ settle = resolve2;
852
+ fail = reject;
853
+ });
854
+ const mimeType = kind === "audio" ? "audio/webm" : "video/webm";
855
+ const name2 = "recording.webm";
856
+ const started = Date.now();
857
+ const item = {
858
+ id,
859
+ kind: kind === "audio" ? "microphone" : "camera",
860
+ label: kind === "audio" ? "Recording microphone" : "Recording camera",
861
+ what: kind === "audio" ? "Desk microphone" : "Face camera",
862
+ asker: "you",
863
+ since: started,
864
+ action: { label: "Stop" }
865
+ };
866
+ const end = (take, error) => {
867
+ if (done) return;
868
+ done = true;
869
+ this.#active.delete(id);
870
+ if (this.#live?.items().some((row) => row.id === id)) this.#prior?.(id);
871
+ if (error) fail(error);
872
+ else if (take) settle(take);
873
+ };
874
+ const session2 = {
875
+ stop: () => end({
876
+ blob: new Blob([PNG], { type: mimeType }),
877
+ mimeType,
878
+ name: name2,
879
+ durationMs: Math.max(0, Date.now() - started)
880
+ }),
881
+ cancel: () => end(null, new DOMException("Recording cancelled", "AbortError"))
882
+ };
883
+ this.#active.set(id, session2);
884
+ this.#live?.add(item);
885
+ return { ...session2, finished };
886
+ }
887
+ async #still() {
888
+ if (this.#deny || !allowed(this.#switches, "screen")) denied("Screen capture");
889
+ await this.#clock.sleep();
890
+ const id = "capture-still";
891
+ if (this.#active.has(id)) throw new DOMException("Already capturing", "InvalidStateError");
892
+ const item = {
893
+ id,
894
+ kind: "screen",
895
+ label: "Taking a photo",
896
+ what: "This screen",
897
+ asker: "you",
898
+ since: Date.now(),
899
+ action: { label: "Cancel" }
900
+ };
901
+ return await new Promise((resolve2, reject) => {
902
+ let done = false;
903
+ const finish = (still, error) => {
904
+ if (done) return;
905
+ done = true;
906
+ this.#active.delete(id);
907
+ if (this.#live?.items().some((row) => row.id === id)) this.#prior?.(id);
908
+ if (error) reject(error);
909
+ else if (still) resolve2(still);
910
+ };
911
+ const abort = () => finish(null, new DOMException("Screenshot cancelled", "AbortError"));
912
+ this.#active.set(id, { stop: abort, cancel: abort });
913
+ this.#live?.add(item);
914
+ void this.#clock.sleep().then(() => {
915
+ if (done) return;
916
+ finish({
917
+ blob: new Blob([PNG], { type: "image/png" }),
918
+ mimeType: "image/png",
919
+ name: "screenshot.png"
920
+ });
921
+ });
922
+ });
923
+ }
924
+ };
925
+
797
926
  // src/dummy/changes.ts
798
927
  var repos = ["/workspace/harbor", "/workspace/skills"];
799
928
  var linkCommand = "curl -fsSL https://get.sliccy.ai/slicc | sh";
@@ -1944,6 +2073,7 @@ var labels = {
1944
2073
  "Count the routes": "Walk through every kind of tool",
1945
2074
  "Ask the API for Lisbon": "Compare the docs with the live API",
1946
2075
  "Switch the page to Celsius": "Move the forecast docs to Celsius, then build and test the site",
2076
+ "git status --short": "Summarise the working tree",
1947
2077
  [fixtures(`${repro}/round2/fixtures`)]: replayLabel
1948
2078
  };
1949
2079
  function label(title) {
@@ -2596,6 +2726,13 @@ var DummyAgent = class extends Emitter {
2596
2726
  starting() {
2597
2727
  return this.#starting;
2598
2728
  }
2729
+ setTitle(agentId, title) {
2730
+ const agent = this.#agent(agentId);
2731
+ if (!agent) return;
2732
+ if (title === void 0) delete agent.title;
2733
+ else agent.title = title;
2734
+ this.#changed();
2735
+ }
2599
2736
  setStarting(line) {
2600
2737
  this.#arrival++;
2601
2738
  this.#starting = line || null;
@@ -4175,6 +4312,7 @@ var DummyFiles = class extends Emitter {
4175
4312
 
4176
4313
  // src/dummy/live.ts
4177
4314
  function liveFixtures(scenario, now2 = Date.now()) {
4315
+ if (scenario === "empty") return [];
4178
4316
  const screen = {
4179
4317
  id: "live-screen",
4180
4318
  kind: "screen",
@@ -4801,9 +4939,9 @@ var outdatedDevice = {
4801
4939
  note: "Update slicc to 1.47.0 or later to share this computer\u2019s browsers."
4802
4940
  };
4803
4941
  var others = linkedDevices.filter((device) => device.id !== pairedDevice.id);
4804
- function grant(device, key, allowed) {
4805
- const access = { ...device.access, [key]: allowed };
4806
- if (key === "view" && !allowed && "control" in access) access.control = false;
4942
+ function grant(device, key, allowed2) {
4943
+ const access = { ...device.access, [key]: allowed2 };
4944
+ if (key === "view" && !allowed2 && "control" in access) access.control = false;
4807
4945
  const next = { ...device, access, asking: device.asking && !access.view };
4808
4946
  if (!access.view && !access.control) next.controlling = void 0;
4809
4947
  else if (!access.control && next.controlling === "prompt") next.controlling = "watch";
@@ -4910,8 +5048,8 @@ var DummyNetwork = class extends Emitter {
4910
5048
  ({ links: this.#links, exit: this.#exit } = linksFixtures(links));
4911
5049
  this.setExit = (exit) => this.#setExit(exit);
4912
5050
  this.unlink = (id) => this.#unlink(id);
4913
- this.setRemoteControl = (id, allowed) => this.#control(id, allowed);
4914
- this.setAccess = (id, key, allowed) => this.#access(id, key, allowed);
5051
+ this.setRemoteControl = (id, allowed2) => this.#control(id, allowed2);
5052
+ this.setAccess = (id, key, allowed2) => this.#access(id, key, allowed2);
4915
5053
  this.rotateJoinUrl = () => this.#rotate();
4916
5054
  this.retryLinks = () => this.#retry();
4917
5055
  this.mountFolder = (source) => this.#mountFolder(source);
@@ -5022,22 +5160,22 @@ var DummyNetwork = class extends Emitter {
5022
5160
  this.#exit = exit;
5023
5161
  this.#emit();
5024
5162
  }
5025
- async #control(id, allowed) {
5163
+ async #control(id, allowed2) {
5026
5164
  await this.#clock.sleep(4);
5027
5165
  const links = this.#links;
5028
5166
  const devices = links.devices.map((device) => {
5029
5167
  if (device.id !== id) return device;
5030
- const next = { ...device, control: { ...device.control, allowed } };
5031
- return allowed ? next : { ...next, controlling: void 0 };
5168
+ const next = { ...device, control: { ...device.control, allowed: allowed2 } };
5169
+ return allowed2 ? next : { ...next, controlling: void 0 };
5032
5170
  });
5033
5171
  this.#links = { ...links, devices };
5034
5172
  this.#emit();
5035
5173
  }
5036
- async #access(id, key, allowed) {
5174
+ async #access(id, key, allowed2) {
5037
5175
  await this.#clock.sleep(4);
5038
5176
  const links = this.#links;
5039
5177
  const devices = links.devices.map(
5040
- (device) => device.id === id ? grant(device, key, allowed) : device
5178
+ (device) => device.id === id ? grant(device, key, allowed2) : device
5041
5179
  );
5042
5180
  this.#links = { ...links, devices };
5043
5181
  this.#emit();
@@ -7549,6 +7687,16 @@ var movedDocs = "https://docs.eu.example/mcp";
7549
7687
  function hinted(login) {
7550
7688
  return login === "code" || login === "url" || login === "lookalike";
7551
7689
  }
7690
+ function capturePorts(capture, live, switches, time) {
7691
+ const livePort = live !== "off" ? new DummyLive(live) : capture === "off" ? void 0 : new DummyLive("empty");
7692
+ const switchPort = switches === "off" ? void 0 : new DummySwitches();
7693
+ const capturePort = capture === "off" ? void 0 : new DummyCapture(capture, time, livePort, switchPort);
7694
+ return {
7695
+ ...livePort ? { live: livePort } : {},
7696
+ ...capturePort ? { capture: capturePort } : {},
7697
+ ...switchPort ? { switches: switchPort } : {}
7698
+ };
7699
+ }
7552
7700
  function signInChat(conversations2, login) {
7553
7701
  if (!hinted(login)) return conversations2;
7554
7702
  return {
@@ -7625,6 +7773,7 @@ function createDummyModel({
7625
7773
  approvals = "off",
7626
7774
  asks = "off",
7627
7775
  live = "off",
7776
+ capture = "off",
7628
7777
  switches = "off",
7629
7778
  follow = "off",
7630
7779
  vault = "off",
@@ -7647,6 +7796,7 @@ function createDummyModel({
7647
7796
  older = "off"
7648
7797
  } = {}) {
7649
7798
  const time = clock(delay);
7799
+ const capturePortsOn = capturePorts(capture, live, switches, time);
7650
7800
  const mount = mounts === "off" ? null : { scenario: mounts, point: mountPoint, files: mounted };
7651
7801
  const pending2 = changes === "git" ? [...pending, skillEdit] : pending;
7652
7802
  const files3 = new DummyFiles(files, directories, pending2, time, mount);
@@ -7716,8 +7866,7 @@ function createDummyModel({
7716
7866
  ...noticePort ? { notices: noticePort } : {},
7717
7867
  ...tabs2 === "off" ? {} : { tabs: new DummyTabs(tabs2, time) },
7718
7868
  ...approvals === "off" ? {} : { approvals: new DummyApprovals(approvals, time, vaultPort) },
7719
- ...live === "off" ? {} : { live: new DummyLive(live) },
7720
- ...switches === "off" ? {} : { switches: new DummySwitches() },
7869
+ ...capturePortsOn,
7721
7870
  ...follow === "off" ? {} : { follow: new DummyFollow(follow, time) },
7722
7871
  ...vaultPort ? { vault: vaultPort } : {},
7723
7872
  ...guestsPort(guests, time)
@@ -7733,6 +7882,7 @@ function createDummyModel({
7733
7882
  export {
7734
7883
  DummyApprovals,
7735
7884
  DummyBrowser,
7885
+ DummyCapture,
7736
7886
  DummyChanges,
7737
7887
  DummyFollow,
7738
7888
  DummyGuestAgent,