@lore-co/cli 0.2.18 → 0.2.20

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/dist/runtime.js CHANGED
@@ -21,7 +21,7 @@ import { CONTEXT_CACHE_MAX_STALE_MS, isContextTransportFailure, selectCachedCont
21
21
  import { RUNTIME_VERSION } from "./runtime-version.js";
22
22
  import { checkLoreAccess, checkDirectory, checkWorkspaceRepository, readLocalConfig, resolveLocalConnection, bindLocalSession } from "./directory-policy.js";
23
23
  import { capturePendingImages, enqueueEventImages, flushImageAttachment, hostMessageImages, rememberImageCapture } from "./image-capture.js";
24
- import { guardRuleConflict, guardToolTrigger, supportedGuardRule, guardEmergencyCommand, emergencyOverrideApplies } from "@lore-co/core/guard-evaluation";
24
+ import { guardRepositoryOverride, guardRuleConflict, guardToolTrigger, supportedGuardRule, guardEmergencyCommand, emergencyOverrideApplies } from "@lore-co/core/guard-evaluation";
25
25
  const IS_STANDALONE_RUNTIME = typeof __LORE_STANDALONE__ === "boolean" && __LORE_STANDALONE__;
26
26
  export const COMMAND_HOOK_AGENT_NAMES = [
27
27
  "codex",
@@ -1548,10 +1548,12 @@ function queuedRequest(value) {
1548
1548
  }
1549
1549
  return null;
1550
1550
  }
1551
- async function flushOne(config, fetchImplementation, store) {
1551
+ async function flushOne(config, fetchImplementation, store, preferredIdempotencyKey) {
1552
1552
  const claimed = await store.claimNext({
1553
1553
  workerId: `native-hook:${process.pid}`,
1554
1554
  kinds: ["turn", "prompt", "guard_override"],
1555
+ skipDeferred: true,
1556
+ ...(preferredIdempotencyKey === undefined ? {} : { preferredIdempotencyKey }),
1555
1557
  eligible: async (entry) => entry.kind === "guard_override" || (await checkWorkspaceRepository(config, queuedRequest(entry.payload)?.request.scope?.repo, fetchImplementation)).allowed,
1556
1558
  });
1557
1559
  if (claimed === null || claimed.claim === undefined) {
@@ -1586,12 +1588,18 @@ async function flushOne(config, fetchImplementation, store) {
1586
1588
  const permission = await checkWorkspaceRepository(config, queued.request.scope?.repo, fetchImplementation);
1587
1589
  if (!permission.allowed)
1588
1590
  throw Object.assign(new Error(permission.reason), { retryable: true });
1591
+ // A persisted capture can already be committed while response enrichment
1592
+ // exceeds the live request budget. Give retries a bounded longer window
1593
+ // to receive the acknowledgement instead of timing out forever.
1594
+ const replayConfig = claimed.retry.attempts > 0
1595
+ ? { ...config, timeoutMs: Math.min(10_000, (config.timeoutMs ?? 2_500) * 2 ** Math.min(claimed.retry.attempts, 2)) }
1596
+ : config;
1589
1597
  let delivery;
1590
1598
  if (queued.kind === "turn") {
1591
- delivery = await postTurn(config, queued.request, fetchImplementation, store);
1599
+ delivery = await postTurn(replayConfig, queued.request, fetchImplementation, store);
1592
1600
  }
1593
1601
  else {
1594
- await postPromptObservation(config, queued.request, fetchImplementation, store);
1602
+ await postPromptObservation(replayConfig, queued.request, fetchImplementation, store);
1595
1603
  }
1596
1604
  await store.acknowledgeClaim(claimed.claim.id);
1597
1605
  return {
@@ -1877,7 +1885,7 @@ async function offlineGuard(config, store, request, now, previouslyEnforced, all
1877
1885
  return { offline: true, mode: "enforce", requiresConfirmation: false, items: [], conflictSummaries: ["An audited, time-limited emergency override is active for this session and repository."] };
1878
1886
  }
1879
1887
  const overrides = isObject(remembered) && Array.isArray(remembered.overrides) ? remembered.overrides : [];
1880
- const override = overrides.find((item) => isObject(item) && item.repo === request.repo);
1888
+ const override = guardRepositoryOverride(overrides, request.repo);
1881
1889
  const knownEnforce = previouslyEnforced || (isObject(override) ? override.mode : isObject(remembered) ? remembered.mode : undefined) === "enforce";
1882
1890
  try {
1883
1891
  if (!allowCachedPolicy)
@@ -1889,7 +1897,7 @@ async function offlineGuard(config, store, request, now, previouslyEnforced, all
1889
1897
  const payload = verifySignedSnapshot(compactJws, {
1890
1898
  workspaceId: store.workspaceId, keys, kind: "guard_policy", now,
1891
1899
  }).payload;
1892
- const cachedOverride = Array.isArray(payload.overrides) ? payload.overrides.find((item) => isObject(item) && item.repo === request.repo) : undefined;
1900
+ const cachedOverride = guardRepositoryOverride(payload.overrides, request.repo);
1893
1901
  const mode = isObject(cachedOverride) ? cachedOverride.mode : payload.mode;
1894
1902
  if (isObject(remembered) && remembered.policyVersion !== payload.policyVersion)
1895
1903
  throw new Error("Policy has changed");
@@ -2121,7 +2129,7 @@ export async function handleHookEvent(value, agent, options = {}) {
2121
2129
  const saved = await runtimeStore(config, options.home).then(store => store.readState("guard-policy-state")).catch(() => null);
2122
2130
  // Use the same scope as live Guard: non-Git folders have no repo override.
2123
2131
  const scope = await repositoryScope(stringField(input.cwd)).catch(() => undefined);
2124
- const override = isObject(saved) && Array.isArray(saved.overrides) ? saved.overrides.find(value => isObject(value) && value.repo === scope?.repo) : undefined;
2132
+ const override = guardRepositoryOverride(isObject(saved) ? saved.overrides : undefined, scope?.repo);
2125
2133
  if (prior?.mode === "enforce" || (isObject(override) ? override.mode : isObject(saved) ? saved.mode : undefined) === "enforce") {
2126
2134
  const reason = "Lore cannot verify workspace repository settings. Restore the connection before retrying.";
2127
2135
  if (agent === "cursor")
@@ -2180,7 +2188,7 @@ export async function handleHookEvent(value, agent, options = {}) {
2180
2188
  const prior = await readGuardState(agent, sessionId, options.home, config.connectionId).catch(() => null);
2181
2189
  const saved = await runtimeStore(config, options.home).then((store) => store.readState("guard-policy-state")).catch(() => null);
2182
2190
  const scope = await repositoryScope(stringField(input.cwd)).catch(() => undefined);
2183
- const override = isObject(saved) && Array.isArray(saved.overrides) ? saved.overrides.find((entry) => isObject(entry) && entry.repo === scope?.repo) : undefined;
2191
+ const override = guardRepositoryOverride(isObject(saved) ? saved.overrides : undefined, scope?.repo);
2184
2192
  if (prior?.mode === "enforce" || (isObject(override) ? override.mode : isObject(saved) ? saved.mode : undefined) === "enforce") {
2185
2193
  const reason = "Lore Guard cannot verify its enforcement policy. Restore Lore before retrying.";
2186
2194
  if (agent === "cursor")
@@ -2313,8 +2321,7 @@ async function handlePromptEvent(input, agent, sessionId, config, options, now,
2313
2321
  try {
2314
2322
  const flushed = await flushOne(config, fetchImplementation, store);
2315
2323
  noticeForFlush(flushed);
2316
- // A retained terminal failure still occupies capacity. Give the next item
2317
- // one upload attempt before enqueueing, including when the queue was full.
2324
+ // Give the next item one upload attempt after a permanent failure.
2318
2325
  if (flushed?.state === "dead")
2319
2326
  noticeForFlush(await flushOne(config, fetchImplementation, store));
2320
2327
  }
@@ -2382,7 +2389,7 @@ async function handlePromptEvent(input, agent, sessionId, config, options, now,
2382
2389
  }
2383
2390
  if (enqueued) {
2384
2391
  try {
2385
- const flushed = await flushOne(config, fetchImplementation, store);
2392
+ const flushed = await flushOne(config, fetchImplementation, store, request.eventId);
2386
2393
  noticeForFlush(flushed);
2387
2394
  if (flushed?.idempotencyKey === request.eventId &&
2388
2395
  flushed.state === "acknowledged" &&
@@ -2456,7 +2463,7 @@ async function handlePromptEvent(input, agent, sessionId, config, options, now,
2456
2463
  }
2457
2464
  if (enqueued) {
2458
2465
  try {
2459
- const flushed = await flushOne(config, fetchImplementation, store);
2466
+ const flushed = await flushOne(config, fetchImplementation, store, observation.eventId);
2460
2467
  noticeForFlush(flushed);
2461
2468
  if (!terminal(flushed, observation.eventId) &&
2462
2469
  (flushed?.idempotencyKey !== observation.eventId || flushed.state !== "acknowledged")) {