tenjin-cli 0.1.0-alpha.1 → 0.1.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/NOTICE.md +33 -0
  2. package/README.md +167 -16
  3. package/dist/{_esm-ZH2J4QEH.js → _esm-C5CRWCYU.js} +2 -2
  4. package/dist/_esm-FEASBWRP.js +881 -0
  5. package/dist/buy-EE6SEXP6.js +1598 -0
  6. package/dist/buy-EE6SEXP6.js.map +1 -0
  7. package/dist/candidate-ERMSYYQZ.js +127 -0
  8. package/dist/candidate-ERMSYYQZ.js.map +1 -0
  9. package/dist/{ccip-UCLT5VOW.js → ccip-NQXCEK2U.js} +6 -5
  10. package/dist/ccip-XR5NE5QK.js +19 -0
  11. package/dist/chunk-2I4QTOLB.js +11 -0
  12. package/dist/chunk-2I4QTOLB.js.map +1 -0
  13. package/dist/chunk-3OV7E5G5.js +18 -0
  14. package/dist/chunk-3OV7E5G5.js.map +1 -0
  15. package/dist/chunk-4ONXEEQL.js +152 -0
  16. package/dist/chunk-4ONXEEQL.js.map +1 -0
  17. package/dist/chunk-5CLSD5YN.js +209 -0
  18. package/dist/chunk-5CLSD5YN.js.map +1 -0
  19. package/dist/chunk-662MSGZB.js +286 -0
  20. package/dist/chunk-662MSGZB.js.map +1 -0
  21. package/dist/chunk-7KUW4MJD.js +59 -0
  22. package/dist/chunk-7KUW4MJD.js.map +1 -0
  23. package/dist/{doctor-3QBYN46N.js → chunk-AWPAWHNX.js} +88 -93
  24. package/dist/chunk-AWPAWHNX.js.map +1 -0
  25. package/dist/chunk-CYOF7ROH.js +70 -0
  26. package/dist/chunk-CYOF7ROH.js.map +1 -0
  27. package/dist/chunk-DXTQ3CSI.js +171 -0
  28. package/dist/chunk-DXTQ3CSI.js.map +1 -0
  29. package/dist/{chunk-EZROUI5U.js → chunk-ESPNTPQ2.js} +80 -8
  30. package/dist/chunk-ESPNTPQ2.js.map +1 -0
  31. package/dist/chunk-FJPLRISB.js +79 -0
  32. package/dist/chunk-FJPLRISB.js.map +1 -0
  33. package/dist/chunk-GO75V3NZ.js +160 -0
  34. package/dist/chunk-GO75V3NZ.js.map +1 -0
  35. package/dist/chunk-HIVZG55D.js +204 -0
  36. package/dist/chunk-HIVZG55D.js.map +1 -0
  37. package/dist/chunk-HSDCI7OV.js +7806 -0
  38. package/dist/chunk-HSDCI7OV.js.map +1 -0
  39. package/dist/chunk-JPHG2JW3.js +96 -0
  40. package/dist/chunk-JPHG2JW3.js.map +1 -0
  41. package/dist/{chunk-ZPZFPVDN.js → chunk-MUBUQVC3.js} +1 -1
  42. package/dist/chunk-MUBUQVC3.js.map +1 -0
  43. package/dist/{chunk-T4LKNY7T.js → chunk-NCE5NSN6.js} +166 -11
  44. package/dist/chunk-NCE5NSN6.js.map +1 -0
  45. package/dist/{chunk-YG2DO46P.js → chunk-OYMYCW7J.js} +18 -3
  46. package/dist/{chunk-YG2DO46P.js.map → chunk-OYMYCW7J.js.map} +1 -1
  47. package/dist/{chunk-Q53IYV2G.js → chunk-QVX5MWJZ.js} +20 -17
  48. package/dist/{chunk-Q53IYV2G.js.map → chunk-QVX5MWJZ.js.map} +1 -1
  49. package/dist/{chunk-CUWUHTIL.js → chunk-RBJPAZFI.js} +16 -202
  50. package/dist/chunk-RBJPAZFI.js.map +1 -0
  51. package/dist/chunk-RRN3YTK7.js +6199 -0
  52. package/dist/chunk-RRN3YTK7.js.map +1 -0
  53. package/dist/chunk-RY4XKNV3.js +140 -0
  54. package/dist/chunk-RY4XKNV3.js.map +1 -0
  55. package/dist/chunk-S3IGX57D.js +14682 -0
  56. package/dist/chunk-S3IGX57D.js.map +1 -0
  57. package/dist/chunk-TLCMMYLY.js +126 -0
  58. package/dist/chunk-TLCMMYLY.js.map +1 -0
  59. package/dist/{chunk-IPOWB3G3.js → chunk-UGX7YPX2.js} +3314 -306
  60. package/dist/chunk-UGX7YPX2.js.map +1 -0
  61. package/dist/chunk-UO22YNY4.js +69 -0
  62. package/dist/chunk-UO22YNY4.js.map +1 -0
  63. package/dist/{config-CEFTL5ZL.js → chunk-XHC6FCGZ.js} +115 -18
  64. package/dist/chunk-XHC6FCGZ.js.map +1 -0
  65. package/dist/chunk-XJIW7USF.js +217 -0
  66. package/dist/chunk-XJIW7USF.js.map +1 -0
  67. package/dist/{chunk-BRJHUQSY.js → chunk-YALGASEU.js} +1548 -1452
  68. package/dist/chunk-YALGASEU.js.map +1 -0
  69. package/dist/{chunk-DXPYFVKG.js → chunk-YN5SHIXQ.js} +6 -6
  70. package/dist/chunk-YN5SHIXQ.js.map +1 -0
  71. package/dist/chunk-Z52RA3NC.js +137 -0
  72. package/dist/chunk-Z52RA3NC.js.map +1 -0
  73. package/dist/{chunk-EXBMF5X7.js → chunk-Z6MFJV5Z.js} +151 -19
  74. package/dist/chunk-Z6MFJV5Z.js.map +1 -0
  75. package/dist/chunk-ZABPQJ3M.js +83 -0
  76. package/dist/chunk-ZABPQJ3M.js.map +1 -0
  77. package/dist/{chunk-LPRVHM7P.js → chunk-ZMHYXMO6.js} +1655 -114
  78. package/dist/chunk-ZMHYXMO6.js.map +1 -0
  79. package/dist/{chunk-3IMLRUZE.js → chunk-ZXTAQYNA.js} +6 -2
  80. package/dist/{cli-WA65NP4Y.js → cli-SBXI5AMS.js} +177 -177
  81. package/dist/cli-SBXI5AMS.js.map +1 -0
  82. package/dist/config-VELDKLHY.js +21 -0
  83. package/dist/doctor-T3KWNNP2.js +20 -0
  84. package/dist/doctor-T3KWNNP2.js.map +1 -0
  85. package/dist/ethersCompat-Df4a6QIZ-3YZIAXDK.js +18 -0
  86. package/dist/ethersCompat-Df4a6QIZ-3YZIAXDK.js.map +1 -0
  87. package/dist/index.js +1 -1
  88. package/dist/inspect-LMKOXE4Y.js +96 -0
  89. package/dist/inspect-LMKOXE4Y.js.map +1 -0
  90. package/dist/install-LEX3ENQ6.js +387 -0
  91. package/dist/install-LEX3ENQ6.js.map +1 -0
  92. package/dist/lookup-ZPN2Q67N.js +129 -0
  93. package/dist/lookup-ZPN2Q67N.js.map +1 -0
  94. package/dist/{mine.wasm-GQECMSGN.js → mine.wasm-6PIT3DK6.js} +2 -2
  95. package/dist/outcome-N7TAK6WR.js +66 -0
  96. package/dist/outcome-N7TAK6WR.js.map +1 -0
  97. package/dist/publish-BKBQQAW4.js +1478 -0
  98. package/dist/publish-BKBQQAW4.js.map +1 -0
  99. package/dist/{secp256k1-BEZS642W.js → secp256k1-N3ZHU7LB.js} +5 -4
  100. package/dist/secp256k1-N3ZHU7LB.js.map +1 -0
  101. package/dist/usdc-JIAJW4SV.js +22 -0
  102. package/dist/usdc-JIAJW4SV.js.map +1 -0
  103. package/dist/viemAdapter-By13KInL-ZZE6UV4Y.js +14 -0
  104. package/dist/viemAdapter-By13KInL-ZZE6UV4Y.js.map +1 -0
  105. package/dist/{wallet-XD576HF3.js → wallet-CWEMYVIH.js} +28 -22
  106. package/dist/{wallet-XD576HF3.js.map → wallet-CWEMYVIH.js.map} +1 -1
  107. package/dist/wallet-PA54CRBL.js +30 -0
  108. package/dist/wallet-PA54CRBL.js.map +1 -0
  109. package/package.json +19 -16
  110. package/skills/tenjin/SKILL.md +199 -0
  111. package/skills/tenjin-publish/SKILL.md +111 -0
  112. package/skills/tenjin-search/SKILL.md +133 -0
  113. package/dist/chunk-BRJHUQSY.js.map +0 -1
  114. package/dist/chunk-CUWUHTIL.js.map +0 -1
  115. package/dist/chunk-DXPYFVKG.js.map +0 -1
  116. package/dist/chunk-EXBMF5X7.js.map +0 -1
  117. package/dist/chunk-EZROUI5U.js.map +0 -1
  118. package/dist/chunk-IPOWB3G3.js.map +0 -1
  119. package/dist/chunk-LPRVHM7P.js.map +0 -1
  120. package/dist/chunk-T4LKNY7T.js.map +0 -1
  121. package/dist/chunk-ZPZFPVDN.js.map +0 -1
  122. package/dist/cli-WA65NP4Y.js.map +0 -1
  123. package/dist/config-CEFTL5ZL.js.map +0 -1
  124. package/dist/doctor-3QBYN46N.js.map +0 -1
  125. package/dist/usdc-44R6XZF2.js +0 -18
  126. package/dist/wallet-ELBTBMXO.js +0 -20
  127. /package/dist/{_esm-ZH2J4QEH.js.map → _esm-C5CRWCYU.js.map} +0 -0
  128. /package/dist/{ccip-UCLT5VOW.js.map → _esm-FEASBWRP.js.map} +0 -0
  129. /package/dist/{chunk-3IMLRUZE.js.map → ccip-NQXCEK2U.js.map} +0 -0
  130. /package/dist/{secp256k1-BEZS642W.js.map → ccip-XR5NE5QK.js.map} +0 -0
  131. /package/dist/{usdc-44R6XZF2.js.map → chunk-ZXTAQYNA.js.map} +0 -0
  132. /package/dist/{wallet-ELBTBMXO.js.map → config-VELDKLHY.js.map} +0 -0
  133. /package/dist/{mine.wasm-GQECMSGN.js.map → mine.wasm-6PIT3DK6.js.map} +0 -0
@@ -3,29 +3,53 @@ import {
3
3
  CliError,
4
4
  configPath,
5
5
  external_exports
6
- } from "./chunk-YG2DO46P.js";
6
+ } from "./chunk-OYMYCW7J.js";
7
7
 
8
8
  // src/lib/config.ts
9
9
  import { readFile } from "fs/promises";
10
10
  var atomicString = external_exports.string().regex(/^\d+$/, "expected an atomic USDC integer string");
11
+ var PublishModeSchema = external_exports.enum(["review", "auto", "full-auto"]);
12
+ function parsePublishModeFlag(value, flagName) {
13
+ const parsed = PublishModeSchema.safeParse(value);
14
+ if (parsed.success) return parsed.data;
15
+ throw new CliError("USAGE", `Invalid ${flagName} ${JSON.stringify(value)}`, {
16
+ fix: 'Use "review", "auto", or "full-auto".'
17
+ });
18
+ }
19
+ var PublishConfigSchema = external_exports.object({
20
+ mode: PublishModeSchema,
21
+ defaultPrice: atomicString
22
+ });
11
23
  var ConfigSchema = external_exports.object({
12
24
  maxAutoSpend: atomicString,
13
25
  sessionBudget: atomicString,
14
26
  confirm: external_exports.union([external_exports.literal("always"), external_exports.string().regex(/^above:\d+$/)]),
15
27
  allowlistCreators: external_exports.array(external_exports.string()),
16
28
  baseUrl: external_exports.url(),
17
- rpcUrl: external_exports.url()
29
+ rpcUrl: external_exports.url(),
30
+ /**
31
+ * Evaluation-cohort opt-in (spec 09 §3): when true, lookup sends
32
+ * X-Tenjin-Eval-Cohort: 1 and the server stores the generalized question for
33
+ * 90 days. Off by default; no query text is retained server-side without it.
34
+ */
35
+ evalCohort: external_exports.boolean(),
36
+ publish: PublishConfigSchema
18
37
  });
19
- var RawConfigSchema = ConfigSchema.partial();
38
+ var RawConfigSchema = ConfigSchema.partial().extend({ publish: PublishConfigSchema.partial().passthrough().optional() }).passthrough();
20
39
  var CONFIG_DEFAULTS = {
21
40
  maxAutoSpend: "0",
22
41
  sessionBudget: "0",
23
42
  confirm: "always",
24
43
  allowlistCreators: [],
25
44
  baseUrl: "https://tenjin.blog",
26
- rpcUrl: "https://mainnet.base.org"
45
+ rpcUrl: "https://mainnet.base.org",
46
+ evalCohort: false,
47
+ publish: { mode: "review", defaultPrice: "100000" }
27
48
  };
28
- var CONFIG_KEYS = Object.keys(CONFIG_DEFAULTS);
49
+ var CONFIG_KEYS = Object.keys(CONFIG_DEFAULTS).filter(
50
+ (key) => key !== "publish"
51
+ );
52
+ var PUBLISH_CONFIG_KEYS = ["publish.mode", "publish.defaultPrice"];
29
53
  async function loadRawConfig(dir) {
30
54
  const path = configPath(dir);
31
55
  let raw;
@@ -57,16 +81,58 @@ async function loadRawConfig(dir) {
57
81
  return parsed.data;
58
82
  }
59
83
  function resolveSettings(input) {
60
- const { config, flags, env } = input;
84
+ const { config, flags, env, project } = input;
61
85
  return {
62
86
  maxAutoSpend: fileOrDefault("maxAutoSpend", config),
63
87
  sessionBudget: fileOrDefault("sessionBudget", config),
64
88
  confirm: fileOrDefault("confirm", config),
65
89
  allowlistCreators: fileOrDefault("allowlistCreators", config),
66
90
  baseUrl: resolveBaseUrl(config, flags, env),
67
- rpcUrl: fileOrDefault("rpcUrl", config)
91
+ rpcUrl: fileOrDefault("rpcUrl", config),
92
+ evalCohort: fileOrDefault("evalCohort", config),
93
+ publishMode: resolvePublishMode({ config, project, env }),
94
+ publishDefaultPrice: resolvePublishDefaultPrice({ config, project })
68
95
  };
69
96
  }
97
+ var FULL_AUTO_DOWNGRADE_WARNING = 'Ignoring publish.mode "full-auto" from a committed .tenjin.json (cloning a repo must not enable auto-publish); using "auto". Add .tenjin.json to .gitignore to opt in.';
98
+ function coercePublishMode(raw) {
99
+ if (raw === void 0 || raw.length === 0) return void 0;
100
+ const parsed = PublishModeSchema.safeParse(raw);
101
+ return parsed.success ? parsed.data : void 0;
102
+ }
103
+ function resolvePublishMode(input) {
104
+ const { config, project, env, flag } = input;
105
+ let winner = { value: CONFIG_DEFAULTS.publish.mode, source: "default" };
106
+ const fromFile = config.publish?.mode;
107
+ if (fromFile !== void 0) winner = { value: fromFile, source: "file" };
108
+ if (project !== void 0 && project.publish?.mode !== void 0) {
109
+ const fromProject = project.publish.mode;
110
+ if (fromProject === "full-auto" && !project.gitignored) {
111
+ winner = { value: "auto", source: "project", downgradedWarning: FULL_AUTO_DOWNGRADE_WARNING };
112
+ } else {
113
+ winner = { value: fromProject, source: "project" };
114
+ }
115
+ }
116
+ const fromEnv = coercePublishMode(env.TENJIN_PUBLISH_MODE);
117
+ if (fromEnv !== void 0) winner = { value: fromEnv, source: "env" };
118
+ const fromFlag = coercePublishMode(flag);
119
+ if (fromFlag !== void 0) winner = { value: fromFlag, source: "flag" };
120
+ return winner;
121
+ }
122
+ function resolvePublishDefaultPrice(input) {
123
+ const { config, project } = input;
124
+ let result = {
125
+ value: CONFIG_DEFAULTS.publish.defaultPrice,
126
+ source: "default"
127
+ };
128
+ if (config.publish?.defaultPrice !== void 0) {
129
+ result = { value: config.publish.defaultPrice, source: "file" };
130
+ }
131
+ if (project?.publish?.defaultPrice !== void 0) {
132
+ result = { value: project.publish.defaultPrice, source: "project" };
133
+ }
134
+ return result;
135
+ }
70
136
  function fileOrDefault(key, config) {
71
137
  const fromFile = config[key];
72
138
  if (fromFile !== void 0) return { value: fromFile, source: "file" };
@@ -125,11 +191,17 @@ function toMoney(atomic) {
125
191
  }
126
192
 
127
193
  export {
194
+ PublishModeSchema,
195
+ parsePublishModeFlag,
128
196
  RawConfigSchema,
197
+ CONFIG_DEFAULTS,
129
198
  CONFIG_KEYS,
199
+ PUBLISH_CONFIG_KEYS,
130
200
  loadRawConfig,
131
201
  resolveSettings,
202
+ resolvePublishMode,
203
+ resolvePublishDefaultPrice,
132
204
  parseUsdToAtomic,
133
205
  toMoney
134
206
  };
135
- //# sourceMappingURL=chunk-EZROUI5U.js.map
207
+ //# sourceMappingURL=chunk-ESPNTPQ2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/config.ts","../src/lib/money.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { z } from 'zod';\nimport { CliError } from './errors';\nimport { configPath } from './paths';\nimport { writeFileAtomic } from './atomic-json';\n\n/** A non-negative integer string in USDC atomic units (6-decimal base). */\nconst atomicString = z.string().regex(/^\\d+$/, 'expected an atomic USDC integer string');\n\n/** The publish consent mode (B3, D38). `full-auto` is loosening-gated, below. */\nexport const PublishModeSchema = z.enum(['review', 'auto', 'full-auto']);\nexport type PublishMode = z.infer<typeof PublishModeSchema>;\n\n/**\n * Validate a publish-mode value at a command edge (`--mode`, `--publish-mode`):\n * an unrecognized value is USAGE (exit 2), never silently dropped. `flagName` is\n * woven into the message so the failing flag is named.\n */\nexport function parsePublishModeFlag(value: string, flagName: string): PublishMode {\n const parsed = PublishModeSchema.safeParse(value);\n if (parsed.success) return parsed.data;\n throw new CliError('USAGE', `Invalid ${flagName} ${JSON.stringify(value)}`, {\n fix: 'Use \"review\", \"auto\", or \"full-auto\".',\n });\n}\n\n/**\n * The publish block (B3): `mode` governs the confirm cascade a `publish` runs,\n * `defaultPrice` is the atomic USDC price a card is published at when no\n * per-publish price is given. Stored atomic like the spend keys.\n */\nconst PublishConfigSchema = z.object({\n mode: PublishModeSchema,\n defaultPrice: atomicString,\n});\n\n/**\n * The persisted config shape. Spend keys are stored atomic (accepted as decimal\n * USD at the command edge, see lib/money); `confirm` is the stored form\n * \"always\" | \"above:<atomic>\". These are client-enforced guardrails, not a\n * security boundary — any process that runs the CLI can also edit this file.\n */\nexport const ConfigSchema = z.object({\n maxAutoSpend: atomicString,\n sessionBudget: atomicString,\n confirm: z.union([z.literal('always'), z.string().regex(/^above:\\d+$/)]),\n allowlistCreators: z.array(z.string()),\n baseUrl: z.url(),\n rpcUrl: z.url(),\n /**\n * Evaluation-cohort opt-in (spec 09 §3): when true, lookup sends\n * X-Tenjin-Eval-Cohort: 1 and the server stores the generalized question for\n * 90 days. Off by default; no query text is retained server-side without it.\n */\n evalCohort: z.boolean(),\n publish: PublishConfigSchema,\n});\nexport type Config = z.infer<typeof ConfigSchema>;\n\n/**\n * Values as they may appear in config.json — every known key optional; absent =\n * default. `.passthrough()` PRESERVES unknown keys through load + persist: without\n * it an older binary's `config set` would strip (and re-serialize away) any newer\n * block a later CLI wrote, e.g. B3's `publish.*`. Known keys are still validated;\n * unknown keys ride along untouched.\n */\nexport const RawConfigSchema = ConfigSchema.partial()\n // The publish block is itself partial + passthrough: `config set publish.mode`\n // writes only the one subkey, and a subkey a newer CLI adds (e.g. publish.*\n // beyond mode/defaultPrice) survives an older binary's set, same reason the\n // outer object passes unknown keys through.\n .extend({ publish: PublishConfigSchema.partial().passthrough().optional() })\n .passthrough();\nexport type PartialConfig = z.infer<typeof RawConfigSchema>;\n\nexport const CONFIG_DEFAULTS: Config = {\n maxAutoSpend: '0',\n sessionBudget: '0',\n confirm: 'always',\n allowlistCreators: [],\n baseUrl: 'https://tenjin.blog',\n rpcUrl: 'https://mainnet.base.org',\n evalCohort: false,\n publish: { mode: 'review', defaultPrice: '100000' },\n};\n\n/**\n * Scalar keys `config get/set/list` render one line each. `publish` is excluded:\n * it is a nested block addressed by the dotted `publish.mode`/`publish.defaultPrice`\n * keys (see PUBLISH_CONFIG_KEYS), so it is never rendered as a bare scalar.\n */\nexport type ScalarConfigKey = Exclude<keyof Config, 'publish'>;\nexport const CONFIG_KEYS = (Object.keys(CONFIG_DEFAULTS) as Array<keyof Config>).filter(\n (key): key is ScalarConfigKey => key !== 'publish',\n);\n\n/** The dotted keys `config get/set` accept for the nested publish block. */\nexport const PUBLISH_CONFIG_KEYS = ['publish.mode', 'publish.defaultPrice'] as const;\nexport type PublishConfigKey = (typeof PUBLISH_CONFIG_KEYS)[number];\n\n/**\n * Read and validate config.json WITHOUT applying defaults, so provenance can\n * distinguish \"present in file\" from \"absent\". Missing file is fine (returns\n * {}); malformed JSON or a failed schema is CONFIG_INVALID with a fix.\n */\nexport async function loadRawConfig(dir: string): Promise<PartialConfig> {\n const path = configPath(dir);\n let raw: string;\n try {\n raw = await readFile(path, 'utf8');\n } catch (err) {\n if (isNotFound(err)) return {};\n throw new CliError('CONFIG_INVALID', `Could not read config at ${path}`, {\n fix: `Check file permissions on ${path}.`,\n cause: err,\n });\n }\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch (err) {\n throw new CliError('CONFIG_INVALID', `Config at ${path} is not valid JSON`, {\n fix: `Fix the JSON syntax in ${path}, or delete it to restore defaults.`,\n cause: err,\n });\n }\n const parsed = RawConfigSchema.safeParse(json);\n if (!parsed.success) {\n throw new CliError('CONFIG_INVALID', `Config at ${path} is invalid`, {\n fix: `Correct the reported keys in ${path}, or delete it to restore defaults.`,\n details: parsed.error.issues,\n });\n }\n return parsed.data;\n}\n\n/** File values merged over defaults — the effective persisted config. The nested\n * publish block is merged per-subkey so a file that sets only publish.mode keeps\n * the default defaultPrice (a shallow spread would drop it). */\nexport async function loadConfig(dir: string): Promise<Config> {\n const raw = await loadRawConfig(dir);\n return {\n ...CONFIG_DEFAULTS,\n ...raw,\n publish: {\n mode: raw.publish?.mode ?? CONFIG_DEFAULTS.publish.mode,\n defaultPrice: raw.publish?.defaultPrice ?? CONFIG_DEFAULTS.publish.defaultPrice,\n },\n };\n}\n\nexport type Provenance = 'default' | 'file' | 'project' | 'env' | 'flag';\n\nexport interface ResolvedSetting<T> {\n value: T;\n source: Provenance;\n}\n\n/**\n * The per-project `.tenjin.json` layer (B3, D38): publish overrides discovered by\n * walking up from cwd, plus whether that file is gitignored. `gitignored` gates\n * `full-auto` — a committed file requesting it is downgraded (loosening gate).\n */\nexport interface ProjectPublishLayer {\n publish?: { mode?: PublishMode; defaultPrice?: string };\n gitignored: boolean;\n}\n\n/** publish.mode resolution: value, source, and the downgrade warning (if any). */\nexport interface PublishModeResolution {\n value: PublishMode;\n source: Provenance;\n /** Set when a committed `.tenjin.json`'s `full-auto` was downgraded to `auto`. */\n downgradedWarning?: string;\n}\n\n/** Effective value + where it came from, per key. What `config` (bare) renders. */\nexport interface EffectiveSettings {\n maxAutoSpend: ResolvedSetting<string>;\n sessionBudget: ResolvedSetting<string>;\n confirm: ResolvedSetting<string>;\n allowlistCreators: ResolvedSetting<string[]>;\n baseUrl: ResolvedSetting<string>;\n rpcUrl: ResolvedSetting<string>;\n evalCohort: ResolvedSetting<boolean>;\n publishMode: PublishModeResolution;\n publishDefaultPrice: ResolvedSetting<string>;\n}\n\n/** CLI flags that participate in settings precedence (`--base-url`). */\nexport interface SettingsFlags {\n baseUrl?: string;\n}\n\nexport interface ResolveSettingsInput {\n /** Raw file values (present keys only) — from loadRawConfig, not loadConfig. */\n config: PartialConfig;\n flags: SettingsFlags;\n env: NodeJS.ProcessEnv;\n /** The nearest `.tenjin.json` layer, when one was found (see publish-settings). */\n project?: ProjectPublishLayer;\n}\n\n/**\n * Apply precedence flag > env > file > default per key, returning each effective\n * value with its source. In B1 only baseUrl has flag/env overrides\n * (`--base-url`, TENJIN_BASE_URL); the rest resolve file-or-default. B3 adds the\n * publish keys, which additionally fold in the per-project `.tenjin.json` layer.\n */\nexport function resolveSettings(input: ResolveSettingsInput): EffectiveSettings {\n const { config, flags, env, project } = input;\n return {\n maxAutoSpend: fileOrDefault('maxAutoSpend', config),\n sessionBudget: fileOrDefault('sessionBudget', config),\n confirm: fileOrDefault('confirm', config),\n allowlistCreators: fileOrDefault('allowlistCreators', config),\n baseUrl: resolveBaseUrl(config, flags, env),\n rpcUrl: fileOrDefault('rpcUrl', config),\n evalCohort: fileOrDefault('evalCohort', config),\n publishMode: resolvePublishMode({ config, project, env }),\n publishDefaultPrice: resolvePublishDefaultPrice({ config, project }),\n };\n}\n\n/**\n * The loosening gate (D38): a committed (not-gitignored) `.tenjin.json` requesting\n * `full-auto` is downgraded to `auto`, never silently honored — cloning a repo\n * must not enable auto-publish. `full-auto` from global config / env / flag (all\n * inherently local, not cloned) is always honored.\n */\nconst FULL_AUTO_DOWNGRADE_WARNING =\n 'Ignoring publish.mode \"full-auto\" from a committed .tenjin.json (cloning a repo must not enable auto-publish); using \"auto\". Add .tenjin.json to .gitignore to opt in.';\n\nfunction coercePublishMode(raw: string | undefined): PublishMode | undefined {\n if (raw === undefined || raw.length === 0) return undefined;\n const parsed = PublishModeSchema.safeParse(raw);\n return parsed.success ? parsed.data : undefined;\n}\n\n/**\n * Resolve publish.mode through global file < project `.tenjin.json` < env\n * (TENJIN_PUBLISH_MODE) < flag (`--mode`). Total: an invalid env/flag value is\n * ignored (validation lives at the command edge, like baseUrl). The project\n * layer's `full-auto` is gated on that file being gitignored.\n */\nexport function resolvePublishMode(input: {\n config: PartialConfig;\n project?: ProjectPublishLayer;\n env: NodeJS.ProcessEnv;\n flag?: string;\n}): PublishModeResolution {\n const { config, project, env, flag } = input;\n let winner: PublishModeResolution = { value: CONFIG_DEFAULTS.publish.mode, source: 'default' };\n\n const fromFile = config.publish?.mode;\n if (fromFile !== undefined) winner = { value: fromFile, source: 'file' };\n\n if (project !== undefined && project.publish?.mode !== undefined) {\n const fromProject = project.publish.mode;\n if (fromProject === 'full-auto' && !project.gitignored) {\n winner = { value: 'auto', source: 'project', downgradedWarning: FULL_AUTO_DOWNGRADE_WARNING };\n } else {\n winner = { value: fromProject, source: 'project' };\n }\n }\n\n const fromEnv = coercePublishMode(env.TENJIN_PUBLISH_MODE);\n if (fromEnv !== undefined) winner = { value: fromEnv, source: 'env' };\n\n const fromFlag = coercePublishMode(flag);\n if (fromFlag !== undefined) winner = { value: fromFlag, source: 'flag' };\n\n return winner;\n}\n\n/** Resolve publish.defaultPrice (atomic) through global file < project < default. */\nexport function resolvePublishDefaultPrice(input: {\n config: PartialConfig;\n project?: ProjectPublishLayer;\n}): ResolvedSetting<string> {\n const { config, project } = input;\n let result: ResolvedSetting<string> = {\n value: CONFIG_DEFAULTS.publish.defaultPrice,\n source: 'default',\n };\n if (config.publish?.defaultPrice !== undefined) {\n result = { value: config.publish.defaultPrice, source: 'file' };\n }\n if (project?.publish?.defaultPrice !== undefined) {\n result = { value: project.publish.defaultPrice, source: 'project' };\n }\n return result;\n}\n\n/** Persist a full, validated config via the atomic writer (0700 dir, 0644 file). */\nexport async function writeConfig(dir: string, config: Config): Promise<void> {\n const validated = ConfigSchema.parse(config);\n await writeFileAtomic(configPath(dir), `${JSON.stringify(validated, null, 2)}\\n`, {\n mode: 0o644,\n dirMode: 0o700,\n });\n}\n\nfunction fileOrDefault<K extends keyof Config>(\n key: K,\n config: PartialConfig,\n): ResolvedSetting<Config[K]> {\n const fromFile = config[key];\n // PartialConfig[K] is Config[K] | undefined; narrowing an indexed access of a\n // type parameter doesn't refine K, so assert the excluded-undefined type.\n if (fromFile !== undefined) return { value: fromFile as Config[K], source: 'file' };\n return { value: CONFIG_DEFAULTS[key], source: 'default' };\n}\n\nfunction resolveBaseUrl(\n config: PartialConfig,\n flags: SettingsFlags,\n env: NodeJS.ProcessEnv,\n): ResolvedSetting<string> {\n if (flags.baseUrl !== undefined && flags.baseUrl.length > 0) {\n return { value: flags.baseUrl, source: 'flag' };\n }\n const fromEnv = env.TENJIN_BASE_URL;\n if (fromEnv !== undefined && fromEnv.length > 0) {\n return { value: fromEnv, source: 'env' };\n }\n if (config.baseUrl !== undefined) return { value: config.baseUrl, source: 'file' };\n return { value: CONFIG_DEFAULTS.baseUrl, source: 'default' };\n}\n\nfunction isNotFound(err: unknown): boolean {\n return (\n typeof err === 'object' &&\n err !== null &&\n 'code' in err &&\n (err as { code?: unknown }).code === 'ENOENT'\n );\n}\n","import { CliError } from './errors';\nimport type { Money } from '../schemas';\n\n/** USDC is a 6-decimal token; one dollar is 1_000_000 atomic units. */\nconst USDC_DECIMALS = 6;\n\n/**\n * Decimal USD at the CLI edge -> atomic USDC string (O1). Accepts \"0\", \"0.25\",\n * \"5\"; rejects negatives, non-numeric input, and more than 6 decimal places as\n * USAGE so a fat-fingered amount fails loudly instead of truncating money.\n * String math throughout — a float would lose precision at the 6th decimal.\n */\nexport function parseUsdToAtomic(input: string): string {\n const trimmed = input.trim();\n if (!/^\\d+(\\.\\d+)?$/.test(trimmed)) {\n throw new CliError('USAGE', `Invalid USD amount: ${JSON.stringify(input)}`, {\n fix: 'Pass a non-negative decimal like 0.25 or 5.',\n });\n }\n const [whole, frac = ''] = trimmed.split('.');\n if (frac.length > USDC_DECIMALS) {\n throw new CliError(\n 'USAGE',\n `USD amount ${JSON.stringify(input)} has more than 6 decimal places`,\n {\n fix: 'USDC supports at most 6 decimal places (micro-dollars).',\n },\n );\n }\n const atomic = BigInt(`${whole}${frac.padEnd(USDC_DECIMALS, '0')}`);\n return atomic.toString();\n}\n\n/**\n * Atomic USDC string -> decimal USD string, trailing zeros trimmed (\"250000\" ->\n * \"0.25\", \"5000000\" -> \"5\", \"0\" -> \"0\"). Throws INTERNAL on a malformed atomic\n * value: atomic strings come from validated config or on-chain reads, so a bad\n * one is a bug, not user input.\n */\nexport function atomicToUsd(atomic: string): string {\n const trimmed = atomic.trim();\n if (!/^\\d+$/.test(trimmed)) {\n throw new CliError('INTERNAL', `Malformed atomic amount: ${JSON.stringify(atomic)}`);\n }\n const value = BigInt(trimmed);\n const base = 10n ** BigInt(USDC_DECIMALS);\n const whole = value / base;\n const frac = (value % base).toString().padStart(USDC_DECIMALS, '0').replace(/0+$/, '');\n return frac.length > 0 ? `${whole}.${frac}` : whole.toString();\n}\n\n/** Dual-form money object for machine output. */\nexport function toMoney(atomic: string): Money {\n return { atomic, usd: atomicToUsd(atomic) };\n}\n\n/**\n * Canonical USD for human COPY (a price a person reads): always at least two\n * decimals (\"0.10\", \"5.00\"), keeping any finer precision below a cent\n * (\"0.000001\"). Distinct from `atomicToUsd`, which trims to the shortest exact\n * form for machine output; use this only where a dollar amount is shown to a human.\n */\nexport function formatUsdDisplay(atomic: string): string {\n const [whole, frac = ''] = atomicToUsd(atomic).split('.');\n return `${whole}.${frac.padEnd(2, '0')}`;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,79 @@
1
+ import { createRequire as __tenjinCreateRequire } from 'node:module'; const require = __tenjinCreateRequire(import.meta.url);
2
+
3
+ // package.json
4
+ var package_default = {
5
+ name: "tenjin-cli",
6
+ version: "0.1.0-alpha.3",
7
+ type: "module",
8
+ description: "Tenjin agent CLI for the x402 knowledge marketplace.",
9
+ license: "MIT",
10
+ repository: {
11
+ type: "git",
12
+ url: "git+https://github.com/BackTrackCo/tenjin-agent.git"
13
+ },
14
+ homepage: "https://tenjin.blog/agents",
15
+ bugs: "https://github.com/BackTrackCo/tenjin-agent/issues",
16
+ keywords: [
17
+ "x402",
18
+ "usdc",
19
+ "base",
20
+ "ai-agents",
21
+ "agent-payments",
22
+ "mcp",
23
+ "knowledge-marketplace",
24
+ "micropayments",
25
+ "claude",
26
+ "codex",
27
+ "cli"
28
+ ],
29
+ bin: {
30
+ tenjin: "dist/index.js"
31
+ },
32
+ engines: {
33
+ node: ">=22"
34
+ },
35
+ files: [
36
+ "dist",
37
+ "skills",
38
+ "NOTICE.md"
39
+ ],
40
+ packageManager: "pnpm@11.11.0",
41
+ scripts: {
42
+ build: "tsup",
43
+ test: "vitest run",
44
+ typecheck: "tsc --noEmit",
45
+ lint: "eslint .",
46
+ format: "prettier --write .",
47
+ "format:check": "prettier --check .",
48
+ check: "pnpm run build && pnpm run test",
49
+ "sync:skill": "node scripts/sync-skill.mjs",
50
+ "pack-smoke": "bash scripts/pack-smoke.sh",
51
+ changeset: "changeset",
52
+ prepublishOnly: "pnpm run build",
53
+ prepare: "git config core.hooksPath .githooks || true"
54
+ },
55
+ devDependencies: {
56
+ "@changesets/cli": "^2.31.1",
57
+ "@eslint/js": "^9",
58
+ "@types/node": "^25",
59
+ "@x402/core": "2.17.0",
60
+ "@x402/evm": "2.17.0",
61
+ "@x402/extensions": "2.17.0",
62
+ commander: "^14.0.1",
63
+ eslint: "^9",
64
+ "eslint-config-prettier": "^10",
65
+ ox: "0.14.30",
66
+ prettier: "^3",
67
+ tsup: "^8.5.0",
68
+ typescript: "^6",
69
+ "typescript-eslint": "^8",
70
+ viem: "^2.53.1",
71
+ vitest: "^4.1.9",
72
+ zod: "^4.4.3"
73
+ }
74
+ };
75
+
76
+ export {
77
+ package_default
78
+ };
79
+ //# sourceMappingURL=chunk-FJPLRISB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"tenjin-cli\",\n \"version\": \"0.1.0-alpha.3\",\n \"type\": \"module\",\n \"description\": \"Tenjin agent CLI for the x402 knowledge marketplace.\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/BackTrackCo/tenjin-agent.git\"\n },\n \"homepage\": \"https://tenjin.blog/agents\",\n \"bugs\": \"https://github.com/BackTrackCo/tenjin-agent/issues\",\n \"keywords\": [\n \"x402\",\n \"usdc\",\n \"base\",\n \"ai-agents\",\n \"agent-payments\",\n \"mcp\",\n \"knowledge-marketplace\",\n \"micropayments\",\n \"claude\",\n \"codex\",\n \"cli\"\n ],\n \"bin\": {\n \"tenjin\": \"dist/index.js\"\n },\n \"engines\": {\n \"node\": \">=22\"\n },\n \"files\": [\n \"dist\",\n \"skills\",\n \"NOTICE.md\"\n ],\n \"packageManager\": \"pnpm@11.11.0\",\n \"scripts\": {\n \"build\": \"tsup\",\n \"test\": \"vitest run\",\n \"typecheck\": \"tsc --noEmit\",\n \"lint\": \"eslint .\",\n \"format\": \"prettier --write .\",\n \"format:check\": \"prettier --check .\",\n \"check\": \"pnpm run build && pnpm run test\",\n \"sync:skill\": \"node scripts/sync-skill.mjs\",\n \"pack-smoke\": \"bash scripts/pack-smoke.sh\",\n \"changeset\": \"changeset\",\n \"prepublishOnly\": \"pnpm run build\",\n \"prepare\": \"git config core.hooksPath .githooks || true\"\n },\n \"devDependencies\": {\n \"@changesets/cli\": \"^2.31.1\",\n \"@eslint/js\": \"^9\",\n \"@types/node\": \"^25\",\n \"@x402/core\": \"2.17.0\",\n \"@x402/evm\": \"2.17.0\",\n \"@x402/extensions\": \"2.17.0\",\n \"commander\": \"^14.0.1\",\n \"eslint\": \"^9\",\n \"eslint-config-prettier\": \"^10\",\n \"ox\": \"0.14.30\",\n \"prettier\": \"^3\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^6\",\n \"typescript-eslint\": \"^8\",\n \"viem\": \"^2.53.1\",\n \"vitest\": \"^4.1.9\",\n \"zod\": \"^4.4.3\"\n }\n}\n"],"mappings":";;;AAAA;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,MAAQ;AAAA,EACR,aAAe;AAAA,EACf,SAAW;AAAA,EACX,YAAc;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,EACT;AAAA,EACA,UAAY;AAAA,EACZ,MAAQ;AAAA,EACR,UAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,KAAO;AAAA,IACL,QAAU;AAAA,EACZ;AAAA,EACA,SAAW;AAAA,IACT,MAAQ;AAAA,EACV;AAAA,EACA,OAAS;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAkB;AAAA,EAClB,SAAW;AAAA,IACT,OAAS;AAAA,IACT,MAAQ;AAAA,IACR,WAAa;AAAA,IACb,MAAQ;AAAA,IACR,QAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,OAAS;AAAA,IACT,cAAc;AAAA,IACd,cAAc;AAAA,IACd,WAAa;AAAA,IACb,gBAAkB;AAAA,IAClB,SAAW;AAAA,EACb;AAAA,EACA,iBAAmB;AAAA,IACjB,mBAAmB;AAAA,IACnB,cAAc;AAAA,IACd,eAAe;AAAA,IACf,cAAc;AAAA,IACd,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,WAAa;AAAA,IACb,QAAU;AAAA,IACV,0BAA0B;AAAA,IAC1B,IAAM;AAAA,IACN,UAAY;AAAA,IACZ,MAAQ;AAAA,IACR,YAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,MAAQ;AAAA,IACR,QAAU;AAAA,IACV,KAAO;AAAA,EACT;AACF;","names":[]}
@@ -0,0 +1,160 @@
1
+ import { createRequire as __tenjinCreateRequire } from 'node:module'; const require = __tenjinCreateRequire(import.meta.url);
2
+ import {
3
+ PublishModeSchema,
4
+ loadRawConfig,
5
+ parseUsdToAtomic,
6
+ resolvePublishDefaultPrice,
7
+ resolvePublishMode,
8
+ resolveSettings
9
+ } from "./chunk-ESPNTPQ2.js";
10
+ import {
11
+ parseConfirmPolicy
12
+ } from "./chunk-UO22YNY4.js";
13
+ import {
14
+ CliError,
15
+ external_exports
16
+ } from "./chunk-OYMYCW7J.js";
17
+
18
+ // src/lib/settings.ts
19
+ import { execFile } from "child_process";
20
+ import { readFile, stat } from "fs/promises";
21
+ import { homedir } from "os";
22
+ import { dirname, join } from "path";
23
+ async function resolveContextSettings(ctx) {
24
+ const config = await loadRawConfig(ctx.dataDir);
25
+ const s = resolveSettings({ config, flags: { baseUrl: ctx.flags.baseUrl }, env: process.env });
26
+ return {
27
+ baseUrl: s.baseUrl.value,
28
+ rpcUrl: s.rpcUrl.value,
29
+ evalCohort: s.evalCohort.value,
30
+ policy: {
31
+ maxAutoSpendAtomic: BigInt(s.maxAutoSpend.value),
32
+ sessionBudgetAtomic: BigInt(s.sessionBudget.value),
33
+ confirm: parseConfirmPolicy(s.confirm.value),
34
+ allowlistCreators: s.allowlistCreators.value
35
+ }
36
+ };
37
+ }
38
+ var PROJECT_CONFIG_FILE = ".tenjin.json";
39
+ var ProjectConfigSchema = external_exports.object({
40
+ publish: external_exports.object({
41
+ mode: PublishModeSchema.optional(),
42
+ defaultPrice: external_exports.string().optional()
43
+ }).passthrough().optional()
44
+ }).passthrough();
45
+ async function resolvePublishSettings(input, deps = {}) {
46
+ const env = input.env ?? process.env;
47
+ const config = await loadRawConfig(input.dataDir);
48
+ const project = await loadProjectConfig(input.cwd, deps);
49
+ const layer = project?.layer;
50
+ const mode = resolvePublishMode({ config, project: layer, env, flag: input.flag });
51
+ const price = resolvePublishDefaultPrice({ config, project: layer });
52
+ const warnings = mode.downgradedWarning !== void 0 ? [mode.downgradedWarning] : [];
53
+ return {
54
+ mode: mode.value,
55
+ modeSource: mode.source,
56
+ defaultPriceAtomic: price.value,
57
+ defaultPriceSource: price.source,
58
+ warnings,
59
+ ...project !== null ? { projectConfigPath: project.path } : {}
60
+ };
61
+ }
62
+ async function loadProjectConfig(cwd, deps = {}) {
63
+ const path = await findProjectConfigFile(cwd, deps);
64
+ if (path === null) return null;
65
+ let json;
66
+ try {
67
+ json = JSON.parse(await readFile(path, "utf8"));
68
+ } catch (err) {
69
+ throw new CliError("CONFIG_INVALID", `${PROJECT_CONFIG_FILE} at ${path} could not be read`, {
70
+ fix: `Fix or delete ${path} (must be a readable JSON file).`,
71
+ cause: err
72
+ });
73
+ }
74
+ const parsed = ProjectConfigSchema.safeParse(json);
75
+ if (!parsed.success) {
76
+ throw new CliError("CONFIG_INVALID", `${PROJECT_CONFIG_FILE} at ${path} is invalid`, {
77
+ fix: `Correct the reported keys in ${path}, or delete it.`,
78
+ details: parsed.error.issues
79
+ });
80
+ }
81
+ const isGitignored = deps.isGitignored ?? defaultIsGitignored;
82
+ const gitignored = await isGitignored(path);
83
+ const layer = { gitignored };
84
+ if (parsed.data.publish !== void 0) {
85
+ const { mode, defaultPrice } = parsed.data.publish;
86
+ layer.publish = {
87
+ ...mode !== void 0 ? { mode } : {},
88
+ ...defaultPrice !== void 0 ? { defaultPrice: parseProjectPrice(defaultPrice, path) } : {}
89
+ };
90
+ }
91
+ return { path, layer };
92
+ }
93
+ function parseProjectPrice(decimalUsd, path) {
94
+ try {
95
+ return parseUsdToAtomic(decimalUsd);
96
+ } catch (err) {
97
+ throw new CliError(
98
+ "CONFIG_INVALID",
99
+ `${PROJECT_CONFIG_FILE} at ${path} has an invalid publish.defaultPrice`,
100
+ { fix: 'Use a non-negative decimal USD amount like "0.10".', cause: err }
101
+ );
102
+ }
103
+ }
104
+ async function findProjectConfigFile(cwd, deps) {
105
+ const homeDir = deps.homeDir ?? homedir();
106
+ const isForeignOwned = deps.isForeignOwned ?? defaultIsForeignOwned;
107
+ const warn = deps.warn ?? ((message) => process.stderr.write(`${message}
108
+ `));
109
+ let dir = cwd;
110
+ for (; ; ) {
111
+ const candidate = join(dir, PROJECT_CONFIG_FILE);
112
+ if (await pathExists(candidate)) {
113
+ if (await isForeignOwned(candidate)) {
114
+ warn(`Ignoring ${candidate}: not owned by the current user.`);
115
+ } else {
116
+ return candidate;
117
+ }
118
+ }
119
+ if (await pathExists(join(dir, ".git"))) return null;
120
+ if (dir === homeDir) return null;
121
+ const parent = dirname(dir);
122
+ if (parent === dir) return null;
123
+ dir = parent;
124
+ }
125
+ }
126
+ async function defaultIsForeignOwned(filePath) {
127
+ const uid = process.getuid?.();
128
+ if (uid === void 0) return false;
129
+ try {
130
+ return (await stat(filePath)).uid !== uid;
131
+ } catch {
132
+ return false;
133
+ }
134
+ }
135
+ async function pathExists(path) {
136
+ try {
137
+ await stat(path);
138
+ return true;
139
+ } catch {
140
+ return false;
141
+ }
142
+ }
143
+ function defaultIsGitignored(filePath) {
144
+ return new Promise((resolve) => {
145
+ execFile(
146
+ "git",
147
+ ["check-ignore", "--quiet", "--", filePath],
148
+ { cwd: dirname(filePath) },
149
+ (err) => resolve(err === null)
150
+ );
151
+ });
152
+ }
153
+
154
+ export {
155
+ resolveContextSettings,
156
+ resolvePublishSettings,
157
+ loadProjectConfig,
158
+ pathExists
159
+ };
160
+ //# sourceMappingURL=chunk-GO75V3NZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/settings.ts"],"sourcesContent":["import { execFile } from 'node:child_process';\nimport { readFile, stat } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { z } from 'zod';\nimport { CliError } from './errors';\nimport {\n PublishModeSchema,\n loadRawConfig,\n resolvePublishDefaultPrice,\n resolvePublishMode,\n resolveSettings,\n} from './config';\nimport type { Provenance, ProjectPublishLayer, PublishMode } from './config';\nimport { parseUsdToAtomic } from './money';\nimport { parseConfirmPolicy, type SpendPolicy } from './policy';\nimport type { CommandContext } from '../context';\n\n/**\n * The effective runtime settings a B2 command needs, resolved once through the\n * same precedence (flag > env > file > default) config/doctor use. Spend values\n * arrive atomic from config and are handed on as bigint for the policy layer.\n */\nexport interface ResolvedSettings {\n baseUrl: string;\n rpcUrl: string;\n policy: SpendPolicy;\n /** Lookup-only privacy opt-in; sends X-Tenjin-Eval-Cohort: 1 when true. */\n evalCohort: boolean;\n}\n\nexport async function resolveContextSettings(ctx: CommandContext): Promise<ResolvedSettings> {\n const config = await loadRawConfig(ctx.dataDir);\n const s = resolveSettings({ config, flags: { baseUrl: ctx.flags.baseUrl }, env: process.env });\n return {\n baseUrl: s.baseUrl.value,\n rpcUrl: s.rpcUrl.value,\n evalCohort: s.evalCohort.value,\n policy: {\n maxAutoSpendAtomic: BigInt(s.maxAutoSpend.value),\n sessionBudgetAtomic: BigInt(s.sessionBudget.value),\n confirm: parseConfirmPolicy(s.confirm.value),\n allowlistCreators: s.allowlistCreators.value,\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Publish consent settings (B3, D38)\n//\n// The publish mode/price cascade extends the same precedence machinery\n// (resolvePublishMode / resolvePublishDefaultPrice in lib/config) with a\n// per-project layer that needs I/O the pure resolvers can't do: it walks up from\n// cwd for a `.tenjin.json` and asks git whether that file is committed (the\n// loosening gate on `full-auto`). It lives here beside resolveContextSettings so\n// there is one settings resolver, not a parallel one.\n// ---------------------------------------------------------------------------\n\nexport const PROJECT_CONFIG_FILE = '.tenjin.json';\n\n/**\n * The per-project override file. `publish.defaultPrice` is DECIMAL USD (\"0.10\"),\n * because a hand-edited project file is a human edge (O1) — unlike config.json,\n * which stores atomic because `config set` converts at the command edge. The\n * decimal string is converted to atomic at load via the same money util the\n * config command uses. Partial + passthrough: forward-compatible with subkeys a\n * newer CLI adds, same posture as the global config.\n */\nconst ProjectConfigSchema = z\n .object({\n publish: z\n .object({\n mode: PublishModeSchema.optional(),\n defaultPrice: z.string().optional(),\n })\n .passthrough()\n .optional(),\n })\n .passthrough();\n\nexport interface LoadedProjectConfig {\n /** Absolute path of the discovered `.tenjin.json`. */\n path: string;\n layer: ProjectPublishLayer;\n}\n\nexport interface PublishSettingsDeps {\n /** git check-ignore seam; defaults to shelling out to git (see wallet/passphrase). */\n isGitignored?: (filePath: string) => Promise<boolean>;\n /** Ownership seam; defaults to stat().uid vs process uid. Gates a planted file. */\n isForeignOwned?: (filePath: string) => Promise<boolean>;\n /** One-line stderr warning sink; defaults to process.stderr. */\n warn?: (message: string) => void;\n /** Upper bound of the walk; defaults to the user's home directory. */\n homeDir?: string;\n}\n\nexport interface ResolvedPublishSettings {\n mode: PublishMode;\n modeSource: Provenance;\n defaultPriceAtomic: string;\n defaultPriceSource: Provenance;\n /** Non-fatal notices for stderr (e.g. the full-auto downgrade). */\n warnings: string[];\n /** The `.tenjin.json` that contributed the project layer, if one was found. */\n projectConfigPath?: string;\n}\n\n/**\n * Resolve the effective publish mode + default price across every layer:\n * global config.json < project `.tenjin.json` < env (TENJIN_PUBLISH_MODE) <\n * flag (`--mode`), with the `full-auto` loosening gate applied to the project\n * layer. The seam a `publish` command (B3.2) resolves its consent through.\n */\nexport async function resolvePublishSettings(\n input: { dataDir: string; cwd: string; flag?: string; env?: NodeJS.ProcessEnv },\n deps: PublishSettingsDeps = {},\n): Promise<ResolvedPublishSettings> {\n const env = input.env ?? process.env;\n const config = await loadRawConfig(input.dataDir);\n const project = await loadProjectConfig(input.cwd, deps);\n const layer = project?.layer;\n\n const mode = resolvePublishMode({ config, project: layer, env, flag: input.flag });\n const price = resolvePublishDefaultPrice({ config, project: layer });\n const warnings = mode.downgradedWarning !== undefined ? [mode.downgradedWarning] : [];\n\n return {\n mode: mode.value,\n modeSource: mode.source,\n defaultPriceAtomic: price.value,\n defaultPriceSource: price.source,\n warnings,\n ...(project !== null ? { projectConfigPath: project.path } : {}),\n };\n}\n\n/**\n * Find the nearest `.tenjin.json` walking up from cwd toward the repo root (the\n * first directory holding a `.git`, inclusive), never crossing above $HOME, then\n * load, validate, and check whether it is gitignored. A file not owned by the\n * current user is ignored with a stderr warning (a planted config on a shared\n * host must not become the honored project layer). Null when none is found; a\n * present-but-unreadable/malformed file is CONFIG_INVALID (never silently\n * skipped).\n */\nexport async function loadProjectConfig(\n cwd: string,\n deps: PublishSettingsDeps = {},\n): Promise<LoadedProjectConfig | null> {\n const path = await findProjectConfigFile(cwd, deps);\n if (path === null) return null;\n\n let json: unknown;\n try {\n // readFile is inside the try: a raced delete (ENOENT), a directory named\n // .tenjin.json (EISDIR), or a permission error (EACCES) is a bad project file,\n // not an INTERNAL fault.\n json = JSON.parse(await readFile(path, 'utf8'));\n } catch (err) {\n throw new CliError('CONFIG_INVALID', `${PROJECT_CONFIG_FILE} at ${path} could not be read`, {\n fix: `Fix or delete ${path} (must be a readable JSON file).`,\n cause: err,\n });\n }\n const parsed = ProjectConfigSchema.safeParse(json);\n if (!parsed.success) {\n throw new CliError('CONFIG_INVALID', `${PROJECT_CONFIG_FILE} at ${path} is invalid`, {\n fix: `Correct the reported keys in ${path}, or delete it.`,\n details: parsed.error.issues,\n });\n }\n\n const isGitignored = deps.isGitignored ?? defaultIsGitignored;\n const gitignored = await isGitignored(path);\n const layer: ProjectPublishLayer = { gitignored };\n if (parsed.data.publish !== undefined) {\n const { mode, defaultPrice } = parsed.data.publish;\n layer.publish = {\n ...(mode !== undefined ? { mode } : {}),\n ...(defaultPrice !== undefined\n ? { defaultPrice: parseProjectPrice(defaultPrice, path) }\n : {}),\n };\n }\n return { path, layer };\n}\n\n/**\n * Convert a `.tenjin.json` decimal-USD price to atomic via the shared money\n * parser. parseUsdToAtomic throws USAGE on a bad amount; re-raise as\n * CONFIG_INVALID naming the file, so it reads like the file's other errors.\n */\nfunction parseProjectPrice(decimalUsd: string, path: string): string {\n try {\n return parseUsdToAtomic(decimalUsd);\n } catch (err) {\n throw new CliError(\n 'CONFIG_INVALID',\n `${PROJECT_CONFIG_FILE} at ${path} has an invalid publish.defaultPrice`,\n { fix: 'Use a non-negative decimal USD amount like \"0.10\".', cause: err },\n );\n }\n}\n\nasync function findProjectConfigFile(\n cwd: string,\n deps: PublishSettingsDeps,\n): Promise<string | null> {\n const homeDir = deps.homeDir ?? homedir();\n const isForeignOwned = deps.isForeignOwned ?? defaultIsForeignOwned;\n const warn = deps.warn ?? ((message: string) => process.stderr.write(`${message}\\n`));\n\n let dir = cwd;\n // Bounded by $HOME (a shared-host trust boundary) and the filesystem root\n // (dirname('/') === '/'), whichever comes first.\n for (;;) {\n const candidate = join(dir, PROJECT_CONFIG_FILE);\n if (await pathExists(candidate)) {\n if (await isForeignOwned(candidate)) {\n // A file owned by another user (e.g. /tmp/.tenjin.json on a shared box)\n // must never become the honored layer; skip it and keep walking.\n warn(`Ignoring ${candidate}: not owned by the current user.`);\n } else {\n return candidate;\n }\n }\n if (await pathExists(join(dir, '.git'))) return null; // repo root, no file\n if (dir === homeDir) return null; // never cross above $HOME\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\n/**\n * True when the file is owned by a different uid than the process. On a platform\n * without a uid model (Windows: process.getuid is undefined) this is always\n * false — the ownership gate is a POSIX shared-host protection.\n */\nasync function defaultIsForeignOwned(filePath: string): Promise<boolean> {\n const uid = process.getuid?.();\n if (uid === undefined) return false;\n try {\n return (await stat(filePath)).uid !== uid;\n } catch {\n return false;\n }\n}\n\n/** True when a path exists (of any type). Shared with the candidate command's\n * repo-root walk so the two `.git`/file probes stay one implementation. */\nexport async function pathExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * True only on a git check-ignore exit 0 (the path is ignored). Exit 1 (tracked)\n * and any error (git absent, not a repo) resolve false: `full-auto` is honored\n * from a project file ONLY when git positively confirms it is ignored. Uses\n * execFile with an argv array (never a shell), matching wallet/passphrase.ts.\n */\nfunction defaultIsGitignored(filePath: string): Promise<boolean> {\n return new Promise((resolve) => {\n execFile(\n 'git',\n ['check-ignore', '--quiet', '--', filePath],\n { cwd: dirname(filePath) },\n (err) => resolve(err === null),\n );\n });\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,204 @@
1
+ import { createRequire as __tenjinCreateRequire } from 'node:module'; const require = __tenjinCreateRequire(import.meta.url);
2
+ import {
3
+ Hash,
4
+ abytes,
5
+ aexists,
6
+ anumber,
7
+ aoutput,
8
+ clean,
9
+ createHasher,
10
+ rotlBH,
11
+ rotlBL,
12
+ rotlSH,
13
+ rotlSL,
14
+ split,
15
+ swap32IfBE,
16
+ toBytes,
17
+ u32
18
+ } from "./chunk-5CLSD5YN.js";
19
+
20
+ // node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/sha3.js
21
+ var _0n = BigInt(0);
22
+ var _1n = BigInt(1);
23
+ var _2n = BigInt(2);
24
+ var _7n = BigInt(7);
25
+ var _256n = BigInt(256);
26
+ var _0x71n = BigInt(113);
27
+ var SHA3_PI = [];
28
+ var SHA3_ROTL = [];
29
+ var _SHA3_IOTA = [];
30
+ for (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) {
31
+ [x, y] = [y, (2 * x + 3 * y) % 5];
32
+ SHA3_PI.push(2 * (5 * y + x));
33
+ SHA3_ROTL.push((round + 1) * (round + 2) / 2 % 64);
34
+ let t = _0n;
35
+ for (let j = 0; j < 7; j++) {
36
+ R = (R << _1n ^ (R >> _7n) * _0x71n) % _256n;
37
+ if (R & _2n)
38
+ t ^= _1n << (_1n << /* @__PURE__ */ BigInt(j)) - _1n;
39
+ }
40
+ _SHA3_IOTA.push(t);
41
+ }
42
+ var IOTAS = split(_SHA3_IOTA, true);
43
+ var SHA3_IOTA_H = IOTAS[0];
44
+ var SHA3_IOTA_L = IOTAS[1];
45
+ var rotlH = (h, l, s) => s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s);
46
+ var rotlL = (h, l, s) => s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s);
47
+ function keccakP(s, rounds = 24) {
48
+ const B = new Uint32Array(5 * 2);
49
+ for (let round = 24 - rounds; round < 24; round++) {
50
+ for (let x = 0; x < 10; x++)
51
+ B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];
52
+ for (let x = 0; x < 10; x += 2) {
53
+ const idx1 = (x + 8) % 10;
54
+ const idx0 = (x + 2) % 10;
55
+ const B0 = B[idx0];
56
+ const B1 = B[idx0 + 1];
57
+ const Th = rotlH(B0, B1, 1) ^ B[idx1];
58
+ const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];
59
+ for (let y = 0; y < 50; y += 10) {
60
+ s[x + y] ^= Th;
61
+ s[x + y + 1] ^= Tl;
62
+ }
63
+ }
64
+ let curH = s[2];
65
+ let curL = s[3];
66
+ for (let t = 0; t < 24; t++) {
67
+ const shift = SHA3_ROTL[t];
68
+ const Th = rotlH(curH, curL, shift);
69
+ const Tl = rotlL(curH, curL, shift);
70
+ const PI = SHA3_PI[t];
71
+ curH = s[PI];
72
+ curL = s[PI + 1];
73
+ s[PI] = Th;
74
+ s[PI + 1] = Tl;
75
+ }
76
+ for (let y = 0; y < 50; y += 10) {
77
+ for (let x = 0; x < 10; x++)
78
+ B[x] = s[y + x];
79
+ for (let x = 0; x < 10; x++)
80
+ s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];
81
+ }
82
+ s[0] ^= SHA3_IOTA_H[round];
83
+ s[1] ^= SHA3_IOTA_L[round];
84
+ }
85
+ clean(B);
86
+ }
87
+ var Keccak = class _Keccak extends Hash {
88
+ // NOTE: we accept arguments in bytes instead of bits here.
89
+ constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) {
90
+ super();
91
+ this.pos = 0;
92
+ this.posOut = 0;
93
+ this.finished = false;
94
+ this.destroyed = false;
95
+ this.enableXOF = false;
96
+ this.blockLen = blockLen;
97
+ this.suffix = suffix;
98
+ this.outputLen = outputLen;
99
+ this.enableXOF = enableXOF;
100
+ this.rounds = rounds;
101
+ anumber(outputLen);
102
+ if (!(0 < blockLen && blockLen < 200))
103
+ throw new Error("only keccak-f1600 function is supported");
104
+ this.state = new Uint8Array(200);
105
+ this.state32 = u32(this.state);
106
+ }
107
+ clone() {
108
+ return this._cloneInto();
109
+ }
110
+ keccak() {
111
+ swap32IfBE(this.state32);
112
+ keccakP(this.state32, this.rounds);
113
+ swap32IfBE(this.state32);
114
+ this.posOut = 0;
115
+ this.pos = 0;
116
+ }
117
+ update(data) {
118
+ aexists(this);
119
+ data = toBytes(data);
120
+ abytes(data);
121
+ const { blockLen, state } = this;
122
+ const len = data.length;
123
+ for (let pos = 0; pos < len; ) {
124
+ const take = Math.min(blockLen - this.pos, len - pos);
125
+ for (let i = 0; i < take; i++)
126
+ state[this.pos++] ^= data[pos++];
127
+ if (this.pos === blockLen)
128
+ this.keccak();
129
+ }
130
+ return this;
131
+ }
132
+ finish() {
133
+ if (this.finished)
134
+ return;
135
+ this.finished = true;
136
+ const { state, suffix, pos, blockLen } = this;
137
+ state[pos] ^= suffix;
138
+ if ((suffix & 128) !== 0 && pos === blockLen - 1)
139
+ this.keccak();
140
+ state[blockLen - 1] ^= 128;
141
+ this.keccak();
142
+ }
143
+ writeInto(out) {
144
+ aexists(this, false);
145
+ abytes(out);
146
+ this.finish();
147
+ const bufferOut = this.state;
148
+ const { blockLen } = this;
149
+ for (let pos = 0, len = out.length; pos < len; ) {
150
+ if (this.posOut >= blockLen)
151
+ this.keccak();
152
+ const take = Math.min(blockLen - this.posOut, len - pos);
153
+ out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
154
+ this.posOut += take;
155
+ pos += take;
156
+ }
157
+ return out;
158
+ }
159
+ xofInto(out) {
160
+ if (!this.enableXOF)
161
+ throw new Error("XOF is not possible for this instance");
162
+ return this.writeInto(out);
163
+ }
164
+ xof(bytes) {
165
+ anumber(bytes);
166
+ return this.xofInto(new Uint8Array(bytes));
167
+ }
168
+ digestInto(out) {
169
+ aoutput(out, this);
170
+ if (this.finished)
171
+ throw new Error("digest() was already called");
172
+ this.writeInto(out);
173
+ this.destroy();
174
+ return out;
175
+ }
176
+ digest() {
177
+ return this.digestInto(new Uint8Array(this.outputLen));
178
+ }
179
+ destroy() {
180
+ this.destroyed = true;
181
+ clean(this.state);
182
+ }
183
+ _cloneInto(to) {
184
+ const { blockLen, suffix, outputLen, rounds, enableXOF } = this;
185
+ to || (to = new _Keccak(blockLen, suffix, outputLen, enableXOF, rounds));
186
+ to.state32.set(this.state32);
187
+ to.pos = this.pos;
188
+ to.posOut = this.posOut;
189
+ to.finished = this.finished;
190
+ to.rounds = rounds;
191
+ to.suffix = suffix;
192
+ to.outputLen = outputLen;
193
+ to.enableXOF = enableXOF;
194
+ to.destroyed = this.destroyed;
195
+ return to;
196
+ }
197
+ };
198
+ var gen = (suffix, blockLen, outputLen) => createHasher(() => new Keccak(blockLen, suffix, outputLen));
199
+ var keccak_256 = /* @__PURE__ */ (() => gen(1, 136, 256 / 8))();
200
+
201
+ export {
202
+ keccak_256
203
+ };
204
+ //# sourceMappingURL=chunk-HIVZG55D.js.map