@juli-os/ledger 0.1.1 → 0.1.3

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/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  export { createLedgerStore, type LifecycleStore } from './platform/ledger/store.ts';
2
2
  export type { Workflow, Step, WorkflowStatus, StepStatus, StepKind } from './contracts/entities.ts';
3
- export { createUsageStore, type UsageStore, type UsageStats } from './platform/ledger/usage.ts';
4
- export { priceUsage, findPrice, type UsageCost, type UsageRow } from './platform/ledger/pricing.ts';
5
- export { emptyCaseFile, parseCaseFile, serializeCaseFile, type CaseFileDoc, appendSection, appendExecution, appendDecision, appendReference, originalEmail, } from './platform/ledger/casefile.ts';
3
+ export { TERMINAL_WORKFLOW_STATUSES, STEP_KINDS, AGENT_STEP_KINDS, INSTRUCTABLE_STEP_KINDS, type LedgerEvent, type Run, type Prompt, type TaskView, } from './contracts/entities.ts';
4
+ export { createUsageStore, type UsageRecord, type UsageStats, type TimelinePoint, type UsageStore, } from './platform/ledger/usage.ts';
5
+ export { findPrice, priceUsage, type TierWhen, type PriceTier, type ModelPrice, PRICING_SOURCE, PRICING_RETRIEVED_AT, BIGMODEL_PRICES, type UsageRow, type CostBreakdown, type ModelUsageCost, type UsageCost, } from './platform/ledger/pricing.ts';
6
+ export { emptyCaseFile, parseCaseFile, serializeCaseFile, withOriginal, appendSection, appendExecution, appendDecision, appendReference, originalEmail, type CaseDecision, type ArtifactRef, type CaseFileDoc, } from './platform/ledger/casefile.ts';
6
7
  export { rfc3339, systemClock, randomIds, type Clock, type IdGen } from './platform/shared/clock.ts';
7
8
  export { asRecord, safeParse, type JsonRecord, type JsonValue } from './platform/shared/json.ts';
package/dist/index.js CHANGED
@@ -29,7 +29,18 @@ var TERMINAL_WORKFLOW_STATUSES = [
29
29
  "cancelled",
30
30
  "rejected"
31
31
  ];
32
+ var STEP_KINDS = [
33
+ "triage",
34
+ "gate",
35
+ "agent",
36
+ "verify",
37
+ "draft",
38
+ "send",
39
+ "llm",
40
+ "share"
41
+ ];
32
42
  var AGENT_STEP_KINDS = ["agent", "verify"];
43
+ var INSTRUCTABLE_STEP_KINDS = ["agent", "verify", "llm", "draft"];
33
44
 
34
45
  // src/contracts/statuses.ts
35
46
  var WORKFLOW_STATUSES = [
@@ -103,6 +114,21 @@ var parseCaseFile = (raw, now) => {
103
114
  };
104
115
  };
105
116
  var serializeCaseFile = (cf) => JSON.stringify(cf);
117
+ var withOriginal = (cf, o, now) => ({
118
+ ...cf,
119
+ original: {
120
+ from: o.from,
121
+ // Sender display name (RFC2047-decoded) — recorded into the case file with
122
+ // the original message after the 2026-10-01 Chen Lijun hallucination
123
+ // incident: the legitimate source for reply salutations, so the agent is no
124
+ // longer forced to invent a name from the address.
125
+ ...o.fromName !== void 0 && o.fromName !== "" ? { from_name: o.fromName } : {},
126
+ subject: o.subject,
127
+ body: o.body,
128
+ message_id: o.messageId
129
+ },
130
+ updatedAt: rfc3339(now)
131
+ });
106
132
  var appendSection = (cf, section, value, now) => ({
107
133
  ...cf,
108
134
  ...section === "extract" ? { extract: value } : { draft: value },
@@ -573,9 +599,11 @@ var createLedgerStore = (dbPath, deps = {}) => {
573
599
  };
574
600
  },
575
601
  activeRunForSession: (session) => activeRunOf(session),
576
- /** 活跃去重:同 dedup_key 且工作流仍在途 → 跳过重复建流。
577
- * ⚠ ESCAPE '\' 必须与转义成对:message-id 几乎必含 `_`,漏写 ESCAPE 时
578
- * `\_` 成了"字面反斜杠+任意字符",模式永不匹配——去重整体失效(09-07 事故)。 */
602
+ /** Active dedup: same dedup_key and the workflow still in flight → skip
603
+ * creating a duplicate. ⚠ ESCAPE '\' must pair with the escaping: a
604
+ * message-id almost always contains `_`; without ESCAPE, `\_` becomes
605
+ * "literal backslash + any character", the pattern never matches — and
606
+ * dedup fails wholesale (09-07 incident). */
579
607
  hasActiveDedup(key) {
580
608
  const r = db.prepare(
581
609
  `SELECT 1 FROM workflows WHERE status IN (${sqlInList(DEDUP_WINDOW_STATUSES)})
@@ -583,8 +611,10 @@ var createLedgerStore = (dbPath, deps = {}) => {
583
611
  ).get(dedupPattern(key));
584
612
  return r !== void 0;
585
613
  },
586
- /** 已摄取去重(轮询层):同 dedup_key 存在任何非 rejected 工作流 → 这封
587
- * 邮件已被处理过(含 failed),轮询不再重复拉取。重试走步骤 retry,不走再摄取。 */
614
+ /** Ingested dedup (polling layer): any non-rejected workflow with the same
615
+ * dedup_key → this email has already been handled (failed included);
616
+ * polling won't fetch it again. Retries go through step retry, not
617
+ * re-ingestion. */
588
618
  hasSeenDedup(key) {
589
619
  const r = db.prepare(
590
620
  `SELECT 1 FROM workflows WHERE status != 'rejected'
@@ -592,11 +622,14 @@ var createLedgerStore = (dbPath, deps = {}) => {
592
622
  ).get(dedupPattern(key));
593
623
  return r !== void 0;
594
624
  },
595
- /** 自回环守卫查询(2026-09-20 断点十三):message_id 是否命中本引擎已
596
- * 发送记录——completed send 步的 output.message_id(email_sent 事件同源
597
- * 落账)。进件层据此丢弃投递副本回灌(引擎给轮询邮箱自己发信的 echo)。
598
- * LIKE 预筛 + 精确比对:JSON 编码取实际存储字节,%/_/\ 照 dedupPattern
599
- * 成对转义(message-id 几乎必含 `_`)。 */
625
+ /** Self-loop guard query (2026-09-20 breakpoint 13): does the message_id
626
+ * hit a record this engine already sent — the output.message_id of a
627
+ * completed send step (booked from the same source as email_sent events)?
628
+ * The intake layer uses this to discard delivery-copy feedback (the echo
629
+ * of the engine mailing the polling mailbox itself). LIKE prefilter +
630
+ * exact comparison: JSON-encode to the actually stored bytes; %/_/\ are
631
+ * escaped in pairs like dedupPattern (a message-id almost always contains
632
+ * `_`). */
600
633
  recordSentMessageId(messageId, meta) {
601
634
  if (messageId === "") return;
602
635
  db.prepare(
@@ -708,59 +741,61 @@ var PRICING_SOURCE = "https://docs.bigmodel.cn/cn/guide/start/pricing";
708
741
  var PRICING_RETRIEVED_AT = "2026-10-06";
709
742
  var K32 = 32e3;
710
743
  var K200 = 200;
711
- var flat = (input, cache, output, note = "\u7EDF\u4E00\u4EF7") => ({ when: {}, input, cache, output, note });
744
+ var flat = (input, cache, output, note = "flat rate") => ({ when: {}, input, cache, output, note });
712
745
  var BIGMODEL_PRICES = [
746
+ // ---- Flagship ----
713
747
  { id: "glm-5.3", label: "GLM-5.3", tiers: [flat(8, 2, 28)] },
714
748
  { id: "glm-5.3-flash", label: "GLM-5.3-Flash", tiers: [flat(0.8, 0.23, 2.8)] },
715
749
  { id: "glm-5.3-flashx", label: "GLM-5.3-FlashX", tiers: [flat(2, 0.57, 7)] },
750
+ // ---- Text ----
716
751
  { id: "glm-5.2", label: "GLM-5.2", tiers: [flat(8, 2, 28)] },
717
752
  {
718
753
  id: "glm-5.1",
719
754
  label: "GLM-5.1",
720
755
  tiers: [
721
- { when: { inputLt: K32 }, input: 6, cache: 1.3, output: 24, note: "\u5165<32K" },
722
- { when: { inputGte: K32 }, input: 8, cache: 2, output: 28, note: "\u5165\u226532K" }
756
+ { when: { inputLt: K32 }, input: 6, cache: 1.3, output: 24, note: "in<32K" },
757
+ { when: { inputGte: K32 }, input: 8, cache: 2, output: 28, note: "in>=32K" }
723
758
  ]
724
759
  },
725
760
  {
726
761
  id: "glm-5-turbo",
727
762
  label: "GLM-5-Turbo",
728
763
  tiers: [
729
- { when: { inputLt: K32 }, input: 5, cache: 1.2, output: 22, note: "\u5165<32K" },
730
- { when: { inputGte: K32 }, input: 7, cache: 1.8, output: 26, note: "\u5165\u226532K" }
764
+ { when: { inputLt: K32 }, input: 5, cache: 1.2, output: 22, note: "in<32K" },
765
+ { when: { inputGte: K32 }, input: 7, cache: 1.8, output: 26, note: "in>=32K" }
731
766
  ]
732
767
  },
733
768
  {
734
769
  id: "glm-5",
735
770
  label: "GLM-5",
736
771
  tiers: [
737
- { when: { inputLt: K32 }, input: 4, cache: 1, output: 18, note: "\u5165<32K" },
738
- { when: { inputGte: K32 }, input: 6, cache: 1.5, output: 22, note: "\u5165\u226532K" }
772
+ { when: { inputLt: K32 }, input: 4, cache: 1, output: 18, note: "in<32K" },
773
+ { when: { inputGte: K32 }, input: 6, cache: 1.5, output: 22, note: "in>=32K" }
739
774
  ]
740
775
  },
741
776
  {
742
777
  id: "glm-4.7",
743
778
  label: "GLM-4.7",
744
779
  tiers: [
745
- { when: { inputLt: K32, outputLt: K200 }, input: 2, cache: 0.4, output: 8, note: "\u5165<32K\xB7\u51FA<0.2K" },
746
- { when: { inputLt: K32, outputGte: K200 }, input: 3, cache: 0.6, output: 14, note: "\u5165<32K\xB7\u51FA\u22650.2K" },
747
- { when: { inputGte: K32 }, input: 4, cache: 0.8, output: 16, note: "\u516532K\u2013200K" }
780
+ { when: { inputLt: K32, outputLt: K200 }, input: 2, cache: 0.4, output: 8, note: "in<32K\xB7out<0.2K" },
781
+ { when: { inputLt: K32, outputGte: K200 }, input: 3, cache: 0.6, output: 14, note: "in<32K\xB7out>=0.2K" },
782
+ { when: { inputGte: K32 }, input: 4, cache: 0.8, output: 16, note: "in 32K\u2013200K" }
748
783
  ]
749
784
  },
750
785
  {
751
786
  id: "glm-4.5-air",
752
787
  label: "GLM-4.5-Air",
753
788
  tiers: [
754
- { when: { inputLt: K32, outputLt: K200 }, input: 0.8, cache: 0.16, output: 2, note: "\u5165<32K\xB7\u51FA<0.2K" },
755
- { when: { inputLt: K32, outputGte: K200 }, input: 0.8, cache: 0.16, output: 6, note: "\u5165<32K\xB7\u51FA\u22650.2K" },
756
- { when: { inputGte: K32 }, input: 1.2, cache: 0.24, output: 8, note: "\u516532K\u2013128K" }
789
+ { when: { inputLt: K32, outputLt: K200 }, input: 0.8, cache: 0.16, output: 2, note: "in<32K\xB7out<0.2K" },
790
+ { when: { inputLt: K32, outputGte: K200 }, input: 0.8, cache: 0.16, output: 6, note: "in<32K\xB7out>=0.2K" },
791
+ { when: { inputGte: K32 }, input: 1.2, cache: 0.24, output: 8, note: "in 32K\u2013128K" }
757
792
  ]
758
793
  },
759
794
  { id: "glm-4.7-flashx", label: "GLM-4.7-FlashX", tiers: [flat(0.5, 0.1, 3)] },
760
- { id: "glm-4.7-flash", label: "GLM-4.7-Flash\uFF08\u514D\u8D39\uFF09", tiers: [flat(0, 0, 0, "\u514D\u8D39")] },
795
+ { id: "glm-4.7-flash", label: "GLM-4.7-Flash (free)", tiers: [flat(0, 0, 0, "free")] },
761
796
  { id: "glm-4-plus", label: "GLM-4-Plus", tiers: [flat(5, 2.5, 5)] },
762
797
  { id: "glm-4-air-250414", label: "GLM-4-Air-250414", tiers: [flat(0.5, 0.25, 0.5)] },
763
- { id: "glm-4-air", label: "GLM-4-Air\uFF08\u540C 250414 \u7248\u4EF7\uFF09", tiers: [flat(0.5, 0.25, 0.5)] },
798
+ { id: "glm-4-air", label: "GLM-4-Air (same price as 250414)", tiers: [flat(0.5, 0.25, 0.5)] },
764
799
  { id: "glm-4-airx", label: "GLM-4-AirX", tiers: [flat(10, null, 10)] },
765
800
  { id: "glm-4-long", label: "GLM-4-Long", tiers: [flat(1, 0.5, 1)] },
766
801
  { id: "glm-4-assistant", label: "GLM-4-Assistant", tiers: [flat(5, null, 5)] },
@@ -768,53 +803,55 @@ var BIGMODEL_PRICES = [
768
803
  { id: "glm-z1-airx", label: "GLM-Z1-AirX", tiers: [flat(5, null, 5)] },
769
804
  { id: "glm-z1-flashx", label: "GLM-Z1-FlashX", tiers: [flat(0.1, null, 0.1)] },
770
805
  { id: "glm-4-flashx-250414", label: "GLM-4-FlashX-250414", tiers: [flat(0.1, 0.05, 0.1)] },
771
- { id: "glm-4-flashx", label: "GLM-4-FlashX\uFF08\u540C 250414 \u7248\u4EF7\uFF09", tiers: [flat(0.1, 0.05, 0.1)] },
772
- { id: "glm-4-flash-250414", label: "GLM-4-Flash-250414\uFF08\u514D\u8D39\uFF09", tiers: [flat(0, null, 0, "\u514D\u8D39\xB7\u7F13\u5B58\u4E0D\u652F\u6301")] },
773
- { id: "glm-4-flash", label: "GLM-4-Flash\uFF08\u514D\u8D39\uFF09", tiers: [flat(0, null, 0, "\u514D\u8D39\xB7\u7F13\u5B58\u4E0D\u652F\u6301")] },
774
- { id: "glm-z1-flash", label: "GLM-Z1-Flash\uFF08\u514D\u8D39\uFF09", tiers: [flat(0, null, 0, "\u514D\u8D39\xB7\u7F13\u5B58\u4E0D\u652F\u6301")] },
806
+ { id: "glm-4-flashx", label: "GLM-4-FlashX (same price as 250414)", tiers: [flat(0.1, 0.05, 0.1)] },
807
+ { id: "glm-4-flash-250414", label: "GLM-4-Flash-250414 (free)", tiers: [flat(0, null, 0, "free \xB7 cache unsupported")] },
808
+ { id: "glm-4-flash", label: "GLM-4-Flash (free)", tiers: [flat(0, null, 0, "free \xB7 cache unsupported")] },
809
+ { id: "glm-z1-flash", label: "GLM-Z1-Flash (free)", tiers: [flat(0, null, 0, "free \xB7 cache unsupported")] },
810
+ // ---- Vision ----
775
811
  { id: "glm-ocr", label: "GLM-OCR", tiers: [flat(0.2, null, 0.2)] },
776
812
  {
777
813
  id: "glm-5v-turbo",
778
814
  label: "GLM-5V-Turbo",
779
815
  tiers: [
780
- { when: { inputLt: K32 }, input: 5, cache: 1.2, output: 22, note: "\u5165<32K" },
781
- { when: { inputGte: K32 }, input: 7, cache: 1.8, output: 26, note: "\u5165\u226532K" }
816
+ { when: { inputLt: K32 }, input: 5, cache: 1.2, output: 22, note: "in<32K" },
817
+ { when: { inputGte: K32 }, input: 7, cache: 1.8, output: 26, note: "in>=32K" }
782
818
  ]
783
819
  },
784
820
  {
785
821
  id: "glm-4.6v",
786
822
  label: "GLM-4.6V",
787
823
  tiers: [
788
- { when: { inputLt: K32 }, input: 1, cache: 0.2, output: 3, note: "\u5165<32K" },
789
- { when: { inputGte: K32 }, input: 2, cache: 0.4, output: 6, note: "\u516532K\u2013128K\uFF08\u8D85\u4E0A\u754C\u5E76\u5165\u9AD8\u6863\uFF09" }
824
+ { when: { inputLt: K32 }, input: 1, cache: 0.2, output: 3, note: "in<32K" },
825
+ { when: { inputGte: K32 }, input: 2, cache: 0.4, output: 6, note: "in 32K\u2013128K (above the upper bound folds into the top tier)" }
790
826
  ]
791
827
  },
792
828
  {
793
829
  id: "glm-4.6v-flashx",
794
830
  label: "GLM-4.6V-FlashX",
795
831
  tiers: [
796
- { when: { inputLt: K32 }, input: 0.15, cache: 0.03, output: 1.5, note: "\u5165<32K" },
797
- { when: { inputGte: K32 }, input: 0.3, cache: 0.03, output: 3, note: "\u516532K\u2013128K\uFF08\u8D85\u4E0A\u754C\u5E76\u5165\u9AD8\u6863\uFF09" }
832
+ { when: { inputLt: K32 }, input: 0.15, cache: 0.03, output: 1.5, note: "in<32K" },
833
+ { when: { inputGte: K32 }, input: 0.3, cache: 0.03, output: 3, note: "in 32K\u2013128K (above the upper bound folds into the top tier)" }
798
834
  ]
799
835
  },
800
- { id: "glm-4.6v-flash", label: "GLM-4.6V-Flash\uFF08\u514D\u8D39\uFF09", tiers: [flat(0, 0, 0, "\u514D\u8D39")] },
836
+ { id: "glm-4.6v-flash", label: "GLM-4.6V-Flash (free)", tiers: [flat(0, 0, 0, "free")] },
801
837
  {
802
838
  id: "glm-4.5v",
803
839
  label: "GLM-4.5V",
804
840
  tiers: [
805
- { when: { inputLt: K32 }, input: 2, cache: 0.4, output: 6, note: "\u5165<32K" },
806
- { when: { inputGte: K32 }, input: 4, cache: 0.8, output: 12, note: "\u516532K\u201364K\uFF08\u8D85\u4E0A\u754C\u5E76\u5165\u9AD8\u6863\uFF09" }
841
+ { when: { inputLt: K32 }, input: 2, cache: 0.4, output: 6, note: "in<32K" },
842
+ { when: { inputGte: K32 }, input: 4, cache: 0.8, output: 12, note: "in 32K\u201364K (above the upper bound folds into the top tier)" }
807
843
  ]
808
844
  },
809
845
  { id: "glm-4v-plus-0111", label: "GLM-4V-Plus-0111", tiers: [flat(4, 2, 4)] },
810
- { id: "glm-4v-plus", label: "GLM-4V-Plus\uFF08\u540C 0111 \u7248\u4EF7\uFF09", tiers: [flat(4, 2, 4)] },
811
- { id: "glm-4v-flash", label: "GLM-4V-Flash\uFF08\u514D\u8D39\uFF09", tiers: [flat(0, null, 0, "\u514D\u8D39\xB7\u7F13\u5B58\u4E0D\u652F\u6301")] },
846
+ { id: "glm-4v-plus", label: "GLM-4V-Plus (same price as 0111)", tiers: [flat(4, 2, 4)] },
847
+ { id: "glm-4v-flash", label: "GLM-4V-Flash (free)", tiers: [flat(0, null, 0, "free \xB7 cache unsupported")] },
812
848
  { id: "glm-4.1v-thinking-flashx", label: "GLM-4.1V-Thinking-FlashX", tiers: [flat(2, null, 2)] },
813
- { id: "glm-4.1v-thinking-flash", label: "GLM-4.1V-Thinking-Flash\uFF08\u514D\u8D39\uFF09", tiers: [flat(0, null, 0, "\u514D\u8D39\xB7\u7F13\u5B58\u4E0D\u652F\u6301")] },
814
- { id: "embedding-3", label: "Embedding-3", tiers: [flat(0.5, null, 0.5, "\u5355\u503C\u4EF7\u76EE\xB7input \u8BA1")] },
815
- { id: "embedding-2", label: "Embedding-2", tiers: [flat(0.5, null, 0.5, "\u5355\u503C\u4EF7\u76EE\xB7input \u8BA1")] },
816
- { id: "rerank", label: "Rerank", tiers: [flat(0.8, null, 0.8, "\u5355\u503C\u4EF7\u76EE")] },
817
- { id: "codegeex-4", label: "CodeGeeX-4", tiers: [flat(0.1, null, 0.1, "\u5355\u503C\u4EF7\u76EE")] }
849
+ { id: "glm-4.1v-thinking-flash", label: "GLM-4.1V-Thinking-Flash (free)", tiers: [flat(0, null, 0, "free \xB7 cache unsupported")] },
850
+ // ---- Embeddings / other (single-value prices are input-based; output billed at the same rate as a floor) ----
851
+ { id: "embedding-3", label: "Embedding-3", tiers: [flat(0.5, null, 0.5, "single-value \xB7 billed on input")] },
852
+ { id: "embedding-2", label: "Embedding-2", tiers: [flat(0.5, null, 0.5, "single-value \xB7 billed on input")] },
853
+ { id: "rerank", label: "Rerank", tiers: [flat(0.8, null, 0.8, "single-value")] },
854
+ { id: "codegeex-4", label: "CodeGeeX-4", tiers: [flat(0.1, null, 0.1, "single-value")] }
818
855
  ];
819
856
  var findPrice = (model) => {
820
857
  const m = model.trim().toLowerCase();
@@ -843,7 +880,7 @@ var priceUsage = (rows) => {
843
880
  const accs = /* @__PURE__ */ new Map();
844
881
  for (const r of rows) {
845
882
  if (r.inputTokens === 0 && r.outputTokens === 0) continue;
846
- const key = r.model === "" ? "\uFF08\u672A\u8BB0\u5F55\u6A21\u578B\uFF09" : r.model;
883
+ const key = r.model === "" ? "(no model recorded)" : r.model;
847
884
  let a = accs.get(key);
848
885
  if (a === void 0) {
849
886
  const p = findPrice(key);
@@ -919,9 +956,10 @@ CREATE TABLE IF NOT EXISTS prompt_usage (
919
956
  note TEXT NOT NULL DEFAULT '',
920
957
  model TEXT NOT NULL DEFAULT '',
921
958
  input_tokens INTEGER NOT NULL DEFAULT 0,
922
- -- cached_tokens\uFF1Az.ai \u53E3\u5F84\u7F13\u5B58\u547D\u4E2D\uFF08input \u5B50\u96C6\uFF0Cwf_66a9b632154d\uFF09
923
- --\uFF08\u5341\u4E09\u8DD1 R1 \u987A\u624B\u4FEE\uFF1A\u539F JS \u98CE\u683C // \u6CE8\u91CA\u5199\u5728 SQL \u4E32\u5185\uFF0CSQLite \u4E0D\u8BA4\uFF0C
924
- -- db.exec(MIGRATIONS) \u76F4\u63A5\u629B near "/": syntax error\uFF0C\u5168\u4ED3 store \u7EA7\u6D4B\u8BD5\u5C3D\u7EA2\uFF09
959
+ -- cached_tokens: z.ai-convention cache hits (subset of input, wf_66a9b632154d)
960
+ -- (fixed in passing during run-13 R1: the original JS-style // comments inside
961
+ -- the SQL string are not valid SQLite; db.exec(MIGRATIONS) threw near "/":
962
+ -- syntax error and every store-level test in the repo went red)
925
963
  cached_tokens INTEGER NOT NULL DEFAULT 0,
926
964
  output_tokens INTEGER NOT NULL DEFAULT 0,
927
965
  duration_ms INTEGER NOT NULL DEFAULT 0,
@@ -1228,6 +1266,13 @@ var parseAssistantLine = (line) => {
1228
1266
  }
1229
1267
  };
1230
1268
  export {
1269
+ AGENT_STEP_KINDS,
1270
+ BIGMODEL_PRICES,
1271
+ INSTRUCTABLE_STEP_KINDS,
1272
+ PRICING_RETRIEVED_AT,
1273
+ PRICING_SOURCE,
1274
+ STEP_KINDS,
1275
+ TERMINAL_WORKFLOW_STATUSES,
1231
1276
  appendDecision,
1232
1277
  appendExecution,
1233
1278
  appendReference,
@@ -1244,5 +1289,6 @@ export {
1244
1289
  rfc3339,
1245
1290
  safeParse,
1246
1291
  serializeCaseFile,
1247
- systemClock
1292
+ systemClock,
1293
+ withOriginal
1248
1294
  };
@@ -553,9 +553,11 @@ var createLedgerStore = (dbPath, deps = {}) => {
553
553
  };
554
554
  },
555
555
  activeRunForSession: (session) => activeRunOf(session),
556
- /** 活跃去重:同 dedup_key 且工作流仍在途 → 跳过重复建流。
557
- * ⚠ ESCAPE '\' 必须与转义成对:message-id 几乎必含 `_`,漏写 ESCAPE 时
558
- * `\_` 成了"字面反斜杠+任意字符",模式永不匹配——去重整体失效(09-07 事故)。 */
556
+ /** Active dedup: same dedup_key and the workflow still in flight → skip
557
+ * creating a duplicate. ⚠ ESCAPE '\' must pair with the escaping: a
558
+ * message-id almost always contains `_`; without ESCAPE, `\_` becomes
559
+ * "literal backslash + any character", the pattern never matches — and
560
+ * dedup fails wholesale (09-07 incident). */
559
561
  hasActiveDedup(key) {
560
562
  const r = db.prepare(
561
563
  `SELECT 1 FROM workflows WHERE status IN (${sqlInList(DEDUP_WINDOW_STATUSES)})
@@ -563,8 +565,10 @@ var createLedgerStore = (dbPath, deps = {}) => {
563
565
  ).get(dedupPattern(key));
564
566
  return r !== void 0;
565
567
  },
566
- /** 已摄取去重(轮询层):同 dedup_key 存在任何非 rejected 工作流 → 这封
567
- * 邮件已被处理过(含 failed),轮询不再重复拉取。重试走步骤 retry,不走再摄取。 */
568
+ /** Ingested dedup (polling layer): any non-rejected workflow with the same
569
+ * dedup_key → this email has already been handled (failed included);
570
+ * polling won't fetch it again. Retries go through step retry, not
571
+ * re-ingestion. */
568
572
  hasSeenDedup(key) {
569
573
  const r = db.prepare(
570
574
  `SELECT 1 FROM workflows WHERE status != 'rejected'
@@ -572,11 +576,14 @@ var createLedgerStore = (dbPath, deps = {}) => {
572
576
  ).get(dedupPattern(key));
573
577
  return r !== void 0;
574
578
  },
575
- /** 自回环守卫查询(2026-09-20 断点十三):message_id 是否命中本引擎已
576
- * 发送记录——completed send 步的 output.message_id(email_sent 事件同源
577
- * 落账)。进件层据此丢弃投递副本回灌(引擎给轮询邮箱自己发信的 echo)。
578
- * LIKE 预筛 + 精确比对:JSON 编码取实际存储字节,%/_/\ 照 dedupPattern
579
- * 成对转义(message-id 几乎必含 `_`)。 */
579
+ /** Self-loop guard query (2026-09-20 breakpoint 13): does the message_id
580
+ * hit a record this engine already sent — the output.message_id of a
581
+ * completed send step (booked from the same source as email_sent events)?
582
+ * The intake layer uses this to discard delivery-copy feedback (the echo
583
+ * of the engine mailing the polling mailbox itself). LIKE prefilter +
584
+ * exact comparison: JSON-encode to the actually stored bytes; %/_/\ are
585
+ * escaped in pairs like dedupPattern (a message-id almost always contains
586
+ * `_`). */
580
587
  recordSentMessageId(messageId, meta) {
581
588
  if (messageId === "") return;
582
589
  db.prepare(
@@ -688,59 +695,61 @@ var PRICING_SOURCE = "https://docs.bigmodel.cn/cn/guide/start/pricing";
688
695
  var PRICING_RETRIEVED_AT = "2026-10-06";
689
696
  var K32 = 32e3;
690
697
  var K200 = 200;
691
- var flat = (input, cache, output, note = "\u7EDF\u4E00\u4EF7") => ({ when: {}, input, cache, output, note });
698
+ var flat = (input, cache, output, note = "flat rate") => ({ when: {}, input, cache, output, note });
692
699
  var BIGMODEL_PRICES = [
700
+ // ---- Flagship ----
693
701
  { id: "glm-5.3", label: "GLM-5.3", tiers: [flat(8, 2, 28)] },
694
702
  { id: "glm-5.3-flash", label: "GLM-5.3-Flash", tiers: [flat(0.8, 0.23, 2.8)] },
695
703
  { id: "glm-5.3-flashx", label: "GLM-5.3-FlashX", tiers: [flat(2, 0.57, 7)] },
704
+ // ---- Text ----
696
705
  { id: "glm-5.2", label: "GLM-5.2", tiers: [flat(8, 2, 28)] },
697
706
  {
698
707
  id: "glm-5.1",
699
708
  label: "GLM-5.1",
700
709
  tiers: [
701
- { when: { inputLt: K32 }, input: 6, cache: 1.3, output: 24, note: "\u5165<32K" },
702
- { when: { inputGte: K32 }, input: 8, cache: 2, output: 28, note: "\u5165\u226532K" }
710
+ { when: { inputLt: K32 }, input: 6, cache: 1.3, output: 24, note: "in<32K" },
711
+ { when: { inputGte: K32 }, input: 8, cache: 2, output: 28, note: "in>=32K" }
703
712
  ]
704
713
  },
705
714
  {
706
715
  id: "glm-5-turbo",
707
716
  label: "GLM-5-Turbo",
708
717
  tiers: [
709
- { when: { inputLt: K32 }, input: 5, cache: 1.2, output: 22, note: "\u5165<32K" },
710
- { when: { inputGte: K32 }, input: 7, cache: 1.8, output: 26, note: "\u5165\u226532K" }
718
+ { when: { inputLt: K32 }, input: 5, cache: 1.2, output: 22, note: "in<32K" },
719
+ { when: { inputGte: K32 }, input: 7, cache: 1.8, output: 26, note: "in>=32K" }
711
720
  ]
712
721
  },
713
722
  {
714
723
  id: "glm-5",
715
724
  label: "GLM-5",
716
725
  tiers: [
717
- { when: { inputLt: K32 }, input: 4, cache: 1, output: 18, note: "\u5165<32K" },
718
- { when: { inputGte: K32 }, input: 6, cache: 1.5, output: 22, note: "\u5165\u226532K" }
726
+ { when: { inputLt: K32 }, input: 4, cache: 1, output: 18, note: "in<32K" },
727
+ { when: { inputGte: K32 }, input: 6, cache: 1.5, output: 22, note: "in>=32K" }
719
728
  ]
720
729
  },
721
730
  {
722
731
  id: "glm-4.7",
723
732
  label: "GLM-4.7",
724
733
  tiers: [
725
- { when: { inputLt: K32, outputLt: K200 }, input: 2, cache: 0.4, output: 8, note: "\u5165<32K\xB7\u51FA<0.2K" },
726
- { when: { inputLt: K32, outputGte: K200 }, input: 3, cache: 0.6, output: 14, note: "\u5165<32K\xB7\u51FA\u22650.2K" },
727
- { when: { inputGte: K32 }, input: 4, cache: 0.8, output: 16, note: "\u516532K\u2013200K" }
734
+ { when: { inputLt: K32, outputLt: K200 }, input: 2, cache: 0.4, output: 8, note: "in<32K\xB7out<0.2K" },
735
+ { when: { inputLt: K32, outputGte: K200 }, input: 3, cache: 0.6, output: 14, note: "in<32K\xB7out>=0.2K" },
736
+ { when: { inputGte: K32 }, input: 4, cache: 0.8, output: 16, note: "in 32K\u2013200K" }
728
737
  ]
729
738
  },
730
739
  {
731
740
  id: "glm-4.5-air",
732
741
  label: "GLM-4.5-Air",
733
742
  tiers: [
734
- { when: { inputLt: K32, outputLt: K200 }, input: 0.8, cache: 0.16, output: 2, note: "\u5165<32K\xB7\u51FA<0.2K" },
735
- { when: { inputLt: K32, outputGte: K200 }, input: 0.8, cache: 0.16, output: 6, note: "\u5165<32K\xB7\u51FA\u22650.2K" },
736
- { when: { inputGte: K32 }, input: 1.2, cache: 0.24, output: 8, note: "\u516532K\u2013128K" }
743
+ { when: { inputLt: K32, outputLt: K200 }, input: 0.8, cache: 0.16, output: 2, note: "in<32K\xB7out<0.2K" },
744
+ { when: { inputLt: K32, outputGte: K200 }, input: 0.8, cache: 0.16, output: 6, note: "in<32K\xB7out>=0.2K" },
745
+ { when: { inputGte: K32 }, input: 1.2, cache: 0.24, output: 8, note: "in 32K\u2013128K" }
737
746
  ]
738
747
  },
739
748
  { id: "glm-4.7-flashx", label: "GLM-4.7-FlashX", tiers: [flat(0.5, 0.1, 3)] },
740
- { id: "glm-4.7-flash", label: "GLM-4.7-Flash\uFF08\u514D\u8D39\uFF09", tiers: [flat(0, 0, 0, "\u514D\u8D39")] },
749
+ { id: "glm-4.7-flash", label: "GLM-4.7-Flash (free)", tiers: [flat(0, 0, 0, "free")] },
741
750
  { id: "glm-4-plus", label: "GLM-4-Plus", tiers: [flat(5, 2.5, 5)] },
742
751
  { id: "glm-4-air-250414", label: "GLM-4-Air-250414", tiers: [flat(0.5, 0.25, 0.5)] },
743
- { id: "glm-4-air", label: "GLM-4-Air\uFF08\u540C 250414 \u7248\u4EF7\uFF09", tiers: [flat(0.5, 0.25, 0.5)] },
752
+ { id: "glm-4-air", label: "GLM-4-Air (same price as 250414)", tiers: [flat(0.5, 0.25, 0.5)] },
744
753
  { id: "glm-4-airx", label: "GLM-4-AirX", tiers: [flat(10, null, 10)] },
745
754
  { id: "glm-4-long", label: "GLM-4-Long", tiers: [flat(1, 0.5, 1)] },
746
755
  { id: "glm-4-assistant", label: "GLM-4-Assistant", tiers: [flat(5, null, 5)] },
@@ -748,53 +757,55 @@ var BIGMODEL_PRICES = [
748
757
  { id: "glm-z1-airx", label: "GLM-Z1-AirX", tiers: [flat(5, null, 5)] },
749
758
  { id: "glm-z1-flashx", label: "GLM-Z1-FlashX", tiers: [flat(0.1, null, 0.1)] },
750
759
  { id: "glm-4-flashx-250414", label: "GLM-4-FlashX-250414", tiers: [flat(0.1, 0.05, 0.1)] },
751
- { id: "glm-4-flashx", label: "GLM-4-FlashX\uFF08\u540C 250414 \u7248\u4EF7\uFF09", tiers: [flat(0.1, 0.05, 0.1)] },
752
- { id: "glm-4-flash-250414", label: "GLM-4-Flash-250414\uFF08\u514D\u8D39\uFF09", tiers: [flat(0, null, 0, "\u514D\u8D39\xB7\u7F13\u5B58\u4E0D\u652F\u6301")] },
753
- { id: "glm-4-flash", label: "GLM-4-Flash\uFF08\u514D\u8D39\uFF09", tiers: [flat(0, null, 0, "\u514D\u8D39\xB7\u7F13\u5B58\u4E0D\u652F\u6301")] },
754
- { id: "glm-z1-flash", label: "GLM-Z1-Flash\uFF08\u514D\u8D39\uFF09", tiers: [flat(0, null, 0, "\u514D\u8D39\xB7\u7F13\u5B58\u4E0D\u652F\u6301")] },
760
+ { id: "glm-4-flashx", label: "GLM-4-FlashX (same price as 250414)", tiers: [flat(0.1, 0.05, 0.1)] },
761
+ { id: "glm-4-flash-250414", label: "GLM-4-Flash-250414 (free)", tiers: [flat(0, null, 0, "free \xB7 cache unsupported")] },
762
+ { id: "glm-4-flash", label: "GLM-4-Flash (free)", tiers: [flat(0, null, 0, "free \xB7 cache unsupported")] },
763
+ { id: "glm-z1-flash", label: "GLM-Z1-Flash (free)", tiers: [flat(0, null, 0, "free \xB7 cache unsupported")] },
764
+ // ---- Vision ----
755
765
  { id: "glm-ocr", label: "GLM-OCR", tiers: [flat(0.2, null, 0.2)] },
756
766
  {
757
767
  id: "glm-5v-turbo",
758
768
  label: "GLM-5V-Turbo",
759
769
  tiers: [
760
- { when: { inputLt: K32 }, input: 5, cache: 1.2, output: 22, note: "\u5165<32K" },
761
- { when: { inputGte: K32 }, input: 7, cache: 1.8, output: 26, note: "\u5165\u226532K" }
770
+ { when: { inputLt: K32 }, input: 5, cache: 1.2, output: 22, note: "in<32K" },
771
+ { when: { inputGte: K32 }, input: 7, cache: 1.8, output: 26, note: "in>=32K" }
762
772
  ]
763
773
  },
764
774
  {
765
775
  id: "glm-4.6v",
766
776
  label: "GLM-4.6V",
767
777
  tiers: [
768
- { when: { inputLt: K32 }, input: 1, cache: 0.2, output: 3, note: "\u5165<32K" },
769
- { when: { inputGte: K32 }, input: 2, cache: 0.4, output: 6, note: "\u516532K\u2013128K\uFF08\u8D85\u4E0A\u754C\u5E76\u5165\u9AD8\u6863\uFF09" }
778
+ { when: { inputLt: K32 }, input: 1, cache: 0.2, output: 3, note: "in<32K" },
779
+ { when: { inputGte: K32 }, input: 2, cache: 0.4, output: 6, note: "in 32K\u2013128K (above the upper bound folds into the top tier)" }
770
780
  ]
771
781
  },
772
782
  {
773
783
  id: "glm-4.6v-flashx",
774
784
  label: "GLM-4.6V-FlashX",
775
785
  tiers: [
776
- { when: { inputLt: K32 }, input: 0.15, cache: 0.03, output: 1.5, note: "\u5165<32K" },
777
- { when: { inputGte: K32 }, input: 0.3, cache: 0.03, output: 3, note: "\u516532K\u2013128K\uFF08\u8D85\u4E0A\u754C\u5E76\u5165\u9AD8\u6863\uFF09" }
786
+ { when: { inputLt: K32 }, input: 0.15, cache: 0.03, output: 1.5, note: "in<32K" },
787
+ { when: { inputGte: K32 }, input: 0.3, cache: 0.03, output: 3, note: "in 32K\u2013128K (above the upper bound folds into the top tier)" }
778
788
  ]
779
789
  },
780
- { id: "glm-4.6v-flash", label: "GLM-4.6V-Flash\uFF08\u514D\u8D39\uFF09", tiers: [flat(0, 0, 0, "\u514D\u8D39")] },
790
+ { id: "glm-4.6v-flash", label: "GLM-4.6V-Flash (free)", tiers: [flat(0, 0, 0, "free")] },
781
791
  {
782
792
  id: "glm-4.5v",
783
793
  label: "GLM-4.5V",
784
794
  tiers: [
785
- { when: { inputLt: K32 }, input: 2, cache: 0.4, output: 6, note: "\u5165<32K" },
786
- { when: { inputGte: K32 }, input: 4, cache: 0.8, output: 12, note: "\u516532K\u201364K\uFF08\u8D85\u4E0A\u754C\u5E76\u5165\u9AD8\u6863\uFF09" }
795
+ { when: { inputLt: K32 }, input: 2, cache: 0.4, output: 6, note: "in<32K" },
796
+ { when: { inputGte: K32 }, input: 4, cache: 0.8, output: 12, note: "in 32K\u201364K (above the upper bound folds into the top tier)" }
787
797
  ]
788
798
  },
789
799
  { id: "glm-4v-plus-0111", label: "GLM-4V-Plus-0111", tiers: [flat(4, 2, 4)] },
790
- { id: "glm-4v-plus", label: "GLM-4V-Plus\uFF08\u540C 0111 \u7248\u4EF7\uFF09", tiers: [flat(4, 2, 4)] },
791
- { id: "glm-4v-flash", label: "GLM-4V-Flash\uFF08\u514D\u8D39\uFF09", tiers: [flat(0, null, 0, "\u514D\u8D39\xB7\u7F13\u5B58\u4E0D\u652F\u6301")] },
800
+ { id: "glm-4v-plus", label: "GLM-4V-Plus (same price as 0111)", tiers: [flat(4, 2, 4)] },
801
+ { id: "glm-4v-flash", label: "GLM-4V-Flash (free)", tiers: [flat(0, null, 0, "free \xB7 cache unsupported")] },
792
802
  { id: "glm-4.1v-thinking-flashx", label: "GLM-4.1V-Thinking-FlashX", tiers: [flat(2, null, 2)] },
793
- { id: "glm-4.1v-thinking-flash", label: "GLM-4.1V-Thinking-Flash\uFF08\u514D\u8D39\uFF09", tiers: [flat(0, null, 0, "\u514D\u8D39\xB7\u7F13\u5B58\u4E0D\u652F\u6301")] },
794
- { id: "embedding-3", label: "Embedding-3", tiers: [flat(0.5, null, 0.5, "\u5355\u503C\u4EF7\u76EE\xB7input \u8BA1")] },
795
- { id: "embedding-2", label: "Embedding-2", tiers: [flat(0.5, null, 0.5, "\u5355\u503C\u4EF7\u76EE\xB7input \u8BA1")] },
796
- { id: "rerank", label: "Rerank", tiers: [flat(0.8, null, 0.8, "\u5355\u503C\u4EF7\u76EE")] },
797
- { id: "codegeex-4", label: "CodeGeeX-4", tiers: [flat(0.1, null, 0.1, "\u5355\u503C\u4EF7\u76EE")] }
803
+ { id: "glm-4.1v-thinking-flash", label: "GLM-4.1V-Thinking-Flash (free)", tiers: [flat(0, null, 0, "free \xB7 cache unsupported")] },
804
+ // ---- Embeddings / other (single-value prices are input-based; output billed at the same rate as a floor) ----
805
+ { id: "embedding-3", label: "Embedding-3", tiers: [flat(0.5, null, 0.5, "single-value \xB7 billed on input")] },
806
+ { id: "embedding-2", label: "Embedding-2", tiers: [flat(0.5, null, 0.5, "single-value \xB7 billed on input")] },
807
+ { id: "rerank", label: "Rerank", tiers: [flat(0.8, null, 0.8, "single-value")] },
808
+ { id: "codegeex-4", label: "CodeGeeX-4", tiers: [flat(0.1, null, 0.1, "single-value")] }
798
809
  ];
799
810
  var findPrice = (model) => {
800
811
  const m = model.trim().toLowerCase();
@@ -823,7 +834,7 @@ var priceUsage = (rows) => {
823
834
  const accs = /* @__PURE__ */ new Map();
824
835
  for (const r of rows) {
825
836
  if (r.inputTokens === 0 && r.outputTokens === 0) continue;
826
- const key = r.model === "" ? "\uFF08\u672A\u8BB0\u5F55\u6A21\u578B\uFF09" : r.model;
837
+ const key = r.model === "" ? "(no model recorded)" : r.model;
827
838
  let a = accs.get(key);
828
839
  if (a === void 0) {
829
840
  const p = findPrice(key);
@@ -899,9 +910,10 @@ CREATE TABLE IF NOT EXISTS prompt_usage (
899
910
  note TEXT NOT NULL DEFAULT '',
900
911
  model TEXT NOT NULL DEFAULT '',
901
912
  input_tokens INTEGER NOT NULL DEFAULT 0,
902
- -- cached_tokens\uFF1Az.ai \u53E3\u5F84\u7F13\u5B58\u547D\u4E2D\uFF08input \u5B50\u96C6\uFF0Cwf_66a9b632154d\uFF09
903
- --\uFF08\u5341\u4E09\u8DD1 R1 \u987A\u624B\u4FEE\uFF1A\u539F JS \u98CE\u683C // \u6CE8\u91CA\u5199\u5728 SQL \u4E32\u5185\uFF0CSQLite \u4E0D\u8BA4\uFF0C
904
- -- db.exec(MIGRATIONS) \u76F4\u63A5\u629B near "/": syntax error\uFF0C\u5168\u4ED3 store \u7EA7\u6D4B\u8BD5\u5C3D\u7EA2\uFF09
913
+ -- cached_tokens: z.ai-convention cache hits (subset of input, wf_66a9b632154d)
914
+ -- (fixed in passing during run-13 R1: the original JS-style // comments inside
915
+ -- the SQL string are not valid SQLite; db.exec(MIGRATIONS) threw near "/":
916
+ -- syntax error and every store-level test in the repo went red)
905
917
  cached_tokens INTEGER NOT NULL DEFAULT 0,
906
918
  output_tokens INTEGER NOT NULL DEFAULT 0,
907
919
  duration_ms INTEGER NOT NULL DEFAULT 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juli-os/ledger",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "juli-os L1 layer: the ledger of record for agent work — workflows, steps, case files, and token usage in one zero-dependency SQLite layer.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -30,13 +30,17 @@
30
30
  "prepublishOnly": "npm run build"
31
31
  },
32
32
  "devDependencies": {
33
+ "@types/node": "^22.0.0",
33
34
  "esbuild": "^0.24.0",
34
- "typescript": "^5.6.0",
35
- "@types/node": "^22.0.0"
35
+ "typescript": "^5.6.0"
36
36
  },
37
37
  "publishConfig": {
38
38
  "registry": "https://registry.npmjs.org/",
39
39
  "access": "public"
40
40
  },
41
- "license": "Apache-2.0"
42
- }
41
+ "license": "Apache-2.0",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/juli-os/ledger.git"
45
+ }
46
+ }