@quantiya/codevibe-codex-plugin 2.0.113 → 2.0.114

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.
@@ -6,10 +6,10 @@ export declare class ProcessRunError extends Error {
6
6
  readonly signal: NodeJS.Signals | null;
7
7
  readonly killed: boolean;
8
8
  readonly stderr: string;
9
- /** the deadline ended the run (or no time was left to start it) */
9
+ /** the deadline ended the run, no time was left to start it, or the runner was aborted */
10
10
  readonly timedOut: boolean;
11
11
  constructor(message: string, code: number | string | null, signal: NodeJS.Signals | null, killed: boolean, stderr: string,
12
- /** the deadline ended the run (or no time was left to start it) */
12
+ /** the deadline ended the run, no time was left to start it, or the runner was aborted */
13
13
  timedOut: boolean);
14
14
  }
15
15
  export interface ProcessRunner {
@@ -18,6 +18,11 @@ export interface ProcessRunner {
18
18
  cwd: string;
19
19
  env: NodeJS.ProcessEnv;
20
20
  }): Promise<string>;
21
+ /**
22
+ * End all remaining work: SIGKILL the group of every spawned child that has not closed, release queued runs, and fail
23
+ * every later run. Idempotent. Returns the ids of the process groups it ended (empty when nothing was live).
24
+ */
25
+ abort(): readonly number[];
21
26
  /** Process-group ids this runner spawned (diagnostics and tests). */
22
27
  readonly spawnedGroups: readonly number[];
23
28
  }
@@ -0,0 +1,18 @@
1
+ import type { AdvisoryWorkspaceFingerprintProbe } from './walk';
2
+ /** Longest a cell waits for its siblings before the shared probe starts anyway. */
3
+ export declare const PANEL_BASELINE_COALESCE_MS = 100;
4
+ export interface PanelBaselineTake {
5
+ probe: AdvisoryWorkspaceFingerprintProbe;
6
+ /** `shared`: the panel's probe; `own`: this cell asked after it started and ran its own */
7
+ baseline: 'shared' | 'own';
8
+ /** time from this cell's request to the start of its probe (the coalescing wait; 0 for `own`) */
9
+ waitedMs: number;
10
+ }
11
+ export interface PanelBaseline {
12
+ take(): Promise<PanelBaselineTake>;
13
+ }
14
+ export declare function createPanelBaseline(opts: {
15
+ expectedCells: number;
16
+ probe: () => Promise<AdvisoryWorkspaceFingerprintProbe>;
17
+ coalesceMs?: number;
18
+ }): PanelBaseline;
@@ -14682,12 +14682,17 @@ function endGroup(pgid) {
14682
14682
  } catch {
14683
14683
  }
14684
14684
  }
14685
+ var abortedError = (code = null, signal = null, stderr = "") => new ProcessRunError("aborted", code, signal, !0, stderr, !0);
14685
14686
  function createProcessRunner(deadline, concurrency = 4) {
14686
- let spawnedGroups = [], active = 0, waiting = [], acquire = () => active < concurrency ? (active++, Promise.resolve()) : new Promise((resolve35) => waiting.push(() => (active++, resolve35()))), release = () => {
14687
+ let spawnedGroups = [], live = /* @__PURE__ */ new Set(), runner = { state: "open" }, active = 0, waiting = [], acquire = () => active < concurrency || runner.state === "aborted" ? (active++, Promise.resolve()) : new Promise((resolve35) => waiting.push(() => (active++, resolve35()))), release = () => {
14687
14688
  active--;
14688
14689
  let next = waiting.shift();
14689
14690
  next && next();
14690
14691
  }, runOnce2 = (bin, args, opts) => new Promise((resolve35, reject) => {
14692
+ if (runner.state === "aborted") {
14693
+ reject(abortedError());
14694
+ return;
14695
+ }
14691
14696
  let remaining = deadline - Date.now();
14692
14697
  if (remaining < MIN_SPAWN_BUDGET_MS) {
14693
14698
  reject(new ProcessRunError("timeout", null, null, !1, "", !0));
@@ -14699,23 +14704,25 @@ function createProcessRunner(deadline, concurrency = 4) {
14699
14704
  detached: !0,
14700
14705
  // own process group: the whole group can be ended at the deadline
14701
14706
  stdio: ["ignore", "pipe", "pipe"]
14702
- });
14703
- typeof child.pid == "number" && spawnedGroups.push(child.pid);
14707
+ }), pid = typeof child.pid == "number" ? child.pid : null;
14708
+ pid !== null && (spawnedGroups.push(pid), live.add(pid));
14704
14709
  let out = [], outBytes = 0, err = "", timedOut = !1, overflow = !1, timer = setTimeout(() => {
14705
- timedOut = !0, typeof child.pid == "number" && endGroup(child.pid);
14710
+ timedOut = !0, pid !== null && endGroup(pid);
14706
14711
  }, remaining);
14707
14712
  child.stdout?.on("data", (chunk) => {
14708
14713
  if (outBytes += chunk.length, outBytes > STDOUT_CAP_BYTES) {
14709
- overflow = !0, typeof child.pid == "number" && endGroup(child.pid);
14714
+ overflow = !0, pid !== null && endGroup(pid);
14710
14715
  return;
14711
14716
  }
14712
14717
  out.push(chunk);
14713
14718
  }), child.stderr?.on("data", (chunk) => {
14714
14719
  err.length < STDERR_CAP_BYTES && (err += chunk.toString("utf8"));
14715
14720
  }), child.on("error", (spawnErr) => {
14716
- clearTimeout(timer), reject(new ProcessRunError(spawnErr.message, spawnErr.code ?? null, null, !1, err, !1));
14721
+ if (clearTimeout(timer), pid !== null && live.delete(pid), runner.state === "aborted") return reject(abortedError(spawnErr.code ?? null, null, err));
14722
+ reject(new ProcessRunError(spawnErr.message, spawnErr.code ?? null, null, !1, err, !1));
14717
14723
  }), child.on("close", (code, signal) => {
14718
- if (clearTimeout(timer), typeof child.pid == "number" && endGroup(child.pid), timedOut) return reject(new ProcessRunError("timeout", code, signal, !0, err, !0));
14724
+ if (clearTimeout(timer), pid !== null && (live.delete(pid), endGroup(pid)), runner.state === "aborted") return reject(abortedError(code, signal, err));
14725
+ if (timedOut) return reject(new ProcessRunError("timeout", code, signal, !0, err, !0));
14719
14726
  if (overflow) return reject(new ProcessRunError("output-too-large", code, signal, !0, err, !1));
14720
14727
  if (code === 0) return resolve35(Buffer.concat(out).toString("utf8"));
14721
14728
  reject(new ProcessRunError(`exit-${code ?? signal}`, code, signal, !1, err, !1));
@@ -14730,6 +14737,14 @@ function createProcessRunner(deadline, concurrency = 4) {
14730
14737
  } finally {
14731
14738
  release();
14732
14739
  }
14740
+ },
14741
+ abort() {
14742
+ if (runner.state === "aborted") return [];
14743
+ runner = { state: "aborted" };
14744
+ let ended = [...live];
14745
+ for (let pgid of ended) endGroup(pgid);
14746
+ for (let next of waiting.splice(0)) next();
14747
+ return ended;
14733
14748
  }
14734
14749
  };
14735
14750
  }
@@ -14812,13 +14827,19 @@ async function resolve3(runner, deps) {
14812
14827
  }
14813
14828
  return { kind: "available", bin };
14814
14829
  }
14815
- var cached = null;
14830
+ var cached = null, cachedRunner = null;
14816
14831
  function handOffGit(runner, deps = defaultAvailabilityDeps) {
14817
- if (cached) return cached;
14832
+ if (cached)
14833
+ return cachedRunner === runner ? cached : cached.catch(() => handOffGit(runner, deps));
14818
14834
  let attempt = resolveHandOffGit(runner, deps);
14819
- return cached = attempt, attempt.catch(() => {
14820
- cached === attempt && (cached = null);
14821
- }), attempt;
14835
+ return cached = attempt, cachedRunner = runner, attempt.then(
14836
+ () => {
14837
+ cached === attempt && (cachedRunner = null);
14838
+ },
14839
+ () => {
14840
+ cached === attempt && (cached = null, cachedRunner = null);
14841
+ }
14842
+ ), attempt;
14822
14843
  }
14823
14844
 
14824
14845
  // src/orchestration-shell/advisory-fingerprint/repo-record.ts
@@ -15017,20 +15038,27 @@ async function probeAdvisoryWorkspaceFingerprintImpl(workspaceRoot, options = {}
15017
15038
  timer = setTimeout(() => {
15018
15039
  state.expired = !0, resolve35({ kind: "probe-failed", method: state.method, reason: "timeout", durationMs: Date.now() - started });
15019
15040
  }, Math.max(0, timeoutMs));
15020
- });
15041
+ }), runner = createProcessRunner(started + timeoutMs, options.gitConcurrency ?? ADVISORY_GIT_CONCURRENCY), result;
15021
15042
  try {
15022
- return await Promise.race([body(workspaceRoot, started, started + timeoutMs, options, state), deadlineHit]);
15043
+ return result = await Promise.race([body(workspaceRoot, started, started + timeoutMs, options, state, runner), deadlineHit]), result;
15023
15044
  } finally {
15024
15045
  clearTimeout(timer);
15046
+ let ended = runner.abort();
15047
+ ended.length > 0 && logger.warn("[orchestration-shell] advisory fingerprint: ended git process group(s) after the probe stopped", {
15048
+ groups: ended.length,
15049
+ pgids: ended,
15050
+ reason: result?.kind === "probe-failed" ? result.reason : result?.kind ?? "unknown"
15051
+ });
15025
15052
  }
15026
15053
  }
15027
- async function body(workspaceRoot, started, deadline, options, state) {
15054
+ async function body(workspaceRoot, started, deadline, options, state, runner) {
15055
+ let resolvedRoot;
15028
15056
  try {
15029
- await fs13.realpath(workspaceRoot);
15057
+ resolvedRoot = await fs13.realpath(workspaceRoot);
15030
15058
  } catch (err) {
15031
15059
  return { kind: "probe-failed", method: "walk", reason: `root-unreadable:${errnoCode(err)}`, durationMs: Date.now() - started };
15032
15060
  }
15033
- let runner = createProcessRunner(deadline, options.gitConcurrency ?? ADVISORY_GIT_CONCURRENCY), marker = gitEnvSelectsRepository() ? "present" : await gitMarkerState(workspaceRoot);
15061
+ let marker = gitEnvSelectsRepository() ? "present" : await gitMarkerState(workspaceRoot);
15034
15062
  if (marker === "unknown")
15035
15063
  return { kind: "probe-failed", method: "marker", reason: "git-marker-unknown", durationMs: Date.now() - started };
15036
15064
  if (marker === "present") {
@@ -15040,14 +15068,15 @@ async function body(workspaceRoot, started, deadline, options, state) {
15040
15068
  if (repo === "error")
15041
15069
  return { kind: "probe-failed", method: "git", reason: "git-rev-parse-failed", durationMs: Date.now() - started };
15042
15070
  if (repo === "repository") {
15043
- let failedGit = { kind: "probe-failed", method: "git", reason: "git-probe-failed" };
15071
+ let failedGit = { kind: "probe-failed", method: "git", reason: "git-probe-failed" }, top = null;
15044
15072
  try {
15045
- let env = launchGitEnv(), top = (await runner.run("git", [...ADVISORY_GIT_PREFIX, "rev-parse", "--show-toplevel"], { cwd: workspaceRoot, env })).trim();
15046
- if (!top) return { ...failedGit, durationMs: Date.now() - started };
15073
+ let env = launchGitEnv();
15074
+ if (top = (await runner.run("git", [...ADVISORY_GIT_PREFIX, "rev-parse", "--show-toplevel"], { cwd: workspaceRoot, env })).trim() || null, !top) return { ...failedGit, durationMs: Date.now() - started };
15047
15075
  let value = `git:${await launchRecord(top, { runner, git: "git", env, before: null, controlSets: {}, repositories: 0 }, repositoryScrubbedEnv())}`;
15048
15076
  return state.expired || Date.now() > deadline ? { kind: "probe-failed", method: "git", reason: "timeout", durationMs: Date.now() - started } : { kind: "fingerprint", method: "git", value, entries: 1, durationMs: Date.now() - started };
15049
15077
  } catch (err) {
15050
- return err instanceof ProbeFailure ? logRepositoryFailure(workspaceRoot, err) : logRepositoryFailure(workspaceRoot, new ProbeFailure("git-probe-failed", workspaceRoot, failureCategory(err))), { ...failedGit, durationMs: Date.now() - started };
15078
+ let logBase = top ?? resolvedRoot;
15079
+ return err instanceof ProbeFailure ? logRepositoryFailure(logBase, err) : logRepositoryFailure(logBase, new ProbeFailure("git-probe-failed", logBase, failureCategory(err))), { ...failedGit, durationMs: Date.now() - started };
15051
15080
  }
15052
15081
  }
15053
15082
  }
@@ -15066,6 +15095,7 @@ async function walkFolder(workspaceRoot, started, deadline, options, state, runn
15066
15095
  return null;
15067
15096
  }
15068
15097
  if (shared.failure) throw shared.failure;
15098
+ if (expired()) throw new ProbeFailure("timeout", abs, "timeout");
15069
15099
  try {
15070
15100
  let git2 = await handOff();
15071
15101
  if (!git2) return null;
@@ -15108,7 +15138,12 @@ async function walkFolder(workspaceRoot, started, deadline, options, state, runn
15108
15138
  if (st.isDirectory()) {
15109
15139
  let repo = await repoOf(abs);
15110
15140
  if (repo !== null) {
15111
- let line = repo.record.then((value2) => JSON.stringify([rel, "repo", String(st.mode), value2]));
15141
+ let line = repo.record.then(
15142
+ (value2) => JSON.stringify([rel, "repo", String(st.mode), value2]),
15143
+ (err) => {
15144
+ throw err instanceof ProbeFailure ? err : new ProbeFailure("repo-probe-failed", abs, "record-other");
15145
+ }
15146
+ );
15112
15147
  return line.catch(() => {
15113
15148
  }), deferred.push(line), null;
15114
15149
  }
@@ -33549,7 +33584,7 @@ function requestOllamaGenerateStream(config, promptText, opts) {
33549
33584
  reject(err instanceof Error ? err : new Error(String(err)));
33550
33585
  }
33551
33586
  }
33552
- }, guarded = (fn) => {
33587
+ }, guarded2 = (fn) => {
33553
33588
  try {
33554
33589
  fn();
33555
33590
  } catch (err) {
@@ -33617,7 +33652,7 @@ function requestOllamaGenerateStream(config, promptText, opts) {
33617
33652
  res.resume(), finish(() => reject(new Error(`Ollama request failed with HTTP ${status}`)));
33618
33653
  return;
33619
33654
  }
33620
- activeRes = res, ndjson = /x-ndjson/i.test(String(res.headers["content-type"] ?? "")), res.on("error", (err) => finish(() => reject(err))), res.on("data", (chunk) => guarded(() => {
33655
+ activeRes = res, ndjson = /x-ndjson/i.test(String(res.headers["content-type"] ?? "")), res.on("error", (err) => finish(() => reject(err))), res.on("data", (chunk) => guarded2(() => {
33621
33656
  if (settled) return;
33622
33657
  if (responseBytes += chunk.byteLength, responseBytes > MAX_RESPONSE_BYTES) {
33623
33658
  finish(() => reject(new Error("Ollama response exceeded the size limit"))), res.destroy();
@@ -33631,7 +33666,7 @@ function requestOllamaGenerateStream(config, promptText, opts) {
33631
33666
  buffer = buffer.slice(nl + 1), handleLine(line, res), nl = buffer.indexOf(`
33632
33667
  `);
33633
33668
  }
33634
- })), res.on("end", () => guarded(() => {
33669
+ })), res.on("end", () => guarded2(() => {
33635
33670
  if (!settled && (buffer += decoder.end(), handleLine(buffer, res), buffer = "", !settled)) {
33636
33671
  if (!sawDone && (ndjson || chunks !== 1 || lastDone === !1)) {
33637
33672
  finish(
@@ -33732,14 +33767,14 @@ function requestOllamaPull(config, onProgress = () => {
33732
33767
  return;
33733
33768
  }
33734
33769
  res.on("error", (err) => finish(() => reject(err)));
33735
- let guarded = (fn) => {
33770
+ let guarded2 = (fn) => {
33736
33771
  try {
33737
33772
  fn();
33738
33773
  } catch (err) {
33739
33774
  finish(() => reject(err instanceof Error ? err : new Error(String(err))));
33740
33775
  }
33741
33776
  };
33742
- res.on("data", (chunk) => guarded(() => {
33777
+ res.on("data", (chunk) => guarded2(() => {
33743
33778
  if (settled) return;
33744
33779
  resetStall(), buffer += pullDecoder.write(chunk);
33745
33780
  let newlineIndex = buffer.indexOf(`
@@ -33751,7 +33786,7 @@ function requestOllamaPull(config, onProgress = () => {
33751
33786
  `);
33752
33787
  }
33753
33788
  buffer.length > MAX_PULL_LINE_BYTES && (finish(() => reject(new Error("Ollama pull response line exceeded the size limit"))), res.destroy());
33754
- })), res.on("end", () => guarded(() => {
33789
+ })), res.on("end", () => guarded2(() => {
33755
33790
  settled || (buffer += pullDecoder.end(), handleLine(buffer), buffer = "", finish(() => resolve35()));
33756
33791
  }));
33757
33792
  }
@@ -94786,6 +94821,68 @@ function composeBrainstormPanelBrief(input) {
94786
94821
  `));
94787
94822
  }
94788
94823
 
94824
+ // src/orchestration-shell/structural-summary-notices.ts
94825
+ var STRUCTURAL_SUMMARY_TRUNCATED_NOTICE = "This folder is too large to summarize in full \u2014 agents see a partial overview. Start CodeVibe in a smaller folder for a complete one.", STRUCTURAL_SUMMARY_SLOW_NOTICE = "The workspace overview took longer than usual to build.";
94826
+ function structuralSummarySlowEvent(sessionId, elapsedMs) {
94827
+ return {
94828
+ sessionId,
94829
+ type: "NOTIFICATION",
94830
+ source: "DESKTOP",
94831
+ isEncrypted: !0,
94832
+ content: STRUCTURAL_SUMMARY_SLOW_NOTICE,
94833
+ metadata: { event: "structural_summary_slow", elapsedMs: Math.round(elapsedMs) }
94834
+ };
94835
+ }
94836
+ function structuralSummaryTruncatedEvent(sessionId, reason) {
94837
+ return {
94838
+ sessionId,
94839
+ type: "NOTIFICATION",
94840
+ source: "DESKTOP",
94841
+ isEncrypted: !0,
94842
+ content: STRUCTURAL_SUMMARY_TRUNCATED_NOTICE,
94843
+ metadata: { event: "structural_summary_truncated", reason }
94844
+ };
94845
+ }
94846
+
94847
+ // src/orchestration-shell/advisory-fingerprint/panel-baseline.ts
94848
+ init_logger2();
94849
+ var PANEL_BASELINE_COALESCE_MS = 100;
94850
+ function guarded(probe) {
94851
+ let started = Date.now();
94852
+ return Promise.resolve().then(probe).catch(
94853
+ () => ({
94854
+ kind: "probe-failed",
94855
+ method: "marker",
94856
+ reason: "panel-baseline-error",
94857
+ durationMs: Date.now() - started
94858
+ })
94859
+ );
94860
+ }
94861
+ function createPanelBaseline(opts) {
94862
+ let coalesceMs = opts.coalesceMs ?? PANEL_BASELINE_COALESCE_MS, state = { phase: "collecting", arrived: 0, waiters: [], timer: null }, start = () => {
94863
+ if (state.phase !== "collecting") return;
94864
+ let { waiters, timer, arrived } = state;
94865
+ timer && clearTimeout(timer);
94866
+ let startedAt = Date.now(), result = guarded(opts.probe);
94867
+ state = { phase: "started", result }, logger.info("[orchestration-shell] advisory fingerprint: panel baseline started", {
94868
+ cells: opts.expectedCells,
94869
+ arrived
94870
+ });
94871
+ for (let w of waiters)
94872
+ result.then((probe) => w.resolve({ probe, baseline: "shared", waitedMs: Math.max(0, startedAt - w.askedAt) }));
94873
+ };
94874
+ return {
94875
+ take() {
94876
+ if (state.phase === "started")
94877
+ return guarded(opts.probe).then((probe) => ({ probe, baseline: "own", waitedMs: 0 }));
94878
+ let collecting = state;
94879
+ return new Promise((resolve35) => {
94880
+ collecting.waiters.push({ askedAt: Date.now(), resolve: resolve35 }), collecting.arrived += 1, collecting.arrived >= opts.expectedCells ? start() : collecting.timer === null && (collecting.timer = setTimeout(start, coalesceMs));
94881
+ });
94882
+ }
94883
+ };
94884
+ }
94885
+
94789
94886
  // src/orchestration-shell/index.ts
94790
94887
  init_process_markers();
94791
94888
 
@@ -99070,10 +99167,12 @@ async function runReadOnlyAgentAdvisoryResult(args) {
99070
99167
  throw new Error("advisory process retirement has no durable authority");
99071
99168
  let authority = processAuthority;
99072
99169
  await attachmentJournal.retireProcess(authority, owner), processAuthority = null;
99073
- } : void 0, advisoryTaskId = syntheticReadOnlyAdvisoryTaskId(), treeBefore = await probeAdvisoryWorkspaceFingerprint(args.workingDir);
99170
+ } : void 0, advisoryTaskId = syntheticReadOnlyAdvisoryTaskId(), before = args.beforeProbe ? await args.beforeProbe() : { probe: await probeAdvisoryWorkspaceFingerprint(args.workingDir), baseline: "own", waitedMs: 0 }, treeBefore = before.probe;
99074
99171
  if (treeBefore.kind !== "fingerprint")
99075
99172
  return logger.error("[orchestration-shell] workspace fingerprint unavailable before read-only advisory turn \u2014 failing closed", {
99076
99173
  agent: args.agent,
99174
+ baseline: before.baseline,
99175
+ baselineWaitMs: before.waitedMs,
99077
99176
  workingDir: args.workingDir,
99078
99177
  method: treeBefore.method,
99079
99178
  reason: treeBefore.reason,
@@ -99128,7 +99227,9 @@ async function runReadOnlyAgentAdvisoryResult(args) {
99128
99227
  method: treeAfter.method,
99129
99228
  entries: treeAfter.entries,
99130
99229
  beforeMs: treeBefore.durationMs,
99131
- afterMs: treeAfter.durationMs
99230
+ afterMs: treeAfter.durationMs,
99231
+ baseline: before.baseline,
99232
+ baselineWaitMs: before.waitedMs
99132
99233
  });
99133
99234
  let output = await readPlanModeOutput({
99134
99235
  agent: args.agent,
@@ -99310,7 +99411,7 @@ async function routeReadOnlyAgentMention(args) {
99310
99411
  });
99311
99412
  let newlyWalled = /* @__PURE__ */ new Set(), isPanelFanout = isBroadcast || agents.length > 1;
99312
99413
  try {
99313
- let completedCount = 0, cells = await Promise.all(agents.map(async (agent) => {
99414
+ let completedCount = 0, panelBaseline = createPanelBaseline({ expectedCells: agents.length, probe: () => probeAdvisoryWorkspaceFingerprint(workingDir) }), cells = await Promise.all(agents.map(async (agent) => {
99314
99415
  let cellIntent = isBroadcast && args.intent.target !== "ALL" ? { ...args.intent, target: "ALL", rawMention: "@all" } : perAgentFraming && agent !== args.intent.target ? { ...args.intent, target: agent, rawMention: normalizedMentionForTarget(agent) } : args.intent, framingPrefix = perAgentFraming ? `You are being addressed as ${normalizedMentionForTarget(agent)}. Respond to the part(s) of the request directed at you; treat the rest as context.
99315
99416
 
99316
99417
  ` : "", attachmentTail = panelCopied.length > 0 ? `${renderAttachmentsForAgent(agent, panelCopied, workingDir)}
@@ -99328,6 +99429,7 @@ ${READ_ONLY_ADVISORY_ATTACHMENT_SCOPE_LINE}` : "", cellBrief = `${framingPrefix}
99328
99429
  // cell (the old 120s interactive cap killed whole-repo advisories mid-run
99329
99430
  // and left every advisor on the bounded failure label).
99330
99431
  timeoutMs: BRAINSTORM_PANEL_ADVISORY_TIMEOUT_MS,
99432
+ beforeProbe: panelBaseline.take,
99331
99433
  ...panelPrepared?.advisoryCleanupAuthority ? { attachmentBatch: panelPrepared.advisoryCleanupAuthority.batch } : {}
99332
99434
  });
99333
99435
  if (!result.ok) {
@@ -100326,8 +100428,8 @@ async function routeDocumentInspectionAdvisory(deps) {
100326
100428
  text: output
100327
100429
  }), !0;
100328
100430
  } else {
100329
- let failureMessage = "A read-capable model is required to inspect and summarize documents in this workspace. No task was started and no files were modified.";
100330
- return result.usage.unavailableReason === "workspace_mutation_detected" ? failureMessage = "A workspace mutation was detected during document inspection. Please inspect the workspace." : result.usage.unavailableReason === "workspace_verification_unavailable" ? failureMessage = "Workspace integrity could not be verified following document inspection." : result.timedOut && (failureMessage = "Document inspection timed out. No task was started and no files were modified."), store.dispatch({
100431
+ let failureMessage = "A read-capable model is required to inspect and summarize documents in this workspace. No task was started and no files were modified.", verificationText = workspaceVerificationMessage(result.usage.unavailableReason);
100432
+ return verificationText ? failureMessage = verificationText : result.timedOut && (failureMessage = "Document inspection timed out. No task was started and no files were modified."), store.dispatch({
100331
100433
  type: "SHELL_ADVISORY",
100332
100434
  source: "shell",
100333
100435
  text: failureMessage
@@ -103342,24 +103444,12 @@ async function refreshStructuralSummaryIntoStore(deps) {
103342
103444
  "[orchestration-shell] emit STRUCTURAL_SUMMARY_GENERATED failed (non-fatal)",
103343
103445
  { error: err.message }
103344
103446
  );
103345
- }), result.recomputed && (elapsedMs > 2e3 && (emitShellEventBound({
103346
- sessionId: args.session.sessionId,
103347
- type: "NOTIFICATION",
103348
- source: "DESKTOP",
103349
- isEncrypted: !0,
103350
- metadata: { event: "structural_summary_slow", elapsedMs: Math.round(elapsedMs) }
103351
- }).catch(() => {
103447
+ }), result.recomputed && (elapsedMs > 2e3 && (emitShellEventBound(structuralSummarySlowEvent(args.session.sessionId, elapsedMs)).catch(() => {
103352
103448
  }), logger.warn("[orchestration-shell] structural summary slow", {
103353
103449
  elapsedMs: Math.round(elapsedMs)
103354
103450
  })), summary.privacyEnvelope.budgetExceeded)) {
103355
103451
  let reason = summary.privacyEnvelope.budgetReason ?? "fileCount";
103356
- emitShellEventBound({
103357
- sessionId: args.session.sessionId,
103358
- type: "NOTIFICATION",
103359
- source: "DESKTOP",
103360
- isEncrypted: !0,
103361
- metadata: { event: "structural_summary_truncated", reason }
103362
- }).catch(() => {
103452
+ emitShellEventBound(structuralSummaryTruncatedEvent(args.session.sessionId, reason)).catch(() => {
103363
103453
  }), logger.warn("[orchestration-shell] structural summary truncated", { reason });
103364
103454
  }
103365
103455
  return result;
@@ -103394,30 +103484,12 @@ async function runStructuralSummarySessionStart(deps) {
103394
103484
  "[orchestration-shell] emit STRUCTURAL_SUMMARY_GENERATED failed (non-fatal)",
103395
103485
  { error: err.message }
103396
103486
  );
103397
- }), elapsedMs > 2e3 && (emitShellEventBound({
103398
- sessionId: args.session.sessionId,
103399
- type: "NOTIFICATION",
103400
- source: "DESKTOP",
103401
- isEncrypted: !0,
103402
- metadata: {
103403
- event: "structural_summary_slow",
103404
- elapsedMs: Math.round(elapsedMs)
103405
- }
103406
- }).catch(() => {
103487
+ }), elapsedMs > 2e3 && (emitShellEventBound(structuralSummarySlowEvent(args.session.sessionId, elapsedMs)).catch(() => {
103407
103488
  }), logger.warn("[orchestration-shell] structural summary slow", {
103408
103489
  elapsedMs: Math.round(elapsedMs)
103409
103490
  })), summary.privacyEnvelope.budgetExceeded) {
103410
103491
  let reason = summary.privacyEnvelope.budgetReason ?? "fileCount";
103411
- emitShellEventBound({
103412
- sessionId: args.session.sessionId,
103413
- type: "NOTIFICATION",
103414
- source: "DESKTOP",
103415
- isEncrypted: !0,
103416
- metadata: {
103417
- event: "structural_summary_truncated",
103418
- reason
103419
- }
103420
- }).catch(() => {
103492
+ emitShellEventBound(structuralSummaryTruncatedEvent(args.session.sessionId, reason)).catch(() => {
103421
103493
  }), logger.warn("[orchestration-shell] structural summary truncated", {
103422
103494
  reason
103423
103495
  });
@@ -0,0 +1,7 @@
1
+ import type { ShellEventEmit } from './emit-shell-event';
2
+ export declare const STRUCTURAL_SUMMARY_TRUNCATED_NOTICE = "This folder is too large to summarize in full \u2014 agents see a partial overview. Start CodeVibe in a smaller folder for a complete one.";
3
+ export declare const STRUCTURAL_SUMMARY_SLOW_NOTICE = "The workspace overview took longer than usual to build.";
4
+ /** §4.7 slow-path audit: the summary walk took longer than its threshold. */
5
+ export declare function structuralSummarySlowEvent(sessionId: string, elapsedMs: number): ShellEventEmit;
6
+ /** The summary hit its privacy budget; `reason` is the dominant cause (file count before body bytes). */
7
+ export declare function structuralSummaryTruncatedEvent(sessionId: string, reason: string): ShellEventEmit;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-core",
3
- "version": "2.0.97",
3
+ "version": "2.0.98",
4
4
  "description": "Core library for CodeVibe plugins - shared keychain, crypto, AppSync, and auth functionality",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-codex-plugin",
3
- "version": "2.0.113",
3
+ "version": "2.0.114",
4
4
  "description": "Control OpenAI Codex CLI from your iPhone and Android — real-time sync, approve file edits, send prompts by voice. Part of CodeVibe.",
5
5
  "main": "dist/server.js",
6
6
  "codevibe": {
@@ -47,7 +47,7 @@
47
47
  "node": ">=22.0.0"
48
48
  },
49
49
  "dependencies": {
50
- "@quantiya/codevibe-core": "^2.0.97",
50
+ "@quantiya/codevibe-core": "^2.0.98",
51
51
  "@quantiya/quorum-core": "^1.0.1",
52
52
  "chokidar": "^4.0.0",
53
53
  "dotenv": "^16.6.1",