iteration-cli 0.14.4 → 0.16.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/cli.js CHANGED
@@ -7,10 +7,9 @@ var __export = (target, all) => {
7
7
 
8
8
  // src/cli.ts
9
9
  import { spawnSync } from "node:child_process";
10
- import { promises as fs23 } from "node:fs";
11
- import os10 from "node:os";
12
- import path29 from "node:path";
13
- import { createInterface as createInterface2 } from "node:readline/promises";
10
+ import { promises as fs24 } from "node:fs";
11
+ import os11 from "node:os";
12
+ import path30 from "node:path";
14
13
  import { parseArgs } from "node:util";
15
14
 
16
15
  // ../trace-vault/packages/cli/dist/index.js
@@ -1163,7 +1162,7 @@ function putProp(target, key, value) {
1163
1162
  else
1164
1163
  target[key] = value;
1165
1164
  }
1166
- function mirrorShape(target, source, keys, wrap) {
1165
+ function mirrorShape(target, source, keys, wrap2) {
1167
1166
  const raw = sourceShape(source);
1168
1167
  for (const key of keys) {
1169
1168
  const desc = Object.getOwnPropertyDescriptor(raw, key);
@@ -1172,10 +1171,10 @@ function mirrorShape(target, source, keys, wrap) {
1172
1171
  if (desc.get) {
1173
1172
  deferProp(target, key, () => {
1174
1173
  const value = source._zod.def.shape[key];
1175
- return wrap ? wrap(value, key) : value;
1174
+ return wrap2 ? wrap2(value, key) : value;
1176
1175
  });
1177
1176
  } else
1178
- putProp(target, key, wrap ? wrap(desc.value, key) : desc.value);
1177
+ putProp(target, key, wrap2 ? wrap2(desc.value, key) : desc.value);
1179
1178
  }
1180
1179
  }
1181
1180
  function mirrorProps(target, source) {
@@ -2015,9 +2014,9 @@ function formatError(error22, mapper = (issue22) => issue22.message) {
2015
2014
  let i = 0;
2016
2015
  while (i < fullpath.length) {
2017
2016
  const el = fullpath[i];
2018
- const terminal = i === fullpath.length - 1;
2017
+ const terminal2 = i === fullpath.length - 1;
2019
2018
  if (el === "_errors") {
2020
- if (terminal)
2019
+ if (terminal2)
2021
2020
  curr._errors.push(mapper(issue22));
2022
2021
  i++;
2023
2022
  continue;
@@ -2031,7 +2030,7 @@ function formatError(error22, mapper = (issue22) => issue22.message) {
2031
2030
  });
2032
2031
  }
2033
2032
  const node22 = curr[el];
2034
- if (terminal) {
2033
+ if (terminal2) {
2035
2034
  node22._errors.push(mapper(issue22));
2036
2035
  }
2037
2036
  curr = node22;
@@ -7890,9 +7889,9 @@ var ClaudeAccountIndex = class {
7890
7889
  add(map, session, id, record32) {
7891
7890
  if (id === null) return;
7892
7891
  const key = this.key(session, id);
7893
- const rows = map.get(key) ?? [];
7894
- rows.push(record32);
7895
- map.set(key, rows);
7892
+ const rows2 = map.get(key) ?? [];
7893
+ rows2.push(record32);
7894
+ map.set(key, rows2);
7896
7895
  }
7897
7896
  get(map, session, id) {
7898
7897
  return id ? map.get(this.key(session, id)) ?? [] : [];
@@ -7968,20 +7967,25 @@ var exportSchema = object({
7968
7967
  });
7969
7968
  var uuid3 = uuid2();
7970
7969
  var identifier2 = string2().regex(/^[A-Za-z0-9_:./-]{1,255}$/);
7970
+ function consoleWriter(line, level) {
7971
+ if (level === "info") console.info(line);
7972
+ else console.error(line);
7973
+ }
7971
7974
  var loggingContext = () => ({});
7972
- function configureCollectorLogging(context) {
7973
- loggingContext = context;
7975
+ var logWriter = consoleWriter;
7976
+ function configureCollectorLogging(context2, write = consoleWriter) {
7977
+ loggingContext = context2;
7978
+ logWriter = write;
7974
7979
  }
7975
7980
  function writeLog(line, level) {
7976
- if (level === "info") console.info(line);
7977
- else console.error(line);
7981
+ logWriter(line, level);
7978
7982
  }
7979
- function createLogger(context, write = writeLog) {
7983
+ function createLogger(context2, write = writeLog) {
7980
7984
  return (entry) => {
7981
7985
  write(
7982
7986
  JSON.stringify({
7983
7987
  ...entry,
7984
- ...context,
7988
+ ...context2,
7985
7989
  at: (/* @__PURE__ */ new Date()).toISOString(),
7986
7990
  pid: process.pid,
7987
7991
  ...loggingContext()
@@ -8380,11 +8384,11 @@ var SecretLintRule = class {
8380
8384
  ruleReportHandle;
8381
8385
  ruleCreator;
8382
8386
  descriptorRule;
8383
- constructor({ descriptorRule, context }) {
8387
+ constructor({ descriptorRule, context: context2 }) {
8384
8388
  this.descriptorRule = descriptorRule;
8385
8389
  this.ruleCreator = descriptorRule.rule;
8386
8390
  const ruleCreatorOptions = descriptorRule.options || {};
8387
- this.ruleReportHandle = this.ruleCreator.create(context, ruleCreatorOptions);
8391
+ this.ruleReportHandle = this.ruleCreator.create(context2, ruleCreatorOptions);
8388
8392
  }
8389
8393
  allowMessageIds() {
8390
8394
  if (!this.descriptorRule.allowMessageIds) {
@@ -8552,7 +8556,7 @@ var createRunningEvents = () => {
8552
8556
  runLint(options) {
8553
8557
  return contextEvents.emit(LINT_HANDLE, options);
8554
8558
  },
8555
- registerRule({ descriptorRule, context }) {
8559
+ registerRule({ descriptorRule, context: context2 }) {
8556
8560
  if (registerSet.has(descriptorRule.id)) {
8557
8561
  throw new Error(`rule.id:${descriptorRule.id} is already registered.
8558
8562
 
@@ -8562,7 +8566,7 @@ Duplicated rule.id is something wrong in .secretlintrc.
8562
8566
  registerSet.add(descriptorRule.id);
8563
8567
  const rule = new SecretLintRule({
8564
8568
  descriptorRule,
8565
- context
8569
+ context: context2
8566
8570
  });
8567
8571
  rules2.push(rule);
8568
8572
  contextEvents.on(LINT_HANDLE, async ({ sourceCode }) => {
@@ -8579,9 +8583,9 @@ Duplicated rule.id is something wrong in .secretlintrc.
8579
8583
  });
8580
8584
  });
8581
8585
  },
8582
- registerRulePreset({ descriptorRulePreset, context }) {
8586
+ registerRulePreset({ descriptorRulePreset, context: context2 }) {
8583
8587
  const rulePresetCreatorOptions = descriptorRulePreset.options || [];
8584
- descriptorRulePreset.rule.create(context, rulePresetCreatorOptions);
8588
+ descriptorRulePreset.rule.create(context2, rulePresetCreatorOptions);
8585
8589
  },
8586
8590
  isRegistered(ruleId) {
8587
8591
  return registerSet.has(ruleId);
@@ -8604,7 +8608,7 @@ var createRulePresetContext = ({ configRulePreset, sourceCode, runningEvents, co
8604
8608
  const descriptorRuleDisabled = descriptorRule ? descriptorRule.disabled : void 0;
8605
8609
  const descriptorRuleSeverity = descriptorRule ? descriptorRule.severity : void 0;
8606
8610
  const descriptorAllowMessageIds = descriptorRule ? descriptorRule.allowMessageIds : void 0;
8607
- const context = createRuleContext({
8611
+ const context2 = createRuleContext({
8608
8612
  // rule id is a single rule in a preset
8609
8613
  ruleId: rule.meta.id,
8610
8614
  // parent rule id is rule preset id
@@ -8631,7 +8635,7 @@ var createRulePresetContext = ({ configRulePreset, sourceCode, runningEvents, co
8631
8635
  allowMessageIds: descriptorAllowMessageIds,
8632
8636
  severity: descriptorRuleSeverity
8633
8637
  },
8634
- context
8638
+ context: context2
8635
8639
  });
8636
8640
  }
8637
8641
  };
@@ -8841,7 +8845,7 @@ var registerRule = ({ sourceCode, config: config22, descriptorRule, contextEvent
8841
8845
  debug("registerRule %s", ruleId);
8842
8846
  const sharedOptionsWithDefault = config22.sharedOptions ?? {};
8843
8847
  if (isRulePreset(descriptorRule)) {
8844
- const context = createRulePresetContext({
8848
+ const context2 = createRulePresetContext({
8845
8849
  configRulePreset: descriptorRule,
8846
8850
  sourceCode,
8847
8851
  contextEvents,
@@ -8851,11 +8855,11 @@ var registerRule = ({ sourceCode, config: config22, descriptorRule, contextEvent
8851
8855
  });
8852
8856
  runningEvents.registerRulePreset({
8853
8857
  descriptorRulePreset: descriptorRule,
8854
- context
8858
+ context: context2
8855
8859
  });
8856
8860
  return;
8857
8861
  } else if (isRule(descriptorRule)) {
8858
- const context = createRuleContext({
8862
+ const context2 = createRuleContext({
8859
8863
  ruleId,
8860
8864
  severity: descriptorRule.severity,
8861
8865
  meta: descriptorRule.rule.meta,
@@ -8866,7 +8870,7 @@ var registerRule = ({ sourceCode, config: config22, descriptorRule, contextEvent
8866
8870
  });
8867
8871
  runningEvents.registerRule({
8868
8872
  descriptorRule,
8869
- context
8873
+ context: context2
8870
8874
  });
8871
8875
  return;
8872
8876
  }
@@ -10569,7 +10573,7 @@ var messages$r = {
10569
10573
  ja: (props) => `AWS Access Key Id: ${props.ID} \u304C\u307F\u3064\u304B\u308A\u307E\u3057\u305F`
10570
10574
  }
10571
10575
  };
10572
- var reportAWSAccessKey = ({ t, source, context, options }) => {
10576
+ var reportAWSAccessKey = ({ t, source, context: context2, options }) => {
10573
10577
  const AWSAccessKeyIDPattern = /\b(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}\b/g;
10574
10578
  const results = source.content.matchAll(AWSAccessKeyIDPattern);
10575
10579
  for (const result of results) {
@@ -10583,7 +10587,7 @@ var reportAWSAccessKey = ({ t, source, context, options }) => {
10583
10587
  if (allowedResults.length > 0) {
10584
10588
  continue;
10585
10589
  }
10586
- context.report({
10590
+ context2.report({
10587
10591
  message: t("AWSAccessKeyID", {
10588
10592
  ID: match
10589
10593
  }),
@@ -10591,7 +10595,7 @@ var reportAWSAccessKey = ({ t, source, context, options }) => {
10591
10595
  });
10592
10596
  }
10593
10597
  };
10594
- var reportAWSSecretAccessKey = ({ t, source, context, options }) => {
10598
+ var reportAWSSecretAccessKey = ({ t, source, context: context2, options }) => {
10595
10599
  const AWS = "(?:AWS|aws|Aws)?_?";
10596
10600
  const QUOTE = `["']?`;
10597
10601
  const CONNECT = "\\s*(?::|=>|=)\\s*";
@@ -10608,7 +10612,7 @@ var reportAWSSecretAccessKey = ({ t, source, context, options }) => {
10608
10612
  if (allowedResults.length > 0) {
10609
10613
  continue;
10610
10614
  }
10611
- context.report({
10615
+ context2.report({
10612
10616
  message: t("AWSSecretAccessKey", {
10613
10617
  KEY: match
10614
10618
  }),
@@ -10616,7 +10620,7 @@ var reportAWSSecretAccessKey = ({ t, source, context, options }) => {
10616
10620
  });
10617
10621
  }
10618
10622
  };
10619
- var reportAWSAccountID = ({ t, source, context, options }) => {
10623
+ var reportAWSAccountID = ({ t, source, context: context2, options }) => {
10620
10624
  const AWS = "(AWS|aws|Aws)?_?";
10621
10625
  const QUOTE = `("|')?`;
10622
10626
  const CONNECT = "\\s*(:|=>|=)\\s*";
@@ -10630,7 +10634,7 @@ var reportAWSAccountID = ({ t, source, context, options }) => {
10630
10634
  if (allowedResults.length > 0) {
10631
10635
  continue;
10632
10636
  }
10633
- context.report({
10637
+ context2.report({
10634
10638
  message: t("AWSAccountID", {
10635
10639
  ID: match
10636
10640
  }),
@@ -10649,19 +10653,19 @@ var creator$s = {
10649
10653
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-aws/README.md"
10650
10654
  }
10651
10655
  },
10652
- create(context, options) {
10656
+ create(context2, options) {
10653
10657
  const normalizedOptions = {
10654
10658
  allows: options.allows || [],
10655
10659
  enableIDScanRule: options.enableIDScanRule ?? false
10656
10660
  };
10657
- const t = context.createTranslator(messages$r);
10661
+ const t = context2.createTranslator(messages$r);
10658
10662
  return {
10659
10663
  file(source) {
10660
10664
  if (normalizedOptions.enableIDScanRule) {
10661
- reportAWSAccessKey({ t, source, context, options: normalizedOptions });
10662
- reportAWSAccountID({ t, source, context, options: normalizedOptions });
10665
+ reportAWSAccessKey({ t, source, context: context2, options: normalizedOptions });
10666
+ reportAWSAccountID({ t, source, context: context2, options: normalizedOptions });
10663
10667
  }
10664
- reportAWSSecretAccessKey({ t, source, context, options: normalizedOptions });
10668
+ reportAWSSecretAccessKey({ t, source, context: context2, options: normalizedOptions });
10665
10669
  }
10666
10670
  };
10667
10671
  }
@@ -10862,7 +10866,7 @@ async function verifyPkcs12Mac(pfxBytes, password) {
10862
10866
  }
10863
10867
  }
10864
10868
  var GCP_SERVICE_ACCOUNT_P12_PASSWORD = "notasecret";
10865
- async function reportIfFoundPrivateKeyP12Format({ source, context, t }) {
10869
+ async function reportIfFoundPrivateKeyP12Format({ source, context: context2, t }) {
10866
10870
  if (!source.filePath) {
10867
10871
  return;
10868
10872
  }
@@ -10874,7 +10878,7 @@ async function reportIfFoundPrivateKeyP12Format({ source, context, t }) {
10874
10878
  if (!isGcpServiceAccountP12) {
10875
10879
  return;
10876
10880
  }
10877
- context.report({
10881
+ context2.report({
10878
10882
  message: t("PrivateKeyP12", {
10879
10883
  FILE_NAME: path172.basename(source.filePath)
10880
10884
  }),
@@ -10893,7 +10897,7 @@ var messages$q = {
10893
10897
  ja: (props) => `GCP\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u306E\u79D8\u5BC6\u9375(json): ${props.FILE_NAME} \u304C\u307F\u3064\u304B\u308A\u307E\u3057\u305F`
10894
10898
  }
10895
10899
  };
10896
- function reportIfFoundPrivateKeyJSONFormat({ source, context, t }) {
10900
+ function reportIfFoundPrivateKeyJSONFormat({ source, context: context2, t }) {
10897
10901
  try {
10898
10902
  const credentialObject = JSON.parse(source.content);
10899
10903
  const PRIVATE_KEY_PATTERN = /-----BEGIN\s?(DSA|RSA|EC|PGP|OPENSSH)?\s?PRIVATE KEY/gm;
@@ -10901,7 +10905,7 @@ function reportIfFoundPrivateKeyJSONFormat({ source, context, t }) {
10901
10905
  if (!isGCPServiceAccountPrivateKeyJSON) {
10902
10906
  return;
10903
10907
  }
10904
- context.report({
10908
+ context2.report({
10905
10909
  message: t("PrivateKeyJSON", {
10906
10910
  FILE_NAME: source.filePath ? path3.basename(source.filePath) : ""
10907
10911
  }),
@@ -10921,17 +10925,17 @@ var creator$r = {
10921
10925
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-gcp/README.md"
10922
10926
  }
10923
10927
  },
10924
- create(context, options) {
10925
- const t = context.createTranslator(messages$q);
10928
+ create(context2, options) {
10929
+ const t = context2.createTranslator(messages$q);
10926
10930
  ({
10927
10931
  allows: options.allows || []
10928
10932
  });
10929
10933
  return {
10930
10934
  file(source) {
10931
10935
  if (source.ext === ".p12") {
10932
- return reportIfFoundPrivateKeyP12Format({ source, context, t });
10936
+ return reportIfFoundPrivateKeyP12Format({ source, context: context2, t });
10933
10937
  } else if (source.ext === ".json") {
10934
- return reportIfFoundPrivateKeyJSONFormat({ source, context, t });
10938
+ return reportIfFoundPrivateKeyJSONFormat({ source, context: context2, t });
10935
10939
  }
10936
10940
  }
10937
10941
  };
@@ -10951,7 +10955,7 @@ var messages$p = {
10951
10955
  ja: (props) => `npm access token: ${props.TOKEN} \u304C\u307F\u3064\u304B\u308A\u307E\u3057\u305F`
10952
10956
  }
10953
10957
  };
10954
- function reportIfFoundXOauthGitHubToken({ source, options, context, t }) {
10958
+ function reportIfFoundXOauthGitHubToken({ source, options, context: context2, t }) {
10955
10959
  const XOAuthPattern = /https?:\/\/(.{1,256}):x-oauth-basic@github.com\//g;
10956
10960
  const results = source.content.matchAll(XOAuthPattern);
10957
10961
  for (const result of results) {
@@ -10962,7 +10966,7 @@ function reportIfFoundXOauthGitHubToken({ source, options, context, t }) {
10962
10966
  if (allowedResults.length > 0) {
10963
10967
  continue;
10964
10968
  }
10965
- context.report({
10969
+ context2.report({
10966
10970
  message: t("PackageJSON_xOauthToken", {
10967
10971
  TOKEN: match
10968
10972
  }),
@@ -10970,7 +10974,7 @@ function reportIfFoundXOauthGitHubToken({ source, options, context, t }) {
10970
10974
  });
10971
10975
  }
10972
10976
  }
10973
- function reportIfFound_AuthTokenInNpmrc({ source, options, context, t }) {
10977
+ function reportIfFound_AuthTokenInNpmrc({ source, options, context: context2, t }) {
10974
10978
  const AuthTokenPattern = /_authToken=([^$].*)/g;
10975
10979
  const results = source.content.matchAll(AuthTokenPattern);
10976
10980
  for (const result of results) {
@@ -10981,7 +10985,7 @@ function reportIfFound_AuthTokenInNpmrc({ source, options, context, t }) {
10981
10985
  if (allowedResults.length > 0) {
10982
10986
  continue;
10983
10987
  }
10984
- context.report({
10988
+ context2.report({
10985
10989
  message: t("Npmrc_authToken", {
10986
10990
  TOKEN: match
10987
10991
  }),
@@ -10989,7 +10993,7 @@ function reportIfFound_AuthTokenInNpmrc({ source, options, context, t }) {
10989
10993
  });
10990
10994
  }
10991
10995
  }
10992
- function reportIfFound_NPM_ACCESS_TOKEN({ source, options, context, t }) {
10996
+ function reportIfFound_NPM_ACCESS_TOKEN({ source, options, context: context2, t }) {
10993
10997
  const NPM_ACCESS_TOKEN_PATTERN = new RegExp("(?<!\\p{L})npm_[A-Za-z0-9_]{36}(?![A-Za-z0-9_])", "gu");
10994
10998
  const results = source.content.matchAll(NPM_ACCESS_TOKEN_PATTERN);
10995
10999
  for (const result of results) {
@@ -11000,7 +11004,7 @@ function reportIfFound_NPM_ACCESS_TOKEN({ source, options, context, t }) {
11000
11004
  if (allowedResults.length > 0) {
11001
11005
  continue;
11002
11006
  }
11003
- context.report({
11007
+ context2.report({
11004
11008
  message: t("NPM_ACCESS_TOKEN", {
11005
11009
  TOKEN: match
11006
11010
  }),
@@ -11031,19 +11035,19 @@ var creator$q = {
11031
11035
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-npm/README.md"
11032
11036
  }
11033
11037
  },
11034
- create(context, options) {
11035
- const t = context.createTranslator(messages$p);
11038
+ create(context2, options) {
11039
+ const t = context2.createTranslator(messages$p);
11036
11040
  const normalizedOptions = {
11037
11041
  allows: options.allows || []
11038
11042
  };
11039
11043
  return {
11040
11044
  file(source) {
11041
11045
  if (isPackageFile(source.filePath)) {
11042
- reportIfFoundXOauthGitHubToken({ source, options: normalizedOptions, context, t });
11046
+ reportIfFoundXOauthGitHubToken({ source, options: normalizedOptions, context: context2, t });
11043
11047
  } else if (isNpmrc(source.filePath)) {
11044
- reportIfFound_AuthTokenInNpmrc({ source, options: normalizedOptions, context, t });
11048
+ reportIfFound_AuthTokenInNpmrc({ source, options: normalizedOptions, context: context2, t });
11045
11049
  }
11046
- reportIfFound_NPM_ACCESS_TOKEN({ source, options: normalizedOptions, context, t });
11050
+ reportIfFound_NPM_ACCESS_TOKEN({ source, options: normalizedOptions, context: context2, t });
11047
11051
  }
11048
11052
  };
11049
11053
  }
@@ -11058,7 +11062,7 @@ var messages$o = {
11058
11062
  ja: (props) => `Slack\u306EIncoming Webhooks: ${props.TOKEN} \u304C\u307F\u3064\u304B\u308A\u307E\u3057\u305F`
11059
11063
  }
11060
11064
  };
11061
- function reportIfFoundRawPrivateKey$1({ source, options, context, t }) {
11065
+ function reportIfFoundRawPrivateKey$1({ source, options, context: context2, t }) {
11062
11066
  const SLACK_TOKEN_PATTERN = /\b(?:xoxb|xoxp|xapp|xoxa|xoxo|xoxr)-(?:\d-)?(?:[a-zA-Z0-9]{1,40}-)+[a-zA-Z0-9]{1,40}\b/g;
11063
11067
  const results = source.content.matchAll(SLACK_TOKEN_PATTERN);
11064
11068
  for (const result of results) {
@@ -11069,7 +11073,7 @@ function reportIfFoundRawPrivateKey$1({ source, options, context, t }) {
11069
11073
  if (allowedResults.length > 0) {
11070
11074
  continue;
11071
11075
  }
11072
- context.report({
11076
+ context2.report({
11073
11077
  message: t("SLACK_TOKEN", {
11074
11078
  TOKEN: match
11075
11079
  }),
@@ -11077,7 +11081,7 @@ function reportIfFoundRawPrivateKey$1({ source, options, context, t }) {
11077
11081
  });
11078
11082
  }
11079
11083
  }
11080
- function reportIfFoundIncomingWebhook({ source, options, context, t }) {
11084
+ function reportIfFoundIncomingWebhook({ source, options, context: context2, t }) {
11081
11085
  const IncomingWebhooksPattern = /https:\/\/hooks\.slack\.com\/services\/T[a-zA-Z0-9]{1,40}\/B[a-zA-Z0-9]{1,40}\/[a-zA-Z0-9]{1,40}/gi;
11082
11086
  const results = source.content.matchAll(IncomingWebhooksPattern);
11083
11087
  for (const result of results) {
@@ -11088,7 +11092,7 @@ function reportIfFoundIncomingWebhook({ source, options, context, t }) {
11088
11092
  if (allowedResults.length > 0) {
11089
11093
  continue;
11090
11094
  }
11091
- context.report({
11095
+ context2.report({
11092
11096
  message: t("IncomingWebhook", {
11093
11097
  URL: match
11094
11098
  }),
@@ -11107,15 +11111,15 @@ var creator$p = {
11107
11111
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-slack/README.md"
11108
11112
  }
11109
11113
  },
11110
- create(context, options) {
11111
- const t = context.createTranslator(messages$o);
11114
+ create(context2, options) {
11115
+ const t = context2.createTranslator(messages$o);
11112
11116
  const normalizedOptions = {
11113
11117
  allows: options.allows || []
11114
11118
  };
11115
11119
  return {
11116
11120
  file(source) {
11117
- reportIfFoundRawPrivateKey$1({ source, options: normalizedOptions, context, t });
11118
- reportIfFoundIncomingWebhook({ source, options: normalizedOptions, context, t });
11121
+ reportIfFoundRawPrivateKey$1({ source, options: normalizedOptions, context: context2, t });
11122
+ reportIfFoundIncomingWebhook({ source, options: normalizedOptions, context: context2, t });
11119
11123
  }
11120
11124
  };
11121
11125
  }
@@ -11180,7 +11184,7 @@ function isLikelyRealPassword(password) {
11180
11184
  return false;
11181
11185
  return true;
11182
11186
  }
11183
- function reportIfFoundBasicAuth({ source, options, context, t }) {
11187
+ function reportIfFoundBasicAuth({ source, options, context: context2, t }) {
11184
11188
  const URL_PATTERN = /(?<protocol>(?:https?|ftp|ftps)):\/\/(?<user>[-a-zA-Z0-9_]{1,256}):(?<password>[-a-zA-Z0-9_]{1,256})@[-a-zA-Z0-9%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b/g;
11185
11189
  const results = source.content.matchAll(URL_PATTERN);
11186
11190
  for (const result of results) {
@@ -11199,7 +11203,7 @@ function reportIfFoundBasicAuth({ source, options, context, t }) {
11199
11203
  if (allowedResults.length > 0) {
11200
11204
  continue;
11201
11205
  }
11202
- context.report({
11206
+ context2.report({
11203
11207
  message: t("BasicAuth", {
11204
11208
  CREDENTIAL: match
11205
11209
  }),
@@ -11218,14 +11222,14 @@ var creator$o = {
11218
11222
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-basicauth/README.md"
11219
11223
  }
11220
11224
  },
11221
- create(context, options) {
11222
- const t = context.createTranslator(messages$n);
11225
+ create(context2, options) {
11226
+ const t = context2.createTranslator(messages$n);
11223
11227
  const normalizedOptions = {
11224
11228
  allows: options.allows || []
11225
11229
  };
11226
11230
  return {
11227
11231
  file(source) {
11228
- reportIfFoundBasicAuth({ source, options: normalizedOptions, context, t });
11232
+ reportIfFoundBasicAuth({ source, options: normalizedOptions, context: context2, t });
11229
11233
  }
11230
11234
  };
11231
11235
  }
@@ -11247,8 +11251,8 @@ var creator$n = {
11247
11251
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-openai/README.md"
11248
11252
  }
11249
11253
  },
11250
- create(context) {
11251
- const t = context.createTranslator(messages$m);
11254
+ create(context2) {
11255
+ const t = context2.createTranslator(messages$m);
11252
11256
  return {
11253
11257
  file(source) {
11254
11258
  const pattern = /sk-(?:proj|svcacct|admin)-(?:[A-Za-z0-9_-]{74}|[A-Za-z0-9_-]{58})T3BlbkFJ(?:[A-Za-z0-9_-]{74}|[A-Za-z0-9_-]{58})\b|sk-[a-zA-Z0-9]{20}T3BlbkFJ[a-zA-Z0-9]{20}/g;
@@ -11257,7 +11261,7 @@ var creator$n = {
11257
11261
  const index = match.index ?? 0;
11258
11262
  const matchString = match[0] ?? "";
11259
11263
  const range = [index, index + matchString.length];
11260
- context.report({
11264
+ context2.report({
11261
11265
  message: t("OPENAI_TOKEN", {
11262
11266
  TOKEN: matchString
11263
11267
  }),
@@ -11285,8 +11289,8 @@ var creator$m = {
11285
11289
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-anthropic/README.md"
11286
11290
  }
11287
11291
  },
11288
- create(context) {
11289
- const t = context.createTranslator(messages$l);
11292
+ create(context2) {
11293
+ const t = context2.createTranslator(messages$l);
11290
11294
  return {
11291
11295
  file(source) {
11292
11296
  const pattern = new RegExp("(?<!\\p{L})sk-ant-api0\\d-[A-Za-z0-9_-]{90,128}AA(?![A-Za-z0-9_-])", "gu");
@@ -11295,7 +11299,7 @@ var creator$m = {
11295
11299
  const index = match.index ?? 0;
11296
11300
  const matchString = match[0] ?? "";
11297
11301
  const range = [index, index + matchString.length];
11298
- context.report({
11302
+ context2.report({
11299
11303
  message: t("ANTHROPIC_API_KEY", {
11300
11304
  KEY: matchString
11301
11305
  }),
@@ -11323,8 +11327,8 @@ var creator$l = {
11323
11327
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-groq/README.md"
11324
11328
  }
11325
11329
  },
11326
- create(context, options) {
11327
- const t = context.createTranslator(messages$k);
11330
+ create(context2, options) {
11331
+ const t = context2.createTranslator(messages$k);
11328
11332
  const normalizedOptions = {
11329
11333
  allows: options?.allows ?? []
11330
11334
  };
@@ -11340,7 +11344,7 @@ var creator$l = {
11340
11344
  continue;
11341
11345
  }
11342
11346
  const range = [index, index + matchString.length];
11343
- context.report({
11347
+ context2.report({
11344
11348
  message: t("GROQ_API_KEY", {
11345
11349
  KEY: matchString
11346
11350
  }),
@@ -11368,8 +11372,8 @@ var creator$k = {
11368
11372
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-huggingface/README.md"
11369
11373
  }
11370
11374
  },
11371
- create(context, options) {
11372
- const t = context.createTranslator(messages$j);
11375
+ create(context2, options) {
11376
+ const t = context2.createTranslator(messages$j);
11373
11377
  const normalizedOptions = {
11374
11378
  allows: options?.allows ?? []
11375
11379
  };
@@ -11385,7 +11389,7 @@ var creator$k = {
11385
11389
  continue;
11386
11390
  }
11387
11391
  const range = [index, index + matchString.length];
11388
- context.report({
11392
+ context2.report({
11389
11393
  message: t("HUGGINGFACE_USER_ACCESS_TOKEN", {
11390
11394
  TOKEN: matchString
11391
11395
  }),
@@ -11413,8 +11417,8 @@ var creator$j = {
11413
11417
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-linear/README.md"
11414
11418
  }
11415
11419
  },
11416
- create(context) {
11417
- const t = context.createTranslator(messages$i);
11420
+ create(context2) {
11421
+ const t = context2.createTranslator(messages$i);
11418
11422
  return {
11419
11423
  file(source) {
11420
11424
  const pattern = new RegExp("(?<!\\p{L})lin_api_[a-zA-Z0-9_]{32,128}(?![a-zA-Z0-9_])", "gu");
@@ -11423,7 +11427,7 @@ var creator$j = {
11423
11427
  const index = match.index ?? 0;
11424
11428
  const matchString = match[0] ?? "";
11425
11429
  const range = [index, index + matchString.length];
11426
- context.report({
11430
+ context2.report({
11427
11431
  message: t("LINEAR_API_TOKEN", {
11428
11432
  ID: matchString
11429
11433
  }),
@@ -11440,7 +11444,7 @@ var messages$h = {
11440
11444
  ja: (props) => `Notion integration \u30C8\u30FC\u30AF\u30F3: ${props.TOKEN} \u304C\u307F\u3064\u304B\u308A\u307E\u3057\u305F`
11441
11445
  }
11442
11446
  };
11443
- function reportIfFoundToken({ source, options, context, t }) {
11447
+ function reportIfFoundToken({ source, options, context: context2, t }) {
11444
11448
  const NOTION_INTEGRATION_TOKEN_PATTERN = new RegExp("(?<!\\p{L})ntn_[0-9]{11}[A-Za-z0-9]{35}(?![A-Za-z0-9])", "gu");
11445
11449
  const results = source.content.matchAll(NOTION_INTEGRATION_TOKEN_PATTERN);
11446
11450
  for (const result of results) {
@@ -11451,7 +11455,7 @@ function reportIfFoundToken({ source, options, context, t }) {
11451
11455
  if (allowedResults.length > 0) {
11452
11456
  continue;
11453
11457
  }
11454
- context.report({
11458
+ context2.report({
11455
11459
  message: t("NOTION_INTEGRATION_TOKEN", {
11456
11460
  TOKEN: match
11457
11461
  }),
@@ -11470,14 +11474,14 @@ var creator$i = {
11470
11474
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-notion/README.md"
11471
11475
  }
11472
11476
  },
11473
- create(context, options) {
11474
- const t = context.createTranslator(messages$h);
11477
+ create(context2, options) {
11478
+ const t = context2.createTranslator(messages$h);
11475
11479
  const normalizedOptions = {
11476
11480
  allows: options.allows ?? []
11477
11481
  };
11478
11482
  return {
11479
11483
  file(source) {
11480
- reportIfFoundToken({ source, options: normalizedOptions, context, t });
11484
+ reportIfFoundToken({ source, options: normalizedOptions, context: context2, t });
11481
11485
  }
11482
11486
  };
11483
11487
  }
@@ -11502,7 +11506,7 @@ function validateBase64KeyContent(base64Content) {
11502
11506
  }
11503
11507
  return true;
11504
11508
  }
11505
- function reportIfFoundRawPrivateKey({ source, options, context, t }) {
11509
+ function reportIfFoundRawPrivateKey({ source, options, context: context2, t }) {
11506
11510
  const results = source.content.matchAll(PEM_CONTENT_PATTERN);
11507
11511
  for (const result of results) {
11508
11512
  const index = result.index || 0;
@@ -11517,7 +11521,7 @@ function reportIfFoundRawPrivateKey({ source, options, context, t }) {
11517
11521
  if (!validateBase64KeyContent(base64Content)) {
11518
11522
  continue;
11519
11523
  }
11520
- context.report({
11524
+ context2.report({
11521
11525
  message: t("PrivateKey", {
11522
11526
  KEY: match
11523
11527
  }),
@@ -11536,14 +11540,14 @@ var creator$h = {
11536
11540
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-privatekey/README.md"
11537
11541
  }
11538
11542
  },
11539
- create(context, options) {
11540
- const t = context.createTranslator(messages$g);
11543
+ create(context2, options) {
11544
+ const t = context2.createTranslator(messages$g);
11541
11545
  const normalizedOptions = {
11542
11546
  allows: options.allows || []
11543
11547
  };
11544
11548
  return {
11545
11549
  file(source) {
11546
- reportIfFoundRawPrivateKey({ source, options: normalizedOptions, context, t });
11550
+ reportIfFoundRawPrivateKey({ source, options: normalizedOptions, context: context2, t });
11547
11551
  }
11548
11552
  };
11549
11553
  }
@@ -11554,7 +11558,7 @@ var messages$f = {
11554
11558
  ja: (props) => `Sendgrid API\u30AD\u30FC\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F\uFF1A ${props.KEY}`
11555
11559
  }
11556
11560
  };
11557
- function reportIfFoundKey$3({ source, options, context, t }) {
11561
+ function reportIfFoundKey$3({ source, options, context: context2, t }) {
11558
11562
  const SENDGRID_KEY_PATTERN = new RegExp("(?<!\\p{L})SG\\.\\w{1,128}\\.\\w{1,128}([-_]?)\\w{1,128}(?!\\w)", "gu");
11559
11563
  const results = source.content.matchAll(SENDGRID_KEY_PATTERN);
11560
11564
  for (const result of results) {
@@ -11568,7 +11572,7 @@ function reportIfFoundKey$3({ source, options, context, t }) {
11568
11572
  if (allowedResults.length > 0) {
11569
11573
  continue;
11570
11574
  }
11571
- context.report({
11575
+ context2.report({
11572
11576
  message: t("SENDGRID_KEY", {
11573
11577
  KEY: match
11574
11578
  }),
@@ -11587,14 +11591,14 @@ var creator$g = {
11587
11591
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-sendgrid/README.md"
11588
11592
  }
11589
11593
  },
11590
- create(context, options) {
11591
- const t = context.createTranslator(messages$f);
11594
+ create(context2, options) {
11595
+ const t = context2.createTranslator(messages$f);
11592
11596
  const normalizedOptions = {
11593
11597
  allows: options.allows || []
11594
11598
  };
11595
11599
  return {
11596
11600
  file(source) {
11597
- reportIfFoundKey$3({ source, options: normalizedOptions, context, t });
11601
+ reportIfFoundKey$3({ source, options: normalizedOptions, context: context2, t });
11598
11602
  }
11599
11603
  };
11600
11604
  }
@@ -11605,7 +11609,7 @@ var messages$e = {
11605
11609
  ja: (props) => `Shopify API\u30AD\u30FC\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F\uFF1A ${props.KEY}`
11606
11610
  }
11607
11611
  };
11608
- function reportIfFoundKey$2({ source, options, context, t }) {
11612
+ function reportIfFoundKey$2({ source, options, context: context2, t }) {
11609
11613
  const SHOPIFY_KEY_PATTERN = new RegExp("(?<!\\p{L})(shppa|shpca|shpat|shpss)_[a-zA-Z0-9]{32,64}(?![a-zA-Z0-9])", "gu");
11610
11614
  const results = source.content.matchAll(SHOPIFY_KEY_PATTERN);
11611
11615
  for (const result of results) {
@@ -11616,7 +11620,7 @@ function reportIfFoundKey$2({ source, options, context, t }) {
11616
11620
  if (allowedResults.length > 0) {
11617
11621
  continue;
11618
11622
  }
11619
- context.report({
11623
+ context2.report({
11620
11624
  message: t("SHOPIFY_KEY", {
11621
11625
  KEY: match
11622
11626
  }),
@@ -11635,14 +11639,14 @@ var creator$f = {
11635
11639
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-shopify/README.md"
11636
11640
  }
11637
11641
  },
11638
- create(context, options) {
11639
- const t = context.createTranslator(messages$e);
11642
+ create(context2, options) {
11643
+ const t = context2.createTranslator(messages$e);
11640
11644
  const normalizedOptions = {
11641
11645
  allows: options.allows || []
11642
11646
  };
11643
11647
  return {
11644
11648
  file(source) {
11645
- reportIfFoundKey$2({ source, options: normalizedOptions, context, t });
11649
+ reportIfFoundKey$2({ source, options: normalizedOptions, context: context2, t });
11646
11650
  }
11647
11651
  };
11648
11652
  }
@@ -11672,7 +11676,7 @@ var messageIdMap$1 = {
11672
11676
  rk_test: "STRIPE_RESTRICTED_KEY_TEST"
11673
11677
  };
11674
11678
  var STRIPE_KEY_PATTERN = new RegExp("(?<!\\p{L})(?<prefix>sk_live|sk_test|rk_live|rk_test)_[a-zA-Z0-9]{24,99}(?![a-zA-Z0-9])", "gu");
11675
- function reportIfFound$2({ source, options, context, t }) {
11679
+ function reportIfFound$2({ source, options, context: context2, t }) {
11676
11680
  const results = source.content.matchAll(STRIPE_KEY_PATTERN);
11677
11681
  for (const result of results) {
11678
11682
  const index = result.index ?? 0;
@@ -11686,7 +11690,7 @@ function reportIfFound$2({ source, options, context, t }) {
11686
11690
  if (allowedResults.length > 0) {
11687
11691
  continue;
11688
11692
  }
11689
- context.report({
11693
+ context2.report({
11690
11694
  message: t(messageIdMap$1[prefix], {
11691
11695
  KEY: match
11692
11696
  }),
@@ -11705,14 +11709,14 @@ var creator$e = {
11705
11709
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-stripe/README.md"
11706
11710
  }
11707
11711
  },
11708
- create(context, options) {
11709
- const t = context.createTranslator(messages$d);
11712
+ create(context2, options) {
11713
+ const t = context2.createTranslator(messages$d);
11710
11714
  const normalizedOptions = {
11711
11715
  allows: options.allows ?? []
11712
11716
  };
11713
11717
  return {
11714
11718
  file(source) {
11715
- reportIfFound$2({ source, options: normalizedOptions, context, t });
11719
+ reportIfFound$2({ source, options: normalizedOptions, context: context2, t });
11716
11720
  }
11717
11721
  };
11718
11722
  }
@@ -11731,7 +11735,7 @@ var typeMap = /* @__PURE__ */ new Map([
11731
11735
  ["ghr", "refresh tokens"],
11732
11736
  ["github_pat", "fine-grained personal access tokens"]
11733
11737
  ]);
11734
- function reportIfFoundKey$1({ pattern, source, options, context, t }) {
11738
+ function reportIfFoundKey$1({ pattern, source, options, context: context2, t }) {
11735
11739
  const results = source.content.matchAll(pattern);
11736
11740
  for (const result of results) {
11737
11741
  const index = result.index || 0;
@@ -11746,7 +11750,7 @@ function reportIfFoundKey$1({ pattern, source, options, context, t }) {
11746
11750
  if (allowedResults.length > 0) {
11747
11751
  continue;
11748
11752
  }
11749
- context.report({
11753
+ context2.report({
11750
11754
  message: t("GITHUB_TOKEN", {
11751
11755
  KEY: match,
11752
11756
  typeName
@@ -11766,7 +11770,7 @@ var creator$d = {
11766
11770
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-github/README.md"
11767
11771
  }
11768
11772
  },
11769
- create(context, options) {
11773
+ create(context2, options) {
11770
11774
  const CLASSIC_GITHUB_TOKEN_PATTERN = new RegExp("(?<!\\p{L})(?<type>ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{36}(?![A-Za-z0-9_])", "gu");
11771
11775
  const FINE_GRAINED_GITHUB_TOKEN_PATTERN = new RegExp("(?<!\\p{L})(?<type>github_pat)_[A-Za-z0-9_]{82}(?![A-Za-z0-9_])", "gu");
11772
11776
  const GITHUB_APP_INSTALLATION_TOKEN_PATTERN = new RegExp("(?<!\\p{L})(?<type>ghs)_[0-9]{1,20}_[A-Za-z0-9_-]{1,1000}\\.[A-Za-z0-9_-]{1,10000}\\.[A-Za-z0-9_-]{1,1000}(?![A-Za-z0-9_-])", "gu");
@@ -11775,14 +11779,14 @@ var creator$d = {
11775
11779
  FINE_GRAINED_GITHUB_TOKEN_PATTERN,
11776
11780
  GITHUB_APP_INSTALLATION_TOKEN_PATTERN
11777
11781
  ];
11778
- const t = context.createTranslator(messages$c);
11782
+ const t = context2.createTranslator(messages$c);
11779
11783
  const normalizedOptions = {
11780
11784
  allows: options.allows || []
11781
11785
  };
11782
11786
  return {
11783
11787
  file(source) {
11784
11788
  for (const pattern of patterns) {
11785
- reportIfFoundKey$1({ pattern, source, options: normalizedOptions, context, t });
11789
+ reportIfFoundKey$1({ pattern, source, options: normalizedOptions, context: context2, t });
11786
11790
  }
11787
11791
  }
11788
11792
  };
@@ -11794,7 +11798,7 @@ var messages$b = {
11794
11798
  ja: (props) => `GitLab Personal Access Token\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F: ${props.KEY}`
11795
11799
  }
11796
11800
  };
11797
- function reportIfFoundKey({ pattern, source, options, context, t }) {
11801
+ function reportIfFoundKey({ pattern, source, options, context: context2, t }) {
11798
11802
  const results = source.content.matchAll(pattern);
11799
11803
  for (const result of results) {
11800
11804
  const index = result.index ?? 0;
@@ -11804,7 +11808,7 @@ function reportIfFoundKey({ pattern, source, options, context, t }) {
11804
11808
  if (allowedResults.length > 0) {
11805
11809
  continue;
11806
11810
  }
11807
- context.report({
11811
+ context2.report({
11808
11812
  message: t("GITLAB_PERSONAL_ACCESS_TOKEN", {
11809
11813
  KEY: match
11810
11814
  }),
@@ -11823,17 +11827,17 @@ var creator$c = {
11823
11827
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-gitlab/README.md"
11824
11828
  }
11825
11829
  },
11826
- create(context, options) {
11830
+ create(context2, options) {
11827
11831
  const GITLAB_PERSONAL_ACCESS_TOKEN_PATTERN = new RegExp("(?<!\\p{L})glpat-[A-Za-z0-9_-]{20,128}(?![A-Za-z0-9_-])", "gu");
11828
11832
  const patterns = [GITLAB_PERSONAL_ACCESS_TOKEN_PATTERN];
11829
- const t = context.createTranslator(messages$b);
11833
+ const t = context2.createTranslator(messages$b);
11830
11834
  const normalizedOptions = {
11831
11835
  allows: options.allows ?? []
11832
11836
  };
11833
11837
  return {
11834
11838
  file(source) {
11835
11839
  for (const pattern of patterns) {
11836
- reportIfFoundKey({ pattern, source, options: normalizedOptions, context, t });
11840
+ reportIfFoundKey({ pattern, source, options: normalizedOptions, context: context2, t });
11837
11841
  }
11838
11842
  }
11839
11843
  };
@@ -11849,7 +11853,7 @@ var messages$a = {
11849
11853
  ja: (props) => `Grafana Service Account \u30C8\u30FC\u30AF\u30F3: ${props.TOKEN} \u304C\u307F\u3064\u304B\u308A\u307E\u3057\u305F`
11850
11854
  }
11851
11855
  };
11852
- function reportIfFound$1({ pattern, messageId, source, options, context, t }) {
11856
+ function reportIfFound$1({ pattern, messageId, source, options, context: context2, t }) {
11853
11857
  const results = source.content.matchAll(pattern);
11854
11858
  for (const result of results) {
11855
11859
  const index = result.index ?? 0;
@@ -11859,7 +11863,7 @@ function reportIfFound$1({ pattern, messageId, source, options, context, t }) {
11859
11863
  continue;
11860
11864
  }
11861
11865
  const range = [index, index + match.length];
11862
- context.report({
11866
+ context2.report({
11863
11867
  message: t(messageId, {
11864
11868
  TOKEN: match
11865
11869
  }),
@@ -11878,8 +11882,8 @@ var creator$b = {
11878
11882
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-grafana/README.md"
11879
11883
  }
11880
11884
  },
11881
- create(context, options) {
11882
- const t = context.createTranslator(messages$a);
11885
+ create(context2, options) {
11886
+ const t = context2.createTranslator(messages$a);
11883
11887
  const normalizedOptions = {
11884
11888
  allows: options?.allows ?? []
11885
11889
  };
@@ -11892,7 +11896,7 @@ var creator$b = {
11892
11896
  messageId: "GRAFANA_CLOUD_API_TOKEN",
11893
11897
  source,
11894
11898
  options: normalizedOptions,
11895
- context,
11899
+ context: context2,
11896
11900
  t
11897
11901
  });
11898
11902
  reportIfFound$1({
@@ -11900,7 +11904,7 @@ var creator$b = {
11900
11904
  messageId: "GRAFANA_SERVICE_ACCOUNT_TOKEN",
11901
11905
  source,
11902
11906
  options: normalizedOptions,
11903
- context,
11907
+ context: context2,
11904
11908
  t
11905
11909
  });
11906
11910
  }
@@ -11933,8 +11937,8 @@ var creator$a = {
11933
11937
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-1password/README.md"
11934
11938
  }
11935
11939
  },
11936
- create(context, options) {
11937
- const t = context.createTranslator(messages$9);
11940
+ create(context2, options) {
11941
+ const t = context2.createTranslator(messages$9);
11938
11942
  const normalizedOptions = {
11939
11943
  allows: options?.allows ?? []
11940
11944
  };
@@ -11954,7 +11958,7 @@ var creator$a = {
11954
11958
  continue;
11955
11959
  }
11956
11960
  const range = [index, index + matchString.length];
11957
- context.report({
11961
+ context2.report({
11958
11962
  message: t("OPS_TOKEN", {
11959
11963
  TOKEN: matchString
11960
11964
  }),
@@ -12036,7 +12040,7 @@ function isLikelyRealCredential(username, password) {
12036
12040
  return false;
12037
12041
  return true;
12038
12042
  }
12039
- function reportMongoDBConnectionString({ source, options, context, t }) {
12043
+ function reportMongoDBConnectionString({ source, options, context: context2, t }) {
12040
12044
  const MONGODB_PATTERN = /mongodb(?:\+srv)?:\/\/(?:(?<username>[^:\/\s]{1,100}):(?<password>[^@\/\s]{1,200})@)?(?<host>[^\/\s?]{1,100})(?:\/(?<database>[^?\s]{0,100}))?(?:\?(?<options>[^\s]{0,500}))?/gi;
12041
12045
  const results = source.content.matchAll(MONGODB_PATTERN);
12042
12046
  for (const result of results) {
@@ -12053,7 +12057,7 @@ function reportMongoDBConnectionString({ source, options, context, t }) {
12053
12057
  if (allowedResults.length > 0) {
12054
12058
  continue;
12055
12059
  }
12056
- context.report({
12060
+ context2.report({
12057
12061
  message: t("MongoDBConnection", {
12058
12062
  URI: match
12059
12063
  }),
@@ -12061,7 +12065,7 @@ function reportMongoDBConnectionString({ source, options, context, t }) {
12061
12065
  });
12062
12066
  }
12063
12067
  }
12064
- function reportMySQLConnectionString({ source, options, context, t }) {
12068
+ function reportMySQLConnectionString({ source, options, context: context2, t }) {
12065
12069
  const MYSQL_URI_PATTERN = /(?:jdbc:)?mysql(?:x)?:\/\/(?:(?<username>[^:\/\s]{1,100}):(?<password>[^@\/\s]{1,200})@)?(?<host>[^\/\s?]{1,100})(?:\/(?<database>[^?\s]{0,100}))?(?:\?(?<options>[^\s]{0,500}))?/gi;
12066
12070
  const results = source.content.matchAll(MYSQL_URI_PATTERN);
12067
12071
  for (const result of results) {
@@ -12078,7 +12082,7 @@ function reportMySQLConnectionString({ source, options, context, t }) {
12078
12082
  if (allowedResults.length > 0) {
12079
12083
  continue;
12080
12084
  }
12081
- context.report({
12085
+ context2.report({
12082
12086
  message: t("MySQLConnection", {
12083
12087
  URI: match
12084
12088
  }),
@@ -12086,7 +12090,7 @@ function reportMySQLConnectionString({ source, options, context, t }) {
12086
12090
  });
12087
12091
  }
12088
12092
  }
12089
- function reportPostgreSQLConnectionString({ source, options, context, t }) {
12093
+ function reportPostgreSQLConnectionString({ source, options, context: context2, t }) {
12090
12094
  const POSTGRESQL_URI_PATTERN = /postgres(?:ql)?:\/\/(?:(?<username>[^:\/\s]{1,100}):(?<password>[^@\/\s]{1,200})@)?(?<host>[^\/\s?]{1,100})(?:\/(?<database>[^?\s]{0,100}))?(?:\?(?<options>[^\s]{0,500}))?/gi;
12091
12095
  const results = source.content.matchAll(POSTGRESQL_URI_PATTERN);
12092
12096
  for (const result of results) {
@@ -12103,7 +12107,7 @@ function reportPostgreSQLConnectionString({ source, options, context, t }) {
12103
12107
  if (allowedResults.length > 0) {
12104
12108
  continue;
12105
12109
  }
12106
- context.report({
12110
+ context2.report({
12107
12111
  message: t("PostgreSQLConnection", {
12108
12112
  URI: match
12109
12113
  }),
@@ -12122,16 +12126,16 @@ var creator$9 = {
12122
12126
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-database-connection-string/README.md"
12123
12127
  }
12124
12128
  },
12125
- create(context, options) {
12129
+ create(context2, options) {
12126
12130
  const normalizedOptions = {
12127
12131
  allows: options.allows || []
12128
12132
  };
12129
- const t = context.createTranslator(messages$8);
12133
+ const t = context2.createTranslator(messages$8);
12130
12134
  return {
12131
12135
  file(source) {
12132
- reportMongoDBConnectionString({ source, options: normalizedOptions, context, t });
12133
- reportMySQLConnectionString({ source, options: normalizedOptions, context, t });
12134
- reportPostgreSQLConnectionString({ source, options: normalizedOptions, context, t });
12136
+ reportMongoDBConnectionString({ source, options: normalizedOptions, context: context2, t });
12137
+ reportMySQLConnectionString({ source, options: normalizedOptions, context: context2, t });
12138
+ reportPostgreSQLConnectionString({ source, options: normalizedOptions, context: context2, t });
12135
12139
  }
12136
12140
  };
12137
12141
  }
@@ -12164,8 +12168,8 @@ var creator$8 = {
12164
12168
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-hashicorp-vault/README.md"
12165
12169
  }
12166
12170
  },
12167
- create(context, options) {
12168
- const t = context.createTranslator(messages$7);
12171
+ create(context2, options) {
12172
+ const t = context2.createTranslator(messages$7);
12169
12173
  const normalizedOptions = {
12170
12174
  allows: options?.allows ?? []
12171
12175
  };
@@ -12179,7 +12183,7 @@ var creator$8 = {
12179
12183
  continue;
12180
12184
  }
12181
12185
  const range = [index, index + matchString.length];
12182
- context.report({
12186
+ context2.report({
12183
12187
  message: t(messageId, {
12184
12188
  TOKEN: matchString
12185
12189
  }),
@@ -12236,8 +12240,8 @@ var creator$7 = {
12236
12240
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-vercel/README.md"
12237
12241
  }
12238
12242
  },
12239
- create(context, options) {
12240
- const t = context.createTranslator(messages$6);
12243
+ create(context2, options) {
12244
+ const t = context2.createTranslator(messages$6);
12241
12245
  const normalizedOptions = {
12242
12246
  allows: options?.allows ?? []
12243
12247
  };
@@ -12255,7 +12259,7 @@ var creator$7 = {
12255
12259
  continue;
12256
12260
  }
12257
12261
  const range = [index, index + matchString.length];
12258
- context.report({
12262
+ context2.report({
12259
12263
  message: t(messageId, {
12260
12264
  ID: matchString
12261
12265
  }),
@@ -12283,8 +12287,8 @@ var creator$6 = {
12283
12287
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-databricks/README.md"
12284
12288
  }
12285
12289
  },
12286
- create(context, options) {
12287
- const t = context.createTranslator(messages$5);
12290
+ create(context2, options) {
12291
+ const t = context2.createTranslator(messages$5);
12288
12292
  const normalizedOptions = {
12289
12293
  allows: options?.allows ?? []
12290
12294
  };
@@ -12300,7 +12304,7 @@ var creator$6 = {
12300
12304
  continue;
12301
12305
  }
12302
12306
  const range = [index, index + matchString.length];
12303
- context.report({
12307
+ context2.report({
12304
12308
  message: t("DATABRICKS_PERSONAL_ACCESS_TOKEN", {
12305
12309
  ID: matchString
12306
12310
  }),
@@ -12317,7 +12321,7 @@ var messages$4 = {
12317
12321
  ja: (props) => `Docker Personal Access Token: ${props.TOKEN} \u304C\u307F\u3064\u304B\u308A\u307E\u3057\u305F`
12318
12322
  }
12319
12323
  };
12320
- function reportIfFoundDockerPAT({ source, options, context, t }) {
12324
+ function reportIfFoundDockerPAT({ source, options, context: context2, t }) {
12321
12325
  const DOCKER_PAT_PATTERN = new RegExp("(?<!\\p{L})dckr_pat_[a-zA-Z0-9_-]{27}(?![a-zA-Z0-9_-])", "gu");
12322
12326
  const results = source.content.matchAll(DOCKER_PAT_PATTERN);
12323
12327
  for (const result of results) {
@@ -12328,7 +12332,7 @@ function reportIfFoundDockerPAT({ source, options, context, t }) {
12328
12332
  if (allowedResults.length > 0) {
12329
12333
  continue;
12330
12334
  }
12331
- context.report({
12335
+ context2.report({
12332
12336
  message: t("DOCKER_PERSONAL_ACCESS_TOKEN", {
12333
12337
  TOKEN: match
12334
12338
  }),
@@ -12347,14 +12351,14 @@ var creator$5 = {
12347
12351
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-docker/README.md"
12348
12352
  }
12349
12353
  },
12350
- create(context, options) {
12351
- const t = context.createTranslator(messages$4);
12354
+ create(context2, options) {
12355
+ const t = context2.createTranslator(messages$4);
12352
12356
  const normalizedOptions = {
12353
12357
  allows: options.allows || []
12354
12358
  };
12355
12359
  return {
12356
12360
  file(source) {
12357
- reportIfFoundDockerPAT({ source, options: normalizedOptions, context, t });
12361
+ reportIfFoundDockerPAT({ source, options: normalizedOptions, context: context2, t });
12358
12362
  }
12359
12363
  };
12360
12364
  }
@@ -12376,8 +12380,8 @@ var creator$4 = {
12376
12380
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-figma/README.md"
12377
12381
  }
12378
12382
  },
12379
- create(context, options) {
12380
- const t = context.createTranslator(messages$3);
12383
+ create(context2, options) {
12384
+ const t = context2.createTranslator(messages$3);
12381
12385
  const normalizedOptions = {
12382
12386
  allows: options?.allows ?? []
12383
12387
  };
@@ -12393,7 +12397,7 @@ var creator$4 = {
12393
12397
  continue;
12394
12398
  }
12395
12399
  const range = [index, index + matchString.length];
12396
- context.report({
12400
+ context2.report({
12397
12401
  message: t("FIGMA_PERSONAL_ACCESS_TOKEN", {
12398
12402
  ID: matchString
12399
12403
  }),
@@ -12424,7 +12428,7 @@ var messageIdMap = {
12424
12428
  cfat: "CLOUDFLARE_ACCOUNT_API_TOKEN"
12425
12429
  };
12426
12430
  var CLOUDFLARE_TOKEN_PATTERN = new RegExp("(?<!\\p{L})(?<prefix>cfk|cfut|cfat)_[A-Za-z0-9]{40}[0-9a-f]{8}(?![A-Za-z0-9])", "gu");
12427
- function reportIfFound({ source, options, context, t }) {
12431
+ function reportIfFound({ source, options, context: context2, t }) {
12428
12432
  const results = source.content.matchAll(CLOUDFLARE_TOKEN_PATTERN);
12429
12433
  for (const result of results) {
12430
12434
  const index = result.index ?? 0;
@@ -12438,7 +12442,7 @@ function reportIfFound({ source, options, context, t }) {
12438
12442
  if (allowedResults.length > 0) {
12439
12443
  continue;
12440
12444
  }
12441
- context.report({
12445
+ context2.report({
12442
12446
  message: t(messageIdMap[prefix], {
12443
12447
  TOKEN: match
12444
12448
  }),
@@ -12457,14 +12461,14 @@ var creator$3 = {
12457
12461
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-cloudflare/README.md"
12458
12462
  }
12459
12463
  },
12460
- create(context, options) {
12461
- const t = context.createTranslator(messages$2);
12464
+ create(context2, options) {
12465
+ const t = context2.createTranslator(messages$2);
12462
12466
  const normalizedOptions = {
12463
12467
  allows: options.allows ?? []
12464
12468
  };
12465
12469
  return {
12466
12470
  file(source) {
12467
- reportIfFound({ source, options: normalizedOptions, context, t });
12471
+ reportIfFound({ source, options: normalizedOptions, context: context2, t });
12468
12472
  }
12469
12473
  };
12470
12474
  }
@@ -12513,8 +12517,8 @@ var creator$2 = {
12513
12517
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-tailscale/README.md"
12514
12518
  }
12515
12519
  },
12516
- create(context, options) {
12517
- const t = context.createTranslator(messages$1);
12520
+ create(context2, options) {
12521
+ const t = context2.createTranslator(messages$1);
12518
12522
  const normalizedOptions = {
12519
12523
  allows: options.allows ?? []
12520
12524
  };
@@ -12532,7 +12536,7 @@ var creator$2 = {
12532
12536
  continue;
12533
12537
  }
12534
12538
  const messageId = messageIdByType[type] ?? "TAILSCALE_KEY";
12535
- context.report({
12539
+ context2.report({
12536
12540
  message: t(messageId, {
12537
12541
  KEY: matchString
12538
12542
  }),
@@ -12694,8 +12698,8 @@ var creator$1 = {
12694
12698
  url: "https://github.com/secretlint/secretlint/blob/master/packages/%40secretlint/secretlint-rule-filter-comments/README.md"
12695
12699
  }
12696
12700
  },
12697
- create(context) {
12698
- const t = context.createTranslator(messages);
12701
+ create(context2) {
12702
+ const t = context2.createTranslator(messages);
12699
12703
  return {
12700
12704
  file(source) {
12701
12705
  const state = new CommentState(source);
@@ -12712,7 +12716,7 @@ var creator$1 = {
12712
12716
  }
12713
12717
  }
12714
12718
  state.getIgnoringMessages().forEach((message) => {
12715
- context.ignore({
12719
+ context2.ignore({
12716
12720
  message: t("IGNORE_MESSAGE"),
12717
12721
  range: [message.startIndex, message.endIndex],
12718
12722
  targetRuleId: message.ruleId
@@ -15813,7 +15817,7 @@ function putProp2(target, key, value) {
15813
15817
  else
15814
15818
  target[key] = value;
15815
15819
  }
15816
- function mirrorShape2(target, source, keys, wrap) {
15820
+ function mirrorShape2(target, source, keys, wrap2) {
15817
15821
  const raw = sourceShape2(source);
15818
15822
  for (const key of keys) {
15819
15823
  const desc = Object.getOwnPropertyDescriptor(raw, key);
@@ -15822,10 +15826,10 @@ function mirrorShape2(target, source, keys, wrap) {
15822
15826
  if (desc.get) {
15823
15827
  deferProp2(target, key, () => {
15824
15828
  const value = source._zod.def.shape[key];
15825
- return wrap ? wrap(value, key) : value;
15829
+ return wrap2 ? wrap2(value, key) : value;
15826
15830
  });
15827
15831
  } else
15828
- putProp2(target, key, wrap ? wrap(desc.value, key) : desc.value);
15832
+ putProp2(target, key, wrap2 ? wrap2(desc.value, key) : desc.value);
15829
15833
  }
15830
15834
  }
15831
15835
  function mirrorProps2(target, source) {
@@ -15850,10 +15854,10 @@ function mergeDefs2(...defs) {
15850
15854
  function cloneDef2(schema) {
15851
15855
  return mergeDefs2(schema._zod.def);
15852
15856
  }
15853
- function getElementAtPath2(obj, path30) {
15854
- if (!path30)
15857
+ function getElementAtPath2(obj, path31) {
15858
+ if (!path31)
15855
15859
  return obj;
15856
- return path30.reduce((acc, key) => acc?.[key], obj);
15860
+ return path31.reduce((acc, key) => acc?.[key], obj);
15857
15861
  }
15858
15862
  function promiseAllObject2(promisesObj) {
15859
15863
  const keys = Object.keys(promisesObj);
@@ -16193,11 +16197,11 @@ function explicitlyAborted2(x, startIndex = 0) {
16193
16197
  }
16194
16198
  return false;
16195
16199
  }
16196
- function prefixIssues2(path30, issues) {
16200
+ function prefixIssues2(path31, issues) {
16197
16201
  return issues.map((iss) => {
16198
16202
  var _a5;
16199
16203
  (_a5 = iss).path ?? (_a5.path = []);
16200
- iss.path.unshift(path30);
16204
+ iss.path.unshift(path31);
16201
16205
  return iss;
16202
16206
  });
16203
16207
  }
@@ -16655,16 +16659,16 @@ function flattenError2(error3, mapper = (issue3) => issue3.message) {
16655
16659
  }
16656
16660
  function formatError2(error3, mapper = (issue3) => issue3.message) {
16657
16661
  const fieldErrors = { _errors: [] };
16658
- const processError = (error4, path30 = []) => {
16662
+ const processError = (error4, path31 = []) => {
16659
16663
  for (const issue3 of error4.issues) {
16660
16664
  if (issue3.code === "invalid_union" && issue3.errors.length) {
16661
- issue3.errors.map((issues) => processError({ issues }, [...path30, ...issue3.path]));
16665
+ issue3.errors.map((issues) => processError({ issues }, [...path31, ...issue3.path]));
16662
16666
  } else if (issue3.code === "invalid_key") {
16663
- processError({ issues: issue3.issues }, [...path30, ...issue3.path]);
16667
+ processError({ issues: issue3.issues }, [...path31, ...issue3.path]);
16664
16668
  } else if (issue3.code === "invalid_element") {
16665
- processError({ issues: issue3.issues }, [...path30, ...issue3.path]);
16669
+ processError({ issues: issue3.issues }, [...path31, ...issue3.path]);
16666
16670
  } else {
16667
- const fullpath = [...path30, ...issue3.path];
16671
+ const fullpath = [...path31, ...issue3.path];
16668
16672
  if (fullpath.length === 0) {
16669
16673
  fieldErrors._errors.push(mapper(issue3));
16670
16674
  } else {
@@ -16672,9 +16676,9 @@ function formatError2(error3, mapper = (issue3) => issue3.message) {
16672
16676
  let i = 0;
16673
16677
  while (i < fullpath.length) {
16674
16678
  const el = fullpath[i];
16675
- const terminal = i === fullpath.length - 1;
16679
+ const terminal2 = i === fullpath.length - 1;
16676
16680
  if (el === "_errors") {
16677
- if (terminal)
16681
+ if (terminal2)
16678
16682
  curr._errors.push(mapper(issue3));
16679
16683
  i++;
16680
16684
  continue;
@@ -16688,7 +16692,7 @@ function formatError2(error3, mapper = (issue3) => issue3.message) {
16688
16692
  });
16689
16693
  }
16690
16694
  const node3 = curr[el];
16691
- if (terminal) {
16695
+ if (terminal2) {
16692
16696
  node3._errors.push(mapper(issue3));
16693
16697
  }
16694
16698
  curr = node3;
@@ -24059,6 +24063,53 @@ async function backgroundServiceDefinition(source) {
24059
24063
  throw error3;
24060
24064
  }
24061
24065
  }
24066
+ function decodeXml(value) {
24067
+ return value.replace(/&(amp|lt|gt|quot|apos);/g, (entity) => {
24068
+ const entities = {
24069
+ "&amp;": "&",
24070
+ "&lt;": "<",
24071
+ "&gt;": ">",
24072
+ "&quot;": '"',
24073
+ "&apos;": "'"
24074
+ };
24075
+ return entities[entity];
24076
+ });
24077
+ }
24078
+ function serviceDataDirectory(definition, platform) {
24079
+ let directory;
24080
+ if (platform === "darwin") {
24081
+ const value = /<string>--data-directory<\/string>\s*<string>([^<]*)<\/string>/.exec(
24082
+ definition
24083
+ )?.[1];
24084
+ if (value !== void 0) directory = decodeXml(value);
24085
+ } else if (platform === "linux") {
24086
+ const value = /^ExecStart=.*?"--data-directory" "((?:\\.|[^"\\])*)"\s*$/m.exec(
24087
+ definition
24088
+ )?.[1];
24089
+ if (value !== void 0)
24090
+ directory = value.replace(/\\([\\"])/g, "$1").replaceAll("%%", "%");
24091
+ } else if (platform === "win32") {
24092
+ const encoded = /-EncodedCommand ([A-Za-z0-9+/=]+)/.exec(definition)?.[1];
24093
+ const script = encoded === void 0 ? "" : Buffer.from(encoded, "base64").toString("utf16le");
24094
+ const args = /\$start\.Arguments = '((?:''|[^'])*)'/.exec(script)?.[1]?.replaceAll("''", "'");
24095
+ const value = /"--data-directory" "(.*)"$/.exec(args ?? "")?.[1];
24096
+ if (value !== void 0)
24097
+ directory = value.replace(
24098
+ /(\\+)"/g,
24099
+ (_, slashes) => `${slashes.slice(0, (slashes.length - 1) / 2)}"`
24100
+ ).replace(
24101
+ /(\\+)$/,
24102
+ (_, slashes) => slashes.slice(0, slashes.length / 2)
24103
+ );
24104
+ }
24105
+ if (!directory || !(platform === "win32" ? path20.win32 : path20.posix).isAbsolute(directory))
24106
+ throw new Error("Could not read the collector service data directory.");
24107
+ return directory;
24108
+ }
24109
+ async function backgroundServiceDataDirectory(source) {
24110
+ const definition = await backgroundServiceDefinition(source);
24111
+ return definition === null ? null : serviceDataDirectory(definition, process.platform);
24112
+ }
24062
24113
  async function installedServiceSources() {
24063
24114
  const definitions = await Promise.all(
24064
24115
  COLLECTOR_SOURCES2.map(backgroundServiceDefinition)
@@ -24195,9 +24246,13 @@ async function uninstallCursorHooks(cursorHome, dataDirectory2) {
24195
24246
  }
24196
24247
 
24197
24248
  // src/logger.ts
24198
- configureCollectorLogging(() => ({
24249
+ var context = () => ({
24199
24250
  runtimeVersion: process.env.ITERATION_RUNTIME_VERSION ?? null
24200
- }));
24251
+ });
24252
+ configureCollectorLogging(context);
24253
+ function silenceCollectorLogs() {
24254
+ configureCollectorLogging(context, () => void 0);
24255
+ }
24201
24256
 
24202
24257
  // src/turn-summary.ts
24203
24258
  import { execFile as execFileCallback7 } from "node:child_process";
@@ -24713,6 +24768,9 @@ var consentSchema = object3({
24713
24768
  function consentPath() {
24714
24769
  return path24.join(os8.homedir(), ".config", "iteration", "auto-connect.json");
24715
24770
  }
24771
+ async function removeMachineConsent() {
24772
+ await fs19.rm(consentPath(), { force: true });
24773
+ }
24716
24774
  async function detectedSources(sourceHomes) {
24717
24775
  const detected = [];
24718
24776
  for (const source of COLLECTOR_SOURCES2) {
@@ -24926,8 +24984,157 @@ async function connectedConfig(source) {
24926
24984
 
24927
24985
  // src/clerk-device-auth.ts
24928
24986
  import { execFile as execFile8 } from "node:child_process";
24929
- import { createInterface } from "node:readline/promises";
24930
24987
  import { promisify as promisify8 } from "node:util";
24988
+
24989
+ // src/terminal.ts
24990
+ import { createInterface } from "node:readline/promises";
24991
+ import { stripVTControlCharacters, styleText } from "node:util";
24992
+ var MEASURE = 80;
24993
+ var INDENT = " ";
24994
+ var UNICODE_SYMBOLS = {
24995
+ brand: "\u25C6",
24996
+ success: "\u2713",
24997
+ warning: "!",
24998
+ failure: "\u2717",
24999
+ question: "?",
25000
+ on: "\u25CF",
25001
+ off: "\u25CB",
25002
+ spinner: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"]
25003
+ };
25004
+ var BASIC_SYMBOLS = {
25005
+ brand: "*",
25006
+ success: "\u221A",
25007
+ warning: "!",
25008
+ failure: "\xD7",
25009
+ question: "?",
25010
+ on: "*",
25011
+ off: "-",
25012
+ spinner: ["-", "\\", "|", "/"]
25013
+ };
25014
+ var TONE_FORMAT = {
25015
+ success: "green",
25016
+ warning: "yellow",
25017
+ failure: "red",
25018
+ muted: "dim"
25019
+ };
25020
+ function supportsUnicode(env) {
25021
+ if (process.platform !== "win32") return env.TERM !== "linux";
25022
+ return env.WT_SESSION !== void 0 || env.TERM_PROGRAM === "vscode" || env.TERMINAL_EMULATOR === "JetBrains-JediTerm" || env.ConEmuTask === "{cmd::Cmder}" || env.TERM === "xterm-256color" || env.TERM === "alacritty";
25023
+ }
25024
+ function terminalFor(stream, env = process.env) {
25025
+ const style = (format) => (text) => styleText(format, text, { stream });
25026
+ return {
25027
+ width: stream.isTTY && stream.columns > 0 ? Math.min(stream.columns, MEASURE) : MEASURE,
25028
+ symbols: supportsUnicode(env) ? UNICODE_SYMBOLS : BASIC_SYMBOLS,
25029
+ bold: style("bold"),
25030
+ dim: style("dim"),
25031
+ link: style("underline"),
25032
+ tone: (tone, text) => style(TONE_FORMAT[tone])(text)
25033
+ };
25034
+ }
25035
+ function safeWorkspaceName(value) {
25036
+ const cleaned = value?.split("").map((character) => {
25037
+ const code = character.charCodeAt(0);
25038
+ return code < 32 || code >= 127 && code <= 159 ? " " : character;
25039
+ }).join("").replace(/\s+/g, " ").trim();
25040
+ return cleaned === void 0 || cleaned === "" ? null : cleaned;
25041
+ }
25042
+ function visibleWidth(text) {
25043
+ return stripVTControlCharacters(text).length;
25044
+ }
25045
+ function padEnd(text, width) {
25046
+ return text + " ".repeat(Math.max(0, width - visibleWidth(text)));
25047
+ }
25048
+ function brand(terminal2, workspaceName = null) {
25049
+ const name = safeWorkspaceName(workspaceName);
25050
+ return `${terminal2.bold(`${terminal2.symbols.brand} Iteration`)}${name === null ? "" : `${terminal2.dim(" \xB7 ")}${name}`}`;
25051
+ }
25052
+ function wrap(terminal2, text, options = {}) {
25053
+ const indent = options.indent ?? INDENT;
25054
+ const style = options.style ?? ((line) => line);
25055
+ const lines = [];
25056
+ let prefix = options.first ?? indent;
25057
+ let words = [];
25058
+ let width = visibleWidth(prefix);
25059
+ const flush = () => {
25060
+ lines.push(`${prefix}${style(words.join(" "))}`.trimEnd());
25061
+ prefix = indent;
25062
+ words = [];
25063
+ width = visibleWidth(indent);
25064
+ };
25065
+ for (const word of text.split(" ")) {
25066
+ const wordWidth = visibleWidth(word);
25067
+ if (words.length > 0 && width + 1 + wordWidth > terminal2.width) flush();
25068
+ if (words.length === 0 && word === "" && lines.length > 0) continue;
25069
+ width += (words.length > 0 ? 1 : 0) + wordWidth;
25070
+ words.push(word);
25071
+ }
25072
+ flush();
25073
+ return lines.join("\n");
25074
+ }
25075
+ function mark(terminal2, kind, text, indent = "") {
25076
+ const tone = kind === "question" ? "success" : kind;
25077
+ return wrap(terminal2, text, {
25078
+ first: `${indent}${terminal2.tone(tone, terminal2.symbols[kind])} `,
25079
+ indent: `${indent}${INDENT}`
25080
+ });
25081
+ }
25082
+ function rows(terminal2, entries2, indent = INDENT) {
25083
+ const labelWidth = Math.max(
25084
+ 0,
25085
+ ...entries2.map(([label2]) => visibleWidth(label2))
25086
+ );
25087
+ const hanging = " ".repeat(visibleWidth(indent) + labelWidth + 2);
25088
+ return entries2.map(
25089
+ ([label2, value]) => wrap(terminal2, value, {
25090
+ first: `${indent}${padEnd(label2, labelWidth + 2)}`,
25091
+ indent: hanging
25092
+ })
25093
+ ).join("\n");
25094
+ }
25095
+ var SPINNER_INTERVAL_MS = 80;
25096
+ function startSpinner(stream, terminal2, text) {
25097
+ if (!stream.isTTY) {
25098
+ stream.write(`${text}
25099
+ `);
25100
+ return () => void 0;
25101
+ }
25102
+ const frames = terminal2.symbols.spinner;
25103
+ let frame = 0;
25104
+ const draw = () => {
25105
+ stream.cursorTo(0);
25106
+ stream.clearLine(1);
25107
+ stream.write(`${terminal2.dim(frames[frame % frames.length])} ${text}`);
25108
+ frame += 1;
25109
+ };
25110
+ draw();
25111
+ const timer = setInterval(draw, SPINNER_INTERVAL_MS);
25112
+ timer.unref();
25113
+ return () => {
25114
+ clearInterval(timer);
25115
+ stream.cursorTo(0);
25116
+ stream.clearLine(0);
25117
+ };
25118
+ }
25119
+ async function ask(terminal2, question) {
25120
+ const prompt = createInterface({
25121
+ input: process.stdin,
25122
+ output: process.stdout
25123
+ });
25124
+ try {
25125
+ return await prompt.question(
25126
+ `${terminal2.tone("success", terminal2.symbols.question)} ${question} `
25127
+ );
25128
+ } catch (error3) {
25129
+ if (!(error3 instanceof Error && error3.name === "AbortError")) throw error3;
25130
+ process.stdout.write("\n");
25131
+ return null;
25132
+ } finally {
25133
+ prompt.close();
25134
+ }
25135
+ }
25136
+
25137
+ // src/clerk-device-auth.ts
24931
25138
  var execFileAsync = promisify8(execFile8);
24932
25139
  var serverAuthConfigSchema = object3({
24933
25140
  issuerUrl: url(),
@@ -25031,7 +25238,11 @@ $start.UseShellExecute = $true
25031
25238
  await execFileAsync("xdg-open", [url2], { timeout: 5e3 });
25032
25239
  else await execFileAsync("open", [url2], { timeout: 5e3 });
25033
25240
  } catch {
25034
- process.stdout.write("Open the verification link in your browser.\n");
25241
+ const terminal2 = terminalFor(process.stdout);
25242
+ process.stdout.write(
25243
+ `${mark(terminal2, "warning", "Your browser did not open. Open the link above to sign in.")}
25244
+ `
25245
+ );
25035
25246
  }
25036
25247
  }
25037
25248
  function delay4(milliseconds) {
@@ -25111,17 +25322,39 @@ async function clerkDeviceSignIn(configuration) {
25111
25322
  configuration.clientId
25112
25323
  );
25113
25324
  const verificationUrl = challenge.verification_uri_complete ?? challenge.verification_uri;
25325
+ const terminal2 = terminalFor(process.stdout);
25114
25326
  process.stdout.write(
25115
- "Sign in to Iteration in your browser and confirm this code.\nCode: " + challenge.user_code + "\nLink: " + verificationUrl + "\n"
25327
+ [
25328
+ "",
25329
+ wrap(
25330
+ terminal2,
25331
+ "Sign in to Iteration in your browser and confirm this code",
25332
+ { style: terminal2.bold }
25333
+ ),
25334
+ rows(terminal2, [
25335
+ ["Code", terminal2.bold(challenge.user_code)],
25336
+ ["Link", terminal2.link(verificationUrl)]
25337
+ ]),
25338
+ ""
25339
+ ].join("\n")
25116
25340
  );
25117
25341
  await openBrowser(verificationUrl);
25118
- return pollForAccessToken(
25119
- endpoints.tokenUrl,
25120
- configuration.clientId,
25121
- challenge.device_code,
25122
- challenge.expires_in,
25123
- challenge.interval
25342
+ const stopSpinner = startSpinner(
25343
+ process.stdout,
25344
+ terminal2,
25345
+ "Waiting for you to confirm in your browser\u2026"
25124
25346
  );
25347
+ try {
25348
+ return await pollForAccessToken(
25349
+ endpoints.tokenUrl,
25350
+ configuration.clientId,
25351
+ challenge.device_code,
25352
+ challenge.expires_in,
25353
+ challenge.interval
25354
+ );
25355
+ } finally {
25356
+ stopSpinner();
25357
+ }
25125
25358
  }
25126
25359
  async function enrollDevice(endpoint, accessToken, deviceName, organizationId, source) {
25127
25360
  const body = { deviceName };
@@ -25151,44 +25384,49 @@ async function enrollDevice(endpoint, accessToken, deviceName, organizationId, s
25151
25384
  );
25152
25385
  }
25153
25386
  async function chooseOrganization(organizations, hasMore) {
25154
- process.stdout.write("Choose an Iteration workspace for this collector:\n");
25155
- for (const [index, organization] of organizations.entries()) {
25156
- process.stdout.write(
25157
- index + 1 + ". " + organization.name + " (" + organization.id + ")\n"
25158
- );
25159
- }
25160
- if (hasMore) {
25161
- process.stdout.write(
25162
- "More workspaces exist; enter an organization ID to choose one not listed.\n"
25163
- );
25164
- }
25387
+ const terminal2 = terminalFor(process.stdout);
25388
+ process.stdout.write(
25389
+ [
25390
+ "",
25391
+ wrap(terminal2, "Choose a workspace for this computer", {
25392
+ style: terminal2.bold
25393
+ }),
25394
+ rows(
25395
+ terminal2,
25396
+ organizations.map((organization2, index) => [
25397
+ String(index + 1),
25398
+ `${safeWorkspaceName(organization2.name) ?? "Unnamed workspace"} ${terminal2.dim(organization2.id)}`
25399
+ ]),
25400
+ " "
25401
+ ),
25402
+ ...hasMore ? [
25403
+ wrap(
25404
+ terminal2,
25405
+ "More workspaces exist; enter a workspace ID to choose one not listed."
25406
+ )
25407
+ ] : [],
25408
+ ""
25409
+ ].join("\n")
25410
+ );
25165
25411
  if (process.stdin.isTTY !== true) {
25166
25412
  throw new Error("Run iteration interactively or pass --workspace.");
25167
25413
  }
25168
- const prompt = createInterface({
25169
- input: process.stdin,
25170
- output: process.stdout
25171
- });
25172
- try {
25173
- const answer = await prompt.question(
25174
- "Workspace number or organization ID: "
25414
+ const answer = await ask(terminal2, terminal2.bold("Workspace number or ID"));
25415
+ if (answer === null)
25416
+ throw new Error(
25417
+ "No workspace was chosen. Run iteration connect to try again."
25175
25418
  );
25176
- const id = uuid5().safeParse(answer.trim());
25177
- if (id.success) return id.data;
25178
- const selection = coerce_exports.number().int().min(1).max(organizations.length).safeParse(answer.trim());
25179
- if (!selection.success) {
25180
- throw new Error(
25181
- "Choose a listed number or enter a valid organization ID."
25182
- );
25183
- }
25184
- const organization = organizations[selection.data - 1];
25185
- if (organization === void 0) {
25186
- throw new Error("The selected workspace is not available.");
25187
- }
25188
- return organization.id;
25189
- } finally {
25190
- prompt.close();
25419
+ const id = uuid5().safeParse(answer.trim());
25420
+ if (id.success) return id.data;
25421
+ const selection = coerce_exports.number().int().min(1).max(organizations.length).safeParse(answer.trim());
25422
+ if (!selection.success) {
25423
+ throw new Error("Choose a listed number or enter a valid workspace ID.");
25191
25424
  }
25425
+ const organization = organizations[selection.data - 1];
25426
+ if (organization === void 0) {
25427
+ throw new Error("The selected workspace is not available.");
25428
+ }
25429
+ return organization.id;
25192
25430
  }
25193
25431
  async function authenticateAndEnrollCollector(endpoint, deviceNameValue, organizationId, source = "codex") {
25194
25432
  const deviceName = string5().trim().min(1).max(160).safeParse(deviceNameValue);
@@ -25289,6 +25527,147 @@ async function importSourceHistory(config3, paths, confirmed, control = backgrou
25289
25527
  return { imported: true, size, backgroundRunning: wasRunning };
25290
25528
  }
25291
25529
 
25530
+ // src/logout.ts
25531
+ import { randomUUID as randomUUID3 } from "node:crypto";
25532
+ import { promises as fs20 } from "node:fs";
25533
+ import os9 from "node:os";
25534
+ import path26 from "node:path";
25535
+ async function pendingDirectories(filename) {
25536
+ let contents;
25537
+ try {
25538
+ contents = await fs20.readFile(filename, "utf8");
25539
+ } catch (error3) {
25540
+ if (error3 instanceof Error && "code" in error3 && error3.code === "ENOENT")
25541
+ return [];
25542
+ throw error3;
25543
+ }
25544
+ const parsed = array2(string5().refine(path26.isAbsolute)).max(64).safeParse(JSON.parse(contents));
25545
+ if (!parsed.success)
25546
+ throw new Error("Pending logout directories are invalid.");
25547
+ return parsed.data;
25548
+ }
25549
+ async function savePendingDirectories(filename, directories) {
25550
+ await ensurePrivateDirectory(path26.dirname(filename));
25551
+ const temporary = `${filename}.${process.pid}.tmp`;
25552
+ await fs20.writeFile(temporary, JSON.stringify([...directories]), {
25553
+ mode: 384
25554
+ });
25555
+ await fs20.rename(temporary, filename);
25556
+ }
25557
+ async function clearConnection(directory) {
25558
+ const paths = collectorPaths(directory);
25559
+ let names;
25560
+ try {
25561
+ names = await fs20.readdir(directory);
25562
+ } catch (error3) {
25563
+ if (error3 instanceof Error && "code" in error3 && error3.code === "ENOENT")
25564
+ return;
25565
+ throw error3;
25566
+ }
25567
+ const release = await waitForCollectorLock(paths);
25568
+ try {
25569
+ for (const name of names)
25570
+ if (/^config\.json\.\d+\.tmp$/.test(name))
25571
+ await fs20.rm(path26.join(directory, name), { force: true });
25572
+ if (!names.includes(path26.basename(paths.config))) return;
25573
+ const config3 = await loadConfig(paths);
25574
+ if (config3.destination === "vault")
25575
+ throw new Error("This directory belongs to Trace Vault, not Iteration.");
25576
+ if ("cursorHome" in config3)
25577
+ await uninstallCursorHooks(config3.cursorHome, config3.dataDirectory);
25578
+ else await uninstallTurnSummary(config3);
25579
+ const retained = [
25580
+ paths.state,
25581
+ paths.outbox,
25582
+ paths.redactionMarker,
25583
+ paths.historyBackfill,
25584
+ paths.health,
25585
+ ...[
25586
+ "cursor-hooks",
25587
+ "cursor-hook-failure.json",
25588
+ "claude-git",
25589
+ "turn-summary",
25590
+ "codex-billing-sync.json",
25591
+ "cursor-billing-sync.json"
25592
+ ].map((name) => path26.join(directory, name))
25593
+ ];
25594
+ const archive = path26.join(directory, "logged-out", randomUUID3());
25595
+ await ensurePrivateDirectory(archive);
25596
+ for (const filename of retained) {
25597
+ try {
25598
+ await fs20.rename(filename, path26.join(archive, path26.basename(filename)));
25599
+ } catch (error3) {
25600
+ if (!(error3 instanceof Error && "code" in error3 && error3.code === "ENOENT"))
25601
+ throw error3;
25602
+ }
25603
+ }
25604
+ await fs20.rm(paths.config);
25605
+ } finally {
25606
+ await release();
25607
+ }
25608
+ }
25609
+ async function logout(extraDirectory) {
25610
+ requireCollectorPlatform();
25611
+ const pending = path26.join(
25612
+ os9.homedir(),
25613
+ ".config",
25614
+ "iteration",
25615
+ "logout-pending.json"
25616
+ );
25617
+ const directories = /* @__PURE__ */ new Set([
25618
+ ...COLLECTOR_SOURCES2.map(defaultCollectorDirectory),
25619
+ ...await pendingDirectories(pending)
25620
+ ]);
25621
+ if (extraDirectory !== void 0)
25622
+ directories.add(path26.resolve(extraDirectory));
25623
+ const failures = [];
25624
+ try {
25625
+ await removeMachineConsent();
25626
+ } catch (error3) {
25627
+ failures.push(
25628
+ `Automatic connection approval: ${error3 instanceof Error ? error3.message : "Could not remove approval."}`
25629
+ );
25630
+ }
25631
+ const unreadableServices = /* @__PURE__ */ new Set();
25632
+ for (const source of COLLECTOR_SOURCES2) {
25633
+ try {
25634
+ const directory = await backgroundServiceDataDirectory(source);
25635
+ if (directory !== null) directories.add(directory);
25636
+ } catch (error3) {
25637
+ unreadableServices.add(source);
25638
+ failures.push(
25639
+ `${source}: ${error3 instanceof Error ? error3.message : "Could not inspect collector startup."}`
25640
+ );
25641
+ }
25642
+ }
25643
+ await savePendingDirectories(pending, directories);
25644
+ for (const source of COLLECTOR_SOURCES2) {
25645
+ if (unreadableServices.has(source)) continue;
25646
+ try {
25647
+ await uninstallBackgroundService(source);
25648
+ } catch (error3) {
25649
+ failures.push(
25650
+ `${source}: ${error3 instanceof Error ? error3.message : "Could not stop collector startup."}`
25651
+ );
25652
+ }
25653
+ }
25654
+ for (const directory of directories) {
25655
+ try {
25656
+ await clearConnection(directory);
25657
+ } catch (error3) {
25658
+ failures.push(
25659
+ `${directory}: ${error3 instanceof Error ? error3.message : "Could not clear the collector connection."}`
25660
+ );
25661
+ }
25662
+ }
25663
+ if (failures.length > 0)
25664
+ throw new Error(
25665
+ `Logout did not finish. Resolve these errors and run iteration logout again:
25666
+ ${failures.join("\n")}`
25667
+ );
25668
+ await fs20.rm(pending);
25669
+ }
25670
+
25292
25671
  // src/runtime-services.ts
25293
25672
  async function refreshBackgroundServices(restart) {
25294
25673
  const refreshed = [];
@@ -25317,8 +25696,8 @@ import { setTimeout as delay5 } from "node:timers/promises";
25317
25696
 
25318
25697
  // src/codex-billing.ts
25319
25698
  import { createHash as createHash7 } from "node:crypto";
25320
- import { promises as fs20 } from "node:fs";
25321
- import path26 from "node:path";
25699
+ import { promises as fs21 } from "node:fs";
25700
+ import path27 from "node:path";
25322
25701
  var TASK_USAGE_URL = "https://chatgpt.com/backend-api/wham/usage/thread_usage/query_v2";
25323
25702
  var UUID2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
25324
25703
  var DAY_MS = 24 * 60 * 60 * 1e3;
@@ -25370,7 +25749,7 @@ function fingerprint(value) {
25370
25749
  async function readAuth(codexHome) {
25371
25750
  let contents;
25372
25751
  try {
25373
- contents = await fs20.readFile(path26.join(codexHome, "auth.json"), "utf8");
25752
+ contents = await fs21.readFile(path27.join(codexHome, "auth.json"), "utf8");
25374
25753
  } catch (error3) {
25375
25754
  if (error3 instanceof Error && "code" in error3 && error3.code === "ENOENT")
25376
25755
  return {
@@ -25405,7 +25784,7 @@ async function readAuth(codexHome) {
25405
25784
  async function readState(filename) {
25406
25785
  let contents;
25407
25786
  try {
25408
- contents = await fs20.readFile(filename, "utf8");
25787
+ contents = await fs21.readFile(filename, "utf8");
25409
25788
  } catch (error3) {
25410
25789
  if (error3 instanceof Error && "code" in error3 && error3.code === "ENOENT")
25411
25790
  return null;
@@ -25427,7 +25806,7 @@ async function readState(filename) {
25427
25806
  }
25428
25807
  async function saveState2(filename, state) {
25429
25808
  const temporary = `${filename}.${process.pid}.tmp`;
25430
- const handle = await fs20.open(temporary, "w", 384);
25809
+ const handle = await fs21.open(temporary, "w", 384);
25431
25810
  try {
25432
25811
  await handle.writeFile(`${JSON.stringify(state)}
25433
25812
  `);
@@ -25435,11 +25814,11 @@ async function saveState2(filename, state) {
25435
25814
  } finally {
25436
25815
  await handle.close();
25437
25816
  }
25438
- await fs20.rename(temporary, filename);
25817
+ await fs21.rename(temporary, filename);
25439
25818
  }
25440
25819
  async function localThread(filename) {
25441
- const stat = await fs20.stat(filename);
25442
- const handle = await fs20.open(filename, "r");
25820
+ const stat = await fs21.stat(filename);
25821
+ const handle = await fs21.open(filename, "r");
25443
25822
  let header = null;
25444
25823
  try {
25445
25824
  const buffer = Buffer.alloc(64 * 1024);
@@ -25539,9 +25918,9 @@ function parseCodexAuthLog(threadId, body) {
25539
25918
  return { threadId, turnId: turn[1], mode };
25540
25919
  }
25541
25920
  async function localAuthTurns(codexHome, modelProviders) {
25542
- const filename = path26.join(codexHome, "logs_2.sqlite");
25921
+ const filename = path27.join(codexHome, "logs_2.sqlite");
25543
25922
  try {
25544
- await fs20.access(filename);
25923
+ await fs21.access(filename);
25545
25924
  } catch (error3) {
25546
25925
  if (error3 instanceof Error && "code" in error3 && error3.code === "ENOENT")
25547
25926
  return [];
@@ -25560,10 +25939,10 @@ async function localAuthTurns(codexHome, modelProviders) {
25560
25939
  feedback_log_body: string5().nullable()
25561
25940
  });
25562
25941
  try {
25563
- const rows = database.prepare(
25942
+ const rows2 = database.prepare(
25564
25943
  "SELECT thread_id, feedback_log_body FROM logs WHERE target = 'feedback_tags' AND feedback_log_body LIKE '%auth_mode=Some(%'"
25565
25944
  ).iterate();
25566
- for (const raw of rows) {
25945
+ for (const raw of rows2) {
25567
25946
  const row = logRowSchema.safeParse(raw);
25568
25947
  if (!row.success)
25569
25948
  throw new Error("Codex's local log row has an invalid shape.");
@@ -25634,7 +26013,7 @@ async function queryTaskUsage(tasks, accessToken, accountId, signal) {
25634
26013
  }
25635
26014
  async function syncCodexBilling(config3, fetcher = collectorFetch, signal) {
25636
26015
  const auth = await readAuth(config3.codexHome);
25637
- const stateFile = path26.join(config3.dataDirectory, "codex-billing-sync.json");
26016
+ const stateFile = path27.join(config3.dataDirectory, "codex-billing-sync.json");
25638
26017
  const prior = await readState(stateFile);
25639
26018
  const nowMs = Date.now();
25640
26019
  const history = prior === null || prior.accountFingerprint !== auth.accountFingerprint;
@@ -25805,9 +26184,9 @@ async function syncCodexBilling(config3, fetcher = collectorFetch, signal) {
25805
26184
 
25806
26185
  // src/cursor-billing.ts
25807
26186
  import { createHash as createHash8 } from "node:crypto";
25808
- import { promises as fs21 } from "node:fs";
25809
- import os9 from "node:os";
25810
- import path27 from "node:path";
26187
+ import { promises as fs22 } from "node:fs";
26188
+ import os10 from "node:os";
26189
+ import path28 from "node:path";
25811
26190
  var CURSOR_USAGE_URL = "https://api2.cursor.sh/aiserver.v1.DashboardService/GetFilteredUsageEvents";
25812
26191
  var PAGE_SIZE = 500;
25813
26192
  var MAX_PAGES = 1e3;
@@ -25838,18 +26217,18 @@ var usagePageSchema = object3({
25838
26217
  var emptyUsagePageSchema = object3({}).strict();
25839
26218
  function cursorAuthDatabase() {
25840
26219
  if (process.platform === "darwin")
25841
- return path27.join(
25842
- os9.homedir(),
26220
+ return path28.join(
26221
+ os10.homedir(),
25843
26222
  "Library/Application Support/Cursor/User/globalStorage/state.vscdb"
25844
26223
  );
25845
26224
  if (process.platform === "linux")
25846
- return path27.join(
25847
- os9.homedir(),
26225
+ return path28.join(
26226
+ os10.homedir(),
25848
26227
  ".config/Cursor/User/globalStorage/state.vscdb"
25849
26228
  );
25850
26229
  if (process.platform === "win32")
25851
- return path27.join(
25852
- process.env.APPDATA ?? path27.join(os9.homedir(), "AppData", "Roaming"),
26230
+ return path28.join(
26231
+ process.env.APPDATA ?? path28.join(os10.homedir(), "AppData", "Roaming"),
25853
26232
  "Cursor/User/globalStorage/state.vscdb"
25854
26233
  );
25855
26234
  return null;
@@ -25891,7 +26270,7 @@ async function readCursorAuth() {
25891
26270
  async function loadBillingState(filename) {
25892
26271
  let contents;
25893
26272
  try {
25894
- contents = await fs21.readFile(filename, "utf8");
26273
+ contents = await fs22.readFile(filename, "utf8");
25895
26274
  } catch (error3) {
25896
26275
  if (error3 instanceof Error && "code" in error3 && error3.code === "ENOENT")
25897
26276
  return null;
@@ -25907,7 +26286,7 @@ async function loadBillingState(filename) {
25907
26286
  }
25908
26287
  async function saveBillingState(filename, state) {
25909
26288
  const temporary = `${filename}.${process.pid}.tmp`;
25910
- const handle = await fs21.open(temporary, "w", 384);
26289
+ const handle = await fs22.open(temporary, "w", 384);
25911
26290
  try {
25912
26291
  await handle.writeFile(`${JSON.stringify(state)}
25913
26292
  `, "utf8");
@@ -25915,7 +26294,7 @@ async function saveBillingState(filename, state) {
25915
26294
  } finally {
25916
26295
  await handle.close();
25917
26296
  }
25918
- await fs21.rename(temporary, filename);
26297
+ await fs22.rename(temporary, filename);
25919
26298
  }
25920
26299
  function planCursorBillingSync(state, accountFingerprint, nowMs) {
25921
26300
  if (state === null || state.accountFingerprint !== accountFingerprint)
@@ -25937,7 +26316,7 @@ function planCursorBillingSync(state, accountFingerprint, nowMs) {
25937
26316
  }
25938
26317
  function cursorConversationIds(filenames) {
25939
26318
  return new Set(
25940
- filenames.map((filename) => path27.basename(filename, ".jsonl")).filter((id) => UUID3.test(id))
26319
+ filenames.map((filename) => path28.basename(filename, ".jsonl")).filter((id) => UUID3.test(id))
25941
26320
  );
25942
26321
  }
25943
26322
  function billingKind(kind) {
@@ -25995,11 +26374,11 @@ async function syncCursorBilling(config3, fetcher = collectorFetch, signal) {
25995
26374
  if (auth === null)
25996
26375
  return { sessions: 0, matched: 0, skipped: true, mode: null };
25997
26376
  const localConversations = cursorConversationIds(
25998
- await cursorFiles(path27.join(config3.cursorHome, "projects"))
26377
+ await cursorFiles(path28.join(config3.cursorHome, "projects"))
25999
26378
  );
26000
26379
  if (localConversations.size === 0)
26001
26380
  return { sessions: 0, matched: 0, skipped: true, mode: null };
26002
- const stateFile = path27.join(config3.dataDirectory, "cursor-billing-sync.json");
26381
+ const stateFile = path28.join(config3.dataDirectory, "cursor-billing-sync.json");
26003
26382
  const priorState = await loadBillingState(stateFile);
26004
26383
  const nowMs = Date.now();
26005
26384
  const plan = planCursorBillingSync(
@@ -26523,13 +26902,6 @@ var CODEX_APPROVAL_STEP = "Friction summary is off: in Codex, type /hooks and ap
26523
26902
  function sourceName(source) {
26524
26903
  return collectorSourceLabel(source);
26525
26904
  }
26526
- function safeWorkspaceName(value) {
26527
- const cleaned = value?.split("").map((character) => {
26528
- const code = character.charCodeAt(0);
26529
- return code < 32 || code >= 127 && code <= 159 ? " " : character;
26530
- }).join("").replace(/\s+/g, " ").trim();
26531
- return cleaned === void 0 || cleaned === "" ? null : cleaned;
26532
- }
26533
26905
  function readableBytes(bytes) {
26534
26906
  if (bytes < 1e3) return `${bytes} B`;
26535
26907
  const units = ["KB", "MB", "GB", "TB"];
@@ -26586,244 +26958,366 @@ function historyDescription(status2, source) {
26586
26958
  return "History imported; scanning current activity.";
26587
26959
  return `History imported; ${readableBytes(remainingBytes)} of new activity waiting to scan.`;
26588
26960
  }
26589
- function failureDescription(status2, source) {
26590
- const name = sourceName(source);
26961
+ function failureSummary(terminal2, status2, source, nowMs) {
26591
26962
  const failure3 = status2.health.lastFailure;
26592
26963
  if (failure3 === null) {
26593
26964
  throw new Error("A collector failure is required to describe it.");
26594
26965
  }
26595
- if (failure3.kind === "http") {
26596
- const code = failure3.status === null ? "HTTP error" : `HTTP ${failure3.status}`;
26597
- if (failure3.status === 401 || failure3.status === 403) {
26966
+ const describe2 = () => {
26967
+ if (failure3.kind === "http") {
26968
+ const code = failure3.status === null ? "HTTP error" : `HTTP ${failure3.status}`;
26969
+ if (failure3.status === 401 || failure3.status === 403)
26970
+ return {
26971
+ tone: "failure",
26972
+ headline: "Upload access needs attention",
26973
+ explanation: `Iteration denied this collector (${code}). Queued data stays on this computer. Contact Iteration support to reconnect it safely.`
26974
+ };
26975
+ if (failure3.status !== null && failure3.status < 500 && failure3.status !== 429)
26976
+ return {
26977
+ tone: "failure",
26978
+ headline: "Uploads need attention",
26979
+ explanation: `Iteration rejected an event batch (${code}). Check the collector log for details.`
26980
+ };
26598
26981
  return {
26599
- heading: `${name} upload access needs attention`,
26600
- explanation: `Iteration denied this collector (${code}). Queued data stays on this computer. Contact Iteration support to reconnect it safely.`
26982
+ tone: "warning",
26983
+ headline: "Uploads are delayed",
26984
+ explanation: `Iteration could not accept an upload (${code}). Retrying automatically.`
26601
26985
  };
26602
26986
  }
26603
- if (failure3.status !== null && failure3.status < 500 && failure3.status !== 429) {
26987
+ if (failure3.kind === "network")
26604
26988
  return {
26605
- heading: `${name} uploads need attention`,
26606
- explanation: `Iteration rejected an event batch (${code}). Check the collector log for details.`
26989
+ tone: "warning",
26990
+ headline: "Uploads are delayed",
26991
+ explanation: "Could not reach Iteration. Retrying automatically."
26992
+ };
26993
+ if (failure3.kind === "response")
26994
+ return {
26995
+ tone: "warning",
26996
+ headline: "Uploads need attention",
26997
+ explanation: "Iteration returned an unexpected upload response. Retrying automatically."
26607
26998
  };
26608
- }
26609
26999
  return {
26610
- heading: `${name} uploads are delayed`,
26611
- explanation: `Iteration could not accept an upload (${code}). Retrying automatically.`
27000
+ tone: "failure",
27001
+ headline: "Collector needs attention",
27002
+ explanation: "A local error interrupted collection."
26612
27003
  };
26613
- }
26614
- if (failure3.kind === "network") {
27004
+ };
27005
+ const { tone, headline, explanation } = describe2();
27006
+ return {
27007
+ tone,
27008
+ headline,
27009
+ facts: [],
27010
+ details: [
27011
+ explanation,
27012
+ ...status2.pendingEvents > 0 ? [`${pendingDescription(status2)}.`] : [],
27013
+ ...status2.health.lastUploadAtMs === null ? [] : [
27014
+ `Last successful upload ${relativeTime(status2.health.lastUploadAtMs, nowMs)}.`
27015
+ ]
27016
+ ],
27017
+ next: `Details: ${terminal2.bold(`iteration status ${source}`)}`
27018
+ };
27019
+ }
27020
+ function connectionSummary(terminal2, status2, source, nowMs) {
27021
+ const name = sourceName(source);
27022
+ const pending = status2.pendingEvents > 0 ? [`${pendingDescription(status2)}.`] : [];
27023
+ const details = `Details: ${terminal2.bold(`iteration status ${source}`)}`;
27024
+ if (!status2.running)
26615
27025
  return {
26616
- heading: `${name} uploads are delayed`,
26617
- explanation: "Could not reach Iteration. Retrying automatically."
27026
+ tone: "warning",
27027
+ headline: "Stopped",
27028
+ facts: [],
27029
+ details: ["New sessions are not being collected.", ...pending],
27030
+ next: `Resume with ${terminal2.bold(`iteration start ${source}`)}`
26618
27031
  };
26619
- }
26620
- if (failure3.kind === "response") {
27032
+ if (status2.hookFailureAtMs !== null && status2.hookFailureAtMs !== void 0)
26621
27033
  return {
26622
- heading: `${name} uploads need attention`,
26623
- explanation: "Iteration returned an unexpected upload response. Retrying automatically."
27034
+ tone: "warning",
27035
+ headline: "Hook capture needs attention",
27036
+ facts: [],
27037
+ details: [
27038
+ `A ${name} hook failed ${relativeTime(status2.hookFailureAtMs, nowMs)}. Some data may be missing.`
27039
+ ],
27040
+ next: details
26624
27041
  };
26625
- }
26626
- return {
26627
- heading: `${name} collector needs attention`,
26628
- explanation: `A local error interrupted collection. See iteration status ${source} for details.`
26629
- };
27042
+ if (!status2.healthAvailable)
27043
+ return {
27044
+ tone: "warning",
27045
+ headline: "Running; local status needs attention",
27046
+ facts: [],
27047
+ details: [
27048
+ "Upload history could not be read. Collection continues in the background.",
27049
+ ...pending
27050
+ ],
27051
+ next: details
27052
+ };
27053
+ if (status2.health.lastFailure !== null)
27054
+ return failureSummary(terminal2, status2, source, nowMs);
27055
+ return null;
26630
27056
  }
26631
- function renderHome(status2, nowMs = Date.now(), source = "codex") {
27057
+ function scanSummary(status2, source, nowMs) {
26632
27058
  const name = sourceName(source);
26633
- if (status2.kind === "not_connected") {
26634
- return [
26635
- "Iteration",
26636
- "",
26637
- `${name} is not connected.`,
26638
- "Run iteration connect to import your existing sessions."
26639
- ].join("\n");
26640
- }
26641
- if (status2.kind === "needs_repair") {
27059
+ const pending = status2.pendingEvents > 0 ? [`${pendingDescription(status2)}.`] : [];
27060
+ const lastUpload = status2.health.lastUploadAtMs === null ? [] : [`last upload ${relativeTime(status2.health.lastUploadAtMs, nowMs)}`];
27061
+ const summary = (headline, details, facts = []) => ({
27062
+ tone: "success",
27063
+ headline,
27064
+ facts: [...facts, ...lastUpload],
27065
+ details,
27066
+ next: null
27067
+ });
27068
+ const scan = status2.scan;
27069
+ if (scan.kind === "waiting") return summary("Preparing your history", []);
27070
+ if (scan.totalBytes > 0 && scan.scannedBytes < scan.totalBytes && status2.health.historyCaughtUpAtMs === null)
27071
+ return summary("Importing existing sessions", [
27072
+ historyDescription(status2, source),
27073
+ "New activity is collected automatically."
27074
+ ]);
27075
+ if (scan.totalBytes - scan.scannedBytes >= 1e6)
27076
+ return summary("Catching up with new activity", [
27077
+ historyDescription(status2, source),
27078
+ ...pending
27079
+ ]);
27080
+ if (status2.pendingEvents > 0)
27081
+ return summary("Uploading captured sessions", pending);
27082
+ if (scan.totalBytes === 0)
27083
+ return summary("Connected", [
27084
+ `Waiting for ${name} sessions on this computer.`
27085
+ ]);
27086
+ if (scan.scannedBytes < scan.totalBytes)
27087
+ return summary("Collecting new activity", [
27088
+ "Local history is imported; current activity is being scanned."
27089
+ ]);
27090
+ return summary("Collecting", [], ["caught up"]);
27091
+ }
27092
+ function sourceSummary(terminal2, status2, source, nowMs) {
27093
+ if (status2.kind === "not_connected")
27094
+ return {
27095
+ tone: "muted",
27096
+ headline: "Not connected",
27097
+ facts: [],
27098
+ details: [],
27099
+ next: `Run ${terminal2.bold("iteration connect")} to include it.`
27100
+ };
27101
+ if (status2.kind === "needs_repair")
27102
+ return {
27103
+ tone: "failure",
27104
+ headline: "Connection needs repair",
27105
+ facts: [],
27106
+ details: [
27107
+ "Local collector data exists, but its connection details are missing.",
27108
+ status2.pendingBytes > 0 ? `${readableBytes(status2.pendingBytes)} of queued data remains on this computer.` : "Existing local progress remains on this computer."
27109
+ ],
27110
+ next: `Run ${terminal2.bold(`iteration status ${source}`)} for recovery details.`
27111
+ };
27112
+ return connectionSummary(terminal2, status2, source, nowMs) ?? scanSummary(status2, source, nowMs);
27113
+ }
27114
+ function statusDot(terminal2, tone) {
27115
+ return terminal2.tone(
27116
+ tone,
27117
+ tone === "muted" ? terminal2.symbols.off : terminal2.symbols.on
27118
+ );
27119
+ }
27120
+ function connectedStatuses(sources) {
27121
+ return sources.flatMap(
27122
+ ({ status: status2 }) => status2.kind === "connected" ? [status2] : []
27123
+ );
27124
+ }
27125
+ function renderHome(terminal2, sources, nowMs = Date.now()) {
27126
+ const connected = connectedStatuses(sources);
27127
+ const workspaces = [
27128
+ ...new Set(
27129
+ connected.flatMap(({ workspaceName }) => {
27130
+ const name = safeWorkspaceName(workspaceName);
27131
+ return name === null ? [] : [name];
27132
+ })
27133
+ )
27134
+ ];
27135
+ const nameWidth = Math.max(
27136
+ ...sources.map(({ source }) => sourceName(source).length)
27137
+ );
27138
+ const blocks = sources.map(({ source, status: status2 }) => {
27139
+ const summary = sourceSummary(terminal2, status2, source, nowMs);
27140
+ const workspace = workspaces.length > 1 && status2.kind === "connected" ? [safeWorkspaceName(status2.workspaceName) ?? "No workspace"] : [];
27141
+ const facts = [...workspace, ...summary.facts];
27142
+ const indent = " ".repeat(4 + nameWidth + 2);
26642
27143
  return [
26643
- "Iteration",
26644
- "",
26645
- `${name} connection needs repair`,
26646
- "Local collector data exists, but its connection details are missing.",
26647
- status2.pendingBytes > 0 ? `${readableBytes(status2.pendingBytes)} of queued data remains on this computer.` : "Existing local progress remains on this computer.",
26648
- `Run iteration status ${source} for recovery details.`
26649
- ].join("\n");
26650
- }
26651
- const workspaceName = safeWorkspaceName(status2.workspaceName);
27144
+ wrap(
27145
+ terminal2,
27146
+ `${summary.headline}${facts.length === 0 ? "" : terminal2.dim(` \xB7 ${facts.join(" \xB7 ")}`)}`,
27147
+ {
27148
+ first: ` ${statusDot(terminal2, summary.tone)} ${padEnd(sourceName(source), nameWidth)} `,
27149
+ indent
27150
+ }
27151
+ ),
27152
+ ...summary.details.map(
27153
+ (line) => wrap(terminal2, line, { indent, style: terminal2.dim })
27154
+ ),
27155
+ ...summary.next === null ? [] : [wrap(terminal2, summary.next, { indent })]
27156
+ ];
27157
+ });
27158
+ const spaced = blocks.some((block) => block.length > 1);
26652
27159
  const lines = [
26653
- workspaceName === null ? "Iteration" : `Iteration \xB7 ${workspaceName}`,
26654
- ""
27160
+ brand(terminal2, workspaces.length === 1 ? workspaces[0] : null),
27161
+ "",
27162
+ ...blocks.flatMap(
27163
+ (block, index) => spaced && index > 0 ? ["", ...block] : block
27164
+ )
26655
27165
  ];
26656
- const appendConnectionStatus = () => {
26657
- if (!status2.running) {
26658
- lines.push(`${name} is stopped`, "New sessions are not being collected.");
26659
- if (status2.pendingEvents > 0)
26660
- lines.push(`${pendingDescription(status2)}.`);
26661
- lines.push(`Resume with iteration start ${source}.`);
26662
- } else if (status2.hookFailureAtMs !== null && status2.hookFailureAtMs !== void 0) {
26663
- lines.push(
26664
- `${name} hook capture needs attention`,
26665
- `A ${name} hook failed ${relativeTime(status2.hookFailureAtMs, nowMs)}. Some data may be missing. See iteration status ${source}.`
26666
- );
26667
- } else if (!status2.healthAvailable) {
26668
- lines.push(
26669
- `${name} is running; local status needs attention`,
26670
- "Upload history could not be read. Collection continues in the background."
26671
- );
26672
- if (status2.pendingEvents > 0)
26673
- lines.push(`${pendingDescription(status2)}.`);
26674
- lines.push(`Details: iteration status ${source}`);
26675
- } else if (status2.health.lastFailure !== null) {
26676
- const failure3 = failureDescription(status2, source);
26677
- lines.push(failure3.heading, failure3.explanation);
26678
- if (status2.pendingEvents > 0)
26679
- lines.push(`${pendingDescription(status2)}.`);
26680
- if (status2.health.lastUploadAtMs !== null) {
26681
- lines.push(
26682
- `Last successful upload ${relativeTime(status2.health.lastUploadAtMs, nowMs)}.`
26683
- );
26684
- }
26685
- lines.push(`Details: iteration status ${source}`);
26686
- } else return false;
26687
- return true;
26688
- };
26689
- const appendScanStatus = () => {
26690
- if (status2.scan.kind === "waiting") {
26691
- lines.push(
26692
- `${name} is preparing your history`,
26693
- progressDescription(status2.scan, source)
26694
- );
26695
- } else if (status2.scan.kind === "scanning" && status2.scan.totalBytes > 0 && status2.scan.scannedBytes < status2.scan.totalBytes && status2.health.historyCaughtUpAtMs === null) {
26696
- lines.push(
26697
- `${name} is importing existing sessions`,
26698
- historyDescription(status2, source),
26699
- "New activity is collected automatically."
26700
- );
26701
- } else if (status2.scan.kind === "scanning" && status2.scan.totalBytes - status2.scan.scannedBytes >= 1e6) {
26702
- lines.push(
26703
- `${name} is catching up with new activity`,
26704
- historyDescription(status2, source)
26705
- );
26706
- if (status2.pendingEvents > 0)
26707
- lines.push(`${pendingDescription(status2)}.`);
26708
- } else if (status2.pendingEvents > 0) {
26709
- lines.push(
26710
- `${name} is uploading captured sessions`,
26711
- `${pendingDescription(status2)}.`
26712
- );
26713
- } else if (status2.scan.totalBytes === 0) {
26714
- lines.push(
26715
- `${name} is connected`,
26716
- `Waiting for ${name} sessions on this computer.`
26717
- );
26718
- } else if (status2.scan.kind === "scanning" && status2.scan.scannedBytes < status2.scan.totalBytes) {
26719
- lines.push(
26720
- `${name} is collecting new activity`,
26721
- "Local history is imported; current activity is being scanned."
26722
- );
26723
- } else {
26724
- lines.push(
26725
- `${name} is collecting`,
26726
- "Local scan is caught up and no uploads are waiting.",
26727
- "New activity is collected automatically."
26728
- );
26729
- }
26730
- };
26731
- if (!appendConnectionStatus()) appendScanStatus();
26732
- const appendLastUpload = () => {
26733
- if (status2.running && status2.health.lastFailure === null && status2.health.lastUploadAtMs !== null) {
26734
- lines.push(
26735
- `Last successful upload ${relativeTime(status2.health.lastUploadAtMs, nowMs)}.`
26736
- );
26737
- }
26738
- };
26739
- appendLastUpload();
26740
- if (status2.turnSummaryNeedsApproval) lines.push("", CODEX_APPROVAL_STEP);
26741
- lines.push("", `Explore traces ${status2.tracesUrl}`);
27166
+ if (connected.some((status2) => status2.turnSummaryNeedsApproval))
27167
+ lines.push("", mark(terminal2, "warning", CODEX_APPROVAL_STEP, " "));
27168
+ const links = [...new Set(connected.map(({ tracesUrl: tracesUrl2 }) => tracesUrl2))];
27169
+ if (links.length > 0)
27170
+ lines.push(
27171
+ "",
27172
+ ...links.map((url2) => ` Open Iteration ${terminal2.link(url2)}`)
27173
+ );
26742
27174
  return lines.join("\n");
26743
27175
  }
26744
- function renderDetailedStatus(status2, nowMs = Date.now(), source = "codex") {
27176
+ function sourceHeading(terminal2, tone, source, note) {
27177
+ return `${statusDot(terminal2, tone)} ${terminal2.bold(sourceName(source))}${note === null ? "" : terminal2.dim(` \xB7 ${note}`)}`;
27178
+ }
27179
+ function sentenceCase(text) {
27180
+ return `${text.charAt(0).toUpperCase()}${text.slice(1)}`;
27181
+ }
27182
+ function renderDetailedStatus(terminal2, source, status2, nowMs = Date.now()) {
26745
27183
  const name = sourceName(source);
26746
27184
  if (status2.kind === "not_connected") {
26747
- return `${name} is not connected. Run iteration connect to connect.`;
27185
+ return [
27186
+ sourceHeading(terminal2, "muted", source, "not connected"),
27187
+ wrap(terminal2, `Run ${terminal2.bold("iteration connect")} to connect.`)
27188
+ ].join("\n");
26748
27189
  }
26749
27190
  if (status2.kind === "needs_repair") {
26750
27191
  return [
26751
- `${name} connection needs repair`,
26752
- "Local collector data exists without its connection details.",
26753
- `Queued data: ${readableBytes(status2.pendingBytes)}`,
26754
- `Restore the missing config from backup: ${status2.configPath}`,
26755
- "If you do not have it, contact Iteration support before reconnecting; existing data has been kept."
27192
+ sourceHeading(terminal2, "failure", source, "connection needs repair"),
27193
+ wrap(
27194
+ terminal2,
27195
+ "Local collector data exists without its connection details."
27196
+ ),
27197
+ rows(terminal2, [["Queued data", readableBytes(status2.pendingBytes)]]),
27198
+ wrap(
27199
+ terminal2,
27200
+ `Restore the missing config from backup: ${status2.configPath}`
27201
+ ),
27202
+ wrap(
27203
+ terminal2,
27204
+ "If you do not have it, contact Iteration support before reconnecting; existing data has been kept."
27205
+ )
26756
27206
  ].join("\n");
26757
27207
  }
26758
- const workspaceName = safeWorkspaceName(status2.workspaceName);
26759
- const lines = [
26760
- `${name} collector`,
26761
- ...workspaceName === null ? [] : [`Workspace: ${workspaceName}`],
26762
- `Background process: ${status2.running ? "Running" : "Stopped"}`,
26763
- `History: ${historyDescription(status2, source).replace(/^History /, "")}`,
26764
- `Uploads: ${status2.pendingEvents === 0 ? "None waiting" : pendingDescription(status2)}`
27208
+ const summary = sourceSummary(terminal2, status2, source, nowMs);
27209
+ const entries2 = [
27210
+ ["Background process", status2.running ? "Running" : "Stopped"],
27211
+ [
27212
+ "History",
27213
+ sentenceCase(historyDescription(status2, source).replace(/^History /, ""))
27214
+ ],
27215
+ [
27216
+ "Uploads",
27217
+ status2.pendingEvents === 0 ? "None waiting" : sentenceCase(pendingDescription(status2))
27218
+ ]
26765
27219
  ];
26766
- if (!status2.healthAvailable) {
26767
- lines.push(
26768
- "Local status: unavailable; check collector file permissions",
26769
- `Collector log: ${status2.logPath}`
26770
- );
26771
- }
26772
- if (status2.health.lastUploadAtMs !== null) {
26773
- lines.push(
26774
- `Last successful upload: ${relativeTime(status2.health.lastUploadAtMs, nowMs)}`
26775
- );
26776
- }
26777
- if (status2.health.lastFailure !== null) {
26778
- const failure3 = status2.health.lastFailure;
27220
+ if (!status2.healthAvailable)
27221
+ entries2.push([
27222
+ "Local status",
27223
+ "Unavailable; check collector file permissions"
27224
+ ]);
27225
+ if (status2.health.lastUploadAtMs !== null)
27226
+ entries2.push([
27227
+ "Last upload",
27228
+ relativeTime(status2.health.lastUploadAtMs, nowMs)
27229
+ ]);
27230
+ const failure3 = status2.health.lastFailure;
27231
+ if (failure3 !== null) {
26779
27232
  const label2 = failure3.kind === "http" && failure3.status !== null ? `HTTP ${failure3.status}` : failure3.kind === "network" ? "Network unavailable" : failure3.kind === "response" ? "Unexpected upload response" : "Local collector error";
26780
- lines.push(
26781
- `Last issue: ${label2} (${relativeTime(failure3.atMs, nowMs)})`,
26782
- `Collector log: ${status2.logPath}`
26783
- );
27233
+ entries2.push([
27234
+ "Last issue",
27235
+ `${label2} (${relativeTime(failure3.atMs, nowMs)})`
27236
+ ]);
26784
27237
  }
26785
27238
  if (status2.hookFailureAtMs !== null && status2.hookFailureAtMs !== void 0)
27239
+ entries2.push([
27240
+ "Hook capture",
27241
+ `Failed ${relativeTime(status2.hookFailureAtMs, nowMs)}. Some data may be missing; inspect ${name} hook logs.`
27242
+ ]);
27243
+ if (!status2.healthAvailable || failure3 !== null)
27244
+ entries2.push(["Collector log", status2.logPath]);
27245
+ entries2.push(["Open Iteration", terminal2.link(status2.tracesUrl)]);
27246
+ const lines = [
27247
+ sourceHeading(
27248
+ terminal2,
27249
+ summary.tone,
27250
+ source,
27251
+ safeWorkspaceName(status2.workspaceName)
27252
+ ),
27253
+ rows(terminal2, entries2)
27254
+ ];
27255
+ if (status2.turnSummaryNeedsApproval)
27256
+ lines.push(mark(terminal2, "warning", CODEX_APPROVAL_STEP, " "));
27257
+ if (!status2.running)
26786
27258
  lines.push(
26787
- `Last ${name} hook capture failure: ${relativeTime(status2.hookFailureAtMs, nowMs)}. Some data may be missing; inspect ${name} hook logs.`
27259
+ wrap(
27260
+ terminal2,
27261
+ `Resume with ${terminal2.bold(`iteration start ${source}`)}`
27262
+ )
26788
27263
  );
26789
- if (status2.turnSummaryNeedsApproval) lines.push(CODEX_APPROVAL_STEP);
26790
- if (!status2.running) lines.push(`Resume: iteration start ${source}`);
26791
- lines.push(`Explore traces: ${status2.tracesUrl}`);
26792
27264
  return lines.join("\n");
26793
27265
  }
26794
- function renderRuntime(summary) {
27266
+ function renderRuntime(terminal2, summary) {
26795
27267
  return [
26796
- `Iteration ${summary.version} \xB7 ${summary.autoUpdate ? "updates automatically" : "automatic updates are off; run iteration update to update"}`,
26797
- ...summary.confirming === null ? [] : [`Starting version ${summary.confirming} after an update.`],
27268
+ wrap(
27269
+ terminal2,
27270
+ `Version ${summary.version} \xB7 ${summary.autoUpdate ? "updates automatically" : "automatic updates are off; run iteration update to update"}`,
27271
+ { style: terminal2.dim }
27272
+ ),
27273
+ ...summary.confirming === null ? [] : [
27274
+ wrap(
27275
+ terminal2,
27276
+ `Starting version ${summary.confirming} after an update.`,
27277
+ { style: terminal2.dim }
27278
+ )
27279
+ ],
26798
27280
  ...summary.rolledBack === null ? [] : [
26799
- `Version ${summary.rolledBack.version} was rolled back: ${summary.rolledBack.reason}`
27281
+ mark(
27282
+ terminal2,
27283
+ "warning",
27284
+ `Version ${summary.rolledBack.version} was rolled back: ${summary.rolledBack.reason}`,
27285
+ " "
27286
+ )
26800
27287
  ],
26801
- ...summary.checkError === null ? [] : [`Last update check failed: ${summary.checkError}`]
27288
+ ...summary.checkError === null ? [] : [
27289
+ mark(
27290
+ terminal2,
27291
+ "warning",
27292
+ `Last update check failed: ${summary.checkError}`,
27293
+ " "
27294
+ )
27295
+ ]
26802
27296
  ].join("\n");
26803
27297
  }
26804
27298
 
26805
27299
  // src/windows-supervisor.ts
26806
27300
  import { spawn } from "node:child_process";
26807
- import { promises as fs22 } from "node:fs";
26808
- import path28 from "node:path";
27301
+ import { promises as fs23 } from "node:fs";
27302
+ import path29 from "node:path";
26809
27303
  import { setTimeout as delay6 } from "node:timers/promises";
26810
27304
  var MAX_LOG_BYTES = 8 * 1024 * 1024;
26811
27305
  var RESTART_DELAY_MS = 5e3;
26812
27306
  async function appendLog(filename, bytes) {
26813
27307
  let offset = 0;
26814
27308
  while (offset < bytes.length) {
26815
- const size = await fs22.stat(filename).then((stat) => stat.size).catch((error3) => {
27309
+ const size = await fs23.stat(filename).then((stat) => stat.size).catch((error3) => {
26816
27310
  if (error3 instanceof Error && "code" in error3 && error3.code === "ENOENT")
26817
27311
  return 0;
26818
27312
  throw error3;
26819
27313
  });
26820
27314
  if (size >= MAX_LOG_BYTES) {
26821
- await fs22.rm(`${filename}.1`, { force: true });
26822
- await fs22.rename(filename, `${filename}.1`);
27315
+ await fs23.rm(`${filename}.1`, { force: true });
27316
+ await fs23.rename(filename, `${filename}.1`);
26823
27317
  continue;
26824
27318
  }
26825
27319
  const count = Math.min(bytes.length - offset, MAX_LOG_BYTES - size);
26826
- await fs22.appendFile(filename, bytes.subarray(offset, offset + count), {
27320
+ await fs23.appendFile(filename, bytes.subarray(offset, offset + count), {
26827
27321
  mode: 384
26828
27322
  });
26829
27323
  offset += count;
@@ -26839,7 +27333,7 @@ async function copyOutput(stream, filename) {
26839
27333
  async function superviseCollector(source, dataDirectory2) {
26840
27334
  const output = windowsOutputPath(source);
26841
27335
  const errors = windowsLogPath(source);
26842
- await ensurePrivateDirectory(path28.dirname(output));
27336
+ await ensurePrivateDirectory(path29.dirname(output));
26843
27337
  const controller = new AbortController();
26844
27338
  const stop = () => controller.abort();
26845
27339
  process.once("SIGTERM", stop);
@@ -26910,6 +27404,14 @@ async function superviseCollector(source, dataDirectory2) {
26910
27404
 
26911
27405
  // src/cli.ts
26912
27406
  var DEFAULT_INGEST_ENDPOINT = "https://useiteration.com/api/traces/ingest";
27407
+ var terminal = terminalFor(process.stdout);
27408
+ function print(...lines) {
27409
+ process.stdout.write(`${lines.join("\n")}
27410
+ `);
27411
+ }
27412
+ function tracesUrl(endpoint) {
27413
+ return new URL("/app/sessions", endpoint).toString();
27414
+ }
26913
27415
  function argumentsForCli() {
26914
27416
  const parsed = parseArgs({
26915
27417
  args: process.argv.slice(2),
@@ -26950,53 +27452,100 @@ function optionalString(values, name) {
26950
27452
  return parsed.data;
26951
27453
  }
26952
27454
  function usage(command) {
26953
- if (command === "connect") {
26954
- process.stdout.write(
26955
- [
26956
- "Connect a coding agent to Iteration",
26957
- " iteration connect Connect all detected agents on this computer",
26958
- " iteration connect codex",
26959
- " iteration connect claude",
26960
- " iteration connect cursor",
26961
- "",
26962
- "Existing local sessions and new activity are collected automatically.",
26963
- "",
26964
- "Options for advanced setups:",
26965
- " --device-name NAME Name this computer in Iteration",
26966
- " --workspace ID Connect to this workspace without a prompt",
26967
- " --codex-home DIR Use a different Codex data directory",
26968
- " --claude-home DIR Use a different Claude data directory",
26969
- " --cursor-home DIR Use a different Cursor data directory",
26970
- " --yes Approve uploads without a terminal prompt",
26971
- " --data-directory DIR Use a different state directory with a source-specific command",
26972
- " --endpoint URL Use a different Iteration server"
26973
- ].join("\n") + "\n"
27455
+ const section = (title, entries2) => [
27456
+ wrap(terminal, title, { style: terminal.bold }),
27457
+ rows(terminal, entries2, " ")
27458
+ ];
27459
+ if (command === "logout") {
27460
+ print(
27461
+ brand(terminal),
27462
+ "",
27463
+ ...section("Sign out of Iteration on this computer", [
27464
+ ["iteration logout", ""]
27465
+ ]),
27466
+ "",
27467
+ wrap(
27468
+ terminal,
27469
+ "Stops all collectors and removes saved credentials and automatic connection approval. Local pending data is archived and will not be uploaded after reconnecting. Agent session files and previously uploaded data are kept."
27470
+ ),
27471
+ "",
27472
+ ...section("Options", [
27473
+ [
27474
+ "--data-directory DIR",
27475
+ "Also clear a custom collector directory with no installed service"
27476
+ ]
27477
+ ]),
27478
+ "",
27479
+ wrap(
27480
+ terminal,
27481
+ `Run ${terminal.bold("iteration connect")} to sign in again.`
27482
+ )
26974
27483
  );
26975
27484
  return;
26976
27485
  }
26977
- process.stdout.write(
26978
- [
26979
- "Iteration CLI",
27486
+ if (command === "connect") {
27487
+ print(
27488
+ brand(terminal),
26980
27489
  "",
26981
- "Get started:",
26982
- " iteration connect Connect detected agents and import sessions",
27490
+ ...section("Connect coding agents", [
27491
+ ["iteration connect", "Connect all detected agents on this computer"],
27492
+ [
27493
+ "iteration connect <agent>",
27494
+ "Connect one agent: codex, claude or cursor"
27495
+ ]
27496
+ ]),
26983
27497
  "",
26984
- "Commands:",
26985
- " iteration See connection status",
26986
- " iteration status See scan, upload, and error details",
26987
- " iteration connect codex|claude|cursor Connect one source (advanced)",
26988
- " iteration disconnect codex|claude|cursor Stop a source",
26989
- " iteration update Update now (updates also install automatically)",
26990
- " iteration update off|on Turn automatic updates off or on",
26991
- " iteration version Show the installed version",
27498
+ wrap(
27499
+ terminal,
27500
+ "Existing local sessions and new activity are collected automatically."
27501
+ ),
26992
27502
  "",
26993
- "Run iteration connect --help for advanced setup options."
26994
- ].join("\n") + "\n"
27503
+ ...section("Options for advanced setups", [
27504
+ ["--device-name NAME", "Name this computer in Iteration"],
27505
+ ["--workspace ID", "Connect to this workspace without a prompt"],
27506
+ ["--codex-home DIR", "Use a different Codex data directory"],
27507
+ ["--claude-home DIR", "Use a different Claude data directory"],
27508
+ ["--cursor-home DIR", "Use a different Cursor data directory"],
27509
+ ["--yes", "Approve uploads without a terminal prompt"],
27510
+ [
27511
+ "--data-directory DIR",
27512
+ "Use a different state directory with a one-agent command"
27513
+ ],
27514
+ ["--endpoint URL", "Use a different Iteration server"]
27515
+ ])
27516
+ );
27517
+ return;
27518
+ }
27519
+ print(
27520
+ brand(terminal),
27521
+ "",
27522
+ ...section("Get started", [
27523
+ ["iteration connect", "Connect detected agents and import sessions"]
27524
+ ]),
27525
+ "",
27526
+ ...section("Commands", [
27527
+ ["iteration", "See connection status"],
27528
+ ["iteration status", "See scan, upload and error details"],
27529
+ [
27530
+ "iteration connect <agent>",
27531
+ "Connect one agent: codex, claude or cursor"
27532
+ ],
27533
+ ["iteration disconnect <agent>", "Stop one agent"],
27534
+ ["iteration logout", "Sign out and stop all sources on this computer"],
27535
+ ["iteration update", "Update now; updates also install automatically"],
27536
+ ["iteration update off|on", "Turn automatic updates off or on"],
27537
+ ["iteration version", "Show the installed version"]
27538
+ ]),
27539
+ "",
27540
+ wrap(
27541
+ terminal,
27542
+ `Run ${terminal.bold("iteration connect --help")} for advanced setup options.`
27543
+ )
26995
27544
  );
26996
27545
  }
26997
27546
  async function fileExists(filename) {
26998
27547
  try {
26999
- await fs23.access(filename);
27548
+ await fs24.access(filename);
27000
27549
  return true;
27001
27550
  } catch (error3) {
27002
27551
  if (error3 instanceof Error && "code" in error3 && error3.code === "ENOENT") {
@@ -27014,29 +27563,20 @@ async function defaultCommand() {
27014
27563
  snapshot: await statusSnapshot(source, {})
27015
27564
  }))
27016
27565
  );
27017
- const connected = snapshots.filter(
27018
- ({ snapshot }) => snapshot.kind !== "not_connected"
27019
- );
27020
- if (connected.length > 0) {
27021
- process.stdout.write(
27022
- `${connected.map(({ source, snapshot }) => renderHome(snapshot, Date.now(), source)).join("\n\n")}
27023
- `
27024
- );
27566
+ if (snapshots.some(({ snapshot }) => snapshot.kind !== "not_connected")) {
27025
27567
  const discovered = await detectedSources({
27026
27568
  codex: sourceHome("codex"),
27027
27569
  claude: sourceHome("claude"),
27028
27570
  cursor: sourceHome("cursor")
27029
27571
  });
27030
- const missing2 = discovered.filter(
27031
- (source) => snapshots.find((item) => item.source === source)?.snapshot.kind === "not_connected"
27572
+ print(
27573
+ renderHome(
27574
+ terminal,
27575
+ snapshots.flatMap(
27576
+ ({ source, snapshot }) => snapshot.kind !== "not_connected" || discovered.includes(source) ? [{ source, status: snapshot }] : []
27577
+ )
27578
+ )
27032
27579
  );
27033
- if (missing2.length > 0) {
27034
- process.stdout.write(
27035
- `
27036
- ${missing2.map(collectorSourceLabel).join(" and ")} found on this computer but not connected. Run iteration connect to include ${missing2.length === 1 ? "it" : "them"}.
27037
- `
27038
- );
27039
- }
27040
27580
  return;
27041
27581
  }
27042
27582
  if (process.stdin.isTTY !== true || process.stdout.isTTY !== true) {
@@ -27046,33 +27586,92 @@ ${missing2.map(collectorSourceLabel).join(" and ")} found on this computer but n
27046
27586
  await connectAll({});
27047
27587
  }
27048
27588
  function dataDirectory(source, values) {
27049
- return path29.resolve(
27589
+ return path30.resolve(
27050
27590
  optionalString(values, "data-directory") ?? defaultCollectorDirectory(source)
27051
27591
  );
27052
27592
  }
27053
- async function turnSummaryNotice(config3) {
27054
- if ("cursorHome" in config3)
27055
- return " Cursor hooks capture tool results and usage automatically.";
27593
+ async function setUpTurnSummary(config3) {
27594
+ if ("cursorHome" in config3) return { kind: "unsupported" };
27056
27595
  try {
27057
27596
  await installTurnSummary(config3);
27058
- if (await codexTurnSummaryApproval(config3) === "needs_approval") {
27059
- return "\nOne more step: in Codex, type /hooks and approve Iteration to see your friction summary after each turn.";
27060
- }
27061
- return " A one-line friction summary now appears after agent turns in your repositories.";
27597
+ return await codexTurnSummaryApproval(config3) === "needs_approval" ? { kind: "needs_approval" } : { kind: "ready" };
27062
27598
  } catch (error3) {
27063
- return ` The turn summary could not be installed: ${error3 instanceof Error ? error3.message : "unknown error"} Run iteration start ${collectorSource(config3)} to retry it.`;
27599
+ return {
27600
+ kind: "failed",
27601
+ reason: error3 instanceof Error ? error3.message : "unknown error"
27602
+ };
27064
27603
  }
27065
27604
  }
27605
+ function turnSummaryLines(results) {
27606
+ const warnings = results.flatMap(({ source, turnSummary }) => {
27607
+ const name = collectorSourceLabel(source);
27608
+ if (turnSummary.kind === "needs_approval")
27609
+ return [
27610
+ mark(
27611
+ terminal,
27612
+ "warning",
27613
+ `${terminal.bold(`One more step for ${name}:`)} type /hooks in ${name} and approve Iteration to see your friction summary after each turn.`
27614
+ )
27615
+ ];
27616
+ if (turnSummary.kind === "failed")
27617
+ return [
27618
+ mark(
27619
+ terminal,
27620
+ "warning",
27621
+ `The ${name} friction summary could not be installed: ${turnSummary.reason} Run ${terminal.bold(`iteration start ${source}`)} to retry it.`
27622
+ )
27623
+ ];
27624
+ return [];
27625
+ });
27626
+ return [
27627
+ ...results.some(({ turnSummary }) => turnSummary.kind === "ready") ? [
27628
+ wrap(
27629
+ terminal,
27630
+ "A one-line friction summary now appears after agent turns in your repositories."
27631
+ )
27632
+ ] : [],
27633
+ ...warnings
27634
+ ];
27635
+ }
27636
+ var CONNECTED_WIDTH = Math.max(
27637
+ ...COLLECTOR_SOURCES2.map(
27638
+ (source) => `${collectorSourceLabel(source)} connected`.length
27639
+ )
27640
+ );
27641
+ function connectedLine(source, sessions) {
27642
+ return mark(
27643
+ terminal,
27644
+ "success",
27645
+ `${padEnd(`${collectorSourceLabel(source)} connected`, CONNECTED_WIDTH)} ${terminal.dim(
27646
+ sessions === 0 ? "no saved sessions yet" : `importing ${sessions.toLocaleString("en-US")} ${sessions === 1 ? "session" : "sessions"}`
27647
+ )}`
27648
+ );
27649
+ }
27650
+ function connectionSummary2(results, imported) {
27651
+ const links = [
27652
+ ...new Set(results.map(({ endpoint }) => tracesUrl(endpoint)))
27653
+ ];
27654
+ const notes = turnSummaryLines(results);
27655
+ return [
27656
+ ...notes.length === 0 ? [] : ["", ...notes],
27657
+ "",
27658
+ wrap(
27659
+ terminal,
27660
+ imported ? `Sessions import newest first. Run ${terminal.bold("iteration")} to follow progress.` : `Run ${terminal.bold("iteration")} to see their status.`
27661
+ ),
27662
+ ...links.map((url2) => ` Open Iteration ${terminal.link(url2)}`)
27663
+ ];
27664
+ }
27066
27665
  async function initialize(source, values) {
27067
27666
  requireCollectorPlatform();
27068
27667
  const endpoint = optionalString(values, "endpoint") ?? DEFAULT_INGEST_ENDPOINT;
27069
27668
  const endpointUrl = validateCollectorEndpoint(endpoint);
27070
- const deviceName = optionalString(values, "device-name") ?? os10.hostname();
27669
+ const deviceName = optionalString(values, "device-name") ?? os11.hostname();
27071
27670
  const organizationId = optionalString(values, "workspace");
27072
27671
  const directory = dataDirectory(source, values);
27073
27672
  const paths = collectorPaths(directory);
27074
- const selectedHome = path29.resolve(
27075
- source === "codex" ? optionalString(values, "codex-home") ?? process.env.CODEX_HOME ?? path29.join(os10.homedir(), ".codex") : source === "claude" ? optionalString(values, "claude-home") ?? process.env.CLAUDE_CONFIG_DIR ?? path29.join(os10.homedir(), ".claude") : optionalString(values, "cursor-home") ?? path29.join(os10.homedir(), ".cursor")
27673
+ const selectedHome = path30.resolve(
27674
+ source === "codex" ? optionalString(values, "codex-home") ?? process.env.CODEX_HOME ?? path30.join(os11.homedir(), ".codex") : source === "claude" ? optionalString(values, "claude-home") ?? process.env.CLAUDE_CONFIG_DIR ?? path30.join(os11.homedir(), ".claude") : optionalString(values, "cursor-home") ?? path30.join(os11.homedir(), ".cursor")
27076
27675
  );
27077
27676
  await assertFreshCollectorDirectory(paths, source);
27078
27677
  const preparedState = await prepareSourceInitialState(
@@ -27087,6 +27686,13 @@ async function initialize(source, values) {
27087
27686
  organizationId,
27088
27687
  source
27089
27688
  );
27689
+ print(
27690
+ mark(
27691
+ terminal,
27692
+ "success",
27693
+ `Signed in to ${terminal.bold(safeWorkspaceName(enrollment.organizationName) ?? "your workspace")}`
27694
+ )
27695
+ );
27090
27696
  const connection = {
27091
27697
  endpoint: endpointUrl.toString(),
27092
27698
  token: enrollment.token,
@@ -27113,22 +27719,40 @@ async function initialize(source, values) {
27113
27719
  { cause: error3 }
27114
27720
  );
27115
27721
  }
27116
- const notice = await turnSummaryNotice(config3);
27117
- process.stdout.write(
27118
- `${collectorSourceLabel(source)} is connected to ${enrollment.organizationName}. Existing sessions are importing, newest first, and new activity is collected automatically. Iteration shows the import as it runs.${notice}
27119
- `
27120
- );
27121
- return config3;
27722
+ const turnSummary = await setUpTurnSummary(config3);
27723
+ print(connectedLine(source, await countSavedSessions(source, selectedHome)));
27724
+ return {
27725
+ config: config3,
27726
+ result: { source, endpoint: config3.endpoint, turnSummary }
27727
+ };
27122
27728
  }
27123
27729
  async function approveAllSources(sources, workspaceName, yes) {
27124
- const names = sources.map(
27125
- ({ source, sessions }) => `${collectorSourceLabel(source)} (${sessions.toLocaleString("en-US")} saved ${sessions === 1 ? "session" : "sessions"})`
27126
- ).join(" and ");
27127
27730
  const safeName = safeWorkspaceName(workspaceName);
27128
- process.stdout.write(
27129
- `Detected ${names || "no saved agent sessions"} on this computer.
27130
- Connect supported agents${safeName ? ` to ${safeName}` : " to the workspace you select"}? Existing sessions and future activity, including prompts, code, and tool output, will be uploaded. Workspace members can read them. Newly detected supported agents will connect automatically.${process.platform === "linux" ? " Collection will continue after you log out." : ""}
27131
- `
27731
+ print(
27732
+ wrap(
27733
+ terminal,
27734
+ sources.length === 0 ? "No saved agent sessions found on this computer" : `Found ${sources.length} coding ${sources.length === 1 ? "agent" : "agents"} on this computer`,
27735
+ { style: terminal.bold }
27736
+ ),
27737
+ ...sources.length === 0 ? [] : [
27738
+ "",
27739
+ rows(
27740
+ terminal,
27741
+ sources.map(({ source, sessions }) => [
27742
+ collectorSourceLabel(source),
27743
+ terminal.dim(
27744
+ `${sessions.toLocaleString("en-US")} saved ${sessions === 1 ? "session" : "sessions"}`
27745
+ )
27746
+ ]),
27747
+ " "
27748
+ )
27749
+ ],
27750
+ "",
27751
+ wrap(
27752
+ terminal,
27753
+ `Existing sessions and new activity, including prompts, code and tool output, upload to ${safeName ?? "your workspace"}, where its members can read them. Supported agents you install later connect automatically.${process.platform === "linux" ? " Collection continues after you log out." : ""}`
27754
+ ),
27755
+ ""
27132
27756
  );
27133
27757
  if (yes) return;
27134
27758
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
@@ -27136,17 +27760,15 @@ Connect supported agents${safeName ? ` to ${safeName}` : " to the workspace you
27136
27760
  "Run iteration connect interactively or pass --yes to approve uploads."
27137
27761
  );
27138
27762
  }
27139
- const prompt = createInterface2({
27140
- input: process.stdin,
27141
- output: process.stdout
27142
- });
27143
- try {
27144
- const answer = (await prompt.question("Connect agents? [y/N] ")).trim().toLowerCase();
27145
- if (answer !== "y" && answer !== "yes")
27146
- throw new Error("No agents were connected.");
27147
- } finally {
27148
- prompt.close();
27149
- }
27763
+ const answer = await ask(
27764
+ terminal,
27765
+ `${terminal.bold(sources.length === 1 ? "Connect this agent?" : "Connect these agents?")} ${terminal.dim("(y/N)")}`
27766
+ );
27767
+ const approved = answer?.trim().toLowerCase();
27768
+ if (approved !== "y" && approved !== "yes")
27769
+ throw new Error(
27770
+ "No agents were connected. Run iteration connect when you are ready."
27771
+ );
27150
27772
  }
27151
27773
  async function connectAll(values) {
27152
27774
  requireCollectorPlatform();
@@ -27157,13 +27779,13 @@ async function connectAll(values) {
27157
27779
  }
27158
27780
  const configs = await Promise.all(COLLECTOR_SOURCES2.map(connectedConfig));
27159
27781
  const resolveSourceHomes = () => ({
27160
- codex: path29.resolve(
27782
+ codex: path30.resolve(
27161
27783
  optionalString(values, "codex-home") ?? (configs[0] && "codexHome" in configs[0] ? configs[0].codexHome : sourceHome("codex"))
27162
27784
  ),
27163
- claude: path29.resolve(
27785
+ claude: path30.resolve(
27164
27786
  optionalString(values, "claude-home") ?? (configs[1] && "claudeHome" in configs[1] ? configs[1].claudeHome : sourceHome("claude"))
27165
27787
  ),
27166
- cursor: path29.resolve(
27788
+ cursor: path30.resolve(
27167
27789
  optionalString(values, "cursor-home") ?? (configs[2] && "cursorHome" in configs[2] ? configs[2].cursorHome : sourceHome("cursor"))
27168
27790
  )
27169
27791
  });
@@ -27172,12 +27794,23 @@ async function connectAll(values) {
27172
27794
  const existing = COLLECTOR_SOURCES2.flatMap(
27173
27795
  (source, index) => configs[index] ? [{ source, config: configs[index] }] : []
27174
27796
  );
27797
+ print(brand(terminal), "");
27175
27798
  if (detected.length === 0 && existing.length === 0) {
27176
- process.stdout.write(
27177
- "No supported local coding agents found yet. Run iteration connect after using Codex, Claude Code, or Cursor on this computer.\n"
27799
+ print(
27800
+ mark(terminal, "warning", "No supported local coding agents found yet"),
27801
+ wrap(
27802
+ terminal,
27803
+ `Run ${terminal.bold("iteration connect")} after using Codex, Claude Code or Cursor on this computer.`
27804
+ )
27178
27805
  );
27179
27806
  return;
27180
27807
  }
27808
+ const sessions = await Promise.all(
27809
+ detected.map(async (source) => ({
27810
+ source,
27811
+ sessions: await countSavedSessions(source, sourceHomes[source])
27812
+ }))
27813
+ );
27181
27814
  const anchorSource = existing[0]?.source ?? detected[0];
27182
27815
  const anchorExisting = existing[0]?.config ?? null;
27183
27816
  const endpoint = validateCollectorEndpoint(
@@ -27216,12 +27849,7 @@ async function connectAll(values) {
27216
27849
  const needsApproval = () => previousConsent === null || anchorExisting === null || previousConsent.endpoint !== endpoint || previousConsent.anchorSource !== anchorSource || previousConsent.anchorDataDirectory !== anchorExisting.dataDirectory || previousConsent.organizationId !== existingScopes[0]?.scope.organizationId || previousConsent.sourceHomes.codex !== sourceHomes.codex || previousConsent.sourceHomes.claude !== sourceHomes.claude || previousConsent.sourceHomes.cursor !== sourceHomes.cursor;
27217
27850
  if (needsApproval()) {
27218
27851
  await approveAllSources(
27219
- await Promise.all(
27220
- detected.map(async (source) => ({
27221
- source,
27222
- sessions: await countSavedSessions(source, sourceHomes[source])
27223
- }))
27224
- ),
27852
+ sessions,
27225
27853
  existingScopes[0]?.scope.organizationName ?? null,
27226
27854
  values.yes === true
27227
27855
  );
@@ -27229,7 +27857,13 @@ async function connectAll(values) {
27229
27857
  };
27230
27858
  await approveConnection();
27231
27859
  await prepareBackgroundPersistence();
27232
- let anchor3 = anchorExisting ?? await initialize(anchorSource, values);
27860
+ const results = [];
27861
+ const initializeAnchor = async () => {
27862
+ const initialized = await initialize(anchorSource, values);
27863
+ results.push(initialized.result);
27864
+ return initialized.config;
27865
+ };
27866
+ let anchor3 = anchorExisting ?? await initializeAnchor();
27233
27867
  let organizationId = requestedOrganizationId ?? existingScopes[0]?.scope.organizationId ?? anchor3.organizationId ?? null;
27234
27868
  const connectDetectedSources = async () => {
27235
27869
  for (const source of detected) {
@@ -27251,10 +27885,16 @@ async function connectAll(values) {
27251
27885
  state
27252
27886
  );
27253
27887
  organizationId = enrollment.organizationId;
27254
- const notice = await turnSummaryNotice(config3);
27255
- process.stdout.write(
27256
- `${collectorSourceLabel(source)} is connected to ${enrollment.organizationName}.${notice}
27257
- `
27888
+ results.push({
27889
+ source,
27890
+ endpoint: config3.endpoint,
27891
+ turnSummary: await setUpTurnSummary(config3)
27892
+ });
27893
+ print(
27894
+ connectedLine(
27895
+ source,
27896
+ sessions.find((item) => item.source === source)?.sessions ?? 0
27897
+ )
27258
27898
  );
27259
27899
  }
27260
27900
  };
@@ -27285,15 +27925,20 @@ async function connectAll(values) {
27285
27925
  item.config.dataDirectory
27286
27926
  );
27287
27927
  await installBackgroundService(item.config.dataDirectory, item.source);
27288
- const notice = await turnSummaryNotice(item.config);
27289
- process.stdout.write(
27290
- `${collectorSourceLabel(item.source)} is still connected.${notice}
27291
- `
27928
+ results.push({
27929
+ source: item.source,
27930
+ endpoint: item.config.endpoint,
27931
+ turnSummary: await setUpTurnSummary(item.config)
27932
+ });
27933
+ print(
27934
+ mark(
27935
+ terminal,
27936
+ "success",
27937
+ `${collectorSourceLabel(item.source)} is still connected`
27938
+ )
27292
27939
  );
27293
27940
  }
27294
- process.stdout.write(
27295
- "Detected agents are connected. New supported agents on this computer will connect automatically.\n"
27296
- );
27941
+ print(...connectionSummary2(results, results.length > existing.length));
27297
27942
  }
27298
27943
  async function importHistory(source, values) {
27299
27944
  requireCollectorPlatform();
@@ -27304,22 +27949,47 @@ async function importHistory(source, values) {
27304
27949
  throw new Error(
27305
27950
  `This collector directory belongs to ${collectorSource(config3)}.`
27306
27951
  );
27952
+ const name = collectorSourceLabel(source);
27307
27953
  const estimate = (await importSourceHistory(config3, paths, false)).size;
27308
- process.stdout.write(
27309
- `Found ${estimate.files} local ${source} session files (${estimate.bytes} bytes). History may include prompts, code, and tool output that workspace members can read.
27310
- `
27954
+ print(
27955
+ wrap(
27956
+ terminal,
27957
+ `Found ${estimate.files.toLocaleString("en-US")} local ${name} session files (${readableBytes(estimate.bytes)})`,
27958
+ { indent: "", style: terminal.bold }
27959
+ ),
27960
+ wrap(
27961
+ terminal,
27962
+ "History may include prompts, code and tool output that workspace members can read."
27963
+ )
27311
27964
  );
27312
27965
  if (values.yes !== true) {
27313
- process.stdout.write(
27314
- `No changes made. Run iteration import-history ${source} --yes to confirm this upload.
27315
- `
27966
+ print(
27967
+ mark(
27968
+ terminal,
27969
+ "warning",
27970
+ `No changes made. Run ${terminal.bold(`iteration import-history ${source} --yes`)} to confirm this upload.`
27971
+ )
27316
27972
  );
27317
27973
  return;
27318
27974
  }
27319
27975
  const result = await importSourceHistory(config3, paths, true);
27320
- process.stdout.write(
27321
- `History scan scheduled for ${result.size.files} local session files (${result.size.bytes} bytes). Scanning and uploads run in bounded batches and may take time. Older sessions appear under the date Iteration receives them. Use iteration status ${source} to see local scan progress and pending uploads.${result.backgroundRunning ? "" : ` The collector was not running; run iteration start ${source} to begin scanning.`}
27322
- `
27976
+ print(
27977
+ mark(
27978
+ terminal,
27979
+ "success",
27980
+ `History scan scheduled for ${result.size.files.toLocaleString("en-US")} local session files (${readableBytes(result.size.bytes)})`
27981
+ ),
27982
+ wrap(
27983
+ terminal,
27984
+ `Scanning and uploads run in bounded batches and may take time. Older sessions appear under the date Iteration receives them. Run ${terminal.bold(`iteration status ${source}`)} to see local scan progress and pending uploads.`
27985
+ ),
27986
+ ...result.backgroundRunning ? [] : [
27987
+ mark(
27988
+ terminal,
27989
+ "warning",
27990
+ `The collector was not running. Run ${terminal.bold(`iteration start ${source}`)} to begin scanning.`
27991
+ )
27992
+ ]
27323
27993
  );
27324
27994
  }
27325
27995
  async function start(source, values) {
@@ -27335,10 +28005,20 @@ async function start(source, values) {
27335
28005
  if ("cursorHome" in config3)
27336
28006
  await installCursorHooks(config3.cursorHome, config3.dataDirectory);
27337
28007
  await installBackgroundService(directory, source);
27338
- const notice = await turnSummaryNotice(config3);
27339
- process.stdout.write(
27340
- `${collectorSourceLabel(source)} is collecting again. Run iteration to check progress.${repairedState ? " Incomplete setup was repaired." : ""}${notice}
27341
- `
28008
+ const turnSummary = await setUpTurnSummary(config3);
28009
+ print(
28010
+ mark(
28011
+ terminal,
28012
+ "success",
28013
+ `${collectorSourceLabel(source)} is collecting again`
28014
+ ),
28015
+ ...repairedState ? [
28016
+ wrap(terminal, "Incomplete setup was repaired.", {
28017
+ style: terminal.dim
28018
+ })
28019
+ ] : [],
28020
+ ...turnSummaryLines([{ source, endpoint: config3.endpoint, turnSummary }]),
28021
+ wrap(terminal, `Run ${terminal.bold("iteration")} to check progress.`)
27342
28022
  );
27343
28023
  }
27344
28024
  async function statusSnapshot(source, values) {
@@ -27380,16 +28060,18 @@ async function statusSnapshot(source, values) {
27380
28060
  healthAvailable: localHealth.kind === "available",
27381
28061
  turnSummaryNeedsApproval: approval === "needs_approval",
27382
28062
  hookFailureAtMs,
27383
- tracesUrl: new URL("/app/sessions", config3.endpoint).toString(),
28063
+ tracesUrl: tracesUrl(config3.endpoint),
27384
28064
  logPath: collectorLogPath(source)
27385
28065
  };
27386
28066
  }
27387
28067
  async function status(source, values) {
27388
28068
  if (source !== void 0) {
27389
- const snapshot = await statusSnapshot(source, values);
27390
- process.stdout.write(
27391
- `${renderDetailedStatus(snapshot, Date.now(), source)}
27392
- `
28069
+ print(
28070
+ renderDetailedStatus(
28071
+ terminal,
28072
+ source,
28073
+ await statusSnapshot(source, values)
28074
+ )
27393
28075
  );
27394
28076
  return;
27395
28077
  }
@@ -27399,9 +28081,10 @@ async function status(source, values) {
27399
28081
  snapshot: await statusSnapshot(item, values)
27400
28082
  }))
27401
28083
  );
27402
- process.stdout.write(
27403
- `${snapshots.map(({ source: item, snapshot }) => renderDetailedStatus(snapshot, Date.now(), item)).join("\n\n")}
27404
- `
28084
+ print(
28085
+ snapshots.map(
28086
+ ({ source: item, snapshot }) => renderDetailedStatus(terminal, item, snapshot)
28087
+ ).join("\n\n")
27405
28088
  );
27406
28089
  }
27407
28090
  var ROLLBACK_NOTICE_MS = 7 * 24 * 60 * 60 * 1e3;
@@ -27411,7 +28094,7 @@ async function runtimeSummaryText() {
27411
28094
  if (state === null) return null;
27412
28095
  const settings = await readRuntimeSettings(paths);
27413
28096
  const rejected = state.rejected.at(-1);
27414
- return renderRuntime({
28097
+ return renderRuntime(terminal, {
27415
28098
  version: state.current,
27416
28099
  autoUpdate: settings.autoUpdate,
27417
28100
  confirming: state.trial?.version ?? null,
@@ -27469,10 +28152,15 @@ async function waitForTrial(to) {
27469
28152
  `Version ${to} did not start and Iteration returned to ${state.current}. ${rejected?.reason ?? ""}`.trim()
27470
28153
  );
27471
28154
  }
27472
- if (state?.trial === null) return `Iteration is updated to ${to}.`;
28155
+ if (state?.trial === null)
28156
+ return mark(terminal, "success", `Iteration is updated to ${to}`);
27473
28157
  await new Promise((resolve) => setTimeout(resolve, 1e3));
27474
28158
  }
27475
- return `Iteration is updated to ${to}; collectors are still starting. Run iteration to check.`;
28159
+ return mark(
28160
+ terminal,
28161
+ "warning",
28162
+ `Iteration is updated to ${to}; collectors are still starting. Run ${terminal.bold("iteration")} to check.`
28163
+ );
27476
28164
  }
27477
28165
  async function update(setting, values) {
27478
28166
  requireCollectorPlatform();
@@ -27489,8 +28177,16 @@ async function update(setting, values) {
27489
28177
  ...setting === void 0 ? {} : { autoUpdate: setting === "on" },
27490
28178
  ...registry3 === null ? {} : { registry: validateRegistryUrl(registry3).toString() }
27491
28179
  });
27492
- process.stdout.write(
27493
- setting === "off" ? "Automatic updates are off. Run iteration update to update.\n" : setting === "on" ? "Automatic updates are on.\n" : "The update registry is saved.\n"
28180
+ print(
28181
+ setting === "off" ? mark(
28182
+ terminal,
28183
+ "success",
28184
+ `Automatic updates are off. Run ${terminal.bold("iteration update")} to update.`
28185
+ ) : mark(
28186
+ terminal,
28187
+ "success",
28188
+ setting === "on" ? "Automatic updates are on" : "The update registry is saved"
28189
+ )
27494
28190
  );
27495
28191
  return;
27496
28192
  }
@@ -27500,33 +28196,56 @@ async function update(setting, values) {
27500
28196
  throw new Error(
27501
28197
  "No collector is set up on this computer. Run iteration connect first."
27502
28198
  );
28199
+ const stopChecking = startSpinner(
28200
+ process.stdout,
28201
+ terminal,
28202
+ "Checking for updates\u2026"
28203
+ );
27503
28204
  const outcome = await updateRuntime(paths, {
27504
28205
  manual: true,
27505
28206
  expected,
27506
28207
  nowMs: Date.now(),
27507
28208
  signal: AbortSignal.timeout(6e5)
27508
- });
28209
+ }).finally(stopChecking);
27509
28210
  if (outcome.kind === "busy") {
27510
- process.stdout.write(
27511
- "Another update is in progress. Run iteration to check.\n"
28211
+ print(
28212
+ mark(
28213
+ terminal,
28214
+ "warning",
28215
+ `Another update is in progress. Run ${terminal.bold("iteration")} to check.`
28216
+ )
27512
28217
  );
27513
28218
  return;
27514
28219
  }
27515
28220
  if (outcome.kind === "up_to_date") {
27516
- process.stdout.write(
27517
- `Iteration ${outcome.version} is the latest version.
27518
- `
28221
+ print(
28222
+ mark(
28223
+ terminal,
28224
+ "success",
28225
+ `Iteration ${outcome.version} is the latest version`
28226
+ )
27519
28227
  );
27520
28228
  return;
27521
28229
  }
27522
28230
  if (outcome.kind === "waiting") {
27523
- process.stdout.write(`No update was installed: ${outcome.reason}.
27524
- `);
28231
+ print(
28232
+ mark(terminal, "warning", `No update was installed: ${outcome.reason}.`)
28233
+ );
27525
28234
  return;
27526
28235
  }
27527
- await refreshBackgroundServices(true);
27528
- process.stdout.write(`${await waitForTrial(outcome.to)}
27529
- `);
28236
+ const stopStarting = startSpinner(
28237
+ process.stdout,
28238
+ terminal,
28239
+ `Starting Iteration ${outcome.to}\u2026`
28240
+ );
28241
+ let result;
28242
+ try {
28243
+ await refreshBackgroundServices(true);
28244
+ result = await waitForTrial(outcome.to);
28245
+ } finally {
28246
+ stopStarting();
28247
+ }
28248
+ print(result);
27530
28249
  }
27531
28250
  async function runInternalCommand() {
27532
28251
  if (process.argv[2] === "supervise") {
@@ -27559,7 +28278,14 @@ async function runInternalCommand() {
27559
28278
  }
27560
28279
  return false;
27561
28280
  }
28281
+ var BACKGROUND_COMMANDS = /* @__PURE__ */ new Set([
28282
+ "run",
28283
+ "supervise",
28284
+ "claude-git-hook",
28285
+ "turn-summary-hook"
28286
+ ]);
27562
28287
  async function main() {
28288
+ if (!BACKGROUND_COMMANDS.has(process.argv[2] ?? "")) silenceCollectorLogs();
27563
28289
  if (await runInternalCommand()) return;
27564
28290
  const delegated = await delegateToInstalledVersion();
27565
28291
  if (delegated !== null) {
@@ -27585,6 +28311,9 @@ async function dispatchCommand({
27585
28311
  if (command === "connect" && source === void 0) {
27586
28312
  return connectAll(values);
27587
28313
  }
28314
+ if (command === "logout") {
28315
+ return signOut(source, values);
28316
+ }
27588
28317
  if (command === "") {
27589
28318
  return showHome(values);
27590
28319
  }
@@ -27598,6 +28327,30 @@ async function dispatchCommand({
27598
28327
  if (command === "update") return update(source, values);
27599
28328
  return dispatchSourceCommand(command, source, values, selectedSource);
27600
28329
  }
28330
+ async function signOut(source, values) {
28331
+ if (source !== void 0 || Object.keys(values).some((name) => name !== "data-directory"))
28332
+ throw new Error(
28333
+ "Run iteration logout without a source. Only --data-directory is supported."
28334
+ );
28335
+ await logout(optionalString(values, "data-directory") ?? void 0);
28336
+ print(
28337
+ mark(
28338
+ terminal,
28339
+ "success",
28340
+ terminal.bold("Signed out of Iteration on this computer")
28341
+ ),
28342
+ "",
28343
+ wrap(
28344
+ terminal,
28345
+ "Collection stopped and saved credentials were removed. Local pending data was archived. Agent sessions and uploaded data were kept."
28346
+ ),
28347
+ "",
28348
+ wrap(
28349
+ terminal,
28350
+ `Run ${terminal.bold("iteration connect")} to sign in again.`
28351
+ )
28352
+ );
28353
+ }
27601
28354
  async function showHome(values) {
27602
28355
  if (Object.keys(values).length > 0) {
27603
28356
  throw new Error(
@@ -27607,9 +28360,7 @@ async function showHome(values) {
27607
28360
  if (isCollectorPlatform()) await adoptRuntime();
27608
28361
  await defaultCommand();
27609
28362
  const summary = await runtimeSummaryText();
27610
- if (summary !== null) process.stdout.write(`
27611
- ${summary}
27612
- `);
28363
+ if (summary !== null) print("", summary);
27613
28364
  }
27614
28365
  async function disconnect(selectedSource, values) {
27615
28366
  await uninstallBackgroundService(selectedSource);
@@ -27620,8 +28371,13 @@ async function disconnect(selectedSource, values) {
27620
28371
  await uninstallCursorHooks(config3.cursorHome, config3.dataDirectory);
27621
28372
  else await uninstallTurnSummary(config3);
27622
28373
  }
27623
- process.stdout.write(
27624
- "Collector startup removed. Local pending data was retained.\n"
28374
+ print(
28375
+ mark(
28376
+ terminal,
28377
+ "success",
28378
+ `${collectorSourceLabel(selectedSource)} is disconnected`
28379
+ ),
28380
+ wrap(terminal, "Collection stopped. Local pending data was kept.")
27625
28381
  );
27626
28382
  }
27627
28383
  async function dispatchSourceCommand(command, source, values, selectedSource) {
@@ -27636,7 +28392,9 @@ async function dispatchSourceCommand(command, source, values, selectedSource) {
27636
28392
  };
27637
28393
  validateSourceOptions();
27638
28394
  if (command === "connect" && selectedSource !== null) {
27639
- await initialize(selectedSource, values);
28395
+ print(brand(terminal), "");
28396
+ const { result } = await initialize(selectedSource, values);
28397
+ print(...connectionSummary2([result], true));
27640
28398
  return;
27641
28399
  }
27642
28400
  if (command === "run") {
@@ -27668,9 +28426,7 @@ async function showStatus(source, selectedSource, values) {
27668
28426
  await adoptRuntime();
27669
28427
  await status(selectedSource ?? void 0, values);
27670
28428
  const summary = await runtimeSummaryText();
27671
- if (summary !== null) process.stdout.write(`
27672
- ${summary}
27673
- `);
28429
+ if (summary !== null) print("", summary);
27674
28430
  }
27675
28431
  var background = process.argv[2] === "run";
27676
28432
  main().then(
@@ -27678,8 +28434,9 @@ main().then(
27678
28434
  if (background) process.exit(process.exitCode ?? 0);
27679
28435
  },
27680
28436
  (error3) => {
28437
+ const message = error3 instanceof Error ? error3.message : "Unknown Iteration CLI error.";
27681
28438
  process.stderr.write(
27682
- `${error3 instanceof Error ? error3.message : "Unknown Iteration CLI error."}
28439
+ `${process.stderr.isTTY ? mark(terminalFor(process.stderr), "failure", message) : message}
27683
28440
  `
27684
28441
  );
27685
28442
  process.exitCode = 1;