@vibe-commit/capture 0.4.4 → 0.5.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 (100) hide show
  1. package/README.md +60 -1
  2. package/dist/atomic_write.d.ts +14 -0
  3. package/dist/atomic_write.js +33 -0
  4. package/dist/atomic_write.js.map +1 -0
  5. package/dist/commands/auth.d.ts +2 -2
  6. package/dist/commands/auth.js +46 -11
  7. package/dist/commands/auth.js.map +1 -1
  8. package/dist/commands/browser_credential.d.ts +39 -12
  9. package/dist/commands/browser_credential.js +84 -11
  10. package/dist/commands/browser_credential.js.map +1 -1
  11. package/dist/commands/connect.d.ts +8 -2
  12. package/dist/commands/connect.js +72 -11
  13. package/dist/commands/connect.js.map +1 -1
  14. package/dist/commands/credential_problem.d.ts +43 -0
  15. package/dist/commands/credential_problem.js +81 -0
  16. package/dist/commands/credential_problem.js.map +1 -0
  17. package/dist/commands/device_credential.d.ts +47 -0
  18. package/dist/commands/device_credential.js +275 -0
  19. package/dist/commands/device_credential.js.map +1 -0
  20. package/dist/commands/finalize.js +9 -1
  21. package/dist/commands/finalize.js.map +1 -1
  22. package/dist/commands/finish_mint.d.ts +73 -0
  23. package/dist/commands/finish_mint.js +140 -0
  24. package/dist/commands/finish_mint.js.map +1 -0
  25. package/dist/commands/probe.d.ts +14 -0
  26. package/dist/commands/probe.js +29 -0
  27. package/dist/commands/probe.js.map +1 -0
  28. package/dist/commands/report.js +6 -1
  29. package/dist/commands/report.js.map +1 -1
  30. package/dist/commands/status.d.ts +1 -1
  31. package/dist/commands/status.js +112 -57
  32. package/dist/commands/status.js.map +1 -1
  33. package/dist/commands/why.d.ts +11 -8
  34. package/dist/commands/why.js +32 -5
  35. package/dist/commands/why.js.map +1 -1
  36. package/dist/copy/index.d.ts +1 -1
  37. package/dist/copy/index.js +1 -1
  38. package/dist/copy/index.js.map +1 -1
  39. package/dist/copy/strings.d.ts +214 -3
  40. package/dist/copy/strings.js +248 -3
  41. package/dist/copy/strings.js.map +1 -1
  42. package/dist/credential.d.ts +25 -0
  43. package/dist/credential.js +41 -3
  44. package/dist/credential.js.map +1 -1
  45. package/dist/credential_meta.d.ts +66 -0
  46. package/dist/credential_meta.js +164 -0
  47. package/dist/credential_meta.js.map +1 -0
  48. package/dist/device_mode.d.ts +18 -0
  49. package/dist/device_mode.js +28 -0
  50. package/dist/device_mode.js.map +1 -0
  51. package/dist/hooks/entry.d.ts +5 -0
  52. package/dist/hooks/entry.js +40 -5
  53. package/dist/hooks/entry.js.map +1 -1
  54. package/dist/index.js +33 -3
  55. package/dist/index.js.map +1 -1
  56. package/dist/install.d.ts +37 -0
  57. package/dist/install.js +29 -2
  58. package/dist/install.js.map +1 -1
  59. package/dist/oauth/device.d.ts +129 -0
  60. package/dist/oauth/device.js +194 -0
  61. package/dist/oauth/device.js.map +1 -0
  62. package/dist/oauth/discovery.d.ts +5 -0
  63. package/dist/oauth/discovery.js +6 -0
  64. package/dist/oauth/discovery.js.map +1 -1
  65. package/dist/oauth/mint.d.ts +18 -5
  66. package/dist/oauth/mint.js +18 -5
  67. package/dist/oauth/mint.js.map +1 -1
  68. package/dist/oauth/retire.d.ts +64 -0
  69. package/dist/oauth/retire.js +106 -0
  70. package/dist/oauth/retire.js.map +1 -0
  71. package/dist/oauth/signin.d.ts +12 -0
  72. package/dist/oauth/signin.js +5 -1
  73. package/dist/oauth/signin.js.map +1 -1
  74. package/dist/oauth/token.d.ts +1 -0
  75. package/dist/oauth/token.js +5 -0
  76. package/dist/oauth/token.js.map +1 -1
  77. package/dist/oauth/whoami.d.ts +55 -0
  78. package/dist/oauth/whoami.js +77 -0
  79. package/dist/oauth/whoami.js.map +1 -0
  80. package/dist/paths.d.ts +19 -0
  81. package/dist/paths.js +25 -0
  82. package/dist/paths.js.map +1 -1
  83. package/dist/post.d.ts +14 -0
  84. package/dist/post.js +15 -0
  85. package/dist/post.js.map +1 -1
  86. package/dist/state.d.ts +80 -0
  87. package/dist/state.js +239 -1
  88. package/dist/state.js.map +1 -1
  89. package/dist/system_message.d.ts +21 -2
  90. package/dist/system_message.js +37 -7
  91. package/dist/system_message.js.map +1 -1
  92. package/dist/term.d.ts +6 -0
  93. package/dist/term.js +15 -0
  94. package/dist/term.js.map +1 -1
  95. package/dist/update_nudge.d.ts +31 -0
  96. package/dist/update_nudge.js +127 -0
  97. package/dist/update_nudge.js.map +1 -0
  98. package/dist/version.d.ts +1 -1
  99. package/dist/version.js +1 -1
  100. package/package.json +3 -3
@@ -29,8 +29,9 @@
29
29
  */
30
30
  import { mkdirSync, writeFileSync } from "node:fs";
31
31
  import { dirname } from "node:path";
32
- import { SYSTEM_MESSAGE, URLS } from "./copy/index.js";
33
- import { repoDayNoticePath, sessionNoticePath } from "./paths.js";
32
+ import { COMMANDS, SYSTEM_MESSAGE, URLS } from "./copy/index.js";
33
+ import { endDateText } from "./credential_meta.js";
34
+ import { machineDayNoticePath, repoDayNoticePath, sessionNoticePath } from "./paths.js";
34
35
  import { NODE_FLOOR_TEXT } from "./runtime.js";
35
36
  /**
36
37
  * The UTC calendar day, `YYYY-MM-DD`.
@@ -43,13 +44,32 @@ import { NODE_FLOOR_TEXT } from "./runtime.js";
43
44
  export function utcDay(now) {
44
45
  return now.toISOString().slice(0, 10);
45
46
  }
47
+ /** `COMMANDS.auth` — what a notice names when the caller did not say how this install is run. */
48
+ const DEFAULT_AUTH_COMMAND = COMMANDS.auth;
46
49
  /** The one-line text for a state. Never contains an escape sequence. */
47
- export function noticeText(state, nodeVersion) {
50
+ export function noticeText(state, nodeVersion, authCommand = DEFAULT_AUTH_COMMAND, endsAt) {
48
51
  switch (state) {
52
+ case "credential_ending": {
53
+ const date = endsAt === undefined ? null : endDateText(endsAt);
54
+ // No date, no message: a "ends ..." line with a blank in it is worse than silence. The caller
55
+ // treats an empty text as "write nothing".
56
+ if (date === null)
57
+ return "";
58
+ const line = SYSTEM_MESSAGE.credentialEnding(date, authCommand);
59
+ return line.length <= SYSTEM_MESSAGE.credentialRejectedBudget
60
+ ? line
61
+ : SYSTEM_MESSAGE.credentialEndingFallback(date);
62
+ }
49
63
  case "not_connected":
50
64
  return SYSTEM_MESSAGE.notConnected;
51
- case "credential_revoked":
52
- return SYSTEM_MESSAGE.credentialRevoked;
65
+ case "credential_revoked": {
66
+ // ≤120 characters (`11A`). A long plugin realpath would blow it, and a truncated command is
67
+ // worse than no command: the fallback points at the page that always works.
68
+ const line = SYSTEM_MESSAGE.credentialRejected(authCommand);
69
+ return line.length <= SYSTEM_MESSAGE.credentialRejectedBudget
70
+ ? line
71
+ : SYSTEM_MESSAGE.credentialRejectedFallback;
72
+ }
53
73
  case "unsupported_runtime":
54
74
  return SYSTEM_MESSAGE.unsupportedRuntime(NODE_FLOOR_TEXT, nodeVersion);
55
75
  case "capture_confirmed":
@@ -68,8 +88,16 @@ export function noticeText(state, nodeVersion) {
68
88
  * this channel's fallback everywhere else too.
69
89
  */
70
90
  export function noticeClaimPath(ctx, state) {
91
+ if (state === "credential_ending") {
92
+ // Per MACHINE and day, and per credential: replacing it re-arms (a new credential has a new end).
93
+ return machineDayNoticePath(ctx.home, utcDay(ctx.now()), `${state}-${ctx.fingerprint ?? "unknown"}`);
94
+ }
71
95
  if (state !== "capture_confirmed") {
72
- return sessionNoticePath(ctx.home, ctx.sessionId, state);
96
+ // State 2 is keyed by the credential too (`11A`); fingerprints are hex, so the path stays clean.
97
+ const key = state === "credential_revoked" && ctx.fingerprint !== undefined
98
+ ? `${state}-${ctx.fingerprint}`
99
+ : state;
100
+ return sessionNoticePath(ctx.home, ctx.sessionId, key);
73
101
  }
74
102
  if (ctx.repoKey === null || ctx.repoKey === "")
75
103
  return null;
@@ -113,7 +141,9 @@ export function claimSessionNotice(ctx, state) {
113
141
  */
114
142
  export function renderNotice(ctx, state) {
115
143
  try {
116
- const text = noticeText(state, ctx.nodeVersion);
144
+ const text = noticeText(state, ctx.nodeVersion, ctx.authCommand, ctx.endsAt);
145
+ if (text === "")
146
+ return null;
117
147
  // A message carrying an escape sequence or a newline is undefined behaviour
118
148
  // in Claude Code's renderer, so it is dropped rather than sent — silence is
119
149
  // the fallback. Tested by char code, not by a regex holding a literal
@@ -1 +1 @@
1
- {"version":3,"file":"system_message.js","sourceRoot":"","sources":["../src/system_message.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"system_message.js","sourceRoot":"","sources":["../src/system_message.ts"],"names":[],"mappings":"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"}
package/dist/term.d.ts CHANGED
@@ -86,6 +86,12 @@ export declare function wrap(text: string, indent: number, hangingIndent?: numbe
86
86
  * filename identifies and the directory does not.
87
87
  */
88
88
  export declare function truncatePath(path: string, max: number): string;
89
+ /**
90
+ * Shorten from the MIDDLE to `max` columns, keeping both ends — §13.4 for values whose start and
91
+ * end both identify them (a workspace name, a handle). `truncatePath` cuts the left, which suits a
92
+ * path whose tail is the name; here the head is just as much the name.
93
+ */
94
+ export declare function truncateMiddle(text: string, max: number): string;
89
95
  /** §13.5 — key/value output on the fixed label gutter. */
90
96
  export declare function labelled(indent: number, key: string, value: string): string;
91
97
  /**
package/dist/term.js CHANGED
@@ -106,6 +106,21 @@ export function truncatePath(path, max) {
106
106
  return path;
107
107
  return `…${path.slice(path.length - (max - 1))}`;
108
108
  }
109
+ /**
110
+ * Shorten from the MIDDLE to `max` columns, keeping both ends — §13.4 for values whose start and
111
+ * end both identify them (a workspace name, a handle). `truncatePath` cuts the left, which suits a
112
+ * path whose tail is the name; here the head is just as much the name.
113
+ */
114
+ export function truncateMiddle(text, max) {
115
+ const chars = [...text];
116
+ if (chars.length <= max)
117
+ return text;
118
+ if (max <= 1)
119
+ return "…".slice(0, max);
120
+ const head = Math.ceil((max - 1) / 2);
121
+ const tail = max - 1 - head;
122
+ return `${chars.slice(0, head).join("")}…${tail === 0 ? "" : chars.slice(chars.length - tail).join("")}`;
123
+ }
109
124
  /** §13.5 — key/value output on the fixed label gutter. */
110
125
  export function labelled(indent, key, value) {
111
126
  return `${" ".repeat(indent)}${key.padEnd(LABEL_GUTTER)}${value}`;
package/dist/term.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"term.js","sourceRoot":"","sources":["../src/term.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"term.js","sourceRoot":"","sources":["../src/term.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The update nudge — `13A`, G7.
3
+ *
4
+ * The CLI had no way to learn that a better one existed: Alexander's machine ran 0.2.3 against an
5
+ * npm `latest` of 0.4.5 and nothing said so. mcp's `GET /client/latest` answers `{ npm?: "x.y.z" }`
6
+ * (it reads npm's `dist-tags.latest`; there is no `plugin` field until TODOS[178]), so user machines
7
+ * still talk to one host.
8
+ *
9
+ * ## When it speaks
10
+ *
11
+ * Interactive `status`, `connect` and `auth` — after the verb has SUCCEEDED, as the last thing on
12
+ * screen, after a blank line. Never after an error (the §13.6 fix line must stay last), never in a
13
+ * hook, never under `--json`, never when stdout is not a terminal, never with
14
+ * `VIBECOMMIT_NO_UPDATE_CHECK=1`.
15
+ *
16
+ * ## ⛔ IT FAILS SILENT, EVERYWHERE
17
+ *
18
+ * Any failure — no channel, a timeout, a bad body, an unwritable cache — returns no lines. The
19
+ * version string is printed only if it matches `^\d+\.\d+\.\d+$` and is newer than this build: it
20
+ * comes from a network response and lands on a user's terminal, so it must be a version and nothing
21
+ * else. The answer (or its absence) is cached for 24 hours, so an offline machine pays the 2 s once
22
+ * a day, not on every command.
23
+ */
24
+ import type { CommandContext } from "./commands/context.js";
25
+ export declare const LATEST_PATH = "/client/latest";
26
+ /** True when `a` is a newer x.y.z than `b`. Both must already match `VERSION`. */
27
+ export declare function isNewer(a: string, b: string): boolean;
28
+ /** The lines to print after a successful verb — `[]` for every reason not to. */
29
+ export declare function updateNudge(ctx: CommandContext, deps?: {
30
+ readonly fetch?: typeof fetch;
31
+ }): Promise<string[]>;
@@ -0,0 +1,127 @@
1
+ /**
2
+ * The update nudge — `13A`, G7.
3
+ *
4
+ * The CLI had no way to learn that a better one existed: Alexander's machine ran 0.2.3 against an
5
+ * npm `latest` of 0.4.5 and nothing said so. mcp's `GET /client/latest` answers `{ npm?: "x.y.z" }`
6
+ * (it reads npm's `dist-tags.latest`; there is no `plugin` field until TODOS[178]), so user machines
7
+ * still talk to one host.
8
+ *
9
+ * ## When it speaks
10
+ *
11
+ * Interactive `status`, `connect` and `auth` — after the verb has SUCCEEDED, as the last thing on
12
+ * screen, after a blank line. Never after an error (the §13.6 fix line must stay last), never in a
13
+ * hook, never under `--json`, never when stdout is not a terminal, never with
14
+ * `VIBECOMMIT_NO_UPDATE_CHECK=1`.
15
+ *
16
+ * ## ⛔ IT FAILS SILENT, EVERYWHERE
17
+ *
18
+ * Any failure — no channel, a timeout, a bad body, an unwritable cache — returns no lines. The
19
+ * version string is printed only if it matches `^\d+\.\d+\.\d+$` and is newer than this build: it
20
+ * comes from a network response and lands on a user's terminal, so it must be a version and nothing
21
+ * else. The answer (or its absence) is cached for 24 hours, so an offline machine pays the 2 s once
22
+ * a day, not on every command.
23
+ */
24
+ import { mkdirSync, readFileSync } from "node:fs";
25
+ import { writeFileAtomic } from "./atomic_write.js";
26
+ import { UPDATE } from "./copy/index.js";
27
+ import { installChannel } from "./install.js";
28
+ import { mcpUrl } from "./oauth/discovery.js";
29
+ import { stateDir, updateCheckPath } from "./paths.js";
30
+ import { paint } from "./term.js";
31
+ import { CLIENT_VERSION, CLIENT_VERSION_HEADER } from "./version.js";
32
+ export const LATEST_PATH = "/client/latest";
33
+ const CACHE_MS = 24 * 60 * 60 * 1000;
34
+ const TIMEOUT_MS = 2_000;
35
+ const VERSION = /^\d+\.\d+\.\d+$/;
36
+ /** True when `a` is a newer x.y.z than `b`. Both must already match `VERSION`. */
37
+ export function isNewer(a, b) {
38
+ const x = a.split(".").map(Number);
39
+ const y = b.split(".").map(Number);
40
+ for (let i = 0; i < 3; i += 1) {
41
+ if ((x[i] ?? 0) !== (y[i] ?? 0))
42
+ return (x[i] ?? 0) > (y[i] ?? 0);
43
+ }
44
+ return false;
45
+ }
46
+ const version = (v) => (typeof v === "string" && VERSION.test(v) ? v : undefined);
47
+ function readCache(home, nowMs) {
48
+ try {
49
+ const doc = JSON.parse(readFileSync(updateCheckPath(home), "utf8"));
50
+ if (typeof doc.checked_at_ms !== "number" || nowMs - doc.checked_at_ms > CACHE_MS)
51
+ return null;
52
+ if (doc.checked_at_ms > nowMs)
53
+ return null; // a clock that moved backwards: ask again
54
+ return { npm: version(doc.npm), plugin: version(doc.plugin) };
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ }
60
+ function writeCache(home, nowMs, latest) {
61
+ try {
62
+ mkdirSync(stateDir(home), { recursive: true, mode: 0o700 });
63
+ writeFileAtomic(updateCheckPath(home), `${JSON.stringify({ checked_at_ms: nowMs, ...latest })}\n`, 0o600);
64
+ }
65
+ catch {
66
+ /* a cache that cannot be written costs one more request tomorrow */
67
+ }
68
+ }
69
+ async function fetchLatest(endpoint, fetchImpl) {
70
+ const controller = new AbortController();
71
+ const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
72
+ try {
73
+ const res = await fetchImpl(new URL(LATEST_PATH, endpoint).toString(), {
74
+ headers: { accept: "application/json", [CLIENT_VERSION_HEADER.toLowerCase()]: CLIENT_VERSION },
75
+ signal: controller.signal,
76
+ redirect: "error",
77
+ });
78
+ if (res.status !== 200)
79
+ return {};
80
+ const doc = (await res.json());
81
+ return { npm: version(doc?.npm), plugin: version(doc?.plugin) };
82
+ }
83
+ catch {
84
+ return {};
85
+ }
86
+ finally {
87
+ clearTimeout(timer);
88
+ }
89
+ }
90
+ /** The lines to print after a successful verb — `[]` for every reason not to. */
91
+ export async function updateNudge(ctx, deps = {}) {
92
+ try {
93
+ if (ctx.env.VIBECOMMIT_NO_UPDATE_CHECK === "1")
94
+ return [];
95
+ if (ctx.stdout.isTTY !== true)
96
+ return [];
97
+ const channel = installChannel(ctx.env, ctx.selfPath);
98
+ if (channel.kind === "unknown")
99
+ return [];
100
+ const endpoint = mcpUrl(ctx.env);
101
+ if (endpoint === null)
102
+ return [];
103
+ const nowMs = ctx.now().getTime();
104
+ let latest = readCache(ctx.home, nowMs);
105
+ if (latest === null) {
106
+ latest = await fetchLatest(endpoint, deps.fetch ?? fetch);
107
+ writeCache(ctx.home, nowMs, latest);
108
+ }
109
+ if (channel.kind === "npm") {
110
+ if (latest.npm === undefined || !isNewer(latest.npm, CLIENT_VERSION))
111
+ return [];
112
+ return [
113
+ "",
114
+ ` ${paint(ctx.colour, "muted", UPDATE.npm(latest.npm, CLIENT_VERSION))}`,
115
+ ` ${paint(ctx.colour, "accent", UPDATE.npmCommand)}`,
116
+ ];
117
+ }
118
+ // plugin
119
+ if (latest.plugin === undefined || !isNewer(latest.plugin, CLIENT_VERSION))
120
+ return [];
121
+ return ["", ` ${paint(ctx.colour, "muted", UPDATE.plugin(latest.plugin))}`];
122
+ }
123
+ catch {
124
+ return [];
125
+ }
126
+ }
127
+ //# sourceMappingURL=update_nudge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update_nudge.js","sourceRoot":"","sources":["../src/update_nudge.ts"],"names":[],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -11,6 +11,6 @@
11
11
  * fields on disk (D58 plan §ER5/§ER14). This constant plus the skew check is the
12
12
  * whole fix: one source, asserted equal to the manifest and to the release tag.
13
13
  */
14
- export declare const CLIENT_VERSION = "0.4.4";
14
+ export declare const CLIENT_VERSION = "0.5.0";
15
15
  /** Header name for the wire contract. */
16
16
  export declare const CLIENT_VERSION_HEADER = "X-Client-Version";
package/dist/version.js CHANGED
@@ -11,7 +11,7 @@
11
11
  * fields on disk (D58 plan §ER5/§ER14). This constant plus the skew check is the
12
12
  * whole fix: one source, asserted equal to the manifest and to the release tag.
13
13
  */
14
- export const CLIENT_VERSION = "0.4.4";
14
+ export const CLIENT_VERSION = "0.5.0";
15
15
  /** Header name for the wire contract. */
16
16
  export const CLIENT_VERSION_HEADER = "X-Client-Version";
17
17
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-commit/capture",
3
- "version": "0.4.4",
3
+ "version": "0.5.0",
4
4
  "description": "VibeCommit capture client \u2014 records Claude Code sessions against the commits they produced.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -38,7 +38,7 @@
38
38
  "build": "tsc -p tsconfig.json",
39
39
  "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json",
40
40
  "pretest": "npm run build",
41
- "test": "node --test --import tsx 'test/**/*.test.ts'",
41
+ "test": "node --test --import tsx --import ./test/no_prod_network.ts 'test/**/*.test.ts'",
42
42
  "check:skew": "node scripts/check-version-skew.mjs",
43
43
  "fixture:write": "node --import tsx scripts/write-wire-fixture.mts"
44
44
  },
@@ -47,5 +47,5 @@
47
47
  "tsx": "^4.19.2",
48
48
  "typescript": "^5.7.3"
49
49
  },
50
- "gitHead": "0515e19b493277dbafad748a67c6fad436d1df97"
50
+ "gitHead": "9ea16fb133d46e37da2ffca2d2c7ecfa686deb72"
51
51
  }