@primitive.ai/prim 0.1.0-alpha.66 → 0.1.0-alpha.68

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.
@@ -245,9 +245,12 @@ function validDecisionUrl(value) {
245
245
  return void 0;
246
246
  }
247
247
  }
248
- function decisionLink(label, decisionUrl) {
248
+ function decisionLink(label, decisionUrl, plain) {
249
249
  const url = validDecisionUrl(decisionUrl);
250
- return url ? `\x1B]8;;${url}\x07\x1B[34;4m${label}\x1B[0m\x1B]8;;\x07` : label;
250
+ if (plain || !url) {
251
+ return label;
252
+ }
253
+ return `\x1B]8;;${url}\x07\x1B[34;4m${label}\x1B[0m\x1B]8;;\x07`;
251
254
  }
252
255
  function formatLabeled(labels, cap) {
253
256
  if (labels === void 0) {
@@ -264,13 +267,13 @@ function formatLabeled(labels, cap) {
264
267
  function formatTeammates(names, cap) {
265
268
  return formatLabeled(names?.map(stripControlChars), cap);
266
269
  }
267
- function formatTeammatesWithArea(teammates, cap) {
270
+ function formatTeammatesWithArea(teammates, cap, plainLinks = false) {
268
271
  return formatLabeled(
269
272
  teammates?.map((t) => {
270
273
  const name = stripControlChars(t.name);
271
274
  const area = stripControlChars(t.area ?? "").trim();
272
275
  const label = area ? `${name} - ${area}` : name;
273
- return decisionLink(label, t.decisionUrl);
276
+ return decisionLink(label, t.decisionUrl, plainLinks);
274
277
  }),
275
278
  cap
276
279
  );
@@ -278,25 +281,26 @@ function formatTeammatesWithArea(teammates, cap) {
278
281
 
279
282
  // src/lib/statusline-render.ts
280
283
  var STATUSLINE_NAME_CAP = 3;
281
- function formatStatusline(version, snapshot, resolveIngestionStatus) {
284
+ function formatStatusline(version, snapshot, resolveIngestionStatus, options = {}) {
285
+ const ingestionSuffix = (status) => status === void 0 ? "" : ` \xB7 Decision ingestion ${status}`;
286
+ const ingestionStatus = snapshot === null || snapshot.healthy === false ? options.includeIngestionWhenUnavailable ? resolveIngestionStatus() : void 0 : resolveIngestionStatus();
282
287
  if (!snapshot) {
283
- return `primitive ${version} (daemon: down)`;
288
+ return `primitive ${version} (daemon: down${ingestionSuffix(ingestionStatus)})`;
284
289
  }
285
290
  if (snapshot.healthy === false) {
286
291
  if (snapshot.needsReauth) {
287
- return `primitive ${version} (daemon: paused \xB7 run \`prim auth login\`)`;
292
+ return `primitive ${version} (daemon: paused \xB7 run \`prim auth login\`${ingestionSuffix(ingestionStatus)})`;
288
293
  }
289
294
  if (snapshot.ingestion?.healthy === false) {
290
295
  const pending = snapshot.ingestion.pendingCount;
291
296
  const qualifier = snapshot.ingestion.pendingSampled ? "at least " : "";
292
- return `primitive ${version} (daemon: degraded \xB7 delivery: stalled${typeof pending === "number" ? ` \xB7 ${qualifier}${String(pending)} pending` : ""})`;
297
+ return `primitive ${version} (daemon: degraded \xB7 delivery: stalled${typeof pending === "number" ? ` \xB7 ${qualifier}${String(pending)} pending` : ""}${ingestionSuffix(ingestionStatus)})`;
293
298
  }
294
299
  if (snapshot.heartbeat?.healthy === false) {
295
- return `primitive ${version} (daemon: degraded \xB7 presence: unavailable)`;
300
+ return `primitive ${version} (daemon: degraded \xB7 presence: unavailable${ingestionSuffix(ingestionStatus)})`;
296
301
  }
297
- return `primitive ${version} (daemon: starting)`;
302
+ return `primitive ${version} (daemon: starting${ingestionSuffix(ingestionStatus)})`;
298
303
  }
299
- const ingestionStatus = resolveIngestionStatus();
300
304
  if (snapshot.envMismatch) {
301
305
  return `primitive ${version} (daemon: live, Decision ingestion ${ingestionStatus} \xB7 presence: other env)`;
302
306
  }
@@ -305,7 +309,7 @@ function formatStatusline(version, snapshot, resolveIngestionStatus) {
305
309
  }
306
310
  let team;
307
311
  if (snapshot.onlineTeammates !== void 0) {
308
- team = `team: ${formatTeammatesWithArea(snapshot.onlineTeammates, STATUSLINE_NAME_CAP)}`;
312
+ team = `team: ${formatTeammatesWithArea(snapshot.onlineTeammates, STATUSLINE_NAME_CAP, options.plainLinks === true)}`;
309
313
  } else if (snapshot.onlineNames !== void 0) {
310
314
  team = `team: ${formatTeammates(snapshot.onlineNames, STATUSLINE_NAME_CAP)}`;
311
315
  } else if (typeof snapshot.onlineCount === "number") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primitive.ai/prim",
3
- "version": "0.1.0-alpha.66",
3
+ "version": "0.1.0-alpha.68",
4
4
  "description": "CLI for Primitive's decision graph — passive decision capture, conflict gate, and team presence",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,123 +0,0 @@
1
- // src/lib/bin-path.ts
2
- import { existsSync, readFileSync } from "fs";
3
- import { dirname, isAbsolute, join } from "path";
4
- import { fileURLToPath } from "url";
5
- var PKG_NAME = "@primitive.ai/prim";
6
- var ROOT_WALK_LIMIT = 6;
7
- var NPX_FALLBACK = `npx --yes -p ${PKG_NAME}@latest`;
8
- var resolvedRoot;
9
- function locateRoot() {
10
- if (resolvedRoot !== void 0) {
11
- return resolvedRoot;
12
- }
13
- let dir = dirname(fileURLToPath(import.meta.url));
14
- for (let depth = 0; depth < ROOT_WALK_LIMIT; depth++) {
15
- const manifestPath = join(dir, "package.json");
16
- if (existsSync(manifestPath)) {
17
- try {
18
- const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
19
- if (manifest.name === PKG_NAME && manifest.bin) {
20
- resolvedRoot = { dir, version: manifest.version, bin: manifest.bin };
21
- return resolvedRoot;
22
- }
23
- } catch {
24
- }
25
- }
26
- const parent = dirname(dir);
27
- if (parent === dir) {
28
- break;
29
- }
30
- dir = parent;
31
- }
32
- resolvedRoot = null;
33
- return resolvedRoot;
34
- }
35
- function binFile(bin) {
36
- const root = locateRoot();
37
- const rel = root?.bin[bin];
38
- if (!root || !rel) {
39
- return null;
40
- }
41
- return isAbsolute(rel) ? rel : join(root.dir, rel);
42
- }
43
- function packageVersion() {
44
- return locateRoot()?.version ?? null;
45
- }
46
- function shellQuote(value) {
47
- return `'${value.replaceAll("'", `'"'"'`)}'`;
48
- }
49
- function pinnedHookCommand(bin, args = "") {
50
- const version = packageVersion();
51
- if (!version) throw new Error("cannot determine Primitive package version");
52
- const suffix = args ? ` ${args}` : "";
53
- const fallback = `npx --yes -p ${PKG_NAME}@${version} ${bin}${suffix}`;
54
- const file = binFile(bin);
55
- if (!file) return fallback;
56
- return `if [ -x ${shellQuote(process.execPath)} ] && [ -f ${shellQuote(file)} ]; then ${shellQuote(process.execPath)} ${shellQuote(file)}${suffix}; else ${fallback}; fi`;
57
- }
58
- function detachedHookShimCommand(bin, args = "") {
59
- return `payload=$(cat); { trap '' HUP; export npm_config_fetch_retries=2 npm_config_fetch_retry_mintimeout=10000 npm_config_fetch_retry_maxtimeout=10000 npm_config_fetch_timeout=60000; printf '%s' "$payload" | { ${pinnedHookCommand(bin, args)}; }; } </dev/null >/dev/null 2>&1 &`;
60
- }
61
- function commandMatchesBin(command, bin) {
62
- if (!command) {
63
- return false;
64
- }
65
- const c = command.trim();
66
- if (c === bin || c.startsWith(`${bin} `)) {
67
- return true;
68
- }
69
- const exactBin = new RegExp(`(?:^|\\s)${bin.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?:\\s|;|$)`);
70
- return c.includes(`command -v ${bin} `) || c.includes(`-p ${PKG_NAME}@`) && exactBin.test(c);
71
- }
72
-
73
- // src/lib/bin-cache.ts
74
- import { chmodSync, mkdirSync, renameSync, writeFileSync } from "fs";
75
- import { homedir } from "os";
76
- import { join as join2 } from "path";
77
- var CACHED_BINS = [
78
- "prim",
79
- "prim-hook",
80
- "prim-pre-tool-use",
81
- "prim-post-tool-use",
82
- "prim-post-commit",
83
- "prim-post-rewrite"
84
- ];
85
- function binCacheDir() {
86
- const base = process.env.XDG_CACHE_HOME || join2(homedir(), ".cache");
87
- return join2(base, "prim", "bin");
88
- }
89
- function writeAtomic(path, content) {
90
- const tmp = `${path}.${process.pid}.tmp`;
91
- writeFileSync(tmp, content, { mode: 384 });
92
- renameSync(tmp, path);
93
- }
94
- function warmBinCache() {
95
- try {
96
- if (process.env.PRIM_BIN_CACHE_HIT) {
97
- return;
98
- }
99
- if (process.env.PRIM_BIN_CACHE === "0") {
100
- return;
101
- }
102
- const dir = binCacheDir();
103
- mkdirSync(dir, { recursive: true, mode: 448 });
104
- chmodSync(dir, 448);
105
- writeAtomic(join2(dir, "node"), process.execPath);
106
- for (const bin of CACHED_BINS) {
107
- const file = binFile(bin);
108
- if (file) {
109
- writeAtomic(join2(dir, bin), file);
110
- }
111
- }
112
- } catch {
113
- }
114
- }
115
-
116
- export {
117
- binFile,
118
- packageVersion,
119
- pinnedHookCommand,
120
- detachedHookShimCommand,
121
- commandMatchesBin,
122
- warmBinCache
123
- };
@@ -1,110 +0,0 @@
1
- // src/lib/ansi.ts
2
- var ANSI_CODES = {
3
- yellow: "\x1B[33m",
4
- magenta: "\x1B[35m",
5
- blue: "\x1B[34m",
6
- cyan: "\x1B[36m",
7
- green: "\x1B[32m",
8
- red: "\x1B[31m",
9
- // 256-color approximation of the orange trigger marker (xterm 208).
10
- orange: "\x1B[38;5;208m",
11
- gray: "\x1B[90m"
12
- };
13
- var ANSI_RESET = "\x1B[0m";
14
- var ANSI_DIM = "\x1B[2m";
15
- var ANSI_BOLD = "\x1B[1m";
16
- function supportsColor() {
17
- if (process.env.NO_COLOR !== void 0 && process.env.NO_COLOR !== "") {
18
- return false;
19
- }
20
- return process.stderr.isTTY === true;
21
- }
22
- function color(text, c) {
23
- if (!supportsColor()) {
24
- return text;
25
- }
26
- return `${ANSI_CODES[c]}${text}${ANSI_RESET}`;
27
- }
28
- function dim(text) {
29
- if (!supportsColor()) {
30
- return text;
31
- }
32
- return `${ANSI_DIM}${text}${ANSI_RESET}`;
33
- }
34
- function bold(text) {
35
- if (!supportsColor()) {
36
- return text;
37
- }
38
- return `${ANSI_BOLD}${text}${ANSI_RESET}`;
39
- }
40
- var AREA_COLORS = {
41
- auth: "yellow",
42
- data: "magenta",
43
- mobile: "blue",
44
- infra: "cyan",
45
- ui: "green",
46
- billing: "orange",
47
- api: "blue",
48
- docs: "gray",
49
- testing: "gray"
50
- };
51
- function colorForArea(area) {
52
- if (!area) {
53
- return "gray";
54
- }
55
- return AREA_COLORS[area] ?? "gray";
56
- }
57
- function stripControlChars(text) {
58
- let out = "";
59
- for (const ch of text) {
60
- const code = ch.codePointAt(0) ?? 0;
61
- if (code > 31 && !(code >= 127 && code <= 159)) {
62
- out += ch;
63
- }
64
- }
65
- return out;
66
- }
67
- var MAX_HEALTH_ERROR_LENGTH = 240;
68
- function boundedHealthError(value) {
69
- if (!value) return void 0;
70
- const clean = stripControlChars(value).replace(/\s+/g, " ").trim();
71
- if (!clean) return void 0;
72
- return clean.length <= MAX_HEALTH_ERROR_LENGTH ? clean : `${clean.slice(0, MAX_HEALTH_ERROR_LENGTH - 1)}\u2026`;
73
- }
74
- function stripAnsi(text) {
75
- return text.replace(/\u001b\[[0-9;]*m/g, "");
76
- }
77
-
78
- // src/ingest-response.ts
79
- var IngestAcknowledgementError = class extends Error {
80
- constructor(message) {
81
- super(message);
82
- this.name = "IngestAcknowledgementError";
83
- }
84
- };
85
- function requireDurableIngestAcknowledgement(value, expected) {
86
- if (typeof value !== "object" || value === null) {
87
- throw new IngestAcknowledgementError("ingest response was not an object");
88
- }
89
- const response = value;
90
- if (response.disposition !== "persisted") {
91
- throw new IngestAcknowledgementError("ingest response did not confirm persistence");
92
- }
93
- if (response.acknowledged !== expected) {
94
- throw new IngestAcknowledgementError(
95
- `ingest acknowledged ${String(response.acknowledged)} of ${String(expected)} moves`
96
- );
97
- }
98
- return value;
99
- }
100
-
101
- export {
102
- color,
103
- dim,
104
- bold,
105
- colorForArea,
106
- stripControlChars,
107
- boundedHealthError,
108
- stripAnsi,
109
- requireDurableIngestAcknowledgement
110
- };