@zuzuucodes/cli 1.2.3 → 1.3.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/bin/zuzuu.mjs CHANGED
@@ -32,6 +32,7 @@ import { code } from '../zuzuu/commands/code.mjs';
32
32
  import { web } from '../zuzuu/commands/web.mjs';
33
33
  import { explain } from '../zuzuu/commands/explain.mjs';
34
34
  import { inbox } from '../zuzuu/commands/inbox.mjs';
35
+ import { session } from '../zuzuu/commands/session.mjs';
35
36
 
36
37
  function parseArgs(argv) {
37
38
  const a = { _: [] };
@@ -89,6 +90,8 @@ usage: zuzuu <command> [options]
89
90
  pin/list/show/roll back faculty generations (lockfiles)
90
91
  enable background hooks: invisible live capture + guardrails gate
91
92
  disable remove the background hooks
93
+ session [status|merge|continue|discard]
94
+ the invisible session branch (one per agent session)
92
95
  eval [--faculty f] rank pending proposals by eval score, highest first
93
96
  migrate [--home] one-time migrators: proposal schema · --home moves agent/ → .zuzuu/
94
97
  doctor environment + session health (reconciles lost sessions)
@@ -122,6 +125,7 @@ switch (cmd) {
122
125
  case 'enable': enable(args); break;
123
126
  case 'disable': disable(args); break;
124
127
  case 'hook': runHook(args._[0], { host: args.host, session: args.session }); break;
128
+ case 'session': session(args); break;
125
129
  case 'eval': evalCmd(args); break;
126
130
  case 'migrate': migrate(args); break;
127
131
  case 'generation': generation(args); break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zuzuucodes/cli",
3
- "version": "1.2.3",
3
+ "version": "1.3.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -11,7 +11,7 @@ import { execFile } from "node:child_process";
11
11
  import { promisify } from "node:util";
12
12
  import { SessionManager } from "./sessions.js";
13
13
  import { createFsApi } from "./fs-api.js";
14
- import { createZuzuuApi } from "./zuzuu-api.js";
14
+ import { createZuzuuApi, runZuzuuMut } from "./zuzuu-api.js";
15
15
  import { search } from "./search.js";
16
16
  import { listFiles } from "./file-list.js";
17
17
  import { listWorkflows, saveWorkflow } from "./workflows.js";
@@ -25,6 +25,8 @@ import { handleFsSocket } from "./ws-fs.js";
25
25
  import { PathError, resolveSafe, safeJoin } from "./safe-path.js";
26
26
  const AUTH_COOKIE = "webcode_auth";
27
27
  const COOKIE_MAX_AGE = 30 * 24 * 3600;
28
+ /** Host CLIs an agent/command session may run. Argv-spawned, never a shell. */
29
+ const DEFAULT_COMMAND_ALLOWLIST = ["claude", "gemini", "codex", "pi", "opencode", "zuzuu"];
28
30
  const STATIC_MIME = {
29
31
  ".html": "text/html; charset=utf-8",
30
32
  ".js": "text/javascript",
@@ -46,10 +48,12 @@ export class WebcodeServer {
46
48
  authSessions = new Set();
47
49
  allowedHosts;
48
50
  allowedOrigins;
51
+ commandAllowlist;
49
52
  server = null;
50
53
  constructor(cfg) {
51
54
  this.cfg = cfg;
52
55
  this.root = cfg.root;
56
+ this.commandAllowlist = new Set(cfg.commandAllowlist ?? DEFAULT_COMMAND_ALLOWLIST);
53
57
  this.sessions = new SessionManager(cfg.root);
54
58
  const hostNames = ["127.0.0.1", "localhost", "[::1]"];
55
59
  this.allowedHosts = new Set(hostNames.flatMap((h) => [h, `${h}:${cfg.port}`]));
@@ -81,6 +85,22 @@ export class WebcodeServer {
81
85
  this.root = resolved;
82
86
  await config.addRecent(resolved);
83
87
  }
88
+ /**
89
+ * Agent PTY exited → squash-merge its invisible session branch back to
90
+ * main via the zuzuu CLI. Runs in the session's cwd (the repo the agent
91
+ * worked in). CLI-only, like every zuzuu mutation; absent CLI is recorded,
92
+ * never fatal. Session.runCloseHook guarantees this runs once per session.
93
+ */
94
+ async closeAgentSession(session) {
95
+ const r = await runZuzuuMut(session.cwd, ["session", "merge"], {
96
+ binary: this.cfg.zuzuuBinary,
97
+ });
98
+ if (r.ok)
99
+ return { ok: true, merge: r.data };
100
+ if (r.code === "absent")
101
+ return { cliAbsent: true };
102
+ return { ok: false, ...(r.stderr !== undefined ? { stderr: r.stderr } : {}), ...(r.data !== undefined ? { refusal: r.data } : {}) };
103
+ }
84
104
  // ── security gates ─────────────────────────────────────────────────
85
105
  /** Host allowlist defeats DNS rebinding: rebinding changes DNS, not the Host header. */
86
106
  hostAllowed(host) {
@@ -152,10 +172,52 @@ export class WebcodeServer {
152
172
  catch {
153
173
  // empty body is fine
154
174
  }
175
+ // Direct command sessions: the allowlist keeps the spawn surface honest
176
+ // (authenticated localhost daemon or not). Argv only — never a shell.
177
+ if (body.command !== undefined) {
178
+ if (typeof body.command !== "string" || !this.commandAllowlist.has(body.command)) {
179
+ return c.json({ error: "command not allowed" }, 400);
180
+ }
181
+ if (body.args !== undefined &&
182
+ (!Array.isArray(body.args) || !body.args.every((a) => typeof a === "string"))) {
183
+ return c.json({ error: "args must be an array of strings" }, 400);
184
+ }
185
+ }
186
+ else if (body.args !== undefined) {
187
+ return c.json({ error: "args require command" }, 400);
188
+ }
189
+ if (body.type !== undefined && body.type !== "shell" && body.type !== "agent") {
190
+ return c.json({ error: "bad type" }, 400);
191
+ }
192
+ if (body.host !== undefined && (typeof body.host !== "string" || body.host.length > 64)) {
193
+ return c.json({ error: "bad host" }, 400);
194
+ }
155
195
  const cwd = body.cwd ? safeJoin(this.root, body.cwd) : this.root;
156
- const session = this.sessions.create(cwd, body.cols, body.rows);
196
+ const type = body.type ?? "shell";
197
+ const session = this.sessions.create(cwd, body.cols, body.rows, {
198
+ ...(body.command !== undefined ? { command: body.command, args: body.args ?? [] } : {}),
199
+ type,
200
+ ...(body.host !== undefined ? { host: body.host } : {}),
201
+ ...(type === "agent" ? { onClose: (s) => this.closeAgentSession(s) } : {}),
202
+ });
157
203
  return c.json(session.info(), 201);
158
204
  });
205
+ // Single-session read: the SPA polls this once after the Exit frame to
206
+ // pick up closeResult (the agent-exit auto-merge outcome). Awaiting
207
+ // whenClosed() means a poll that races the merge still gets the result.
208
+ app.get("/api/sessions/:id", async (c) => {
209
+ const session = this.sessions.get(c.req.param("id"));
210
+ if (!session)
211
+ return c.json({ error: "no such session" }, 404);
212
+ await session.whenClosed();
213
+ const body = {
214
+ ...session.info(),
215
+ ...(session.closeResult !== undefined
216
+ ? { closeResult: session.closeResult }
217
+ : {}),
218
+ };
219
+ return c.json(body);
220
+ });
159
221
  app.delete("/api/sessions/:id", (c) => {
160
222
  const ok = this.sessions.close(c.req.param("id"));
161
223
  return ok ? c.json({ ok: true }) : c.json({ error: "no such session" }, 404);
@@ -333,7 +395,7 @@ export class WebcodeServer {
333
395
  return c.json({ ok: true, root: this.root });
334
396
  });
335
397
  app.route("/api/fs", createFsApi(() => this.root));
336
- app.route("/api/zuzuu", createZuzuuApi(() => this.root));
398
+ app.route("/api/zuzuu", createZuzuuApi(() => this.root, { binary: cfg.zuzuuBinary }));
337
399
  // Static SPA with index.html fallback
338
400
  app.get("*", async (c) => {
339
401
  let rel = decodeURIComponent(new URL(c.req.url).pathname);
@@ -65,10 +65,17 @@ export class Session {
65
65
  cwd;
66
66
  root;
67
67
  onUpdate;
68
+ opts;
68
69
  id = crypto.randomBytes(8).toString("hex");
69
70
  createdAt = Date.now();
70
71
  title;
71
72
  alive = true;
73
+ type;
74
+ host;
75
+ /** result of the agent-exit close hook (e.g. the session-git merge) */
76
+ closeResult;
77
+ closeRan = false;
78
+ closeSettled = Promise.resolve();
72
79
  /** live working directory of the shell (absolute) */
73
80
  cwdAbs;
74
81
  pty;
@@ -87,13 +94,16 @@ export class Session {
87
94
  castEvents = [];
88
95
  castBytes = 0;
89
96
  castTruncated = false;
90
- constructor(cwd, root, cols = 80, rows = 24, onUpdate) {
97
+ constructor(cwd, root, cols = 80, rows = 24, onUpdate, opts = {}) {
91
98
  this.cwd = cwd;
92
99
  this.root = root;
93
100
  this.onUpdate = onUpdate;
101
+ this.opts = opts;
94
102
  this.cwdAbs = cwd;
95
- const shell = pickShell();
96
- this.title = shell.split("/").pop() ?? shell;
103
+ this.type = opts.type ?? "shell";
104
+ this.host = opts.host;
105
+ const file = opts.command ?? pickShell();
106
+ this.title = file.split("/").pop() ?? file;
97
107
  this.mirror = new Terminal({ cols, rows, scrollback: SCROLLBACK, allowProposedApi: true });
98
108
  this.mirror.loadAddon(this.serializer);
99
109
  // OSC 7: the shell reports its real cwd instantly/exactly; this makes
@@ -111,10 +121,15 @@ export class Session {
111
121
  }
112
122
  return true;
113
123
  });
114
- const injection = process.platform === "win32" ? null : buildInjection(shell);
124
+ // Direct command sessions (agents) get NO shell and NO rc injection:
125
+ // the argv is spawned as-is with a plain env, so nothing a host CLI
126
+ // prints/parses is polluted by our shell-integration hook.
127
+ const injection = opts.command || process.platform === "win32" ? null : buildInjection(file);
115
128
  this.tempDir = injection?.tempDir;
116
- const args = injection?.args ?? (process.platform === "win32" ? [] : ["-l"]);
117
- this.pty = pty.spawn(shell, args, {
129
+ const args = opts.command !== undefined
130
+ ? opts.args ?? []
131
+ : injection?.args ?? (process.platform === "win32" ? [] : ["-l"]);
132
+ this.pty = pty.spawn(file, args, {
118
133
  name: "xterm-256color",
119
134
  cols,
120
135
  rows,
@@ -148,11 +163,28 @@ export class Session {
148
163
  });
149
164
  this.pty.onExit(({ exitCode, signal }) => {
150
165
  this.alive = false;
166
+ this.runCloseHook();
151
167
  this.exitPayload = JSON.stringify({ exitCode, signal });
152
168
  this.send(encodeFrame(ServerOp.Exit, this.exitPayload));
153
169
  this.onUpdate();
154
170
  });
155
171
  }
172
+ /** Agent exit → run the close hook (session-git merge) exactly once. */
173
+ runCloseHook() {
174
+ const onClose = this.opts.onClose;
175
+ if (this.type !== "agent" || !onClose || this.closeRan)
176
+ return;
177
+ this.closeRan = true;
178
+ this.closeSettled = onClose(this).then((result) => {
179
+ this.closeResult = result;
180
+ }, () => {
181
+ this.closeResult = { ok: false, stderr: "close hook failed" };
182
+ });
183
+ }
184
+ /** Resolves once any pending agent close hook has settled (immediately otherwise). */
185
+ whenClosed() {
186
+ return this.closeSettled;
187
+ }
156
188
  /** Single-attachment model: a new client takes over the session. */
157
189
  attach(ws) {
158
190
  if (this.socket && this.socket !== ws) {
@@ -296,6 +328,8 @@ export class Session {
296
328
  cwd: this.cwdAbs,
297
329
  alive: this.alive,
298
330
  createdAt: this.createdAt,
331
+ type: this.type,
332
+ ...(this.host !== undefined ? { host: this.host } : {}),
299
333
  };
300
334
  }
301
335
  }
@@ -305,8 +339,8 @@ export class SessionManager {
305
339
  constructor(defaultCwd = os.homedir()) {
306
340
  this.defaultCwd = defaultCwd;
307
341
  }
308
- create(cwd, cols, rows) {
309
- const session = new Session(cwd ?? this.defaultCwd, this.defaultCwd, cols, rows, () => { });
342
+ create(cwd, cols, rows, opts) {
343
+ const session = new Session(cwd ?? this.defaultCwd, this.defaultCwd, cols, rows, () => { }, opts);
310
344
  this.sessions.set(session.id, session);
311
345
  return session;
312
346
  }
@@ -98,8 +98,17 @@ export function runZuzuuMut(root, args, opts = {}) {
98
98
  });
99
99
  child.on("close", (code) => {
100
100
  clearTimeout(timer);
101
- if (code !== 0)
102
- return finish({ ok: false, code: "failed", stderr: err.slice(-STDERR_TAIL) });
101
+ if (code !== 0) {
102
+ // zuzuu prints structured JSON even on refusals (exit 1, e.g.
103
+ // empty-squash-with-checkpoints) — keep it so the UI can act on reason.
104
+ try {
105
+ const parsed = JSON.parse(out);
106
+ return finish({ ok: false, code: "failed", stderr: err.slice(-STDERR_TAIL), data: parsed });
107
+ }
108
+ catch {
109
+ return finish({ ok: false, code: "failed", stderr: err.slice(-STDERR_TAIL) });
110
+ }
111
+ }
103
112
  try {
104
113
  finish({ ok: true, data: JSON.parse(out) });
105
114
  }
@@ -279,7 +288,7 @@ export function createZuzuuApi(getRoot, opts = {}) {
279
288
  if (!r.ok) {
280
289
  return r.code === "absent"
281
290
  ? c.json({ error: "zuzuu CLI required" }, 503)
282
- : c.json({ error: "zuzuu command failed", stderr: r.stderr ?? "" }, 502);
291
+ : c.json({ error: "zuzuu command failed", stderr: r.stderr ?? "", data: r.data ?? null }, 502);
283
292
  }
284
293
  return c.json(r.data);
285
294
  };
@@ -327,6 +336,18 @@ export function createZuzuuApi(getRoot, opts = {}) {
327
336
  return c.json({ error: "bad id" }, 400);
328
337
  return mutate(c, ["generation", "rollback", id]);
329
338
  });
339
+ // ── Session-git (the invisible zz/session-* branch) — CLI-only, no
340
+ // file-read fallback: branch state lives in git, only the CLI computes it.
341
+ app.get("/session", async (c) => {
342
+ const viaCli = await runZuzuu(root, ["session", "status"], { binary: opts.binary });
343
+ if (viaCli)
344
+ return c.json(viaCli);
345
+ return c.json({ enabled: false, cliAbsent: true });
346
+ });
347
+ app.post("/session/merge", (c) => mutate(c, ["session", "merge"]));
348
+ app.post("/session/continue", (c) => mutate(c, ["session", "continue"]));
349
+ // --yes rides server-side: the SPA's confirm dialog is the human gate
350
+ app.post("/session/discard", (c) => mutate(c, ["session", "discard", "--yes"]));
330
351
  app.get("/eval", async (c) => {
331
352
  const viaCli = await runZuzuu(root, ["eval"], { binary: opts.binary });
332
353
  if (viaCli)
@@ -1 +1 @@
1
- import{d as e,f as t,u as n}from"./index-Cfwhe1gB.js";import{i as r,n as i,t as a}from"./monaco-setup-BBNGrQzm.js";var o=t();function s({path:t,name:s}){let{data:l,isLoading:u,error:d}=e({queryKey:[`git`,`diff`,t],queryFn:async()=>{let[e,r]=await Promise.all([n.gitDiff(t),n.readFile(t).catch(()=>``)]);return{original:e.original,working:r}}});return d?(0,o.jsx)(c,{danger:!0,children:d.message}):u||!l?(0,o.jsx)(c,{children:`loading diff…`}):(0,o.jsx)(r,{original:l.original,modified:l.working,language:i(s),theme:a(),options:{readOnly:!0,renderSideBySide:!0,fontFamily:`"JetBrains Mono Variable", ui-monospace, monospace`,fontSize:13,minimap:{enabled:!1},automaticLayout:!0}})}function c({children:e,danger:t}){return(0,o.jsx)(`div`,{className:`flex h-full items-center justify-center text-ui ${t?`text-danger`:`text-ink-500`}`,children:e})}export{s as DiffTab,s as default};
1
+ import{d as e,f as t,u as n}from"./index-Ye54YyTn.js";import{i as r,n as i,t as a}from"./monaco-setup-Dszx738Y.js";var o=t();function s({path:t,name:s}){let{data:l,isLoading:u,error:d}=e({queryKey:[`git`,`diff`,t],queryFn:async()=>{let[e,r]=await Promise.all([n.gitDiff(t),n.readFile(t).catch(()=>``)]);return{original:e.original,working:r}}});return d?(0,o.jsx)(c,{danger:!0,children:d.message}):u||!l?(0,o.jsx)(c,{children:`loading diff…`}):(0,o.jsx)(r,{original:l.original,modified:l.working,language:i(s),theme:a(),options:{readOnly:!0,renderSideBySide:!0,fontFamily:`"JetBrains Mono Variable", ui-monospace, monospace`,fontSize:13,minimap:{enabled:!1},automaticLayout:!0}})}function c({children:e,danger:t}){return(0,o.jsx)(`div`,{className:`flex h-full items-center justify-center text-ui ${t?`text-danger`:`text-ink-500`}`,children:e})}export{s as DiffTab,s as default};
@@ -1 +1 @@
1
- import{f as e,l as t}from"./index-Cfwhe1gB.js";import{n,r,t as i}from"./monaco-setup-BBNGrQzm.js";var a=e();function o({path:e,name:o}){let c=t(t=>t.buffers[e]),l=t(e=>e.setValue),u=t(e=>e.save);return!c||c.loading?(0,a.jsx)(s,{children:`loading…`}):c.error?(0,a.jsx)(s,{danger:!0,children:c.error}):(0,a.jsx)(r,{path:e,language:n(o),theme:i(),value:c.value,onChange:t=>l(e,t??``),onMount:(t,n)=>{t.addCommand(n.KeyMod.CtrlCmd|n.KeyCode.KeyS,()=>{u(e)})},options:{fontFamily:`"JetBrains Mono Variable", ui-monospace, monospace`,fontSize:13,lineHeight:1.5,minimap:{enabled:!0,scale:1},scrollBeyondLastLine:!1,smoothScrolling:!0,renderWhitespace:`selection`,tabSize:2,automaticLayout:!0,padding:{top:8}}})}function s({children:e,danger:t}){return(0,a.jsx)(`div`,{className:`flex h-full items-center justify-center text-ui ${t?`text-danger`:`text-ink-500`}`,children:e})}export{o as MonacoFile,o as default};
1
+ import{f as e,l as t}from"./index-Ye54YyTn.js";import{n,r,t as i}from"./monaco-setup-Dszx738Y.js";var a=e();function o({path:e,name:o}){let c=t(t=>t.buffers[e]),l=t(e=>e.setValue),u=t(e=>e.save);return!c||c.loading?(0,a.jsx)(s,{children:`loading…`}):c.error?(0,a.jsx)(s,{danger:!0,children:c.error}):(0,a.jsx)(r,{path:e,language:n(o),theme:i(),value:c.value,onChange:t=>l(e,t??``),onMount:(t,n)=>{t.addCommand(n.KeyMod.CtrlCmd|n.KeyCode.KeyS,()=>{u(e)})},options:{fontFamily:`"JetBrains Mono Variable", ui-monospace, monospace`,fontSize:13,lineHeight:1.5,minimap:{enabled:!0,scale:1},scrollBeyondLastLine:!1,smoothScrolling:!0,renderWhitespace:`selection`,tabSize:2,automaticLayout:!0,padding:{top:8}}})}function s({children:e,danger:t}){return(0,a.jsx)(`div`,{className:`flex h-full items-center justify-center text-ui ${t?`text-danger`:`text-ink-500`}`,children:e})}export{o as MonacoFile,o as default};
@@ -1 +1 @@
1
- import{h as e}from"./editor.api2-BmGoRSl4.js";import{o as t}from"./monaco-setup-BBNGrQzm.js";import{_ as n,a as r,c as i,d as a,f as o,g as s,h as c,i as l,l as u,m as d,n as f,o as p,p as m,r as h,s as g,t as _,u as v,v as y}from"./lspLanguageFeatures-gTnJsses.js";var b=120*1e3,x=class{constructor(e){this._defaults=e,this._worker=null,this._client=null,this._idleCheckInterval=window.setInterval(()=>this._checkIfIdle(),30*1e3),this._lastUsedTime=0,this._configChangeListener=this._defaults.onDidChange(()=>this._stopWorker())}_stopWorker(){this._worker&&=(this._worker.dispose(),null),this._client=null}dispose(){clearInterval(this._idleCheckInterval),this._configChangeListener.dispose(),this._stopWorker()}_checkIfIdle(){this._worker&&Date.now()-this._lastUsedTime>b&&this._stopWorker()}_getClient(){return this._lastUsedTime=Date.now(),this._client||=(this._worker=t({moduleId:`vs/language/css/cssWorker`,createWorker:()=>new Worker(new URL(`/assets/css.worker-CvXBzhp8.js`,``+import.meta.url),{type:`module`}),label:this._defaults.languageId,createData:{options:this._defaults.options,languageId:this._defaults.languageId}}),this._worker.getProxy()),this._client}getLanguageServiceWorker(...e){let t;return this._getClient().then(e=>{t=e}).then(t=>{if(this._worker)return this._worker.withSyncedResources(e)}).then(e=>t)}};function S(t){let n=[],s=[],c=new x(t);n.push(c);let g=(...e)=>c.getLanguageServiceWorker(...e);function y(){let{languageId:n,modeConfiguration:c}=t;w(s),c.completionItems&&s.push(e.registerCompletionItemProvider(n,new _(g,[`/`,`-`,`:`]))),c.hovers&&s.push(e.registerHoverProvider(n,new a(g))),c.documentHighlights&&s.push(e.registerDocumentHighlightProvider(n,new p(g))),c.definitions&&s.push(e.registerDefinitionProvider(n,new f(g))),c.references&&s.push(e.registerReferenceProvider(n,new o(g))),c.documentSymbols&&s.push(e.registerDocumentSymbolProvider(n,new u(g))),c.rename&&s.push(e.registerRenameProvider(n,new m(g))),c.colors&&s.push(e.registerColorProvider(n,new l(g))),c.foldingRanges&&s.push(e.registerFoldingRangeProvider(n,new v(g))),c.diagnostics&&s.push(new h(n,g,t.onDidChange)),c.selectionRanges&&s.push(e.registerSelectionRangeProvider(n,new d(g))),c.documentFormattingEdits&&s.push(e.registerDocumentFormattingEditProvider(n,new r(g))),c.documentRangeFormattingEdits&&s.push(e.registerDocumentRangeFormattingEditProvider(n,new i(g)))}return y(),n.push(C(s)),C(n)}function C(e){return{dispose:()=>w(e)}}function w(e){for(;e.length;)e.pop().dispose()}export{_ as CompletionAdapter,f as DefinitionAdapter,h as DiagnosticsAdapter,l as DocumentColorAdapter,r as DocumentFormattingEditProvider,p as DocumentHighlightAdapter,g as DocumentLinkAdapter,i as DocumentRangeFormattingEditProvider,u as DocumentSymbolAdapter,v as FoldingRangeAdapter,a as HoverAdapter,o as ReferenceAdapter,m as RenameAdapter,d as SelectionRangeAdapter,x as WorkerManager,c as fromPosition,s as fromRange,S as setupMode,n as toRange,y as toTextEdit};
1
+ import{h as e}from"./editor.api2-BmGoRSl4.js";import{o as t}from"./monaco-setup-Dszx738Y.js";import{_ as n,a as r,c as i,d as a,f as o,g as s,h as c,i as l,l as u,m as d,n as f,o as p,p as m,r as h,s as g,t as _,u as v,v as y}from"./lspLanguageFeatures-gTnJsses.js";var b=120*1e3,x=class{constructor(e){this._defaults=e,this._worker=null,this._client=null,this._idleCheckInterval=window.setInterval(()=>this._checkIfIdle(),30*1e3),this._lastUsedTime=0,this._configChangeListener=this._defaults.onDidChange(()=>this._stopWorker())}_stopWorker(){this._worker&&=(this._worker.dispose(),null),this._client=null}dispose(){clearInterval(this._idleCheckInterval),this._configChangeListener.dispose(),this._stopWorker()}_checkIfIdle(){this._worker&&Date.now()-this._lastUsedTime>b&&this._stopWorker()}_getClient(){return this._lastUsedTime=Date.now(),this._client||=(this._worker=t({moduleId:`vs/language/css/cssWorker`,createWorker:()=>new Worker(new URL(`/assets/css.worker-CvXBzhp8.js`,``+import.meta.url),{type:`module`}),label:this._defaults.languageId,createData:{options:this._defaults.options,languageId:this._defaults.languageId}}),this._worker.getProxy()),this._client}getLanguageServiceWorker(...e){let t;return this._getClient().then(e=>{t=e}).then(t=>{if(this._worker)return this._worker.withSyncedResources(e)}).then(e=>t)}};function S(t){let n=[],s=[],c=new x(t);n.push(c);let g=(...e)=>c.getLanguageServiceWorker(...e);function y(){let{languageId:n,modeConfiguration:c}=t;w(s),c.completionItems&&s.push(e.registerCompletionItemProvider(n,new _(g,[`/`,`-`,`:`]))),c.hovers&&s.push(e.registerHoverProvider(n,new a(g))),c.documentHighlights&&s.push(e.registerDocumentHighlightProvider(n,new p(g))),c.definitions&&s.push(e.registerDefinitionProvider(n,new f(g))),c.references&&s.push(e.registerReferenceProvider(n,new o(g))),c.documentSymbols&&s.push(e.registerDocumentSymbolProvider(n,new u(g))),c.rename&&s.push(e.registerRenameProvider(n,new m(g))),c.colors&&s.push(e.registerColorProvider(n,new l(g))),c.foldingRanges&&s.push(e.registerFoldingRangeProvider(n,new v(g))),c.diagnostics&&s.push(new h(n,g,t.onDidChange)),c.selectionRanges&&s.push(e.registerSelectionRangeProvider(n,new d(g))),c.documentFormattingEdits&&s.push(e.registerDocumentFormattingEditProvider(n,new r(g))),c.documentRangeFormattingEdits&&s.push(e.registerDocumentRangeFormattingEditProvider(n,new i(g)))}return y(),n.push(C(s)),C(n)}function C(e){return{dispose:()=>w(e)}}function w(e){for(;e.length;)e.pop().dispose()}export{_ as CompletionAdapter,f as DefinitionAdapter,h as DiagnosticsAdapter,l as DocumentColorAdapter,r as DocumentFormattingEditProvider,p as DocumentHighlightAdapter,g as DocumentLinkAdapter,i as DocumentRangeFormattingEditProvider,u as DocumentSymbolAdapter,v as FoldingRangeAdapter,a as HoverAdapter,o as ReferenceAdapter,m as RenameAdapter,d as SelectionRangeAdapter,x as WorkerManager,c as fromPosition,s as fromRange,S as setupMode,n as toRange,y as toTextEdit};