@gamaze/hicortex 0.18.3 → 0.19.0

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.
@@ -92,7 +92,14 @@ function isTokenBudgetExceeded(stateDir) {
92
92
  * consistent with total (distill + consolidation).
93
93
  */
94
94
  function recordDistillUsage(stateDir, usage) {
95
- if (cap <= 0 || usage.total <= 0)
95
+ // Record ALWAYS; the cap only governs ENFORCEMENT (isTokenBudgetExceeded)
96
+ // and the 80% warning below. Without this, an uncapped install (self-hosted
97
+ // default) never accrues distill tokens into the period meter, so the
98
+ // dashboard's monthly headline read consolidation-only while the per-run
99
+ // chart next to it showed true (distill-inclusive) totals — numbers on the
100
+ // same card telling different stories (#287 CR). Always-recording makes the
101
+ // meter the honest "what did this install spend" number everywhere.
102
+ if (usage.total <= 0)
96
103
  return;
97
104
  let newTotal = 0;
98
105
  let periodStart = "";
@@ -123,7 +130,8 @@ function recordDistillUsage(stateDir, usage) {
123
130
  periodStart = s.llmTokensThisPeriod.periodStart;
124
131
  }, stateDir);
125
132
  // 80% warning — dedup per period (once per month per threshold crossing).
126
- if (periodStart && warnedPeriod !== periodStart && newTotal >= cap * 0.8) {
133
+ // Cap-gated by design: no cap no percentage to warn about.
134
+ if (cap > 0 && periodStart && warnedPeriod !== periodStart && newTotal >= cap * 0.8) {
127
135
  warnedPeriod = periodStart;
128
136
  const pct = Math.round((newTotal / cap) * 100);
129
137
  console.warn(`[hicortex] Token usage at ${pct}% of monthly cap (${newTotal.toLocaleString()}/${cap.toLocaleString()}).`);
@@ -78,10 +78,13 @@ function buildTypeClassifyPrompt(content) {
78
78
  `occurrence ("tried X, failed because Y", a correction, a debugging session).\n` +
79
79
  `- knowledge: a durable truth that holds across sessions, not tied to a ` +
80
80
  `single moment ("the API is at :8787", "uv is used for packages").\n` +
81
- `- decisions: a choice made that future work builds on and a later ` +
82
- `decision can supersede ("switched from gemma4 to qwen3.5", "adopted the ` +
83
- `graded-schema tag model"). Not knowledge (it can change) and not an ` +
84
- `experience (it persists).\n\n` +
81
+ `- decisions: a choice the user explicitly made or confirmed (or one the ` +
82
+ `memory records as actually carried out/applied) that future work builds ` +
83
+ `on and a later decision can supersede ("switched from gemma4 to qwen3.5", ` +
84
+ `"adopted the graded-schema tag model"). Not knowledge (it can change) and ` +
85
+ `not an experience (it persists). A bare AI recommendation or proposal is ` +
86
+ `NEVER a decision — "AI proposed X → user declined/held" is experience ` +
87
+ `(#290).\n\n` +
85
88
  `IMPORTANCE (0.0–1.0):\n` +
86
89
  `- 0.8–1.0: load-bearing — a core piece of knowledge or a decision the ` +
87
90
  `agent must know.\n` +
package/dist/types.d.ts CHANGED
@@ -434,6 +434,46 @@ export interface HicortexConfig {
434
434
  * set it. Period resets monthly (state.json `llmTokensThisPeriod.periodStart`).
435
435
  */
436
436
  llmTokensPerMonth?: number;
437
+ /**
438
+ * Max request body size in MB accepted by the REST/MCP server (#7). The body
439
+ * is fully JSON-parsed into memory before the distiller truncates content to
440
+ * 80K chars, so an unbounded body is an OOM vector — a tenant (hosted) or a
441
+ * misbehaving client could POST a huge payload to exhaust RAM. Default: 25 MB
442
+ * self-hosted (unchanged), 5 MB hosted (the spec §6.3 figure — ~25× the 200KB
443
+ * segment max, so legitimate capture never approaches it; it's a pure
444
+ * abuse/OOM backstop). Oversized bodies get HTTP 413.
445
+ */
446
+ distillBodyLimitMb?: number;
447
+ /**
448
+ * Output directory for backup artifacts (#6). Default `<HICORTEX_HOME>/backups`.
449
+ * Both the CLI (`hicortex backup`) and the nightly backup stage resolve this
450
+ * before calling createBackup; an unset value falls back to the home dir.
451
+ * Operator-owned: point at a mounted backup volume, a tmpfs, etc.
452
+ */
453
+ backupDir?: string;
454
+ /**
455
+ * Post-backup offsite hook (#6). When set, `hicortex backup` and the nightly
456
+ * backup stage invoke this command with the artifact path appended as the LAST
457
+ * arg (e.g. `"rclone copyto"` → `rclone copyto <path> remote:bucket/`). Cloud
458
+ * credentials + active alerting (email/Discord) stay in the operator's wrapper
459
+ * script, out of the product. The hook is split on whitespace (no shell); a
460
+ * command with quoted args containing spaces should be a wrapper script. A
461
+ * failing/missing/timed-out hook reports `{ok:false}` and never throws —
462
+ * capture/consolidation have already succeeded, so a backup-hook failure must
463
+ * not fail the nightly. 5 min timeout.
464
+ */
465
+ backupCommand?: string;
466
+ /**
467
+ * Account identity shown in the dashboard header (hosted). When ALL three
468
+ * are absent the header renders no account element (self-hosted default —
469
+ * nothing changes). Strings only; read via readStringConfig, null when
470
+ * absent/not a string. Set per-tenant by provision-tenant.sh.
471
+ */
472
+ displayName?: string;
473
+ /** Organization name — rendered alongside displayName as "Name · Org". */
474
+ orgName?: string;
475
+ /** Plan/tier label rendered as a small badge (e.g. "Cloud · Early bird"). */
476
+ planLabel?: string;
437
477
  }
438
478
  /** A config-owned life-sphere domain (see HicortexConfig.domains). */
439
479
  export interface DomainDef {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gamaze/hicortex",
3
- "version": "0.18.3",
4
- "description": "Persistent agent identity for AI agents a hand-edited identity layer, nightly-distilled experience, and lessons injected every session, shared across your whole fleet. Works with Hermes, OpenClaw, Claude Code, and Pi.",
3
+ "version": "0.19.0",
4
+ "description": "Persistent agent identity for AI agents \u2014 a hand-edited identity layer, nightly-distilled experience, and lessons injected every session, shared across your whole fleet. Works with Hermes, OpenClaw, Claude Code, and Pi.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
7
  "hicortex": "dist/cli.js"
@@ -47,6 +47,7 @@
47
47
  "@types/better-sqlite3": "^7.6.0",
48
48
  "@types/express": "^5.0.6",
49
49
  "@types/node": "^22.0.0",
50
+ "@types/tar-stream": "^3.1.4",
50
51
  "typescript": "^5.4.0",
51
52
  "vitest": "^3.0.0"
52
53
  },
@@ -69,6 +70,7 @@
69
70
  "@modelcontextprotocol/sdk": "^1.28.0",
70
71
  "better-sqlite3": "^12.11.1",
71
72
  "express": "^4.21.0",
72
- "sqlite-vec": "^0.1.7"
73
+ "sqlite-vec": "^0.1.7",
74
+ "tar-stream": "^2.2.0"
73
75
  }
74
- }
76
+ }