@noodleseed/one 0.10.0 → 0.12.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.
Files changed (153) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +16 -4
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/archive-ops.d.ts +3 -0
  5. package/dist/commands/archive-ops.d.ts.map +1 -0
  6. package/dist/commands/archive-ops.js +168 -0
  7. package/dist/commands/archive-ops.js.map +1 -0
  8. package/dist/commands/org-admin.d.ts +17 -0
  9. package/dist/commands/org-admin.d.ts.map +1 -0
  10. package/dist/commands/org-admin.js +241 -0
  11. package/dist/commands/org-admin.js.map +1 -0
  12. package/dist/commands/policy-ops.d.ts.map +1 -1
  13. package/dist/commands/policy-ops.js +123 -1
  14. package/dist/commands/policy-ops.js.map +1 -1
  15. package/dist/commands/session.d.ts +1 -15
  16. package/dist/commands/session.d.ts.map +1 -1
  17. package/dist/commands/session.js +15 -170
  18. package/dist/commands/session.js.map +1 -1
  19. package/dist/commands/shared.d.ts.map +1 -1
  20. package/dist/commands/shared.js +13 -5
  21. package/dist/commands/shared.js.map +1 -1
  22. package/dist/commands/update-ops.d.ts +29 -0
  23. package/dist/commands/update-ops.d.ts.map +1 -0
  24. package/dist/commands/update-ops.js +315 -0
  25. package/dist/commands/update-ops.js.map +1 -0
  26. package/dist/config.d.ts +2 -0
  27. package/dist/config.d.ts.map +1 -1
  28. package/dist/config.js.map +1 -1
  29. package/dist/update-binary.d.ts +38 -0
  30. package/dist/update-binary.d.ts.map +1 -0
  31. package/dist/update-binary.js +144 -0
  32. package/dist/update-binary.js.map +1 -0
  33. package/dist/update-check.d.ts +40 -0
  34. package/dist/update-check.d.ts.map +1 -0
  35. package/dist/update-check.js +212 -0
  36. package/dist/update-check.js.map +1 -0
  37. package/dist/update-render.d.ts +17 -0
  38. package/dist/update-render.d.ts.map +1 -0
  39. package/dist/update-render.js +39 -0
  40. package/dist/update-render.js.map +1 -0
  41. package/dist/update.d.ts +10 -9
  42. package/dist/update.d.ts.map +1 -1
  43. package/dist/update.js +21 -89
  44. package/dist/update.js.map +1 -1
  45. package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.d.ts.map +1 -1
  46. package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.js +13 -1
  47. package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.js.map +1 -1
  48. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.d.ts.map +1 -1
  49. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +2 -0
  50. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js.map +1 -1
  51. package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
  52. package/node_modules/@noodle-borg/service/dist/archive-sweeper.d.ts +43 -0
  53. package/node_modules/@noodle-borg/service/dist/archive-sweeper.d.ts.map +1 -0
  54. package/node_modules/@noodle-borg/service/dist/archive-sweeper.js +122 -0
  55. package/node_modules/@noodle-borg/service/dist/archive-sweeper.js.map +1 -0
  56. package/node_modules/@noodle-borg/service/dist/commercial-plans.d.ts +11 -0
  57. package/node_modules/@noodle-borg/service/dist/commercial-plans.d.ts.map +1 -0
  58. package/node_modules/@noodle-borg/service/dist/commercial-plans.js +119 -0
  59. package/node_modules/@noodle-borg/service/dist/commercial-plans.js.map +1 -0
  60. package/node_modules/@noodle-borg/service/dist/deployment-versioning.d.ts +2 -0
  61. package/node_modules/@noodle-borg/service/dist/deployment-versioning.d.ts.map +1 -1
  62. package/node_modules/@noodle-borg/service/dist/deployment-versioning.js +1 -1
  63. package/node_modules/@noodle-borg/service/dist/deployment-versioning.js.map +1 -1
  64. package/node_modules/@noodle-borg/service/dist/index.d.ts +3 -1
  65. package/node_modules/@noodle-borg/service/dist/index.d.ts.map +1 -1
  66. package/node_modules/@noodle-borg/service/dist/index.js +2 -0
  67. package/node_modules/@noodle-borg/service/dist/index.js.map +1 -1
  68. package/node_modules/@noodle-borg/service/dist/options.d.ts +9 -0
  69. package/node_modules/@noodle-borg/service/dist/options.d.ts.map +1 -1
  70. package/node_modules/@noodle-borg/service/dist/policy.d.ts +3 -0
  71. package/node_modules/@noodle-borg/service/dist/policy.d.ts.map +1 -1
  72. package/node_modules/@noodle-borg/service/dist/policy.js +32 -0
  73. package/node_modules/@noodle-borg/service/dist/policy.js.map +1 -1
  74. package/node_modules/@noodle-borg/service/dist/registry-state.d.ts +25 -0
  75. package/node_modules/@noodle-borg/service/dist/registry-state.d.ts.map +1 -0
  76. package/node_modules/@noodle-borg/service/dist/registry-state.js +119 -0
  77. package/node_modules/@noodle-borg/service/dist/registry-state.js.map +1 -0
  78. package/node_modules/@noodle-borg/service/dist/registry.d.ts +7 -6
  79. package/node_modules/@noodle-borg/service/dist/registry.d.ts.map +1 -1
  80. package/node_modules/@noodle-borg/service/dist/registry.js +44 -44
  81. package/node_modules/@noodle-borg/service/dist/registry.js.map +1 -1
  82. package/node_modules/@noodle-borg/service/dist/routes/archive.d.ts +16 -0
  83. package/node_modules/@noodle-borg/service/dist/routes/archive.d.ts.map +1 -0
  84. package/node_modules/@noodle-borg/service/dist/routes/archive.js +83 -0
  85. package/node_modules/@noodle-borg/service/dist/routes/archive.js.map +1 -0
  86. package/node_modules/@noodle-borg/service/dist/routes/control-plane.d.ts +1 -18
  87. package/node_modules/@noodle-borg/service/dist/routes/control-plane.d.ts.map +1 -1
  88. package/node_modules/@noodle-borg/service/dist/routes/control-plane.js +18 -260
  89. package/node_modules/@noodle-borg/service/dist/routes/control-plane.js.map +1 -1
  90. package/node_modules/@noodle-borg/service/dist/routes/deployments.d.ts +17 -0
  91. package/node_modules/@noodle-borg/service/dist/routes/deployments.d.ts.map +1 -0
  92. package/node_modules/@noodle-borg/service/dist/routes/deployments.js +88 -0
  93. package/node_modules/@noodle-borg/service/dist/routes/deployments.js.map +1 -0
  94. package/node_modules/@noodle-borg/service/dist/routes/org-admin.d.ts +40 -0
  95. package/node_modules/@noodle-borg/service/dist/routes/org-admin.d.ts.map +1 -0
  96. package/node_modules/@noodle-borg/service/dist/routes/org-admin.js +353 -0
  97. package/node_modules/@noodle-borg/service/dist/routes/org-admin.js.map +1 -0
  98. package/node_modules/@noodle-borg/service/dist/routes/paths.d.ts +15 -0
  99. package/node_modules/@noodle-borg/service/dist/routes/paths.d.ts.map +1 -1
  100. package/node_modules/@noodle-borg/service/dist/routes/paths.js +47 -0
  101. package/node_modules/@noodle-borg/service/dist/routes/paths.js.map +1 -1
  102. package/node_modules/@noodle-borg/service/dist/routes/plans.d.ts +20 -0
  103. package/node_modules/@noodle-borg/service/dist/routes/plans.d.ts.map +1 -0
  104. package/node_modules/@noodle-borg/service/dist/routes/plans.js +217 -0
  105. package/node_modules/@noodle-borg/service/dist/routes/plans.js.map +1 -0
  106. package/node_modules/@noodle-borg/service/dist/routes/policies.d.ts.map +1 -1
  107. package/node_modules/@noodle-borg/service/dist/routes/policies.js +7 -0
  108. package/node_modules/@noodle-borg/service/dist/routes/policies.js.map +1 -1
  109. package/node_modules/@noodle-borg/service/dist/routes/rollback.d.ts.map +1 -1
  110. package/node_modules/@noodle-borg/service/dist/routes/rollback.js +19 -1
  111. package/node_modules/@noodle-borg/service/dist/routes/rollback.js.map +1 -1
  112. package/node_modules/@noodle-borg/service/dist/service.d.ts.map +1 -1
  113. package/node_modules/@noodle-borg/service/dist/service.js +107 -4
  114. package/node_modules/@noodle-borg/service/dist/service.js.map +1 -1
  115. package/node_modules/@noodle-borg/service/dist/store/control-plane.d.ts +14 -0
  116. package/node_modules/@noodle-borg/service/dist/store/control-plane.d.ts.map +1 -1
  117. package/node_modules/@noodle-borg/service/dist/store/control-plane.js +38 -0
  118. package/node_modules/@noodle-borg/service/dist/store/control-plane.js.map +1 -1
  119. package/node_modules/@noodle-borg/service/dist/store/json-file.d.ts +25 -0
  120. package/node_modules/@noodle-borg/service/dist/store/json-file.d.ts.map +1 -0
  121. package/node_modules/@noodle-borg/service/dist/store/json-file.js +163 -0
  122. package/node_modules/@noodle-borg/service/dist/store/json-file.js.map +1 -0
  123. package/node_modules/@noodle-borg/service/dist/store/postgres-control-plane.d.ts +14 -0
  124. package/node_modules/@noodle-borg/service/dist/store/postgres-control-plane.d.ts.map +1 -1
  125. package/node_modules/@noodle-borg/service/dist/store/postgres-control-plane.js +16 -0
  126. package/node_modules/@noodle-borg/service/dist/store/postgres-control-plane.js.map +1 -1
  127. package/node_modules/@noodle-borg/service/dist/store/postgres-policy.d.ts.map +1 -1
  128. package/node_modules/@noodle-borg/service/dist/store/postgres-policy.js +10 -4
  129. package/node_modules/@noodle-borg/service/dist/store/postgres-policy.js.map +1 -1
  130. package/node_modules/@noodle-borg/service/dist/store/postgres-rows.d.ts +60 -0
  131. package/node_modules/@noodle-borg/service/dist/store/postgres-rows.d.ts.map +1 -0
  132. package/node_modules/@noodle-borg/service/dist/store/postgres-rows.js +101 -0
  133. package/node_modules/@noodle-borg/service/dist/store/postgres-rows.js.map +1 -0
  134. package/node_modules/@noodle-borg/service/dist/store/postgres-schema.d.ts.map +1 -1
  135. package/node_modules/@noodle-borg/service/dist/store/postgres-schema.js +10 -0
  136. package/node_modules/@noodle-borg/service/dist/store/postgres-schema.js.map +1 -1
  137. package/node_modules/@noodle-borg/service/dist/store/postgres.d.ts +20 -6
  138. package/node_modules/@noodle-borg/service/dist/store/postgres.d.ts.map +1 -1
  139. package/node_modules/@noodle-borg/service/dist/store/postgres.js +74 -122
  140. package/node_modules/@noodle-borg/service/dist/store/postgres.js.map +1 -1
  141. package/node_modules/@noodle-borg/service/dist/store/records.d.ts +35 -0
  142. package/node_modules/@noodle-borg/service/dist/store/records.d.ts.map +1 -0
  143. package/node_modules/@noodle-borg/service/dist/store/records.js +87 -0
  144. package/node_modules/@noodle-borg/service/dist/store/records.js.map +1 -0
  145. package/node_modules/@noodle-borg/service/dist/store/validate.d.ts +19 -0
  146. package/node_modules/@noodle-borg/service/dist/store/validate.d.ts.map +1 -0
  147. package/node_modules/@noodle-borg/service/dist/store/validate.js +61 -0
  148. package/node_modules/@noodle-borg/service/dist/store/validate.js.map +1 -0
  149. package/node_modules/@noodle-borg/service/dist/store.d.ts +68 -44
  150. package/node_modules/@noodle-borg/service/dist/store.d.ts.map +1 -1
  151. package/node_modules/@noodle-borg/service/dist/store.js +48 -213
  152. package/node_modules/@noodle-borg/service/dist/store.js.map +1 -1
  153. package/package.json +2 -2
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Binary ownership resolver for `noodle update` repair (#242, ADR 0118).
3
+ *
4
+ * npm's `EEXIST .../bin/noodle` failure happens before any of our code runs, so
5
+ * `noodle update` inspects the expected global bin path itself: does a `noodle`
6
+ * binary exist there, is it a symlink, where does it resolve, and is that target
7
+ * provably a Noodle CLI install? Classification is deliberately conservative:
8
+ *
9
+ * - SAFE to repair: a symlink into an `@noodleseed/one` (or legacy `noodleseed-cli`)
10
+ * package outside the active prefix, a dangling symlink, or a launcher file that
11
+ * provably references a Noodle CLI package.
12
+ * - UNSAFE: everything else — real files of unknown content, symlinks into other
13
+ * packages or arbitrary files, unreadable paths. Ambiguous is always UNSAFE.
14
+ *
15
+ * All probes are dependency-injected (fs + execPath) so every classification case
16
+ * is unit-testable against temp prefixes, never the developer's real global prefix.
17
+ */
18
+ import { lstatSync, readFileSync, readlinkSync, realpathSync } from 'node:fs';
19
+ import { dirname, isAbsolute, join, resolve, sep } from 'node:path';
20
+ /** Real-filesystem probes; `execPath` is overridable so tests point at a temp prefix. */
21
+ export function realBinaryProbeDeps(overrides = {}) {
22
+ return {
23
+ execPath: overrides.execPath ?? process.execPath,
24
+ lstatKind: (path) => {
25
+ try {
26
+ const stat = lstatSync(path);
27
+ if (stat.isSymbolicLink())
28
+ return 'symlink';
29
+ if (stat.isFile())
30
+ return 'file';
31
+ if (stat.isDirectory())
32
+ return 'dir';
33
+ return 'other';
34
+ }
35
+ catch (error) {
36
+ return error.code === 'ENOENT' ? 'missing' : 'error';
37
+ }
38
+ },
39
+ readlink: (path) => {
40
+ try {
41
+ return readlinkSync(path);
42
+ }
43
+ catch {
44
+ return undefined;
45
+ }
46
+ },
47
+ realpath: (path) => {
48
+ try {
49
+ return realpathSync(path);
50
+ }
51
+ catch {
52
+ return undefined;
53
+ }
54
+ },
55
+ readFileHead: (path) => {
56
+ try {
57
+ return readFileSync(path, 'utf8').slice(0, 4096);
58
+ }
59
+ catch {
60
+ return undefined;
61
+ }
62
+ },
63
+ };
64
+ }
65
+ /** The npm-installed package directory of the current CLI. */
66
+ const CURRENT_PACKAGE_PATH = join('node_modules', '@noodleseed', 'one');
67
+ /** Known previous Noodle CLI installs (also safe to replace, but never "active"). */
68
+ const LEGACY_PACKAGE_PATHS = [join('node_modules', 'noodleseed-cli')];
69
+ function containsPackagePath(path, packagePath) {
70
+ return path.includes(`${sep}${packagePath}${sep}`) || path.endsWith(`${sep}${packagePath}`);
71
+ }
72
+ function isCurrentPackagePath(path) {
73
+ return containsPackagePath(path, CURRENT_PACKAGE_PATH);
74
+ }
75
+ function isOwnedPackagePath(path) {
76
+ return (isCurrentPackagePath(path) ||
77
+ LEGACY_PACKAGE_PATHS.some((legacy) => containsPackagePath(path, legacy)));
78
+ }
79
+ /** Inspect the expected global `noodle` binary and classify it. Never mutates anything. */
80
+ export function inspectNoodleBinary(deps = realBinaryProbeDeps()) {
81
+ const expectedBinDir = dirname(deps.execPath);
82
+ const binPath = join(expectedBinDir, 'noodle');
83
+ return { expectedBinDir, binPath, status: classify(deps, expectedBinDir, binPath) };
84
+ }
85
+ function classify(deps, expectedBinDir, binPath) {
86
+ switch (deps.lstatKind(binPath)) {
87
+ case 'missing':
88
+ return { kind: 'none' };
89
+ case 'error':
90
+ return { kind: 'unsafe', reason: 'the existing binary could not be inspected' };
91
+ case 'dir':
92
+ case 'other':
93
+ return { kind: 'unsafe', reason: 'the path is not a regular file or symlink' };
94
+ case 'symlink':
95
+ return classifySymlink(deps, expectedBinDir, binPath);
96
+ case 'file':
97
+ return classifyFile(deps, binPath);
98
+ }
99
+ }
100
+ function classifySymlink(deps, expectedBinDir, binPath) {
101
+ const link = deps.readlink(binPath);
102
+ if (link === undefined)
103
+ return { kind: 'unsafe', reason: 'the symlink could not be read' };
104
+ const linkTarget = isAbsolute(link) ? link : resolve(dirname(binPath), link);
105
+ const real = deps.realpath(binPath);
106
+ if (real === undefined) {
107
+ // Dangling symlink: removing it cannot destroy anything.
108
+ return { kind: 'safe-repair', reason: `broken symlink to ${linkTarget}` };
109
+ }
110
+ if (isOwnedPackagePath(real) || isOwnedPackagePath(linkTarget)) {
111
+ // Only the current package inside the active prefix is npm-updatable in place;
112
+ // a legacy package's bin (any prefix) still blocks `npm install -g @noodleseed/one`.
113
+ if (isCurrentPackagePath(real)) {
114
+ // Canonicalize the active prefix too (macOS tmp dirs resolve through /private).
115
+ const prefixDir = dirname(expectedBinDir);
116
+ const prefix = deps.realpath(prefixDir) ?? prefixDir;
117
+ if (real.startsWith(`${prefix}${sep}`)) {
118
+ return { kind: 'active-install', target: real };
119
+ }
120
+ }
121
+ return {
122
+ kind: 'safe-repair',
123
+ reason: `symlink into a Noodle CLI install that npm cannot update in place (${real})`,
124
+ };
125
+ }
126
+ return {
127
+ kind: 'unsafe',
128
+ reason: `the symlink resolves to ${real}, which is not a Noodle CLI install`,
129
+ };
130
+ }
131
+ function classifyFile(deps, binPath) {
132
+ const head = deps.readFileHead(binPath);
133
+ if (head === undefined)
134
+ return { kind: 'unsafe', reason: 'the existing file is unreadable' };
135
+ // npm launcher shims (Windows-style .cmd/.ps1 or sh) embed the package path they run.
136
+ if (head.includes('@noodleseed/one') || head.includes('noodleseed-cli')) {
137
+ return { kind: 'safe-repair', reason: 'launcher script for a previous Noodle CLI install' };
138
+ }
139
+ return {
140
+ kind: 'unsafe',
141
+ reason: 'the existing file is not known to be owned by @noodleseed/one',
142
+ };
143
+ }
144
+ //# sourceMappingURL=update-binary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-binary.js","sourceRoot":"","sources":["../src/update-binary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Passive post-command update check (#242, ADR 0118, refining ADR 0079).
3
+ *
4
+ * Default behavior on a human TTY: at most once per day, offer "Update now?"
5
+ * (Enter = yes; "n" snoozes for 24h via `updateCheck.snoozedUntil`). When a prompt
6
+ * is not possible (no interactive stdin, NOODLE_NO_PROMPT, machine notices) it
7
+ * falls back to the once-per-day notice. `NOODLE_UPDATE_MODE` selects explicit
8
+ * behaviors for automation: `off` (no checks), `notify` (notice only), `check`
9
+ * (stable exit-code overlay 10 when an update is available — the only mode that
10
+ * runs without a TTY / in CI), and `auto` (run the update, interactive shells
11
+ * only; `NOODLE_AUTO_UPDATE` stays as the shipped alias).
12
+ *
13
+ * A failed, declined, or crashed check must NEVER break or re-code the user's
14
+ * actual command — every failure path resolves to `undefined`.
15
+ */
16
+ export type UpdateMode = 'off' | 'notify' | 'check' | 'auto' | 'prompt';
17
+ export interface UpdateCheckInput {
18
+ readonly command: string | undefined;
19
+ /** Remaining argv of the invocation; any `--json` invocation skips the check. */
20
+ readonly argv?: readonly string[];
21
+ readonly env: NodeJS.ProcessEnv;
22
+ readonly home: string;
23
+ readonly fetchImpl?: typeof fetch;
24
+ /** Injectable updater (defaults to `runUpdateCommand`); tests avoid spawning npm. */
25
+ readonly runUpdate?: (rest: readonly string[]) => Promise<number>;
26
+ readonly confirmImpl?: (message: string) => Promise<boolean>;
27
+ /** May we prompt? Defaults to stdin+stderr being TTYs. */
28
+ readonly promptCapable?: boolean;
29
+ /** May we print a notice? Defaults to stderr being a TTY. */
30
+ readonly noticeCapable?: boolean;
31
+ }
32
+ /** Resolve the update mode: NOODLE_UPDATE_MODE, else the NOODLE_AUTO_UPDATE alias, else the default prompt. */
33
+ export declare function resolveUpdateMode(env: NodeJS.ProcessEnv): UpdateMode;
34
+ /**
35
+ * Run the passive update check after a successful command. Returns an exit-code
36
+ * overlay only under `NOODLE_UPDATE_MODE=check` (10 = update available); every
37
+ * other outcome — including all failures — resolves `undefined`.
38
+ */
39
+ export declare function maybeCheckForCliUpdate(input: UpdateCheckInput): Promise<number | undefined>;
40
+ //# sourceMappingURL=update-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAsBH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AAExE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,iFAAiF;IACjF,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IAClC,qFAAqF;IACrF,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClE,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,0DAA0D;IAC1D,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,+GAA+G;AAC/G,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,UAAU,CAKpE;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAMjG"}
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Passive post-command update check (#242, ADR 0118, refining ADR 0079).
3
+ *
4
+ * Default behavior on a human TTY: at most once per day, offer "Update now?"
5
+ * (Enter = yes; "n" snoozes for 24h via `updateCheck.snoozedUntil`). When a prompt
6
+ * is not possible (no interactive stdin, NOODLE_NO_PROMPT, machine notices) it
7
+ * falls back to the once-per-day notice. `NOODLE_UPDATE_MODE` selects explicit
8
+ * behaviors for automation: `off` (no checks), `notify` (notice only), `check`
9
+ * (stable exit-code overlay 10 when an update is available — the only mode that
10
+ * runs without a TTY / in CI), and `auto` (run the update, interactive shells
11
+ * only; `NOODLE_AUTO_UPDATE` stays as the shipped alias).
12
+ *
13
+ * A failed, declined, or crashed check must NEVER break or re-code the user's
14
+ * actual command — every failure path resolves to `undefined`.
15
+ */
16
+ import { runUpdateCommand } from './commands/update-ops.js';
17
+ import { readConfig, writeConfig } from './config.js';
18
+ import { detectColorMode } from './gradient.js';
19
+ import { confirm } from './prompts.js';
20
+ import { bundledAgentKitVersion, fetchLatestAgentKitVersion, isSkillsUpdateAvailable, skillsUpdatePromptMessage, } from './skills-update.js';
21
+ import { CLI_PACKAGE_NAME, compareVersions, currentCliVersion, fetchLatestVersion, truthyEnv, UPDATE_CHECK_INTERVAL_MS, } from './update.js';
22
+ import { renderUpdateAvailable } from './update-render.js';
23
+ /** Resolve the update mode: NOODLE_UPDATE_MODE, else the NOODLE_AUTO_UPDATE alias, else the default prompt. */
24
+ export function resolveUpdateMode(env) {
25
+ const raw = env.NOODLE_UPDATE_MODE?.toLowerCase();
26
+ if (raw === 'off' || raw === 'notify' || raw === 'check' || raw === 'auto')
27
+ return raw;
28
+ if (truthyEnv(env.NOODLE_AUTO_UPDATE))
29
+ return 'auto';
30
+ return 'prompt';
31
+ }
32
+ /**
33
+ * Run the passive update check after a successful command. Returns an exit-code
34
+ * overlay only under `NOODLE_UPDATE_MODE=check` (10 = update available); every
35
+ * other outcome — including all failures — resolves `undefined`.
36
+ */
37
+ export async function maybeCheckForCliUpdate(input) {
38
+ try {
39
+ return await checkForCliUpdate(input);
40
+ }
41
+ catch {
42
+ return undefined; // an optional check must never break the user's command
43
+ }
44
+ }
45
+ async function checkForCliUpdate(input) {
46
+ const { env } = input;
47
+ if (shouldSkipCommand(input.command))
48
+ return undefined;
49
+ if (truthyEnv(env.NOODLE_DISABLE_UPDATE_CHECK))
50
+ return undefined;
51
+ if (input.argv?.includes('--json'))
52
+ return undefined;
53
+ const mode = resolveUpdateMode(env);
54
+ if (mode === 'off')
55
+ return undefined;
56
+ const noticeCapable = input.noticeCapable ?? process.stderr.isTTY === true;
57
+ const promptCapable = input.promptCapable ?? (process.stdin.isTTY === true && noticeCapable);
58
+ const jsonNotices = truthyEnv(env.NOODLE_UPDATE_JSON);
59
+ // `check` is the automation contract and runs anywhere; everything else stays
60
+ // out of CI and non-interactive shells (never prompt or auto-update there).
61
+ if (mode !== 'check' && (truthyEnv(env.CI) || !noticeCapable))
62
+ return undefined;
63
+ const installed = currentCliVersion();
64
+ const fetchImpl = input.fetchImpl ?? fetch;
65
+ const config = readConfig(input.home);
66
+ const wantsPrompt = mode === 'prompt' && promptCapable && !truthyEnv(env.NOODLE_NO_PROMPT) && !jsonNotices;
67
+ if (wantsPrompt || mode === 'check') {
68
+ if (wantsPrompt && isSnoozed(config.updateCheck?.snoozedUntil))
69
+ return undefined;
70
+ // Deterministic freshness: use the cached latest when fresh, else fetch once.
71
+ let latest;
72
+ let skillsLatest;
73
+ if (isFresh(config.updateCheck?.checkedAt) && config.updateCheck?.latestVersion !== undefined) {
74
+ latest = config.updateCheck.latestVersion;
75
+ }
76
+ else {
77
+ latest = await fetchLatestVersion(fetchImpl).catch(() => undefined);
78
+ skillsLatest = await fetchLatestAgentKitVersion(fetchImpl).catch(() => undefined);
79
+ if (latest !== undefined || skillsLatest !== undefined) {
80
+ writeCheckCache(input.home, latest, skillsLatest);
81
+ }
82
+ }
83
+ const newer = latest !== undefined && compareVersions(latest, installed) > 0;
84
+ if (mode === 'check') {
85
+ if (!newer || latest === undefined)
86
+ return undefined;
87
+ emitNotice(jsonNotices, installed, latest);
88
+ return 10;
89
+ }
90
+ if (newer && latest !== undefined) {
91
+ // Snooze before asking so an aborted or killed prompt never repeats.
92
+ snooze(input.home);
93
+ console.error(renderUpdateAvailable(installed, latest, detectColorMode(process.stderr)));
94
+ const ask = input.confirmImpl ?? ((message) => confirm(message, { output: process.stderr }));
95
+ const accepted = await ask('Update now?').catch(() => false);
96
+ if (accepted) {
97
+ await runUpdate(input)(['--yes']).catch(() => 1);
98
+ }
99
+ else {
100
+ console.error('Snoozed for 24 hours. Run `noodle update` when ready.');
101
+ }
102
+ }
103
+ maybeSkillsNotice(jsonNotices, skillsLatest);
104
+ return undefined;
105
+ }
106
+ // notify / auto (and non-promptable defaults): the once-per-24h notice pass.
107
+ if (isFresh(config.updateCheck?.checkedAt))
108
+ return undefined;
109
+ const latest = await fetchLatestVersion(fetchImpl).catch(() => undefined);
110
+ const skillsLatest = await fetchLatestAgentKitVersion(fetchImpl).catch(() => undefined);
111
+ if (latest === undefined && skillsLatest === undefined)
112
+ return undefined;
113
+ writeCheckCache(input.home, latest, skillsLatest);
114
+ if (latest !== undefined && compareVersions(latest, installed) > 0) {
115
+ if (mode === 'auto') {
116
+ console.error(`A newer Noodle CLI is available: ${installed} -> ${latest}`);
117
+ console.error(`${autoTrigger(env)} — updating now...`);
118
+ await runUpdate(input)(['--yes']).catch(() => 1);
119
+ }
120
+ else {
121
+ emitNotice(jsonNotices, installed, latest);
122
+ }
123
+ }
124
+ maybeSkillsNotice(jsonNotices, skillsLatest);
125
+ return undefined;
126
+ }
127
+ function runUpdate(input) {
128
+ return input.runUpdate ?? ((rest) => runUpdateCommand(rest, { env: input.env }));
129
+ }
130
+ function shouldSkipCommand(command) {
131
+ return (command === undefined ||
132
+ command === '--version' ||
133
+ command === '-v' ||
134
+ command === 'version' ||
135
+ command === '--help' ||
136
+ command === '-h' ||
137
+ command === 'help' ||
138
+ command === 'update');
139
+ }
140
+ function emitNotice(jsonNotices, installed, latest) {
141
+ if (jsonNotices) {
142
+ console.error(JSON.stringify({
143
+ event: 'update_available',
144
+ package: CLI_PACKAGE_NAME,
145
+ installed,
146
+ latest,
147
+ recommendedCommand: 'noodle update --yes --json',
148
+ }));
149
+ return;
150
+ }
151
+ console.error(`A newer Noodle CLI is available: ${installed} -> ${latest}`);
152
+ console.error('Update: noodle update');
153
+ }
154
+ /** Self-checking skills: notify (never auto-update) when the registry has a newer agent-kit. */
155
+ function maybeSkillsNotice(jsonNotices, skillsLatest) {
156
+ if (jsonNotices)
157
+ return; // machine notices carry only the CLI update event
158
+ if (skillsLatest !== undefined && isSkillsUpdateAvailable(skillsLatest)) {
159
+ console.error(skillsUpdatePromptMessage(skillsLatest, bundledAgentKitVersion()));
160
+ }
161
+ }
162
+ function autoTrigger(env) {
163
+ return env.NOODLE_UPDATE_MODE?.toLowerCase() === 'auto'
164
+ ? 'NOODLE_UPDATE_MODE=auto'
165
+ : 'NOODLE_AUTO_UPDATE is set';
166
+ }
167
+ function isFresh(checkedAt) {
168
+ if (checkedAt === undefined)
169
+ return false;
170
+ const checked = Date.parse(checkedAt);
171
+ if (!Number.isFinite(checked))
172
+ return false;
173
+ return Date.now() - checked < UPDATE_CHECK_INTERVAL_MS;
174
+ }
175
+ function isSnoozed(snoozedUntil) {
176
+ if (snoozedUntil === undefined)
177
+ return false;
178
+ const until = Date.parse(snoozedUntil);
179
+ return Number.isFinite(until) && Date.now() < until;
180
+ }
181
+ function writeCheckCache(home, latestVersion, skillsLatestVersion) {
182
+ const config = readConfig(home);
183
+ writeConfig({
184
+ ...config,
185
+ updateCheck: {
186
+ checkedAt: new Date().toISOString(),
187
+ ...(latestVersion !== undefined ? { latestVersion } : {}),
188
+ ...(skillsLatestVersion !== undefined ? { skillsLatestVersion } : {}),
189
+ ...(config.updateCheck?.snoozedUntil !== undefined &&
190
+ isSnoozed(config.updateCheck.snoozedUntil)
191
+ ? { snoozedUntil: config.updateCheck.snoozedUntil }
192
+ : {}),
193
+ },
194
+ }, home);
195
+ }
196
+ function snooze(home) {
197
+ const config = readConfig(home);
198
+ writeConfig({
199
+ ...config,
200
+ updateCheck: {
201
+ checkedAt: config.updateCheck?.checkedAt ?? new Date().toISOString(),
202
+ ...(config.updateCheck?.latestVersion !== undefined
203
+ ? { latestVersion: config.updateCheck.latestVersion }
204
+ : {}),
205
+ ...(config.updateCheck?.skillsLatestVersion !== undefined
206
+ ? { skillsLatestVersion: config.updateCheck.skillsLatestVersion }
207
+ : {}),
208
+ snoozedUntil: new Date(Date.now() + UPDATE_CHECK_INTERVAL_MS).toISOString(),
209
+ },
210
+ }, home);
211
+ }
212
+ //# sourceMappingURL=update-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-check.js","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Branded rendering for the update flow: the warm palette and step glyphs the
3
+ * rest of the CLI already speaks (gradient.ts + status.ts), composed - never
4
+ * reinvented - for version deltas, settled results, and repair notices.
5
+ *
6
+ * The 'none' color mode is a hard contract: byte-identical plain, escape-free
7
+ * copy. It is what agents, CI, pipes, NO_COLOR, and the update-command tests
8
+ * see, and it matches the #242 spec strings exactly.
9
+ */
10
+ import { type ColorMode } from './gradient.js';
11
+ /** "Noodle CLI update available: X -> Y" - old version dimmed, arrow amber, new version orange. */
12
+ export declare function renderUpdateAvailable(installed: string, latest: string, mode: ColorMode): string;
13
+ export declare function renderUpToDate(installed: string, mode: ColorMode): string;
14
+ export declare function renderUpdated(installed: string, latest: string, mode: ColorMode): string;
15
+ /** A calm ⚠ line for repair situations; plain mode passes the text through untouched. */
16
+ export declare function renderRepairNotice(text: string, mode: ColorMode): string;
17
+ //# sourceMappingURL=update-render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-render.d.ts","sourceRoot":"","sources":["../src/update-render.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAS,KAAK,SAAS,EAAkC,MAAM,eAAe,CAAC;AAQtF,mGAAmG;AACnG,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAGhG;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAIzE;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAQxF;AAED,yFAAyF;AACzF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAGxE"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Branded rendering for the update flow: the warm palette and step glyphs the
3
+ * rest of the CLI already speaks (gradient.ts + status.ts), composed - never
4
+ * reinvented - for version deltas, settled results, and repair notices.
5
+ *
6
+ * The 'none' color mode is a hard contract: byte-identical plain, escape-free
7
+ * copy. It is what agents, CI, pipes, NO_COLOR, and the update-command tests
8
+ * see, and it matches the #242 spec strings exactly.
9
+ */
10
+ import { AMBER, detectGlyphMode, ORANGE, paint } from './gradient.js';
11
+ import { renderStep } from './status.js';
12
+ // Control codes composed per the gradient.ts convention (no raw ESC bytes in source).
13
+ const ESC = String.fromCharCode(27);
14
+ const DIM = `${ESC}[2m`;
15
+ const UNDIM = `${ESC}[22m`;
16
+ /** "Noodle CLI update available: X -> Y" - old version dimmed, arrow amber, new version orange. */
17
+ export function renderUpdateAvailable(installed, latest, mode) {
18
+ if (mode === 'none')
19
+ return `Noodle CLI update available: ${installed} -> ${latest}`;
20
+ return `Noodle CLI update available: ${DIM}${installed}${UNDIM} ${paint(AMBER, '→', mode)} ${paint(ORANGE, latest, mode)}`;
21
+ }
22
+ export function renderUpToDate(installed, mode) {
23
+ const text = `Noodle CLI is up to date. (v${installed})`;
24
+ if (mode === 'none')
25
+ return text;
26
+ return renderStep('done', text, mode, detectGlyphMode());
27
+ }
28
+ export function renderUpdated(installed, latest, mode) {
29
+ if (mode === 'none')
30
+ return `Updated Noodle CLI: ${installed} -> ${latest}`;
31
+ return renderStep('done', `Updated Noodle CLI: ${DIM}${installed}${UNDIM} ${paint(AMBER, '→', mode)} ${paint(ORANGE, latest, mode)}`, mode, detectGlyphMode());
32
+ }
33
+ /** A calm ⚠ line for repair situations; plain mode passes the text through untouched. */
34
+ export function renderRepairNotice(text, mode) {
35
+ if (mode === 'none')
36
+ return text;
37
+ return renderStep('warn', text, mode, detectGlyphMode());
38
+ }
39
+ //# sourceMappingURL=update-render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-render.js","sourceRoot":"","sources":["../src/update-render.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,EAAkB,eAAe,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,sFAAsF;AACtF,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;AACpC,MAAM,GAAG,GAAG,GAAG,GAAG,KAAK,CAAC;AACxB,MAAM,KAAK,GAAG,GAAG,GAAG,MAAM,CAAC;AAE3B,mGAAmG;AACnG,MAAM,UAAU,qBAAqB,CAAC,SAAiB,EAAE,MAAc,EAAE,IAAe;IACtF,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,gCAAgC,SAAS,OAAO,MAAM,EAAE,CAAC;IACrF,OAAO,gCAAgC,GAAG,GAAG,SAAS,GAAG,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;AAC7H,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,SAAiB,EAAE,IAAe;IAC/D,MAAM,IAAI,GAAG,+BAA+B,SAAS,GAAG,CAAC;IACzD,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE,MAAc,EAAE,IAAe;IAC9E,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,uBAAuB,SAAS,OAAO,MAAM,EAAE,CAAC;IAC5E,OAAO,UAAU,CACf,MAAM,EACN,uBAAuB,GAAG,GAAG,SAAS,GAAG,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAC1G,IAAI,EACJ,eAAe,EAAE,CAClB,CAAC;AACJ,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,IAAe;IAC9D,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC;AAC3D,CAAC"}
package/dist/update.d.ts CHANGED
@@ -1,14 +1,15 @@
1
1
  export declare const CLI_PACKAGE_NAME = "@noodleseed/one";
2
2
  export declare const GLOBAL_UPDATE_COMMAND = "npm install -g @noodleseed/one@latest";
3
+ export declare const UPDATE_CHECK_INTERVAL_MS: number;
3
4
  export declare function currentCliVersion(): string;
4
- export declare function runUpdateCommand(rest: readonly string[]): Promise<number>;
5
- export declare function maybeCheckForCliUpdate(input: {
6
- readonly command: string | undefined;
7
- readonly env: NodeJS.ProcessEnv;
8
- readonly home: string;
9
- readonly fetchImpl?: typeof fetch;
10
- /** Injectable updater (defaults to {@link runUpdateCommand}); used by tests to avoid spawning npm. */
11
- readonly runUpdate?: (rest: readonly string[]) => Promise<number>;
12
- }): Promise<void>;
5
+ /** True for set env toggles, honoring the `0`/`false` opt-outs. */
6
+ export declare function truthyEnv(value: string | undefined): boolean;
7
+ /**
8
+ * Fetch the registry `latest` dist-tag version of the CLI package. Throws on
9
+ * failure so callers choose their own inconclusive-network handling. The passive
10
+ * check uses the default ~1s budget; the explicit `noodle update` command passes
11
+ * a longer one.
12
+ */
13
+ export declare function fetchLatestVersion(fetchImpl: typeof fetch, timeoutMs?: number): Promise<string | undefined>;
13
14
  export declare function compareVersions(a: string, b: string): number;
14
15
  //# sourceMappingURL=update.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,gBAAgB,oBAAoB,CAAC;AAClD,eAAO,MAAM,qBAAqB,0CAA8C,CAAC;AAOjF,wBAAgB,iBAAiB,IAAI,MAAM,CAO1C;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAkB/E;AAED,wBAAsB,sBAAsB,CAAC,KAAK,EAAE;IAClD,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IAClC,sGAAsG;IACtG,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACnE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyChB;AA2CD,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAU5D"}
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,gBAAgB,oBAAoB,CAAC;AAClD,eAAO,MAAM,qBAAqB,0CAA8C,CAAC;AAEjF,eAAO,MAAM,wBAAwB,QAAsB,CAAC;AAK5D,wBAAgB,iBAAiB,IAAI,MAAM,CAO1C;AAED,mEAAmE;AACnE,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAG5D;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,OAAO,KAAK,EACvB,SAAS,SAAO,GACf,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAQ7B;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAU5D"}