@primitive.ai/prim 0.1.0-alpha.44 → 0.1.0-alpha.45
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/dist/{chunk-BSZGI5RL.js → chunk-6MKLCOEH.js} +1 -1
- package/dist/{chunk-UISU3A7W.js → chunk-6TRRGGLD.js} +1 -1
- package/dist/{chunk-W6PAKEDO.js → chunk-PI6LDYNJ.js} +13 -4
- package/dist/{chunk-OKUXEBPT.js → chunk-ZWTZMTV5.js} +1 -1
- package/dist/daemon/server.js +82 -8
- package/dist/hooks/post-commit.js +2 -2
- package/dist/hooks/post-tool-use.js +2 -2
- package/dist/hooks/pre-commit.js +2 -2
- package/dist/hooks/pre-tool-use.js +1 -1
- package/dist/hooks/prim-hook.js +3 -3
- package/dist/hooks/session-start.js +2 -2
- package/dist/index.js +11 -4
- package/package.json +1 -1
|
@@ -79,6 +79,7 @@ function getSiteUrl() {
|
|
|
79
79
|
}
|
|
80
80
|
return DEFAULT_API_URL;
|
|
81
81
|
}
|
|
82
|
+
var _endedRefreshToken;
|
|
82
83
|
async function performTokenRefresh(options = {}) {
|
|
83
84
|
if (!existsSync(REFRESH_TOKEN_PATH)) {
|
|
84
85
|
return void 0;
|
|
@@ -87,6 +88,9 @@ async function performTokenRefresh(options = {}) {
|
|
|
87
88
|
if (!refreshTokenValue) {
|
|
88
89
|
return void 0;
|
|
89
90
|
}
|
|
91
|
+
if (_endedRefreshToken !== void 0 && refreshTokenValue === _endedRefreshToken) {
|
|
92
|
+
return void 0;
|
|
93
|
+
}
|
|
90
94
|
const siteUrl = getSiteUrl();
|
|
91
95
|
const response = await fetch(`${siteUrl}/mcp/broker/refresh`, {
|
|
92
96
|
method: "POST",
|
|
@@ -95,18 +99,23 @@ async function performTokenRefresh(options = {}) {
|
|
|
95
99
|
signal: options.signal
|
|
96
100
|
});
|
|
97
101
|
if (!response.ok) {
|
|
98
|
-
if (options.quiet) return void 0;
|
|
99
102
|
const detail = (await response.text().catch(() => "")).slice(0, 200);
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
if (detail.includes("invalid_grant") || detail.includes("Session has already ended")) {
|
|
104
|
+
_endedRefreshToken = refreshTokenValue;
|
|
105
|
+
}
|
|
106
|
+
if (!options.quiet) {
|
|
107
|
+
process.stderr.write(
|
|
108
|
+
`[prim] token refresh rejected by broker: ${response.status} ${response.statusText}${detail ? ` \u2014 ${detail}` : ""}
|
|
102
109
|
`
|
|
103
|
-
|
|
110
|
+
);
|
|
111
|
+
}
|
|
104
112
|
return void 0;
|
|
105
113
|
}
|
|
106
114
|
const data = await response.json();
|
|
107
115
|
if (!data.access_token) {
|
|
108
116
|
return void 0;
|
|
109
117
|
}
|
|
118
|
+
_endedRefreshToken = void 0;
|
|
110
119
|
writeFileSync(TOKEN_FILE_PATH, data.access_token, { mode: 384 });
|
|
111
120
|
if (data.refresh_token) {
|
|
112
121
|
writeFileSync(REFRESH_TOKEN_PATH, data.refresh_token, { mode: 384 });
|
package/dist/daemon/server.js
CHANGED
|
@@ -88,6 +88,17 @@ function getSiteUrl() {
|
|
|
88
88
|
}
|
|
89
89
|
return DEFAULT_API_URL;
|
|
90
90
|
}
|
|
91
|
+
var _endedRefreshToken;
|
|
92
|
+
function isSessionEnded() {
|
|
93
|
+
if (_endedRefreshToken === void 0) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
if (!existsSync(REFRESH_TOKEN_PATH)) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
const current = readFileSync(REFRESH_TOKEN_PATH, "utf-8").trim();
|
|
100
|
+
return current === _endedRefreshToken;
|
|
101
|
+
}
|
|
91
102
|
async function performTokenRefresh(options = {}) {
|
|
92
103
|
if (!existsSync(REFRESH_TOKEN_PATH)) {
|
|
93
104
|
return void 0;
|
|
@@ -96,6 +107,9 @@ async function performTokenRefresh(options = {}) {
|
|
|
96
107
|
if (!refreshTokenValue) {
|
|
97
108
|
return void 0;
|
|
98
109
|
}
|
|
110
|
+
if (_endedRefreshToken !== void 0 && refreshTokenValue === _endedRefreshToken) {
|
|
111
|
+
return void 0;
|
|
112
|
+
}
|
|
99
113
|
const siteUrl = getSiteUrl();
|
|
100
114
|
const response = await fetch(`${siteUrl}/mcp/broker/refresh`, {
|
|
101
115
|
method: "POST",
|
|
@@ -104,18 +118,23 @@ async function performTokenRefresh(options = {}) {
|
|
|
104
118
|
signal: options.signal
|
|
105
119
|
});
|
|
106
120
|
if (!response.ok) {
|
|
107
|
-
if (options.quiet) return void 0;
|
|
108
121
|
const detail = (await response.text().catch(() => "")).slice(0, 200);
|
|
109
|
-
|
|
110
|
-
|
|
122
|
+
if (detail.includes("invalid_grant") || detail.includes("Session has already ended")) {
|
|
123
|
+
_endedRefreshToken = refreshTokenValue;
|
|
124
|
+
}
|
|
125
|
+
if (!options.quiet) {
|
|
126
|
+
process.stderr.write(
|
|
127
|
+
`[prim] token refresh rejected by broker: ${response.status} ${response.statusText}${detail ? ` \u2014 ${detail}` : ""}
|
|
111
128
|
`
|
|
112
|
-
|
|
129
|
+
);
|
|
130
|
+
}
|
|
113
131
|
return void 0;
|
|
114
132
|
}
|
|
115
133
|
const data = await response.json();
|
|
116
134
|
if (!data.access_token) {
|
|
117
135
|
return void 0;
|
|
118
136
|
}
|
|
137
|
+
_endedRefreshToken = void 0;
|
|
119
138
|
writeFileSync(TOKEN_FILE_PATH, data.access_token, { mode: 384 });
|
|
120
139
|
if (data.refresh_token) {
|
|
121
140
|
writeFileSync(REFRESH_TOKEN_PATH, data.refresh_token, { mode: 384 });
|
|
@@ -719,7 +738,7 @@ function createDaemonHealthState(version, pid, startedAt2) {
|
|
|
719
738
|
function refreshDaemonHealth(state, now) {
|
|
720
739
|
state.heartbeat.healthy = state.heartbeat.consecutiveFailures === 0 && state.heartbeat.lastSuccessAt !== void 0 && now - state.heartbeat.lastSuccessAt < HEARTBEAT_FRESH_MS;
|
|
721
740
|
state.ingestion.healthy = state.ingestion.consecutiveFailures === 0 && !state.ingestion.pendingSampled && (state.ingestion.pendingCount === 0 || state.ingestion.oldestPendingAt !== void 0 && now - state.ingestion.oldestPendingAt <= INGESTION_SLA_MS);
|
|
722
|
-
state.healthy = state.heartbeat.healthy && state.ingestion.healthy;
|
|
741
|
+
state.healthy = state.heartbeat.healthy && state.ingestion.healthy && !state.needsReauth;
|
|
723
742
|
}
|
|
724
743
|
function retryDelayMs(consecutiveFailures, capMs, random) {
|
|
725
744
|
const exponent = Math.max(0, consecutiveFailures - 1);
|
|
@@ -935,6 +954,7 @@ var heartbeatRerunRequested = false;
|
|
|
935
954
|
var ownership;
|
|
936
955
|
var socketServer;
|
|
937
956
|
var shuttingDown = false;
|
|
957
|
+
var reauthHold = false;
|
|
938
958
|
function resolveRuntimeVersion() {
|
|
939
959
|
if (process.env.PRIM_RUNTIME_VERSION) {
|
|
940
960
|
return process.env.PRIM_RUNTIME_VERSION;
|
|
@@ -967,6 +987,42 @@ function updatePendingHealth() {
|
|
|
967
987
|
daemonHealth.ingestion.oldestPendingAt = pending.oldestPendingAt;
|
|
968
988
|
daemonHealth.ingestion.strandedCount = pending.strandedCount;
|
|
969
989
|
}
|
|
990
|
+
function enterReauthHold() {
|
|
991
|
+
if (reauthHold) {
|
|
992
|
+
return;
|
|
993
|
+
}
|
|
994
|
+
reauthHold = true;
|
|
995
|
+
daemonHealth.needsReauth = true;
|
|
996
|
+
if (heartbeatTimer) {
|
|
997
|
+
clearTimeout(heartbeatTimer);
|
|
998
|
+
heartbeatTimer = void 0;
|
|
999
|
+
}
|
|
1000
|
+
if (ingestionTimer) {
|
|
1001
|
+
clearTimeout(ingestionTimer);
|
|
1002
|
+
ingestionTimer = void 0;
|
|
1003
|
+
}
|
|
1004
|
+
persistHealth();
|
|
1005
|
+
process.stderr.write(
|
|
1006
|
+
"[prim-daemon] authentication ended \u2014 halting heartbeat + ingestion until `prim auth login` (captures continue to the journal)\n"
|
|
1007
|
+
);
|
|
1008
|
+
}
|
|
1009
|
+
function exitReauthHold() {
|
|
1010
|
+
if (!reauthHold) {
|
|
1011
|
+
return;
|
|
1012
|
+
}
|
|
1013
|
+
reauthHold = false;
|
|
1014
|
+
daemonHealth.needsReauth = false;
|
|
1015
|
+
daemonHealth.heartbeat.consecutiveFailures = 0;
|
|
1016
|
+
daemonHealth.ingestion.consecutiveFailures = 0;
|
|
1017
|
+
daemonHealth.heartbeat.lastError = void 0;
|
|
1018
|
+
daemonHealth.ingestion.lastError = void 0;
|
|
1019
|
+
persistHealth();
|
|
1020
|
+
process.stderr.write(
|
|
1021
|
+
"[prim-daemon] re-authentication detected \u2014 resuming heartbeat + ingestion\n"
|
|
1022
|
+
);
|
|
1023
|
+
void sendHeartbeat();
|
|
1024
|
+
void runIngestionLoop();
|
|
1025
|
+
}
|
|
970
1026
|
async function takeOwnership() {
|
|
971
1027
|
const now = Date.now();
|
|
972
1028
|
const recordedOwner = readDaemonOwner(CONFIG_DIR);
|
|
@@ -1051,6 +1107,10 @@ async function performHeartbeat() {
|
|
|
1051
1107
|
daemonHealth.heartbeat.lastError = errorMessage(err);
|
|
1052
1108
|
daemonHealth.heartbeat.consecutiveFailures += 1;
|
|
1053
1109
|
persistHealth();
|
|
1110
|
+
if (isSessionEnded()) {
|
|
1111
|
+
enterReauthHold();
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
1054
1114
|
process.stderr.write(`[prim-daemon] heartbeat error: ${errorMessage(err)}
|
|
1055
1115
|
`);
|
|
1056
1116
|
}
|
|
@@ -1076,7 +1136,7 @@ function sendHeartbeat() {
|
|
|
1076
1136
|
return heartbeatInFlight;
|
|
1077
1137
|
}
|
|
1078
1138
|
function scheduleHeartbeat() {
|
|
1079
|
-
if (shuttingDown) {
|
|
1139
|
+
if (shuttingDown || reauthHold) {
|
|
1080
1140
|
return;
|
|
1081
1141
|
}
|
|
1082
1142
|
const failures = daemonHealth.heartbeat.consecutiveFailures;
|
|
@@ -1101,7 +1161,7 @@ async function ensureTokenFresh() {
|
|
|
1101
1161
|
}
|
|
1102
1162
|
}
|
|
1103
1163
|
function scheduleIngestion(delayMs) {
|
|
1104
|
-
if (shuttingDown) {
|
|
1164
|
+
if (shuttingDown || reauthHold) {
|
|
1105
1165
|
return;
|
|
1106
1166
|
}
|
|
1107
1167
|
ingestionTimer = setTimeout(() => {
|
|
@@ -1154,6 +1214,10 @@ async function runIngestionLoop() {
|
|
|
1154
1214
|
} catch {
|
|
1155
1215
|
}
|
|
1156
1216
|
persistHealth();
|
|
1217
|
+
if (isSessionEnded()) {
|
|
1218
|
+
enterReauthHold();
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1157
1221
|
process.stderr.write(`[prim-daemon] ingestion error: ${errorMessage(err)}
|
|
1158
1222
|
`);
|
|
1159
1223
|
scheduleIngestion(delay);
|
|
@@ -1198,6 +1262,7 @@ function handleStatusSnapshot(params) {
|
|
|
1198
1262
|
lastHeartbeatAt,
|
|
1199
1263
|
version: runtimeVersion,
|
|
1200
1264
|
healthy: daemonHealth.healthy,
|
|
1265
|
+
needsReauth: daemonHealth.needsReauth === true,
|
|
1201
1266
|
heartbeat: { ...daemonHealth.heartbeat },
|
|
1202
1267
|
ingestion: { ...daemonHealth.ingestion }
|
|
1203
1268
|
};
|
|
@@ -1338,7 +1403,16 @@ function startTimers() {
|
|
|
1338
1403
|
void runTokenCheckLoop();
|
|
1339
1404
|
}
|
|
1340
1405
|
async function runTokenCheckLoop() {
|
|
1341
|
-
|
|
1406
|
+
if (reauthHold) {
|
|
1407
|
+
if (!isSessionEnded()) {
|
|
1408
|
+
exitReauthHold();
|
|
1409
|
+
}
|
|
1410
|
+
} else {
|
|
1411
|
+
await ensureTokenFresh();
|
|
1412
|
+
if (isSessionEnded()) {
|
|
1413
|
+
enterReauthHold();
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1342
1416
|
if (!shuttingDown) {
|
|
1343
1417
|
tokenCheckTimer = setTimeout(() => {
|
|
1344
1418
|
tokenCheckTimer = void 0;
|
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
appendMove,
|
|
7
7
|
resolveOrg
|
|
8
|
-
} from "../chunk-
|
|
9
|
-
import "../chunk-
|
|
8
|
+
} from "../chunk-ZWTZMTV5.js";
|
|
9
|
+
import "../chunk-PI6LDYNJ.js";
|
|
10
10
|
|
|
11
11
|
// src/hooks/post-commit.ts
|
|
12
12
|
import { execSync, spawn } from "child_process";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
appendMove,
|
|
15
15
|
resolveOrg
|
|
16
|
-
} from "../chunk-
|
|
16
|
+
} from "../chunk-ZWTZMTV5.js";
|
|
17
17
|
import {
|
|
18
18
|
getOrCreateWorkspaceId
|
|
19
19
|
} from "../chunk-IMAIBPUC.js";
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
} from "../chunk-F7O7V6ZM.js";
|
|
24
24
|
import {
|
|
25
25
|
getClient
|
|
26
|
-
} from "../chunk-
|
|
26
|
+
} from "../chunk-PI6LDYNJ.js";
|
|
27
27
|
import {
|
|
28
28
|
normalizeEnvelope,
|
|
29
29
|
parseAgent
|
package/dist/hooks/pre-commit.js
CHANGED
package/dist/hooks/prim-hook.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
appendMove,
|
|
11
11
|
resolveOrg
|
|
12
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-ZWTZMTV5.js";
|
|
13
13
|
import {
|
|
14
14
|
buildHookOutput,
|
|
15
15
|
handoffHookOutput
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
acknowledgeDecisionFeedback,
|
|
20
20
|
leaseDecisionFeedback,
|
|
21
21
|
renderFeedback
|
|
22
|
-
} from "../chunk-
|
|
22
|
+
} from "../chunk-6TRRGGLD.js";
|
|
23
23
|
import {
|
|
24
24
|
getOrCreateWorkspaceId
|
|
25
25
|
} from "../chunk-IMAIBPUC.js";
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
isRepoActiveForCapture,
|
|
28
28
|
warmBinCache
|
|
29
29
|
} from "../chunk-F7O7V6ZM.js";
|
|
30
|
-
import "../chunk-
|
|
30
|
+
import "../chunk-PI6LDYNJ.js";
|
|
31
31
|
import {
|
|
32
32
|
normalizeEnvelope,
|
|
33
33
|
parseAgent
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
acknowledgeDecisionFeedback,
|
|
9
9
|
leaseDecisionFeedback,
|
|
10
10
|
renderFeedback
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-6TRRGGLD.js";
|
|
12
12
|
import {
|
|
13
13
|
getOrCreateWorkspaceId
|
|
14
14
|
} from "../chunk-IMAIBPUC.js";
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
} from "../chunk-F7O7V6ZM.js";
|
|
20
20
|
import {
|
|
21
21
|
getSiteUrl
|
|
22
|
-
} from "../chunk-
|
|
22
|
+
} from "../chunk-PI6LDYNJ.js";
|
|
23
23
|
import {
|
|
24
24
|
daemonRequest
|
|
25
25
|
} from "../chunk-UTKQTZHL.js";
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
checkAffectedDecisions,
|
|
13
13
|
daemonOrDirectGet,
|
|
14
14
|
formatDecisionsWarning
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-6MKLCOEH.js";
|
|
16
16
|
import {
|
|
17
17
|
JOURNAL_DIR,
|
|
18
18
|
SESSIONS_DIR,
|
|
@@ -21,10 +21,10 @@ import {
|
|
|
21
21
|
listFlushing,
|
|
22
22
|
pendingJournalStats,
|
|
23
23
|
readMovesFromPath
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-ZWTZMTV5.js";
|
|
25
25
|
import {
|
|
26
26
|
fetchFeedbackCapability
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-6TRRGGLD.js";
|
|
28
28
|
import {
|
|
29
29
|
inspectWorkspaceId
|
|
30
30
|
} from "./chunk-IMAIBPUC.js";
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
getSiteUrl,
|
|
49
49
|
getTokenExpiresAt,
|
|
50
50
|
saveTokenExpiry
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-PI6LDYNJ.js";
|
|
52
52
|
import {
|
|
53
53
|
daemonIsLive,
|
|
54
54
|
daemonRequest
|
|
@@ -3195,6 +3195,13 @@ function classifyDaemonHealth(snapshot, options = {}) {
|
|
|
3195
3195
|
detail: `launchd does not own the daemon socket (launchd ${String(options.service.pid ?? "none")} \xB7 socket ${String(snapshot.pid ?? "none")})`
|
|
3196
3196
|
};
|
|
3197
3197
|
}
|
|
3198
|
+
if (snapshot.needsReauth) {
|
|
3199
|
+
return {
|
|
3200
|
+
name: "daemon",
|
|
3201
|
+
status: "fail",
|
|
3202
|
+
detail: "authentication ended \u2014 run `prim auth login`"
|
|
3203
|
+
};
|
|
3204
|
+
}
|
|
3198
3205
|
if (!snapshot.heartbeat?.healthy) {
|
|
3199
3206
|
return {
|
|
3200
3207
|
name: "daemon",
|
package/package.json
CHANGED