tesseract-agent 0.4.13 → 0.4.14

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.
Files changed (2) hide show
  1. package/dist-bundle/cli.js +353 -75
  2. package/package.json +1 -1
@@ -20274,9 +20274,9 @@ function parseColorToRgb(v) {
20274
20274
  const hex3 = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(s);
20275
20275
  if (hex3)
20276
20276
  return [parseInt(hex3[1] + hex3[1], 16), parseInt(hex3[2] + hex3[2], 16), parseInt(hex3[3] + hex3[3], 16)];
20277
- const hex6 = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(s);
20278
- if (hex6)
20279
- return [parseInt(hex6[1], 16), parseInt(hex6[2], 16), parseInt(hex6[3], 16)];
20277
+ const hex68 = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})(?:[0-9a-f]{2})?$/i.exec(s);
20278
+ if (hex68)
20279
+ return [parseInt(hex68[1], 16), parseInt(hex68[2], 16), parseInt(hex68[3], 16)];
20280
20280
  const hsl = /^(-?\d+(?:\.\d+)?)\s*[, ]\s*(-?\d+(?:\.\d+)?)%\s*[, ]\s*(-?\d+(?:\.\d+)?)%$/.exec(s);
20281
20281
  if (hsl)
20282
20282
  return hslToRgb(parseFloat(hsl[1]), parseFloat(hsl[2]), parseFloat(hsl[3]));
@@ -20360,8 +20360,13 @@ function tokensToTailwindConfig(input) {
20360
20360
  ].join("\n");
20361
20361
  }
20362
20362
  function leafSignature(token) {
20363
- const dark = tessExt(token)?.modes?.dark;
20364
- return JSON.stringify(dark === void 0 ? [token.$value] : [token.$value, dark]);
20363
+ const modes = tessExt(token)?.modes;
20364
+ if (!modes || typeof modes !== "object")
20365
+ return JSON.stringify([token.$value]);
20366
+ const sorted = {};
20367
+ for (const k of Object.keys(modes).sort())
20368
+ sorted[k] = modes[k];
20369
+ return JSON.stringify([token.$value, sorted]);
20365
20370
  }
20366
20371
  function indexLeaves(t) {
20367
20372
  const m = /* @__PURE__ */ new Map();
@@ -20541,6 +20546,7 @@ var init_types = __esm({
20541
20546
  // ../../packages/design-packs/dist/packs/_build.js
20542
20547
  function buildPack(s) {
20543
20548
  const dual = (lv) => ({ $value: lv[0], $extensions: { "com.tesseract": { modes: { dark: lv[1] } } } });
20549
+ const val = (v) => Array.isArray(v) ? dual(v) : { $value: v };
20544
20550
  const r = s.radius ?? { sm: "6px", md: "10px", lg: "16px" };
20545
20551
  const sh = s.shadow ?? {
20546
20552
  sm: "0 1px 2px rgb(0 0 0 / 0.06)",
@@ -20553,9 +20559,9 @@ function buildPack(s) {
20553
20559
  color: {
20554
20560
  $type: "color",
20555
20561
  brand: {
20556
- primary: { $value: s.brandPrimary },
20557
- onPrimary: { $value: s.onPrimary },
20558
- ...s.brandAccent ? { accent: { $value: s.brandAccent } } : {}
20562
+ primary: val(s.brandPrimary),
20563
+ onPrimary: val(s.onPrimary),
20564
+ ...s.brandAccent ? { accent: val(s.brandAccent) } : {}
20559
20565
  },
20560
20566
  surface: { page: dual(s.page), card: dual(s.card) },
20561
20567
  text: { primary: dual(s.textPrimary), secondary: dual(s.textSecondary), muted: dual(s.textMuted) },
@@ -20607,16 +20613,18 @@ var init_clean_minimal = __esm({
20607
20613
  clean_minimal_default = buildPack({
20608
20614
  id: "clean-minimal",
20609
20615
  name: "Clean Minimal",
20610
- description: "Whitespace, neutral grays, restrained. The safe default.",
20616
+ description: "Warm off-white, soft stone neutrals, restrained. The safe default.",
20611
20617
  style: "minimal",
20612
- brandPrimary: "#111827",
20613
- onPrimary: "#ffffff",
20614
- page: ["#ffffff", "#0b0b0c"],
20615
- card: ["#fafafa", "#151517"],
20616
- textPrimary: ["#111827", "#f4f4f5"],
20617
- textSecondary: ["#4b5563", "#a1a1aa"],
20618
- textMuted: ["#888d99", "#71717a"],
20619
- border: ["#e5e7eb", "#27272a"],
20618
+ // Warm neutral (2026 "Cloud Dancer" direction) + a brand that flips light↔dark so the CTA
20619
+ // stays visible: near-black button in light, near-white button in dark.
20620
+ brandPrimary: ["#1c1917", "#f5f5f4"],
20621
+ onPrimary: ["#ffffff", "#1c1917"],
20622
+ page: ["#faf9f7", "#0b0b0a"],
20623
+ card: ["#ffffff", "#161513"],
20624
+ textPrimary: ["#1c1917", "#fafaf9"],
20625
+ textSecondary: ["#57534e", "#a8a29e"],
20626
+ textMuted: ["#79716b", "#8a847c"],
20627
+ border: ["#e7e5e4", "#292524"],
20620
20628
  sans: ["Inter", "-apple-system", "BlinkMacSystemFont", "Segoe UI", "sans-serif"],
20621
20629
  radius: { sm: "6px", md: "8px", lg: "12px" }
20622
20630
  });
@@ -20660,8 +20668,8 @@ var init_refined_brutalist = __esm({
20660
20668
  name: "Refined Brutalist",
20661
20669
  description: "Raw grotesk type, visible grid, hard edges, high accessible contrast.",
20662
20670
  style: "brutalist",
20663
- brandPrimary: "#000000",
20664
- onPrimary: "#ffffff",
20671
+ brandPrimary: ["#000000", "#ffffff"],
20672
+ onPrimary: ["#ffffff", "#000000"],
20665
20673
  brandAccent: "#ff3b00",
20666
20674
  page: ["#ffffff", "#000000"],
20667
20675
  card: ["#f4f4f4", "#0c0c0c"],
@@ -20688,9 +20696,9 @@ var init_editorial = __esm({
20688
20696
  name: "Editorial",
20689
20697
  description: "Serif display, classical art-converging, magazine layout.",
20690
20698
  style: "editorial",
20691
- brandPrimary: "#1a1a1a",
20692
- onPrimary: "#ffffff",
20693
- brandAccent: "#9a3412",
20699
+ brandPrimary: ["#1a1a1a", "#f0ece4"],
20700
+ onPrimary: ["#ffffff", "#1a1a1a"],
20701
+ brandAccent: ["#9a3412", "#e0794a"],
20694
20702
  page: ["#fbfaf7", "#1a1714"],
20695
20703
  card: ["#ffffff", "#221d19"],
20696
20704
  textPrimary: ["#1a1a1a", "#f0ece4"],
@@ -20857,7 +20865,7 @@ var init_warm_organic = __esm({
20857
20865
  card: ["#fffdf9", "#221b16"],
20858
20866
  textPrimary: ["#2b211a", "#efe7dd"],
20859
20867
  textSecondary: ["#6b5b4d", "#c4b3a3"],
20860
- textMuted: ["#998a7a", "#8a7868"],
20868
+ textMuted: ["#877564", "#8a7868"],
20861
20869
  border: ["#e8ddcf", "#33291f"],
20862
20870
  sans: ["Source Sans 3", "Source Sans Pro", "-apple-system", "sans-serif"],
20863
20871
  radius: { sm: "8px", md: "14px", lg: "20px" }
@@ -20876,8 +20884,8 @@ var init_luxury_elegant = __esm({
20876
20884
  name: "Luxury Elegant",
20877
20885
  description: "Muted, fine serif, gold-on-black, refined restraint.",
20878
20886
  style: "luxury",
20879
- brandPrimary: "#11100f",
20880
- onPrimary: "#d4af37",
20887
+ brandPrimary: ["#11100f", "#d4af37"],
20888
+ onPrimary: ["#d4af37", "#11100f"],
20881
20889
  brandAccent: "#b08d57",
20882
20890
  page: ["#faf9f7", "#0e0d0c"],
20883
20891
  card: ["#ffffff", "#171513"],
@@ -20911,7 +20919,7 @@ var init_bento_tech = __esm({
20911
20919
  card: ["#ffffff", "#13161c"],
20912
20920
  textPrimary: ["#0b0e14", "#e9edf5"],
20913
20921
  textSecondary: ["#3f4756", "#9aa4b8"],
20914
- textMuted: ["#7a8499", "#6b7488"],
20922
+ textMuted: ["#6f7892", "#6b7488"],
20915
20923
  border: ["#e6e8ee", "#1d212b"],
20916
20924
  sans: ["Geist", "Inter", "-apple-system", "sans-serif"],
20917
20925
  mono: ["Geist Mono", "ui-monospace", "monospace"],
@@ -20920,6 +20928,61 @@ var init_bento_tech = __esm({
20920
20928
  }
20921
20929
  });
20922
20930
 
20931
+ // ../../packages/design-packs/dist/packs/fintech-emerald.js
20932
+ var fintech_emerald_default;
20933
+ var init_fintech_emerald = __esm({
20934
+ "../../packages/design-packs/dist/packs/fintech-emerald.js"() {
20935
+ "use strict";
20936
+ init_build();
20937
+ fintech_emerald_default = buildPack({
20938
+ id: "fintech-emerald",
20939
+ name: "Fintech Emerald",
20940
+ description: "Fresh emerald, growth-and-trust. Fintech, health, sustainability.",
20941
+ style: "fresh",
20942
+ // Emerald shifts lighter in dark (emerald-700 → emerald-400) so the CTA pops on a deep
20943
+ // green-black, per modern light/dark accent practice.
20944
+ brandPrimary: ["#047857", "#34d399"],
20945
+ onPrimary: ["#ffffff", "#022c22"],
20946
+ brandAccent: ["#0d9488", "#5eead4"],
20947
+ page: ["#f7faf8", "#07120d"],
20948
+ card: ["#ffffff", "#0e1a14"],
20949
+ textPrimary: ["#0a1f17", "#e6f5ee"],
20950
+ textSecondary: ["#3f5a4f", "#9cc3b3"],
20951
+ textMuted: ["#6a8579", "#728d80"],
20952
+ border: ["#dcebe3", "#1a2a22"],
20953
+ sans: ["Inter", "-apple-system", "Segoe UI", "sans-serif"],
20954
+ radius: { sm: "8px", md: "12px", lg: "18px" }
20955
+ });
20956
+ }
20957
+ });
20958
+
20959
+ // ../../packages/design-packs/dist/packs/sunset-coral.js
20960
+ var sunset_coral_default;
20961
+ var init_sunset_coral = __esm({
20962
+ "../../packages/design-packs/dist/packs/sunset-coral.js"() {
20963
+ "use strict";
20964
+ init_build();
20965
+ sunset_coral_default = buildPack({
20966
+ id: "sunset-coral",
20967
+ name: "Sunset Coral",
20968
+ description: "Warm coral + amber, energetic but friendly. Lifestyle, creative, DTC.",
20969
+ style: "sunset",
20970
+ // Coral deepens for white legibility in light, brightens in dark; amber as the warm accent.
20971
+ brandPrimary: ["#d23b1e", "#ff8a6b"],
20972
+ onPrimary: ["#ffffff", "#3d0f06"],
20973
+ brandAccent: ["#f59e0b", "#fcd34d"],
20974
+ page: ["#fff8f4", "#1a0f0a"],
20975
+ card: ["#ffffff", "#251510"],
20976
+ textPrimary: ["#2b1610", "#fdeee6"],
20977
+ textSecondary: ["#6b4133", "#d6a795"],
20978
+ textMuted: ["#9a6f5e", "#9a786a"],
20979
+ border: ["#f4ddd0", "#3a221a"],
20980
+ sans: ["Plus Jakarta Sans", "Inter", "-apple-system", "sans-serif"],
20981
+ radius: { sm: "10px", md: "16px", lg: "22px" }
20982
+ });
20983
+ }
20984
+ });
20985
+
20923
20986
  // ../../packages/design-packs/dist/index.js
20924
20987
  function getPack(id) {
20925
20988
  return PACKS_BY_ID[id];
@@ -20941,15 +21004,19 @@ var init_dist3 = __esm({
20941
21004
  init_warm_organic();
20942
21005
  init_luxury_elegant();
20943
21006
  init_bento_tech();
21007
+ init_fintech_emerald();
21008
+ init_sunset_coral();
20944
21009
  PACKS = [
20945
21010
  clean_minimal_default,
20946
21011
  corporate_trust_default,
21012
+ fintech_emerald_default,
20947
21013
  refined_brutalist_default,
20948
21014
  editorial_default,
20949
21015
  soft_clay_playful_default,
20950
21016
  premium_dark_default,
20951
21017
  glass_aurora_default,
20952
21018
  dopamine_pop_default,
21019
+ sunset_coral_default,
20953
21020
  retro_y2k_default,
20954
21021
  warm_organic_default,
20955
21022
  luxury_elegant_default,
@@ -21355,6 +21422,23 @@ function sessionDir(cwd) {
21355
21422
  function sessionFile(cwd, sessionId) {
21356
21423
  return join5(sessionDir(cwd), `${sessionId}.jsonl`);
21357
21424
  }
21425
+ async function resolveSessionFile(sessionId, projectDir) {
21426
+ if (projectDir) {
21427
+ const direct = sessionFile(projectDir, sessionId);
21428
+ if (existsSync(direct))
21429
+ return direct;
21430
+ }
21431
+ const target = `${sessionId}.jsonl`;
21432
+ const projects = await readdir(projectsRoot(), { withFileTypes: true }).catch(() => []);
21433
+ for (const dir of projects) {
21434
+ if (!dir.isDirectory())
21435
+ continue;
21436
+ const candidate = join5(projectsRoot(), dir.name, target);
21437
+ if (existsSync(candidate))
21438
+ return candidate;
21439
+ }
21440
+ return null;
21441
+ }
21358
21442
  async function walkFiles(root) {
21359
21443
  const out = [];
21360
21444
  async function rec(dir, prefix) {
@@ -21632,9 +21716,10 @@ var init_session_store = __esm({
21632
21716
  * WITHOUT file-history/undo snapshots (SDK behavior). */
21633
21717
  async forkSession(sessionId, opts) {
21634
21718
  try {
21719
+ const upToMessageId = opts?.upToMessageId ?? await this.lastResumableMessageId(sessionId, opts?.projectDir);
21635
21720
  const result = await forkSession(sessionId, {
21636
21721
  ...opts?.projectDir ? { dir: opts.projectDir } : {},
21637
- ...opts?.upToMessageId ? { upToMessageId: opts.upToMessageId } : {},
21722
+ ...upToMessageId ? { upToMessageId } : {},
21638
21723
  ...opts?.title ? { title: opts.title } : {}
21639
21724
  });
21640
21725
  return result.sessionId;
@@ -21642,6 +21727,51 @@ var init_session_store = __esm({
21642
21727
  return null;
21643
21728
  }
21644
21729
  }
21730
+ /** The uuid of the last transcript message after which NO tool_use is left without
21731
+ * its tool_result — the safe point to fork at. Reads the same on-disk `.jsonl` the
21732
+ * SDK fork copies (filtering sidechains identically) and pairs tool_use ids against
21733
+ * tool_result ids. Returns undefined when the transcript already ends balanced
21734
+ * (fork everything) or it can't be read (best-effort: fall back to a full fork). */
21735
+ async lastResumableMessageId(sessionId, projectDir) {
21736
+ try {
21737
+ const file2 = await resolveSessionFile(sessionId, projectDir);
21738
+ if (!file2)
21739
+ return void 0;
21740
+ const raw = await readFile3(file2, "utf-8");
21741
+ const outstanding = /* @__PURE__ */ new Set();
21742
+ let lastBalancedUuid;
21743
+ for (const line of raw.split("\n")) {
21744
+ const t = line.trim();
21745
+ if (!t)
21746
+ continue;
21747
+ let e;
21748
+ try {
21749
+ e = JSON.parse(t);
21750
+ } catch {
21751
+ continue;
21752
+ }
21753
+ if (e.isSidechain === true)
21754
+ continue;
21755
+ const content = e.message?.content;
21756
+ if (Array.isArray(content)) {
21757
+ for (const b of content) {
21758
+ if (!b || typeof b !== "object")
21759
+ continue;
21760
+ const blk = b;
21761
+ if (blk.type === "tool_use" && typeof blk.id === "string")
21762
+ outstanding.add(blk.id);
21763
+ else if (blk.type === "tool_result" && typeof blk.tool_use_id === "string")
21764
+ outstanding.delete(blk.tool_use_id);
21765
+ }
21766
+ }
21767
+ if (typeof e.uuid === "string" && outstanding.size === 0)
21768
+ lastBalancedUuid = e.uuid;
21769
+ }
21770
+ return outstanding.size === 0 ? void 0 : lastBalancedUuid;
21771
+ } catch {
21772
+ return void 0;
21773
+ }
21774
+ }
21645
21775
  };
21646
21776
  }
21647
21777
  });
@@ -23709,6 +23839,7 @@ __export(dist_exports, {
23709
23839
  normalizeTokens: () => normalizeTokens,
23710
23840
  parseColorToRgb: () => parseColorToRgb,
23711
23841
  resolveOauthToken: () => resolveOauthToken,
23842
+ resolveSessionFile: () => resolveSessionFile,
23712
23843
  sanitizeProjectDir: () => sanitizeProjectDir,
23713
23844
  sessionDir: () => sessionDir,
23714
23845
  sessionFile: () => sessionFile,
@@ -43530,12 +43661,12 @@ import { createHash as createHash5 } from "node:crypto";
43530
43661
  import { spawn as spawn7 } from "node:child_process";
43531
43662
  import { fileURLToPath as fileURLToPath2 } from "node:url";
43532
43663
  import { homedir as homedir14 } from "node:os";
43533
- import { dirname as dirname16, join as join33, resolve as resolve8 } from "node:path";
43664
+ import { dirname as dirname17, join as join33, resolve as resolve8 } from "node:path";
43534
43665
  import { createInterface } from "node:readline/promises";
43535
43666
 
43536
43667
  // ../../packages/host-core/dist/control-link.js
43537
43668
  import { hostname as hostname3, homedir as homedir10 } from "node:os";
43538
- import { join as join26, basename as basename5 } from "node:path";
43669
+ import { join as join26, basename as basename6 } from "node:path";
43539
43670
  import { mkdirSync as mkdirSync9 } from "node:fs";
43540
43671
 
43541
43672
  // ../../node_modules/ws/wrapper.mjs
@@ -43587,7 +43718,7 @@ import { join as join15 } from "node:path";
43587
43718
 
43588
43719
  // ../../packages/host-core/dist/agent-backend.js
43589
43720
  async function createClaudeCodeBackend(send2, onBrowserRequest, loadPluginRuntime2) {
43590
- const { AgentManager: AgentManager2, SessionStore: SessionStore2 } = await Promise.resolve().then(() => (init_dist4(), dist_exports));
43721
+ const { AgentManager: AgentManager2, SessionStore: SessionStore2, resolveSessionFile: resolveSessionFile2 } = await Promise.resolve().then(() => (init_dist4(), dist_exports));
43591
43722
  const manager2 = new AgentManager2(send2, onBrowserRequest);
43592
43723
  const store = new SessionStore2();
43593
43724
  const refreshPlugins = async (projectDir) => {
@@ -43613,6 +43744,8 @@ async function createClaudeCodeBackend(send2, onBrowserRequest, loadPluginRuntim
43613
43744
  listSessions: (projectDir) => store.getSessions(projectDir),
43614
43745
  searchSessions: (query2, projectDir) => store.searchSessions(query2, projectDir),
43615
43746
  getMessages: (sessionId) => store.getSessionMessages(sessionId),
43747
+ isSessionBusy: (sessionId) => manager2.isSessionBusy(sessionId),
43748
+ resolveSessionFile: (sessionId, projectDir) => resolveSessionFile2(sessionId, projectDir),
43616
43749
  setConfig: (projectDir) => {
43617
43750
  manager2.setConfig(projectDir);
43618
43751
  void refreshPlugins(projectDir);
@@ -44365,12 +44498,12 @@ async function loadPluginRuntime(opts) {
44365
44498
  }
44366
44499
  function buildDaemonPluginLoader(pluginsDir) {
44367
44500
  return async () => {
44368
- const scan = join8(pluginsDir, "node_modules");
44369
- if (!existsSync3(scan))
44501
+ const scan2 = join8(pluginsDir, "node_modules");
44502
+ if (!existsSync3(scan2))
44370
44503
  return { tools: [], hooks: [], engines: [] };
44371
44504
  writeOpenClawShim(pluginsDir);
44372
44505
  return loadPluginRuntime({
44373
- roots: [{ dir: scan, trusted: true, relaxHardlink: true }],
44506
+ roots: [{ dir: scan2, trusted: true, relaxHardlink: true }],
44374
44507
  secretResolver: (_pluginId, envKey2) => process.env[envKey2]
44375
44508
  });
44376
44509
  };
@@ -45903,6 +46036,123 @@ function unwatchAllRemote() {
45903
46036
  remoteWatches.clear();
45904
46037
  }
45905
46038
 
46039
+ // ../../packages/host-core/dist/session-watch.js
46040
+ import { watch as watch2 } from "node:fs";
46041
+ import { dirname as dirname7, basename as basename3 } from "node:path";
46042
+ var DEBOUNCE_MS = 120;
46043
+ var BUSY_GRACE_MS = 2e3;
46044
+ var watches = /* @__PURE__ */ new Map();
46045
+ var sessionToFile = /* @__PURE__ */ new Map();
46046
+ async function watchSession(sessionId, key2, projectDir, deps) {
46047
+ let filePath = sessionToFile.get(sessionId);
46048
+ if (!filePath) {
46049
+ const resolved = await deps.resolveFile?.(sessionId, projectDir);
46050
+ if (!resolved)
46051
+ return;
46052
+ filePath = resolved;
46053
+ sessionToFile.set(sessionId, filePath);
46054
+ }
46055
+ const baseline = await deps.getMessages(sessionId).then((m) => m.length).catch(() => 0);
46056
+ const existing = watches.get(filePath);
46057
+ if (existing) {
46058
+ existing.listeners.set(key2, { emittedCount: baseline, deps });
46059
+ return;
46060
+ }
46061
+ const fileName = basename3(filePath);
46062
+ const fw = {
46063
+ watcher: void 0,
46064
+ sessionId,
46065
+ listeners: /* @__PURE__ */ new Map([[key2, { emittedCount: baseline, deps }]]),
46066
+ timer: null,
46067
+ lastBusyAt: 0
46068
+ };
46069
+ try {
46070
+ fw.watcher = watch2(dirname7(filePath), (_event, changed) => {
46071
+ if (changed && basename3(String(changed)) !== fileName)
46072
+ return;
46073
+ scheduleScan(filePath);
46074
+ });
46075
+ } catch {
46076
+ return;
46077
+ }
46078
+ watches.set(filePath, fw);
46079
+ }
46080
+ function unwatchSession(sessionId, key2) {
46081
+ const filePath = sessionToFile.get(sessionId);
46082
+ if (!filePath)
46083
+ return;
46084
+ const fw = watches.get(filePath);
46085
+ if (!fw)
46086
+ return;
46087
+ fw.listeners.delete(key2);
46088
+ if (fw.listeners.size === 0)
46089
+ closeWatch(filePath);
46090
+ }
46091
+ function unwatchSessionClient(key2) {
46092
+ for (const [filePath, fw] of [...watches]) {
46093
+ if (fw.listeners.delete(key2) && fw.listeners.size === 0)
46094
+ closeWatch(filePath);
46095
+ }
46096
+ }
46097
+ function unwatchAllSessions() {
46098
+ for (const [filePath] of [...watches])
46099
+ closeWatch(filePath);
46100
+ }
46101
+ function closeWatch(filePath) {
46102
+ const fw = watches.get(filePath);
46103
+ if (!fw)
46104
+ return;
46105
+ if (fw.timer)
46106
+ clearTimeout(fw.timer);
46107
+ try {
46108
+ fw.watcher.close();
46109
+ } catch {
46110
+ }
46111
+ watches.delete(filePath);
46112
+ sessionToFile.delete(fw.sessionId);
46113
+ }
46114
+ function scheduleScan(filePath) {
46115
+ const fw = watches.get(filePath);
46116
+ if (!fw)
46117
+ return;
46118
+ if (fw.timer)
46119
+ clearTimeout(fw.timer);
46120
+ fw.timer = setTimeout(() => {
46121
+ fw.timer = null;
46122
+ void scan(filePath);
46123
+ }, DEBOUNCE_MS);
46124
+ }
46125
+ async function scan(filePath) {
46126
+ const fw = watches.get(filePath);
46127
+ if (!fw)
46128
+ return;
46129
+ const { sessionId } = fw;
46130
+ const any2 = fw.listeners.values().next().value;
46131
+ if (!any2)
46132
+ return;
46133
+ const busy = any2.deps.isSessionBusy?.(sessionId) === true;
46134
+ const now = Date.now();
46135
+ if (busy)
46136
+ fw.lastBusyAt = now;
46137
+ const inGrace = busy || now - fw.lastBusyAt < BUSY_GRACE_MS;
46138
+ const messages = await any2.deps.getMessages(sessionId).catch(() => null);
46139
+ if (!messages)
46140
+ return;
46141
+ const len = messages.length;
46142
+ for (const [key2, listener] of fw.listeners) {
46143
+ if (inGrace) {
46144
+ listener.emittedCount = len;
46145
+ continue;
46146
+ }
46147
+ if (len < listener.emittedCount) {
46148
+ listener.deps.emit(key2, { type: "session:messages", sessionId, messages });
46149
+ } else if (len > listener.emittedCount) {
46150
+ listener.deps.emit(key2, { type: "session:appended", sessionId, messages: messages.slice(listener.emittedCount) });
46151
+ }
46152
+ listener.emittedCount = len;
46153
+ }
46154
+ }
46155
+
45906
46156
  // ../../packages/host-core/dist/fs-datachannel-host.js
45907
46157
  var SCTP_BUF = 16 * 1024 * 1024;
45908
46158
  var ndcPromise = null;
@@ -46115,7 +46365,7 @@ function dynamicMetrics() {
46115
46365
  // ../../packages/host-core/dist/fs-transfer.js
46116
46366
  import { readdir as readdir3, lstat, mkdir as mkdir5, chmod, rm as rm2, readlink, symlink, stat as stat3 } from "node:fs/promises";
46117
46367
  import { openSync as openSync3, readSync as readSync2, closeSync as closeSync3, existsSync as existsSync9, createWriteStream } from "node:fs";
46118
- import { dirname as dirname7, join as join18, relative as relative5, sep as sep5 } from "node:path";
46368
+ import { dirname as dirname8, join as join18, relative as relative5, sep as sep5 } from "node:path";
46119
46369
 
46120
46370
  // ../../packages/host-core/dist/active-link/paths.js
46121
46371
  import { homedir as homedir7 } from "node:os";
@@ -46462,9 +46712,9 @@ async function writeInboundChunk(msg, send2) {
46462
46712
  try {
46463
46713
  if (msg.kind === "symlink") {
46464
46714
  const target = Buffer.from(msg.base64, "base64").toString("utf-8");
46465
- const resolved = join18(dirname7(abs), target);
46715
+ const resolved = join18(dirname8(abs), target);
46466
46716
  if (isInsideRoot(resolved, s.destRoot)) {
46467
- await mkdir5(dirname7(abs), { recursive: true }).catch(() => {
46717
+ await mkdir5(dirname8(abs), { recursive: true }).catch(() => {
46468
46718
  });
46469
46719
  await symlink(target, abs).catch(() => {
46470
46720
  });
@@ -46477,7 +46727,7 @@ async function writeInboundChunk(msg, send2) {
46477
46727
  if (s.curIx !== msg.fileIx || !s.curStream) {
46478
46728
  if (s.curStream)
46479
46729
  await new Promise((r) => s.curStream.end(r));
46480
- await mkdir5(dirname7(abs), { recursive: true }).catch(() => {
46730
+ await mkdir5(dirname8(abs), { recursive: true }).catch(() => {
46481
46731
  });
46482
46732
  s.curStream = createWriteStream(abs);
46483
46733
  s.curIx = msg.fileIx;
@@ -46548,7 +46798,7 @@ var import_selfsigned = __toESM(require_selfsigned(), 1);
46548
46798
  import tls from "node:tls";
46549
46799
  import { X509Certificate } from "node:crypto";
46550
46800
  import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, existsSync as existsSync10, mkdirSync as mkdirSync6 } from "node:fs";
46551
- import { dirname as dirname8 } from "node:path";
46801
+ import { dirname as dirname9 } from "node:path";
46552
46802
  function fingerprintOf(certPem) {
46553
46803
  return new X509Certificate(certPem).fingerprint256;
46554
46804
  }
@@ -46561,7 +46811,7 @@ async function loadOrCreateIdentity(certPath, keyPath) {
46561
46811
  const tenYears = new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1e3);
46562
46812
  const pems = await (0, import_selfsigned.generate)([{ name: "commonName", value: "tesseract-peer" }], { keySize: 2048, notAfterDate: tenYears, algorithm: "sha256" });
46563
46813
  try {
46564
- mkdirSync6(dirname8(certPath), { recursive: true });
46814
+ mkdirSync6(dirname9(certPath), { recursive: true });
46565
46815
  } catch {
46566
46816
  }
46567
46817
  try {
@@ -47067,13 +47317,13 @@ async function openPeerLink(peerHostId, ctx) {
47067
47317
  // ../../packages/host-core/dist/active-link/engine.js
47068
47318
  import { lstat as lstat6, readlink as readlink4, rm as rm3, mkdir as mkdir7, symlink as symlink2, rename as rename2, utimes as utimes2, writeFile as writeFile5 } from "node:fs/promises";
47069
47319
  import { existsSync as existsSync12 } from "node:fs";
47070
- import { dirname as dirname12, join as join24, resolve as resolve7 } from "node:path";
47320
+ import { dirname as dirname13, join as join24, resolve as resolve7 } from "node:path";
47071
47321
 
47072
47322
  // ../../packages/host-core/dist/active-link/blocks.js
47073
47323
  import { createHash as createHash3 } from "node:crypto";
47074
47324
  import { createReadStream } from "node:fs";
47075
47325
  import { open, mkdir as mkdir6, rename, chmod as chmod2, utimes, unlink } from "node:fs/promises";
47076
- import { dirname as dirname9 } from "node:path";
47326
+ import { dirname as dirname10 } from "node:path";
47077
47327
  var CHUNK3 = 1024 * 1024;
47078
47328
  var MAX_INFLIGHT2 = 8 * CHUNK3;
47079
47329
  var IDLE_MS2 = 6e4;
@@ -47201,7 +47451,7 @@ var StagingWriter = class {
47201
47451
  }
47202
47452
  async ensureOpen() {
47203
47453
  if (!this.fh) {
47204
- await mkdir6(dirname9(this.stagingPath), { recursive: true });
47454
+ await mkdir6(dirname10(this.stagingPath), { recursive: true });
47205
47455
  this.fh = await open(this.stagingPath, "w");
47206
47456
  }
47207
47457
  return this.fh;
@@ -47231,7 +47481,7 @@ var StagingWriter = class {
47231
47481
  });
47232
47482
  await fh.close();
47233
47483
  this.fh = null;
47234
- await mkdir6(dirname9(dest), { recursive: true });
47484
+ await mkdir6(dirname10(dest), { recursive: true });
47235
47485
  await chmod2(this.stagingPath, mode & 511).catch(() => {
47236
47486
  });
47237
47487
  const secs = mtimeMs / 1e3;
@@ -47264,7 +47514,7 @@ var BlockAssembler = class {
47264
47514
  this.stagingPath = stagingPath;
47265
47515
  }
47266
47516
  async open() {
47267
- await mkdir6(dirname9(this.stagingPath), { recursive: true });
47517
+ await mkdir6(dirname10(this.stagingPath), { recursive: true });
47268
47518
  this.fh = await open(this.stagingPath, "w");
47269
47519
  }
47270
47520
  /** Write a received block at its byte offset (index * CHUNK). */
@@ -47308,7 +47558,7 @@ var BlockAssembler = class {
47308
47558
  });
47309
47559
  return false;
47310
47560
  }
47311
- await mkdir6(dirname9(dest), { recursive: true });
47561
+ await mkdir6(dirname10(dest), { recursive: true });
47312
47562
  await chmod2(this.stagingPath, mode & 511).catch(() => {
47313
47563
  });
47314
47564
  const secs = mtimeMs / 1e3;
@@ -47886,10 +48136,10 @@ var ReaddirpStream = class extends Readable {
47886
48136
  }
47887
48137
  async _formatEntry(dirent, path5) {
47888
48138
  let entry;
47889
- const basename6 = this._isDirent ? dirent.name : dirent;
48139
+ const basename7 = this._isDirent ? dirent.name : dirent;
47890
48140
  try {
47891
- const fullPath = presolve(pjoin(path5, basename6));
47892
- entry = { path: prelative(this._root, fullPath), fullPath, basename: basename6 };
48141
+ const fullPath = presolve(pjoin(path5, basename7));
48142
+ entry = { path: prelative(this._root, fullPath), fullPath, basename: basename7 };
47893
48143
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
47894
48144
  } catch (err) {
47895
48145
  this._onError(err);
@@ -48428,9 +48678,9 @@ var NodeFsHandler = class {
48428
48678
  _watchWithNodeFs(path5, listener) {
48429
48679
  const opts = this.fsw.options;
48430
48680
  const directory = sysPath.dirname(path5);
48431
- const basename6 = sysPath.basename(path5);
48681
+ const basename7 = sysPath.basename(path5);
48432
48682
  const parent = this.fsw._getWatchedDir(directory);
48433
- parent.add(basename6);
48683
+ parent.add(basename7);
48434
48684
  const absolutePath = sysPath.resolve(path5);
48435
48685
  const options = {
48436
48686
  persistent: opts.persistent
@@ -48440,7 +48690,7 @@ var NodeFsHandler = class {
48440
48690
  let closer;
48441
48691
  if (opts.usePolling) {
48442
48692
  const enableBin = opts.interval !== opts.binaryInterval;
48443
- options.interval = enableBin && isBinaryPath(basename6) ? opts.binaryInterval : opts.interval;
48693
+ options.interval = enableBin && isBinaryPath(basename7) ? opts.binaryInterval : opts.interval;
48444
48694
  closer = setFsWatchFileListener(path5, absolutePath, options, {
48445
48695
  listener,
48446
48696
  rawEmitter: this.fsw._emitRaw
@@ -48462,11 +48712,11 @@ var NodeFsHandler = class {
48462
48712
  if (this.fsw.closed) {
48463
48713
  return;
48464
48714
  }
48465
- const dirname17 = sysPath.dirname(file2);
48466
- const basename6 = sysPath.basename(file2);
48467
- const parent = this.fsw._getWatchedDir(dirname17);
48715
+ const dirname18 = sysPath.dirname(file2);
48716
+ const basename7 = sysPath.basename(file2);
48717
+ const parent = this.fsw._getWatchedDir(dirname18);
48468
48718
  let prevStats = stats;
48469
- if (parent.has(basename6))
48719
+ if (parent.has(basename7))
48470
48720
  return;
48471
48721
  const listener = async (path5, newStats) => {
48472
48722
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
@@ -48491,9 +48741,9 @@ var NodeFsHandler = class {
48491
48741
  prevStats = newStats2;
48492
48742
  }
48493
48743
  } catch (error51) {
48494
- this.fsw._remove(dirname17, basename6);
48744
+ this.fsw._remove(dirname18, basename7);
48495
48745
  }
48496
- } else if (parent.has(basename6)) {
48746
+ } else if (parent.has(basename7)) {
48497
48747
  const at = newStats.atimeMs;
48498
48748
  const mt = newStats.mtimeMs;
48499
48749
  if (!at || at <= mt || mt !== prevStats.mtimeMs) {
@@ -49417,7 +49667,7 @@ var FSWatcher = class extends EventEmitter2 {
49417
49667
  return stream;
49418
49668
  }
49419
49669
  };
49420
- function watch2(paths, options = {}) {
49670
+ function watch3(paths, options = {}) {
49421
49671
  const watcher = new FSWatcher(options);
49422
49672
  watcher.add(paths);
49423
49673
  return watcher;
@@ -49435,7 +49685,7 @@ var LinkWatcher = class {
49435
49685
  this.debounceMs = opts.debounceMs ?? 500;
49436
49686
  }
49437
49687
  async start() {
49438
- this.fsw = watch2(this.opts.root, {
49688
+ this.fsw = watch3(this.opts.root, {
49439
49689
  ignoreInitial: true,
49440
49690
  // the engine does its own hashing scan on start
49441
49691
  followSymlinks: false,
@@ -49934,13 +50184,13 @@ var ActiveLinkEngine = class {
49934
50184
  * file so the path still exists — recorded as a FILE matching disk so the local
49935
50185
  * watcher doesn't churn. The target is containment-checked, never dereferenced. */
49936
50186
  async applySymlink(rel, dest, target, mtimeMs, mode) {
49937
- const resolved = resolve7(dirname12(dest), target);
50187
+ const resolved = resolve7(dirname13(dest), target);
49938
50188
  if (!isInsideRoot(resolved, this.opts.localRoot))
49939
50189
  return;
49940
50190
  const hash2 = hashString(target);
49941
50191
  const secs = mtimeMs / 1e3;
49942
50192
  try {
49943
- await mkdir7(dirname12(dest), { recursive: true });
50193
+ await mkdir7(dirname13(dest), { recursive: true });
49944
50194
  await rm3(dest, { force: true, recursive: true });
49945
50195
  try {
49946
50196
  await symlink2(target, dest);
@@ -49990,7 +50240,7 @@ var ActiveLinkEngine = class {
49990
50240
  return;
49991
50241
  if (fromRec && fromRec.kind === "file") {
49992
50242
  try {
49993
- await mkdir7(dirname12(toAbs), { recursive: true });
50243
+ await mkdir7(dirname13(toAbs), { recursive: true });
49994
50244
  await rename2(fromAbs, toAbs);
49995
50245
  const secs = mtimeMs / 1e3;
49996
50246
  await utimes2(toAbs, secs, secs).catch(() => {
@@ -50190,7 +50440,7 @@ var ActiveLinkEngine = class {
50190
50440
  };
50191
50441
 
50192
50442
  // ../../packages/host-core/dist/active-link/config.js
50193
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, existsSync as existsSync13, renameSync as renameSync6, watch as watch3 } from "node:fs";
50443
+ import { readFileSync as readFileSync10, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, existsSync as existsSync13, renameSync as renameSync6, watch as watch4 } from "node:fs";
50194
50444
  import { join as join25 } from "node:path";
50195
50445
  function configPath2() {
50196
50446
  return join25(activeLinkRoot(), "links.json");
@@ -50264,7 +50514,7 @@ function watchLinkConfigs(onChange) {
50264
50514
  let timer = null;
50265
50515
  let watcher = null;
50266
50516
  try {
50267
- watcher = watch3(dir, (_evt, file2) => {
50517
+ watcher = watch4(dir, (_evt, file2) => {
50268
50518
  if (file2 && file2 !== "links.json")
50269
50519
  return;
50270
50520
  if (timer)
@@ -50920,7 +51170,7 @@ function sendActiveLinkProvision(cfg2) {
50920
51170
  type: "provision",
50921
51171
  linkId: cfg2.linkId,
50922
51172
  fromHost: ownHostId(),
50923
- projectName: cfg2.remoteSubfolder ?? basename5(cfg2.localRoot),
51173
+ projectName: cfg2.remoteSubfolder ?? basename6(cfg2.localRoot),
50924
51174
  ...cfg2.remoteParent ? { remoteParent: cfg2.remoteParent } : {},
50925
51175
  ...cfg2.remoteSubfolder ? { remoteSubfolder: cfg2.remoteSubfolder } : {},
50926
51176
  ...cfg2.workspaceLinkId ? { workspaceLinkId: cfg2.workspaceLinkId } : {}
@@ -51127,6 +51377,20 @@ async function handleInboundAgent(msg, driverClientId) {
51127
51377
  send("agent", { type: "session:messages", sessionId: msg.sessionId, messages }, route2);
51128
51378
  break;
51129
51379
  }
51380
+ case "session:watch":
51381
+ if (driverClientId) {
51382
+ void watchSession(msg.sessionId, driverClientId, msg.projectDir, {
51383
+ getMessages: (sid) => b.getMessages(sid),
51384
+ isSessionBusy: (sid) => b.isSessionBusy?.(sid) ?? false,
51385
+ resolveFile: (sid, dir) => b.resolveSessionFile?.(sid, dir) ?? Promise.resolve(null),
51386
+ emit: (key2, m) => send("agent", m, { clientId: key2 })
51387
+ });
51388
+ }
51389
+ break;
51390
+ case "session:unwatch":
51391
+ if (driverClientId)
51392
+ unwatchSession(msg.sessionId, driverClientId);
51393
+ break;
51130
51394
  case "session:fork": {
51131
51395
  const newId = await b.forkSession?.(msg.sessionId, { projectDir: msg.projectDir, upToMessageId: msg.upToMessageId, title: msg.title }).catch(() => null);
51132
51396
  if (newId)
@@ -51249,6 +51513,7 @@ async function serveInboundTerm(p, driverClientId) {
51249
51513
  }
51250
51514
  function releaseDriver(clientId) {
51251
51515
  unwatchRemoteClient(clientId);
51516
+ unwatchSessionClient(clientId);
51252
51517
  releaseClientPtys(clientId);
51253
51518
  releaseDcClient(clientId);
51254
51519
  for (const [sid, cid] of [...driverBySession]) {
@@ -51281,6 +51546,7 @@ function teardownHostRole() {
51281
51546
  driverBySession.clear();
51282
51547
  driverByRequest.clear();
51283
51548
  unwatchAllRemote();
51549
+ unwatchAllSessions();
51284
51550
  releaseRemotePtys();
51285
51551
  try {
51286
51552
  hostBackend?.reclaim("critical");
@@ -51700,6 +51966,7 @@ async function startLocalServer(opts) {
51700
51966
  });
51701
51967
  ws.on("close", () => {
51702
51968
  unregisterSink();
51969
+ unwatchSessionClient(loopbackOrigin);
51703
51970
  clearBrowserOrigin(loopbackOrigin);
51704
51971
  if (heldSessions.size) {
51705
51972
  const b = peekSharedBackend();
@@ -51758,6 +52025,17 @@ async function startLocalServer(opts) {
51758
52025
  send2("agent", { type: "session:messages", sessionId: msg.sessionId, messages });
51759
52026
  break;
51760
52027
  }
52028
+ case "session:watch":
52029
+ void watchSession(msg.sessionId, loopbackOrigin, msg.projectDir, {
52030
+ getMessages: (sid) => b.getMessages(sid),
52031
+ isSessionBusy: (sid) => b.isSessionBusy?.(sid) ?? false,
52032
+ resolveFile: (sid, dir) => b.resolveSessionFile?.(sid, dir) ?? Promise.resolve(null),
52033
+ emit: (_key, m) => send2("agent", m)
52034
+ });
52035
+ break;
52036
+ case "session:unwatch":
52037
+ unwatchSession(msg.sessionId, loopbackOrigin);
52038
+ break;
51761
52039
  case "session:fork": {
51762
52040
  const newId = await b.forkSession?.(msg.sessionId, { projectDir: msg.projectDir, upToMessageId: msg.upToMessageId, title: msg.title }).catch(() => null);
51763
52041
  if (newId)
@@ -52100,7 +52378,7 @@ import { platform as platform2 } from "node:os";
52100
52378
 
52101
52379
  // ../../packages/host-core/dist/service/launchd.js
52102
52380
  import { writeFileSync as writeFileSync11, existsSync as existsSync16, mkdirSync as mkdirSync11, unlinkSync as unlinkSync3 } from "node:fs";
52103
- import { dirname as dirname13, join as join28 } from "node:path";
52381
+ import { dirname as dirname14, join as join28 } from "node:path";
52104
52382
  import { homedir as homedir12, userInfo } from "node:os";
52105
52383
 
52106
52384
  // ../../packages/host-core/dist/service/exec.js
@@ -52167,8 +52445,8 @@ ${env}
52167
52445
  }
52168
52446
  return {
52169
52447
  async install(spec) {
52170
- mkdirSync11(dirname13(plistPath()), { recursive: true });
52171
- mkdirSync11(dirname13(spec.logPath), { recursive: true });
52448
+ mkdirSync11(dirname14(plistPath()), { recursive: true });
52449
+ mkdirSync11(dirname14(spec.logPath), { recursive: true });
52172
52450
  writeFileSync11(plistPath(), buildPlist(spec));
52173
52451
  await run("launchctl", ["bootout", serviceTarget()]).catch(() => {
52174
52452
  });
@@ -52220,7 +52498,7 @@ ${env}
52220
52498
 
52221
52499
  // ../../packages/host-core/dist/service/systemd.js
52222
52500
  import { writeFileSync as writeFileSync12, existsSync as existsSync17, mkdirSync as mkdirSync12, unlinkSync as unlinkSync4 } from "node:fs";
52223
- import { dirname as dirname14, join as join29 } from "node:path";
52501
+ import { dirname as dirname15, join as join29 } from "node:path";
52224
52502
  import { homedir as homedir13, userInfo as userInfo2 } from "node:os";
52225
52503
  function shq(s) {
52226
52504
  return `"${s.replace(/(["\\$`])/g, "\\$1")}"`;
@@ -52254,8 +52532,8 @@ WantedBy=default.target
52254
52532
  }
52255
52533
  return {
52256
52534
  async install(spec) {
52257
- mkdirSync12(dirname14(unitPath()), { recursive: true });
52258
- mkdirSync12(dirname14(spec.logPath), { recursive: true });
52535
+ mkdirSync12(dirname15(unitPath()), { recursive: true });
52536
+ mkdirSync12(dirname15(spec.logPath), { recursive: true });
52259
52537
  writeFileSync12(unitPath(), buildUnit(spec));
52260
52538
  await run("loginctl", ["enable-linger", userInfo2().username]).catch(() => {
52261
52539
  });
@@ -52300,7 +52578,7 @@ WantedBy=default.target
52300
52578
 
52301
52579
  // ../../packages/host-core/dist/service/windows.js
52302
52580
  import { writeFileSync as writeFileSync13, existsSync as existsSync18, mkdirSync as mkdirSync13, unlinkSync as unlinkSync5 } from "node:fs";
52303
- import { dirname as dirname15, join as join30 } from "node:path";
52581
+ import { dirname as dirname16, join as join30 } from "node:path";
52304
52582
  function makeWindowsTask(instanceId) {
52305
52583
  const task = `Fineguide\\TesseractHost${instanceId ? `-${instanceId}` : ""}`;
52306
52584
  const wrapperPath = () => join30(daemonDir(), `run-host${instanceId ? `-${instanceId}` : ""}.cmd`);
@@ -52315,8 +52593,8 @@ start "" /b ${cmd} >> "${spec.logPath}" 2>&1\r
52315
52593
  }
52316
52594
  return {
52317
52595
  async install(spec) {
52318
- mkdirSync13(dirname15(spec.logPath), { recursive: true });
52319
- mkdirSync13(dirname15(wrapperPath()), { recursive: true });
52596
+ mkdirSync13(dirname16(spec.logPath), { recursive: true });
52597
+ mkdirSync13(dirname16(wrapperPath()), { recursive: true });
52320
52598
  writeFileSync13(wrapperPath(), buildWrapper(spec));
52321
52599
  await run("schtasks", ["/Create", "/TN", task, "/SC", "ONLOGON", "/RL", "LIMITED", "/F", "/TR", `"${wrapperPath()}"`]);
52322
52600
  await run("schtasks", ["/Run", "/TN", task]).catch(() => {
@@ -52750,7 +53028,7 @@ async function logs(instanceId, follow) {
52750
53028
  // src/cli.ts
52751
53029
  function pkgVersion() {
52752
53030
  try {
52753
- const p = join33(dirname16(fileURLToPath2(import.meta.url)), "..", "package.json");
53031
+ const p = join33(dirname17(fileURLToPath2(import.meta.url)), "..", "package.json");
52754
53032
  return JSON.parse(readFileSync13(p, "utf8")).version ?? "0.0.0";
52755
53033
  } catch {
52756
53034
  return "0.0.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tesseract-agent",
3
- "version": "0.4.13",
3
+ "version": "0.4.14",
4
4
  "license": "UNLICENSED",
5
5
  "publishConfig": {
6
6
  "access": "public"