olakai-cli 0.2.1 → 0.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/dist/index.js CHANGED
@@ -2188,6 +2188,12 @@ import * as path3 from "path";
2188
2188
  import * as readline from "readline";
2189
2189
 
2190
2190
  // src/commands/monitor-transcript.ts
2191
+ var FILE_EDITING_TOOL_NAMES = /* @__PURE__ */ new Set([
2192
+ "Edit",
2193
+ "Write",
2194
+ "MultiEdit"
2195
+ ]);
2196
+ var BASH_TOOL_NAME = "Bash";
2191
2197
  var SKILL_REGEX = /^\/([\w-]+)(?:\s|$)/;
2192
2198
  function detectSkill(userMessage) {
2193
2199
  if (typeof userMessage !== "string") return void 0;
@@ -2230,7 +2236,10 @@ function parseTranscript(raw) {
2230
2236
  inputTokens: 0,
2231
2237
  outputTokens: 0,
2232
2238
  modelName: null,
2233
- numTurns: 0
2239
+ numTurns: 0,
2240
+ toolCallCount: 0,
2241
+ filesEditedCount: 0,
2242
+ bashCommandCount: 0
2234
2243
  };
2235
2244
  if (!raw) return empty;
2236
2245
  const lines = raw.split("\n");
@@ -2244,6 +2253,9 @@ function parseTranscript(raw) {
2244
2253
  let lastAssistantOutputTokens = 0;
2245
2254
  let numTurns = 0;
2246
2255
  let currentTurnUserTimestamp = NaN;
2256
+ let toolCallCount = 0;
2257
+ let bashCommandCount = 0;
2258
+ let editedFilePaths = /* @__PURE__ */ new Set();
2247
2259
  for (const rawLine of lines) {
2248
2260
  if (!rawLine) continue;
2249
2261
  let parsed;
@@ -2260,6 +2272,9 @@ function parseTranscript(raw) {
2260
2272
  lastUserText = text;
2261
2273
  lastUserTimestamp = parseTimestamp(parsed.timestamp);
2262
2274
  currentTurnUserTimestamp = lastUserTimestamp;
2275
+ toolCallCount = 0;
2276
+ bashCommandCount = 0;
2277
+ editedFilePaths = /* @__PURE__ */ new Set();
2263
2278
  lastUserTimestampRaw = typeof parsed.timestamp === "string" && parsed.timestamp ? parsed.timestamp : void 0;
2264
2279
  } else if (parsed.type === "assistant" && parsed.message) {
2265
2280
  const text = extractTextContent(parsed.message.content);
@@ -2268,6 +2283,30 @@ function parseTranscript(raw) {
2268
2283
  if (typeof parsed.message.model === "string") {
2269
2284
  lastAssistantModel = parsed.message.model;
2270
2285
  }
2286
+ const content = parsed.message.content;
2287
+ if (Array.isArray(content)) {
2288
+ for (const block of content) {
2289
+ try {
2290
+ if (!block || block.type !== "tool_use") continue;
2291
+ toolCallCount += 1;
2292
+ const name = typeof block.name === "string" ? block.name : "";
2293
+ if (name === BASH_TOOL_NAME) {
2294
+ bashCommandCount += 1;
2295
+ continue;
2296
+ }
2297
+ if (FILE_EDITING_TOOL_NAMES.has(name)) {
2298
+ const input = block.input;
2299
+ if (input !== null && typeof input === "object" && "file_path" in input) {
2300
+ const filePath = input.file_path;
2301
+ if (typeof filePath === "string" && filePath) {
2302
+ editedFilePaths.add(filePath);
2303
+ }
2304
+ }
2305
+ }
2306
+ } catch {
2307
+ }
2308
+ }
2309
+ }
2271
2310
  const usage = parsed.message.usage;
2272
2311
  if (usage) {
2273
2312
  const input = (usage.input_tokens ?? 0) + (usage.cache_creation_input_tokens ?? 0) + (usage.cache_read_input_tokens ?? 0);
@@ -2288,7 +2327,10 @@ function parseTranscript(raw) {
2288
2327
  inputTokens: lastAssistantInputTokens,
2289
2328
  outputTokens: lastAssistantOutputTokens,
2290
2329
  modelName: lastAssistantModel,
2291
- numTurns
2330
+ numTurns,
2331
+ toolCallCount,
2332
+ filesEditedCount: editedFilePaths.size,
2333
+ bashCommandCount
2292
2334
  };
2293
2335
  if (!Number.isNaN(currentTurnUserTimestamp) && !Number.isNaN(lastAssistantTimestamp) && lastAssistantTimestamp >= currentTurnUserTimestamp) {
2294
2336
  result.latencyMs = Math.round(
@@ -2651,7 +2693,10 @@ function extractFromTranscript(transcriptPath) {
2651
2693
  inputTokens: 0,
2652
2694
  outputTokens: 0,
2653
2695
  modelName: null,
2654
- numTurns: 0
2696
+ numTurns: 0,
2697
+ toolCallCount: 0,
2698
+ filesEditedCount: 0,
2699
+ bashCommandCount: 0
2655
2700
  };
2656
2701
  if (!transcriptPath) return empty;
2657
2702
  let raw;
@@ -2777,7 +2822,15 @@ function buildPayload(event, eventData, config) {
2777
2822
  stopHookActive: eventData.stop_hook_active ?? false,
2778
2823
  inputTokens: extracted.inputTokens,
2779
2824
  outputTokens: extracted.outputTokens,
2780
- numTurns: extracted.numTurns
2825
+ numTurns: extracted.numTurns,
2826
+ // Per-turn work signals for the Claude Code classifier (D-027).
2827
+ // Always emitted as JSON numbers — the backend classifier and
2828
+ // future KPI formulas must see numeric 0, not missing keys or
2829
+ // strings. File paths and bash command strings are deliberately
2830
+ // NOT emitted; only the cardinality is privacy-safe to ship.
2831
+ toolCallCount: extracted.toolCallCount,
2832
+ filesEditedCount: extracted.filesEditedCount,
2833
+ bashCommandCount: extracted.bashCommandCount
2781
2834
  };
2782
2835
  if (typeof extracted.latencyMs === "number") {
2783
2836
  customData.latencyMs = extracted.latencyMs;