@primitive.ai/prim 0.1.0-alpha.65 → 0.1.0-alpha.67

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.
@@ -95,6 +95,9 @@ function toMove(parsed, cliVersion, agent = "claude_code", workspaceId, reposito
95
95
  ...toolOutcome ? { toolOutcome } : {}
96
96
  };
97
97
  }
98
+ var MAX_REWRITE_PAIRS_PER_MOVE = 40;
99
+ var MAX_REWRITE_PAIRS_PER_HOOK = 2e3;
100
+ var FULL_SHA_RE = /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/u;
98
101
  var MAX_CLASSIFIER_ID_CHARS = 256;
99
102
  var INVALID_CLASSIFIER_ID_RE = /[\u0000-\u001f\u007f\uD800-\uDFFF]/u;
100
103
  function validSessionHint(value) {
@@ -152,6 +155,63 @@ function toCommitMove(commit, cliVersion, cwd, context = {}) {
152
155
  producer: validatedAttribution.producer
153
156
  } : { ...base, envelopeVersion: ENVELOPE_VERSION };
154
157
  }
158
+ function canonicalRewritePairs(pairs) {
159
+ const unique = /* @__PURE__ */ new Map();
160
+ for (const pair of pairs) {
161
+ const oldSha = pair.oldSha.toLowerCase();
162
+ const newSha = pair.newSha.toLowerCase();
163
+ if (!FULL_SHA_RE.test(oldSha) || !FULL_SHA_RE.test(newSha)) return null;
164
+ if (oldSha === newSha) continue;
165
+ unique.set(`${oldSha}\0${newSha}`, { oldSha, newSha });
166
+ }
167
+ return [...unique.values()].sort((left, right) => {
168
+ const leftKey = `${left.oldSha}\0${left.newSha}`;
169
+ const rightKey = `${right.oldSha}\0${right.newSha}`;
170
+ return leftKey < rightKey ? -1 : leftKey > rightKey ? 1 : 0;
171
+ }).slice(0, MAX_REWRITE_PAIRS_PER_HOOK);
172
+ }
173
+ function toRewriteMove(rewrite, cliVersion, cwd, context) {
174
+ const { repository, repoFullName, repoSyncId, workspaceId, capturedAt } = context;
175
+ if (rewrite.source !== "amend" && rewrite.source !== "rebase" || !isValidRepoSyncId(repoSyncId) || !workspaceId || !isCanonicalWorkspaceId(workspaceId)) {
176
+ return [];
177
+ }
178
+ const pairs = canonicalRewritePairs(rewrite.pairs);
179
+ if (!pairs || pairs.length === 0) return [];
180
+ const branch = rewrite.branch && rewrite.branch === rewrite.branch.trim() && ![...rewrite.branch].some((char) => char < " " || char === "\x7F") ? rewrite.branch : void 0;
181
+ const observedAt = typeof capturedAt === "number" && Number.isSafeInteger(capturedAt) && capturedAt > 0 ? capturedAt : Date.now();
182
+ const moves = [];
183
+ for (let offset = 0; offset < pairs.length; offset += MAX_REWRITE_PAIRS_PER_MOVE) {
184
+ const sortedPairs = pairs.slice(offset, offset + MAX_REWRITE_PAIRS_PER_MOVE);
185
+ const moveId = `rewrite:v1:${createHash("sha256").update(JSON.stringify(["rewrite:v1", repoSyncId, workspaceId, rewrite.source, sortedPairs])).digest("hex")}`;
186
+ moves.push({
187
+ moveId,
188
+ capturedAt: observedAt,
189
+ sessionId: "",
190
+ eventType: "git.rewrite",
191
+ payload: {
192
+ kind: "git.rewrite",
193
+ source: rewrite.source,
194
+ pairs: sortedPairs,
195
+ ...branch ? { branch } : {}
196
+ },
197
+ env: {
198
+ cwd,
199
+ cliVersion,
200
+ osPlatform: platform(),
201
+ ...repository ? {
202
+ repoRoot: repository.repoRoot,
203
+ repoKey: repository.repoKey,
204
+ gitRoot: repository.repoRoot
205
+ } : {},
206
+ ...repoFullName ? { repoFullName } : {},
207
+ repoSyncId,
208
+ workspaceId
209
+ },
210
+ envelopeVersion: ENVELOPE_VERSION
211
+ });
212
+ }
213
+ return moves;
214
+ }
155
215
  function shouldFlushAfter(eventType) {
156
216
  return eventType === "SessionEnd";
157
217
  }
@@ -162,5 +222,7 @@ export {
162
222
  toMove,
163
223
  commitAttributionFromEnvironment,
164
224
  toCommitMove,
225
+ canonicalRewritePairs,
226
+ toRewriteMove,
165
227
  shouldFlushAfter
166
228
  };
@@ -79,7 +79,8 @@ var CACHED_BINS = [
79
79
  "prim-hook",
80
80
  "prim-pre-tool-use",
81
81
  "prim-post-tool-use",
82
- "prim-post-commit"
82
+ "prim-post-commit",
83
+ "prim-post-rewrite"
83
84
  ];
84
85
  function binCacheDir() {
85
86
  const base = process.env.XDG_CACHE_HOME || join2(homedir(), ".cache");
@@ -422,10 +422,12 @@ function refreshToken(options = {}) {
422
422
  }
423
423
  var HttpError = class extends Error {
424
424
  status;
425
- constructor(status, message) {
425
+ body;
426
+ constructor(status, message, body) {
426
427
  super(message);
427
428
  this.name = "HttpError";
428
429
  this.status = status;
430
+ this.body = body;
429
431
  }
430
432
  };
431
433
  var _cachedCredential;
@@ -486,7 +488,9 @@ async function request(method, path, body, options) {
486
488
  throw new HttpError(401, AUTH_EXPIRED_MESSAGE);
487
489
  }
488
490
  const errorBody = await response.json().catch(() => null);
489
- throw new HttpError(response.status, errorBody?.error ?? `HTTP ${response.status}`);
491
+ const errorRecord = typeof errorBody === "object" && errorBody !== null && !Array.isArray(errorBody) ? errorBody : void 0;
492
+ const message = typeof errorRecord?.error === "string" ? errorRecord.error : `HTTP ${response.status}`;
493
+ throw new HttpError(response.status, message, errorBody);
490
494
  }
491
495
  return response.json();
492
496
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getClient
3
- } from "./chunk-CPX3BUOC.js";
3
+ } from "./chunk-RTLFE6EZ.js";
4
4
 
5
5
  // src/decisions/feedback.ts
6
6
  var FEEDBACK_PROTOCOL_VERSION = 1;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getSiteUrl
3
- } from "./chunk-CPX3BUOC.js";
3
+ } from "./chunk-RTLFE6EZ.js";
4
4
 
5
5
  // src/journal.ts
6
6
  import {