@jun133/kitty 0.0.11 → 0.0.12

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/cli.js CHANGED
@@ -40,7 +40,7 @@ var init_package = __esm({
40
40
  "package.json"() {
41
41
  package_default = {
42
42
  name: "@jun133/kitty",
43
- version: "0.0.11",
43
+ version: "0.0.12",
44
44
  description: "Agent",
45
45
  license: "MIT",
46
46
  keywords: [
@@ -9939,6 +9939,7 @@ function buildRuntimeScene(status) {
9939
9939
  nextAction: readNextAction(status, blockedExecutions, watchExecutions),
9940
9940
  blocked: readBlocked(blockedExecutions),
9941
9941
  cost: readCost(status),
9942
+ toolOutputs: readToolOutputs(status),
9942
9943
  recovery: readRecovery(status, executions),
9943
9944
  skills: {
9944
9945
  ready: status.skills.ready,
@@ -10025,6 +10026,23 @@ function readCost(status) {
10025
10026
  const usageText = latest?.usage ? readUsageCost(latest.usage) : latest ? "provider usage unavailable" : "no model request yet";
10026
10027
  return `${budgetText}; ${layoutText}; ${usageText}`;
10027
10028
  }
10029
+ function readToolOutputs(status) {
10030
+ const recent = status.toolOutputs.recent;
10031
+ if (recent.length === 0) {
10032
+ return "no tool output governance yet";
10033
+ }
10034
+ const saved = recent.reduce((total, item) => total + (item.savedTokens ?? 0), 0);
10035
+ const truncated = recent.filter((item) => item.truncated).length;
10036
+ const degraded = recent.filter((item) => item.degraded).length;
10037
+ const best = recent.filter((item) => typeof item.savedTokens === "number").sort((a, b) => (b.savedTokens ?? 0) - (a.savedTokens ?? 0))[0];
10038
+ return [
10039
+ `${recent.length} recent`,
10040
+ `${saved} tokens saved est.`,
10041
+ truncated > 0 ? `${truncated} recoverable` : void 0,
10042
+ degraded > 0 ? `${degraded} degraded` : void 0,
10043
+ best ? `top=${best.toolName ?? "tool"}:${best.kind ?? "output"}` : void 0
10044
+ ].filter(Boolean).join("; ");
10045
+ }
10028
10046
  function readStableRatio(stableChars, volatileChars) {
10029
10047
  const total = stableChars + volatileChars;
10030
10048
  return total > 0 ? `${Math.round(stableChars / total * 100)}%` : "unknown";
@@ -10152,13 +10170,14 @@ async function buildRuntimeStatus(rootDir) {
10152
10170
  const sessionStore = new SessionStore(paths.sessionsDir, {
10153
10171
  memorySessionsDir: paths.sessionMemoryDir
10154
10172
  });
10155
- const [sessionRead, memoryAssets, control, projectMap, projectContext, modelRequests] = await Promise.all([
10173
+ const [sessionRead, memoryAssets, control, projectMap, projectContext, modelRequests, toolOutputs] = await Promise.all([
10156
10174
  sessionStore.listReadable?.(DEFAULT_RECENT_LIMIT) ?? sessionStore.list(DEFAULT_RECENT_LIMIT).then((sessions2) => ({ sessions: sessions2, skipped: [] })),
10157
10175
  listRuntimeMemoryAssets(paths.rootDir),
10158
10176
  readControlPlaneStatus(paths.rootDir),
10159
10177
  buildProjectMap(paths.rootDir),
10160
10178
  loadProjectContext(paths.rootDir, { projectDocMaxBytes: 24576 }),
10161
- readRecentModelRequests(paths.observabilityEventsDir)
10179
+ readRecentModelRequests(paths.observabilityEventsDir),
10180
+ readRecentToolOutputs(paths.observabilityEventsDir)
10162
10181
  ]);
10163
10182
  const sessions = sessionRead.sessions.map(summarizeSession);
10164
10183
  const taskLifecycle = sessions[0] ? readTaskLifecycleStatus(paths.rootDir, sessions[0].id) : void 0;
@@ -10179,6 +10198,9 @@ async function buildRuntimeStatus(rootDir) {
10179
10198
  modelRequests: {
10180
10199
  recent: modelRequests
10181
10200
  },
10201
+ toolOutputs: {
10202
+ recent: toolOutputs
10203
+ },
10182
10204
  taskLifecycle,
10183
10205
  executions: control.executions,
10184
10206
  wakeSignals: control.wakeSignals
@@ -10253,6 +10275,25 @@ async function readRecentModelRequests(eventsDir) {
10253
10275
  }
10254
10276
  return records.slice(-DEFAULT_RECENT_LIMIT).reverse();
10255
10277
  }
10278
+ async function readRecentToolOutputs(eventsDir) {
10279
+ const files = await import_promises24.default.readdir(eventsDir).catch(() => []);
10280
+ const jsonlFiles = files.filter((file) => file.endsWith(".jsonl")).sort().slice(-3);
10281
+ const records = [];
10282
+ for (const file of jsonlFiles) {
10283
+ const content = await import_promises24.default.readFile(import_node_path37.default.join(eventsDir, file), "utf8").catch(() => "");
10284
+ for (const line of content.split(/\r?\n/)) {
10285
+ if (!line.trim()) {
10286
+ continue;
10287
+ }
10288
+ const record = parseObservabilityRecord(line);
10289
+ if (!record || record.event !== "tool.output") {
10290
+ continue;
10291
+ }
10292
+ records.push(summarizeToolOutput(record));
10293
+ }
10294
+ }
10295
+ return records.slice(-DEFAULT_RECENT_LIMIT).reverse();
10296
+ }
10256
10297
  function parseObservabilityRecord(line) {
10257
10298
  try {
10258
10299
  const parsed = JSON.parse(line);
@@ -10273,6 +10314,25 @@ function summarizeModelRequest(record) {
10273
10314
  usage
10274
10315
  };
10275
10316
  }
10317
+ function summarizeToolOutput(record) {
10318
+ const details = record.details ?? {};
10319
+ return {
10320
+ timestamp: record.timestamp,
10321
+ toolName: record.toolName,
10322
+ kind: readString4(details.kind),
10323
+ mode: readString4(details.mode),
10324
+ rawChars: readNumber(details.rawChars),
10325
+ projectedChars: readNumber(details.projectedChars),
10326
+ rawTokens: readNumber(details.rawTokens),
10327
+ projectedTokens: readNumber(details.projectedTokens),
10328
+ savedTokens: readNumber(details.savedTokens),
10329
+ savingsRatio: readNumber(details.savingsRatio),
10330
+ truncated: details.truncated === true,
10331
+ outputPath: readString4(details.outputPath),
10332
+ degraded: details.degraded === true,
10333
+ reason: readString4(details.reason)
10334
+ };
10335
+ }
10276
10336
  function readUsageSummary(value) {
10277
10337
  if (!value || typeof value !== "object") {
10278
10338
  return void 0;
@@ -10294,6 +10354,9 @@ function readUsageSummary(value) {
10294
10354
  function readNumber(value) {
10295
10355
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
10296
10356
  }
10357
+ function readString4(value) {
10358
+ return typeof value === "string" && value.length > 0 ? value : void 0;
10359
+ }
10297
10360
  function summarizeSkills(skills) {
10298
10361
  const summaries = skills.map((skill) => ({
10299
10362
  name: skill.name,
@@ -12443,6 +12506,7 @@ function formatRuntimeStatusText(status) {
12443
12506
  lines.push(`- Skills: ${status.scene.skills.ready}/${status.scene.skills.total} ready; ${status.scene.skills.nextAction}`);
12444
12507
  lines.push(`- Memory: ${status.scene.memory.assets} asset(s), session=${status.scene.memory.latestSessionMemory ? "yes" : "no"}; ${status.scene.memory.nextAction}`);
12445
12508
  lines.push(`- Cost: ${status.scene.cost}`);
12509
+ lines.push(`- Tool output: ${status.scene.toolOutputs}`);
12446
12510
  lines.push(`- Recovery: ${status.scene.recovery}`);
12447
12511
  lines.push("");
12448
12512
  lines.push("Current workspace:");
@@ -12554,6 +12618,24 @@ function formatRuntimeStatusText(status) {
12554
12618
  ].filter(Boolean).join(" "));
12555
12619
  }
12556
12620
  }
12621
+ if (status.toolOutputs.recent.length > 0) {
12622
+ lines.push("");
12623
+ lines.push("Recent tool output:");
12624
+ for (const output of status.toolOutputs.recent.slice(0, 5)) {
12625
+ lines.push([
12626
+ output.toolName ?? "tool",
12627
+ output.kind ? `kind=${output.kind}` : void 0,
12628
+ output.mode ? `mode=${output.mode}` : void 0,
12629
+ output.rawTokens === void 0 ? void 0 : `raw=${output.rawTokens}`,
12630
+ output.projectedTokens === void 0 ? void 0 : `projected=${output.projectedTokens}`,
12631
+ output.savedTokens === void 0 ? void 0 : `saved=${output.savedTokens}`,
12632
+ output.savingsRatio === void 0 ? void 0 : `savedRatio=${Math.round(output.savingsRatio * 100)}%`,
12633
+ output.truncated ? "recoverable=yes" : void 0,
12634
+ output.degraded ? "degraded=yes" : void 0,
12635
+ output.outputPath ? `full=${truncateCliValue(output.outputPath, 80)}` : void 0
12636
+ ].filter(Boolean).join(" "));
12637
+ }
12638
+ }
12557
12639
  if (status.executions.active.length > 0) {
12558
12640
  lines.push("");
12559
12641
  lines.push("Active executions:");
@@ -13339,6 +13421,9 @@ var init_leadWait2 = __esm({
13339
13421
 
13340
13422
  // src/agent/toolResults/modelProjection.ts
13341
13423
  function projectToolResultForModel(input) {
13424
+ if (input.result.metadata?.outputGovernance) {
13425
+ return input.result.metadata.outputGovernance.projection;
13426
+ }
13342
13427
  const parsed = parseObject(input.result.output);
13343
13428
  if (!input.result.ok) {
13344
13429
  return projectFailure(input.toolName, input.result.output, parsed);
@@ -13370,14 +13455,14 @@ function projectToolResultForModel(input) {
13370
13455
  function projectExecutionAction(payload) {
13371
13456
  const execution = readObject2(payload.execution) ?? payload;
13372
13457
  return joinLines([
13373
- readString4(execution.id) ?? "execution",
13374
- readString4(execution.kind),
13375
- readString4(execution.status),
13376
- readString4(execution.command),
13377
- readString4(execution.summary),
13378
- readString4(execution.outputPreview),
13379
- readObject2(execution.health) ? readString4(readObject2(execution.health)?.message) : void 0,
13380
- readString4(execution.error)
13458
+ readString5(execution.id) ?? "execution",
13459
+ readString5(execution.kind),
13460
+ readString5(execution.status),
13461
+ readString5(execution.command),
13462
+ readString5(execution.summary),
13463
+ readString5(execution.outputPreview),
13464
+ readObject2(execution.health) ? readString5(readObject2(execution.health)?.message) : void 0,
13465
+ readString5(execution.error)
13381
13466
  ]);
13382
13467
  }
13383
13468
  function projectExecutionCheck(payload) {
@@ -13387,12 +13472,12 @@ function projectExecutionCheck(payload) {
13387
13472
  const stale = readArray(payload.stale) ?? [];
13388
13473
  const entries = [...active, ...recent].filter((item) => Boolean(item) && typeof item === "object" && !Array.isArray(item)).slice(0, 8).map((item) => {
13389
13474
  const parts = [
13390
- readString4(item.id) ?? "execution",
13391
- readString4(item.kind),
13392
- readString4(item.status),
13393
- readString4(item.summary),
13394
- readString4(item.outputPreview),
13395
- readString4(item.error)
13475
+ readString5(item.id) ?? "execution",
13476
+ readString5(item.kind),
13477
+ readString5(item.status),
13478
+ readString5(item.summary),
13479
+ readString5(item.outputPreview),
13480
+ readString5(item.error)
13396
13481
  ].filter((part) => Boolean(part));
13397
13482
  return parts.join(" ");
13398
13483
  });
@@ -13403,17 +13488,17 @@ function projectExecutionCheck(payload) {
13403
13488
  ]);
13404
13489
  }
13405
13490
  function projectRead(payload) {
13406
- const path59 = readString4(payload.path) ?? readString4(payload.requestedPath) ?? "file";
13491
+ const path59 = readString5(payload.path) ?? readString5(payload.requestedPath) ?? "file";
13407
13492
  if (payload.readable === false) {
13408
13493
  return joinLines([
13409
13494
  `${path59}: not readable`,
13410
- readString4(payload.reason),
13411
- readString4(payload.detectedCapability) ? `capability: ${readString4(payload.detectedCapability)}` : void 0
13495
+ readString5(payload.reason),
13496
+ readString5(payload.detectedCapability) ? `capability: ${readString5(payload.detectedCapability)}` : void 0
13412
13497
  ]);
13413
13498
  }
13414
13499
  const startLine = readNumber2(payload.startLine);
13415
13500
  const endLine = readNumber2(payload.endLine);
13416
- const content = readString4(payload.content) ?? "";
13501
+ const content = readString5(payload.content) ?? "";
13417
13502
  const continuation = readObject2(payload.continuation);
13418
13503
  const continuationArgs = readObject2(continuation?.continuationArgs);
13419
13504
  return joinLines([
@@ -13423,29 +13508,34 @@ function projectRead(payload) {
13423
13508
  ]);
13424
13509
  }
13425
13510
  function projectEdit(payload) {
13426
- const path59 = readString4(payload.path) ?? "file";
13511
+ const path59 = readString5(payload.path) ?? "file";
13427
13512
  const applied = readNumber2(payload.appliedEdits) ?? readNumber2(payload.requestedEdits);
13428
- const diff = readString4(payload.diff) ?? readString4(payload.preview);
13513
+ const diff = readString5(payload.diff) ?? readString5(payload.preview);
13429
13514
  return joinLines([
13430
13515
  `edited ${path59}${applied ? ` (${applied} replacement${applied === 1 ? "" : "s"})` : ""}`,
13431
13516
  diff ? truncateText(diff, DIFF_MAX_CHARS) : void 0
13432
13517
  ]);
13433
13518
  }
13434
13519
  function projectWrite(payload) {
13435
- const path59 = readString4(payload.path) ?? "file";
13520
+ const path59 = readString5(payload.path) ?? "file";
13436
13521
  const bytes = readNumber2(payload.bytes);
13437
13522
  const existed = payload.existed === true;
13438
- const diff = readString4(payload.diff) ?? readString4(payload.preview);
13523
+ const diff = readString5(payload.diff) ?? readString5(payload.preview);
13439
13524
  return joinLines([
13440
13525
  `${existed ? "wrote" : "created"} ${path59}${bytes !== void 0 ? ` (${bytes} bytes)` : ""}`,
13441
13526
  diff ? truncateText(diff, DIFF_MAX_CHARS) : void 0
13442
13527
  ]);
13443
13528
  }
13444
13529
  function projectBash(payload) {
13530
+ const governance = readObject2(payload.outputGovernance);
13531
+ const projection = readString5(governance?.projection);
13532
+ if (projection) {
13533
+ return projection;
13534
+ }
13445
13535
  const exitCode = readNumber2(payload.exitCode);
13446
13536
  const durationMs = readNumber2(payload.durationMs);
13447
- const status = readString4(payload.status);
13448
- const output = readString4(payload.output);
13537
+ const status = readString5(payload.status);
13538
+ const output = readString5(payload.output);
13449
13539
  const lines = [
13450
13540
  `exit ${exitCode ?? "?"}${durationMs !== void 0 ? ` in ${durationMs}ms` : ""}${status && status !== "completed" ? ` (${status})` : ""}`
13451
13541
  ];
@@ -13459,10 +13549,10 @@ function projectBash(payload) {
13459
13549
  }
13460
13550
  function projectSkillLoad(payload) {
13461
13551
  const skill = readObject2(payload.skill);
13462
- const name = readString4(skill?.name) ?? "skill";
13463
- const description = readString4(skill?.description);
13464
- const path59 = readString4(skill?.path);
13465
- const body = readString4(payload.body) ?? "";
13552
+ const name = readString5(skill?.name) ?? "skill";
13553
+ const description = readString5(skill?.description);
13554
+ const path59 = readString5(skill?.path);
13555
+ const body = readString5(payload.body) ?? "";
13466
13556
  return joinLines([
13467
13557
  `loaded skill: ${name}${path59 ? ` (${path59})` : ""}`,
13468
13558
  description,
@@ -13471,10 +13561,10 @@ function projectSkillLoad(payload) {
13471
13561
  }
13472
13562
  function projectGenericSuccess(payload, rawOutput) {
13473
13563
  const lines = [
13474
- readString4(payload.summary),
13475
- readString4(payload.preview),
13476
- readString4(payload.output),
13477
- readString4(payload.content)
13564
+ readString5(payload.summary),
13565
+ readString5(payload.preview),
13566
+ readString5(payload.output),
13567
+ readString5(payload.content)
13478
13568
  ].filter((line) => Boolean(line));
13479
13569
  if (lines.length > 0) {
13480
13570
  return truncateText(lines.join("\n"), DEFAULT_MAX_CHARS);
@@ -13498,9 +13588,9 @@ function projectFailure(toolName, rawOutput, payload) {
13498
13588
  const readArgs = readObject2(details?.readArgs);
13499
13589
  const suggestions = readArray(details?.suggestions);
13500
13590
  const lines = [
13501
- `${toolName} failed: ${readString4(payload.error) ?? "unknown error"}`,
13502
- readString4(payload.code) ? `code: ${readString4(payload.code)}` : void 0,
13503
- readString4(payload.hint) ? `hint: ${readString4(payload.hint)}` : void 0,
13591
+ `${toolName} failed: ${readString5(payload.error) ?? "unknown error"}`,
13592
+ readString5(payload.code) ? `code: ${readString5(payload.code)}` : void 0,
13593
+ readString5(payload.hint) ? `hint: ${readString5(payload.hint)}` : void 0,
13504
13594
  readArgs ? `read: read ${JSON.stringify(readArgs)}` : void 0,
13505
13595
  suggestions && suggestions.length > 0 ? `suggestions: ${suggestions.slice(0, 5).map((item) => String(item)).join(", ")}` : void 0
13506
13596
  ];
@@ -13523,7 +13613,7 @@ function readObject2(value) {
13523
13613
  function readArray(value) {
13524
13614
  return Array.isArray(value) ? value : void 0;
13525
13615
  }
13526
- function readString4(value) {
13616
+ function readString5(value) {
13527
13617
  return typeof value === "string" && value.length > 0 ? value : void 0;
13528
13618
  }
13529
13619
  function readNumber2(value) {
@@ -13550,6 +13640,322 @@ var init_modelProjection = __esm({
13550
13640
  }
13551
13641
  });
13552
13642
 
13643
+ // src/tools/outputKernel/classifier.ts
13644
+ function classifyToolOutput(source) {
13645
+ const output = source.output.trim();
13646
+ if (!output) {
13647
+ return "empty";
13648
+ }
13649
+ const command = (source.command ?? "").toLowerCase();
13650
+ const text = output.toLowerCase();
13651
+ if (looksLikeGitDiff(command, text)) {
13652
+ return "git_diff";
13653
+ }
13654
+ if (looksLikeSearch(command)) {
13655
+ return "search";
13656
+ }
13657
+ if (looksLikeTypecheck(command, text)) {
13658
+ return "typecheck";
13659
+ }
13660
+ if (looksLikeTest(command, text)) {
13661
+ return "test";
13662
+ }
13663
+ if (looksLikeBuild(command, text)) {
13664
+ return "build";
13665
+ }
13666
+ return "generic";
13667
+ }
13668
+ function looksLikeGitDiff(command, text) {
13669
+ return /\bgit\s+(diff|show)\b/.test(command) || text.includes("diff --git ");
13670
+ }
13671
+ function looksLikeSearch(command) {
13672
+ return /(^|\s)(rg|grep)(\s|$)/.test(command);
13673
+ }
13674
+ function looksLikeTypecheck(command, text) {
13675
+ return /\b(tsc|typecheck|mypy)\b/.test(command) || /\b(error|warning)\s+ts\d+:/i.test(text);
13676
+ }
13677
+ function looksLikeTest(command, text) {
13678
+ return /\b(test|vitest|jest|pytest|playwright|node --test)\b/.test(command) || /\b(test result|tests? failed|tests? passed|failing tests?|failures?)\b/.test(text);
13679
+ }
13680
+ function looksLikeBuild(command, text) {
13681
+ return /\b(build|compile|cargo check|cargo clippy|npm run build|pnpm build)\b/.test(command) || /\b(compilation failed|build failed|compiled successfully|error\[e\d+\])\b/.test(text);
13682
+ }
13683
+ var init_classifier = __esm({
13684
+ "src/tools/outputKernel/classifier.ts"() {
13685
+ "use strict";
13686
+ }
13687
+ });
13688
+
13689
+ // src/tools/outputKernel/metrics.ts
13690
+ function estimateTextTokens(value) {
13691
+ const trimmed = value.trim();
13692
+ if (!trimmed) {
13693
+ return 0;
13694
+ }
13695
+ return Math.max(1, Math.ceil(trimmed.length / 4));
13696
+ }
13697
+ function computeSavings(input) {
13698
+ const rawChars = input.raw.length;
13699
+ const projectedChars = input.projected.length;
13700
+ const rawTokens = estimateTextTokens(input.raw);
13701
+ const projectedTokens = estimateTextTokens(input.projected);
13702
+ const savedTokens = Math.max(0, rawTokens - projectedTokens);
13703
+ const savingsRatio = rawTokens > 0 ? Math.round(savedTokens / rawTokens * 1e4) / 1e4 : 0;
13704
+ return {
13705
+ rawChars,
13706
+ projectedChars,
13707
+ rawTokens,
13708
+ projectedTokens,
13709
+ savedTokens,
13710
+ savingsRatio
13711
+ };
13712
+ }
13713
+ var init_metrics2 = __esm({
13714
+ "src/tools/outputKernel/metrics.ts"() {
13715
+ "use strict";
13716
+ }
13717
+ });
13718
+
13719
+ // src/tools/outputKernel/projectors/shared.ts
13720
+ function buildHeader(source, label) {
13721
+ return [
13722
+ `${source.toolName}: ${label}`,
13723
+ source.exitCode === void 0 ? void 0 : `exit=${source.exitCode ?? "null"}`,
13724
+ source.durationMs === void 0 ? void 0 : `duration=${source.durationMs}ms`,
13725
+ source.status ? `status=${source.status}` : void 0
13726
+ ].filter(Boolean).join(" ");
13727
+ }
13728
+ function splitOutputLines(value) {
13729
+ return value.split(/\r?\n/).map((line) => line.trimEnd());
13730
+ }
13731
+ function dedupeProjectedLines(lines) {
13732
+ const seen = /* @__PURE__ */ new Set();
13733
+ const result = [];
13734
+ for (const rawLine of lines) {
13735
+ const line = truncateText(rawLine.trim(), 260);
13736
+ if (!line || seen.has(line)) {
13737
+ continue;
13738
+ }
13739
+ seen.add(line);
13740
+ result.push(line);
13741
+ }
13742
+ return result;
13743
+ }
13744
+ var init_shared6 = __esm({
13745
+ "src/tools/outputKernel/projectors/shared.ts"() {
13746
+ "use strict";
13747
+ init_fs();
13748
+ }
13749
+ });
13750
+
13751
+ // src/tools/outputKernel/projectors/diagnostic.ts
13752
+ function buildDiagnosticProjection(source, label) {
13753
+ const lines = splitOutputLines(source.output);
13754
+ const evidence = lines.filter(isDiagnosticEvidenceLine).slice(0, STRUCTURED_MAX_LINES);
13755
+ const summaryLines = lines.filter(isSummaryLine).slice(0, 8);
13756
+ return dedupeProjectedLines([
13757
+ buildHeader(source, label),
13758
+ ...summaryLines,
13759
+ ...evidence
13760
+ ]).join("\n");
13761
+ }
13762
+ function isDiagnosticEvidenceLine(line) {
13763
+ return /(^|\b)(error|warning|fail|failed|failure|panic|exception|traceback|expected|received|cannot find|not assignable|mismatched|undefined|denied)(\b|:)/i.test(line) || /^\s*(at\s|file\s|src\/|tests?\/|[A-Za-z]:\\|\.\/)/.test(line) || /\(\d+,\d+\):\s+(error|warning)\s+/i.test(line) || /error\[e\d+\]/i.test(line);
13764
+ }
13765
+ function isSummaryLine(line) {
13766
+ return /\b(\d+\s+(passed|failed|skipped|errors?|warnings?)|test result|found \d+ errors?|failed tests?|build failed|compiled successfully)\b/i.test(line);
13767
+ }
13768
+ var STRUCTURED_MAX_LINES;
13769
+ var init_diagnostic = __esm({
13770
+ "src/tools/outputKernel/projectors/diagnostic.ts"() {
13771
+ "use strict";
13772
+ init_shared6();
13773
+ STRUCTURED_MAX_LINES = 28;
13774
+ }
13775
+ });
13776
+
13777
+ // src/tools/outputKernel/projectors/gitDiff.ts
13778
+ function buildGitDiffProjection(source) {
13779
+ const lines = splitOutputLines(source.output);
13780
+ const files = lines.filter((line) => line.startsWith("diff --git ")).map((line) => line.replace(/^diff --git a\//, "").replace(/ b\//, " -> ")).slice(0, DIFF_MAX_FILES);
13781
+ const stats = lines.filter((line) => /(\d+ files? changed|\d+ insertions?\(\+\)|\d+ deletions?\(-\))/.test(line)).slice(0, 8);
13782
+ const hunks = lines.filter((line) => line.startsWith("@@") || line.startsWith("+++ ") || line.startsWith("--- ")).slice(0, 18).map((line) => truncateText(line, 220));
13783
+ return [
13784
+ buildHeader(source, "git diff"),
13785
+ files.length > 0 ? `files: ${files.join(", ")}` : void 0,
13786
+ ...stats,
13787
+ ...hunks
13788
+ ].filter((line) => Boolean(line)).join("\n");
13789
+ }
13790
+ var DIFF_MAX_FILES;
13791
+ var init_gitDiff = __esm({
13792
+ "src/tools/outputKernel/projectors/gitDiff.ts"() {
13793
+ "use strict";
13794
+ init_fs();
13795
+ init_shared6();
13796
+ DIFF_MAX_FILES = 24;
13797
+ }
13798
+ });
13799
+
13800
+ // src/tools/outputKernel/projectors/generic.ts
13801
+ function projectEmptyOutput(source) {
13802
+ return {
13803
+ mode: "empty",
13804
+ projection: buildHeader(source, "no output"),
13805
+ degraded: false,
13806
+ reason: "empty_output"
13807
+ };
13808
+ }
13809
+ function projectGenericOutput(source, reason = "generic_output") {
13810
+ return {
13811
+ mode: "generic",
13812
+ projection: buildGenericPreview(source),
13813
+ degraded: false,
13814
+ reason
13815
+ };
13816
+ }
13817
+ function projectStructuredOutput(source, body) {
13818
+ const trimmed = body.trim();
13819
+ if (!trimmed) {
13820
+ return {
13821
+ mode: "generic",
13822
+ projection: buildGenericPreview(source),
13823
+ degraded: true,
13824
+ reason: "structured_projection_empty"
13825
+ };
13826
+ }
13827
+ return {
13828
+ mode: "structured",
13829
+ projection: trimmed,
13830
+ degraded: false,
13831
+ reason: "structured_projection"
13832
+ };
13833
+ }
13834
+ function buildGenericPreview(source) {
13835
+ return [
13836
+ buildHeader(source, "output"),
13837
+ truncateText(source.output.trim(), GENERIC_MAX_CHARS)
13838
+ ].filter(Boolean).join("\n");
13839
+ }
13840
+ var GENERIC_MAX_CHARS;
13841
+ var init_generic = __esm({
13842
+ "src/tools/outputKernel/projectors/generic.ts"() {
13843
+ "use strict";
13844
+ init_fs();
13845
+ init_shared6();
13846
+ GENERIC_MAX_CHARS = 1500;
13847
+ }
13848
+ });
13849
+
13850
+ // src/tools/outputKernel/projectors/search.ts
13851
+ function buildSearchProjection(source) {
13852
+ const nonEmptyLines = splitOutputLines(source.output).filter((line) => line.trim().length > 0);
13853
+ const matches = nonEmptyLines.slice(0, SEARCH_MAX_MATCHES).map((line) => truncateText(line, 220));
13854
+ const omitted = Math.max(0, nonEmptyLines.length - matches.length);
13855
+ return [
13856
+ buildHeader(source, "search"),
13857
+ `matches shown: ${matches.length}${omitted > 0 ? `, omitted: ${omitted}` : ""}`,
13858
+ ...matches
13859
+ ].join("\n");
13860
+ }
13861
+ var SEARCH_MAX_MATCHES;
13862
+ var init_search2 = __esm({
13863
+ "src/tools/outputKernel/projectors/search.ts"() {
13864
+ "use strict";
13865
+ init_fs();
13866
+ init_shared6();
13867
+ SEARCH_MAX_MATCHES = 24;
13868
+ }
13869
+ });
13870
+
13871
+ // src/tools/outputKernel/projectors/recovery.ts
13872
+ function appendRecoveryHint(projection, governance) {
13873
+ if (!governance.recoveryHint) {
13874
+ return projection;
13875
+ }
13876
+ if (projection.includes(governance.recoveryHint)) {
13877
+ return projection;
13878
+ }
13879
+ return `${projection.trimEnd()}
13880
+ ${governance.recoveryHint}`;
13881
+ }
13882
+ var init_recovery = __esm({
13883
+ "src/tools/outputKernel/projectors/recovery.ts"() {
13884
+ "use strict";
13885
+ }
13886
+ });
13887
+
13888
+ // src/tools/outputKernel/projectors.ts
13889
+ function projectOutputByKind(kind, source) {
13890
+ switch (kind) {
13891
+ case "empty":
13892
+ return projectEmptyOutput(source);
13893
+ case "test":
13894
+ return projectStructuredOutput(source, buildDiagnosticProjection(source, "test"));
13895
+ case "build":
13896
+ return projectStructuredOutput(source, buildDiagnosticProjection(source, "build"));
13897
+ case "typecheck":
13898
+ return projectStructuredOutput(source, buildDiagnosticProjection(source, "typecheck"));
13899
+ case "search":
13900
+ return projectStructuredOutput(source, buildSearchProjection(source));
13901
+ case "git_diff":
13902
+ return projectStructuredOutput(source, buildGitDiffProjection(source));
13903
+ case "generic":
13904
+ return projectGenericOutput(source);
13905
+ }
13906
+ }
13907
+ var init_projectors = __esm({
13908
+ "src/tools/outputKernel/projectors.ts"() {
13909
+ "use strict";
13910
+ init_diagnostic();
13911
+ init_gitDiff();
13912
+ init_generic();
13913
+ init_search2();
13914
+ init_recovery();
13915
+ }
13916
+ });
13917
+
13918
+ // src/tools/outputKernel/index.ts
13919
+ function governToolOutput(source) {
13920
+ const kind = classifyToolOutput(source);
13921
+ const projected = projectOutputByKind(kind, source);
13922
+ const recoveryHint = source.outputPath ? `[full output: ${source.outputPath}]` : void 0;
13923
+ const projection = appendRecoveryHint(projected.projection, {
13924
+ outputPath: source.outputPath,
13925
+ recoveryHint
13926
+ });
13927
+ const metrics = computeSavings({
13928
+ raw: source.output,
13929
+ projected: projection
13930
+ });
13931
+ return {
13932
+ version: 1,
13933
+ kind,
13934
+ mode: projected.mode,
13935
+ projection,
13936
+ rawChars: source.outputChars ?? metrics.rawChars,
13937
+ projectedChars: metrics.projectedChars,
13938
+ rawTokens: metrics.rawTokens,
13939
+ projectedTokens: metrics.projectedTokens,
13940
+ savedTokens: metrics.savedTokens,
13941
+ savingsRatio: metrics.savingsRatio,
13942
+ truncated: Boolean(source.truncated),
13943
+ outputPath: source.outputPath,
13944
+ recoveryHint,
13945
+ degraded: projected.degraded,
13946
+ reason: projected.reason
13947
+ };
13948
+ }
13949
+ var init_outputKernel = __esm({
13950
+ "src/tools/outputKernel/index.ts"() {
13951
+ "use strict";
13952
+ init_classifier();
13953
+ init_metrics2();
13954
+ init_projectors();
13955
+ init_metrics2();
13956
+ }
13957
+ });
13958
+
13553
13959
  // src/tools/bash.ts
13554
13960
  var SHELL_RUNTIME, bashToolDefinition;
13555
13961
  var init_bash = __esm({
@@ -13559,6 +13965,7 @@ var init_bash = __esm({
13559
13965
  init_shellRuntime();
13560
13966
  init_fs();
13561
13967
  init_shared2();
13968
+ init_outputKernel();
13562
13969
  SHELL_RUNTIME = getShellRuntimeInfo();
13563
13970
  bashToolDefinition = {
13564
13971
  definition: {
@@ -13607,6 +14014,18 @@ var init_bash = __esm({
13607
14014
  }
13608
14015
  });
13609
14016
  const status = result.aborted ? "aborted" : result.stalled ? "stalled" : result.timedOut ? "timed_out" : result.exitCode === 0 ? "completed" : "failed";
14017
+ const outputGovernance = governToolOutput({
14018
+ toolName: "bash",
14019
+ command,
14020
+ status,
14021
+ exitCode: result.exitCode,
14022
+ durationMs: result.durationMs,
14023
+ output: result.output,
14024
+ outputPath: result.outputPath,
14025
+ truncated: result.truncated,
14026
+ outputChars: result.outputChars,
14027
+ outputBytes: result.outputBytes
14028
+ });
13610
14029
  const metadata = {
13611
14030
  runtime: {
13612
14031
  status,
@@ -13619,7 +14038,8 @@ var init_bash = __esm({
13619
14038
  truncated: result.truncated,
13620
14039
  outputPath: result.outputPath,
13621
14040
  outputPreview: result.output
13622
- }
14041
+ },
14042
+ outputGovernance
13623
14043
  };
13624
14044
  return okResult(
13625
14045
  JSON.stringify(
@@ -13634,6 +14054,7 @@ var init_bash = __esm({
13634
14054
  outputPath: result.outputPath,
13635
14055
  outputChars: result.outputChars,
13636
14056
  outputBytes: result.outputBytes,
14057
+ outputGovernance,
13637
14058
  output: truncateText(result.output, 4e3),
13638
14059
  ...status === "completed" ? {} : {
13639
14060
  shell: shell.shell,
@@ -226060,6 +226481,31 @@ async function processToolCallBatch(input) {
226060
226481
  changedPathCount: metadata?.changedPaths?.length ?? 0
226061
226482
  }
226062
226483
  });
226484
+ if (metadata?.outputGovernance) {
226485
+ await recordObservabilityEvent(projectContext.stateRootDir, {
226486
+ event: "tool.output",
226487
+ status: result.ok ? "completed" : "failed",
226488
+ sessionId: session.id,
226489
+ identityKind: identity.kind,
226490
+ identityName: identity.name,
226491
+ toolName: toolCall.function.name,
226492
+ durationMs,
226493
+ details: {
226494
+ kind: metadata.outputGovernance.kind,
226495
+ mode: metadata.outputGovernance.mode,
226496
+ rawChars: metadata.outputGovernance.rawChars,
226497
+ projectedChars: metadata.outputGovernance.projectedChars,
226498
+ rawTokens: metadata.outputGovernance.rawTokens,
226499
+ projectedTokens: metadata.outputGovernance.projectedTokens,
226500
+ savedTokens: metadata.outputGovernance.savedTokens,
226501
+ savingsRatio: metadata.outputGovernance.savingsRatio,
226502
+ truncated: metadata.outputGovernance.truncated,
226503
+ outputPath: metadata.outputGovernance.outputPath,
226504
+ degraded: metadata.outputGovernance.degraded,
226505
+ reason: metadata.outputGovernance.reason
226506
+ }
226507
+ });
226508
+ }
226063
226509
  if (result.ok) {
226064
226510
  options.callbacks?.onToolResult?.(toolCall.function.name, result.output);
226065
226511
  } else {
@@ -229745,7 +230191,7 @@ function readStringField(payload, key) {
229745
230191
  const value = payload[key];
229746
230192
  return typeof value === "string" && value.length > 0 ? value : void 0;
229747
230193
  }
229748
- var init_shared6 = __esm({
230194
+ var init_shared7 = __esm({
229749
230195
  "src/runtime-ui/toolDisplay/shared.ts"() {
229750
230196
  "use strict";
229751
230197
  }
@@ -229867,7 +230313,7 @@ var init_call = __esm({
229867
230313
  init_json();
229868
230314
  init_pathDisplay2();
229869
230315
  init_previewPolicy();
229870
- init_shared6();
230316
+ init_shared7();
229871
230317
  }
229872
230318
  });
229873
230319
 
@@ -229913,7 +230359,7 @@ function buildToolResultVisiblePreview(name, rawOutput, cwd) {
229913
230359
  function buildToolFailureDetail(name, rawOutput, cwd) {
229914
230360
  const display = buildToolResultDisplay(name, rawOutput, cwd);
229915
230361
  const parsed = parseJsonObject(display.preview ?? rawOutput);
229916
- const error = readString5(parsed?.error) ?? readString5(parsed?.reason) ?? readString5(parsed?.hint);
230362
+ const error = readString6(parsed?.error) ?? readString6(parsed?.reason) ?? readString6(parsed?.hint);
229917
230363
  if (error) {
229918
230364
  return truncateVisiblePreview(error);
229919
230365
  }
@@ -229959,7 +230405,7 @@ function parseJsonObject(value) {
229959
230405
  return null;
229960
230406
  }
229961
230407
  }
229962
- function readString5(value) {
230408
+ function readString6(value) {
229963
230409
  return typeof value === "string" && value.trim().length > 0 ? value : void 0;
229964
230410
  }
229965
230411
  var init_result = __esm({
@@ -229968,7 +230414,7 @@ var init_result = __esm({
229968
230414
  init_json();
229969
230415
  init_pathDisplay2();
229970
230416
  init_previewPolicy();
229971
- init_shared6();
230417
+ init_shared7();
229972
230418
  }
229973
230419
  });
229974
230420