@rallycry/conveyor-agent 10.7.1 → 10.7.3

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.
@@ -1937,6 +1937,7 @@ async function restoreOnBoot(bundle, cwd) {
1937
1937
  import { z } from "zod";
1938
1938
  import { z as z2 } from "zod";
1939
1939
  var DEFAULT_SONNET_MODEL = "claude-sonnet-5";
1940
+ var FABLE_MODEL = "claude-fable-5";
1940
1941
  var TUI_KINDS = ["claude-code", "opencode"];
1941
1942
  var MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024;
1942
1943
  var EMBED_THRESHOLD_IMAGES = 5 * 1024 * 1024;
@@ -2502,7 +2503,7 @@ var ListMyLiveSessionsRequestSchema = z2.object({
2502
2503
  /** Admin-only: list another member's sessions instead of the caller's. */
2503
2504
  targetUserId: z2.string().optional()
2504
2505
  });
2505
- var ListActiveSessionUsersRequestSchema = z2.object({
2506
+ var ListProjectSessionGroupsRequestSchema = z2.object({
2506
2507
  projectId: z2.string()
2507
2508
  });
2508
2509
  var GetProjectAvailableTuisRequestSchema = z2.object({
@@ -4239,7 +4240,50 @@ function seedWorkspaceTrust(config, trustCwd) {
4239
4240
  config.projects = projects;
4240
4241
  return true;
4241
4242
  }
4242
- function planClaudeJsonSeed(existingRaw, trustCwd) {
4243
+ var FABLE_MODEL_OPTION = {
4244
+ value: `${FABLE_MODEL}[1m]`,
4245
+ label: "Fable",
4246
+ description: "Fable 5 - most capable for your hardest and longest-running tasks"
4247
+ };
4248
+ function seedFableModelOption(config) {
4249
+ const cache = Array.isArray(config.additionalModelOptionsCache) ? config.additionalModelOptionsCache : [];
4250
+ const hasFable = cache.some((entry) => {
4251
+ if (typeof entry !== "object" || entry === null) return false;
4252
+ const value = entry.value;
4253
+ return typeof value === "string" && value.toLowerCase().includes("fable");
4254
+ });
4255
+ if (hasFable) return false;
4256
+ config.additionalModelOptionsCache = [...cache, { ...FABLE_MODEL_OPTION }];
4257
+ return true;
4258
+ }
4259
+ function normalizeOauthIdentity(record) {
4260
+ const organizationUuid = typeof record.organizationUuid === "string" && record.organizationUuid !== "" ? record.organizationUuid : void 0;
4261
+ const accountUuid = typeof record.accountUuid === "string" && record.accountUuid !== "" ? record.accountUuid : void 0;
4262
+ if (!organizationUuid && !accountUuid) return null;
4263
+ return { organizationUuid, accountUuid };
4264
+ }
4265
+ function extractOauthIdentity(config) {
4266
+ return normalizeOauthIdentity(asRecord(config.oauthAccount));
4267
+ }
4268
+ function seedFableConsent(config, fallbackIdentity) {
4269
+ const identity = extractOauthIdentity(config) ?? fallbackIdentity;
4270
+ if (!identity) return false;
4271
+ const consent = asRecord(config.fableOverageConsentV2);
4272
+ let changed = false;
4273
+ const keys = [
4274
+ ...identity.organizationUuid ? [identity.organizationUuid] : [],
4275
+ ...identity.accountUuid ? [`acct:${identity.accountUuid}`] : []
4276
+ ];
4277
+ for (const key of keys) {
4278
+ if (consent[key] !== true) {
4279
+ consent[key] = true;
4280
+ changed = true;
4281
+ }
4282
+ }
4283
+ if (changed) config.fableOverageConsentV2 = consent;
4284
+ return changed;
4285
+ }
4286
+ function planClaudeJsonSeed(existingRaw, trustCwd, oauthIdentity) {
4243
4287
  const config = parseClaudeJson(existingRaw);
4244
4288
  const isFresh = Object.keys(config).length === 0;
4245
4289
  let changed = false;
@@ -4258,13 +4302,56 @@ function planClaudeJsonSeed(existingRaw, trustCwd) {
4258
4302
  if (trustCwd && seedWorkspaceTrust(config, trustCwd)) {
4259
4303
  changed = true;
4260
4304
  }
4305
+ if (seedFableModelOption(config)) {
4306
+ changed = true;
4307
+ }
4308
+ if (seedFableConsent(config, oauthIdentity ?? null)) {
4309
+ changed = true;
4310
+ }
4261
4311
  return changed ? JSON.stringify(config) : null;
4262
4312
  }
4313
+ function conveyorOauthMarkerPath() {
4314
+ return join3(claudeConfigHome(), "conveyor-oauth-account.json");
4315
+ }
4316
+ function parseOauthIdentity(raw) {
4317
+ if (!raw || raw.trim() === "") return null;
4318
+ try {
4319
+ return normalizeOauthIdentity(asRecord(JSON.parse(raw)));
4320
+ } catch {
4321
+ return null;
4322
+ }
4323
+ }
4324
+ async function persistOauthIdentityMarker(configIdentity, markerIdentity) {
4325
+ try {
4326
+ if (!configIdentity) return;
4327
+ if (markerIdentity !== null && markerIdentity.organizationUuid === configIdentity.organizationUuid && markerIdentity.accountUuid === configIdentity.accountUuid) {
4328
+ return;
4329
+ }
4330
+ await mkdir2(claudeConfigHome(), { recursive: true });
4331
+ const verified = await writeWithReadBackRetry(
4332
+ fsWriteIo(conveyorOauthMarkerPath()),
4333
+ JSON.stringify(configIdentity)
4334
+ );
4335
+ if (verified) {
4336
+ process.stderr.write("[conveyor-agent] persisted oauth identity marker for fable consent\n");
4337
+ }
4338
+ } catch (err) {
4339
+ const message = err instanceof Error ? err.message : String(err);
4340
+ process.stderr.write(`[conveyor-agent] oauth identity marker write failed: ${message}
4341
+ `);
4342
+ }
4343
+ }
4263
4344
  async function ensureClaudeOnboarding(env = process.env, trustCwd) {
4264
4345
  try {
4265
4346
  if (!isConveyorCloudEnv(env)) return;
4266
4347
  const path4 = claudeJsonPath();
4267
- const contents = planClaudeJsonSeed(await readRaw(path4), trustCwd);
4348
+ const existingRaw = await readRaw(path4);
4349
+ const markerIdentity = parseOauthIdentity(await readRaw(conveyorOauthMarkerPath()));
4350
+ await persistOauthIdentityMarker(
4351
+ extractOauthIdentity(parseClaudeJson(existingRaw)),
4352
+ markerIdentity
4353
+ );
4354
+ const contents = planClaudeJsonSeed(existingRaw, trustCwd, markerIdentity);
4268
4355
  if (contents === null) return;
4269
4356
  const verified = await writeWithReadBackRetry(fsWriteIo(path4), contents);
4270
4357
  if (verified) {
@@ -5521,6 +5608,8 @@ function formatIncidents(incidents) {
5521
5608
  // src/execution/tag-context-resolver.ts
5522
5609
  import { readFile as readFile2, readdir, stat as stat4 } from "fs/promises";
5523
5610
  var TYPE_PRIORITY = { rule: 0, file: 1, folder: 2, doc: 3 };
5611
+ var SUMMARY_SCAN_CHARS = 4e3;
5612
+ var SUMMARY_MAX_CHARS = 160;
5524
5613
  var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
5525
5614
  ".png",
5526
5615
  ".jpg",
@@ -5554,19 +5643,41 @@ function isBinaryPath(filePath) {
5554
5643
  const ext = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
5555
5644
  return BINARY_EXTENSIONS.has(ext);
5556
5645
  }
5557
- var fileContentCache = /* @__PURE__ */ new Map();
5646
+ var fileSummaryCache = /* @__PURE__ */ new Map();
5558
5647
  var folderListingCache = /* @__PURE__ */ new Map();
5559
5648
  var fileReadCount = 0;
5560
5649
  var folderReadCount = 0;
5561
- function getContextBudgetChars(_model, betas, runnerMode) {
5562
- const contextWindow = betas?.some((b) => b.includes("context-1m")) ? 1e6 : 2e5;
5563
- const budgetPct = runnerMode === "task" ? 0.15 : 0.25;
5564
- return contextWindow * budgetPct * 4;
5650
+ function deriveSummary(raw) {
5651
+ let body = raw;
5652
+ let frontmatter = "";
5653
+ if (raw.startsWith("---")) {
5654
+ const end = raw.indexOf("\n---", 3);
5655
+ if (end !== -1) {
5656
+ frontmatter = raw.slice(3, end);
5657
+ const afterClose = raw.indexOf("\n", end + 1);
5658
+ body = afterClose === -1 ? "" : raw.slice(afterClose + 1);
5659
+ }
5660
+ }
5661
+ const fmDescription = frontmatter.split("\n").map((l) => l.trim()).find((l) => /^(description|title):/i.test(l));
5662
+ if (fmDescription) {
5663
+ const value = fmDescription.slice(fmDescription.indexOf(":") + 1).trim().replace(/^["']|["']$/g, "");
5664
+ if (value) return truncateSummary(value);
5665
+ }
5666
+ for (const rawLine of body.split("\n")) {
5667
+ const line = rawLine.trim();
5668
+ if (!line) continue;
5669
+ const cleaned = line.replace(/^#+\s*/, "").replace(/^[-*]\s+/, "").trim();
5670
+ if (cleaned) return truncateSummary(cleaned);
5671
+ }
5672
+ return null;
5673
+ }
5674
+ function truncateSummary(text) {
5675
+ const collapsed = text.replace(/\s+/g, " ").trim();
5676
+ return collapsed.length > SUMMARY_MAX_CHARS ? collapsed.slice(0, SUMMARY_MAX_CHARS - 1).trimEnd() + "\u2026" : collapsed;
5565
5677
  }
5566
- async function readFileContent(filePath, maxChars) {
5678
+ async function readFileSummary(filePath) {
5567
5679
  try {
5568
5680
  if (isBinaryPath(filePath)) return null;
5569
- let rawContent;
5570
5681
  let mtimeMs;
5571
5682
  try {
5572
5683
  const st = await stat4(filePath);
@@ -5574,20 +5685,15 @@ async function readFileContent(filePath, maxChars) {
5574
5685
  } catch {
5575
5686
  return null;
5576
5687
  }
5577
- const cached = fileContentCache.get(filePath);
5688
+ const cached = fileSummaryCache.get(filePath);
5578
5689
  if (cached && cached.mtimeMs === mtimeMs) {
5579
- rawContent = cached.content;
5580
- } else {
5581
- rawContent = await readFile2(filePath, "utf-8");
5582
- fileReadCount++;
5583
- fileContentCache.set(filePath, { mtimeMs, content: rawContent });
5690
+ return cached.summary;
5584
5691
  }
5585
- if (rawContent.length > maxChars) {
5586
- const omitted = rawContent.length - maxChars;
5587
- return rawContent.slice(0, maxChars) + `
5588
- [... truncated, ${omitted} chars omitted]`;
5589
- }
5590
- return rawContent;
5692
+ const raw = await readFile2(filePath, "utf-8");
5693
+ fileReadCount++;
5694
+ const summary = deriveSummary(raw.slice(0, SUMMARY_SCAN_CHARS));
5695
+ fileSummaryCache.set(filePath, { mtimeMs, summary });
5696
+ return summary;
5591
5697
  } catch {
5592
5698
  return null;
5593
5699
  }
@@ -5614,76 +5720,49 @@ async function readFolderListing(folderPath) {
5614
5720
  return null;
5615
5721
  }
5616
5722
  }
5617
- async function resolveEntry(entry, budget) {
5723
+ async function resolveEntry(entry) {
5618
5724
  const result = {
5619
5725
  type: entry.type,
5620
5726
  path: entry.path,
5621
5727
  label: entry.label,
5622
- content: null,
5623
- charCount: 0
5728
+ summary: null
5624
5729
  };
5625
- if (budget.remaining <= 0) return result;
5730
+ if (entry.label) {
5731
+ result.summary = truncateSummary(entry.label);
5732
+ return result;
5733
+ }
5626
5734
  if (entry.type === "doc") {
5627
5735
  return result;
5628
5736
  }
5629
5737
  if (entry.type === "folder") {
5630
- const listing = await readFolderListing(entry.path);
5631
- if (listing) {
5632
- result.content = listing;
5633
- result.charCount = listing.length;
5634
- budget.remaining -= listing.length;
5635
- }
5738
+ result.summary = await readFolderListing(entry.path);
5636
5739
  return result;
5637
5740
  }
5638
- const maxChars = Math.floor(budget.remaining * 0.5) || budget.remaining;
5639
- const content = await readFileContent(entry.path, maxChars);
5640
- if (content) {
5641
- result.content = content;
5642
- result.charCount = content.length;
5643
- budget.remaining -= content.length;
5644
- }
5741
+ result.summary = await readFileSummary(entry.path);
5645
5742
  return result;
5646
5743
  }
5647
5744
  function formatEntry(entry) {
5648
- const label = entry.label ? ` (${entry.label})` : "";
5649
- const header = `#### ${entry.path}${label} (${entry.type})`;
5650
- if (entry.content === null) {
5651
- return `> ${entry.type}: ${entry.path}${label}`;
5652
- }
5653
- if (entry.type === "folder") {
5654
- return `${header}
5655
- ${entry.content}`;
5656
- }
5657
- return `${header}
5658
- \`\`\`
5659
- ${entry.content}
5660
- \`\`\``;
5745
+ const suffix = entry.summary ? ` \u2014 ${entry.summary}` : "";
5746
+ return `- \`${entry.path}\`${suffix}`;
5661
5747
  }
5662
5748
  function formatResolvedTags(resolved) {
5663
- const parts = [`
5664
- ## Tag Context`];
5749
+ const parts = [
5750
+ `
5751
+ ## Reference Guides (load on demand)`,
5752
+ `These docs match this task's tags. They auto-load when you edit matching files, and you can Read any of them the moment you need its detail \u2014 do NOT read them all up front.`
5753
+ ];
5665
5754
  for (const tag of resolved) {
5666
5755
  if (tag.entries.length === 0) continue;
5667
5756
  const desc = tag.description ? ` \u2014 ${tag.description}` : "";
5668
5757
  parts.push(`
5669
5758
  ### Tag: "${tag.tagName}"${desc}`);
5670
- const contentEntries = tag.entries.filter((e) => e.content !== null);
5671
- const pointerEntries = tag.entries.filter((e) => e.content === null);
5672
- for (const entry of contentEntries) {
5673
- parts.push(`
5674
- ${formatEntry(entry)}`);
5675
- }
5676
- if (pointerEntries.length > 0) {
5677
- parts.push(``);
5678
- parts.push(`> Budget limit reached. Remaining linked files (read manually if needed):`);
5679
- for (const entry of pointerEntries) {
5680
- parts.push(formatEntry(entry));
5681
- }
5759
+ for (const entry of tag.entries) {
5760
+ parts.push(formatEntry(entry));
5682
5761
  }
5683
5762
  }
5684
5763
  return parts.join("\n");
5685
5764
  }
5686
- async function resolveTagContext(projectTags, taskTagIds, model, betas, runnerMode) {
5765
+ async function resolveTagContext(projectTags, taskTagIds, _model, _betas, _runnerMode) {
5687
5766
  if (!projectTags?.length || !taskTagIds.length) {
5688
5767
  return { injectedSection: "", stats: { injected: 0, skipped: 0 } };
5689
5768
  }
@@ -5706,8 +5785,6 @@ async function resolveTagContext(projectTags, taskTagIds, model, betas, runnerMo
5706
5785
  if (allEntries.length === 0) {
5707
5786
  return { injectedSection: "", stats: { injected: 0, skipped: 0 } };
5708
5787
  }
5709
- const budgetChars = getContextBudgetChars(model, betas, runnerMode);
5710
- const budget = { remaining: budgetChars };
5711
5788
  let injected = 0;
5712
5789
  let skipped = 0;
5713
5790
  const resolved = assignedTags.map((t) => ({
@@ -5716,9 +5793,9 @@ async function resolveTagContext(projectTags, taskTagIds, model, betas, runnerMo
5716
5793
  entries: []
5717
5794
  }));
5718
5795
  for (const { tagIndex, entry } of allEntries) {
5719
- const result = await resolveEntry(entry, budget);
5796
+ const result = await resolveEntry(entry);
5720
5797
  resolved[tagIndex].entries.push(result);
5721
- if (result.content === null) {
5798
+ if (result.summary === null) {
5722
5799
  skipped++;
5723
5800
  } else {
5724
5801
  injected++;
@@ -11008,4 +11085,4 @@ export {
11008
11085
  runStartCommand,
11009
11086
  unshallowRepo
11010
11087
  };
11011
- //# sourceMappingURL=chunk-EBZRRNO5.js.map
11088
+ //# sourceMappingURL=chunk-UOHROQ6A.js.map