@yadsh/dsh-kv-persist 0.1.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.
Files changed (98) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +110 -0
  3. package/compatibility.json +16 -0
  4. package/cordis.patch.yml +4 -0
  5. package/docs/dsh-kv-persist.md +3311 -0
  6. package/lib/backends/llama-cpp/backend.d.ts +20 -0
  7. package/lib/backends/llama-cpp/backend.d.ts.map +1 -0
  8. package/lib/backends/llama-cpp/backend.js +37 -0
  9. package/lib/backends/llama-cpp/backend.js.map +1 -0
  10. package/lib/backends/llama-cpp/client.d.ts +31 -0
  11. package/lib/backends/llama-cpp/client.d.ts.map +1 -0
  12. package/lib/backends/llama-cpp/client.js +120 -0
  13. package/lib/backends/llama-cpp/client.js.map +1 -0
  14. package/lib/backends/llama-cpp/discovery.d.ts +20 -0
  15. package/lib/backends/llama-cpp/discovery.d.ts.map +1 -0
  16. package/lib/backends/llama-cpp/discovery.js +33 -0
  17. package/lib/backends/llama-cpp/discovery.js.map +1 -0
  18. package/lib/backends/llama-cpp/types.d.ts +30 -0
  19. package/lib/backends/llama-cpp/types.d.ts.map +1 -0
  20. package/lib/backends/llama-cpp/types.js +9 -0
  21. package/lib/backends/llama-cpp/types.js.map +1 -0
  22. package/lib/backends/types.d.ts +52 -0
  23. package/lib/backends/types.d.ts.map +1 -0
  24. package/lib/backends/types.js +6 -0
  25. package/lib/backends/types.js.map +1 -0
  26. package/lib/config.d.ts +258 -0
  27. package/lib/config.d.ts.map +1 -0
  28. package/lib/config.js +169 -0
  29. package/lib/config.js.map +1 -0
  30. package/lib/coordinator/checkpoint-policy.d.ts +19 -0
  31. package/lib/coordinator/checkpoint-policy.d.ts.map +1 -0
  32. package/lib/coordinator/checkpoint-policy.js +40 -0
  33. package/lib/coordinator/checkpoint-policy.js.map +1 -0
  34. package/lib/coordinator/circuit-breaker.d.ts +29 -0
  35. package/lib/coordinator/circuit-breaker.d.ts.map +1 -0
  36. package/lib/coordinator/circuit-breaker.js +62 -0
  37. package/lib/coordinator/circuit-breaker.js.map +1 -0
  38. package/lib/coordinator/coordinator.d.ts +74 -0
  39. package/lib/coordinator/coordinator.d.ts.map +1 -0
  40. package/lib/coordinator/coordinator.js +542 -0
  41. package/lib/coordinator/coordinator.js.map +1 -0
  42. package/lib/coordinator/slot-lease.d.ts +22 -0
  43. package/lib/coordinator/slot-lease.d.ts.map +1 -0
  44. package/lib/coordinator/slot-lease.js +38 -0
  45. package/lib/coordinator/slot-lease.js.map +1 -0
  46. package/lib/coordinator/state-machine.d.ts +65 -0
  47. package/lib/coordinator/state-machine.d.ts.map +1 -0
  48. package/lib/coordinator/state-machine.js +40 -0
  49. package/lib/coordinator/state-machine.js.map +1 -0
  50. package/lib/errors.d.ts +82 -0
  51. package/lib/errors.d.ts.map +1 -0
  52. package/lib/errors.js +113 -0
  53. package/lib/errors.js.map +1 -0
  54. package/lib/index.d.ts +26 -0
  55. package/lib/index.d.ts.map +1 -0
  56. package/lib/index.js +17 -0
  57. package/lib/index.js.map +1 -0
  58. package/lib/logging/dsh-home.d.ts +13 -0
  59. package/lib/logging/dsh-home.d.ts.map +1 -0
  60. package/lib/logging/dsh-home.js +18 -0
  61. package/lib/logging/dsh-home.js.map +1 -0
  62. package/lib/logging/index.d.ts +10 -0
  63. package/lib/logging/index.d.ts.map +1 -0
  64. package/lib/logging/index.js +10 -0
  65. package/lib/logging/index.js.map +1 -0
  66. package/lib/logging/plugin-logger.d.ts +94 -0
  67. package/lib/logging/plugin-logger.d.ts.map +1 -0
  68. package/lib/logging/plugin-logger.js +397 -0
  69. package/lib/logging/plugin-logger.js.map +1 -0
  70. package/lib/observability/diagnostics.d.ts +37 -0
  71. package/lib/observability/diagnostics.d.ts.map +1 -0
  72. package/lib/observability/diagnostics.js +75 -0
  73. package/lib/observability/diagnostics.js.map +1 -0
  74. package/lib/observability/metrics.d.ts +38 -0
  75. package/lib/observability/metrics.d.ts.map +1 -0
  76. package/lib/observability/metrics.js +29 -0
  77. package/lib/observability/metrics.js.map +1 -0
  78. package/lib/service.d.ts +231 -0
  79. package/lib/service.d.ts.map +1 -0
  80. package/lib/service.js +232 -0
  81. package/lib/service.js.map +1 -0
  82. package/lib/snapshots/fingerprint.d.ts +53 -0
  83. package/lib/snapshots/fingerprint.d.ts.map +1 -0
  84. package/lib/snapshots/fingerprint.js +69 -0
  85. package/lib/snapshots/fingerprint.js.map +1 -0
  86. package/lib/snapshots/manifest.d.ts +51 -0
  87. package/lib/snapshots/manifest.d.ts.map +1 -0
  88. package/lib/snapshots/manifest.js +0 -0
  89. package/lib/snapshots/manifest.js.map +1 -0
  90. package/lib/snapshots/naming.d.ts +18 -0
  91. package/lib/snapshots/naming.d.ts.map +1 -0
  92. package/lib/snapshots/naming.js +33 -0
  93. package/lib/snapshots/naming.js.map +1 -0
  94. package/lib/snapshots/repository.d.ts +52 -0
  95. package/lib/snapshots/repository.d.ts.map +1 -0
  96. package/lib/snapshots/repository.js +270 -0
  97. package/lib/snapshots/repository.js.map +1 -0
  98. package/package.json +83 -0
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Slot mutex (SPEC §20, Invariant 8).
3
+ *
4
+ * No two operations may concurrently mutate the same physical slot:
5
+ * restore, erase, inference, and save all run inside one exclusive lease.
6
+ * For v0.1 a single promise-chain mutex per server is sufficient.
7
+ */
8
+ /**
9
+ * Serialize async work: every `runExclusive` body starts only after all
10
+ * previously queued bodies finished (successfully or not). Bodies must not
11
+ * re-enter `runExclusive` on the same mutex — that deadlocks by design, and
12
+ * the invariant violation would be a plugin bug, not a runtime condition.
13
+ */
14
+ export declare class SlotMutex {
15
+ #private;
16
+ constructor(name: string);
17
+ /** Diagnostic: whether any lease is queued or running. */
18
+ get held(): boolean;
19
+ get name(): string;
20
+ runExclusive<T>(body: () => Promise<T>): Promise<T>;
21
+ }
22
+ //# sourceMappingURL=slot-lease.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slot-lease.d.ts","sourceRoot":"","sources":["../../src/coordinator/slot-lease.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;GAKG;AACH,qBAAa,SAAS;;gBAKR,IAAI,EAAE,MAAM;IAIxB,0DAA0D;IAC1D,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAYpD"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Slot mutex (SPEC §20, Invariant 8).
3
+ *
4
+ * No two operations may concurrently mutate the same physical slot:
5
+ * restore, erase, inference, and save all run inside one exclusive lease.
6
+ * For v0.1 a single promise-chain mutex per server is sufficient.
7
+ */
8
+ /**
9
+ * Serialize async work: every `runExclusive` body starts only after all
10
+ * previously queued bodies finished (successfully or not). Bodies must not
11
+ * re-enter `runExclusive` on the same mutex — that deadlocks by design, and
12
+ * the invariant violation would be a plugin bug, not a runtime condition.
13
+ */
14
+ export class SlotMutex {
15
+ #name;
16
+ #tail = Promise.resolve();
17
+ #depth = 0;
18
+ constructor(name) {
19
+ this.#name = name;
20
+ }
21
+ /** Diagnostic: whether any lease is queued or running. */
22
+ get held() {
23
+ return this.#depth > 0;
24
+ }
25
+ get name() {
26
+ return this.#name;
27
+ }
28
+ runExclusive(body) {
29
+ this.#depth += 1;
30
+ const result = this.#tail.then(body, body);
31
+ this.#tail = result.then(() => undefined, () => undefined);
32
+ void this.#tail.then(() => {
33
+ this.#depth = Math.max(0, this.#depth - 1);
34
+ });
35
+ return result;
36
+ }
37
+ }
38
+ //# sourceMappingURL=slot-lease.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slot-lease.js","sourceRoot":"","sources":["../../src/coordinator/slot-lease.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;GAKG;AACH,MAAM,OAAO,SAAS;IACX,KAAK,CAAS;IACvB,KAAK,GAAqB,OAAO,CAAC,OAAO,EAAE,CAAC;IAC5C,MAAM,GAAG,CAAC,CAAC;IAEX,YAAY,IAAY;QACtB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IAED,0DAA0D;IAC1D,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,YAAY,CAAI,IAAsB;QACpC,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;QACjB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CACtB,GAAG,EAAE,CAAC,SAAS,EACf,GAAG,EAAE,CAAC,SAAS,CAChB,CAAC;QACF,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;YACxB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Session and slot state machines (SPEC §18-§19).
3
+ *
4
+ * Pure state + transition helpers; the coordinator owns the transitions.
5
+ * These types also back the status/diagnostics API (SPEC §47).
6
+ */
7
+ /** Session-side lifecycle state (SPEC §18). */
8
+ export type SessionKvLifecycle = "none" | "cold" | "restoring" | "active-clean" | "active-dirty" | "saving" | "saved" | "invalid";
9
+ /** Physical slot state (SPEC §19). */
10
+ export type SlotState = "unknown" | "idle" | "restoring" | "ready" | "inference" | "dirty" | "saving" | "broken";
11
+ /** The one managed physical slot of v0.1 (SPEC §19, §7). */
12
+ export interface ManagedSlot {
13
+ readonly id: number;
14
+ /** Session that currently owns the slot, when any. */
15
+ ownerSessionId: string | null;
16
+ /** Dirty generation at the time the slot state was last established. */
17
+ snapshotRevision: string | null;
18
+ state: SlotState;
19
+ lastUsedAt: number | null;
20
+ }
21
+ /** Runtime bookkeeping for one known session (SPEC §27-§28). */
22
+ export interface SessionRuntime {
23
+ readonly sessionId: string;
24
+ /** Route of the latest request (provider + model, SPEC §56). */
25
+ route: {
26
+ provider: string;
27
+ model: string;
28
+ };
29
+ /** Monotonic dirty generation: increments on every successful inference. */
30
+ dirtyRevision: number;
31
+ /** Generation covered by the latest durable snapshot. */
32
+ persistedRevision: number;
33
+ /** In-flight save for the current generation, when any (SPEC §27). */
34
+ saveInFlight: Promise<SnapshotResult> | null;
35
+ lifecycle: SessionKvLifecycle;
36
+ }
37
+ /** Result of a save operation (SPEC §11). */
38
+ export interface SnapshotResult {
39
+ readonly kind: "saved" | "skipped-clean" | "skipped-not-owner" | "failed";
40
+ readonly sessionId: string;
41
+ readonly revision: number;
42
+ readonly bytes: number | null;
43
+ readonly error: string | null;
44
+ }
45
+ /** Result of a restore attempt (SPEC §23). */
46
+ export interface RestoreOutcome {
47
+ readonly kind: "already-active" | "cold" | "restored" | "cold-fallback";
48
+ readonly sessionId: string;
49
+ readonly tokens: number | null;
50
+ readonly bytes: number | null;
51
+ readonly durationMs: number | null;
52
+ readonly error: string | null;
53
+ }
54
+ export declare function createManagedSlot(id: number): ManagedSlot;
55
+ export declare function createSessionRuntime(sessionId: string, route: {
56
+ provider: string;
57
+ model: string;
58
+ }): SessionRuntime;
59
+ /** Dirty in the generation sense (SPEC §28), not a boolean. */
60
+ export declare function isDirty(runtime: SessionRuntime): boolean;
61
+ /** Record a completed successful inference: bump the dirty generation. */
62
+ export declare function markDirty(runtime: SessionRuntime): void;
63
+ /** Record a durable snapshot covering `revision`. */
64
+ export declare function markPersisted(runtime: SessionRuntime, revision: number): void;
65
+ //# sourceMappingURL=state-machine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-machine.d.ts","sourceRoot":"","sources":["../../src/coordinator/state-machine.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,+CAA+C;AAC/C,MAAM,MAAM,kBAAkB,GAC1B,MAAM,GACN,MAAM,GACN,WAAW,GACX,cAAc,GACd,cAAc,GACd,QAAQ,GACR,OAAO,GACP,SAAS,CAAC;AAEd,sCAAsC;AACtC,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,MAAM,GACN,WAAW,GACX,OAAO,GACP,WAAW,GACX,OAAO,GACP,QAAQ,GACR,QAAQ,CAAC;AAEb,4DAA4D;AAC5D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,gEAAgE;AAChE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,gEAAgE;IAChE,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,4EAA4E;IAC5E,aAAa,EAAE,MAAM,CAAC;IACtB,yDAAyD;IACzD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sEAAsE;IACtE,YAAY,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC;IAC7C,SAAS,EAAE,kBAAkB,CAAC;CAC/B;AAED,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,GAAG,mBAAmB,GAAG,QAAQ,CAAC;IAC1E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,GAAG,UAAU,GAAG,eAAe,CAAC;IACxE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,CAQzD;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACzC,cAAc,CAShB;AAED,+DAA+D;AAC/D,wBAAgB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAExD;AAED,0EAA0E;AAC1E,wBAAgB,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAGvD;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAG7E"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Session and slot state machines (SPEC §18-§19).
3
+ *
4
+ * Pure state + transition helpers; the coordinator owns the transitions.
5
+ * These types also back the status/diagnostics API (SPEC §47).
6
+ */
7
+ export function createManagedSlot(id) {
8
+ return {
9
+ id,
10
+ ownerSessionId: null,
11
+ snapshotRevision: null,
12
+ state: "unknown",
13
+ lastUsedAt: null,
14
+ };
15
+ }
16
+ export function createSessionRuntime(sessionId, route) {
17
+ return {
18
+ sessionId,
19
+ route: { ...route },
20
+ dirtyRevision: 0,
21
+ persistedRevision: 0,
22
+ saveInFlight: null,
23
+ lifecycle: "none",
24
+ };
25
+ }
26
+ /** Dirty in the generation sense (SPEC §28), not a boolean. */
27
+ export function isDirty(runtime) {
28
+ return runtime.dirtyRevision > runtime.persistedRevision;
29
+ }
30
+ /** Record a completed successful inference: bump the dirty generation. */
31
+ export function markDirty(runtime) {
32
+ runtime.dirtyRevision += 1;
33
+ runtime.lifecycle = "active-dirty";
34
+ }
35
+ /** Record a durable snapshot covering `revision`. */
36
+ export function markPersisted(runtime, revision) {
37
+ runtime.persistedRevision = Math.max(runtime.persistedRevision, revision);
38
+ runtime.lifecycle = isDirty(runtime) ? "active-dirty" : "saved";
39
+ }
40
+ //# sourceMappingURL=state-machine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-machine.js","sourceRoot":"","sources":["../../src/coordinator/state-machine.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAoEH,MAAM,UAAU,iBAAiB,CAAC,EAAU;IAC1C,OAAO;QACL,EAAE;QACF,cAAc,EAAE,IAAI;QACpB,gBAAgB,EAAE,IAAI;QACtB,KAAK,EAAE,SAAS;QAChB,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,SAAiB,EACjB,KAA0C;IAE1C,OAAO;QACL,SAAS;QACT,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE;QACnB,aAAa,EAAE,CAAC;QAChB,iBAAiB,EAAE,CAAC;QACpB,YAAY,EAAE,IAAI;QAClB,SAAS,EAAE,MAAM;KAClB,CAAC;AACJ,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,OAAO,CAAC,OAAuB;IAC7C,OAAO,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC;AAC3D,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,SAAS,CAAC,OAAuB;IAC/C,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC;IAC3B,OAAO,CAAC,SAAS,GAAG,cAAc,CAAC;AACrC,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,aAAa,CAAC,OAAuB,EAAE,QAAgB;IACrE,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;IAC1E,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC;AAClE,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Error taxonomy for the kv-persist plugin (SPEC §79).
3
+ *
4
+ * Every failure carries a stable machine-readable `code`; messages are for
5
+ * humans. Per the failure policy (SPEC §32) these errors normally degrade to
6
+ * cold inference — only `strict: true` turns them into request failures.
7
+ */
8
+ export type KvPersistErrorCode = "KV_BACKEND_UNAVAILABLE" | "KV_BACKEND_UNSUPPORTED" | "KV_SLOT_NOT_FOUND" | "KV_SLOT_BUSY" | "KV_SLOT_STATE_INVALID" | "KV_SNAPSHOT_NOT_FOUND" | "KV_SNAPSHOT_INCOMPATIBLE" | "KV_SNAPSHOT_CORRUPT" | "KV_SAVE_FAILED" | "KV_RESTORE_FAILED" | "KV_ERASE_FAILED" | "KV_MANIFEST_INVALID" | "KV_METADATA_IO" | "KV_OPERATION_TIMEOUT" | "KV_INVARIANT";
9
+ /** Base class of every typed kv-persist error. */
10
+ export declare class KvPersistError extends Error {
11
+ readonly code: KvPersistErrorCode;
12
+ constructor(code: KvPersistErrorCode, message: string, options?: ErrorOptions);
13
+ }
14
+ /** The llama server or its slots endpoint cannot be reached. */
15
+ export declare class KvBackendUnavailableError extends KvPersistError {
16
+ constructor(message: string, options?: ErrorOptions);
17
+ }
18
+ /** The configured backend type does not expose the required slot surface. */
19
+ export declare class KvBackendUnsupportedError extends KvPersistError {
20
+ constructor(message: string);
21
+ }
22
+ /** A slot operation referenced a slot the server does not have. */
23
+ export declare class KvSlotNotFoundError extends KvPersistError {
24
+ readonly slotId: number;
25
+ constructor(slotId: number, message?: string);
26
+ }
27
+ /** A slot is busy with another exclusive operation. */
28
+ export declare class KvSlotBusyError extends KvPersistError {
29
+ readonly slotId: number;
30
+ constructor(slotId: number, message?: string);
31
+ }
32
+ /** The slot exists but its reported state cannot be used safely. */
33
+ export declare class KvSlotStateInvalidError extends KvPersistError {
34
+ readonly slotId: number;
35
+ constructor(slotId: number, message: string);
36
+ }
37
+ /** The requested snapshot does not exist. */
38
+ export declare class KvSnapshotNotFoundError extends KvPersistError {
39
+ constructor(message: string);
40
+ }
41
+ /** A snapshot exists but its runtime identity is incompatible. */
42
+ export declare class KvSnapshotIncompatibleError extends KvPersistError {
43
+ constructor(message: string);
44
+ }
45
+ /** A snapshot exists but cannot be used (corrupt, truncated, failed restore). */
46
+ export declare class KvSnapshotCorruptError extends KvPersistError {
47
+ constructor(message: string, options?: ErrorOptions);
48
+ }
49
+ /** A save operation failed on the backend. */
50
+ export declare class KvSaveFailedError extends KvPersistError {
51
+ constructor(message: string, options?: ErrorOptions);
52
+ }
53
+ /** A restore operation failed on the backend. */
54
+ export declare class KvRestoreFailedError extends KvPersistError {
55
+ constructor(message: string, options?: ErrorOptions);
56
+ }
57
+ /** An erase operation failed on the backend. */
58
+ export declare class KvEraseFailedError extends KvPersistError {
59
+ constructor(message: string, options?: ErrorOptions);
60
+ }
61
+ /** A snapshot manifest exists but fails schema validation. */
62
+ export declare class KvManifestInvalidError extends KvPersistError {
63
+ constructor(message: string);
64
+ }
65
+ /** Local metadata storage could not be read or written. */
66
+ export declare class KvMetadataIoError extends KvPersistError {
67
+ constructor(message: string, options?: ErrorOptions);
68
+ }
69
+ /** A persistence operation exceeded its own bounded timeout (SPEC §59). */
70
+ export declare class KvOperationTimeoutError extends KvPersistError {
71
+ constructor(message: string, options?: ErrorOptions);
72
+ }
73
+ /** An internal invariant was violated; always a plugin bug. */
74
+ export declare class KvInvariantError extends KvPersistError {
75
+ constructor(message: string);
76
+ }
77
+ /**
78
+ * Why a snapshot was invalidated (SPEC §31). Invalidation never deletes
79
+ * binary data; it only flips manifest state so cleanup can happen later.
80
+ */
81
+ export type SnapshotInvalidationReason = "MODEL_FINGERPRINT_CHANGED" | "RESTORE_FAILED" | "MANIFEST_MALFORMED" | "SNAPSHOT_FILE_MISSING" | "EXPLICIT";
82
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,kBAAkB,GAC1B,wBAAwB,GACxB,wBAAwB,GACxB,mBAAmB,GACnB,cAAc,GACd,uBAAuB,GACvB,uBAAuB,GACvB,0BAA0B,GAC1B,qBAAqB,GACrB,gBAAgB,GAChB,mBAAmB,GACnB,iBAAiB,GACjB,qBAAqB,GACrB,gBAAgB,GAChB,sBAAsB,GACtB,cAAc,CAAC;AAEnB,kDAAkD;AAClD,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;gBAEtB,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAK9E;AAED,gEAAgE;AAChE,qBAAa,yBAA0B,SAAQ,cAAc;gBAC/C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAGpD;AAED,6EAA6E;AAC7E,qBAAa,yBAA0B,SAAQ,cAAc;gBAC/C,OAAO,EAAE,MAAM;CAG5B;AAED,mEAAmE;AACnE,qBAAa,mBAAoB,SAAQ,cAAc;IACrD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAI7C;AAED,uDAAuD;AACvD,qBAAa,eAAgB,SAAQ,cAAc;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAI7C;AAED,oEAAoE;AACpE,qBAAa,uBAAwB,SAAQ,cAAc;IACzD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAI5C;AAED,6CAA6C;AAC7C,qBAAa,uBAAwB,SAAQ,cAAc;gBAC7C,OAAO,EAAE,MAAM;CAG5B;AAED,kEAAkE;AAClE,qBAAa,2BAA4B,SAAQ,cAAc;gBACjD,OAAO,EAAE,MAAM;CAG5B;AAED,iFAAiF;AACjF,qBAAa,sBAAuB,SAAQ,cAAc;gBAC5C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAGpD;AAED,8CAA8C;AAC9C,qBAAa,iBAAkB,SAAQ,cAAc;gBACvC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAGpD;AAED,iDAAiD;AACjD,qBAAa,oBAAqB,SAAQ,cAAc;gBAC1C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAGpD;AAED,gDAAgD;AAChD,qBAAa,kBAAmB,SAAQ,cAAc;gBACxC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAGpD;AAED,8DAA8D;AAC9D,qBAAa,sBAAuB,SAAQ,cAAc;gBAC5C,OAAO,EAAE,MAAM;CAG5B;AAED,2DAA2D;AAC3D,qBAAa,iBAAkB,SAAQ,cAAc;gBACvC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAGpD;AAED,2EAA2E;AAC3E,qBAAa,uBAAwB,SAAQ,cAAc;gBAC7C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAGpD;AAED,+DAA+D;AAC/D,qBAAa,gBAAiB,SAAQ,cAAc;gBACtC,OAAO,EAAE,MAAM;CAG5B;AAED;;;GAGG;AACH,MAAM,MAAM,0BAA0B,GAClC,2BAA2B,GAC3B,gBAAgB,GAChB,oBAAoB,GACpB,uBAAuB,GACvB,UAAU,CAAC"}
package/lib/errors.js ADDED
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Error taxonomy for the kv-persist plugin (SPEC §79).
3
+ *
4
+ * Every failure carries a stable machine-readable `code`; messages are for
5
+ * humans. Per the failure policy (SPEC §32) these errors normally degrade to
6
+ * cold inference — only `strict: true` turns them into request failures.
7
+ */
8
+ /** Base class of every typed kv-persist error. */
9
+ export class KvPersistError extends Error {
10
+ code;
11
+ constructor(code, message, options) {
12
+ super(message, options);
13
+ this.name = new.target.name;
14
+ this.code = code;
15
+ }
16
+ }
17
+ /** The llama server or its slots endpoint cannot be reached. */
18
+ export class KvBackendUnavailableError extends KvPersistError {
19
+ constructor(message, options) {
20
+ super("KV_BACKEND_UNAVAILABLE", message, options);
21
+ }
22
+ }
23
+ /** The configured backend type does not expose the required slot surface. */
24
+ export class KvBackendUnsupportedError extends KvPersistError {
25
+ constructor(message) {
26
+ super("KV_BACKEND_UNSUPPORTED", message);
27
+ }
28
+ }
29
+ /** A slot operation referenced a slot the server does not have. */
30
+ export class KvSlotNotFoundError extends KvPersistError {
31
+ slotId;
32
+ constructor(slotId, message) {
33
+ super("KV_SLOT_NOT_FOUND", message ?? `slot ${slotId} not found on the server`);
34
+ this.slotId = slotId;
35
+ }
36
+ }
37
+ /** A slot is busy with another exclusive operation. */
38
+ export class KvSlotBusyError extends KvPersistError {
39
+ slotId;
40
+ constructor(slotId, message) {
41
+ super("KV_SLOT_BUSY", message ?? `slot ${slotId} is busy`);
42
+ this.slotId = slotId;
43
+ }
44
+ }
45
+ /** The slot exists but its reported state cannot be used safely. */
46
+ export class KvSlotStateInvalidError extends KvPersistError {
47
+ slotId;
48
+ constructor(slotId, message) {
49
+ super("KV_SLOT_STATE_INVALID", message);
50
+ this.slotId = slotId;
51
+ }
52
+ }
53
+ /** The requested snapshot does not exist. */
54
+ export class KvSnapshotNotFoundError extends KvPersistError {
55
+ constructor(message) {
56
+ super("KV_SNAPSHOT_NOT_FOUND", message);
57
+ }
58
+ }
59
+ /** A snapshot exists but its runtime identity is incompatible. */
60
+ export class KvSnapshotIncompatibleError extends KvPersistError {
61
+ constructor(message) {
62
+ super("KV_SNAPSHOT_INCOMPATIBLE", message);
63
+ }
64
+ }
65
+ /** A snapshot exists but cannot be used (corrupt, truncated, failed restore). */
66
+ export class KvSnapshotCorruptError extends KvPersistError {
67
+ constructor(message, options) {
68
+ super("KV_SNAPSHOT_CORRUPT", message, options);
69
+ }
70
+ }
71
+ /** A save operation failed on the backend. */
72
+ export class KvSaveFailedError extends KvPersistError {
73
+ constructor(message, options) {
74
+ super("KV_SAVE_FAILED", message, options);
75
+ }
76
+ }
77
+ /** A restore operation failed on the backend. */
78
+ export class KvRestoreFailedError extends KvPersistError {
79
+ constructor(message, options) {
80
+ super("KV_RESTORE_FAILED", message, options);
81
+ }
82
+ }
83
+ /** An erase operation failed on the backend. */
84
+ export class KvEraseFailedError extends KvPersistError {
85
+ constructor(message, options) {
86
+ super("KV_ERASE_FAILED", message, options);
87
+ }
88
+ }
89
+ /** A snapshot manifest exists but fails schema validation. */
90
+ export class KvManifestInvalidError extends KvPersistError {
91
+ constructor(message) {
92
+ super("KV_MANIFEST_INVALID", message);
93
+ }
94
+ }
95
+ /** Local metadata storage could not be read or written. */
96
+ export class KvMetadataIoError extends KvPersistError {
97
+ constructor(message, options) {
98
+ super("KV_METADATA_IO", message, options);
99
+ }
100
+ }
101
+ /** A persistence operation exceeded its own bounded timeout (SPEC §59). */
102
+ export class KvOperationTimeoutError extends KvPersistError {
103
+ constructor(message, options) {
104
+ super("KV_OPERATION_TIMEOUT", message, options);
105
+ }
106
+ }
107
+ /** An internal invariant was violated; always a plugin bug. */
108
+ export class KvInvariantError extends KvPersistError {
109
+ constructor(message) {
110
+ super("KV_INVARIANT", message);
111
+ }
112
+ }
113
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * dsh-kv-persist — persistent KV-cache/session-state manager (SPEC §1).
3
+ *
4
+ * The Cordis entrypoint: registers `ctx.kvPersist`, the `llm/stream`
5
+ * coordination wrapper, and the session lifecycle listeners. All logic
6
+ * lives in the domain modules (SPEC §10).
7
+ */
8
+ import { KvPersistService } from "./service.js";
9
+ export { KvPersistService } from "./service.js";
10
+ export type { KvPersistStatus, SessionKvState, KvPersistDoctorReport, KvPersistServiceDeps, } from "./service.js";
11
+ export { resolveKvPersistConfig, isManagedProvider, KvPersistConfigSchema } from "./config.js";
12
+ export type { KvPersistConfig, ResolvedKvPersistConfig } from "./config.js";
13
+ export { KvPersistError, KvBackendUnavailableError, KvBackendUnsupportedError, KvSaveFailedError, KvRestoreFailedError, KvEraseFailedError, } from "./errors.js";
14
+ export type { KvPersistErrorCode, SnapshotInvalidationReason } from "./errors.js";
15
+ export type { KvPersistenceBackend, BackendCapabilities } from "./backends/types.js";
16
+ export { LlamaCppBackend } from "./backends/llama-cpp/backend.js";
17
+ export { SingleSlotCoordinator } from "./coordinator/coordinator.js";
18
+ export { SnapshotRepository } from "./snapshots/repository.js";
19
+ export { snapshotFilename } from "./snapshots/naming.js";
20
+ declare module "@deepseek-ai/cordis" {
21
+ interface Context {
22
+ kvPersist: KvPersistService;
23
+ }
24
+ }
25
+ export default KvPersistService;
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,YAAY,EACV,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC/F,YAAY,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,yBAAyB,EACzB,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAClF,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,SAAS,EAAE,gBAAgB,CAAC;KAC7B;CACF;AAED,eAAe,gBAAgB,CAAC"}
package/lib/index.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * dsh-kv-persist — persistent KV-cache/session-state manager (SPEC §1).
3
+ *
4
+ * The Cordis entrypoint: registers `ctx.kvPersist`, the `llm/stream`
5
+ * coordination wrapper, and the session lifecycle listeners. All logic
6
+ * lives in the domain modules (SPEC §10).
7
+ */
8
+ import { KvPersistService } from "./service.js";
9
+ export { KvPersistService } from "./service.js";
10
+ export { resolveKvPersistConfig, isManagedProvider, KvPersistConfigSchema } from "./config.js";
11
+ export { KvPersistError, KvBackendUnavailableError, KvBackendUnsupportedError, KvSaveFailedError, KvRestoreFailedError, KvEraseFailedError, } from "./errors.js";
12
+ export { LlamaCppBackend } from "./backends/llama-cpp/backend.js";
13
+ export { SingleSlotCoordinator } from "./coordinator/coordinator.js";
14
+ export { SnapshotRepository } from "./snapshots/repository.js";
15
+ export { snapshotFilename } from "./snapshots/naming.js";
16
+ export default KvPersistService;
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAOhD,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAE/F,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,yBAAyB,EACzB,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAQzD,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * DSH home resolution for plugin runtime helpers.
3
+ *
4
+ * Part of the future `@yadsh/dsh-plugin-log` package seed: this folder is a
5
+ * verbatim, self-contained copy in every adopting plugin (guidelines §5.2),
6
+ * so keep it free of imports outside `./`.
7
+ */
8
+ /**
9
+ * Resolve the DSH home directory: `$DSH_HOME` when set to a non-blank value,
10
+ * otherwise `~/.dsh` (the same convention as `dsh-draft-sessions` storage).
11
+ */
12
+ export declare function resolveDshHome(env?: NodeJS.ProcessEnv): string;
13
+ //# sourceMappingURL=dsh-home.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dsh-home.d.ts","sourceRoot":"","sources":["../../src/logging/dsh-home.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAG3E"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * DSH home resolution for plugin runtime helpers.
3
+ *
4
+ * Part of the future `@yadsh/dsh-plugin-log` package seed: this folder is a
5
+ * verbatim, self-contained copy in every adopting plugin (guidelines §5.2),
6
+ * so keep it free of imports outside `./`.
7
+ */
8
+ import { homedir } from "node:os";
9
+ import { join, resolve } from "node:path";
10
+ /**
11
+ * Resolve the DSH home directory: `$DSH_HOME` when set to a non-blank value,
12
+ * otherwise `~/.dsh` (the same convention as `dsh-draft-sessions` storage).
13
+ */
14
+ export function resolveDshHome(env = process.env) {
15
+ const configured = env.DSH_HOME?.trim();
16
+ return configured ? resolve(configured) : join(homedir(), ".dsh");
17
+ }
18
+ //# sourceMappingURL=dsh-home.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dsh-home.js","sourceRoot":"","sources":["../../src/logging/dsh-home.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAAyB,OAAO,CAAC,GAAG;IACjE,MAAM,UAAU,GAAG,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;IACxC,OAAO,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC;AACpE,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Plugin logging bundle (future `@yadsh/dsh-plugin-log`).
3
+ *
4
+ * Self-contained by design: every import stays inside this folder so the
5
+ * whole directory can be copied between plugins verbatim, or replaced by the
6
+ * extracted package import once it exists.
7
+ */
8
+ export * from "./dsh-home.js";
9
+ export * from "./plugin-logger.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/logging/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Plugin logging bundle (future `@yadsh/dsh-plugin-log`).
3
+ *
4
+ * Self-contained by design: every import stays inside this folder so the
5
+ * whole directory can be copied between plugins verbatim, or replaced by the
6
+ * extracted package import once it exists.
7
+ */
8
+ export * from "./dsh-home.js";
9
+ export * from "./plugin-logger.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/logging/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Plugin file logger — the seed of the future `@yadsh/dsh-plugin-log` package.
3
+ *
4
+ * Every plugin currently carries its own verbatim copy of `src/logging/`
5
+ * (guidelines §5.2); the exported API below is frozen so that switching to
6
+ * the extracted package later is a one-line import change. The wrapper:
7
+ *
8
+ * - wraps `pino` for severity levels and NDJSON serialization;
9
+ * - writes daily files `<dir>/<YYYY-MM-DD>.log`, by default under
10
+ * `<$DSH_HOME>/logs/<pluginId>`;
11
+ * - mirrors selected records to an injectable console sink (default level
12
+ * `warn`) so operators still see problems live;
13
+ * - never throws at runtime: file-system failures degrade to console-only
14
+ * logging (fail-open), and closed loggers silently drop records;
15
+ * - disables file output when `DSH_LOG_DISABLED=1`, and under `NODE_ENV=test`
16
+ * unless `dir` is set explicitly (unit tests never touch a real home).
17
+ *
18
+ * Record shape (one JSON object per line): pino's `level` (numeric),
19
+ * `time` (epoch ms) and `msg` (= the event code), plus `plugin` and the
20
+ * caller's fields; `child(module)` adds `module`. Reserved pino keys
21
+ * (`level`, `time`, `msg`, `plugin`, `module`) must not be used as field
22
+ * names.
23
+ */
24
+ /** Ordered severity levels; `silent` disables the logger entirely. */
25
+ export declare const PLUGIN_LOG_LEVELS: readonly ["trace", "debug", "info", "warn", "error", "fatal", "silent"];
26
+ export type PluginLogLevel = (typeof PLUGIN_LOG_LEVELS)[number];
27
+ /** Every level except `silent` (which also disables the console mirror). */
28
+ export type ConsoleLevel = Exclude<PluginLogLevel, "silent">;
29
+ /**
30
+ * Receives console-mirrored records. Must not throw; the wrapper guards every
31
+ * call regardless.
32
+ */
33
+ export type PluginConsoleSink = (level: ConsoleLevel, message: string) => void;
34
+ /** Default console mirror threshold. */
35
+ export declare const DEFAULT_CONSOLE_LEVEL: PluginLogLevel;
36
+ /** Daily log files kept per plugin by default (0 = keep forever). */
37
+ export declare const DEFAULT_LOG_RETENTION_DAYS = 14;
38
+ /** Type guard for level strings (config parsing, env overrides). */
39
+ export declare function isPluginLogLevel(value: unknown): value is PluginLogLevel;
40
+ /** Logger configuration; every field except `pluginId` is optional. */
41
+ export interface PluginLoggerOptions {
42
+ /**
43
+ * Plugin id: directory name, `plugin` record field and env-prefix source
44
+ * (`DSH_LOG_LEVEL_<ID>`). Must match `[A-Za-z0-9][A-Za-z0-9._-]*`.
45
+ */
46
+ readonly pluginId: string;
47
+ /** Severity threshold. Default: `DSH_LOG_LEVEL_<ID>` / `DSH_LOG_LEVEL` env, else `info`. */
48
+ readonly level?: PluginLogLevel;
49
+ /** Absolute log directory. Default: `<$DSH_HOME>/logs/<pluginId>`. */
50
+ readonly dir?: string;
51
+ /** Overrides the DSH home used to build the default `dir` (tests). */
52
+ readonly dshHome?: string;
53
+ /** Console mirror threshold; `silent` disables mirroring. Default: `warn`. */
54
+ readonly console?: PluginLogLevel;
55
+ /** Mirror target. Default: the global `console`. */
56
+ readonly consoleSink?: PluginConsoleSink;
57
+ /** Daily files older than this are deleted on rollover. Default: 14; 0 disables. */
58
+ readonly retentionDays?: number;
59
+ /** Master switch for file output. Default: auto (see the module docs). */
60
+ readonly file?: boolean;
61
+ /** Record fields to redact (pino `redact` paths), e.g. `["apiKey"]`. */
62
+ readonly redact?: readonly string[];
63
+ /** Clock for file naming, rollover and retention (tests). */
64
+ readonly now?: () => number;
65
+ }
66
+ /** Stable logging surface shared by every plugin (future package contract). */
67
+ export interface PluginLogger {
68
+ trace(event: string, fields?: Record<string, unknown>): void;
69
+ debug(event: string, fields?: Record<string, unknown>): void;
70
+ info(event: string, fields?: Record<string, unknown>): void;
71
+ warn(event: string, fields?: Record<string, unknown>): void;
72
+ error(event: string, fields?: Record<string, unknown>): void;
73
+ fatal(event: string, fields?: Record<string, unknown>): void;
74
+ /** Bound sub-logger that adds a `module` field to every record. */
75
+ child(module: string): PluginLogger;
76
+ /** Current severity threshold. */
77
+ get level(): PluginLogLevel;
78
+ /** Change the severity threshold at runtime. */
79
+ setLevel(level: PluginLogLevel): void;
80
+ /** Best-effort synchronous flush of buffered file output. */
81
+ flush(): void;
82
+ /** Flush and close the destination; idempotent; later writes are dropped. */
83
+ close(): Promise<void>;
84
+ }
85
+ /** Create a standalone logger instance (no caching). */
86
+ export declare function createPluginLogger(options: PluginLoggerOptions): PluginLogger;
87
+ /**
88
+ * Create or return the cached logger for `pluginId` + resolved `dir`. A later
89
+ * call with an explicit `level` updates the cached instance's threshold, so
90
+ * plugin config reloads take effect. `close()` evicts the cache entry; the
91
+ * next call creates a fresh instance.
92
+ */
93
+ export declare function getPluginLogger(options: PluginLoggerOptions): PluginLogger;
94
+ //# sourceMappingURL=plugin-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-logger.d.ts","sourceRoot":"","sources":["../../src/logging/plugin-logger.ts"],"names":[],"mappings":"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"}