@primitive.ai/prim 0.1.0-alpha.90 → 0.1.0-alpha.91
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.
- package/README.md +20 -12
- package/SKILL.md +6 -6
- package/dist/{chunk-LMRYZL3D.js → chunk-5AFRMOPX.js} +1 -1
- package/dist/{chunk-RO3F6JYV.js → chunk-5GYQ4J3D.js} +2 -2
- package/dist/{chunk-3EEFL6NJ.js → chunk-67VNLLBN.js} +261 -1
- package/dist/{chunk-LEMX3IOG.js → chunk-BTNNEH2W.js} +1 -1
- package/dist/chunk-EWZMDD44.js +1474 -0
- package/dist/{chunk-YWO7O6QG.js → chunk-FBAYCS3X.js} +2 -2
- package/dist/{chunk-R26A7TWY.js → chunk-FKXFUUWJ.js} +1 -1
- package/dist/{chunk-C7T7B45R.js → chunk-FOLKHXLJ.js} +150 -21
- package/dist/chunk-H4UNYFUC.js +196 -0
- package/dist/chunk-HU4PW6I6.js +264 -0
- package/dist/{chunk-CUE2LKLR.js → chunk-KFXF2V5G.js} +1 -1
- package/dist/{chunk-6IWNH776.js → chunk-LFFLHSQO.js} +4 -3
- package/dist/{chunk-MAZWKJGL.js → chunk-M6RIJVRE.js} +42 -232
- package/dist/{chunk-2JRX7ZR4.js → chunk-NAHHFSLH.js} +16 -5
- package/dist/{chunk-FI3LIRCB.js → chunk-OAAP2MY6.js} +2 -2
- package/dist/{chunk-Z7YPFWAZ.js → chunk-PCVGBE5B.js} +10 -268
- package/dist/{chunk-UZPBB7V4.js → chunk-VW3FDYRT.js} +60 -48
- package/dist/chunk-WX52U7Z2.js +112 -0
- package/dist/{chunk-PPQYQEIR.js → chunk-ZB4F75SZ.js} +28 -0
- package/dist/daemon/server.js +20 -20
- package/dist/hook-runtime/daemon/server.js +20 -20
- package/dist/hook-runtime/hooks/post-commit.js +20 -20
- package/dist/hook-runtime/hooks/post-rewrite.js +20 -20
- package/dist/hook-runtime/hooks/post-tool-use.js +651 -132
- package/dist/hook-runtime/hooks/pre-tool-use.js +644 -96
- package/dist/hook-runtime/hooks/prim-hook.js +612 -96
- package/dist/hook-runtime/hooks/session-end.js +610 -27
- package/dist/hook-runtime/hooks/session-start.js +1132 -533
- package/dist/hook-runtime/index.js +735 -264
- package/dist/hook-runtime/statusline-main.js +48 -4
- package/dist/hooks/post-commit.js +11 -9
- package/dist/hooks/post-rewrite.js +11 -9
- package/dist/hooks/post-tool-use.js +73 -48
- package/dist/hooks/pre-commit.js +4 -4
- package/dist/hooks/pre-tool-use.js +46 -44
- package/dist/hooks/prim-hook.js +47 -25
- package/dist/hooks/session-end.js +15 -26
- package/dist/hooks/session-start.js +59 -32
- package/dist/index.js +558 -1436
- package/dist/statusline-main.js +48 -4
- package/package.json +1 -1
- package/dist/chunk-PMRDE2DA.js +0 -310
- package/dist/chunk-WB7AUZ4C.js +0 -52
|
@@ -4963,7 +4963,7 @@ var require_rc = __commonJS({
|
|
|
4963
4963
|
"node_modules/.pnpm/rc@1.2.8/node_modules/rc/index.js"(exports, module) {
|
|
4964
4964
|
"use strict";
|
|
4965
4965
|
var cc = require_utils();
|
|
4966
|
-
var
|
|
4966
|
+
var join28 = __require("path").join;
|
|
4967
4967
|
var deepExtend = require_deep_extend();
|
|
4968
4968
|
var etc = "/etc";
|
|
4969
4969
|
var win = process.platform === "win32";
|
|
@@ -4988,15 +4988,15 @@ var require_rc = __commonJS({
|
|
|
4988
4988
|
}
|
|
4989
4989
|
if (!win)
|
|
4990
4990
|
[
|
|
4991
|
-
|
|
4992
|
-
|
|
4991
|
+
join28(etc, name, "config"),
|
|
4992
|
+
join28(etc, name + "rc")
|
|
4993
4993
|
].forEach(addConfigFile);
|
|
4994
4994
|
if (home)
|
|
4995
4995
|
[
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
4996
|
+
join28(home, ".config", name, "config"),
|
|
4997
|
+
join28(home, ".config", name),
|
|
4998
|
+
join28(home, "." + name, "config"),
|
|
4999
|
+
join28(home, "." + name + "rc")
|
|
5000
5000
|
].forEach(addConfigFile);
|
|
5001
5001
|
addConfigFile(cc.find("." + name + "rc"));
|
|
5002
5002
|
if (env4.config) addConfigFile(env4.config);
|
|
@@ -8896,7 +8896,7 @@ var require_ucs2length = __commonJS({
|
|
|
8896
8896
|
});
|
|
8897
8897
|
|
|
8898
8898
|
// src/index.ts
|
|
8899
|
-
import { readFileSync as
|
|
8899
|
+
import { readFileSync as readFileSync22 } from "fs";
|
|
8900
8900
|
import { dirname as dirname18, resolve as resolve10 } from "path";
|
|
8901
8901
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
8902
8902
|
|
|
@@ -13041,7 +13041,7 @@ var PRIM_REPO_SYNC_REPOSITORY_KEY = "prim.repoSyncRepository";
|
|
|
13041
13041
|
var PRIM_REPO_BINDING_STATE_KEY = "prim.repoBindingState";
|
|
13042
13042
|
var GIT_TIMEOUT_MS2 = 1e3;
|
|
13043
13043
|
var REPO_SYNC_ID_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;
|
|
13044
|
-
var PROJECT_INSTALL_FILES = [".claude/settings.json", ".codex/hooks.json"];
|
|
13044
|
+
var PROJECT_INSTALL_FILES = [".claude/settings.json", ".codex/hooks.json", ".cursor/hooks.json"];
|
|
13045
13045
|
var PRIM_HOOK_BINS = ["prim-hook", "prim-pre-tool-use", "prim-post-tool-use"];
|
|
13046
13046
|
function repoActiveFlag(cwd) {
|
|
13047
13047
|
try {
|
|
@@ -14850,7 +14850,7 @@ function validate23(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
14850
14850
|
}
|
|
14851
14851
|
validate23.evaluated = { "props": true, "dynamicProps": false, "dynamicItems": false };
|
|
14852
14852
|
var isDecisionCollectScopeResponse = validate24;
|
|
14853
|
-
var schema39 = { "type": "object", "properties": { "policy": { "anyOf": [{ "type": "object", "properties": { "repositories": { "type": "array", "items": { "type": "string" } }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } }, "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } }, "updatedAt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": ["updatedAt"], "additionalProperties": {} }, { "type": "null" }] }, "collectScopeVersion": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "callerIncluded": { "type": "boolean" } }, "required": ["policy", "collectScopeVersion", "callerIncluded"], "additionalProperties": {} };
|
|
14853
|
+
var schema39 = { "type": "object", "properties": { "policy": { "anyOf": [{ "type": "object", "properties": { "repositories": { "type": "array", "items": { "type": "string" } }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } }, "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } }, "updatedAt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": ["updatedAt"], "additionalProperties": {} }, { "type": "null" }] }, "collectScopeVersion": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "callerIncluded": { "type": "boolean" } }, "required": ["policy", "collectScopeVersion", "callerIncluded"], "additionalProperties": {} };
|
|
14854
14854
|
function validate24(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
|
|
14855
14855
|
;
|
|
14856
14856
|
let vErrors = null;
|
|
@@ -15401,7 +15401,7 @@ function validate24(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
15401
15401
|
}
|
|
15402
15402
|
errors++;
|
|
15403
15403
|
}
|
|
15404
|
-
if (!(data18 === "claude_code" || data18 === "codex" || data18 === "hermes")) {
|
|
15404
|
+
if (!(data18 === "claude_code" || data18 === "codex" || data18 === "cursor" || data18 === "hermes")) {
|
|
15405
15405
|
const err34 = { instancePath: instancePath + "/policy/users/" + i4 + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/DecisionCollectScopeResponse/properties/policy/anyOf/0/properties/users/items/oneOf/2/properties/agent/enum", keyword: "enum", params: { allowedValues: schema39.properties.policy.anyOf[0].properties.users.items.oneOf[2].properties.agent.enum }, message: "must be equal to one of the allowed values" };
|
|
15406
15406
|
if (vErrors === null) {
|
|
15407
15407
|
vErrors = [err34];
|
|
@@ -16170,7 +16170,7 @@ function validate26(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
16170
16170
|
return errors === 0;
|
|
16171
16171
|
}
|
|
16172
16172
|
validate26.evaluated = { "dynamicProps": true, "dynamicItems": false };
|
|
16173
|
-
var schema45 = { "type": "object", "properties": { "intent": { "type": "string", "minLength": 1, "maxLength": 500 }, "attribution": { "type": "string", "enum": ["user", "agent", "unknown"] }, "kind": { "type": "string", "enum": ["change", "exploration", "task_execution", "unclear"] }, "rationale": { "type": "string" }, "area": { "type": "string" }, "decided": { "type": "array", "items": { "type": "string" } }, "alternatives": { "type": "array", "items": { "type": "string" } }, "confidence": { "type": "string", "enum": ["high", "medium", "low"] }, "reversibility": { "type": "string", "enum": ["high", "low"] }, "files": { "type": "array", "items": { "type": "string" } }, "protocolVersion": { "type": "number", "const": 3 }, "repoSyncId": { "type": "string" }, "scope": { "default": {}, "type": "object", "properties": { "location": { "default": {}, "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "additionalProperties": {} }, "time": { "default": {}, "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "additionalProperties": {} }, "stageOverride": { "type": "string", "enum": ["candidate", "draft", "adopted"] } }, "required": ["intent"], "additionalProperties": {}, "x-primitive-runtime-refinements": ["degrade_invalid_rollout_fields", "degrade_invalid_location_scope", "degrade_invalid_time_scope"] };
|
|
16173
|
+
var schema45 = { "type": "object", "properties": { "intent": { "type": "string", "minLength": 1, "maxLength": 500 }, "attribution": { "type": "string", "enum": ["user", "agent", "unknown"] }, "kind": { "type": "string", "enum": ["change", "exploration", "task_execution", "unclear"] }, "rationale": { "type": "string" }, "area": { "type": "string" }, "decided": { "type": "array", "items": { "type": "string" } }, "alternatives": { "type": "array", "items": { "type": "string" } }, "confidence": { "type": "string", "enum": ["high", "medium", "low"] }, "reversibility": { "type": "string", "enum": ["high", "low"] }, "files": { "type": "array", "items": { "type": "string" } }, "protocolVersion": { "type": "number", "const": 3 }, "repoSyncId": { "type": "string" }, "scope": { "default": {}, "type": "object", "properties": { "location": { "default": {}, "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "additionalProperties": {} }, "time": { "default": {}, "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "additionalProperties": {} }, "stageOverride": { "type": "string", "enum": ["candidate", "draft", "adopted"] } }, "required": ["intent"], "additionalProperties": {}, "x-primitive-runtime-refinements": ["degrade_invalid_rollout_fields", "degrade_invalid_location_scope", "degrade_invalid_time_scope"] };
|
|
16174
16174
|
function validate27(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
|
|
16175
16175
|
;
|
|
16176
16176
|
let vErrors = null;
|
|
@@ -16874,7 +16874,7 @@ function validate27(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
16874
16874
|
}
|
|
16875
16875
|
errors++;
|
|
16876
16876
|
}
|
|
16877
|
-
if (!(data34 === "claude_code" || data34 === "codex" || data34 === "hermes")) {
|
|
16877
|
+
if (!(data34 === "claude_code" || data34 === "codex" || data34 === "cursor" || data34 === "hermes")) {
|
|
16878
16878
|
const err19 = { instancePath: instancePath + "/scope/users/" + i6 + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/DecisionCreateRequest/properties/scope/properties/users/items/oneOf/2/properties/agent/enum", keyword: "enum", params: { allowedValues: schema45.properties.scope.properties.users.items.oneOf[2].properties.agent.enum }, message: "must be equal to one of the allowed values" };
|
|
16879
16879
|
if (vErrors === null) {
|
|
16880
16880
|
vErrors = [err19];
|
|
@@ -17102,7 +17102,7 @@ function validate27(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
17102
17102
|
return errors === 0;
|
|
17103
17103
|
}
|
|
17104
17104
|
validate27.evaluated = { "props": true, "dynamicProps": false, "dynamicItems": false };
|
|
17105
|
-
var schema47 = { "type": "object", "properties": { "decisionId": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "createdAt": { "type": "number" }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "scopeWarnings": { "type": "array", "items": { "type": "string" } } }, "required": ["decisionId", "shortId", "createdAt"], "additionalProperties": {} };
|
|
17105
|
+
var schema47 = { "type": "object", "properties": { "decisionId": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "createdAt": { "type": "number" }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "scopeWarnings": { "type": "array", "items": { "type": "string" } } }, "required": ["decisionId", "shortId", "createdAt"], "additionalProperties": {} };
|
|
17106
17106
|
function validate28(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
|
|
17107
17107
|
;
|
|
17108
17108
|
let vErrors = null;
|
|
@@ -17638,7 +17638,7 @@ function validate28(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
17638
17638
|
}
|
|
17639
17639
|
errors++;
|
|
17640
17640
|
}
|
|
17641
|
-
if (!(data22 === "claude_code" || data22 === "codex" || data22 === "hermes")) {
|
|
17641
|
+
if (!(data22 === "claude_code" || data22 === "codex" || data22 === "cursor" || data22 === "hermes")) {
|
|
17642
17642
|
const err19 = { instancePath: instancePath + "/scope/users/" + i3 + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/DecisionCreateResponse/properties/scope/properties/users/items/oneOf/2/properties/agent/enum", keyword: "enum", params: { allowedValues: schema47.properties.scope.properties.users.items.oneOf[2].properties.agent.enum }, message: "must be equal to one of the allowed values" };
|
|
17643
17643
|
if (vErrors === null) {
|
|
17644
17644
|
vErrors = [err19];
|
|
@@ -17870,7 +17870,7 @@ function validate28(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
17870
17870
|
return errors === 0;
|
|
17871
17871
|
}
|
|
17872
17872
|
validate28.evaluated = { "props": true, "dynamicProps": false, "dynamicItems": false };
|
|
17873
|
-
var schema49 = { "type": "object", "properties": { "decision": { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "intent": { "type": "string" }, "intentKind": { "type": "string", "enum": ["change", "exploration", "task_execution", "unclear"] }, "rationale": { "type": "string" }, "decided": { "type": "array", "items": { "type": "string" } }, "alternatives": { "type": "array", "items": { "type": "string" } }, "area": { "type": "string" }, "producerKind": { "type": "string" }, "stage": { "type": "string", "enum": ["draft", "provisional", "adopted", "superseded", "abandoned"] }, "status": { "type": "string", "enum": ["active", "superseded", "under_review"] }, "supersededBy": { "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }] }, "confidence": { "type": "string", "enum": ["high", "medium", "low"] }, "reversibility": { "type": "string", "enum": ["high", "low"] }, "confirmed": { "type": "boolean" }, "respondedAt": { "type": "number" }, "fanOut": { "type": "number" }, "classifiedAt": { "type": "number" }, "authorName": { "type": "string" } }, "required": ["id", "intent", "intentKind", "alternatives", "stage", "status", "supersededBy", "confidence", "classifiedAt", "authorName"], "additionalProperties": {} }, "files": { "type": "array", "items": { "type": "string" } }, "flags": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": ["file_edit", "supersession", "invalidation", "confirmation_request"] }, "file": { "type": "string" }, "flaggedAt": { "type": "number" }, "acknowledgedAt": { "type": "number" }, "gateVerdict": { "type": "string" }, "reason": { "type": "string" } }, "required": ["type", "flaggedAt"], "additionalProperties": {} } }, "dependsOn": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "intent": { "type": "string" }, "area": { "type": "string" }, "authorName": { "type": "string" }, "classifiedAt": { "type": "number" }, "status": { "type": "string", "enum": ["active", "superseded", "under_review"] } }, "required": ["id", "intent", "authorName", "classifiedAt", "status"], "additionalProperties": {} } }, "dependents": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "intent": { "type": "string" }, "area": { "type": "string" }, "authorName": { "type": "string" }, "classifiedAt": { "type": "number" }, "status": { "type": "string", "enum": ["active", "superseded", "under_review"] } }, "required": ["id", "intent", "authorName", "classifiedAt", "status"], "additionalProperties": {} } }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 }, "displayName": { "type": "string" } }, "required": ["kind", "userId", "displayName"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "truncated": { "type": "boolean" } }, "required": ["decision", "files", "flags", "dependsOn", "dependents", "scope", "truncated"], "additionalProperties": {} };
|
|
17873
|
+
var schema49 = { "type": "object", "properties": { "decision": { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "intent": { "type": "string" }, "intentKind": { "type": "string", "enum": ["change", "exploration", "task_execution", "unclear"] }, "rationale": { "type": "string" }, "decided": { "type": "array", "items": { "type": "string" } }, "alternatives": { "type": "array", "items": { "type": "string" } }, "area": { "type": "string" }, "producerKind": { "type": "string" }, "stage": { "type": "string", "enum": ["draft", "provisional", "adopted", "superseded", "abandoned"] }, "status": { "type": "string", "enum": ["active", "superseded", "under_review"] }, "supersededBy": { "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }] }, "confidence": { "type": "string", "enum": ["high", "medium", "low"] }, "reversibility": { "type": "string", "enum": ["high", "low"] }, "confirmed": { "type": "boolean" }, "respondedAt": { "type": "number" }, "fanOut": { "type": "number" }, "classifiedAt": { "type": "number" }, "authorName": { "type": "string" } }, "required": ["id", "intent", "intentKind", "alternatives", "stage", "status", "supersededBy", "confidence", "classifiedAt", "authorName"], "additionalProperties": {} }, "files": { "type": "array", "items": { "type": "string" } }, "flags": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": ["file_edit", "supersession", "invalidation", "confirmation_request"] }, "file": { "type": "string" }, "flaggedAt": { "type": "number" }, "acknowledgedAt": { "type": "number" }, "gateVerdict": { "type": "string" }, "reason": { "type": "string" } }, "required": ["type", "flaggedAt"], "additionalProperties": {} } }, "dependsOn": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "intent": { "type": "string" }, "area": { "type": "string" }, "authorName": { "type": "string" }, "classifiedAt": { "type": "number" }, "status": { "type": "string", "enum": ["active", "superseded", "under_review"] } }, "required": ["id", "intent", "authorName", "classifiedAt", "status"], "additionalProperties": {} } }, "dependents": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "intent": { "type": "string" }, "area": { "type": "string" }, "authorName": { "type": "string" }, "classifiedAt": { "type": "number" }, "status": { "type": "string", "enum": ["active", "superseded", "under_review"] } }, "required": ["id", "intent", "authorName", "classifiedAt", "status"], "additionalProperties": {} } }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 }, "displayName": { "type": "string" } }, "required": ["kind", "userId", "displayName"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "truncated": { "type": "boolean" } }, "required": ["decision", "files", "flags", "dependsOn", "dependents", "scope", "truncated"], "additionalProperties": {} };
|
|
17874
17874
|
function validate29(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
|
|
17875
17875
|
;
|
|
17876
17876
|
let vErrors = null;
|
|
@@ -19164,7 +19164,7 @@ function validate29(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
19164
19164
|
}
|
|
19165
19165
|
errors++;
|
|
19166
19166
|
}
|
|
19167
|
-
if (!(data70 === "claude_code" || data70 === "codex" || data70 === "hermes")) {
|
|
19167
|
+
if (!(data70 === "claude_code" || data70 === "codex" || data70 === "cursor" || data70 === "hermes")) {
|
|
19168
19168
|
const err24 = { instancePath: instancePath + "/scope/users/" + i9 + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/DecisionDetailResponse/properties/scope/properties/users/items/oneOf/2/properties/agent/enum", keyword: "enum", params: { allowedValues: schema49.properties.scope.properties.users.items.oneOf[2].properties.agent.enum }, message: "must be equal to one of the allowed values" };
|
|
19169
19169
|
if (vErrors === null) {
|
|
19170
19170
|
vErrors = [err24];
|
|
@@ -19727,7 +19727,7 @@ function validate33(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
19727
19727
|
}
|
|
19728
19728
|
validate33.evaluated = { "props": true, "dynamicProps": false, "dynamicItems": false };
|
|
19729
19729
|
var isDecisionRescopeRequest = validate34;
|
|
19730
|
-
var schema59 = { "type": "object", "properties": { "id": { "type": "string" }, "location": { "anyOf": [{ "default": {}, "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "additionalProperties": {} }, { "type": "null" }] }, "time": { "anyOf": [{ "default": {}, "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, { "type": "null" }] }, "users": { "anyOf": [{ "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } }, { "type": "null" }] } }, "required": ["id"], "additionalProperties": {} };
|
|
19730
|
+
var schema59 = { "type": "object", "properties": { "id": { "type": "string" }, "location": { "anyOf": [{ "default": {}, "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "additionalProperties": {} }, { "type": "null" }] }, "time": { "anyOf": [{ "default": {}, "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, { "type": "null" }] }, "users": { "anyOf": [{ "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } }, { "type": "null" }] } }, "required": ["id"], "additionalProperties": {} };
|
|
19731
19731
|
function validate34(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
|
|
19732
19732
|
;
|
|
19733
19733
|
let vErrors = null;
|
|
@@ -20368,7 +20368,7 @@ function validate34(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
20368
20368
|
}
|
|
20369
20369
|
errors++;
|
|
20370
20370
|
}
|
|
20371
|
-
if (!(data19 === "claude_code" || data19 === "codex" || data19 === "hermes")) {
|
|
20371
|
+
if (!(data19 === "claude_code" || data19 === "codex" || data19 === "cursor" || data19 === "hermes")) {
|
|
20372
20372
|
const err38 = { instancePath: instancePath + "/users/" + i3 + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/DecisionRescopeRequest/properties/users/anyOf/0/items/oneOf/2/properties/agent/enum", keyword: "enum", params: { allowedValues: schema59.properties.users.anyOf[0].items.oneOf[2].properties.agent.enum }, message: "must be equal to one of the allowed values" };
|
|
20373
20373
|
if (vErrors === null) {
|
|
20374
20374
|
vErrors = [err38];
|
|
@@ -20597,7 +20597,7 @@ function validate34(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
20597
20597
|
}
|
|
20598
20598
|
validate34.evaluated = { "props": true, "dynamicProps": false, "dynamicItems": false };
|
|
20599
20599
|
var isDecisionRescopeResponse = validate35;
|
|
20600
|
-
var schema61 = { "anyOf": [{ "type": "object", "properties": { "outcome": { "type": "string", "const": "no_op" }, "stage": { "type": "string", "enum": ["draft", "provisional", "adopted", "superseded", "abandoned"] }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "scopeWarnings": { "type": "array", "items": { "type": "string" } } }, "required": ["outcome", "stage", "scope"], "additionalProperties": {} }, { "type": "object", "properties": { "outcome": { "type": "string", "const": "ok" }, "decisionId": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "stage": { "type": "string", "enum": ["draft", "provisional", "adopted", "superseded", "abandoned"] }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "scopeWarnings": { "type": "array", "items": { "type": "string" } } }, "required": ["outcome", "decisionId", "stage", "scope"], "additionalProperties": {} }] };
|
|
20600
|
+
var schema61 = { "anyOf": [{ "type": "object", "properties": { "outcome": { "type": "string", "const": "no_op" }, "stage": { "type": "string", "enum": ["draft", "provisional", "adopted", "superseded", "abandoned"] }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "scopeWarnings": { "type": "array", "items": { "type": "string" } } }, "required": ["outcome", "stage", "scope"], "additionalProperties": {} }, { "type": "object", "properties": { "outcome": { "type": "string", "const": "ok" }, "decisionId": { "type": "string", "minLength": 1 }, "shortId": { "type": "string" }, "stage": { "type": "string", "enum": ["draft", "provisional", "adopted", "superseded", "abandoned"] }, "scope": { "type": "object", "properties": { "location": { "type": "object", "properties": { "repository": { "type": "boolean" }, "directories": { "type": "array", "items": { "type": "string" } }, "globs": { "type": "array", "items": { "type": "string" } }, "branches": { "type": "array", "items": { "type": "string" } } }, "required": ["repository", "directories", "globs", "branches"], "additionalProperties": {} }, "time": { "type": "object", "properties": { "effectiveFrom": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "effectiveUntil": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "additionalProperties": {} }, "users": { "type": "array", "items": { "oneOf": [{ "type": "object", "properties": { "kind": { "type": "string", "const": "user" }, "userId": { "type": "string", "minLength": 1 } }, "required": ["kind", "userId"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "role" }, "role": { "type": "string", "enum": ["owner", "admin", "member"] } }, "required": ["kind", "role"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "agent" }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] } }, "required": ["kind", "agent"], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "credential" }, "credential": { "type": "string", "enum": ["workos_jwt", "workos_api_key", "service_token"] } }, "required": ["kind", "credential"], "additionalProperties": false }] } } }, "required": ["location", "time", "users"], "additionalProperties": {} }, "scopeWarnings": { "type": "array", "items": { "type": "string" } } }, "required": ["outcome", "decisionId", "stage", "scope"], "additionalProperties": {} }] };
|
|
20601
20601
|
function validate35(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
|
|
20602
20602
|
;
|
|
20603
20603
|
let vErrors = null;
|
|
@@ -21235,7 +21235,7 @@ function validate35(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
21235
21235
|
}
|
|
21236
21236
|
errors++;
|
|
21237
21237
|
}
|
|
21238
|
-
if (!(data21 === "claude_code" || data21 === "codex" || data21 === "hermes")) {
|
|
21238
|
+
if (!(data21 === "claude_code" || data21 === "codex" || data21 === "cursor" || data21 === "hermes")) {
|
|
21239
21239
|
const err41 = { instancePath: instancePath + "/scope/users/" + i3 + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/DecisionRescopeResponse/anyOf/0/properties/scope/properties/users/items/oneOf/2/properties/agent/enum", keyword: "enum", params: { allowedValues: schema61.anyOf[0].properties.scope.properties.users.items.oneOf[2].properties.agent.enum }, message: "must be equal to one of the allowed values" };
|
|
21240
21240
|
if (vErrors === null) {
|
|
21241
21241
|
vErrors = [err41];
|
|
@@ -22159,7 +22159,7 @@ function validate35(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
22159
22159
|
}
|
|
22160
22160
|
errors++;
|
|
22161
22161
|
}
|
|
22162
|
-
if (!(data49 === "claude_code" || data49 === "codex" || data49 === "hermes")) {
|
|
22162
|
+
if (!(data49 === "claude_code" || data49 === "codex" || data49 === "cursor" || data49 === "hermes")) {
|
|
22163
22163
|
const err100 = { instancePath: instancePath + "/scope/users/" + i8 + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/DecisionRescopeResponse/anyOf/1/properties/scope/properties/users/items/oneOf/2/properties/agent/enum", keyword: "enum", params: { allowedValues: schema61.anyOf[1].properties.scope.properties.users.items.oneOf[2].properties.agent.enum }, message: "must be equal to one of the allowed values" };
|
|
22164
22164
|
if (vErrors === null) {
|
|
22165
22165
|
vErrors = [err100];
|
|
@@ -27811,7 +27811,7 @@ function validate50(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
27811
27811
|
}
|
|
27812
27812
|
validate50.evaluated = { "dynamicProps": true, "dynamicItems": false };
|
|
27813
27813
|
var isMoveIngestRequest = validate51;
|
|
27814
|
-
var schema93 = { "type": "object", "properties": { "batch": { "type": "array", "items": { "anyOf": [{ "type": "object", "properties": { "moveId": { "type": "string" }, "capturedAt": { "type": "number" }, "sessionId": { "type": "string" }, "invocationId": { "type": "string" }, "eventType": { "type": "string" }, "payload": {}, "env": {}, "capturedOrganizationId": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9_-]+$" }, "captureAuthorityKind": { "type": "string", "enum": ["workos", "service_token"] }, "decisionLifecycleProtocolVersion": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "producer": { "type": "string", "enum": ["claude_code", "codex", "hermes"] }, "toolOutcome": { "type": "string", "enum": ["succeeded", "returned", "failed", "interrupted", "prevented", "unknown"] }, "envelopeVersion": { "type": "number", "const": 4 } }, "required": ["moveId", "capturedAt", "sessionId", "eventType", "capturedOrganizationId", "captureAuthorityKind", "decisionLifecycleProtocolVersion", "envelopeVersion"], "additionalProperties": {} }, { "type": "object", "properties": { "moveId": { "type": "string" }, "capturedAt": { "type": "number" }, "sessionId": { "type": "string" }, "invocationId": { "type": "string" }, "eventType": { "type": "string" }, "payload": {}, "env": {}, "capturedOrganizationId": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9_-]+$" }, "captureAuthorityKind": { "type": "string", "enum": ["workos", "service_token"] }, "decisionLifecycleProtocolVersion": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "producer": { "type": "string", "enum": ["claude_code", "codex", "hermes"] }, "toolOutcome": { "type": "string", "enum": ["succeeded", "returned", "failed", "interrupted", "prevented", "unknown"] }, "envelopeVersion": { "type": "number", "exclusiveMaximum": 4 } }, "required": ["moveId", "capturedAt", "sessionId", "eventType"], "additionalProperties": {} }] } } }, "required": ["batch"], "additionalProperties": {} };
|
|
27814
|
+
var schema93 = { "type": "object", "properties": { "batch": { "type": "array", "items": { "anyOf": [{ "type": "object", "properties": { "moveId": { "type": "string" }, "capturedAt": { "type": "number" }, "sessionId": { "type": "string" }, "invocationId": { "type": "string" }, "eventType": { "type": "string" }, "payload": {}, "env": {}, "capturedOrganizationId": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9_-]+$" }, "captureAuthorityKind": { "type": "string", "enum": ["workos", "service_token"] }, "decisionLifecycleProtocolVersion": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "producer": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] }, "toolOutcome": { "type": "string", "enum": ["succeeded", "returned", "failed", "interrupted", "prevented", "unknown"] }, "envelopeVersion": { "type": "number", "const": 4 } }, "required": ["moveId", "capturedAt", "sessionId", "eventType", "capturedOrganizationId", "captureAuthorityKind", "decisionLifecycleProtocolVersion", "envelopeVersion"], "additionalProperties": {} }, { "type": "object", "properties": { "moveId": { "type": "string" }, "capturedAt": { "type": "number" }, "sessionId": { "type": "string" }, "invocationId": { "type": "string" }, "eventType": { "type": "string" }, "payload": {}, "env": {}, "capturedOrganizationId": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9_-]+$" }, "captureAuthorityKind": { "type": "string", "enum": ["workos", "service_token"] }, "decisionLifecycleProtocolVersion": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "producer": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] }, "toolOutcome": { "type": "string", "enum": ["succeeded", "returned", "failed", "interrupted", "prevented", "unknown"] }, "envelopeVersion": { "type": "number", "exclusiveMaximum": 4 } }, "required": ["moveId", "capturedAt", "sessionId", "eventType"], "additionalProperties": {} }] } } }, "required": ["batch"], "additionalProperties": {} };
|
|
27815
27815
|
var pattern8 = new RegExp("^[A-Za-z0-9_-]+$", "u");
|
|
27816
27816
|
function validate51(data, { instancePath = "", parentData, parentDataProperty, rootData = data, dynamicAnchors = {} } = {}) {
|
|
27817
27817
|
;
|
|
@@ -28065,7 +28065,7 @@ function validate51(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
28065
28065
|
}
|
|
28066
28066
|
errors++;
|
|
28067
28067
|
}
|
|
28068
|
-
if (!(data10 === "claude_code" || data10 === "codex" || data10 === "hermes")) {
|
|
28068
|
+
if (!(data10 === "claude_code" || data10 === "codex" || data10 === "cursor" || data10 === "hermes")) {
|
|
28069
28069
|
const err16 = { instancePath: instancePath + "/batch/" + i0 + "/producer", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/MoveIngestRequest/properties/batch/items/anyOf/0/properties/producer/enum", keyword: "enum", params: { allowedValues: schema93.properties.batch.items.anyOf[0].properties.producer.enum }, message: "must be equal to one of the allowed values" };
|
|
28070
28070
|
if (vErrors === null) {
|
|
28071
28071
|
vErrors = [err16];
|
|
@@ -28377,7 +28377,7 @@ function validate51(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
28377
28377
|
}
|
|
28378
28378
|
errors++;
|
|
28379
28379
|
}
|
|
28380
|
-
if (!(data21 === "claude_code" || data21 === "codex" || data21 === "hermes")) {
|
|
28380
|
+
if (!(data21 === "claude_code" || data21 === "codex" || data21 === "cursor" || data21 === "hermes")) {
|
|
28381
28381
|
const err38 = { instancePath: instancePath + "/batch/" + i0 + "/producer", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/MoveIngestRequest/properties/batch/items/anyOf/1/properties/producer/enum", keyword: "enum", params: { allowedValues: schema93.properties.batch.items.anyOf[1].properties.producer.enum }, message: "must be equal to one of the allowed values" };
|
|
28382
28382
|
if (vErrors === null) {
|
|
28383
28383
|
vErrors = [err38];
|
|
@@ -28514,7 +28514,7 @@ function validate51(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
28514
28514
|
return errors === 0;
|
|
28515
28515
|
}
|
|
28516
28516
|
validate51.evaluated = { "props": true, "dynamicProps": false, "dynamicItems": false };
|
|
28517
|
-
var schema95 = { "type": "object", "properties": { "protocolVersion": { "type": "number", "const": 3 }, "agent": { "type": "string", "enum": ["claude_code", "codex", "hermes"] }, "sessionId": { "type": "string", "pattern": "^[A-Za-z0-9._:-]{1,128}$" }, "invocationId": { "type": "string", "pattern": "^[A-Za-z0-9._:-]{1,128}$" }, "repoSyncId": { "type": "string", "pattern": "^[A-Za-z0-9]{1,64}$" }, "paths": { "maxItems": 32, "type": "array", "items": { "type": "string" } }, "coverage": { "type": "string", "enum": ["complete", "unverified"] }, "branch": { "type": "string", "maxLength": 255, "pattern": "^(?!@?$)(?!\\/)(?!.*\\/$)(?!.*\\/\\/)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*(?:^|\\/)[^/]*\\.lock(?:\\/|$))(?!.*\\.\\.)(?!.*@\\{)(?!.*[~^:?*\\\\]).+$" }, "clientMode": { "type": "string", "enum": ["block", "warn"] }, "clientVersion": { "type": "string", "maxLength": 32, "pattern": "^[A-Za-z0-9][A-Za-z0-9._+-]*$" }, "proposal": { "type": "string" } }, "required": ["protocolVersion", "agent", "sessionId", "invocationId", "repoSyncId", "paths", "coverage", "proposal"], "additionalProperties": false, "x-primitive-runtime-refinements": ["canonical_repository_paths", "unique_repository_paths", "complete_coverage_requires_path", "proposal_utf8_max_6144", "degrade_invalid_rollout_fields", "degrade_invalid_branch"] };
|
|
28517
|
+
var schema95 = { "type": "object", "properties": { "protocolVersion": { "type": "number", "const": 3 }, "agent": { "type": "string", "enum": ["claude_code", "codex", "cursor", "hermes"] }, "sessionId": { "type": "string", "pattern": "^[A-Za-z0-9._:-]{1,128}$" }, "invocationId": { "type": "string", "pattern": "^[A-Za-z0-9._:-]{1,128}$" }, "repoSyncId": { "type": "string", "pattern": "^[A-Za-z0-9]{1,64}$" }, "paths": { "maxItems": 32, "type": "array", "items": { "type": "string" } }, "coverage": { "type": "string", "enum": ["complete", "unverified"] }, "branch": { "type": "string", "maxLength": 255, "pattern": "^(?!@?$)(?!\\/)(?!.*\\/$)(?!.*\\/\\/)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*(?:^|\\/)[^/]*\\.lock(?:\\/|$))(?!.*\\.\\.)(?!.*@\\{)(?!.*[~^:?*\\\\]).+$" }, "clientMode": { "type": "string", "enum": ["block", "warn"] }, "clientVersion": { "type": "string", "maxLength": 32, "pattern": "^[A-Za-z0-9][A-Za-z0-9._+-]*$" }, "proposal": { "type": "string" } }, "required": ["protocolVersion", "agent", "sessionId", "invocationId", "repoSyncId", "paths", "coverage", "proposal"], "additionalProperties": false, "x-primitive-runtime-refinements": ["canonical_repository_paths", "unique_repository_paths", "complete_coverage_requires_path", "proposal_utf8_max_6144", "degrade_invalid_rollout_fields", "degrade_invalid_branch"] };
|
|
28518
28518
|
var pattern10 = new RegExp("^[A-Za-z0-9._:-]{1,128}$", "u");
|
|
28519
28519
|
var pattern12 = new RegExp("^[A-Za-z0-9]{1,64}$", "u");
|
|
28520
28520
|
var pattern13 = new RegExp("^(?!@?$)(?!\\/)(?!.*\\/$)(?!.*\\/\\/)(?!.*(?:^|\\/)\\.{1,2}(?:\\/|$))(?!.*(?:^|\\/)[^/]*\\.lock(?:\\/|$))(?!.*\\.\\.)(?!.*@\\{)(?!.*[~^:?*\\\\]).+$", "u");
|
|
@@ -28570,7 +28570,7 @@ function validate52(data, { instancePath = "", parentData, parentDataProperty, r
|
|
|
28570
28570
|
validate52.errors = [{ instancePath: instancePath + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/PreflightRequestV3/properties/agent/type", keyword: "type", params: { type: "string" }, message: "must be string" }];
|
|
28571
28571
|
return false;
|
|
28572
28572
|
}
|
|
28573
|
-
if (!(data1 === "claude_code" || data1 === "codex" || data1 === "hermes")) {
|
|
28573
|
+
if (!(data1 === "claude_code" || data1 === "codex" || data1 === "cursor" || data1 === "hermes")) {
|
|
28574
28574
|
validate52.errors = [{ instancePath: instancePath + "/agent", schemaPath: "https://api.getprimitive.ai/contracts/cli-http-v1.schema.json#/$defs/PreflightRequestV3/properties/agent/enum", keyword: "enum", params: { allowedValues: schema95.properties.agent.enum }, message: "must be equal to one of the allowed values" }];
|
|
28575
28575
|
return false;
|
|
28576
28576
|
}
|
|
@@ -31883,7 +31883,7 @@ function optionalUserScopeMembers(record2) {
|
|
|
31883
31883
|
members.push({ kind: "role", role: candidate.role });
|
|
31884
31884
|
continue;
|
|
31885
31885
|
}
|
|
31886
|
-
if (candidate.kind === "agent" && (candidate.agent === "claude_code" || candidate.agent === "codex" || candidate.agent === "hermes")) {
|
|
31886
|
+
if (candidate.kind === "agent" && (candidate.agent === "claude_code" || candidate.agent === "codex" || candidate.agent === "cursor" || candidate.agent === "hermes")) {
|
|
31887
31887
|
members.push({ kind: "agent", agent: candidate.agent });
|
|
31888
31888
|
continue;
|
|
31889
31889
|
}
|
|
@@ -32187,7 +32187,7 @@ function stableHookCommand(bin, args = "") {
|
|
|
32187
32187
|
// it as inert data during the rolling window so an older uninstall or
|
|
32188
32188
|
// reinstall can remove the stable entry without invoking npm or PATH.
|
|
32189
32189
|
`prim_legacy_reader='-p ${PKG_NAME}@stable prim-shim.sh ${bin} '; `,
|
|
32190
|
-
'prim_absolute() { case "$1" in
|
|
32190
|
+
'prim_absolute() { case "$1" in [/]* ) ;; *) return 1 ;; esac; case "$1" in [[:space:]]*|*[[:space:]]|*[/][/]*|*[/].[/]*|*[/]..[/]*|*[/].|*[/]..|?*[/]) return 1 ;; esac; }; ',
|
|
32191
32191
|
'prim_config=${PRIM_CONFIG_DIR:-}; if ! prim_absolute "$prim_config"; then prim_config=${XDG_CONFIG_HOME:-}; if prim_absolute "$prim_config"; then ',
|
|
32192
32192
|
'case "$prim_config" in /) prim_config=/prim ;; *) prim_config="$prim_config/prim" ;; esac; ',
|
|
32193
32193
|
'else prim_home=${HOME:-}; prim_absolute "$prim_home" || exit 78; case "$prim_home" in /) prim_config=/.config/prim ;; *) prim_config="$prim_home/.config/prim" ;; esac; ',
|
|
@@ -35805,7 +35805,7 @@ function performPermissionInstall(scope) {
|
|
|
35805
35805
|
};
|
|
35806
35806
|
}
|
|
35807
35807
|
function performStatus() {
|
|
35808
|
-
const
|
|
35808
|
+
const statusFor2 = (path9) => {
|
|
35809
35809
|
const settings = readSettings(path9);
|
|
35810
35810
|
return {
|
|
35811
35811
|
path: path9,
|
|
@@ -35818,7 +35818,7 @@ function performStatus() {
|
|
|
35818
35818
|
statuslineState: statuslineState(settings)
|
|
35819
35819
|
};
|
|
35820
35820
|
};
|
|
35821
|
-
return { user:
|
|
35821
|
+
return { user: statusFor2(USER_SCOPE_PATH), project: statusFor2(projectScopePath()) };
|
|
35822
35822
|
}
|
|
35823
35823
|
function resolveScope(input) {
|
|
35824
35824
|
if (input === void 0 || input === "project") {
|
|
@@ -36017,7 +36017,7 @@ function performUninstall2(scope) {
|
|
|
36017
36017
|
return resultFor(scope, path9, after, changed);
|
|
36018
36018
|
}
|
|
36019
36019
|
function performStatus2() {
|
|
36020
|
-
const
|
|
36020
|
+
const statusFor2 = (path9) => {
|
|
36021
36021
|
const settings = readSettings(path9);
|
|
36022
36022
|
return {
|
|
36023
36023
|
path: path9,
|
|
@@ -36027,7 +36027,7 @@ function performStatus2() {
|
|
|
36027
36027
|
complete: hasCompleteHookRegistration2(settings)
|
|
36028
36028
|
};
|
|
36029
36029
|
};
|
|
36030
|
-
return { user:
|
|
36030
|
+
return { user: statusFor2(USER_SCOPE_PATH2), project: statusFor2(projectScopePath2()) };
|
|
36031
36031
|
}
|
|
36032
36032
|
function resolveScope2(input) {
|
|
36033
36033
|
if (input === void 0 || input === "project") {
|
|
@@ -36079,14 +36079,302 @@ ${line("project", result.project)}`);
|
|
|
36079
36079
|
});
|
|
36080
36080
|
}
|
|
36081
36081
|
|
|
36082
|
+
// src/commands/cursor-install.ts
|
|
36083
|
+
import { existsSync as existsSync10, readFileSync as readFileSync11 } from "fs";
|
|
36084
|
+
import { homedir as homedir7 } from "os";
|
|
36085
|
+
import { isAbsolute as isAbsolute6, join as join13 } from "path";
|
|
36086
|
+
var CAPTURE_BIN3 = "prim-hook";
|
|
36087
|
+
var GATE_BIN3 = "prim-pre-tool-use";
|
|
36088
|
+
var POST_TOOL_BIN = "prim-post-tool-use";
|
|
36089
|
+
var SESSION_START_BIN3 = "prim-session-start";
|
|
36090
|
+
var SESSION_END_BIN2 = "prim-session-end";
|
|
36091
|
+
var STATUSLINE_BIN2 = "prim-statusline";
|
|
36092
|
+
var PRIM_BINS3 = [CAPTURE_BIN3, GATE_BIN3, POST_TOOL_BIN, SESSION_START_BIN3, SESSION_END_BIN2];
|
|
36093
|
+
var CURSOR_EVENTS = [
|
|
36094
|
+
"sessionStart",
|
|
36095
|
+
"beforeSubmitPrompt",
|
|
36096
|
+
"preToolUse",
|
|
36097
|
+
"postToolUse",
|
|
36098
|
+
"postToolUseFailure",
|
|
36099
|
+
"afterAgentResponse",
|
|
36100
|
+
"subagentStop",
|
|
36101
|
+
"stop",
|
|
36102
|
+
"sessionEnd"
|
|
36103
|
+
];
|
|
36104
|
+
var REGISTRATIONS2 = [
|
|
36105
|
+
...CURSOR_EVENTS.map((event) => ({ event, bin: CAPTURE_BIN3 })),
|
|
36106
|
+
{ event: "preToolUse", bin: GATE_BIN3, matcher: "Write|Delete|Shell", timeout: 10 },
|
|
36107
|
+
{ event: "postToolUse", bin: POST_TOOL_BIN },
|
|
36108
|
+
{ event: "postToolUseFailure", bin: POST_TOOL_BIN },
|
|
36109
|
+
{ event: "sessionStart", bin: SESSION_START_BIN3 },
|
|
36110
|
+
{ event: "sessionEnd", bin: SESSION_END_BIN2 }
|
|
36111
|
+
];
|
|
36112
|
+
function cursorConfigDirectory(env4 = process.env, home = homedir7(), platform2 = process.platform) {
|
|
36113
|
+
const explicit = env4.CURSOR_CONFIG_DIR?.trim();
|
|
36114
|
+
if (explicit && isAbsolute6(explicit)) return explicit;
|
|
36115
|
+
const xdg = env4.XDG_CONFIG_HOME?.trim();
|
|
36116
|
+
if (platform2 !== "darwin" && xdg && isAbsolute6(xdg)) return join13(xdg, "cursor");
|
|
36117
|
+
return join13(home, ".cursor");
|
|
36118
|
+
}
|
|
36119
|
+
function cursorHooksPath(scope, root = projectRoot()) {
|
|
36120
|
+
return scope === "user" ? join13(cursorConfigDirectory(), "hooks.json") : join13(root, ".cursor", "hooks.json");
|
|
36121
|
+
}
|
|
36122
|
+
function cursorCliConfigPath() {
|
|
36123
|
+
return join13(cursorConfigDirectory(), "cli-config.json");
|
|
36124
|
+
}
|
|
36125
|
+
function plainObject(value) {
|
|
36126
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36127
|
+
}
|
|
36128
|
+
function readCursorHooks(path9) {
|
|
36129
|
+
if (!existsSync10(path9)) return {};
|
|
36130
|
+
let parsed;
|
|
36131
|
+
try {
|
|
36132
|
+
parsed = JSON.parse(readFileSync11(path9, "utf8"));
|
|
36133
|
+
} catch {
|
|
36134
|
+
throw new Error(`invalid Cursor hooks JSON at ${path9}`);
|
|
36135
|
+
}
|
|
36136
|
+
if (!plainObject(parsed)) throw new Error(`Cursor hooks config must be an object: ${path9}`);
|
|
36137
|
+
if (parsed.version !== void 0 && parsed.version !== 1) {
|
|
36138
|
+
throw new Error(`unsupported Cursor hooks version at ${path9} (expected version 1)`);
|
|
36139
|
+
}
|
|
36140
|
+
if (parsed.hooks !== void 0) {
|
|
36141
|
+
if (!plainObject(parsed.hooks)) throw new Error(`Cursor hooks must be an object: ${path9}`);
|
|
36142
|
+
for (const [event, entries] of Object.entries(parsed.hooks)) {
|
|
36143
|
+
if (!Array.isArray(entries) || !entries.every(plainObject)) {
|
|
36144
|
+
throw new Error(`Cursor hook list must contain objects: ${event} in ${path9}`);
|
|
36145
|
+
}
|
|
36146
|
+
}
|
|
36147
|
+
}
|
|
36148
|
+
return parsed;
|
|
36149
|
+
}
|
|
36150
|
+
function readObject(path9) {
|
|
36151
|
+
if (!existsSync10(path9)) return {};
|
|
36152
|
+
let parsed;
|
|
36153
|
+
try {
|
|
36154
|
+
parsed = JSON.parse(readFileSync11(path9, "utf8"));
|
|
36155
|
+
} catch {
|
|
36156
|
+
throw new Error(`invalid Cursor CLI config JSON at ${path9}`);
|
|
36157
|
+
}
|
|
36158
|
+
if (!plainObject(parsed)) throw new Error(`Cursor CLI config must be an object: ${path9}`);
|
|
36159
|
+
return parsed;
|
|
36160
|
+
}
|
|
36161
|
+
function writeJson(path9, value) {
|
|
36162
|
+
atomicWriteFile(path9, `${JSON.stringify(value, null, 2)}
|
|
36163
|
+
`, { ensureParent: true });
|
|
36164
|
+
}
|
|
36165
|
+
function commandFor(registration, scope) {
|
|
36166
|
+
return stableHookCommand(
|
|
36167
|
+
registration.bin,
|
|
36168
|
+
`--agent cursor --event ${registration.event} --scope ${scope}`
|
|
36169
|
+
);
|
|
36170
|
+
}
|
|
36171
|
+
var OWNED_COMMANDS = new Set(
|
|
36172
|
+
["project", "user"].flatMap(
|
|
36173
|
+
(scope) => REGISTRATIONS2.map((registration) => commandFor(registration, scope))
|
|
36174
|
+
)
|
|
36175
|
+
);
|
|
36176
|
+
function jsoncUnsafeCommand(command) {
|
|
36177
|
+
return command.replace('case "$1" in [/]* ', 'case "$1" in /*').replace("*[/][/]*", "*//*").replace("*[/].[/]*", "*/./*").replace("*[/]..[/]*", "*/../*").replace("*[/].", "*/.").replace("*[/]..", "*/..").replace("?*[/]", "?*/");
|
|
36178
|
+
}
|
|
36179
|
+
var JSONC_UNSAFE_OWNED_COMMANDS = new Set([...OWNED_COMMANDS].map(jsoncUnsafeCommand));
|
|
36180
|
+
function isOwnedCursorHookCommand(command) {
|
|
36181
|
+
return typeof command === "string" && (OWNED_COMMANDS.has(command) || JSONC_UNSAFE_OWNED_COMMANDS.has(command));
|
|
36182
|
+
}
|
|
36183
|
+
function hookFor(registration, scope) {
|
|
36184
|
+
return {
|
|
36185
|
+
command: commandFor(registration, scope),
|
|
36186
|
+
...registration.matcher ? { matcher: registration.matcher } : {},
|
|
36187
|
+
...registration.timeout ? { timeout: registration.timeout } : {}
|
|
36188
|
+
};
|
|
36189
|
+
}
|
|
36190
|
+
function exactHook(entry, registration, scope) {
|
|
36191
|
+
return JSON.stringify(entry) === JSON.stringify(hookFor(registration, scope));
|
|
36192
|
+
}
|
|
36193
|
+
function applyCursorInstall(settings, scope) {
|
|
36194
|
+
const hooks = {};
|
|
36195
|
+
for (const [event, entries] of Object.entries(settings.hooks ?? {})) {
|
|
36196
|
+
hooks[event] = entries.filter((entry) => !isOwnedCursorHookCommand(entry.command));
|
|
36197
|
+
}
|
|
36198
|
+
for (const registration of REGISTRATIONS2) {
|
|
36199
|
+
const entries = hooks[registration.event] ?? [];
|
|
36200
|
+
entries.push(hookFor(registration, scope));
|
|
36201
|
+
hooks[registration.event] = entries;
|
|
36202
|
+
}
|
|
36203
|
+
return { ...settings, version: 1, hooks };
|
|
36204
|
+
}
|
|
36205
|
+
function applyCursorUninstall(settings) {
|
|
36206
|
+
const hooks = {};
|
|
36207
|
+
for (const [event, entries] of Object.entries(settings.hooks ?? {})) {
|
|
36208
|
+
const retained = entries.filter((entry) => !isOwnedCursorHookCommand(entry.command));
|
|
36209
|
+
if (retained.length > 0) hooks[event] = retained;
|
|
36210
|
+
}
|
|
36211
|
+
return { ...settings, hooks };
|
|
36212
|
+
}
|
|
36213
|
+
function ownedEntries(settings) {
|
|
36214
|
+
return Object.entries(settings.hooks ?? {}).flatMap(
|
|
36215
|
+
([event, entries]) => entries.filter((entry) => isOwnedCursorHookCommand(entry.command)).map((entry) => ({ event, entry }))
|
|
36216
|
+
);
|
|
36217
|
+
}
|
|
36218
|
+
function hasExactCursorHandler(settings, event, bin, scope) {
|
|
36219
|
+
const registration = REGISTRATIONS2.find(
|
|
36220
|
+
(candidate) => candidate.event === event && candidate.bin === bin
|
|
36221
|
+
);
|
|
36222
|
+
return registration ? (settings.hooks?.[event] ?? []).some((entry) => exactHook(entry, registration, scope)) : false;
|
|
36223
|
+
}
|
|
36224
|
+
function complete(settings, scope) {
|
|
36225
|
+
const owned = ownedEntries(settings);
|
|
36226
|
+
return owned.length === REGISTRATIONS2.length && REGISTRATIONS2.every(
|
|
36227
|
+
(registration) => owned.filter(
|
|
36228
|
+
({ event, entry }) => event === registration.event && exactHook(entry, registration, scope)
|
|
36229
|
+
).length === 1
|
|
36230
|
+
);
|
|
36231
|
+
}
|
|
36232
|
+
function captureInstalled3(settings, scope) {
|
|
36233
|
+
return CURSOR_EVENTS.every((event) => hasExactCursorHandler(settings, event, CAPTURE_BIN3, scope));
|
|
36234
|
+
}
|
|
36235
|
+
function gateInstalled(settings, scope) {
|
|
36236
|
+
return hasExactCursorHandler(settings, "preToolUse", GATE_BIN3, scope);
|
|
36237
|
+
}
|
|
36238
|
+
var FOOTER = {
|
|
36239
|
+
type: "command",
|
|
36240
|
+
command: stableHookCommand(STATUSLINE_BIN2),
|
|
36241
|
+
updateIntervalMs: 1e3,
|
|
36242
|
+
timeoutMs: 2e3
|
|
36243
|
+
};
|
|
36244
|
+
var JSONC_UNSAFE_FOOTER = {
|
|
36245
|
+
...FOOTER,
|
|
36246
|
+
command: jsoncUnsafeCommand(FOOTER.command)
|
|
36247
|
+
};
|
|
36248
|
+
function exactFooter(value) {
|
|
36249
|
+
return plainObject(value) && JSON.stringify(value) === JSON.stringify(FOOTER);
|
|
36250
|
+
}
|
|
36251
|
+
function jsoncUnsafeFooter(value) {
|
|
36252
|
+
return plainObject(value) && JSON.stringify(value) === JSON.stringify(JSONC_UNSAFE_FOOTER);
|
|
36253
|
+
}
|
|
36254
|
+
function applyCursorFooterInstall(config) {
|
|
36255
|
+
if (config.statusLine === void 0)
|
|
36256
|
+
return { config: { ...config, statusLine: FOOTER }, installed: true, preservedCustom: false };
|
|
36257
|
+
if (exactFooter(config.statusLine)) return { config, installed: true, preservedCustom: false };
|
|
36258
|
+
if (jsoncUnsafeFooter(config.statusLine)) {
|
|
36259
|
+
return { config: { ...config, statusLine: FOOTER }, installed: true, preservedCustom: false };
|
|
36260
|
+
}
|
|
36261
|
+
return { config, installed: false, preservedCustom: true };
|
|
36262
|
+
}
|
|
36263
|
+
function applyCursorFooterUninstall(config) {
|
|
36264
|
+
if (!exactFooter(config.statusLine) && !jsoncUnsafeFooter(config.statusLine)) {
|
|
36265
|
+
return { config, removed: false };
|
|
36266
|
+
}
|
|
36267
|
+
return {
|
|
36268
|
+
config: Object.fromEntries(Object.entries(config).filter(([key]) => key !== "statusLine")),
|
|
36269
|
+
removed: true
|
|
36270
|
+
};
|
|
36271
|
+
}
|
|
36272
|
+
function statusFor(scope, path9 = cursorHooksPath(scope)) {
|
|
36273
|
+
const settings = readCursorHooks(path9);
|
|
36274
|
+
const base = {
|
|
36275
|
+
path: path9,
|
|
36276
|
+
present: ownedEntries(settings).length > 0,
|
|
36277
|
+
gate: gateInstalled(settings, scope),
|
|
36278
|
+
capture: captureInstalled3(settings, scope),
|
|
36279
|
+
complete: complete(settings, scope)
|
|
36280
|
+
};
|
|
36281
|
+
if (scope === "user") {
|
|
36282
|
+
const cliConfig = readObject(cursorCliConfigPath());
|
|
36283
|
+
base.footer = exactFooter(cliConfig.statusLine);
|
|
36284
|
+
base.footerPreservedCustom = cliConfig.statusLine !== void 0 && !base.footer;
|
|
36285
|
+
}
|
|
36286
|
+
return base;
|
|
36287
|
+
}
|
|
36288
|
+
function performInstall3(scope, _force = false) {
|
|
36289
|
+
stageHookRuntime();
|
|
36290
|
+
const path9 = cursorHooksPath(scope);
|
|
36291
|
+
const before = readCursorHooks(path9);
|
|
36292
|
+
const after = applyCursorInstall(before, scope);
|
|
36293
|
+
let changed = JSON.stringify(before) !== JSON.stringify(after);
|
|
36294
|
+
if (changed) writeJson(path9, after);
|
|
36295
|
+
let restartRequired = false;
|
|
36296
|
+
if (scope === "user") {
|
|
36297
|
+
const cliPath = cursorCliConfigPath();
|
|
36298
|
+
const cliBefore = readObject(cliPath);
|
|
36299
|
+
const footer = applyCursorFooterInstall(cliBefore);
|
|
36300
|
+
if (JSON.stringify(cliBefore) !== JSON.stringify(footer.config)) {
|
|
36301
|
+
writeJson(cliPath, footer.config);
|
|
36302
|
+
changed = true;
|
|
36303
|
+
restartRequired = true;
|
|
36304
|
+
}
|
|
36305
|
+
}
|
|
36306
|
+
return { scope, ...statusFor(scope, path9), changed, restartRequired };
|
|
36307
|
+
}
|
|
36308
|
+
function performUninstall3(scope) {
|
|
36309
|
+
const path9 = cursorHooksPath(scope);
|
|
36310
|
+
const before = readCursorHooks(path9);
|
|
36311
|
+
const after = applyCursorUninstall(before);
|
|
36312
|
+
let changed = JSON.stringify(before) !== JSON.stringify(after);
|
|
36313
|
+
if (changed) writeJson(path9, after);
|
|
36314
|
+
let restartRequired = false;
|
|
36315
|
+
if (scope === "user") {
|
|
36316
|
+
const cliPath = cursorCliConfigPath();
|
|
36317
|
+
const cliBefore = readObject(cliPath);
|
|
36318
|
+
const footer = applyCursorFooterUninstall(cliBefore);
|
|
36319
|
+
if (footer.removed) {
|
|
36320
|
+
writeJson(cliPath, footer.config);
|
|
36321
|
+
changed = true;
|
|
36322
|
+
restartRequired = true;
|
|
36323
|
+
}
|
|
36324
|
+
}
|
|
36325
|
+
return { scope, ...statusFor(scope, path9), changed, restartRequired };
|
|
36326
|
+
}
|
|
36327
|
+
function performStatus3() {
|
|
36328
|
+
return { user: statusFor("user"), project: statusFor("project") };
|
|
36329
|
+
}
|
|
36330
|
+
function inspectHookRuntimeResolutions3() {
|
|
36331
|
+
const commands = ["user", "project"].flatMap(
|
|
36332
|
+
(scope) => ownedEntries(readCursorHooks(cursorHooksPath(scope))).map(({ entry }) => entry.command)
|
|
36333
|
+
);
|
|
36334
|
+
return hookCommandResolutions(commands, PRIM_BINS3);
|
|
36335
|
+
}
|
|
36336
|
+
function resolveScope3(input) {
|
|
36337
|
+
if (input === void 0 || input === "project") return "project";
|
|
36338
|
+
if (input === "user") return "user";
|
|
36339
|
+
throw new Error(`unknown --scope "${input}" (expected: user or project)`);
|
|
36340
|
+
}
|
|
36341
|
+
function registerCursorCommands(program3) {
|
|
36342
|
+
const cursor = program3.command("cursor").description("Manage the native Cursor integration (capture, gate, ingest, presence)");
|
|
36343
|
+
cursor.command("install").description("Register Primitive in Cursor's native hooks.json").option("--scope <scope>", "project (default) or user").option("--force", "Repair drifted Primitive entries; custom Cursor fields remain untouched").action((opts) => {
|
|
36344
|
+
const result = performInstall3(resolveScope3(opts.scope), opts.force);
|
|
36345
|
+
console.error(
|
|
36346
|
+
result.changed ? `[prim] Cursor integration installed (${result.scope} scope) at ${result.path}` : `[prim] Cursor integration already present at ${result.path}`
|
|
36347
|
+
);
|
|
36348
|
+
if (result.restartRequired) console.error("[prim] restart Cursor CLI to load the footer");
|
|
36349
|
+
console.log(JSON.stringify(result, null, 2));
|
|
36350
|
+
});
|
|
36351
|
+
cursor.command("uninstall").description("Remove only Primitive-owned Cursor hooks and footer").option("--scope <scope>", "project (default) or user").action((opts) => {
|
|
36352
|
+
const result = performUninstall3(resolveScope3(opts.scope));
|
|
36353
|
+
console.error(
|
|
36354
|
+
result.changed ? `[prim] Cursor integration removed (${result.scope} scope)` : `[prim] no Primitive-owned Cursor integration found (${result.scope} scope)`
|
|
36355
|
+
);
|
|
36356
|
+
if (result.restartRequired) console.error("[prim] restart Cursor CLI to remove the footer");
|
|
36357
|
+
console.log(JSON.stringify(result, null, 2));
|
|
36358
|
+
});
|
|
36359
|
+
cursor.command("status").description("Report native Cursor hook and footer status").action(() => {
|
|
36360
|
+
const result = performStatus3();
|
|
36361
|
+
const mark = (value) => value ? "\u2713" : "\u2717";
|
|
36362
|
+
console.error(
|
|
36363
|
+
`[prim] user: gate ${mark(result.user.gate)} \xB7 capture ${mark(result.user.capture)} \xB7 footer ${mark(result.user.footer)} (${result.user.path})
|
|
36364
|
+
[prim] project: gate ${mark(result.project.gate)} \xB7 capture ${mark(result.project.capture)} (${result.project.path})`
|
|
36365
|
+
);
|
|
36366
|
+
console.log(JSON.stringify(result, null, 2));
|
|
36367
|
+
});
|
|
36368
|
+
}
|
|
36369
|
+
|
|
36082
36370
|
// src/commands/daemon.ts
|
|
36083
36371
|
import { spawn as spawn3 } from "child_process";
|
|
36084
|
-
import { closeSync as closeSync3, existsSync as
|
|
36085
|
-
import { join as
|
|
36372
|
+
import { closeSync as closeSync3, existsSync as existsSync12, mkdirSync as mkdirSync9, openSync as openSync3, readFileSync as readFileSync13, unlinkSync as unlinkSync3 } from "fs";
|
|
36373
|
+
import { join as join16 } from "path";
|
|
36086
36374
|
|
|
36087
36375
|
// src/daemon/latest-bootstrap.ts
|
|
36088
36376
|
import { spawn as spawn2 } from "child_process";
|
|
36089
|
-
import { join as
|
|
36377
|
+
import { join as join14 } from "path";
|
|
36090
36378
|
var LATEST_BOOTSTRAP_TIMEOUT_MS = 45e3;
|
|
36091
36379
|
var LATEST_BOOTSTRAP_LOCK_NAME = "daemon-latest.lock";
|
|
36092
36380
|
async function runPinnedEnsure(options) {
|
|
@@ -36127,7 +36415,7 @@ async function runPinnedEnsure(options) {
|
|
|
36127
36415
|
});
|
|
36128
36416
|
}
|
|
36129
36417
|
async function runLatestDaemonBootstrap(ensureCurrent, options = {}) {
|
|
36130
|
-
const lockPath = options.lockPath ??
|
|
36418
|
+
const lockPath = options.lockPath ?? join14(
|
|
36131
36419
|
primConfigDirectory({ env: options.env, homeDir: options.homeDir }),
|
|
36132
36420
|
LATEST_BOOTSTRAP_LOCK_NAME
|
|
36133
36421
|
);
|
|
@@ -36157,11 +36445,11 @@ import {
|
|
|
36157
36445
|
accessSync as accessSync2,
|
|
36158
36446
|
chmodSync as chmodSync4,
|
|
36159
36447
|
copyFileSync as copyFileSync2,
|
|
36160
|
-
existsSync as
|
|
36448
|
+
existsSync as existsSync11,
|
|
36161
36449
|
lstatSync as lstatSync5,
|
|
36162
36450
|
mkdirSync as mkdirSync8,
|
|
36163
36451
|
mkdtempSync as mkdtempSync2,
|
|
36164
|
-
readFileSync as
|
|
36452
|
+
readFileSync as readFileSync12,
|
|
36165
36453
|
readdirSync as readdirSync3,
|
|
36166
36454
|
readlinkSync,
|
|
36167
36455
|
realpathSync as realpathSync3,
|
|
@@ -36170,8 +36458,8 @@ import {
|
|
|
36170
36458
|
symlinkSync,
|
|
36171
36459
|
writeFileSync as writeFileSync7
|
|
36172
36460
|
} from "fs";
|
|
36173
|
-
import { homedir as
|
|
36174
|
-
import { basename as basename3, dirname as dirname10, isAbsolute as
|
|
36461
|
+
import { homedir as homedir8 } from "os";
|
|
36462
|
+
import { basename as basename3, dirname as dirname10, isAbsolute as isAbsolute7, join as join15, resolve as resolve6 } from "path";
|
|
36175
36463
|
|
|
36176
36464
|
// src/daemon/env-binding.ts
|
|
36177
36465
|
function normalizeApiUrl(url) {
|
|
@@ -36210,31 +36498,31 @@ var LaunchctlError = class extends Error {
|
|
|
36210
36498
|
}
|
|
36211
36499
|
};
|
|
36212
36500
|
function xdgDataHome(options) {
|
|
36213
|
-
const home = options.homeDir ??
|
|
36501
|
+
const home = options.homeDir ?? homedir8();
|
|
36214
36502
|
const configured = (options.env ?? process.env).XDG_DATA_HOME;
|
|
36215
|
-
return configured &&
|
|
36503
|
+
return configured && isAbsolute7(configured) ? configured : join15(home, ".local", "share");
|
|
36216
36504
|
}
|
|
36217
36505
|
function runtimePaths(options = {}) {
|
|
36218
|
-
const dataDir =
|
|
36219
|
-
const runtimeDir =
|
|
36220
|
-
const currentLink =
|
|
36506
|
+
const dataDir = join15(xdgDataHome(options), "prim");
|
|
36507
|
+
const runtimeDir = join15(dataDir, "runtime");
|
|
36508
|
+
const currentLink = join15(runtimeDir, "current");
|
|
36221
36509
|
return {
|
|
36222
36510
|
dataDir,
|
|
36223
36511
|
runtimeDir,
|
|
36224
|
-
releasesDir:
|
|
36512
|
+
releasesDir: join15(runtimeDir, "releases"),
|
|
36225
36513
|
currentLink,
|
|
36226
|
-
statuslineLauncher:
|
|
36227
|
-
disabledMarker:
|
|
36228
|
-
lifecycleLockDir:
|
|
36514
|
+
statuslineLauncher: join15(runtimeDir, "prim-statusline"),
|
|
36515
|
+
disabledMarker: join15(dataDir, "daemon.disabled"),
|
|
36516
|
+
lifecycleLockDir: join15(dataDir, "daemon.lifecycle.lock")
|
|
36229
36517
|
};
|
|
36230
36518
|
}
|
|
36231
36519
|
function daemonControlPaths(options = {}) {
|
|
36232
36520
|
const configDir = primConfigDirectory(options);
|
|
36233
36521
|
const legacy = runtimePaths(options);
|
|
36234
36522
|
return {
|
|
36235
|
-
launcher:
|
|
36236
|
-
disabledMarker:
|
|
36237
|
-
lifecycleLockDir:
|
|
36523
|
+
launcher: join15(configDir, `prim-daemon-launcher-v${LAUNCHER_SCHEMA_VERSION}`),
|
|
36524
|
+
disabledMarker: join15(configDir, "daemon.disabled"),
|
|
36525
|
+
lifecycleLockDir: join15(configDir, "daemon.lifecycle.lock"),
|
|
36238
36526
|
legacyDisabledMarker: legacy.disabledMarker,
|
|
36239
36527
|
legacyLifecycleLockDir: legacy.lifecycleLockDir
|
|
36240
36528
|
};
|
|
@@ -36242,10 +36530,10 @@ function daemonControlPaths(options = {}) {
|
|
|
36242
36530
|
function findPackageVersion(entryFile) {
|
|
36243
36531
|
let dir = dirname10(resolve6(entryFile));
|
|
36244
36532
|
for (let depth = 0; depth < 6; depth++) {
|
|
36245
|
-
const packagePath =
|
|
36246
|
-
if (
|
|
36533
|
+
const packagePath = join15(dir, "package.json");
|
|
36534
|
+
if (existsSync11(packagePath)) {
|
|
36247
36535
|
try {
|
|
36248
|
-
const manifest = JSON.parse(
|
|
36536
|
+
const manifest = JSON.parse(readFileSync12(packagePath, "utf8"));
|
|
36249
36537
|
if (manifest.name === "@primitive.ai/prim" && manifest.version) {
|
|
36250
36538
|
return manifest.version;
|
|
36251
36539
|
}
|
|
@@ -36260,7 +36548,7 @@ function findPackageVersion(entryFile) {
|
|
|
36260
36548
|
}
|
|
36261
36549
|
function readRuntimeManifest(path9) {
|
|
36262
36550
|
try {
|
|
36263
|
-
const parsed = JSON.parse(
|
|
36551
|
+
const parsed = JSON.parse(readFileSync12(path9, "utf8"));
|
|
36264
36552
|
if (parsed.schemaVersion !== RUNTIME_SCHEMA_VERSION || typeof parsed.version !== "string" || typeof parsed.nodePath !== "string" || parsed.daemonFile !== "prim-daemon-server" || typeof parsed.daemonSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(parsed.daemonSha256)) {
|
|
36265
36553
|
return null;
|
|
36266
36554
|
}
|
|
@@ -36276,10 +36564,10 @@ function exactKeys2(value, expected) {
|
|
|
36276
36564
|
return actual.length === wanted.length && actual.every((key, index) => key === wanted[index]);
|
|
36277
36565
|
}
|
|
36278
36566
|
function readOwnedRuntimeManifest(releaseDir) {
|
|
36279
|
-
const manifestPath =
|
|
36280
|
-
const daemonPath =
|
|
36567
|
+
const manifestPath = join15(releaseDir, "manifest.json");
|
|
36568
|
+
const daemonPath = join15(releaseDir, "prim-daemon-server");
|
|
36281
36569
|
try {
|
|
36282
|
-
const raw =
|
|
36570
|
+
const raw = readFileSync12(manifestPath, "utf8");
|
|
36283
36571
|
const parsed = JSON.parse(raw);
|
|
36284
36572
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
36285
36573
|
if (!exactKeys2(parsed, [
|
|
@@ -36293,7 +36581,7 @@ function readOwnedRuntimeManifest(releaseDir) {
|
|
|
36293
36581
|
return null;
|
|
36294
36582
|
}
|
|
36295
36583
|
const manifest = parsed;
|
|
36296
|
-
if (manifest.schemaVersion !== RUNTIME_SCHEMA_VERSION || compareSemver(manifest.version, manifest.version) !== 0 || !
|
|
36584
|
+
if (manifest.schemaVersion !== RUNTIME_SCHEMA_VERSION || compareSemver(manifest.version, manifest.version) !== 0 || !isAbsolute7(manifest.nodePath) || /[\r\n]/u.test(manifest.nodePath) || manifest.daemonFile !== "prim-daemon-server" || !/^[0-9a-f]{64}$/u.test(manifest.daemonSha256) || new Date(manifest.stagedAt).toISOString() !== manifest.stagedAt || raw !== `${JSON.stringify(manifest, null, 2)}
|
|
36297
36585
|
` || !lstatSync5(daemonPath).isFile() || sha256File(daemonPath) !== manifest.daemonSha256) {
|
|
36298
36586
|
return null;
|
|
36299
36587
|
}
|
|
@@ -36314,7 +36602,7 @@ function sameRuntime(current, desired, daemonPath) {
|
|
|
36314
36602
|
}
|
|
36315
36603
|
}
|
|
36316
36604
|
function sha256File(path9) {
|
|
36317
|
-
return createHash8("sha256").update(
|
|
36605
|
+
return createHash8("sha256").update(readFileSync12(path9)).digest("hex");
|
|
36318
36606
|
}
|
|
36319
36607
|
function atomicSymlink(target, linkPath) {
|
|
36320
36608
|
const tempLink = `${linkPath}.tmp-${process.pid}-${createHash8("sha256").update(`${target}\0${Date.now()}\0${Math.random()}`).digest("hex").slice(0, 12)}`;
|
|
@@ -36329,7 +36617,7 @@ function atomicSymlink(target, linkPath) {
|
|
|
36329
36617
|
function stageRuntime(options = {}) {
|
|
36330
36618
|
const paths = runtimePaths(options);
|
|
36331
36619
|
const daemonSource = options.daemonSource ?? binFile("prim-daemon-server");
|
|
36332
|
-
if (!daemonSource || !
|
|
36620
|
+
if (!daemonSource || !existsSync11(daemonSource)) {
|
|
36333
36621
|
throw new Error("cannot stage runtime: prim-daemon-server bundle is unavailable");
|
|
36334
36622
|
}
|
|
36335
36623
|
const nodePath = resolve6(options.nodePath ?? process.execPath);
|
|
@@ -36347,8 +36635,8 @@ function stageRuntime(options = {}) {
|
|
|
36347
36635
|
currentRelease = realpathSync3(paths.currentLink);
|
|
36348
36636
|
} catch {
|
|
36349
36637
|
}
|
|
36350
|
-
const current = currentRelease ? readRuntimeManifest(
|
|
36351
|
-
const currentDaemon = currentRelease ?
|
|
36638
|
+
const current = currentRelease ? readRuntimeManifest(join15(currentRelease, "manifest.json")) : null;
|
|
36639
|
+
const currentDaemon = currentRelease ? join15(currentRelease, desired.daemonFile) : "";
|
|
36352
36640
|
if (currentRelease && sameRuntime(current, desired, currentDaemon)) {
|
|
36353
36641
|
const manifest = current;
|
|
36354
36642
|
atomicWrite3(
|
|
@@ -36366,17 +36654,17 @@ function stageRuntime(options = {}) {
|
|
|
36366
36654
|
mkdirSync8(paths.releasesDir, { recursive: true, mode: RUNTIME_DIR_MODE });
|
|
36367
36655
|
chmodSync4(paths.runtimeDir, RUNTIME_DIR_MODE);
|
|
36368
36656
|
chmodSync4(paths.releasesDir, RUNTIME_DIR_MODE);
|
|
36369
|
-
const stagingDir = mkdtempSync2(
|
|
36657
|
+
const stagingDir = mkdtempSync2(join15(paths.releasesDir, ".stage-"));
|
|
36370
36658
|
chmodSync4(stagingDir, RUNTIME_DIR_MODE);
|
|
36371
36659
|
let releaseDir;
|
|
36372
36660
|
try {
|
|
36373
|
-
const daemonTarget =
|
|
36661
|
+
const daemonTarget = join15(stagingDir, desired.daemonFile);
|
|
36374
36662
|
copyFileSync2(daemonSource, daemonTarget);
|
|
36375
36663
|
chmodSync4(daemonTarget, RUNTIME_FILE_MODE);
|
|
36376
36664
|
if (sha256File(daemonTarget) !== desired.daemonSha256) {
|
|
36377
36665
|
throw new Error("cannot stage runtime: daemon bundle changed while it was copied");
|
|
36378
36666
|
}
|
|
36379
|
-
const manifestTarget =
|
|
36667
|
+
const manifestTarget = join15(stagingDir, "manifest.json");
|
|
36380
36668
|
writeFileSync7(manifestTarget, `${JSON.stringify(desired, null, 2)}
|
|
36381
36669
|
`, {
|
|
36382
36670
|
encoding: "utf8",
|
|
@@ -36384,10 +36672,10 @@ function stageRuntime(options = {}) {
|
|
|
36384
36672
|
flag: "wx"
|
|
36385
36673
|
});
|
|
36386
36674
|
const releaseName = `release-${createHash8("sha256").update(`${version}\0${nodePath}\0${desired.stagedAt}\0${process.pid}\0${Math.random()}`).digest("hex").slice(0, 16)}`;
|
|
36387
|
-
releaseDir =
|
|
36675
|
+
releaseDir = join15(paths.releasesDir, releaseName);
|
|
36388
36676
|
renameSync4(stagingDir, releaseDir);
|
|
36389
36677
|
releaseDir = realpathSync3(releaseDir);
|
|
36390
|
-
atomicSymlink(
|
|
36678
|
+
atomicSymlink(join15("releases", releaseName), paths.currentLink);
|
|
36391
36679
|
atomicWrite3(
|
|
36392
36680
|
paths.statuslineLauncher,
|
|
36393
36681
|
statuslineLauncherContent(desired.version, options),
|
|
@@ -36401,14 +36689,14 @@ function stageRuntime(options = {}) {
|
|
|
36401
36689
|
changed: true,
|
|
36402
36690
|
manifest: desired,
|
|
36403
36691
|
paths,
|
|
36404
|
-
daemonPath:
|
|
36692
|
+
daemonPath: join15(releaseDir, desired.daemonFile)
|
|
36405
36693
|
};
|
|
36406
36694
|
}
|
|
36407
36695
|
function shellQuote2(value) {
|
|
36408
36696
|
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
36409
36697
|
}
|
|
36410
36698
|
function statuslineLauncherContent(version, options = {}) {
|
|
36411
|
-
const socketPath =
|
|
36699
|
+
const socketPath = join15(primConfigDirectory(options), "sock");
|
|
36412
36700
|
const fallback = `primitive ${version} (daemon: down)`;
|
|
36413
36701
|
return `#!/bin/sh
|
|
36414
36702
|
response=$(
|
|
@@ -36441,7 +36729,7 @@ function lstatIfPresent3(path9) {
|
|
|
36441
36729
|
function assertExactFile(path9, expected, label) {
|
|
36442
36730
|
if (!lstatIfPresent3(path9)) return;
|
|
36443
36731
|
assertRegularFile(path9, label);
|
|
36444
|
-
if (
|
|
36732
|
+
if (readFileSync12(path9, "utf8") !== expected) {
|
|
36445
36733
|
throw new Error(`refusing to remove unrecognized ${label} at ${path9}`);
|
|
36446
36734
|
}
|
|
36447
36735
|
}
|
|
@@ -36450,12 +36738,12 @@ function assertOwnedDaemonRuntime(options) {
|
|
|
36450
36738
|
const control = daemonControlPaths(options);
|
|
36451
36739
|
const configDir = primConfigDirectory(options);
|
|
36452
36740
|
const service = process.platform === "darwin" ? launchdPaths(options) : void 0;
|
|
36453
|
-
const logPath = service?.logPath ??
|
|
36741
|
+
const logPath = service?.logPath ?? join15(configDir, "daemon.log");
|
|
36454
36742
|
for (const activeArtifact of [
|
|
36455
|
-
|
|
36456
|
-
|
|
36457
|
-
|
|
36458
|
-
|
|
36743
|
+
join15(configDir, "daemon.pid"),
|
|
36744
|
+
join15(configDir, "sock"),
|
|
36745
|
+
join15(configDir, "daemon.lock"),
|
|
36746
|
+
join15(configDir, "client-instance.lock")
|
|
36459
36747
|
]) {
|
|
36460
36748
|
if (lstatIfPresent3(activeArtifact)) {
|
|
36461
36749
|
throw new Error(`refusing runtime removal while daemon state remains at ${activeArtifact}`);
|
|
@@ -36476,17 +36764,17 @@ function assertOwnedDaemonRuntime(options) {
|
|
|
36476
36764
|
);
|
|
36477
36765
|
}
|
|
36478
36766
|
assertRegularFile(logPath, "daemon log");
|
|
36479
|
-
assertRegularFile(
|
|
36480
|
-
assertRegularFile(
|
|
36767
|
+
assertRegularFile(join15(configDir, "daemon-health.json"), "daemon health snapshot");
|
|
36768
|
+
assertRegularFile(join15(configDir, "client_instance_id"), "daemon client instance id");
|
|
36481
36769
|
if (service && lstatIfPresent3(service.plistPath)) {
|
|
36482
36770
|
assertRegularFile(service.plistPath, "launchd property list");
|
|
36483
36771
|
const expected = generateLaunchAgentPlist({
|
|
36484
36772
|
launcherPath: control.launcher,
|
|
36485
36773
|
logPath,
|
|
36486
|
-
workingDirectory: options.homeDir ??
|
|
36774
|
+
workingDirectory: options.homeDir ?? homedir8(),
|
|
36487
36775
|
label: options.label
|
|
36488
36776
|
});
|
|
36489
|
-
if (
|
|
36777
|
+
if (readFileSync12(service.plistPath, "utf8") !== expected) {
|
|
36490
36778
|
throw new Error(
|
|
36491
36779
|
`refusing to remove unrecognized launchd property list at ${service.plistPath}`
|
|
36492
36780
|
);
|
|
@@ -36511,7 +36799,7 @@ function assertOwnedDaemonRuntime(options) {
|
|
|
36511
36799
|
throw new Error(`refusing to remove non-directory daemon releases at ${runtime.releasesDir}`);
|
|
36512
36800
|
}
|
|
36513
36801
|
for (const entry of readdirSync3(runtime.releasesDir, { withFileTypes: true })) {
|
|
36514
|
-
const releaseDir =
|
|
36802
|
+
const releaseDir = join15(runtime.releasesDir, entry.name);
|
|
36515
36803
|
const manifest = entry.isDirectory() && RUNTIME_RELEASE_RE.test(entry.name) ? readOwnedRuntimeManifest(releaseDir) : null;
|
|
36516
36804
|
if (!manifest) {
|
|
36517
36805
|
throw new Error(`refusing to remove unrecognized daemon release ${releaseDir}`);
|
|
@@ -36529,7 +36817,7 @@ function assertOwnedDaemonRuntime(options) {
|
|
|
36529
36817
|
}
|
|
36530
36818
|
const target = readlinkSync(runtime.currentLink);
|
|
36531
36819
|
const releaseName = basename3(target);
|
|
36532
|
-
if (target !==
|
|
36820
|
+
if (target !== join15("releases", releaseName) || !RUNTIME_RELEASE_RE.test(releaseName)) {
|
|
36533
36821
|
throw new Error(
|
|
36534
36822
|
`refusing to remove malformed daemon runtime selector ${runtime.currentLink}`
|
|
36535
36823
|
);
|
|
@@ -36557,7 +36845,7 @@ async function removeDaemonRuntime(options = {}) {
|
|
|
36557
36845
|
const control = daemonControlPaths(options);
|
|
36558
36846
|
const configDir = primConfigDirectory(options);
|
|
36559
36847
|
const service = process.platform === "darwin" ? launchdPaths(options) : void 0;
|
|
36560
|
-
const logPath = service?.logPath ??
|
|
36848
|
+
const logPath = service?.logPath ?? join15(configDir, "daemon.log");
|
|
36561
36849
|
const ownedArtifacts = [
|
|
36562
36850
|
runtime.runtimeDir,
|
|
36563
36851
|
control.launcher,
|
|
@@ -36565,8 +36853,8 @@ async function removeDaemonRuntime(options = {}) {
|
|
|
36565
36853
|
control.legacyDisabledMarker,
|
|
36566
36854
|
...service ? [service.plistPath] : [],
|
|
36567
36855
|
logPath,
|
|
36568
|
-
|
|
36569
|
-
|
|
36856
|
+
join15(configDir, "daemon-health.json"),
|
|
36857
|
+
join15(configDir, "client_instance_id")
|
|
36570
36858
|
];
|
|
36571
36859
|
if (!ownedArtifacts.some((path9) => lstatIfPresent3(path9))) {
|
|
36572
36860
|
return { changed: false, runtimePaths: runtime };
|
|
@@ -36610,11 +36898,11 @@ ${config.configDir ? `export PRIM_CONFIG_DIR=${shellQuote2(config.configDir)}
|
|
|
36610
36898
|
}
|
|
36611
36899
|
function readDaemonLauncher(path9) {
|
|
36612
36900
|
try {
|
|
36613
|
-
const content =
|
|
36901
|
+
const content = readFileSync12(path9, "utf8");
|
|
36614
36902
|
const encoded = /^# prim-daemon-launcher: ([A-Za-z0-9_-]+)$/mu.exec(content)?.[1];
|
|
36615
36903
|
if (!encoded) return null;
|
|
36616
36904
|
const value = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
|
|
36617
|
-
if (value.schemaVersion !== LAUNCHER_SCHEMA_VERSION || typeof value.nodePath !== "string" || typeof value.daemonPath !== "string" || typeof value.runtimeVersion !== "string" || value.apiUrl !== null && typeof value.apiUrl !== "string" || value.configDir !== void 0 && (typeof value.configDir !== "string" || !
|
|
36905
|
+
if (value.schemaVersion !== LAUNCHER_SCHEMA_VERSION || typeof value.nodePath !== "string" || typeof value.daemonPath !== "string" || typeof value.runtimeVersion !== "string" || value.apiUrl !== null && typeof value.apiUrl !== "string" || value.configDir !== void 0 && (typeof value.configDir !== "string" || !isAbsolute7(value.configDir)) || typeof value.revision !== "string") {
|
|
36618
36906
|
return null;
|
|
36619
36907
|
}
|
|
36620
36908
|
const config = {
|
|
@@ -36633,7 +36921,7 @@ function readDaemonLauncher(path9) {
|
|
|
36633
36921
|
function readUsableDaemonConfig(path9) {
|
|
36634
36922
|
const config = readDaemonLauncher(path9);
|
|
36635
36923
|
if (!config) return null;
|
|
36636
|
-
const manifest = readRuntimeManifest(
|
|
36924
|
+
const manifest = readRuntimeManifest(join15(dirname10(config.daemonPath), "manifest.json"));
|
|
36637
36925
|
try {
|
|
36638
36926
|
accessSync2(config.nodePath, constants4.X_OK);
|
|
36639
36927
|
return manifest?.version === config.runtimeVersion && manifest.nodePath === config.nodePath && manifest.daemonSha256 === sha256File(config.daemonPath) ? config : null;
|
|
@@ -36678,7 +36966,7 @@ function generateLaunchAgentPlist(config) {
|
|
|
36678
36966
|
`;
|
|
36679
36967
|
}
|
|
36680
36968
|
function launchdPaths(options = {}) {
|
|
36681
|
-
const home = options.homeDir ??
|
|
36969
|
+
const home = options.homeDir ?? homedir8();
|
|
36682
36970
|
const configDir = primConfigDirectory(options);
|
|
36683
36971
|
const uid = options.uid ?? process.getuid?.();
|
|
36684
36972
|
const label = options.label ?? LAUNCHD_LABEL;
|
|
@@ -36686,8 +36974,8 @@ function launchdPaths(options = {}) {
|
|
|
36686
36974
|
return {
|
|
36687
36975
|
domainTarget: `gui/${uid}`,
|
|
36688
36976
|
serviceTarget: `gui/${uid}/${label}`,
|
|
36689
|
-
plistPath:
|
|
36690
|
-
logPath:
|
|
36977
|
+
plistPath: join15(home, "Library", "LaunchAgents", `${label}.plist`),
|
|
36978
|
+
logPath: join15(configDir, "daemon.log")
|
|
36691
36979
|
};
|
|
36692
36980
|
}
|
|
36693
36981
|
var runLaunchctl = (args, timeoutMs2 = COMMAND_TIMEOUT_MS) => {
|
|
@@ -36720,7 +37008,7 @@ function getLaunchdService(options = {}) {
|
|
|
36720
37008
|
}
|
|
36721
37009
|
function atomicWrite3(path9, content, mode, validate3) {
|
|
36722
37010
|
try {
|
|
36723
|
-
if (
|
|
37011
|
+
if (readFileSync12(path9, "utf8") === content) {
|
|
36724
37012
|
chmodSync4(path9, mode);
|
|
36725
37013
|
validate3?.(path9, COMMAND_TIMEOUT_MS);
|
|
36726
37014
|
return false;
|
|
@@ -36762,14 +37050,14 @@ async function inspectDaemon(timeoutMs2) {
|
|
|
36762
37050
|
function canonicalProspectivePath(path9) {
|
|
36763
37051
|
const suffix = [];
|
|
36764
37052
|
let ancestor = resolve6(path9);
|
|
36765
|
-
while (!
|
|
37053
|
+
while (!existsSync11(ancestor)) {
|
|
36766
37054
|
const parent = dirname10(ancestor);
|
|
36767
37055
|
if (parent === ancestor) return resolve6(path9);
|
|
36768
37056
|
suffix.unshift(basename3(ancestor));
|
|
36769
37057
|
ancestor = parent;
|
|
36770
37058
|
}
|
|
36771
37059
|
try {
|
|
36772
|
-
return
|
|
37060
|
+
return join15(realpathSync3(ancestor), ...suffix);
|
|
36773
37061
|
} catch {
|
|
36774
37062
|
return resolve6(path9);
|
|
36775
37063
|
}
|
|
@@ -36784,10 +37072,10 @@ async function withDaemonLifecycleLock(operation, options = {}) {
|
|
|
36784
37072
|
);
|
|
36785
37073
|
}
|
|
36786
37074
|
async function stopVerifiedLegacyDaemon(options, deadlineMs, nowMs, sleep2) {
|
|
36787
|
-
const pidPath =
|
|
37075
|
+
const pidPath = join15(primConfigDirectory(options), "daemon.pid");
|
|
36788
37076
|
let pid;
|
|
36789
37077
|
try {
|
|
36790
|
-
pid = Number(
|
|
37078
|
+
pid = Number(readFileSync12(pidPath, "utf8").trim());
|
|
36791
37079
|
} catch {
|
|
36792
37080
|
throw new Error("an unsupervised daemon answered, but it has no verifiable pidfile");
|
|
36793
37081
|
}
|
|
@@ -36964,7 +37252,7 @@ async function waitForAbsence(context) {
|
|
|
36964
37252
|
}
|
|
36965
37253
|
function daemonExplicitlyDisabled(options = {}) {
|
|
36966
37254
|
const paths = daemonControlPaths(options);
|
|
36967
|
-
return
|
|
37255
|
+
return existsSync11(paths.disabledMarker) || existsSync11(paths.legacyDisabledMarker);
|
|
36968
37256
|
}
|
|
36969
37257
|
function setDaemonExplicitlyDisabled(disabled, options = {}) {
|
|
36970
37258
|
const paths = daemonControlPaths(options);
|
|
@@ -36987,7 +37275,7 @@ async function ensureMacDaemonLocked(options) {
|
|
|
36987
37275
|
let service = getLaunchdService({ ...options, runner });
|
|
36988
37276
|
if (!options.explicitlyStarted && daemonExplicitlyDisabled(options)) {
|
|
36989
37277
|
const control2 = daemonControlPaths(options);
|
|
36990
|
-
if (!
|
|
37278
|
+
if (!existsSync11(control2.disabledMarker)) {
|
|
36991
37279
|
atomicWrite3(control2.disabledMarker, "disabled by `prim daemon stop`\n", RUNTIME_FILE_MODE);
|
|
36992
37280
|
}
|
|
36993
37281
|
return {
|
|
@@ -37014,7 +37302,7 @@ async function ensureMacDaemonLocked(options) {
|
|
|
37014
37302
|
const configuredApiUrl = (options.env ?? process.env).PRIM_API_URL;
|
|
37015
37303
|
const apiUrl = configuredApiUrl ? normalizeApiUrl(configuredApiUrl) || void 0 : void 0;
|
|
37016
37304
|
const configDir = primConfigDirectory(options);
|
|
37017
|
-
const legacyDefaultConfigDir =
|
|
37305
|
+
const legacyDefaultConfigDir = join15(options.homeDir ?? homedir8(), ".config", "prim");
|
|
37018
37306
|
const launcherConfigDir = configDir === legacyDefaultConfigDir ? void 0 : configDir;
|
|
37019
37307
|
if (retainSelected && selected) {
|
|
37020
37308
|
const usable = readUsableDaemonConfig(control.launcher);
|
|
@@ -37049,7 +37337,7 @@ async function ensureMacDaemonLocked(options) {
|
|
|
37049
37337
|
const plist = generateLaunchAgentPlist({
|
|
37050
37338
|
launcherPath: control.launcher,
|
|
37051
37339
|
logPath: servicePaths.logPath,
|
|
37052
|
-
workingDirectory: options.homeDir ??
|
|
37340
|
+
workingDirectory: options.homeDir ?? homedir8(),
|
|
37053
37341
|
label: options.label
|
|
37054
37342
|
});
|
|
37055
37343
|
const plistChanged = atomicWrite3(
|
|
@@ -37272,9 +37560,9 @@ function formatStatusline(version, snapshot, resolveIngestionStatus, options = {
|
|
|
37272
37560
|
// src/commands/daemon.ts
|
|
37273
37561
|
var DAEMON_BIN = "prim-daemon-server";
|
|
37274
37562
|
var CONFIG_DIR = primConfigDirectory();
|
|
37275
|
-
var PID_PATH =
|
|
37276
|
-
var SOCK_PATH2 =
|
|
37277
|
-
var LOG_PATH =
|
|
37563
|
+
var PID_PATH = join16(CONFIG_DIR, "daemon.pid");
|
|
37564
|
+
var SOCK_PATH2 = join16(CONFIG_DIR, "sock");
|
|
37565
|
+
var LOG_PATH = join16(CONFIG_DIR, "daemon.log");
|
|
37278
37566
|
var CONFIG_DIR_MODE2 = 448;
|
|
37279
37567
|
var LOG_FILE_MODE = 384;
|
|
37280
37568
|
var STOP_TIMEOUT_MS = 5e3;
|
|
@@ -37312,10 +37600,10 @@ function daemonDegradedReason(snapshot) {
|
|
|
37312
37600
|
return "health checks have not recovered";
|
|
37313
37601
|
}
|
|
37314
37602
|
function readPidfile() {
|
|
37315
|
-
if (!
|
|
37603
|
+
if (!existsSync12(PID_PATH)) {
|
|
37316
37604
|
return null;
|
|
37317
37605
|
}
|
|
37318
|
-
const raw =
|
|
37606
|
+
const raw = readFileSync13(PID_PATH, "utf-8").trim();
|
|
37319
37607
|
const pid = Number(raw);
|
|
37320
37608
|
if (!Number.isInteger(pid) || pid <= 0) {
|
|
37321
37609
|
return null;
|
|
@@ -37340,10 +37628,10 @@ function spawnDaemon(options) {
|
|
|
37340
37628
|
return file ? spawn3(process.execPath, [file], options) : spawn3(DAEMON_BIN, [], options);
|
|
37341
37629
|
}
|
|
37342
37630
|
function openDaemonLog(configDir = CONFIG_DIR) {
|
|
37343
|
-
if (!
|
|
37631
|
+
if (!existsSync12(configDir)) {
|
|
37344
37632
|
mkdirSync9(configDir, { recursive: true, mode: CONFIG_DIR_MODE2 });
|
|
37345
37633
|
}
|
|
37346
|
-
return openSync3(
|
|
37634
|
+
return openSync3(join16(configDir, "daemon.log"), "a", LOG_FILE_MODE);
|
|
37347
37635
|
}
|
|
37348
37636
|
async function waitForReady() {
|
|
37349
37637
|
const deadline = Date.now() + READY_TIMEOUT_MS;
|
|
@@ -37477,7 +37765,7 @@ async function detachedDaemonStop() {
|
|
|
37477
37765
|
{},
|
|
37478
37766
|
{ timeoutMs: STATUS_PROBE_TIMEOUT_MS }
|
|
37479
37767
|
);
|
|
37480
|
-
if (
|
|
37768
|
+
if (existsSync12(PID_PATH) || existsSync12(SOCK_PATH2) || socketOwner) {
|
|
37481
37769
|
process.stderr.write(
|
|
37482
37770
|
`[prim] refusing to verify daemon absence: ${socketOwner ? `socket is owned by pid=${socketOwner.pid}` : "daemon artifacts remain"}
|
|
37483
37771
|
`
|
|
@@ -37509,7 +37797,7 @@ async function detachedDaemonStop() {
|
|
|
37509
37797
|
{},
|
|
37510
37798
|
{ timeoutMs: STATUS_PROBE_TIMEOUT_MS }
|
|
37511
37799
|
);
|
|
37512
|
-
if (socketOwner ||
|
|
37800
|
+
if (socketOwner || existsSync12(SOCK_PATH2)) {
|
|
37513
37801
|
process.stderr.write(
|
|
37514
37802
|
`[prim] refusing to clear stale pidfile: ${socketOwner ? `socket is owned by pid=${socketOwner.pid}` : "socket artifact remains"}
|
|
37515
37803
|
`
|
|
@@ -38298,6 +38586,8 @@ function authorLabel(row) {
|
|
|
38298
38586
|
return "Your Claude Code";
|
|
38299
38587
|
case "codex":
|
|
38300
38588
|
return "Your Codex";
|
|
38589
|
+
case "cursor":
|
|
38590
|
+
return "Your Cursor";
|
|
38301
38591
|
case "hermes":
|
|
38302
38592
|
return "Your Hermes";
|
|
38303
38593
|
case "chat":
|
|
@@ -39730,6 +40020,7 @@ function describeAudienceMember(member) {
|
|
|
39730
40020
|
return {
|
|
39731
40021
|
claude_code: "Claude Code agent",
|
|
39732
40022
|
codex: "Codex agent",
|
|
40023
|
+
cursor: "Cursor agent",
|
|
39733
40024
|
hermes: "Hermes agent"
|
|
39734
40025
|
}[member.agent] ?? terminalSafeLine(member.agent);
|
|
39735
40026
|
case "credential":
|
|
@@ -39941,7 +40232,7 @@ var UserScopeInputError = class extends Error {
|
|
|
39941
40232
|
}
|
|
39942
40233
|
};
|
|
39943
40234
|
var USER_SCOPE_ROLES = /* @__PURE__ */ new Set(["owner", "admin", "member"]);
|
|
39944
|
-
var USER_SCOPE_AGENTS = /* @__PURE__ */ new Set(["claude_code", "codex", "hermes"]);
|
|
40235
|
+
var USER_SCOPE_AGENTS = /* @__PURE__ */ new Set(["claude_code", "codex", "cursor", "hermes"]);
|
|
39945
40236
|
var USER_SCOPE_CREDENTIALS = /* @__PURE__ */ new Set(["workos_jwt", "workos_api_key", "service_token"]);
|
|
39946
40237
|
function requiredScopeValue(flag, value) {
|
|
39947
40238
|
const trimmed = value.trim();
|
|
@@ -39969,9 +40260,12 @@ function userScopeFromOptions(opts) {
|
|
|
39969
40260
|
for (const value of agents) {
|
|
39970
40261
|
const agent = requiredScopeValue("--for-agent", value);
|
|
39971
40262
|
if (!USER_SCOPE_AGENTS.has(agent)) {
|
|
39972
|
-
throw new UserScopeInputError("--for-agent must be claude_code, codex, or hermes");
|
|
40263
|
+
throw new UserScopeInputError("--for-agent must be claude_code, codex, cursor, or hermes");
|
|
39973
40264
|
}
|
|
39974
|
-
members.push({
|
|
40265
|
+
members.push({
|
|
40266
|
+
kind: "agent",
|
|
40267
|
+
agent
|
|
40268
|
+
});
|
|
39975
40269
|
}
|
|
39976
40270
|
for (const value of credentials) {
|
|
39977
40271
|
const credential = requiredScopeValue("--for-credential", value);
|
|
@@ -40178,7 +40472,7 @@ function registerDecisionsCommands(program3) {
|
|
|
40178
40472
|
[]
|
|
40179
40473
|
).option(
|
|
40180
40474
|
"--for-agent <agent>",
|
|
40181
|
-
"Include one agent: claude_code | codex | hermes (repeatable)",
|
|
40475
|
+
"Include one agent: claude_code | codex | cursor | hermes (repeatable)",
|
|
40182
40476
|
collectItem,
|
|
40183
40477
|
[]
|
|
40184
40478
|
).option(
|
|
@@ -40334,7 +40628,7 @@ function registerDecisionsCommands(program3) {
|
|
|
40334
40628
|
[]
|
|
40335
40629
|
).option(
|
|
40336
40630
|
"--for-agent <agent>",
|
|
40337
|
-
"Set one agent: claude_code | codex | hermes (repeatable)",
|
|
40631
|
+
"Set one agent: claude_code | codex | cursor | hermes (repeatable)",
|
|
40338
40632
|
collectItem,
|
|
40339
40633
|
[]
|
|
40340
40634
|
).option(
|
|
@@ -40414,7 +40708,7 @@ function registerDecisionsCommands(program3) {
|
|
|
40414
40708
|
}
|
|
40415
40709
|
|
|
40416
40710
|
// src/commands/doctor.ts
|
|
40417
|
-
import { existsSync as
|
|
40711
|
+
import { existsSync as existsSync15 } from "fs";
|
|
40418
40712
|
|
|
40419
40713
|
// src/decisions/feedback.ts
|
|
40420
40714
|
var FEEDBACK_PROTOCOL_VERSION = 2;
|
|
@@ -40559,17 +40853,17 @@ async function inspectJournalDelivery(buckets, options = {}) {
|
|
|
40559
40853
|
import {
|
|
40560
40854
|
appendFileSync,
|
|
40561
40855
|
closeSync as closeSync4,
|
|
40562
|
-
existsSync as
|
|
40856
|
+
existsSync as existsSync13,
|
|
40563
40857
|
fstatSync,
|
|
40564
40858
|
mkdirSync as mkdirSync10,
|
|
40565
40859
|
openSync as openSync4,
|
|
40566
40860
|
opendirSync,
|
|
40567
|
-
readFileSync as
|
|
40861
|
+
readFileSync as readFileSync14,
|
|
40568
40862
|
readSync,
|
|
40569
40863
|
readdirSync as readdirSync4
|
|
40570
40864
|
} from "fs";
|
|
40571
|
-
import { dirname as dirname11, join as
|
|
40572
|
-
var JOURNAL_DIR =
|
|
40865
|
+
import { dirname as dirname11, join as join17 } from "path";
|
|
40866
|
+
var JOURNAL_DIR = join17(primConfigDirectory(), "moves");
|
|
40573
40867
|
var JOURNAL_BASENAME = "journal.ndjson";
|
|
40574
40868
|
var JOURNAL_STATS_SAMPLE_BYTES = 64 * 1024;
|
|
40575
40869
|
var PENDING_STATS_MAX_FILES = 128;
|
|
@@ -40581,7 +40875,7 @@ function envSlug(apiUrl) {
|
|
|
40581
40875
|
return slug;
|
|
40582
40876
|
}
|
|
40583
40877
|
function currentEnvDir() {
|
|
40584
|
-
return
|
|
40878
|
+
return join17(JOURNAL_DIR, envSlug(getSiteUrl()));
|
|
40585
40879
|
}
|
|
40586
40880
|
function parseMoves(content) {
|
|
40587
40881
|
const moves = [];
|
|
@@ -40597,23 +40891,23 @@ function parseMoves(content) {
|
|
|
40597
40891
|
return moves;
|
|
40598
40892
|
}
|
|
40599
40893
|
function readMovesFromPath(path9) {
|
|
40600
|
-
if (!
|
|
40894
|
+
if (!existsSync13(path9)) {
|
|
40601
40895
|
return [];
|
|
40602
40896
|
}
|
|
40603
|
-
return parseMoves(
|
|
40897
|
+
return parseMoves(readFileSync14(path9, "utf-8"));
|
|
40604
40898
|
}
|
|
40605
40899
|
function listBuckets() {
|
|
40606
40900
|
const out = [];
|
|
40607
40901
|
const envDir = currentEnvDir();
|
|
40608
|
-
if (!
|
|
40902
|
+
if (!existsSync13(envDir)) {
|
|
40609
40903
|
return out;
|
|
40610
40904
|
}
|
|
40611
40905
|
for (const entry of readdirSync4(envDir, { withFileTypes: true })) {
|
|
40612
40906
|
if (!entry.isDirectory()) {
|
|
40613
40907
|
continue;
|
|
40614
40908
|
}
|
|
40615
|
-
const path9 =
|
|
40616
|
-
if (
|
|
40909
|
+
const path9 = join17(envDir, entry.name, JOURNAL_BASENAME);
|
|
40910
|
+
if (existsSync13(path9)) {
|
|
40617
40911
|
out.push({ bucket: entry.name, path: path9 });
|
|
40618
40912
|
}
|
|
40619
40913
|
}
|
|
@@ -40673,7 +40967,7 @@ function parseFlushingPid(name) {
|
|
|
40673
40967
|
return Number.isSafeInteger(pid) && pid > 0 ? pid : void 0;
|
|
40674
40968
|
}
|
|
40675
40969
|
function listFlushingInDir(dir, bucket, options = {}) {
|
|
40676
|
-
if (!
|
|
40970
|
+
if (!existsSync13(dir)) {
|
|
40677
40971
|
return [];
|
|
40678
40972
|
}
|
|
40679
40973
|
const out = [];
|
|
@@ -40687,7 +40981,7 @@ function listFlushingInDir(dir, bucket, options = {}) {
|
|
|
40687
40981
|
entry = entries.readSync();
|
|
40688
40982
|
continue;
|
|
40689
40983
|
}
|
|
40690
|
-
const path9 =
|
|
40984
|
+
const path9 = join17(dir, entry.name);
|
|
40691
40985
|
let sample;
|
|
40692
40986
|
try {
|
|
40693
40987
|
sample = sampleJournalFile(path9, remainingBytes);
|
|
@@ -40714,7 +41008,7 @@ function listFlushingInDir(dir, bucket, options = {}) {
|
|
|
40714
41008
|
}
|
|
40715
41009
|
function listFlushing(options = {}) {
|
|
40716
41010
|
const envDir = currentEnvDir();
|
|
40717
|
-
if (!
|
|
41011
|
+
if (!existsSync13(envDir)) {
|
|
40718
41012
|
return [];
|
|
40719
41013
|
}
|
|
40720
41014
|
const out = [];
|
|
@@ -40725,7 +41019,7 @@ function listFlushing(options = {}) {
|
|
|
40725
41019
|
break;
|
|
40726
41020
|
}
|
|
40727
41021
|
if (entry.isDirectory()) {
|
|
40728
|
-
const found = listFlushingInDir(
|
|
41022
|
+
const found = listFlushingInDir(join17(envDir, entry.name), entry.name, {
|
|
40729
41023
|
sampleBytes: remainingBytes,
|
|
40730
41024
|
maxFiles: maxFiles - out.length
|
|
40731
41025
|
});
|
|
@@ -40783,9 +41077,9 @@ function pendingJournalStats() {
|
|
|
40783
41077
|
}
|
|
40784
41078
|
|
|
40785
41079
|
// src/commands/hermes-install.ts
|
|
40786
|
-
import { existsSync as
|
|
40787
|
-
import { homedir as
|
|
40788
|
-
import { join as
|
|
41080
|
+
import { existsSync as existsSync14, readFileSync as readFileSync15, rmSync as rmSync6, statSync as statSync3 } from "fs";
|
|
41081
|
+
import { homedir as homedir9 } from "os";
|
|
41082
|
+
import { join as join18 } from "path";
|
|
40789
41083
|
|
|
40790
41084
|
// node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/browser/dist/nodes/identity.js
|
|
40791
41085
|
var ALIAS = /* @__PURE__ */ Symbol.for("yaml.alias");
|
|
@@ -47053,33 +47347,33 @@ function stringify3(value, replacer, options) {
|
|
|
47053
47347
|
}
|
|
47054
47348
|
|
|
47055
47349
|
// src/commands/hermes-install.ts
|
|
47056
|
-
var
|
|
47057
|
-
var
|
|
47350
|
+
var CAPTURE_BIN4 = "prim-hook";
|
|
47351
|
+
var GATE_BIN4 = "prim-pre-tool-use";
|
|
47058
47352
|
var POST_TOOL_USE_BIN3 = "prim-post-tool-use";
|
|
47059
|
-
var
|
|
47060
|
-
var
|
|
47353
|
+
var SESSION_START_BIN4 = "prim-session-start";
|
|
47354
|
+
var SESSION_END_BIN3 = "prim-session-end";
|
|
47061
47355
|
var HERMES_ARGS = "--agent hermes";
|
|
47062
47356
|
var EDIT_MATCHER = "write_file|patch";
|
|
47063
47357
|
var JSON_INDENT3 = 2;
|
|
47064
47358
|
var CONFIG_MODE = 384;
|
|
47065
|
-
var
|
|
47359
|
+
var PRIM_BINS4 = [CAPTURE_BIN4, GATE_BIN4, POST_TOOL_USE_BIN3, SESSION_START_BIN4, SESSION_END_BIN3];
|
|
47066
47360
|
function hermesHome() {
|
|
47067
|
-
return process.env.HERMES_HOME ??
|
|
47361
|
+
return process.env.HERMES_HOME ?? join18(homedir9(), ".hermes");
|
|
47068
47362
|
}
|
|
47069
47363
|
function configPath() {
|
|
47070
|
-
return
|
|
47364
|
+
return join18(hermesHome(), "config.yaml");
|
|
47071
47365
|
}
|
|
47072
47366
|
function legacyShimPath() {
|
|
47073
|
-
return
|
|
47367
|
+
return join18(hermesHome(), "agent-hooks", "prim-shim.sh");
|
|
47074
47368
|
}
|
|
47075
|
-
function
|
|
47369
|
+
function commandFor2(bin) {
|
|
47076
47370
|
return stableHookCommand(bin, HERMES_ARGS);
|
|
47077
47371
|
}
|
|
47078
47372
|
function legacyCommandFor(bin) {
|
|
47079
47373
|
return `"${legacyShimPath()}" ${bin} ${HERMES_ARGS}`;
|
|
47080
47374
|
}
|
|
47081
47375
|
function commandUsesBin(command, bin) {
|
|
47082
|
-
return command ===
|
|
47376
|
+
return command === commandFor2(bin) || command === legacyCommandFor(bin);
|
|
47083
47377
|
}
|
|
47084
47378
|
var CAPTURE_EVENTS2 = [
|
|
47085
47379
|
"on_session_start",
|
|
@@ -47091,13 +47385,13 @@ var CAPTURE_EVENTS2 = [
|
|
|
47091
47385
|
"subagent_stop"
|
|
47092
47386
|
];
|
|
47093
47387
|
var GATE_TIMEOUT_SECONDS = 10;
|
|
47094
|
-
var
|
|
47095
|
-
...CAPTURE_EVENTS2.map((event) => ({ event, bin:
|
|
47096
|
-
{ event: "pre_tool_call", matcher: EDIT_MATCHER, bin:
|
|
47388
|
+
var REGISTRATIONS3 = [
|
|
47389
|
+
...CAPTURE_EVENTS2.map((event) => ({ event, bin: CAPTURE_BIN4 })),
|
|
47390
|
+
{ event: "pre_tool_call", matcher: EDIT_MATCHER, bin: GATE_BIN4, timeout: GATE_TIMEOUT_SECONDS },
|
|
47097
47391
|
{ event: "post_tool_call", matcher: EDIT_MATCHER, bin: POST_TOOL_USE_BIN3 },
|
|
47098
47392
|
{ event: "post_approval_response", bin: POST_TOOL_USE_BIN3 },
|
|
47099
|
-
{ event: "on_session_start", bin:
|
|
47100
|
-
{ event: "on_session_end", bin:
|
|
47393
|
+
{ event: "on_session_start", bin: SESSION_START_BIN4 },
|
|
47394
|
+
{ event: "on_session_end", bin: SESSION_END_BIN3 }
|
|
47101
47395
|
];
|
|
47102
47396
|
function yamlValue(node) {
|
|
47103
47397
|
return typeof node?.toJSON === "function" ? node.toJSON?.() : node;
|
|
@@ -47107,7 +47401,7 @@ function hookEntry(node) {
|
|
|
47107
47401
|
return typeof value === "object" && value !== null && typeof value.command === "string" ? value : null;
|
|
47108
47402
|
}
|
|
47109
47403
|
function entryFor(reg) {
|
|
47110
|
-
const command =
|
|
47404
|
+
const command = commandFor2(reg.bin);
|
|
47111
47405
|
const entry = reg.matcher ? { matcher: reg.matcher, command } : { command };
|
|
47112
47406
|
if (reg.timeout !== void 0) {
|
|
47113
47407
|
entry.timeout = reg.timeout;
|
|
@@ -47129,7 +47423,7 @@ function ensureReg(list, reg, force) {
|
|
|
47129
47423
|
}
|
|
47130
47424
|
function applyInstall3(hooks, force) {
|
|
47131
47425
|
const next = { ...hooks };
|
|
47132
|
-
for (const reg of
|
|
47426
|
+
for (const reg of REGISTRATIONS3) {
|
|
47133
47427
|
next[reg.event] = ensureReg(next[reg.event] ?? [], reg, force);
|
|
47134
47428
|
}
|
|
47135
47429
|
return next;
|
|
@@ -47138,7 +47432,7 @@ function applyUninstall3(hooks) {
|
|
|
47138
47432
|
const next = {};
|
|
47139
47433
|
for (const [event, list] of Object.entries(hooks)) {
|
|
47140
47434
|
let kept = list;
|
|
47141
|
-
for (const bin of
|
|
47435
|
+
for (const bin of PRIM_BINS4) {
|
|
47142
47436
|
kept = stripBin(kept, bin);
|
|
47143
47437
|
}
|
|
47144
47438
|
if (kept.length > 0) {
|
|
@@ -47148,15 +47442,15 @@ function applyUninstall3(hooks) {
|
|
|
47148
47442
|
return next;
|
|
47149
47443
|
}
|
|
47150
47444
|
function isGateInstalled3(hooks) {
|
|
47151
|
-
return (hooks.pre_tool_call ?? []).some((e) => commandUsesBin(e.command,
|
|
47445
|
+
return (hooks.pre_tool_call ?? []).some((e) => commandUsesBin(e.command, GATE_BIN4));
|
|
47152
47446
|
}
|
|
47153
47447
|
function isCaptureInstalled(hooks) {
|
|
47154
47448
|
return CAPTURE_EVENTS2.some(
|
|
47155
|
-
(event) => (hooks[event] ?? []).some((e) => commandUsesBin(e.command,
|
|
47449
|
+
(event) => (hooks[event] ?? []).some((e) => commandUsesBin(e.command, CAPTURE_BIN4))
|
|
47156
47450
|
);
|
|
47157
47451
|
}
|
|
47158
47452
|
function entryUsesOwnedBin(entry) {
|
|
47159
|
-
return
|
|
47453
|
+
return PRIM_BINS4.some(
|
|
47160
47454
|
(bin) => commandUsesBin(entry.command, bin) || commandMatchesBin(entry.command, bin)
|
|
47161
47455
|
);
|
|
47162
47456
|
}
|
|
@@ -47171,21 +47465,21 @@ function hasAnyHookRegistration3(hooks) {
|
|
|
47171
47465
|
function hookRuntimeResolutions3(hooks) {
|
|
47172
47466
|
const resolutions = hookCommandResolutions(
|
|
47173
47467
|
Object.values(hooks).flatMap((entries) => entries.map((entry) => entry.command)),
|
|
47174
|
-
|
|
47468
|
+
PRIM_BINS4
|
|
47175
47469
|
);
|
|
47176
47470
|
for (const entries of Object.values(hooks)) {
|
|
47177
47471
|
for (const entry of entries) {
|
|
47178
|
-
for (const bin of
|
|
47472
|
+
for (const bin of PRIM_BINS4) {
|
|
47179
47473
|
if (entry.command === legacyCommandFor(bin)) resolutions.push({ kind: "legacy_path" });
|
|
47180
47474
|
}
|
|
47181
47475
|
}
|
|
47182
47476
|
}
|
|
47183
47477
|
return resolutions;
|
|
47184
47478
|
}
|
|
47185
|
-
function
|
|
47479
|
+
function inspectHookRuntimeResolutions4() {
|
|
47186
47480
|
const path9 = configPath();
|
|
47187
|
-
if (!
|
|
47188
|
-
return hookRuntimeResolutions3(readHooks(parseHermesDocument(
|
|
47481
|
+
if (!existsSync14(path9)) return [];
|
|
47482
|
+
return hookRuntimeResolutions3(readHooks(parseHermesDocument(readFileSync15(path9, "utf8"))));
|
|
47189
47483
|
}
|
|
47190
47484
|
function entryMatchesRegistration3(owned, registration) {
|
|
47191
47485
|
const expected = entryFor(registration);
|
|
@@ -47193,7 +47487,7 @@ function entryMatchesRegistration3(owned, registration) {
|
|
|
47193
47487
|
}
|
|
47194
47488
|
function hasCompleteHookRegistration3(hooks) {
|
|
47195
47489
|
const owned = ownedRegistrationEntries3(hooks);
|
|
47196
|
-
return owned.length ===
|
|
47490
|
+
return owned.length === REGISTRATIONS3.length && REGISTRATIONS3.every(
|
|
47197
47491
|
(registration) => owned.filter((entry) => entryMatchesRegistration3(entry, registration)).length === 1
|
|
47198
47492
|
);
|
|
47199
47493
|
}
|
|
@@ -47269,7 +47563,7 @@ function serializeHooks(hooks) {
|
|
|
47269
47563
|
return stringify3({ hooks }, { lineWidth: 0 });
|
|
47270
47564
|
}
|
|
47271
47565
|
function isPrimEntry(entry) {
|
|
47272
|
-
return
|
|
47566
|
+
return PRIM_BINS4.some((bin) => commandUsesBin(entry.command, bin));
|
|
47273
47567
|
}
|
|
47274
47568
|
function entryKey(entry) {
|
|
47275
47569
|
return JSON.stringify(entry);
|
|
@@ -47454,11 +47748,11 @@ function assertMergeValid(before, after, expectedHooks) {
|
|
|
47454
47748
|
}
|
|
47455
47749
|
}
|
|
47456
47750
|
function readConfigSnapshot(path9) {
|
|
47457
|
-
if (!
|
|
47751
|
+
if (!existsSync14(path9)) return { exists: false, mode: CONFIG_MODE, raw: "" };
|
|
47458
47752
|
return {
|
|
47459
47753
|
exists: true,
|
|
47460
47754
|
mode: statSync3(path9).mode & 511,
|
|
47461
|
-
raw:
|
|
47755
|
+
raw: readFileSync15(path9, "utf8")
|
|
47462
47756
|
};
|
|
47463
47757
|
}
|
|
47464
47758
|
var CONCURRENT_CONFIG_MESSAGE = "Hermes config changed during update; concurrent changes were preserved, retry the command";
|
|
@@ -47467,7 +47761,7 @@ function writeHermesConfigSnapshot(path9, before, after, expectedHooks) {
|
|
|
47467
47761
|
ensureParent: true,
|
|
47468
47762
|
mode: before.mode,
|
|
47469
47763
|
validate(temporaryPath) {
|
|
47470
|
-
const flushed =
|
|
47764
|
+
const flushed = readFileSync15(temporaryPath, "utf8");
|
|
47471
47765
|
if (!mergePreservesHermesSemantics(before.raw, flushed, expectedHooks)) {
|
|
47472
47766
|
throw new Error(INVALID_MERGE_MESSAGE);
|
|
47473
47767
|
}
|
|
@@ -47490,7 +47784,7 @@ function autoAcceptOf(raw) {
|
|
|
47490
47784
|
function readHooksFromRaw(raw) {
|
|
47491
47785
|
return readHooks(parseHermesDocument(raw));
|
|
47492
47786
|
}
|
|
47493
|
-
function
|
|
47787
|
+
function performInstall4(opts) {
|
|
47494
47788
|
(opts.stageRuntime ?? stageHookRuntime)();
|
|
47495
47789
|
const path9 = configPath();
|
|
47496
47790
|
const snapshot = readConfigSnapshot(path9);
|
|
@@ -47518,9 +47812,9 @@ function performInstall3(opts) {
|
|
|
47518
47812
|
changed
|
|
47519
47813
|
};
|
|
47520
47814
|
}
|
|
47521
|
-
function
|
|
47815
|
+
function performUninstall4() {
|
|
47522
47816
|
const path9 = configPath();
|
|
47523
|
-
if (!
|
|
47817
|
+
if (!existsSync14(path9)) {
|
|
47524
47818
|
removeLegacyShim();
|
|
47525
47819
|
return { path: path9, gate: false, capture: false, autoAccept: false, changed: false };
|
|
47526
47820
|
}
|
|
@@ -47543,9 +47837,9 @@ function performUninstall3() {
|
|
|
47543
47837
|
changed
|
|
47544
47838
|
};
|
|
47545
47839
|
}
|
|
47546
|
-
function
|
|
47840
|
+
function performStatus4() {
|
|
47547
47841
|
const path9 = configPath();
|
|
47548
|
-
const raw =
|
|
47842
|
+
const raw = existsSync14(path9) ? readFileSync15(path9, "utf8") : "";
|
|
47549
47843
|
const hooks = raw ? readHooks(parseHermesDocument(raw)) : {};
|
|
47550
47844
|
return {
|
|
47551
47845
|
path: path9,
|
|
@@ -47569,7 +47863,7 @@ function registerHermesCommands(program3) {
|
|
|
47569
47863
|
const hermes = program3.command("hermes").description("Manage the prim Hermes Agent integration (capture, gate, ingest, presence)");
|
|
47570
47864
|
hermes.command("install").description("Register the prim hooks in Hermes's ~/.hermes/config.yaml").option("--scope <scope>", "user (default; Hermes config is global-only)").option("--force", "Replace any drifted prim hook entries").option("--auto-accept", "Also set hooks_auto_accept: true so the hooks need no TTY consent").action((opts) => {
|
|
47571
47865
|
rejectProjectScope(opts.scope);
|
|
47572
|
-
const result =
|
|
47866
|
+
const result = performInstall4({
|
|
47573
47867
|
force: opts.force ?? false,
|
|
47574
47868
|
autoAccept: opts.autoAccept ?? false
|
|
47575
47869
|
});
|
|
@@ -47580,14 +47874,14 @@ function registerHermesCommands(program3) {
|
|
|
47580
47874
|
console.log(JSON.stringify(result, null, JSON_INDENT3));
|
|
47581
47875
|
});
|
|
47582
47876
|
hermes.command("uninstall").description("Remove all prim hooks from Hermes's ~/.hermes/config.yaml").action(() => {
|
|
47583
|
-
const result =
|
|
47877
|
+
const result = performUninstall4();
|
|
47584
47878
|
console.error(
|
|
47585
47879
|
result.changed ? `[prim] prim hooks removed from ${result.path}` : `[prim] no prim hooks to remove at ${result.path} (nothing changed)`
|
|
47586
47880
|
);
|
|
47587
47881
|
console.log(JSON.stringify(result, null, JSON_INDENT3));
|
|
47588
47882
|
});
|
|
47589
47883
|
hermes.command("status").description("Report whether each prim surface (gate, capture) is installed").action(() => {
|
|
47590
|
-
const result =
|
|
47884
|
+
const result = performStatus4();
|
|
47591
47885
|
const mark = (b) => b ? "\u2713" : "\u2717";
|
|
47592
47886
|
console.error(
|
|
47593
47887
|
`[prim] hermes: gate ${mark(result.gate)} \xB7 capture ${mark(result.capture)} (${result.path})`
|
|
@@ -47635,7 +47929,7 @@ function checkAuth() {
|
|
|
47635
47929
|
return classifyAuthCredential(
|
|
47636
47930
|
credential,
|
|
47637
47931
|
storedCredential ? getTokenExpiresAt() : void 0,
|
|
47638
|
-
storedCredential &&
|
|
47932
|
+
storedCredential && existsSync15(REFRESH_TOKEN_PATH)
|
|
47639
47933
|
);
|
|
47640
47934
|
}
|
|
47641
47935
|
function classifyDaemonHealth(snapshot, options = {}) {
|
|
@@ -47979,6 +48273,34 @@ function classifyCodexHooks(statuses) {
|
|
|
47979
48273
|
detail: "installed; Codex trust is not machine-readable \u2014 verify with `/hooks`"
|
|
47980
48274
|
};
|
|
47981
48275
|
}
|
|
48276
|
+
function classifyCursorHooks(statuses) {
|
|
48277
|
+
const installed = statuses.filter((status) => status.present);
|
|
48278
|
+
if (installed.length === 0)
|
|
48279
|
+
return { name: "cursor-hooks", status: "ok", detail: "not installed" };
|
|
48280
|
+
if (installed.some((status) => !status.complete)) {
|
|
48281
|
+
return {
|
|
48282
|
+
name: "cursor-hooks",
|
|
48283
|
+
status: "fail",
|
|
48284
|
+
detail: "incomplete or drifted native lifecycle \u2014 run `prim cursor install --force`"
|
|
48285
|
+
};
|
|
48286
|
+
}
|
|
48287
|
+
const user = statuses.find((status) => status.footer !== void 0);
|
|
48288
|
+
if (user?.present && user.footer === false && !user.footerPreservedCustom) {
|
|
48289
|
+
return {
|
|
48290
|
+
name: "cursor-hooks",
|
|
48291
|
+
status: "fail",
|
|
48292
|
+
detail: "native lifecycle ready but Cursor CLI footer is missing \u2014 run `prim cursor install --scope user --force`"
|
|
48293
|
+
};
|
|
48294
|
+
}
|
|
48295
|
+
if (statuses.some((status) => status.footerPreservedCustom)) {
|
|
48296
|
+
return {
|
|
48297
|
+
name: "cursor-hooks",
|
|
48298
|
+
status: "warn",
|
|
48299
|
+
detail: "native lifecycle ready; custom Cursor CLI footer preserved"
|
|
48300
|
+
};
|
|
48301
|
+
}
|
|
48302
|
+
return { name: "cursor-hooks", status: "ok", detail: "complete native lifecycle ready" };
|
|
48303
|
+
}
|
|
47982
48304
|
function classifyHermesHooks(status) {
|
|
47983
48305
|
if (!status.present) {
|
|
47984
48306
|
return { name: "hermes-hooks", status: "ok", detail: "not installed" };
|
|
@@ -48010,7 +48332,18 @@ function checkAgentHooks() {
|
|
|
48010
48332
|
});
|
|
48011
48333
|
}
|
|
48012
48334
|
try {
|
|
48013
|
-
|
|
48335
|
+
const status = performStatus3();
|
|
48336
|
+
checks.push(classifyCursorHooks([status.project, status.user]));
|
|
48337
|
+
} catch (error) {
|
|
48338
|
+
const detail = boundedHealthError(error instanceof Error ? error.message : String(error));
|
|
48339
|
+
checks.push({
|
|
48340
|
+
name: "cursor-hooks",
|
|
48341
|
+
status: "fail",
|
|
48342
|
+
detail: detail ?? "hook configuration is unreadable"
|
|
48343
|
+
});
|
|
48344
|
+
}
|
|
48345
|
+
try {
|
|
48346
|
+
checks.push(classifyHermesHooks(performStatus4()));
|
|
48014
48347
|
} catch (error) {
|
|
48015
48348
|
const detail = boundedHealthError(error instanceof Error ? error.message : String(error));
|
|
48016
48349
|
checks.push({
|
|
@@ -48120,7 +48453,8 @@ function checkHookRuntime() {
|
|
|
48120
48453
|
[
|
|
48121
48454
|
...inspectHookRuntimeResolutions(),
|
|
48122
48455
|
...inspectHookRuntimeResolutions2(),
|
|
48123
|
-
...inspectHookRuntimeResolutions3()
|
|
48456
|
+
...inspectHookRuntimeResolutions3(),
|
|
48457
|
+
...inspectHookRuntimeResolutions4()
|
|
48124
48458
|
],
|
|
48125
48459
|
inspectHookRuntime,
|
|
48126
48460
|
packageVersion
|
|
@@ -48255,12 +48589,12 @@ function registerDoctorCommands(program3) {
|
|
|
48255
48589
|
}
|
|
48256
48590
|
|
|
48257
48591
|
// src/commands/moves.ts
|
|
48258
|
-
import { existsSync as
|
|
48259
|
-
import { join as
|
|
48592
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync12, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
|
|
48593
|
+
import { join as join21 } from "path";
|
|
48260
48594
|
|
|
48261
48595
|
// src/flusher.ts
|
|
48262
48596
|
import { createReadStream, renameSync as renameSync6, unlinkSync as unlinkSync4 } from "fs";
|
|
48263
|
-
import { dirname as dirname13, join as
|
|
48597
|
+
import { dirname as dirname13, join as join20 } from "path";
|
|
48264
48598
|
|
|
48265
48599
|
// src/dead-letter.ts
|
|
48266
48600
|
import { createHash as createHash9, randomBytes as randomBytes6 } from "crypto";
|
|
@@ -48268,7 +48602,7 @@ import {
|
|
|
48268
48602
|
constants as constants5,
|
|
48269
48603
|
chmodSync as chmodSync5,
|
|
48270
48604
|
closeSync as closeSync5,
|
|
48271
|
-
existsSync as
|
|
48605
|
+
existsSync as existsSync16,
|
|
48272
48606
|
fchmodSync as fchmodSync3,
|
|
48273
48607
|
fsyncSync as fsyncSync3,
|
|
48274
48608
|
mkdirSync as mkdirSync11,
|
|
@@ -48277,16 +48611,16 @@ import {
|
|
|
48277
48611
|
rmSync as rmSync7,
|
|
48278
48612
|
writeFileSync as writeFileSync8
|
|
48279
48613
|
} from "fs";
|
|
48280
|
-
import { dirname as dirname12, join as
|
|
48614
|
+
import { dirname as dirname12, join as join19 } from "path";
|
|
48281
48615
|
var DIRECTORY_MODE3 = 448;
|
|
48282
48616
|
var FILE_MODE2 = 384;
|
|
48283
48617
|
var DEAD_LETTER_DIRNAME = "dead-letter";
|
|
48284
48618
|
function deadLetterDirectoryForRotation(flushingPath) {
|
|
48285
|
-
return
|
|
48619
|
+
return join19(dirname12(flushingPath), DEAD_LETTER_DIRNAME);
|
|
48286
48620
|
}
|
|
48287
48621
|
function deadLetterPathForRawLine(flushingPath, rawLine) {
|
|
48288
48622
|
const quarantineId = createHash9("sha256").update(rawLine).digest("hex");
|
|
48289
|
-
return
|
|
48623
|
+
return join19(deadLetterDirectoryForRotation(flushingPath), `raw-${quarantineId}.json`);
|
|
48290
48624
|
}
|
|
48291
48625
|
function ensureDeadLetterDirectory(flushingPath, persistDirectory) {
|
|
48292
48626
|
const directory = deadLetterDirectoryForRotation(flushingPath);
|
|
@@ -48296,11 +48630,11 @@ function ensureDeadLetterDirectory(flushingPath, persistDirectory) {
|
|
|
48296
48630
|
return directory;
|
|
48297
48631
|
}
|
|
48298
48632
|
function persistDeadLetter(directory, path9, quarantineId, record2, persistDirectory) {
|
|
48299
|
-
if (
|
|
48633
|
+
if (existsSync16(path9)) {
|
|
48300
48634
|
persistDirectory(directory);
|
|
48301
48635
|
return;
|
|
48302
48636
|
}
|
|
48303
|
-
const temporaryPath =
|
|
48637
|
+
const temporaryPath = join19(
|
|
48304
48638
|
directory,
|
|
48305
48639
|
`.${quarantineId}.${String(process.pid)}.${randomBytes6(8).toString("hex")}.tmp`
|
|
48306
48640
|
);
|
|
@@ -48332,7 +48666,7 @@ function quarantineMove(flushingPath, move, reason, now = Date.now, options = {}
|
|
|
48332
48666
|
reason,
|
|
48333
48667
|
move
|
|
48334
48668
|
};
|
|
48335
|
-
const path9 =
|
|
48669
|
+
const path9 = join19(directory, `${record2.quarantineId}.json`);
|
|
48336
48670
|
persistDeadLetter(directory, path9, record2.quarantineId, record2, persistDirectory);
|
|
48337
48671
|
return record2;
|
|
48338
48672
|
}
|
|
@@ -48644,7 +48978,7 @@ async function flushOnce() {
|
|
|
48644
48978
|
return inspection.retainedBuckets.length > 0 ? { flushed: total, quarantined, retained: inspection.retainedBuckets } : { flushed: total, quarantined };
|
|
48645
48979
|
}
|
|
48646
48980
|
var flushInFlight;
|
|
48647
|
-
var FLUSH_LOCK_PATH =
|
|
48981
|
+
var FLUSH_LOCK_PATH = join20(dirname13(JOURNAL_DIR), ".flush.lock");
|
|
48648
48982
|
var FLUSH_LOCK_TIMEOUT_MS = 250;
|
|
48649
48983
|
function isFlushLockContended(error) {
|
|
48650
48984
|
return error instanceof Error && error.message.startsWith("timed out waiting for file lock");
|
|
@@ -48778,19 +49112,19 @@ function registerMovesCommands(program3) {
|
|
|
48778
49112
|
}
|
|
48779
49113
|
});
|
|
48780
49114
|
moves.command("bind").description("Pin the current directory to an org via .prim/workspace.json").requiredOption("--orgId <orgId>", "Convex organization id").action((opts) => {
|
|
48781
|
-
const dir =
|
|
48782
|
-
if (!
|
|
49115
|
+
const dir = join21(process.cwd(), ".prim");
|
|
49116
|
+
if (!existsSync17(dir)) {
|
|
48783
49117
|
mkdirSync12(dir, { recursive: true, mode: DIR_MODE });
|
|
48784
49118
|
}
|
|
48785
|
-
const file =
|
|
49119
|
+
const file = join21(process.cwd(), WORKSPACE_FILE);
|
|
48786
49120
|
writeFileSync9(file, JSON.stringify({ orgId: opts.orgId, boundAt: Date.now() }, null, 2), {
|
|
48787
49121
|
mode: FILE_MODE3
|
|
48788
49122
|
});
|
|
48789
49123
|
console.log(`[prim] bound ${process.cwd()} to org ${opts.orgId}`);
|
|
48790
49124
|
});
|
|
48791
49125
|
moves.command("drop").description("Remove the .prim/workspace.json binding from the cwd").action(() => {
|
|
48792
|
-
const file =
|
|
48793
|
-
if (!
|
|
49126
|
+
const file = join21(process.cwd(), WORKSPACE_FILE);
|
|
49127
|
+
if (!existsSync17(file)) {
|
|
48794
49128
|
console.log("[prim] no workspace binding in cwd");
|
|
48795
49129
|
return;
|
|
48796
49130
|
}
|
|
@@ -48881,31 +49215,31 @@ function registerReconcileCommands(program3) {
|
|
|
48881
49215
|
|
|
48882
49216
|
// src/commands/session.ts
|
|
48883
49217
|
import {
|
|
48884
|
-
existsSync as
|
|
49218
|
+
existsSync as existsSync19,
|
|
48885
49219
|
mkdirSync as mkdirSync13,
|
|
48886
|
-
readFileSync as
|
|
49220
|
+
readFileSync as readFileSync17,
|
|
48887
49221
|
readdirSync as readdirSync5,
|
|
48888
49222
|
unlinkSync as unlinkSync6,
|
|
48889
49223
|
writeFileSync as writeFileSync10
|
|
48890
49224
|
} from "fs";
|
|
48891
|
-
import { join as
|
|
49225
|
+
import { join as join23 } from "path";
|
|
48892
49226
|
|
|
48893
49227
|
// src/binding.ts
|
|
48894
|
-
import { existsSync as
|
|
48895
|
-
import { dirname as dirname14, join as
|
|
49228
|
+
import { existsSync as existsSync18, readFileSync as readFileSync16 } from "fs";
|
|
49229
|
+
import { dirname as dirname14, join as join22 } from "path";
|
|
48896
49230
|
var PRIM_CONFIG_DIR = primConfigDirectory();
|
|
48897
|
-
var SESSIONS_DIR =
|
|
49231
|
+
var SESSIONS_DIR = join22(PRIM_CONFIG_DIR, "sessions");
|
|
48898
49232
|
|
|
48899
49233
|
// src/commands/session.ts
|
|
48900
49234
|
var DIR_MODE2 = 448;
|
|
48901
49235
|
var FILE_MODE4 = 384;
|
|
48902
49236
|
function ensureDir() {
|
|
48903
|
-
if (!
|
|
49237
|
+
if (!existsSync19(SESSIONS_DIR)) {
|
|
48904
49238
|
mkdirSync13(SESSIONS_DIR, { recursive: true, mode: DIR_MODE2 });
|
|
48905
49239
|
}
|
|
48906
49240
|
}
|
|
48907
49241
|
function markerPath(sessionId) {
|
|
48908
|
-
return
|
|
49242
|
+
return join23(SESSIONS_DIR, `${sessionId}.json`);
|
|
48909
49243
|
}
|
|
48910
49244
|
function registerSessionCommands(program3) {
|
|
48911
49245
|
const session = program3.command("session").description("Decision Event Pipeline \u2014 session binding markers");
|
|
@@ -48921,7 +49255,7 @@ function registerSessionCommands(program3) {
|
|
|
48921
49255
|
console.log(`[prim] session ${sessionId} bound to org ${opts.orgId}`);
|
|
48922
49256
|
});
|
|
48923
49257
|
session.command("list").description("List active session markers").action(() => {
|
|
48924
|
-
if (!
|
|
49258
|
+
if (!existsSync19(SESSIONS_DIR)) {
|
|
48925
49259
|
console.log("[prim] no session markers");
|
|
48926
49260
|
return;
|
|
48927
49261
|
}
|
|
@@ -48933,7 +49267,7 @@ function registerSessionCommands(program3) {
|
|
|
48933
49267
|
for (const f of files) {
|
|
48934
49268
|
const sessionId = f.replace(/\.json$/, "");
|
|
48935
49269
|
try {
|
|
48936
|
-
const m = JSON.parse(
|
|
49270
|
+
const m = JSON.parse(readFileSync17(join23(SESSIONS_DIR, f), "utf-8"));
|
|
48937
49271
|
console.log(`${sessionId} org=${m.orgId}`);
|
|
48938
49272
|
} catch {
|
|
48939
49273
|
}
|
|
@@ -48941,7 +49275,7 @@ function registerSessionCommands(program3) {
|
|
|
48941
49275
|
});
|
|
48942
49276
|
session.command("drop <sessionId>").description("Remove a session marker").action((sessionId) => {
|
|
48943
49277
|
const p = markerPath(sessionId);
|
|
48944
|
-
if (!
|
|
49278
|
+
if (!existsSync19(p)) {
|
|
48945
49279
|
console.log(`[prim] no marker for session ${sessionId}`);
|
|
48946
49280
|
return;
|
|
48947
49281
|
}
|
|
@@ -48952,13 +49286,14 @@ function registerSessionCommands(program3) {
|
|
|
48952
49286
|
|
|
48953
49287
|
// src/commands/setup.ts
|
|
48954
49288
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
48955
|
-
import { existsSync as
|
|
48956
|
-
import { join as
|
|
49289
|
+
import { existsSync as existsSync20, readFileSync as readFileSync18 } from "fs";
|
|
49290
|
+
import { join as join24 } from "path";
|
|
48957
49291
|
var EXIT_INCOMPLETE = 1;
|
|
48958
49292
|
var EXIT_USAGE3 = 2;
|
|
48959
49293
|
var SESSION_LABELS = {
|
|
48960
49294
|
claude: "Claude Code integration",
|
|
48961
49295
|
codex: "Codex integration",
|
|
49296
|
+
cursor: "Cursor integration",
|
|
48962
49297
|
hermes: "Hermes integration"
|
|
48963
49298
|
};
|
|
48964
49299
|
function planSetupSteps(opts) {
|
|
@@ -49034,8 +49369,8 @@ function detectProjectConflicts(agent, run) {
|
|
|
49034
49369
|
}
|
|
49035
49370
|
try {
|
|
49036
49371
|
const root = gitToplevel();
|
|
49037
|
-
const preCommit = root &&
|
|
49038
|
-
if (preCommit &&
|
|
49372
|
+
const preCommit = root && join24(root, ".git", "hooks", "pre-commit");
|
|
49373
|
+
if (preCommit && existsSync20(preCommit) && readFileSync18(preCommit, "utf-8").includes("prim-pre-commit")) {
|
|
49039
49374
|
conflicts.push(CONFLICT_HOOKS);
|
|
49040
49375
|
}
|
|
49041
49376
|
} catch {
|
|
@@ -49053,6 +49388,9 @@ function detectAgent(env4) {
|
|
|
49053
49388
|
if (env4.HERMES_INTERACTIVE) {
|
|
49054
49389
|
return "hermes";
|
|
49055
49390
|
}
|
|
49391
|
+
if (env4.CURSOR_AGENT) {
|
|
49392
|
+
return "cursor";
|
|
49393
|
+
}
|
|
49056
49394
|
return "claude";
|
|
49057
49395
|
}
|
|
49058
49396
|
function resolveAgent(agentFlag, env4) {
|
|
@@ -49074,7 +49412,7 @@ function parseSetupAuthStatus(result) {
|
|
|
49074
49412
|
function registerSetupCommand(program3, dependencies = {}) {
|
|
49075
49413
|
program3.command("setup").description(
|
|
49076
49414
|
"Install everything in one shot (auth, session + git hooks, daemon, skill, welcome)"
|
|
49077
|
-
).option("--agent <agent>", "claude, codex, or hermes (auto-detected when omitted)").option(
|
|
49415
|
+
).option("--agent <agent>", "claude, codex, cursor, or hermes (auto-detected when omitted)").option(
|
|
49078
49416
|
"--scope <scope>",
|
|
49079
49417
|
"user (default \u2014 install once for every repo) or project (this repo only)",
|
|
49080
49418
|
"user"
|
|
@@ -49083,9 +49421,9 @@ function registerSetupCommand(program3, dependencies = {}) {
|
|
|
49083
49421
|
"with the default user scope, remove any project-scoped prim config in this repo (else just warn)"
|
|
49084
49422
|
).option("--no-daemon", "stop and disable the companion daemon").action((opts) => {
|
|
49085
49423
|
const { agent: agentInput, detected } = resolveAgent(opts.agent, process.env);
|
|
49086
|
-
if (agentInput !== "claude" && agentInput !== "codex" && agentInput !== "hermes") {
|
|
49424
|
+
if (agentInput !== "claude" && agentInput !== "codex" && agentInput !== "cursor" && agentInput !== "hermes") {
|
|
49087
49425
|
process.stderr.write(
|
|
49088
|
-
`[prim] unknown --agent "${agentInput}" (expected claude, codex, or hermes)
|
|
49426
|
+
`[prim] unknown --agent "${agentInput}" (expected claude, codex, cursor, or hermes)
|
|
49089
49427
|
`
|
|
49090
49428
|
);
|
|
49091
49429
|
(dependencies.exit ?? process.exit)(EXIT_USAGE3);
|
|
@@ -49196,18 +49534,22 @@ function registerSetupCommand(program3, dependencies = {}) {
|
|
|
49196
49534
|
}
|
|
49197
49535
|
|
|
49198
49536
|
// src/commands/skill.ts
|
|
49537
|
+
import { createHash as createHash11 } from "crypto";
|
|
49199
49538
|
import {
|
|
49200
49539
|
constants as constants7,
|
|
49201
49540
|
closeSync as closeSync7,
|
|
49202
|
-
existsSync as
|
|
49541
|
+
existsSync as existsSync22,
|
|
49203
49542
|
fstatSync as fstatSync3,
|
|
49204
49543
|
lstatSync as lstatSync7,
|
|
49205
49544
|
openSync as openSync7,
|
|
49206
|
-
readFileSync as
|
|
49207
|
-
readSync as readSync3
|
|
49545
|
+
readFileSync as readFileSync20,
|
|
49546
|
+
readSync as readSync3,
|
|
49547
|
+
readdirSync as readdirSync7,
|
|
49548
|
+
rmdirSync as rmdirSync2,
|
|
49549
|
+
unlinkSync as unlinkSync7
|
|
49208
49550
|
} from "fs";
|
|
49209
|
-
import { homedir as
|
|
49210
|
-
import { dirname as dirname16, join as
|
|
49551
|
+
import { homedir as homedir11 } from "os";
|
|
49552
|
+
import { dirname as dirname16, join as join27, resolve as resolve8 } from "path";
|
|
49211
49553
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
49212
49554
|
|
|
49213
49555
|
// node_modules/.pnpm/diff@5.2.2/node_modules/diff/lib/index.mjs
|
|
@@ -49377,7 +49719,7 @@ Diff.prototype = {
|
|
|
49377
49719
|
tokenize: function tokenize(value) {
|
|
49378
49720
|
return value.split("");
|
|
49379
49721
|
},
|
|
49380
|
-
join: function
|
|
49722
|
+
join: function join25(chars) {
|
|
49381
49723
|
return chars.join("");
|
|
49382
49724
|
}
|
|
49383
49725
|
};
|
|
@@ -49717,28 +50059,28 @@ import { createHash as createHash10 } from "crypto";
|
|
|
49717
50059
|
import {
|
|
49718
50060
|
constants as constants6,
|
|
49719
50061
|
closeSync as closeSync6,
|
|
49720
|
-
existsSync as
|
|
50062
|
+
existsSync as existsSync21,
|
|
49721
50063
|
fstatSync as fstatSync2,
|
|
49722
50064
|
lstatSync as lstatSync6,
|
|
49723
50065
|
mkdirSync as mkdirSync14,
|
|
49724
50066
|
openSync as openSync6,
|
|
49725
|
-
readFileSync as
|
|
50067
|
+
readFileSync as readFileSync19,
|
|
49726
50068
|
readSync as readSync2,
|
|
49727
50069
|
readdirSync as readdirSync6,
|
|
49728
50070
|
realpathSync as realpathSync4,
|
|
49729
50071
|
rmSync as rmSync8,
|
|
49730
50072
|
rmdirSync
|
|
49731
50073
|
} from "fs";
|
|
49732
|
-
import { homedir as
|
|
49733
|
-
import { dirname as dirname15, isAbsolute as
|
|
50074
|
+
import { homedir as homedir10 } from "os";
|
|
50075
|
+
import { dirname as dirname15, isAbsolute as isAbsolute8, join as join26, relative as relative2, resolve as resolve7, sep as sep2 } from "path";
|
|
49734
50076
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
49735
50077
|
var __dirname4 = dirname15(fileURLToPath4(import.meta.url));
|
|
49736
50078
|
var PLUGIN_DESCRIPTION = "Primitive decision-graph guidance for the prim CLI \u2014 a model-invoked skill installed by prim skill install.";
|
|
49737
50079
|
var MAX_MANIFEST_BYTES2 = 64 * 1024;
|
|
49738
50080
|
var MAX_SKILL_BYTES = 1024 * 1024;
|
|
49739
50081
|
function pluginDirFor(cwd, scope) {
|
|
49740
|
-
const base = scope === "user" ?
|
|
49741
|
-
return
|
|
50082
|
+
const base = scope === "user" ? join26(homedir10(), ".claude") : join26(gitToplevel(cwd) ?? cwd, ".claude");
|
|
50083
|
+
return join26(base, "skills", "prim");
|
|
49742
50084
|
}
|
|
49743
50085
|
function resolvePluginDir(cwd, scope) {
|
|
49744
50086
|
if (scope && scope !== "user" && scope !== "project") {
|
|
@@ -49751,7 +50093,7 @@ function packageVersion2() {
|
|
|
49751
50093
|
let dir = __dirname4;
|
|
49752
50094
|
while (dir !== dirname15(dir)) {
|
|
49753
50095
|
const p = resolve7(dir, "package.json");
|
|
49754
|
-
if (
|
|
50096
|
+
if (existsSync21(p)) return JSON.parse(readFileSync19(p, "utf-8")).version;
|
|
49755
50097
|
dir = dirname15(dir);
|
|
49756
50098
|
}
|
|
49757
50099
|
return "0.0.0";
|
|
@@ -49766,12 +50108,12 @@ function renderClaudePlugin() {
|
|
|
49766
50108
|
return { manifest: pluginManifest(version), skill: loadSkill(), version };
|
|
49767
50109
|
}
|
|
49768
50110
|
function removeDirIfEmpty(dir) {
|
|
49769
|
-
if (
|
|
50111
|
+
if (existsSync21(dir) && readdirSync6(dir).length === 0) rmdirSync(dir);
|
|
49770
50112
|
}
|
|
49771
50113
|
function pluginPaths(dir) {
|
|
49772
50114
|
return {
|
|
49773
|
-
manifestPath:
|
|
49774
|
-
skillPath:
|
|
50115
|
+
manifestPath: join26(dir, ".claude-plugin", "plugin.json"),
|
|
50116
|
+
skillPath: join26(dir, "SKILL.md")
|
|
49775
50117
|
};
|
|
49776
50118
|
}
|
|
49777
50119
|
function installClaudePlugin(cwd, opts) {
|
|
@@ -49779,8 +50121,8 @@ function installClaudePlugin(cwd, opts) {
|
|
|
49779
50121
|
if (dir === null) return 1;
|
|
49780
50122
|
const { manifestPath, skillPath } = pluginPaths(dir);
|
|
49781
50123
|
const { manifest, skill } = renderClaudePlugin();
|
|
49782
|
-
const manifestCurrent =
|
|
49783
|
-
const skillCurrent =
|
|
50124
|
+
const manifestCurrent = existsSync21(manifestPath) ? readFileSync19(manifestPath, "utf-8") : null;
|
|
50125
|
+
const skillCurrent = existsSync21(skillPath) ? readFileSync19(skillPath, "utf-8") : null;
|
|
49784
50126
|
if (manifestCurrent === manifest && skillCurrent === skill) {
|
|
49785
50127
|
console.log("No changes \u2014 prim skill plugin already up to date.");
|
|
49786
50128
|
return 0;
|
|
@@ -49789,7 +50131,7 @@ function installClaudePlugin(cwd, opts) {
|
|
|
49789
50131
|
console.log(`Would write plugin to ${dir} (.claude-plugin/plugin.json + SKILL.md)`);
|
|
49790
50132
|
return 0;
|
|
49791
50133
|
}
|
|
49792
|
-
mkdirSync14(
|
|
50134
|
+
mkdirSync14(join26(dir, ".claude-plugin"), { recursive: true });
|
|
49793
50135
|
atomicWrite4(manifestPath, manifest);
|
|
49794
50136
|
atomicWrite4(skillPath, skill);
|
|
49795
50137
|
console.log(`Installed prim skill plugin at ${dir}`);
|
|
@@ -49803,13 +50145,13 @@ function uninstallClaudePlugin(cwd, opts) {
|
|
|
49803
50145
|
const dir = resolvePluginDir(cwd, opts.scope);
|
|
49804
50146
|
if (dir === null) return 1;
|
|
49805
50147
|
const { manifestPath, skillPath } = pluginPaths(dir);
|
|
49806
|
-
if (!
|
|
50148
|
+
if (!existsSync21(manifestPath) && !existsSync21(skillPath)) {
|
|
49807
50149
|
console.log(`prim skill plugin not present at ${dir}`);
|
|
49808
50150
|
return 0;
|
|
49809
50151
|
}
|
|
49810
50152
|
rmSync8(manifestPath, { force: true });
|
|
49811
50153
|
rmSync8(skillPath, { force: true });
|
|
49812
|
-
removeDirIfEmpty(
|
|
50154
|
+
removeDirIfEmpty(join26(dir, ".claude-plugin"));
|
|
49813
50155
|
removeDirIfEmpty(dir);
|
|
49814
50156
|
console.log(`Removed prim skill plugin from ${dir}`);
|
|
49815
50157
|
return 0;
|
|
@@ -49818,7 +50160,7 @@ function statusClaudePlugin(cwd, opts) {
|
|
|
49818
50160
|
const dir = resolvePluginDir(cwd, opts.scope);
|
|
49819
50161
|
if (dir === null) return 1;
|
|
49820
50162
|
const { skillPath } = pluginPaths(dir);
|
|
49821
|
-
const installed =
|
|
50163
|
+
const installed = existsSync21(skillPath);
|
|
49822
50164
|
if (opts.json) {
|
|
49823
50165
|
printJson({ installed, target: dir });
|
|
49824
50166
|
return installed ? 0 : 1;
|
|
@@ -49853,11 +50195,109 @@ var AGENT_TARGET = {
|
|
|
49853
50195
|
codex: "AGENTS.md",
|
|
49854
50196
|
hermes: ".hermes.md"
|
|
49855
50197
|
};
|
|
50198
|
+
var CURSOR_SKILL_OWNER = "@primitive.ai/prim";
|
|
50199
|
+
var CURSOR_SKILL_MANIFEST = ".prim-owned.json";
|
|
50200
|
+
function sha2563(content) {
|
|
50201
|
+
return createHash11("sha256").update(content).digest("hex");
|
|
50202
|
+
}
|
|
50203
|
+
function cursorSkillDirectory(cwd, scope) {
|
|
50204
|
+
const base = scope === "user" ? cursorConfigDirectory() : gitToplevel(cwd) ?? cwd;
|
|
50205
|
+
return join27(base, scope === "user" ? "skills" : ".cursor/skills", "prim");
|
|
50206
|
+
}
|
|
50207
|
+
function cursorSkillPaths(cwd, scope) {
|
|
50208
|
+
const directory = cursorSkillDirectory(cwd, scope);
|
|
50209
|
+
return {
|
|
50210
|
+
directory,
|
|
50211
|
+
skill: join27(directory, "SKILL.md"),
|
|
50212
|
+
manifest: join27(directory, CURSOR_SKILL_MANIFEST)
|
|
50213
|
+
};
|
|
50214
|
+
}
|
|
50215
|
+
function readCursorSkillManifest(path9) {
|
|
50216
|
+
try {
|
|
50217
|
+
const value = JSON.parse(readFileSync20(path9, "utf8"));
|
|
50218
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
50219
|
+
const record2 = value;
|
|
50220
|
+
if (record2.version !== 1 || record2.owner !== CURSOR_SKILL_OWNER || typeof record2.contentSha256 !== "string" || !/^[0-9a-f]{64}$/u.test(record2.contentSha256)) {
|
|
50221
|
+
return;
|
|
50222
|
+
}
|
|
50223
|
+
return record2;
|
|
50224
|
+
} catch {
|
|
50225
|
+
return;
|
|
50226
|
+
}
|
|
50227
|
+
}
|
|
50228
|
+
function cursorSkillStatus(cwd, scope) {
|
|
50229
|
+
const paths = cursorSkillPaths(cwd, scope);
|
|
50230
|
+
const manifest = readCursorSkillManifest(paths.manifest);
|
|
50231
|
+
const content = existsSync22(paths.skill) ? readFileSync20(paths.skill, "utf8") : void 0;
|
|
50232
|
+
const owned = manifest !== void 0;
|
|
50233
|
+
const installed = owned && content !== void 0 && sha2563(content) === manifest.contentSha256;
|
|
50234
|
+
return {
|
|
50235
|
+
installed,
|
|
50236
|
+
owned,
|
|
50237
|
+
edited: owned && content !== void 0 && !installed,
|
|
50238
|
+
target: paths.skill
|
|
50239
|
+
};
|
|
50240
|
+
}
|
|
50241
|
+
function validCursorSkillScope(scope) {
|
|
50242
|
+
if (scope === void 0 || scope === "project" || scope === "user") return true;
|
|
50243
|
+
console.error(`Unknown --scope "${scope}" (expected user or project)`);
|
|
50244
|
+
return false;
|
|
50245
|
+
}
|
|
50246
|
+
function installCursorSkill(cwd, opts) {
|
|
50247
|
+
const paths = cursorSkillPaths(cwd, opts.scope);
|
|
50248
|
+
const status = cursorSkillStatus(cwd, opts.scope);
|
|
50249
|
+
const manifestExists = existsSync22(paths.manifest);
|
|
50250
|
+
const skillExists = existsSync22(paths.skill);
|
|
50251
|
+
if (manifestExists && !status.owned || !manifestExists && skillExists || status.edited) {
|
|
50252
|
+
console.error(`Refusing to overwrite a foreign or edited Cursor skill at ${paths.skill}`);
|
|
50253
|
+
return 1;
|
|
50254
|
+
}
|
|
50255
|
+
const content = loadSkill();
|
|
50256
|
+
const manifest = {
|
|
50257
|
+
version: 1,
|
|
50258
|
+
owner: CURSOR_SKILL_OWNER,
|
|
50259
|
+
contentSha256: sha2563(content)
|
|
50260
|
+
};
|
|
50261
|
+
if (status.installed && readFileSync20(paths.skill, "utf8") === content) {
|
|
50262
|
+
console.log(`No changes \u2014 Cursor skill already up to date at ${paths.skill}`);
|
|
50263
|
+
return 0;
|
|
50264
|
+
}
|
|
50265
|
+
if (opts.dryRun) {
|
|
50266
|
+
const existing = skillExists ? readFileSync20(paths.skill, "utf8") : "";
|
|
50267
|
+
process.stdout.write(createPatch(paths.skill, existing, content, "current", "proposed"));
|
|
50268
|
+
return 0;
|
|
50269
|
+
}
|
|
50270
|
+
atomicWriteFile(paths.skill, content, { ensureParent: true });
|
|
50271
|
+
atomicWriteFile(paths.manifest, `${JSON.stringify(manifest, null, 2)}
|
|
50272
|
+
`, { ensureParent: true });
|
|
50273
|
+
console.log(`Installed Cursor skill at ${paths.skill}`);
|
|
50274
|
+
return 0;
|
|
50275
|
+
}
|
|
50276
|
+
function uninstallCursorSkill(cwd, scope) {
|
|
50277
|
+
const paths = cursorSkillPaths(cwd, scope);
|
|
50278
|
+
const status = cursorSkillStatus(cwd, scope);
|
|
50279
|
+
if (!status.owned) {
|
|
50280
|
+
console.log(`No Primitive-owned Cursor skill at ${paths.skill}`);
|
|
50281
|
+
return 0;
|
|
50282
|
+
}
|
|
50283
|
+
if (status.edited) {
|
|
50284
|
+
console.error(`Refusing to remove an edited Cursor skill at ${paths.skill}`);
|
|
50285
|
+
return 1;
|
|
50286
|
+
}
|
|
50287
|
+
if (existsSync22(paths.skill)) unlinkSync7(paths.skill);
|
|
50288
|
+
if (existsSync22(paths.manifest)) unlinkSync7(paths.manifest);
|
|
50289
|
+
try {
|
|
50290
|
+
if (readdirSync7(paths.directory).length === 0) rmdirSync2(paths.directory);
|
|
50291
|
+
} catch {
|
|
50292
|
+
}
|
|
50293
|
+
console.log(`Removed Primitive-owned Cursor skill from ${paths.skill}`);
|
|
50294
|
+
return 0;
|
|
50295
|
+
}
|
|
49856
50296
|
function userTargetFor(agent) {
|
|
49857
|
-
if (agent === "claude") return
|
|
49858
|
-
if (agent === "codex") return
|
|
50297
|
+
if (agent === "claude") return join27(homedir11(), ".claude", "CLAUDE.md");
|
|
50298
|
+
if (agent === "codex") return join27(homedir11(), ".codex", "AGENTS.md");
|
|
49859
50299
|
if (agent === "hermes") {
|
|
49860
|
-
return
|
|
50300
|
+
return join27(process.env.HERMES_HOME ?? join27(homedir11(), ".hermes"), ".hermes.md");
|
|
49861
50301
|
}
|
|
49862
50302
|
return null;
|
|
49863
50303
|
}
|
|
@@ -49865,13 +50305,13 @@ function loadSkill() {
|
|
|
49865
50305
|
let dir = __dirname5;
|
|
49866
50306
|
while (dir !== dirname16(dir)) {
|
|
49867
50307
|
const p = resolve8(dir, "SKILL.md");
|
|
49868
|
-
if (
|
|
50308
|
+
if (existsSync22(p)) return readFileSync20(p, "utf-8");
|
|
49869
50309
|
dir = dirname16(dir);
|
|
49870
50310
|
}
|
|
49871
50311
|
throw new Error("SKILL.md not found in package");
|
|
49872
50312
|
}
|
|
49873
50313
|
function detectTargets(cwd) {
|
|
49874
|
-
return TARGET_CANDIDATES.filter((p) =>
|
|
50314
|
+
return TARGET_CANDIDATES.filter((p) => existsSync22(resolve8(cwd, p)));
|
|
49875
50315
|
}
|
|
49876
50316
|
function detectNewline(content) {
|
|
49877
50317
|
return content.includes("\r\n") ? "\r\n" : "\n";
|
|
@@ -49908,18 +50348,18 @@ function resolveTarget(cwd, opts) {
|
|
|
49908
50348
|
if (opts.target) return resolve8(cwd, opts.target);
|
|
49909
50349
|
if (opts.scope === "user") {
|
|
49910
50350
|
if (!opts.agent) {
|
|
49911
|
-
console.error("--scope user requires --agent (claude, codex, or hermes)");
|
|
50351
|
+
console.error("--scope user requires --agent (claude, codex, cursor, or hermes)");
|
|
49912
50352
|
return null;
|
|
49913
50353
|
}
|
|
49914
50354
|
const userTarget = userTargetFor(opts.agent);
|
|
49915
50355
|
if (userTarget) return userTarget;
|
|
49916
|
-
console.error(`Unknown --agent "${opts.agent}" (expected claude, codex, or hermes)`);
|
|
50356
|
+
console.error(`Unknown --agent "${opts.agent}" (expected claude, codex, cursor, or hermes)`);
|
|
49917
50357
|
return null;
|
|
49918
50358
|
}
|
|
49919
50359
|
if (opts.agent) {
|
|
49920
50360
|
const mapped = AGENT_TARGET[opts.agent];
|
|
49921
50361
|
if (typeof mapped === "string") return resolve8(cwd, mapped);
|
|
49922
|
-
console.error(`Unknown --agent "${opts.agent}" (expected claude, codex, or hermes)`);
|
|
50362
|
+
console.error(`Unknown --agent "${opts.agent}" (expected claude, codex, cursor, or hermes)`);
|
|
49923
50363
|
return null;
|
|
49924
50364
|
}
|
|
49925
50365
|
const matches = detectTargets(cwd);
|
|
@@ -49931,9 +50371,13 @@ function resolveTarget(cwd, opts) {
|
|
|
49931
50371
|
}
|
|
49932
50372
|
function runInstall(cwd, opts) {
|
|
49933
50373
|
if (opts.agent === "claude" && !opts.target) return installClaudePlugin(cwd, opts);
|
|
50374
|
+
if (opts.agent === "cursor" && !opts.target) {
|
|
50375
|
+
if (!validCursorSkillScope(opts.scope)) return 1;
|
|
50376
|
+
return installCursorSkill(cwd, opts);
|
|
50377
|
+
}
|
|
49934
50378
|
const target = resolveTarget(cwd, opts);
|
|
49935
50379
|
if (target === null) return 1;
|
|
49936
|
-
const existing =
|
|
50380
|
+
const existing = existsSync22(target) ? readFileSync20(target, "utf-8") : "";
|
|
49937
50381
|
const eol = existing ? detectNewline(existing) : "\n";
|
|
49938
50382
|
const block = composeBlock(loadSkill(), eol);
|
|
49939
50383
|
const next = applyBlock(existing, block, eol);
|
|
@@ -49951,13 +50395,17 @@ function runInstall(cwd, opts) {
|
|
|
49951
50395
|
}
|
|
49952
50396
|
function runUninstall(cwd, opts) {
|
|
49953
50397
|
if (opts.agent === "claude" && !opts.target) return uninstallClaudePlugin(cwd, opts);
|
|
50398
|
+
if (opts.agent === "cursor" && !opts.target) {
|
|
50399
|
+
if (!validCursorSkillScope(opts.scope)) return 1;
|
|
50400
|
+
return uninstallCursorSkill(cwd, opts.scope);
|
|
50401
|
+
}
|
|
49954
50402
|
const target = resolveTarget(cwd, opts);
|
|
49955
50403
|
if (target === null) return 1;
|
|
49956
|
-
if (!
|
|
50404
|
+
if (!existsSync22(target)) {
|
|
49957
50405
|
console.log(`Skill block not present at ${target}`);
|
|
49958
50406
|
return 0;
|
|
49959
50407
|
}
|
|
49960
|
-
const existing =
|
|
50408
|
+
const existing = readFileSync20(target, "utf-8");
|
|
49961
50409
|
const next = removeBlock(existing);
|
|
49962
50410
|
if (next === null) {
|
|
49963
50411
|
console.log(`Skill block not present at ${target}`);
|
|
@@ -49969,12 +50417,22 @@ function runUninstall(cwd, opts) {
|
|
|
49969
50417
|
}
|
|
49970
50418
|
function runStatus(cwd, opts) {
|
|
49971
50419
|
if (opts.agent === "claude" && !opts.target) return statusClaudePlugin(cwd, opts);
|
|
50420
|
+
if (opts.agent === "cursor" && !opts.target) {
|
|
50421
|
+
if (!validCursorSkillScope(opts.scope)) return 1;
|
|
50422
|
+
const status = cursorSkillStatus(cwd, opts.scope);
|
|
50423
|
+
if (opts.json) printJson(status);
|
|
50424
|
+
else
|
|
50425
|
+
console.log(
|
|
50426
|
+
status.installed ? `Primitive Cursor skill installed at ${status.target}` : `No intact Primitive-owned Cursor skill at ${status.target}`
|
|
50427
|
+
);
|
|
50428
|
+
return status.installed ? 0 : 1;
|
|
50429
|
+
}
|
|
49972
50430
|
const target = resolveTarget(cwd, opts);
|
|
49973
50431
|
if (target === null) return 1;
|
|
49974
|
-
const fileExists =
|
|
50432
|
+
const fileExists = existsSync22(target);
|
|
49975
50433
|
let installed = false;
|
|
49976
50434
|
if (fileExists) {
|
|
49977
|
-
const content =
|
|
50435
|
+
const content = readFileSync20(target, "utf-8");
|
|
49978
50436
|
installed = content.includes(SKILL_BEGIN) && content.includes(SKILL_END);
|
|
49979
50437
|
}
|
|
49980
50438
|
if (opts.json) {
|
|
@@ -49994,7 +50452,7 @@ function runStatus(cwd, opts) {
|
|
|
49994
50452
|
}
|
|
49995
50453
|
function registerSkillCommands(program3) {
|
|
49996
50454
|
const skill = program3.command("skill").description("Manage the prim skill in your project rules file");
|
|
49997
|
-
skill.command("install").description("Install the prim skill block into your project rules file").option("--target <path>", "Path to the rules file (overrides auto-detection)").option("--agent <agent>", "claude, codex, or hermes
|
|
50455
|
+
skill.command("install").description("Install the prim skill block into your project rules file").option("--target <path>", "Path to the rules file (overrides auto-detection)").option("--agent <agent>", "claude, codex, cursor, or hermes").option("--scope <scope>", "project (default, this repo) or user (machine-global \u2014 every repo)").option("--dry-run", "Print a unified diff without writing").action((opts) => {
|
|
49998
50456
|
try {
|
|
49999
50457
|
process.exit(runInstall(process.cwd(), opts));
|
|
50000
50458
|
} catch (err) {
|
|
@@ -50002,16 +50460,16 @@ function registerSkillCommands(program3) {
|
|
|
50002
50460
|
process.exit(2);
|
|
50003
50461
|
}
|
|
50004
50462
|
});
|
|
50005
|
-
skill.command("uninstall").description("Remove the prim skill block from your project rules file").option("--target <path>", "Path to the rules file (overrides auto-detection)").option("--agent <agent>", "claude, codex, or hermes
|
|
50463
|
+
skill.command("uninstall").description("Remove the prim skill block from your project rules file").option("--target <path>", "Path to the rules file (overrides auto-detection)").option("--agent <agent>", "claude, codex, cursor, or hermes").option("--scope <scope>", "project (default, this repo) or user (machine-global \u2014 every repo)").action((opts) => {
|
|
50006
50464
|
process.exit(runUninstall(process.cwd(), opts));
|
|
50007
50465
|
});
|
|
50008
|
-
skill.command("status").description("Report whether the prim skill block is installed").option("--target <path>", "Path to the rules file (overrides auto-detection)").option("--agent <agent>", "claude, codex, or hermes
|
|
50466
|
+
skill.command("status").description("Report whether the prim skill block is installed").option("--target <path>", "Path to the rules file (overrides auto-detection)").option("--agent <agent>", "claude, codex, cursor, or hermes").option("--scope <scope>", "project (default, this repo) or user (machine-global \u2014 every repo)").option("--json", "Output as JSON").action((opts) => {
|
|
50009
50467
|
process.exit(runStatus(process.cwd(), opts));
|
|
50010
50468
|
});
|
|
50011
50469
|
}
|
|
50012
50470
|
|
|
50013
50471
|
// src/commands/statusline.ts
|
|
50014
|
-
import { readFileSync as
|
|
50472
|
+
import { readFileSync as readFileSync21 } from "fs";
|
|
50015
50473
|
import { dirname as dirname17, resolve as resolve9 } from "path";
|
|
50016
50474
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
50017
50475
|
var STATUSLINE_TIMEOUT_MS = 200;
|
|
@@ -50027,7 +50485,7 @@ function readPackageVersion() {
|
|
|
50027
50485
|
];
|
|
50028
50486
|
for (const path9 of candidates) {
|
|
50029
50487
|
try {
|
|
50030
|
-
const pkg2 = JSON.parse(
|
|
50488
|
+
const pkg2 = JSON.parse(readFileSync21(path9, "utf-8"));
|
|
50031
50489
|
if (pkg2.version) {
|
|
50032
50490
|
return pkg2.version;
|
|
50033
50491
|
}
|
|
@@ -50044,9 +50502,8 @@ function debug(msg) {
|
|
|
50044
50502
|
`);
|
|
50045
50503
|
}
|
|
50046
50504
|
}
|
|
50047
|
-
async function renderStatusline() {
|
|
50505
|
+
async function renderStatusline(cwd = process.cwd()) {
|
|
50048
50506
|
const version = readPackageVersion();
|
|
50049
|
-
const cwd = process.cwd();
|
|
50050
50507
|
let ingestion;
|
|
50051
50508
|
const resolveIngestion = () => {
|
|
50052
50509
|
ingestion ??= decisionIngestionStatus(cwd);
|
|
@@ -50094,6 +50551,11 @@ function planUninstallSteps(inRepository) {
|
|
|
50094
50551
|
label: "Codex project integration",
|
|
50095
50552
|
args: ["codex", "uninstall", "--scope", "project"]
|
|
50096
50553
|
},
|
|
50554
|
+
{
|
|
50555
|
+
key: "cursor-project",
|
|
50556
|
+
label: "Cursor project integration",
|
|
50557
|
+
args: ["cursor", "uninstall", "--scope", "project"]
|
|
50558
|
+
},
|
|
50097
50559
|
{
|
|
50098
50560
|
key: "hooks-project",
|
|
50099
50561
|
label: "project Git hooks",
|
|
@@ -50113,6 +50575,11 @@ function planUninstallSteps(inRepository) {
|
|
|
50113
50575
|
label: "Codex user integration",
|
|
50114
50576
|
args: ["codex", "uninstall", "--scope", "user"]
|
|
50115
50577
|
},
|
|
50578
|
+
{
|
|
50579
|
+
key: "cursor-user",
|
|
50580
|
+
label: "Cursor user integration",
|
|
50581
|
+
args: ["cursor", "uninstall", "--scope", "user"]
|
|
50582
|
+
},
|
|
50116
50583
|
{ key: "hermes-user", label: "Hermes integration", args: ["hermes", "uninstall"] },
|
|
50117
50584
|
{
|
|
50118
50585
|
key: "hooks-user",
|
|
@@ -50131,7 +50598,7 @@ function uninstallStepSucceeded(step, result) {
|
|
|
50131
50598
|
return false;
|
|
50132
50599
|
}
|
|
50133
50600
|
}
|
|
50134
|
-
if (!step.key.startsWith("claude-") && !step.key.startsWith("codex-") && step.key !== "hermes-user") {
|
|
50601
|
+
if (!step.key.startsWith("claude-") && !step.key.startsWith("codex-") && !step.key.startsWith("cursor-") && step.key !== "hermes-user") {
|
|
50135
50602
|
return true;
|
|
50136
50603
|
}
|
|
50137
50604
|
try {
|
|
@@ -50139,7 +50606,7 @@ function uninstallStepSucceeded(step, result) {
|
|
|
50139
50606
|
if (step.key.startsWith("claude-")) {
|
|
50140
50607
|
return parsed.gate === false && parsed.capture === false && parsed.feedback === false && parsed.statusline === false;
|
|
50141
50608
|
}
|
|
50142
|
-
return parsed.gate === false && parsed.capture === false;
|
|
50609
|
+
return parsed.gate === false && parsed.capture === false && (!step.key.startsWith("cursor-user") || parsed.footer === false);
|
|
50143
50610
|
} catch {
|
|
50144
50611
|
return false;
|
|
50145
50612
|
}
|
|
@@ -50254,9 +50721,9 @@ function registerUninstallCommand(program3, dependencies = {}) {
|
|
|
50254
50721
|
note(`uninstall \xB7 runtime removal incomplete (unknown state): ${detail}`);
|
|
50255
50722
|
}
|
|
50256
50723
|
}
|
|
50257
|
-
const
|
|
50724
|
+
const complete2 = failed.length === 0;
|
|
50258
50725
|
const result = {
|
|
50259
|
-
uninstalled:
|
|
50726
|
+
uninstalled: complete2,
|
|
50260
50727
|
projectScopeChecked: inRepository,
|
|
50261
50728
|
steps: results,
|
|
50262
50729
|
runtime,
|
|
@@ -50270,16 +50737,16 @@ function registerUninstallCommand(program3, dependencies = {}) {
|
|
|
50270
50737
|
write(`${JSON.stringify(result, null, 2)}
|
|
50271
50738
|
`);
|
|
50272
50739
|
note(
|
|
50273
|
-
|
|
50740
|
+
complete2 ? "uninstall complete \xB7 credentials and pending journals preserved" : `uninstall incomplete \xB7 failed: ${failed.join(", ")}`
|
|
50274
50741
|
);
|
|
50275
|
-
exit(
|
|
50742
|
+
exit(complete2 ? 0 : EXIT_INCOMPLETE2);
|
|
50276
50743
|
});
|
|
50277
50744
|
}
|
|
50278
50745
|
|
|
50279
50746
|
// src/commands/welcome.ts
|
|
50280
50747
|
var CMD_GUTTER = 38;
|
|
50281
50748
|
var RECENT_LIMIT = 5;
|
|
50282
|
-
var WELCOME_AGENTS = ["claude", "codex", "hermes"];
|
|
50749
|
+
var WELCOME_AGENTS = ["claude", "codex", "cursor", "hermes"];
|
|
50283
50750
|
function resolveWelcomeAgent(agentFlag, env4) {
|
|
50284
50751
|
if (agentFlag !== void 0 && WELCOME_AGENTS.includes(agentFlag)) {
|
|
50285
50752
|
return agentFlag;
|
|
@@ -50287,6 +50754,9 @@ function resolveWelcomeAgent(agentFlag, env4) {
|
|
|
50287
50754
|
if (agentFlag === void 0 && env4.HERMES_INTERACTIVE) {
|
|
50288
50755
|
return "hermes";
|
|
50289
50756
|
}
|
|
50757
|
+
if (agentFlag === void 0 && env4.CURSOR_AGENT) {
|
|
50758
|
+
return "cursor";
|
|
50759
|
+
}
|
|
50290
50760
|
return void 0;
|
|
50291
50761
|
}
|
|
50292
50762
|
var CAPTURE_LINES = {
|
|
@@ -50295,6 +50765,7 @@ var CAPTURE_LINES = {
|
|
|
50295
50765
|
"Capture starts once you trust the prim hooks \u2014 run /hooks in Codex;",
|
|
50296
50766
|
"until then nothing is recorded."
|
|
50297
50767
|
],
|
|
50768
|
+
cursor: ["Capture is automatic in trusted Cursor workspaces; restart Cursor CLI for the footer."],
|
|
50298
50769
|
hermes: [
|
|
50299
50770
|
"Capture starts once you approve the prim hooks when Hermes prompts;",
|
|
50300
50771
|
"until then nothing is recorded."
|
|
@@ -50310,6 +50781,7 @@ var PASSIVE_LINES = {
|
|
|
50310
50781
|
"Once you trust the prim hooks (/hooks in Codex), Primitive captures",
|
|
50311
50782
|
"decisions passively while you work."
|
|
50312
50783
|
],
|
|
50784
|
+
cursor: ["In trusted Cursor workspaces, Primitive captures decisions passively while you work."],
|
|
50313
50785
|
hermes: [
|
|
50314
50786
|
"Once you approve the prim hooks, Primitive captures decisions",
|
|
50315
50787
|
"passively while you work."
|
|
@@ -50322,6 +50794,7 @@ var PASSIVE_LINES = {
|
|
|
50322
50794
|
var GUIDANCE_PASSIVE = {
|
|
50323
50795
|
claude: "Otherwise, Primitive passively captures decisions in the background while you work.",
|
|
50324
50796
|
codex: "Otherwise, once you trust the prim hooks (run /hooks in Codex), Primitive passively captures decisions in the background while you work.",
|
|
50797
|
+
cursor: "Otherwise, Primitive passively captures decisions in trusted Cursor workspaces while you work.",
|
|
50325
50798
|
hermes: "Otherwise, once you approve the prim hooks when Hermes prompts, Primitive passively captures decisions in the background while you work.",
|
|
50326
50799
|
generic: "Otherwise, once your agent's prim hooks are active, Primitive passively captures decisions in the background while you work."
|
|
50327
50800
|
};
|
|
@@ -50416,10 +50889,7 @@ function welcomeJson(state, agent) {
|
|
|
50416
50889
|
return { welcomed: true, org: "unknown" };
|
|
50417
50890
|
}
|
|
50418
50891
|
function registerWelcomeCommand(program3, deps = { getClient }) {
|
|
50419
|
-
program3.command("welcome").description("Print a brief orientation to Primitive's decision graph").option(
|
|
50420
|
-
"--agent <agent>",
|
|
50421
|
-
"claude, codex, or hermes \u2014 tailors the capture guidance (Hermes auto-detected)"
|
|
50422
|
-
).action(async (options) => {
|
|
50892
|
+
program3.command("welcome").description("Print a brief orientation to Primitive's decision graph").option("--agent <agent>", "claude, codex, cursor, or hermes \u2014 tailors the capture guidance").action(async (options) => {
|
|
50423
50893
|
const agent = resolveWelcomeAgent(options.agent, process.env);
|
|
50424
50894
|
const result = await fetchRecent({ limit: RECENT_LIMIT }, deps);
|
|
50425
50895
|
const state = welcomeStateFromRecent(result);
|
|
@@ -50447,7 +50917,7 @@ function runStartupBackgroundWork(argv, env4, work) {
|
|
|
50447
50917
|
|
|
50448
50918
|
// src/index.ts
|
|
50449
50919
|
var __dirname6 = dirname18(fileURLToPath7(import.meta.url));
|
|
50450
|
-
var pkg = JSON.parse(
|
|
50920
|
+
var pkg = JSON.parse(readFileSync22(resolve10(__dirname6, "../package.json"), "utf-8"));
|
|
50451
50921
|
runStartupBackgroundWork(process.argv.slice(2), process.env, {
|
|
50452
50922
|
notify: () => updateNotifier({ pkg }).notify(),
|
|
50453
50923
|
flush: () => flushIfNeeded()
|
|
@@ -50466,6 +50936,7 @@ registerSessionCommands(program2);
|
|
|
50466
50936
|
registerDecisionsCommands(program2);
|
|
50467
50937
|
registerClaudeCommands(program2);
|
|
50468
50938
|
registerCodexCommands(program2);
|
|
50939
|
+
registerCursorCommands(program2);
|
|
50469
50940
|
registerHermesCommands(program2);
|
|
50470
50941
|
registerDaemonCommands(program2);
|
|
50471
50942
|
registerGithubCommands(program2);
|