@primitive.ai/prim 0.1.0-alpha.8 → 0.1.0-alpha.81

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 (45) hide show
  1. package/README.md +295 -37
  2. package/SKILL.md +269 -0
  3. package/dist/chunk-3EEFL6NJ.js +529 -0
  4. package/dist/chunk-4CZTNXIS.js +505 -0
  5. package/dist/chunk-4GLVJLEQ.js +55 -0
  6. package/dist/chunk-BQUJ4AFJ.js +771 -0
  7. package/dist/chunk-CUE2LKLR.js +155 -0
  8. package/dist/chunk-EZXEWFDG.js +210 -0
  9. package/dist/chunk-FI3LIRCB.js +262 -0
  10. package/dist/chunk-HWSS4BV5.js +1400 -0
  11. package/dist/chunk-LEMX3IOG.js +79 -0
  12. package/dist/chunk-LMRYZL3D.js +209 -0
  13. package/dist/chunk-OUXH3UEP.js +247 -0
  14. package/dist/chunk-PMRDE2DA.js +310 -0
  15. package/dist/chunk-RO3F6JYV.js +126 -0
  16. package/dist/chunk-TJTVHDJ5.js +321 -0
  17. package/dist/chunk-WB7AUZ4C.js +52 -0
  18. package/dist/chunk-XGADQPCI.js +26 -0
  19. package/dist/chunk-YWO7O6QG.js +327 -0
  20. package/dist/chunk-Z7YPFWAZ.js +917 -0
  21. package/dist/chunk-ZOSNEO5N.js +77 -0
  22. package/dist/daemon/server.js +15329 -0
  23. package/dist/hook-runtime/daemon/server.js +15329 -0
  24. package/dist/hook-runtime/hooks/post-commit.js +1128 -0
  25. package/dist/hook-runtime/hooks/post-rewrite.js +1148 -0
  26. package/dist/hook-runtime/hooks/post-tool-use.js +7586 -0
  27. package/dist/hook-runtime/hooks/pre-commit.js +1314 -0
  28. package/dist/hook-runtime/hooks/pre-tool-use.js +7099 -0
  29. package/dist/hook-runtime/hooks/prim-hook.js +7691 -0
  30. package/dist/hook-runtime/hooks/session-end.js +495 -0
  31. package/dist/hook-runtime/hooks/session-start.js +11313 -0
  32. package/dist/hook-runtime/index.js +44696 -0
  33. package/dist/hook-runtime/statusline-main.js +765 -0
  34. package/dist/hooks/post-commit.js +179 -0
  35. package/dist/hooks/post-rewrite.js +197 -0
  36. package/dist/hooks/post-tool-use.js +250 -0
  37. package/dist/hooks/pre-commit.js +21 -74
  38. package/dist/hooks/pre-tool-use.js +348 -0
  39. package/dist/hooks/prim-hook.js +195 -0
  40. package/dist/hooks/session-end.js +70 -0
  41. package/dist/hooks/session-start.js +299 -0
  42. package/dist/index.js +20981 -519
  43. package/dist/statusline-main.js +765 -0
  44. package/package.json +35 -13
  45. package/dist/chunk-3APLWTLB.js +0 -165
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@primitive.ai/prim",
3
- "version": "0.1.0-alpha.8",
4
- "description": "CLI for managing Primitive specs, contexts, and git hooks",
3
+ "version": "0.1.0-alpha.81",
4
+ "description": "CLI for Primitive's decision graph — passive decision capture, conflict gate, and team presence",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -19,8 +19,8 @@
19
19
  "primitive",
20
20
  "prim",
21
21
  "cli",
22
- "specs",
23
- "contexts",
22
+ "decisions",
23
+ "decision-graph",
24
24
  "pre-commit"
25
25
  ],
26
26
  "engines": {
@@ -29,34 +29,56 @@
29
29
  "packageManager": "pnpm@9.15.9",
30
30
  "bin": {
31
31
  "prim": "dist/index.js",
32
- "prim-pre-commit": "dist/hooks/pre-commit.js"
32
+ "prim-pre-commit": "dist/hooks/pre-commit.js",
33
+ "prim-post-commit": "dist/hooks/post-commit.js",
34
+ "prim-post-rewrite": "dist/hooks/post-rewrite.js",
35
+ "prim-hook": "dist/hooks/prim-hook.js",
36
+ "prim-pre-tool-use": "dist/hooks/pre-tool-use.js",
37
+ "prim-post-tool-use": "dist/hooks/post-tool-use.js",
38
+ "prim-session-start": "dist/hooks/session-start.js",
39
+ "prim-session-end": "dist/hooks/session-end.js",
40
+ "prim-daemon-server": "dist/daemon/server.js",
41
+ "prim-statusline": "dist/statusline-main.js"
33
42
  },
34
43
  "main": "./dist/index.js",
35
44
  "files": [
36
45
  "dist",
37
46
  "LICENSE",
38
- "README.md"
47
+ "README.md",
48
+ "SKILL.md"
39
49
  ],
40
50
  "scripts": {
41
- "build": "tsup src/index.ts src/hooks/pre-commit.ts --format esm --clean",
42
- "postbuild": "chmod +x ./dist/index.js ./dist/hooks/pre-commit.js",
43
- "dev": "tsup src/index.ts src/hooks/pre-commit.ts --format esm --watch --clean",
51
+ "build": "tsup src/index.ts src/hooks/pre-commit.ts src/hooks/post-commit.ts src/hooks/post-rewrite.ts src/hooks/prim-hook.ts src/hooks/pre-tool-use.ts src/hooks/post-tool-use.ts src/hooks/session-start.ts src/hooks/session-end.ts --format esm --clean && tsup src/statusline-main.ts src/daemon/server.ts --format esm --splitting false && tsup --config tsup.hook-runtime.config.ts",
52
+ "contracts:generate": "node scripts/generate-cli-contract.mjs --write",
53
+ "contracts:check": "node scripts/generate-cli-contract.mjs --check",
54
+ "contracts:provenance": "node scripts/update-cli-contract.mjs --check",
55
+ "contracts:update": "node scripts/update-cli-contract.mjs",
56
+ "postbuild": "chmod +x ./dist/index.js ./dist/statusline-main.js ./dist/hooks/pre-commit.js ./dist/hooks/post-commit.js ./dist/hooks/post-rewrite.js ./dist/hooks/prim-hook.js ./dist/hooks/pre-tool-use.js ./dist/hooks/post-tool-use.js ./dist/hooks/session-start.js ./dist/hooks/session-end.js ./dist/daemon/server.js",
57
+ "dev": "tsup src/index.ts src/statusline-main.ts src/hooks/pre-commit.ts src/hooks/post-commit.ts src/hooks/post-rewrite.ts src/hooks/prim-hook.ts src/hooks/pre-tool-use.ts src/hooks/post-tool-use.ts src/hooks/session-start.ts src/hooks/session-end.ts src/daemon/server.ts --format esm --watch --clean --splitting false",
44
58
  "clean": "rm -rf dist coverage",
45
- "lint": "biome check src/",
46
- "format": "biome check --fix src/",
47
- "format:check": "biome check src/",
59
+ "lint": "biome check src/ scripts/",
60
+ "format": "biome check --fix src/ scripts/",
61
+ "format:check": "biome check src/ scripts/",
48
62
  "typecheck": "tsc --noEmit",
49
63
  "test": "vitest run",
50
64
  "test:watch": "vitest",
51
65
  "test:coverage": "vitest run --coverage"
52
66
  },
53
67
  "dependencies": {
54
- "commander": "^12.1.0"
68
+ "commander": "^12.1.0",
69
+ "diff": "^5.2.0",
70
+ "unbash": "4.0.3",
71
+ "update-notifier": "^7.3.1",
72
+ "yaml": "^2.9.0"
55
73
  },
56
74
  "devDependencies": {
57
75
  "@biomejs/biome": "^1.9.0",
76
+ "@types/diff": "^5.2.0",
58
77
  "@types/node": "^25.5.0",
78
+ "@types/update-notifier": "^6.0.8",
59
79
  "@vitest/coverage-v8": "^3.1.0",
80
+ "ajv": "8.20.0",
81
+ "json-schema-to-typescript": "15.0.4",
60
82
  "tsup": "^8.0.0",
61
83
  "typescript": "^5.5.0",
62
84
  "vitest": "^3.1.0"
@@ -1,165 +0,0 @@
1
- // src/client.ts
2
- import { existsSync, readFileSync, writeFileSync } from "fs";
3
- import { homedir } from "os";
4
- import { join, resolve } from "path";
5
- function loadEnvFile() {
6
- const envVars = {};
7
- const candidates = [".env.local", ".env"];
8
- for (const file of candidates) {
9
- const filePath = resolve(process.cwd(), file);
10
- if (existsSync(filePath)) {
11
- const content = readFileSync(filePath, "utf-8");
12
- for (const line of content.split("\n")) {
13
- const trimmed = line.trim();
14
- if (!trimmed || trimmed.startsWith("#")) continue;
15
- const eqIdx = trimmed.indexOf("=");
16
- if (eqIdx === -1) continue;
17
- const key = trimmed.slice(0, eqIdx).trim();
18
- const value = trimmed.slice(eqIdx + 1).trim();
19
- envVars[key] = value;
20
- }
21
- }
22
- }
23
- return envVars;
24
- }
25
- var TOKEN_FILE_PATH = join(homedir(), ".config", "prim", "token");
26
- var REFRESH_TOKEN_PATH = TOKEN_FILE_PATH.replace("/token", "/refresh_token");
27
- var TOKEN_EXPIRES_PATH = join(homedir(), ".config", "prim", "token_expires_at");
28
- var REFRESH_THRESHOLD_MS = 6e4;
29
- function isTokenExpiringSoon() {
30
- if (!existsSync(TOKEN_EXPIRES_PATH)) return false;
31
- const expiresAt = Number(readFileSync(TOKEN_EXPIRES_PATH, "utf-8").trim());
32
- return !Number.isNaN(expiresAt) && Date.now() >= expiresAt - REFRESH_THRESHOLD_MS;
33
- }
34
- function getJwtExpiry(token) {
35
- const parts = token.split(".");
36
- if (parts.length !== 3) return void 0;
37
- try {
38
- const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
39
- return payload.exp ? payload.exp * 1e3 : void 0;
40
- } catch {
41
- return void 0;
42
- }
43
- }
44
- function saveTokenExpiry(token, expiresIn) {
45
- const expiresAt = expiresIn ? Date.now() + expiresIn * 1e3 : getJwtExpiry(token);
46
- if (expiresAt) {
47
- writeFileSync(TOKEN_EXPIRES_PATH, String(expiresAt), { mode: 384 });
48
- }
49
- }
50
- function getTokenExpiresAt() {
51
- if (!existsSync(TOKEN_EXPIRES_PATH)) return void 0;
52
- const val = Number(readFileSync(TOKEN_EXPIRES_PATH, "utf-8").trim());
53
- return Number.isNaN(val) ? void 0 : val;
54
- }
55
- function getAuthToken() {
56
- if (process.env.PRIM_TOKEN) {
57
- return process.env.PRIM_TOKEN;
58
- }
59
- if (existsSync(TOKEN_FILE_PATH)) {
60
- const token = readFileSync(TOKEN_FILE_PATH, "utf-8").trim();
61
- if (token) {
62
- return token;
63
- }
64
- }
65
- const envVars = loadEnvFile();
66
- if (envVars.PRIM_TOKEN) {
67
- return envVars.PRIM_TOKEN;
68
- }
69
- return void 0;
70
- }
71
- var API_URL = "https://api.getprimitive.ai";
72
- function getSiteUrl() {
73
- return API_URL;
74
- }
75
- async function refreshToken() {
76
- if (!existsSync(REFRESH_TOKEN_PATH)) {
77
- return void 0;
78
- }
79
- const refreshTokenValue = readFileSync(REFRESH_TOKEN_PATH, "utf-8").trim();
80
- if (!refreshTokenValue) {
81
- return void 0;
82
- }
83
- const siteUrl = getSiteUrl();
84
- const response = await fetch(`${siteUrl}/mcp/broker/refresh`, {
85
- method: "POST",
86
- headers: { "Content-Type": "application/json" },
87
- body: JSON.stringify({ refresh_token: refreshTokenValue })
88
- });
89
- if (!response.ok) {
90
- return void 0;
91
- }
92
- const data = await response.json();
93
- if (!data.access_token) {
94
- return void 0;
95
- }
96
- writeFileSync(TOKEN_FILE_PATH, data.access_token, { mode: 384 });
97
- if (data.refresh_token) {
98
- writeFileSync(REFRESH_TOKEN_PATH, data.refresh_token, { mode: 384 });
99
- }
100
- saveTokenExpiry(data.access_token, data.expires_in);
101
- return data.access_token;
102
- }
103
- var _cachedToken;
104
- async function request(method, path, body, options) {
105
- const siteUrl = getSiteUrl();
106
- const url = `${siteUrl}${path}`;
107
- if (!_cachedToken) {
108
- _cachedToken = getAuthToken();
109
- }
110
- if (_cachedToken && isTokenExpiringSoon()) {
111
- const newToken = await refreshToken();
112
- if (newToken) {
113
- _cachedToken = newToken;
114
- }
115
- }
116
- const doFetch = async (token) => {
117
- const headers = {
118
- "Content-Type": "application/json"
119
- };
120
- if (token) {
121
- headers.Authorization = `Bearer ${token}`;
122
- }
123
- return fetch(url, {
124
- method,
125
- headers,
126
- body: body !== void 0 ? JSON.stringify(body) : void 0,
127
- signal: options?.signal
128
- });
129
- };
130
- let res = await doFetch(_cachedToken);
131
- if (res.status === 401) {
132
- const newToken = await refreshToken();
133
- if (newToken) {
134
- _cachedToken = newToken;
135
- res = await doFetch(newToken);
136
- }
137
- }
138
- if (!res.ok) {
139
- if (res.status === 401) {
140
- throw new Error("Authentication expired. Run `prim auth login` to re-authenticate.");
141
- }
142
- const errorBody = await res.json().catch(() => null);
143
- throw new Error(errorBody?.error ?? `HTTP ${res.status}`);
144
- }
145
- return res.json();
146
- }
147
- function getClient() {
148
- return {
149
- get: (path, options) => request("GET", path, void 0, options),
150
- post: (path, body, options) => request("POST", path, body, options),
151
- patch: (path, body, options) => request("PATCH", path, body, options),
152
- delete: (path, options) => request("DELETE", path, void 0, options)
153
- };
154
- }
155
-
156
- export {
157
- TOKEN_FILE_PATH,
158
- REFRESH_TOKEN_PATH,
159
- TOKEN_EXPIRES_PATH,
160
- saveTokenExpiry,
161
- getTokenExpiresAt,
162
- getAuthToken,
163
- getSiteUrl,
164
- getClient
165
- };