@synkro-sh/cli 1.6.87 → 1.6.88

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/bootstrap.js CHANGED
@@ -2143,10 +2143,12 @@ export function appendSessionAction(sessionId: string, entry: SessionAction): vo
2143
2143
  appendFileSync(logPath, JSON.stringify(entry) + '\\n', 'utf-8');
2144
2144
  } catch {}
2145
2145
 
2146
- // Cloud: ship the action to the API transcript-sync (org from login JWT) with an
2147
- // explicit step so streamed single-action sends stay idempotent + ordered.
2146
+ // Cloud: stream the action to the session_actions hypertable (salience tagged
2147
+ // server-side, indexed) so the grade path pulls a BOUNDED indexed slice instead
2148
+ // of re-reading a multi-GB log \u2014 what lets us scale to million-tool-call
2149
+ // sessions. Fire-and-forget, idempotent by (session, step).
2148
2150
  if (deployIsCloud()) {
2149
- void syncTranscriptCloud(sessionId, '', [], [{ step, tool: entry.tool, summary: entry.summary, file: entry.file, outcome: entry.outcome }]);
2151
+ shipCloud(loadJwt(), '/api/v1/cli/session-action', { session_id: sessionId, step, tool: entry.tool, summary: entry.summary, file: entry.file, outcome: entry.outcome });
2150
2152
  return;
2151
2153
  }
2152
2154
  const mcpPort = process.env.SYNKRO_MCP_PORT || '18931';
@@ -2274,6 +2276,39 @@ export function compressSessionLog(actions: SessionAction[], rules?: Rule[]): st
2274
2276
  return 'SESSION HISTORY (' + total + ' actions):\\n' + lines.join('\\n');
2275
2277
  }
2276
2278
 
2279
+ // Cloud: fetch the BOUNDED, indexed session context from Timescale (salient +
2280
+ // recent + complete summary) \u2014 flat cost at any session length. Returns null if
2281
+ // the session isn't streamed yet (brand-new / streaming lagging) so the caller
2282
+ // falls back to the local path.
2283
+ async function fetchSessionContext(sessionId: string): Promise<string | null> {
2284
+ const jwt = loadJwt();
2285
+ if (!jwt) return null;
2286
+ try {
2287
+ const r = await fetch(GATEWAY_URL + '/api/v1/hook/session-context', {
2288
+ method: 'POST',
2289
+ headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + jwt },
2290
+ body: JSON.stringify({ session_id: sessionId }),
2291
+ signal: AbortSignal.timeout(3000),
2292
+ });
2293
+ if (!r.ok) return null;
2294
+ const d = await r.json() as { context?: string };
2295
+ return (d && typeof d.context === 'string' && d.context) ? d.context : null;
2296
+ } catch {
2297
+ return null;
2298
+ }
2299
+ }
2300
+
2301
+ // Grade-time session log. CLOUD \u2192 Timescale-backed bounded context (this is the
2302
+ // million-tool-call path: no full-history read); falls back to the local
2303
+ // retrieval compressor only if the session isn't streamed yet. LOCAL \u2192 the
2304
+ // on-device dump, completely UNTOUCHED.
2305
+ export async function sessionLogForGrade(sessionId: string, rules: Rule[]): Promise<string> {
2306
+ if (isLocalStorageMode()) return compressSessionLog(readSessionLog(sessionId));
2307
+ const ctx = await fetchSessionContext(sessionId);
2308
+ if (ctx) return ctx;
2309
+ return compressSessionLog(readSessionLog(sessionId), rules);
2310
+ }
2311
+
2277
2312
  export function cleanupSessionLog(sessionId: string): void {
2278
2313
  const logPath = sessionLogPath(sessionId);
2279
2314
  if (!logPath) return;
@@ -4021,7 +4056,7 @@ import {
4021
4056
  loadJwt, ensureFreshJwt, detectRepo, loadConfig, route, tag, localGrade,
4022
4057
  parseVerdict, parseCombinedVerdict, combinedEditGradeEnabled, dispatchCapture, dispatchFinding, ruleMode, reconstructContent, isPathUnder, postWithRetry,
4023
4058
  readStdin, extractTranscript, readLastPrompt, findNearestDeps, filePathFromToolInput,
4024
- appendSessionAction, readSessionLog, compressSessionLog, log,
4059
+ appendSessionAction, readSessionLog, compressSessionLog, sessionLogForGrade, log,
4025
4060
  outputJson, outputEmpty, setupCursorHookSignals, installHookWatchdog, isEditTool, hookSessionId, GATEWAY_URL,
4026
4061
  logGraderUnavailable, graderUnavailableMessage, filterRules, ruleFilterText, normalizeMode, countEditLineDelta,
4027
4062
  captureLineMetrics, cursorModelFromPayload, resolveTranscriptPath, isCursorInvokingCcHook,
@@ -4148,7 +4183,7 @@ async function main() {
4148
4183
  if (rt === 'local') {
4149
4184
  // \u2500\u2500\u2500 Local grading: org rules ONLY (channel 1, port 18929) \u2500\u2500\u2500
4150
4185
  const proposedShort = proposed.slice(0, 4000);
4151
- const sessionLog = compressSessionLog(readSessionLog(sessionId), config.rules);
4186
+ const sessionLog = await sessionLogForGrade(sessionId, config.rules);
4152
4187
  const graderContent = 'file=' + filePath + ' content=' + proposedShort;
4153
4188
  const relevantRules = await filterRules(
4154
4189
  ruleFilterText(graderContent, transcript.userIntent || lastPrompt),
@@ -4341,7 +4376,7 @@ async function main() {
4341
4376
  recent_user_messages: transcript.recentUserMessages,
4342
4377
  recent_messages: transcript.recentMessages,
4343
4378
  recent_actions: transcript.recentActions,
4344
- session_history: compressSessionLog(readSessionLog(sessionId), config.rules),
4379
+ session_history: await sessionLogForGrade(sessionId, config.rules),
4345
4380
  session_id: sessionId || null,
4346
4381
  tool_use_id: toolUseId || null,
4347
4382
  cwd: cwd || null,
@@ -5412,7 +5447,7 @@ import process from 'node:process';
5412
5447
  import {
5413
5448
  loadJwt, ensureFreshJwt, detectRepo, loadConfig, route, tag, localGrade,
5414
5449
  parseVerdict, dispatchCapture, dispatchFinding, ruleMode, postWithRetry, readStdin,
5415
- extractTranscript, readLastPrompt, appendSessionAction, readSessionLog, compressSessionLog, log,
5450
+ extractTranscript, readLastPrompt, appendSessionAction, readSessionLog, compressSessionLog, sessionLogForGrade, log,
5416
5451
  outputJson, outputEmpty, setupCursorHookSignals, installHookWatchdog, isShellTool, hookSessionId, GATEWAY_URL,
5417
5452
  logGraderUnavailable, graderUnavailableMessage, filterRules, ruleFilterText, normalizeMode, appendLocalTelemetry, isSafeInRepoRead,
5418
5453
  loadSynkroFile, effectiveGraderPool, synkroFilePresent, noSynkroSkipMessage,
@@ -5580,7 +5615,7 @@ async function main() {
5580
5615
  // mode was also checked up there.
5581
5616
 
5582
5617
  if (rt === 'local') {
5583
- const sessionLog = compressSessionLog(readSessionLog(sessionId), config.rules);
5618
+ const sessionLog = await sessionLogForGrade(sessionId, config.rules);
5584
5619
  const relevantRules = await filterRules(
5585
5620
  ruleFilterText(command, transcript.userIntent || lastPrompt),
5586
5621
  config.rules,
@@ -5662,7 +5697,7 @@ async function main() {
5662
5697
  recent_user_messages: transcript.recentUserMessages,
5663
5698
  recent_messages: transcript.recentMessages,
5664
5699
  recent_actions: transcript.recentActions,
5665
- session_history: compressSessionLog(readSessionLog(sessionId), config.rules),
5700
+ session_history: await sessionLogForGrade(sessionId, config.rules),
5666
5701
  session_id: sessionId || null,
5667
5702
  tool_use_id: toolUseId || null,
5668
5703
  cwd: cwd || null,
@@ -5713,7 +5748,7 @@ main();
5713
5748
  import {
5714
5749
  loadJwt, ensureFreshJwt, detectRepo, loadConfig, route, tag, localGrade,
5715
5750
  parseVerdict, dispatchCapture, ruleMode, postWithRetry, readStdin,
5716
- extractTranscript, readLastPrompt, appendSessionAction, readSessionLog, compressSessionLog, log,
5751
+ extractTranscript, readLastPrompt, appendSessionAction, readSessionLog, compressSessionLog, sessionLogForGrade, log,
5717
5752
  outputJson, outputEmpty, setupCursorHookSignals, installHookWatchdog, isAgentTool, hookSessionId, GATEWAY_URL,
5718
5753
  logGraderUnavailable, graderUnavailableMessage, filterRules, normalizeMode, resolveTranscriptPath, isCursorInvokingCcHook,
5719
5754
  loadSynkroFile, effectiveGraderPool, synkroFilePresent, noSynkroSkipMessage,
@@ -5795,7 +5830,7 @@ async function main() {
5795
5830
  }
5796
5831
 
5797
5832
  if (rt === 'local') {
5798
- const sessionLog = compressSessionLog(readSessionLog(sessionId), config.rules);
5833
+ const sessionLog = await sessionLogForGrade(sessionId, config.rules);
5799
5834
  const agentText = 'agent=' + subagentType + ' description=' + description + ' prompt=' + prompt.slice(0, 2000);
5800
5835
  const relevantRules = await filterRules(agentText, config.rules);
5801
5836
  const graderPrompt = [
@@ -5868,7 +5903,7 @@ async function main() {
5868
5903
  recent_user_messages: transcript.recentUserMessages,
5869
5904
  recent_messages: transcript.recentMessages,
5870
5905
  recent_actions: transcript.recentActions,
5871
- session_history: compressSessionLog(readSessionLog(sessionId), config.rules),
5906
+ session_history: await sessionLogForGrade(sessionId, config.rules),
5872
5907
  session_id: sessionId || null,
5873
5908
  tool_use_id: toolUseId || null,
5874
5909
  cwd: cwd || null,
@@ -5906,7 +5941,7 @@ main();
5906
5941
  PLAN_JUDGE_TS = `#!/usr/bin/env bun
5907
5942
  import {
5908
5943
  loadJwt, ensureFreshJwt, detectRepo, loadConfig, route, tag, localGrade,
5909
- parseVerdict, dispatchCapture, appendSessionAction, readSessionLog, compressSessionLog, postWithRetry, readStdin, log,
5944
+ parseVerdict, dispatchCapture, appendSessionAction, readSessionLog, compressSessionLog, sessionLogForGrade, postWithRetry, readStdin, log,
5910
5945
  outputJson, outputEmpty, setupCursorHookSignals, installHookWatchdog, isPlanTool, hookSessionId, GATEWAY_URL,
5911
5946
  filterRules, graderUnavailableMessage, logGraderUnavailable, resolveTranscriptPath, isCursorInvokingCcHook,
5912
5947
  loadSynkroFile, effectiveGraderPool, synkroFilePresent, noSynkroSkipMessage,
@@ -6013,7 +6048,7 @@ async function main() {
6013
6048
  }
6014
6049
 
6015
6050
  if (rt === 'local') {
6016
- const sessionLog = compressSessionLog(readSessionLog(sessionId), config.rules);
6051
+ const sessionLog = await sessionLogForGrade(sessionId, config.rules);
6017
6052
  const relevantRules = await filterRules(plan.slice(0, 2000), config.rules);
6018
6053
  const graderPrompt = [
6019
6054
  'Working directory: ' + (cwd || '.'),
@@ -6446,7 +6481,7 @@ import {
6446
6481
  loadJwt, ensureFreshJwt, detectRepo, loadConfig, route, tag, localGrade,
6447
6482
  parseVerdict, dispatchCapture, dispatchFinding, ruleMode, normalizeMode, filterRules, ruleFilterText,
6448
6483
  isSafeInRepoRead, resolveTranscriptPath, postWithRetry, readStdin, hashCommand,
6449
- extractTranscript, readLastPrompt, readSessionLog, compressSessionLog,
6484
+ extractTranscript, readLastPrompt, readSessionLog, compressSessionLog, sessionLogForGrade,
6450
6485
  appendLocalTelemetry, logGraderUnavailable, graderUnavailableMessage, log, GATEWAY_URL,
6451
6486
  loadSynkroFile, effectiveGraderPool, synkroFilePresent,
6452
6487
  type Rule,
@@ -6619,7 +6654,7 @@ async function main() {
6619
6654
  }
6620
6655
 
6621
6656
  if (rt === 'local') {
6622
- const sessionLog = compressSessionLog(readSessionLog(sessionId), config.rules);
6657
+ const sessionLog = await sessionLogForGrade(sessionId, config.rules);
6623
6658
  const relevantRules = await filterRules(
6624
6659
  ruleFilterText(command, transcript.userIntent || lastPrompt),
6625
6660
  config.rules,
@@ -10916,7 +10951,7 @@ function writeConfigEnv(opts) {
10916
10951
  `SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
10917
10952
  `SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
10918
10953
  `SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
10919
- `SYNKRO_VERSION=${shellQuoteSingle("1.6.87")}`
10954
+ `SYNKRO_VERSION=${shellQuoteSingle("1.6.88")}`
10920
10955
  ];
10921
10956
  if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
10922
10957
  if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
@@ -14959,7 +14994,7 @@ var args = process.argv.slice(2);
14959
14994
  var cmd = args[0] || "";
14960
14995
  var subArgs = args.slice(1);
14961
14996
  function printVersion() {
14962
- console.log("1.6.87");
14997
+ console.log("1.6.88");
14963
14998
  }
14964
14999
  function printHelp2() {
14965
15000
  console.log(`Synkro CLI \u2014 runtime safety for AI coding agents