@primitive.ai/prim 0.1.0-alpha.92 → 0.1.0-alpha.93

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +34 -2
  2. package/dist/{chunk-67VNLLBN.js → chunk-2GP5UFV7.js} +1 -0
  3. package/dist/{chunk-ADUTW66W.js → chunk-36TWVNBE.js} +6 -6
  4. package/dist/{chunk-5HRR4AOR.js → chunk-C3VAA5CG.js} +1 -1
  5. package/dist/{chunk-LGGMJYY4.js → chunk-DCJN6LZH.js} +37 -5
  6. package/dist/{chunk-M6RIJVRE.js → chunk-DSWT6BCC.js} +78 -4
  7. package/dist/{chunk-FBAYCS3X.js → chunk-DXJQR4QI.js} +150 -38
  8. package/dist/{chunk-PCVGBE5B.js → chunk-G2VMA2QO.js} +2 -1
  9. package/dist/{chunk-NAHHFSLH.js → chunk-ICM2XCXS.js} +2 -2
  10. package/dist/{chunk-OAAP2MY6.js → chunk-K7D2EYBS.js} +2 -2
  11. package/dist/{chunk-5AFRMOPX.js → chunk-OH3EZXYX.js} +1 -1
  12. package/dist/{chunk-KFXF2V5G.js → chunk-OTHKG76J.js} +1 -1
  13. package/dist/chunk-OYHYCK4K.js +13 -0
  14. package/dist/{chunk-FKXFUUWJ.js → chunk-TYAHC25F.js} +1 -1
  15. package/dist/{chunk-5GYQ4J3D.js → chunk-UKUAAAXE.js} +2 -2
  16. package/dist/{chunk-26P57LAR.js → chunk-X64HTHUF.js} +3 -1
  17. package/dist/{chunk-WX52U7Z2.js → chunk-ZU563PQI.js} +58 -2
  18. package/dist/daemon/server.js +372 -123
  19. package/dist/hook-runtime/daemon/server.js +372 -123
  20. package/dist/hook-runtime/hooks/post-commit.js +57 -39
  21. package/dist/hook-runtime/hooks/post-rewrite.js +58 -40
  22. package/dist/hook-runtime/hooks/post-tool-use.js +95 -62
  23. package/dist/hook-runtime/hooks/pre-tool-use.js +32 -10
  24. package/dist/hook-runtime/hooks/prim-hook.js +142 -102
  25. package/dist/hook-runtime/hooks/session-start.js +37 -3
  26. package/dist/hook-runtime/index.js +1264 -523
  27. package/dist/hook-runtime/statusline-main.js +23 -1
  28. package/dist/hooks/post-commit.js +11 -8
  29. package/dist/hooks/post-rewrite.js +11 -8
  30. package/dist/hooks/post-tool-use.js +13 -15
  31. package/dist/hooks/pre-commit.js +4 -4
  32. package/dist/hooks/pre-tool-use.js +10 -12
  33. package/dist/hooks/prim-hook.js +17 -14
  34. package/dist/hooks/session-end.js +4 -4
  35. package/dist/hooks/session-start.js +12 -36
  36. package/dist/index.js +857 -290
  37. package/dist/statusline-main.js +23 -1
  38. package/package.json +1 -1
  39. package/dist/chunk-BTNNEH2W.js +0 -79
@@ -52,8 +52,8 @@ var require_ucs2length = __commonJS({
52
52
  });
53
53
 
54
54
  // src/hooks/post-tool-use.ts
55
- import { readFileSync as readFileSync14 } from "fs";
56
- import { dirname as dirname11, join as join16 } from "path";
55
+ import { readFileSync as readFileSync15 } from "fs";
56
+ import { dirname as dirname12, join as join17 } from "path";
57
57
  import { fileURLToPath as fileURLToPath2 } from "url";
58
58
 
59
59
  // src/binding.ts
@@ -20022,6 +20022,67 @@ function detachedHookShimCommand(bin, args = "") {
20022
20022
  return `payload=$(cat); { trap '' HUP; printf '%s' "$payload" | { ${stableHookCommand(bin, args)}; }; } </dev/null >/dev/null 2>&1 &`;
20023
20023
  }
20024
20024
 
20025
+ // src/lib/ansi.ts
20026
+ var ANSI_CODES = {
20027
+ yellow: "\x1B[33m",
20028
+ magenta: "\x1B[35m",
20029
+ blue: "\x1B[34m",
20030
+ cyan: "\x1B[36m",
20031
+ green: "\x1B[32m",
20032
+ red: "\x1B[31m",
20033
+ // 256-color approximation of the orange trigger marker (xterm 208).
20034
+ orange: "\x1B[38;5;208m",
20035
+ gray: "\x1B[90m"
20036
+ };
20037
+ var ANSI_RESET = "\x1B[0m";
20038
+ var ANSI_BOLD = "\x1B[1m";
20039
+ function supportsColor() {
20040
+ if (process.env.NO_COLOR !== void 0 && process.env.NO_COLOR !== "") {
20041
+ return false;
20042
+ }
20043
+ return process.stderr.isTTY === true;
20044
+ }
20045
+ function color(text, c) {
20046
+ if (!supportsColor()) {
20047
+ return text;
20048
+ }
20049
+ return `${ANSI_CODES[c]}${text}${ANSI_RESET}`;
20050
+ }
20051
+ function bold(text) {
20052
+ if (!supportsColor()) {
20053
+ return text;
20054
+ }
20055
+ return `${ANSI_BOLD}${text}${ANSI_RESET}`;
20056
+ }
20057
+ var MAX_HEALTH_ERROR_LENGTH = 240;
20058
+ function boundedHealthError(value) {
20059
+ if (!value) return void 0;
20060
+ const clean = terminalSafeLine(value);
20061
+ if (!clean) return void 0;
20062
+ return clean.length <= MAX_HEALTH_ERROR_LENGTH ? clean : `${clean.slice(0, MAX_HEALTH_ERROR_LENGTH - 1)}\u2026`;
20063
+ }
20064
+
20065
+ // src/lib/delivery-backlog.ts
20066
+ var MS_PER_SECOND = 1e3;
20067
+ var MS_PER_MINUTE = 60 * MS_PER_SECOND;
20068
+ var MS_PER_HOUR = 60 * MS_PER_MINUTE;
20069
+ var MS_PER_DAY = 24 * MS_PER_HOUR;
20070
+ function isNonNegativeInteger(value) {
20071
+ return typeof value === "number" && Number.isInteger(value) && value >= 0;
20072
+ }
20073
+ function isPositiveInteger(value) {
20074
+ return isNonNegativeInteger(value) && value > 0;
20075
+ }
20076
+ function deliveryBacklogState(ingestion) {
20077
+ if (ingestion?.healthy !== false) return void 0;
20078
+ const failures = ingestion.consecutiveFailures;
20079
+ const failedWithoutProgress = failures !== 0 && !(isPositiveInteger(failures) && isPositiveInteger(ingestion.lastFailedDrainAcknowledgedCount));
20080
+ if (failedWithoutProgress) return "failing";
20081
+ const retained = ingestion.lastRetainedBucketCount;
20082
+ if (!isNonNegativeInteger(retained)) return "failing";
20083
+ return retained > 0 ? "retained" : "draining";
20084
+ }
20085
+
20025
20086
  // src/lib/presence.ts
20026
20087
  var DECISION_ORIGIN = "https://app.getprimitive.ai";
20027
20088
  function validDecisionUrl(value) {
@@ -20096,7 +20157,8 @@ function formatStatusline(version, snapshot, resolveIngestionStatus, options = {
20096
20157
  if (snapshot.ingestion?.healthy === false) {
20097
20158
  const pending = snapshot.ingestion.pendingCount;
20098
20159
  const qualifier = snapshot.ingestion.pendingSampled ? "at least " : "";
20099
- return `primitive ${version} (daemon: degraded \xB7 delivery: stalled${typeof pending === "number" ? ` \xB7 ${qualifier}${String(pending)} pending` : ""}${repositorySuffix}${ingestionSuffix(ingestionStatus)})`;
20160
+ const delivery = deliveryBacklogState(snapshot.ingestion) === "draining" && snapshot.heartbeat?.healthy === true ? "draining" : "stalled";
20161
+ return `primitive ${version} (daemon: degraded \xB7 delivery: ${delivery}${typeof pending === "number" ? ` \xB7 ${qualifier}${String(pending)} pending` : ""}${repositorySuffix}${ingestionSuffix(ingestionStatus)})`;
20100
20162
  }
20101
20163
  if (snapshot.heartbeat?.healthy === false) {
20102
20164
  return `primitive ${version} (daemon: degraded \xB7 presence: unavailable${repositorySuffix}${ingestionSuffix(ingestionStatus)})`;
@@ -25682,17 +25744,30 @@ function requireDurableIngestAcknowledgement(value, expected, cwd = process.cwd(
25682
25744
  import {
25683
25745
  appendFileSync,
25684
25746
  closeSync as closeSync3,
25685
- existsSync as existsSync10,
25747
+ existsSync as existsSync11,
25686
25748
  fstatSync,
25687
25749
  mkdirSync as mkdirSync7,
25688
25750
  openSync as openSync3,
25689
25751
  opendirSync,
25690
- readFileSync as readFileSync12,
25752
+ readFileSync as readFileSync13,
25691
25753
  readSync,
25692
- readdirSync as readdirSync3
25754
+ readdirSync as readdirSync4
25693
25755
  } from "fs";
25694
- import { dirname as dirname10, join as join14 } from "path";
25695
- var JOURNAL_DIR = join14(primConfigDirectory(), "moves");
25756
+ import { dirname as dirname11, join as join15 } from "path";
25757
+
25758
+ // src/drain-progress.ts
25759
+ import {
25760
+ chmodSync as chmodSync5,
25761
+ existsSync as existsSync10,
25762
+ readFileSync as readFileSync12,
25763
+ readdirSync as readdirSync3,
25764
+ rmSync as rmSync6,
25765
+ rmdirSync
25766
+ } from "fs";
25767
+ import { basename as basename2, dirname as dirname10, join as join14 } from "path";
25768
+
25769
+ // src/journal.ts
25770
+ var JOURNAL_DIR = join15(primConfigDirectory(), "moves");
25696
25771
  var UNBOUND_BUCKET = "_unbound";
25697
25772
  var JOURNAL_BASENAME = "journal.ndjson";
25698
25773
  var JOURNAL_STATS_SAMPLE_BYTES = 64 * 1024;
@@ -25704,15 +25779,15 @@ function envSlug(apiUrl) {
25704
25779
  return slug;
25705
25780
  }
25706
25781
  function currentEnvDir() {
25707
- return join14(JOURNAL_DIR, envSlug(getSiteUrl()));
25782
+ return join15(JOURNAL_DIR, envSlug(getSiteUrl()));
25708
25783
  }
25709
25784
  var DIR_MODE = 448;
25710
25785
  var FILE_MODE2 = 384;
25711
25786
  var SAFE_BUCKET = /^[A-Za-z0-9_-]+$/;
25712
25787
  var RESERVED_BUCKETS = /* @__PURE__ */ new Set([UNBOUND_BUCKET, "_legacy"]);
25713
25788
  function appendMoveToPath(path, move) {
25714
- const dir = dirname10(path);
25715
- if (!existsSync10(dir)) {
25789
+ const dir = dirname11(path);
25790
+ if (!existsSync11(dir)) {
25716
25791
  mkdirSync7(dir, { recursive: true, mode: DIR_MODE });
25717
25792
  }
25718
25793
  appendFileSync(path, `${JSON.stringify(move)}
@@ -25720,10 +25795,10 @@ function appendMoveToPath(path, move) {
25720
25795
  }
25721
25796
  function bucketDir(orgId) {
25722
25797
  const safe = orgId !== void 0 && SAFE_BUCKET.test(orgId) && !RESERVED_BUCKETS.has(orgId);
25723
- return join14(currentEnvDir(), safe ? orgId : UNBOUND_BUCKET);
25798
+ return join15(currentEnvDir(), safe ? orgId : UNBOUND_BUCKET);
25724
25799
  }
25725
25800
  function journalPath(orgId) {
25726
- return join14(bucketDir(orgId), JOURNAL_BASENAME);
25801
+ return join15(bucketDir(orgId), JOURNAL_BASENAME);
25727
25802
  }
25728
25803
  function appendMove(move, orgId) {
25729
25804
  appendMoveToPath(journalPath(orgId), move);
@@ -25750,51 +25825,9 @@ import { platform } from "os";
25750
25825
  var AGENT_ENVELOPE_VERSION = 3;
25751
25826
 
25752
25827
  // src/hooks/redact.ts
25753
- import { existsSync as existsSync11, readFileSync as readFileSync13, statSync as statSync5 } from "fs";
25754
- import { join as join15 } from "path";
25828
+ import { existsSync as existsSync12, readFileSync as readFileSync14, statSync as statSync5 } from "fs";
25829
+ import { join as join16 } from "path";
25755
25830
  import { Worker } from "worker_threads";
25756
-
25757
- // src/lib/ansi.ts
25758
- var ANSI_CODES = {
25759
- yellow: "\x1B[33m",
25760
- magenta: "\x1B[35m",
25761
- blue: "\x1B[34m",
25762
- cyan: "\x1B[36m",
25763
- green: "\x1B[32m",
25764
- red: "\x1B[31m",
25765
- // 256-color approximation of the orange trigger marker (xterm 208).
25766
- orange: "\x1B[38;5;208m",
25767
- gray: "\x1B[90m"
25768
- };
25769
- var ANSI_RESET = "\x1B[0m";
25770
- var ANSI_BOLD = "\x1B[1m";
25771
- function supportsColor() {
25772
- if (process.env.NO_COLOR !== void 0 && process.env.NO_COLOR !== "") {
25773
- return false;
25774
- }
25775
- return process.stderr.isTTY === true;
25776
- }
25777
- function color(text, c) {
25778
- if (!supportsColor()) {
25779
- return text;
25780
- }
25781
- return `${ANSI_CODES[c]}${text}${ANSI_RESET}`;
25782
- }
25783
- function bold(text) {
25784
- if (!supportsColor()) {
25785
- return text;
25786
- }
25787
- return `${ANSI_BOLD}${text}${ANSI_RESET}`;
25788
- }
25789
- var MAX_HEALTH_ERROR_LENGTH = 240;
25790
- function boundedHealthError(value) {
25791
- if (!value) return void 0;
25792
- const clean = terminalSafeLine(value);
25793
- if (!clean) return void 0;
25794
- return clean.length <= MAX_HEALTH_ERROR_LENGTH ? clean : `${clean.slice(0, MAX_HEALTH_ERROR_LENGTH - 1)}\u2026`;
25795
- }
25796
-
25797
- // src/hooks/redact.ts
25798
25831
  var USER_HOME_RULES = [
25799
25832
  {
25800
25833
  pattern: /\/Users\/[^/\\\s"'`]+/g,
@@ -25869,15 +25902,15 @@ function normalizedWorkspaceFlags(value) {
25869
25902
  return [...new Set(`g${requested}`)].sort().join("");
25870
25903
  }
25871
25904
  function loadWorkspaceRules(cwd) {
25872
- const path = join15(cwd, WORKSPACE_FILE2);
25873
- if (!existsSync11(path)) return [];
25905
+ const path = join16(cwd, WORKSPACE_FILE2);
25906
+ if (!existsSync12(path)) return [];
25874
25907
  let cfg;
25875
25908
  try {
25876
25909
  if (statSync5(path).size > MAX_WORKSPACE_CONFIG_BYTES) {
25877
25910
  debugRedaction(`ignoring oversized ${WORKSPACE_FILE2}`);
25878
25911
  return [];
25879
25912
  }
25880
- cfg = JSON.parse(readFileSync13(path, "utf-8"));
25913
+ cfg = JSON.parse(readFileSync14(path, "utf-8"));
25881
25914
  } catch {
25882
25915
  debugRedaction(`ignoring unparseable ${WORKSPACE_FILE2}`);
25883
25916
  return [];
@@ -26182,10 +26215,10 @@ function editingToolsFor(agent) {
26182
26215
  }
26183
26216
  return EDITING_TOOLS;
26184
26217
  }
26185
- var here = dirname11(fileURLToPath2(import.meta.url));
26218
+ var here = dirname12(fileURLToPath2(import.meta.url));
26186
26219
  function resolveCliVersion() {
26187
26220
  try {
26188
- const pkg = JSON.parse(readFileSync14(join16(here, "..", "..", "package.json"), "utf-8"));
26221
+ const pkg = JSON.parse(readFileSync15(join17(here, "..", "..", "package.json"), "utf-8"));
26189
26222
  return pkg.version ?? "unknown";
26190
26223
  } catch {
26191
26224
  return "unknown";
@@ -19677,6 +19677,36 @@ function isActionablePrivateDraft(row) {
19677
19677
  return typeof candidate.id === "string" && SAFE_PRIVATE_DRAFT_ID.test(candidate.id) && typeof candidate.intent === "string" && candidate.authorIsSelf === true && candidate.stage === "draft" && (candidate.intentKind === void 0 || candidate.intentKind === "change");
19678
19678
  }
19679
19679
 
19680
+ // src/lib/ansi.ts
19681
+ var MAX_HEALTH_ERROR_LENGTH = 240;
19682
+ function boundedHealthError(value) {
19683
+ if (!value) return void 0;
19684
+ const clean = terminalSafeLine(value);
19685
+ if (!clean) return void 0;
19686
+ return clean.length <= MAX_HEALTH_ERROR_LENGTH ? clean : `${clean.slice(0, MAX_HEALTH_ERROR_LENGTH - 1)}\u2026`;
19687
+ }
19688
+
19689
+ // src/lib/delivery-backlog.ts
19690
+ var MS_PER_SECOND = 1e3;
19691
+ var MS_PER_MINUTE = 60 * MS_PER_SECOND;
19692
+ var MS_PER_HOUR = 60 * MS_PER_MINUTE;
19693
+ var MS_PER_DAY = 24 * MS_PER_HOUR;
19694
+ function isNonNegativeInteger(value) {
19695
+ return typeof value === "number" && Number.isInteger(value) && value >= 0;
19696
+ }
19697
+ function isPositiveInteger(value) {
19698
+ return isNonNegativeInteger(value) && value > 0;
19699
+ }
19700
+ function deliveryBacklogState(ingestion) {
19701
+ if (ingestion?.healthy !== false) return void 0;
19702
+ const failures = ingestion.consecutiveFailures;
19703
+ const failedWithoutProgress = failures !== 0 && !(isPositiveInteger(failures) && isPositiveInteger(ingestion.lastFailedDrainAcknowledgedCount));
19704
+ if (failedWithoutProgress) return "failing";
19705
+ const retained = ingestion.lastRetainedBucketCount;
19706
+ if (!isNonNegativeInteger(retained)) return "failing";
19707
+ return retained > 0 ? "retained" : "draining";
19708
+ }
19709
+
19680
19710
  // src/lib/presence.ts
19681
19711
  var DECISION_ORIGIN = "https://app.getprimitive.ai";
19682
19712
  function validDecisionUrl(value) {
@@ -19751,7 +19781,8 @@ function formatStatusline(version, snapshot, resolveIngestionStatus, options = {
19751
19781
  if (snapshot.ingestion?.healthy === false) {
19752
19782
  const pending = snapshot.ingestion.pendingCount;
19753
19783
  const qualifier = snapshot.ingestion.pendingSampled ? "at least " : "";
19754
- return `primitive ${version} (daemon: degraded \xB7 delivery: stalled${typeof pending === "number" ? ` \xB7 ${qualifier}${String(pending)} pending` : ""}${repositorySuffix}${ingestionSuffix(ingestionStatus)})`;
19784
+ const delivery = deliveryBacklogState(snapshot.ingestion) === "draining" && snapshot.heartbeat?.healthy === true ? "draining" : "stalled";
19785
+ return `primitive ${version} (daemon: degraded \xB7 delivery: ${delivery}${typeof pending === "number" ? ` \xB7 ${qualifier}${String(pending)} pending` : ""}${repositorySuffix}${ingestionSuffix(ingestionStatus)})`;
19755
19786
  }
19756
19787
  if (snapshot.heartbeat?.healthy === false) {
19757
19788
  return `primitive ${version} (daemon: degraded \xB7 presence: unavailable${repositorySuffix}${ingestionSuffix(ingestionStatus)})`;
@@ -20945,15 +20976,6 @@ function demoteForMode(verdict, mode) {
20945
20976
  // src/hooks/preflight-v3.ts
20946
20977
  import { Buffer as Buffer2 } from "buffer";
20947
20978
 
20948
- // src/lib/ansi.ts
20949
- var MAX_HEALTH_ERROR_LENGTH = 240;
20950
- function boundedHealthError(value) {
20951
- if (!value) return void 0;
20952
- const clean = terminalSafeLine(value);
20953
- if (!clean) return void 0;
20954
- return clean.length <= MAX_HEALTH_ERROR_LENGTH ? clean : `${clean.slice(0, MAX_HEALTH_ERROR_LENGTH - 1)}\u2026`;
20955
- }
20956
-
20957
20979
  // src/hooks/redact.ts
20958
20980
  import { existsSync as existsSync9, readFileSync as readFileSync10, statSync as statSync4 } from "fs";
20959
20981
  import { join as join12 } from "path";