@theokit/sdk 4.0.2 → 4.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.
- package/CHANGELOG.md +6 -0
- package/dist/a2a/index.cjs +129 -97
- package/dist/a2a/index.cjs.map +1 -1
- package/dist/a2a/index.js +129 -97
- package/dist/a2a/index.js.map +1 -1
- package/dist/{cron-L5QTlAtl.d.ts → cron-AzT5D0VP.d.ts} +89 -1
- package/dist/{cron-BfPhZjRJ.d.cts → cron-BlAjYOew.d.cts} +89 -1
- package/dist/cron.cjs +129 -97
- package/dist/cron.cjs.map +1 -1
- package/dist/cron.d.cts +1 -1
- package/dist/cron.d.ts +1 -1
- package/dist/cron.js +129 -97
- package/dist/cron.js.map +1 -1
- package/dist/eval.cjs +129 -97
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +129 -97
- package/dist/eval.js.map +1 -1
- package/dist/index.cjs +129 -97
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +129 -97
- package/dist/index.js.map +1 -1
- package/dist/internal/persistence/fs-session-store.d.cts +26 -0
- package/dist/internal/persistence/fs-session-store.d.ts +26 -0
- package/dist/internal/runtime/session/agent-session-store.d.ts +21 -13
- package/dist/types/agent.d.ts +10 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/session-store.d.ts +59 -0
- package/package.json +1 -1
|
@@ -626,6 +626,84 @@ declare class Skill {
|
|
|
626
626
|
static create(spec: CreateSkillSpec): InlineSkill;
|
|
627
627
|
}
|
|
628
628
|
|
|
629
|
+
/** One transcript record (one JSONL line). `message` absent on `system` (compact_boundary) records. */
|
|
630
|
+
interface SessionRecord {
|
|
631
|
+
type: "user" | "assistant" | "system";
|
|
632
|
+
uuid: string;
|
|
633
|
+
parentUuid: string | null;
|
|
634
|
+
sessionId: string;
|
|
635
|
+
timestamp: string;
|
|
636
|
+
isSidechain?: boolean;
|
|
637
|
+
userType?: string;
|
|
638
|
+
cwd?: string;
|
|
639
|
+
version?: string;
|
|
640
|
+
subtype?: string;
|
|
641
|
+
compactMetadata?: {
|
|
642
|
+
preTokens: number;
|
|
643
|
+
trigger: string;
|
|
644
|
+
};
|
|
645
|
+
message?: Record<string, unknown>;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* SE41 — the pluggable `SessionStore` seam over the NATIVE session transcript.
|
|
650
|
+
*
|
|
651
|
+
* A minimal, two-method port so an external store (Postgres / Redis / KV /
|
|
652
|
+
* durable object) can be the **primary store AND resume source** — the
|
|
653
|
+
* serverless (ephemeral FS) and multi-host / multi-pod use case that SE40
|
|
654
|
+
* dropped when it removed the `ConversationStorageAdapter`. This is deliberately
|
|
655
|
+
* NOT that removed ~10-method adapter: the seam is JUST record read/append over
|
|
656
|
+
* the native {@link SessionRecord} shape (no getMessages / getSessionMeta /
|
|
657
|
+
* delete / objective methods).
|
|
658
|
+
*
|
|
659
|
+
* The SDK ships a real default implementation, `FsSessionStore`, that reads and
|
|
660
|
+
* append-writes the native Claude-shaped `.jsonl` transcript — omitting
|
|
661
|
+
* `local.sessionStore` yields byte-identical current behavior (back-compat, zero
|
|
662
|
+
* consumer change). Injected via `local.sessionStore` for external stores.
|
|
663
|
+
*
|
|
664
|
+
* Consistency contract: `appendRecords` is append-only and ordering-preserving.
|
|
665
|
+
* The FS default serializes appends per agent with a cross-process file lock;
|
|
666
|
+
* external implementations own (and MUST document) their own concurrency
|
|
667
|
+
* guarantees for two hosts appending to the same `agentId`.
|
|
668
|
+
*
|
|
669
|
+
* @public
|
|
670
|
+
*/
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* The pluggable session-store seam. Exactly two methods over the native
|
|
674
|
+
* {@link SessionRecord} shape.
|
|
675
|
+
*
|
|
676
|
+
* @public
|
|
677
|
+
*/
|
|
678
|
+
interface SessionStore {
|
|
679
|
+
/**
|
|
680
|
+
* Return every persisted record for `agentId`, in append order. A session
|
|
681
|
+
* that was never written MUST resolve to `[]` (not throw) — a fresh agent has
|
|
682
|
+
* no history. The SDK reconstructs the resumable `LlmMessage[]` from these
|
|
683
|
+
* records via the native DAG reader, so the shape MUST be the exact
|
|
684
|
+
* {@link SessionRecord} the SDK writes.
|
|
685
|
+
*
|
|
686
|
+
* A store that cannot READ (e.g. the backing DB is unreachable on resume)
|
|
687
|
+
* MUST throw a typed error rather than silently returning `[]` — a silent
|
|
688
|
+
* empty read would masquerade as "no history" and drop the conversation.
|
|
689
|
+
*/
|
|
690
|
+
readRecords(agentId: string): Promise<SessionRecord[]>;
|
|
691
|
+
/**
|
|
692
|
+
* Append `records` (the new-turn delta) to `agentId`'s session, append-only.
|
|
693
|
+
* MUST preserve order and MUST NOT drop or rewrite prior records — the native
|
|
694
|
+
* format is an append-only `parentUuid` DAG (compaction is a new-root
|
|
695
|
+
* `compact_boundary` record, still an append).
|
|
696
|
+
*
|
|
697
|
+
* Note on the write path: per-turn persistence is fire-and-forget so `send()`
|
|
698
|
+
* is never blocked by store I/O — an `appendRecords` rejection is logged to
|
|
699
|
+
* stderr, NOT thrown to the caller (best-effort write). An external store that
|
|
700
|
+
* must guarantee durability should make `appendRecords` resilient (retry /
|
|
701
|
+
* durable write) internally. This differs from {@link SessionStore.readRecords},
|
|
702
|
+
* which MUST throw on failure (a resume cannot proceed on a silent partial history).
|
|
703
|
+
*/
|
|
704
|
+
appendRecords(agentId: string, records: readonly SessionRecord[]): Promise<void>;
|
|
705
|
+
}
|
|
706
|
+
|
|
629
707
|
/**
|
|
630
708
|
* Context manager backend.
|
|
631
709
|
*
|
|
@@ -989,6 +1067,16 @@ interface LocalOptions {
|
|
|
989
1067
|
* Set to `~/.claude` to write sessions the Claude Code CLI can `--continue`.
|
|
990
1068
|
*/
|
|
991
1069
|
baseDir?: string;
|
|
1070
|
+
/**
|
|
1071
|
+
* SE41 — inject an external {@link import("./session-store.js").SessionStore}
|
|
1072
|
+
* (Postgres / Redis / KV / durable object) as the PRIMARY session store and
|
|
1073
|
+
* resume source. Omit for the default FS transcript store (`baseDir` above) —
|
|
1074
|
+
* byte-identical to SE40. Use this for serverless (ephemeral FS) or multi-host /
|
|
1075
|
+
* multi-pod deployments where a resumed agent must read its history from a shared
|
|
1076
|
+
* store instead of local disk. The records stay the native Claude-shaped shape,
|
|
1077
|
+
* so `--continue` interop is preserved (a store may also mirror to `~/.claude`).
|
|
1078
|
+
*/
|
|
1079
|
+
sessionStore?: SessionStore;
|
|
992
1080
|
}
|
|
993
1081
|
/**
|
|
994
1082
|
* Repo to clone into a cloud agent's VM.
|
|
@@ -2442,4 +2530,4 @@ declare class Cron {
|
|
|
2442
2530
|
static status(_options?: CronStartOptions): Promise<CronSchedulerStatus>;
|
|
2443
2531
|
}
|
|
2444
2532
|
|
|
2445
|
-
export { type GoalOptions as $, type AgentOptions as A, type BudgetTracker as B, type CloudOptions as C, type ContextBudget as D, type ContextManagerKind as E, type ContextSnapshot as F, type GetAgentOptions as G, type ContextSource as H, type InlineSkill as I, type ContextSourceStatus as J, type CreateSkillSpec as K, type LocalOptions as L, type MemorySettings as M, Cron as N, type CronCreateOptions as O, type ProviderRoutingSettings as P, type CronGetOptions as Q, type CronJob as R, type SystemPromptResolver as S, type CronJobStatus as T, type CronListOptions as U, type CronOperationOptions as V, type CronRunOptions as W, type CronRuntime as X, type CronSchedulerStatus as Y, type CronStartOptions as Z, type GoalEvent as _, type AgentDefinition as a, type GoalResult as a0, type HookName as a1, type InvalidateCacheOptions as a2, type MemoryAdapter as a3, type MemoryAdapterCapabilities as a4, type MemoryContext as a5, type MemoryFact as a6, type MemoryProviderHandle as a7, type MemoryProviderInitOptions as a8, type MemoryRevision as a9, type
|
|
2533
|
+
export { type GoalOptions as $, type AgentOptions as A, type BudgetTracker as B, type CloudOptions as C, type ContextBudget as D, type ContextManagerKind as E, type ContextSnapshot as F, type GetAgentOptions as G, type ContextSource as H, type InlineSkill as I, type ContextSourceStatus as J, type CreateSkillSpec as K, type LocalOptions as L, type MemorySettings as M, Cron as N, type CronCreateOptions as O, type ProviderRoutingSettings as P, type CronGetOptions as Q, type CronJob as R, type SystemPromptResolver as S, type CronJobStatus as T, type CronListOptions as U, type CronOperationOptions as V, type CronRunOptions as W, type CronRuntime as X, type CronSchedulerStatus as Y, type CronStartOptions as Z, type GoalEvent as _, type AgentDefinition as a, type GoalResult as a0, type HookName as a1, type InvalidateCacheOptions as a2, type MemoryAdapter as a3, type MemoryAdapterCapabilities as a4, type MemoryContext as a5, type MemoryFact as a6, type MemoryProviderHandle as a7, type MemoryProviderInitOptions as a8, type MemoryRevision as a9, type SystemPromptContext as aA, type SystemPromptMemoryFact as aB, type SystemPromptSkillRef as aC, type TelemetrySettings as aD, type MemoryToolSchema as aa, type MemoryTurnMessage as ab, type PersonalityPreset as ac, type PluginContext as ad, type PostAssistantReplyContext as ae, type PreToolCallContext as af, type PreUserSendContext as ag, type PreUserSendResult as ah, type ProviderCapability as ai, type ProviderRoute as aj, type RecordSessionSummaryArgs as ak, type ResolvedProviderRoute as al, type RunUntilIterator as am, type SDKAgentPlugins as an, type SDKAgentSkillDetail as ao, type SDKAgentSkills as ap, type SDKArtifact as aq, type SDKContextManager as ar, type SDKPluginMetadata as as, type SDKProvidersManager as at, type SessionRecord as au, type SessionStore as av, type SettingSource as aw, Skill as ax, type SkillsResolver as ay, type SkillsResolverContext as az, type ContextSettings as b, type PluginsSettings as c, type SkillsSettings as d, type SDKAgent as e, type ListAgentsOptions as f, type ListResult as g, type SDKAgentInfo as h, type ListRunsOptions as i, type GetRunOptions as j, type AgentOperationOptions as k, type ProviderProfile as l, Plugin as m, type MemoryProvider as n, type MemoryId as o, type PreToolCallDecision as p, type StepResult as q, type SDKProvider as r, type ActiveMemoryPassArgs as s, type ActiveMemoryPassResult as t, type AgentMemory as u, type BudgetCheck as v, type BudgetTotal as w, type BudgetUsageEvent as x, type CloudEnv as y, type CloudRepo as z };
|
|
@@ -626,6 +626,84 @@ declare class Skill {
|
|
|
626
626
|
static create(spec: CreateSkillSpec): InlineSkill;
|
|
627
627
|
}
|
|
628
628
|
|
|
629
|
+
/** One transcript record (one JSONL line). `message` absent on `system` (compact_boundary) records. */
|
|
630
|
+
interface SessionRecord {
|
|
631
|
+
type: "user" | "assistant" | "system";
|
|
632
|
+
uuid: string;
|
|
633
|
+
parentUuid: string | null;
|
|
634
|
+
sessionId: string;
|
|
635
|
+
timestamp: string;
|
|
636
|
+
isSidechain?: boolean;
|
|
637
|
+
userType?: string;
|
|
638
|
+
cwd?: string;
|
|
639
|
+
version?: string;
|
|
640
|
+
subtype?: string;
|
|
641
|
+
compactMetadata?: {
|
|
642
|
+
preTokens: number;
|
|
643
|
+
trigger: string;
|
|
644
|
+
};
|
|
645
|
+
message?: Record<string, unknown>;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* SE41 — the pluggable `SessionStore` seam over the NATIVE session transcript.
|
|
650
|
+
*
|
|
651
|
+
* A minimal, two-method port so an external store (Postgres / Redis / KV /
|
|
652
|
+
* durable object) can be the **primary store AND resume source** — the
|
|
653
|
+
* serverless (ephemeral FS) and multi-host / multi-pod use case that SE40
|
|
654
|
+
* dropped when it removed the `ConversationStorageAdapter`. This is deliberately
|
|
655
|
+
* NOT that removed ~10-method adapter: the seam is JUST record read/append over
|
|
656
|
+
* the native {@link SessionRecord} shape (no getMessages / getSessionMeta /
|
|
657
|
+
* delete / objective methods).
|
|
658
|
+
*
|
|
659
|
+
* The SDK ships a real default implementation, `FsSessionStore`, that reads and
|
|
660
|
+
* append-writes the native Claude-shaped `.jsonl` transcript — omitting
|
|
661
|
+
* `local.sessionStore` yields byte-identical current behavior (back-compat, zero
|
|
662
|
+
* consumer change). Injected via `local.sessionStore` for external stores.
|
|
663
|
+
*
|
|
664
|
+
* Consistency contract: `appendRecords` is append-only and ordering-preserving.
|
|
665
|
+
* The FS default serializes appends per agent with a cross-process file lock;
|
|
666
|
+
* external implementations own (and MUST document) their own concurrency
|
|
667
|
+
* guarantees for two hosts appending to the same `agentId`.
|
|
668
|
+
*
|
|
669
|
+
* @public
|
|
670
|
+
*/
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* The pluggable session-store seam. Exactly two methods over the native
|
|
674
|
+
* {@link SessionRecord} shape.
|
|
675
|
+
*
|
|
676
|
+
* @public
|
|
677
|
+
*/
|
|
678
|
+
interface SessionStore {
|
|
679
|
+
/**
|
|
680
|
+
* Return every persisted record for `agentId`, in append order. A session
|
|
681
|
+
* that was never written MUST resolve to `[]` (not throw) — a fresh agent has
|
|
682
|
+
* no history. The SDK reconstructs the resumable `LlmMessage[]` from these
|
|
683
|
+
* records via the native DAG reader, so the shape MUST be the exact
|
|
684
|
+
* {@link SessionRecord} the SDK writes.
|
|
685
|
+
*
|
|
686
|
+
* A store that cannot READ (e.g. the backing DB is unreachable on resume)
|
|
687
|
+
* MUST throw a typed error rather than silently returning `[]` — a silent
|
|
688
|
+
* empty read would masquerade as "no history" and drop the conversation.
|
|
689
|
+
*/
|
|
690
|
+
readRecords(agentId: string): Promise<SessionRecord[]>;
|
|
691
|
+
/**
|
|
692
|
+
* Append `records` (the new-turn delta) to `agentId`'s session, append-only.
|
|
693
|
+
* MUST preserve order and MUST NOT drop or rewrite prior records — the native
|
|
694
|
+
* format is an append-only `parentUuid` DAG (compaction is a new-root
|
|
695
|
+
* `compact_boundary` record, still an append).
|
|
696
|
+
*
|
|
697
|
+
* Note on the write path: per-turn persistence is fire-and-forget so `send()`
|
|
698
|
+
* is never blocked by store I/O — an `appendRecords` rejection is logged to
|
|
699
|
+
* stderr, NOT thrown to the caller (best-effort write). An external store that
|
|
700
|
+
* must guarantee durability should make `appendRecords` resilient (retry /
|
|
701
|
+
* durable write) internally. This differs from {@link SessionStore.readRecords},
|
|
702
|
+
* which MUST throw on failure (a resume cannot proceed on a silent partial history).
|
|
703
|
+
*/
|
|
704
|
+
appendRecords(agentId: string, records: readonly SessionRecord[]): Promise<void>;
|
|
705
|
+
}
|
|
706
|
+
|
|
629
707
|
/**
|
|
630
708
|
* Context manager backend.
|
|
631
709
|
*
|
|
@@ -989,6 +1067,16 @@ interface LocalOptions {
|
|
|
989
1067
|
* Set to `~/.claude` to write sessions the Claude Code CLI can `--continue`.
|
|
990
1068
|
*/
|
|
991
1069
|
baseDir?: string;
|
|
1070
|
+
/**
|
|
1071
|
+
* SE41 — inject an external {@link import("./session-store.js").SessionStore}
|
|
1072
|
+
* (Postgres / Redis / KV / durable object) as the PRIMARY session store and
|
|
1073
|
+
* resume source. Omit for the default FS transcript store (`baseDir` above) —
|
|
1074
|
+
* byte-identical to SE40. Use this for serverless (ephemeral FS) or multi-host /
|
|
1075
|
+
* multi-pod deployments where a resumed agent must read its history from a shared
|
|
1076
|
+
* store instead of local disk. The records stay the native Claude-shaped shape,
|
|
1077
|
+
* so `--continue` interop is preserved (a store may also mirror to `~/.claude`).
|
|
1078
|
+
*/
|
|
1079
|
+
sessionStore?: SessionStore;
|
|
992
1080
|
}
|
|
993
1081
|
/**
|
|
994
1082
|
* Repo to clone into a cloud agent's VM.
|
|
@@ -2442,4 +2530,4 @@ declare class Cron {
|
|
|
2442
2530
|
static status(_options?: CronStartOptions): Promise<CronSchedulerStatus>;
|
|
2443
2531
|
}
|
|
2444
2532
|
|
|
2445
|
-
export { type GoalOptions as $, type AgentOptions as A, type BudgetTracker as B, type CloudOptions as C, type ContextBudget as D, type ContextManagerKind as E, type ContextSnapshot as F, type GetAgentOptions as G, type ContextSource as H, type InlineSkill as I, type ContextSourceStatus as J, type CreateSkillSpec as K, type LocalOptions as L, type MemorySettings as M, Cron as N, type CronCreateOptions as O, type ProviderRoutingSettings as P, type CronGetOptions as Q, type CronJob as R, type SystemPromptResolver as S, type CronJobStatus as T, type CronListOptions as U, type CronOperationOptions as V, type CronRunOptions as W, type CronRuntime as X, type CronSchedulerStatus as Y, type CronStartOptions as Z, type GoalEvent as _, type AgentDefinition as a, type GoalResult as a0, type HookName as a1, type InvalidateCacheOptions as a2, type MemoryAdapter as a3, type MemoryAdapterCapabilities as a4, type MemoryContext as a5, type MemoryFact as a6, type MemoryProviderHandle as a7, type MemoryProviderInitOptions as a8, type MemoryRevision as a9, type
|
|
2533
|
+
export { type GoalOptions as $, type AgentOptions as A, type BudgetTracker as B, type CloudOptions as C, type ContextBudget as D, type ContextManagerKind as E, type ContextSnapshot as F, type GetAgentOptions as G, type ContextSource as H, type InlineSkill as I, type ContextSourceStatus as J, type CreateSkillSpec as K, type LocalOptions as L, type MemorySettings as M, Cron as N, type CronCreateOptions as O, type ProviderRoutingSettings as P, type CronGetOptions as Q, type CronJob as R, type SystemPromptResolver as S, type CronJobStatus as T, type CronListOptions as U, type CronOperationOptions as V, type CronRunOptions as W, type CronRuntime as X, type CronSchedulerStatus as Y, type CronStartOptions as Z, type GoalEvent as _, type AgentDefinition as a, type GoalResult as a0, type HookName as a1, type InvalidateCacheOptions as a2, type MemoryAdapter as a3, type MemoryAdapterCapabilities as a4, type MemoryContext as a5, type MemoryFact as a6, type MemoryProviderHandle as a7, type MemoryProviderInitOptions as a8, type MemoryRevision as a9, type SystemPromptContext as aA, type SystemPromptMemoryFact as aB, type SystemPromptSkillRef as aC, type TelemetrySettings as aD, type MemoryToolSchema as aa, type MemoryTurnMessage as ab, type PersonalityPreset as ac, type PluginContext as ad, type PostAssistantReplyContext as ae, type PreToolCallContext as af, type PreUserSendContext as ag, type PreUserSendResult as ah, type ProviderCapability as ai, type ProviderRoute as aj, type RecordSessionSummaryArgs as ak, type ResolvedProviderRoute as al, type RunUntilIterator as am, type SDKAgentPlugins as an, type SDKAgentSkillDetail as ao, type SDKAgentSkills as ap, type SDKArtifact as aq, type SDKContextManager as ar, type SDKPluginMetadata as as, type SDKProvidersManager as at, type SessionRecord as au, type SessionStore as av, type SettingSource as aw, Skill as ax, type SkillsResolver as ay, type SkillsResolverContext as az, type ContextSettings as b, type PluginsSettings as c, type SkillsSettings as d, type SDKAgent as e, type ListAgentsOptions as f, type ListResult as g, type SDKAgentInfo as h, type ListRunsOptions as i, type GetRunOptions as j, type AgentOperationOptions as k, type ProviderProfile as l, Plugin as m, type MemoryProvider as n, type MemoryId as o, type PreToolCallDecision as p, type StepResult as q, type SDKProvider as r, type ActiveMemoryPassArgs as s, type ActiveMemoryPassResult as t, type AgentMemory as u, type BudgetCheck as v, type BudgetTotal as w, type BudgetUsageEvent as x, type CloudEnv as y, type CloudRepo as z };
|
package/dist/cron.cjs
CHANGED
|
@@ -3510,6 +3510,72 @@ var init_cloud_tool_parity = __esm({
|
|
|
3510
3510
|
init_errors();
|
|
3511
3511
|
}
|
|
3512
3512
|
});
|
|
3513
|
+
|
|
3514
|
+
// src/internal/persistence/file-lock.ts
|
|
3515
|
+
async function getProperLockfile() {
|
|
3516
|
+
if (cached !== void 0) return cached;
|
|
3517
|
+
try {
|
|
3518
|
+
const mod = await import('proper-lockfile');
|
|
3519
|
+
if (!validateLockModule(mod)) {
|
|
3520
|
+
if (!warnedStructural) {
|
|
3521
|
+
warnedStructural = true;
|
|
3522
|
+
process.stderr.write(
|
|
3523
|
+
"[theokit-sdk] proper-lockfile: imported module does NOT expose the expected `lock`/`unlock` API surface. This may indicate a supply-chain compromise or an incompatible major version. Falling back to in-process mutex (no cross-process safety). Reinstall with: pnpm add proper-lockfile@^11\n"
|
|
3524
|
+
);
|
|
3525
|
+
}
|
|
3526
|
+
cached = null;
|
|
3527
|
+
return cached;
|
|
3528
|
+
}
|
|
3529
|
+
cached = mod;
|
|
3530
|
+
} catch {
|
|
3531
|
+
cached = null;
|
|
3532
|
+
}
|
|
3533
|
+
return cached;
|
|
3534
|
+
}
|
|
3535
|
+
function validateLockModule(mod) {
|
|
3536
|
+
if (mod === null || mod === void 0 || typeof mod !== "object") return false;
|
|
3537
|
+
const m = mod;
|
|
3538
|
+
return typeof m.lock === "function" && typeof m.unlock === "function";
|
|
3539
|
+
}
|
|
3540
|
+
async function withFileLock(path, fn, options) {
|
|
3541
|
+
const lib = await getProperLockfile();
|
|
3542
|
+
if (lib === null) {
|
|
3543
|
+
if (!warnedMissing) {
|
|
3544
|
+
warnedMissing = true;
|
|
3545
|
+
process.stderr.write(
|
|
3546
|
+
"[theokit-sdk] proper-lockfile not installed; cross-process file lock unavailable. Install with: pnpm add proper-lockfile\n"
|
|
3547
|
+
);
|
|
3548
|
+
}
|
|
3549
|
+
return withCwdMutex(`file-lock:${path}`, fn);
|
|
3550
|
+
}
|
|
3551
|
+
return withCwdMutex(`file-lock:${path}`, async () => {
|
|
3552
|
+
const release = await lib.lock(path, {
|
|
3553
|
+
// EC-1: companion lockfile, target path may not exist yet.
|
|
3554
|
+
lockfilePath: `${path}.lock`,
|
|
3555
|
+
realpath: false,
|
|
3556
|
+
stale: 3e4,
|
|
3557
|
+
retries: {
|
|
3558
|
+
retries: 5,
|
|
3559
|
+
factor: 1.5,
|
|
3560
|
+
minTimeout: 100,
|
|
3561
|
+
maxTimeout: 5e3
|
|
3562
|
+
}
|
|
3563
|
+
});
|
|
3564
|
+
try {
|
|
3565
|
+
return await fn();
|
|
3566
|
+
} finally {
|
|
3567
|
+
await release();
|
|
3568
|
+
}
|
|
3569
|
+
});
|
|
3570
|
+
}
|
|
3571
|
+
var cached, warnedMissing, warnedStructural;
|
|
3572
|
+
var init_file_lock = __esm({
|
|
3573
|
+
"src/internal/persistence/file-lock.ts"() {
|
|
3574
|
+
init_cwd_mutex();
|
|
3575
|
+
warnedMissing = false;
|
|
3576
|
+
warnedStructural = false;
|
|
3577
|
+
}
|
|
3578
|
+
});
|
|
3513
3579
|
function encodeProjectDir(cwd) {
|
|
3514
3580
|
return cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
3515
3581
|
}
|
|
@@ -3736,70 +3802,31 @@ var init_session_transcript = __esm({
|
|
|
3736
3802
|
};
|
|
3737
3803
|
}
|
|
3738
3804
|
});
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
if (mod === null || mod === void 0 || typeof mod !== "object") return false;
|
|
3763
|
-
const m = mod;
|
|
3764
|
-
return typeof m.lock === "function" && typeof m.unlock === "function";
|
|
3765
|
-
}
|
|
3766
|
-
async function withFileLock(path, fn, options) {
|
|
3767
|
-
const lib = await getProperLockfile();
|
|
3768
|
-
if (lib === null) {
|
|
3769
|
-
if (!warnedMissing) {
|
|
3770
|
-
warnedMissing = true;
|
|
3771
|
-
process.stderr.write(
|
|
3772
|
-
"[theokit-sdk] proper-lockfile not installed; cross-process file lock unavailable. Install with: pnpm add proper-lockfile\n"
|
|
3773
|
-
);
|
|
3774
|
-
}
|
|
3775
|
-
return withCwdMutex(`file-lock:${path}`, fn);
|
|
3776
|
-
}
|
|
3777
|
-
return withCwdMutex(`file-lock:${path}`, async () => {
|
|
3778
|
-
const release = await lib.lock(path, {
|
|
3779
|
-
// EC-1: companion lockfile, target path may not exist yet.
|
|
3780
|
-
lockfilePath: `${path}.lock`,
|
|
3781
|
-
realpath: false,
|
|
3782
|
-
stale: 3e4,
|
|
3783
|
-
retries: {
|
|
3784
|
-
retries: 5,
|
|
3785
|
-
factor: 1.5,
|
|
3786
|
-
minTimeout: 100,
|
|
3787
|
-
maxTimeout: 5e3
|
|
3805
|
+
var FsSessionStore;
|
|
3806
|
+
var init_fs_session_store = __esm({
|
|
3807
|
+
"src/internal/persistence/fs-session-store.ts"() {
|
|
3808
|
+
init_file_lock();
|
|
3809
|
+
init_session_transcript();
|
|
3810
|
+
FsSessionStore = class {
|
|
3811
|
+
#baseDir;
|
|
3812
|
+
#cwd;
|
|
3813
|
+
constructor(options) {
|
|
3814
|
+
this.#baseDir = options.baseDir;
|
|
3815
|
+
this.#cwd = options.cwd;
|
|
3816
|
+
}
|
|
3817
|
+
async readRecords(agentId) {
|
|
3818
|
+
return readTranscript(transcriptPath(this.#baseDir, this.#cwd, agentId));
|
|
3819
|
+
}
|
|
3820
|
+
async appendRecords(agentId, records) {
|
|
3821
|
+
if (records.length === 0) return;
|
|
3822
|
+
const path$1 = transcriptPath(this.#baseDir, this.#cwd, agentId);
|
|
3823
|
+
await promises.mkdir(path.dirname(path$1), { recursive: true });
|
|
3824
|
+
await withFileLock(path$1, async () => {
|
|
3825
|
+
const prior = await readTranscript(path$1);
|
|
3826
|
+
await writeTranscript(path$1, [...prior, ...records]);
|
|
3827
|
+
});
|
|
3788
3828
|
}
|
|
3789
|
-
}
|
|
3790
|
-
try {
|
|
3791
|
-
return await fn();
|
|
3792
|
-
} finally {
|
|
3793
|
-
await release();
|
|
3794
|
-
}
|
|
3795
|
-
});
|
|
3796
|
-
}
|
|
3797
|
-
var cached, warnedMissing, warnedStructural;
|
|
3798
|
-
var init_file_lock = __esm({
|
|
3799
|
-
"src/internal/persistence/file-lock.ts"() {
|
|
3800
|
-
init_cwd_mutex();
|
|
3801
|
-
warnedMissing = false;
|
|
3802
|
-
warnedStructural = false;
|
|
3829
|
+
};
|
|
3803
3830
|
}
|
|
3804
3831
|
});
|
|
3805
3832
|
function getTheokitHome(cwd) {
|
|
@@ -5131,6 +5158,8 @@ var init_memory_path_selector = __esm({
|
|
|
5131
5158
|
PORT_MEMORY_PATH_ENV_VAR = "THEOKIT_PORT_MEMORY_PATH";
|
|
5132
5159
|
}
|
|
5133
5160
|
});
|
|
5161
|
+
|
|
5162
|
+
// src/internal/runtime/session/agent-session-store.ts
|
|
5134
5163
|
function seedTranscript(prior, opts) {
|
|
5135
5164
|
return SessionTranscript.fromRecords(prior, opts);
|
|
5136
5165
|
}
|
|
@@ -5168,8 +5197,8 @@ function appendConversation(transcript, conversation) {
|
|
|
5168
5197
|
if (toolResults.length > 0) transcript.appendToolResults(toolResults);
|
|
5169
5198
|
}
|
|
5170
5199
|
}
|
|
5171
|
-
async function readSessionMessages(
|
|
5172
|
-
const records = await
|
|
5200
|
+
async function readSessionMessages(store, agentId) {
|
|
5201
|
+
const records = await store.readRecords(agentId);
|
|
5173
5202
|
return reconstructMessages(records).map(narrowToSessionMessage);
|
|
5174
5203
|
}
|
|
5175
5204
|
function partToText(p) {
|
|
@@ -5186,37 +5215,31 @@ function narrowToSessionMessage(m) {
|
|
|
5186
5215
|
const text = m.content.map(partToText).filter((s) => s.length > 0).join("\n");
|
|
5187
5216
|
return { role, text };
|
|
5188
5217
|
}
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
await promises.mkdir(path.dirname(path$1), { recursive: true });
|
|
5192
|
-
await withFileLock(path$1, async () => {
|
|
5193
|
-
const prior = await readTranscript(path$1);
|
|
5194
|
-
const transcript = seedTranscript(prior, { cwd: loc.cwd, sessionId, model: loc.model });
|
|
5195
|
-
transcript.appendUserTurn(turn.userText);
|
|
5196
|
-
appendConversation(transcript, turn.conversation);
|
|
5197
|
-
await writeTranscript(path$1, transcript.records());
|
|
5198
|
-
});
|
|
5218
|
+
function deltaRecords(transcript, priorLength) {
|
|
5219
|
+
return transcript.records().slice(priorLength);
|
|
5199
5220
|
}
|
|
5200
|
-
async function
|
|
5201
|
-
const
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5221
|
+
async function persistTurn(store, loc, sessionId, turn) {
|
|
5222
|
+
const prior = await store.readRecords(loc.agentId);
|
|
5223
|
+
const transcript = seedTranscript(prior, { cwd: loc.cwd, sessionId, model: loc.model });
|
|
5224
|
+
transcript.appendUserTurn(turn.userText);
|
|
5225
|
+
appendConversation(transcript, turn.conversation);
|
|
5226
|
+
await store.appendRecords(loc.agentId, deltaRecords(transcript, prior.length));
|
|
5227
|
+
}
|
|
5228
|
+
async function appendCompactBoundaryRecord(store, loc, sessionId, meta) {
|
|
5229
|
+
const prior = await store.readRecords(loc.agentId);
|
|
5230
|
+
const transcript = seedTranscript(prior, { cwd: loc.cwd, sessionId, model: loc.model });
|
|
5231
|
+
transcript.appendCompactBoundary(meta);
|
|
5232
|
+
await store.appendRecords(loc.agentId, deltaRecords(transcript, prior.length));
|
|
5209
5233
|
}
|
|
5210
5234
|
var init_agent_session_store = __esm({
|
|
5211
5235
|
"src/internal/runtime/session/agent-session-store.ts"() {
|
|
5212
|
-
init_file_lock();
|
|
5213
5236
|
init_session_transcript();
|
|
5214
5237
|
}
|
|
5215
5238
|
});
|
|
5216
5239
|
|
|
5217
5240
|
// src/internal/runtime/session/agent-session.ts
|
|
5218
|
-
function transcriptKey(
|
|
5219
|
-
return `${
|
|
5241
|
+
function transcriptKey(cwd, agentId) {
|
|
5242
|
+
return `${cwd}::${agentId}`;
|
|
5220
5243
|
}
|
|
5221
5244
|
function appendSessionMessage(agentId, message) {
|
|
5222
5245
|
const existing = sessions.get(agentId) ?? [];
|
|
@@ -5226,15 +5249,15 @@ function appendSessionMessage(agentId, message) {
|
|
|
5226
5249
|
function getSessionMessages(agentId) {
|
|
5227
5250
|
return sessions.get(agentId) ?? [];
|
|
5228
5251
|
}
|
|
5229
|
-
function persistTurnToTranscript(loc, sessionId, turn, onCompact) {
|
|
5230
|
-
const key = transcriptKey(loc.
|
|
5252
|
+
function persistTurnToTranscript(store, loc, sessionId, turn, onCompact) {
|
|
5253
|
+
const key = transcriptKey(loc.cwd, loc.agentId);
|
|
5231
5254
|
const chained = (pendingWrites.get(key) ?? Promise.resolve()).then(async () => {
|
|
5232
5255
|
try {
|
|
5233
|
-
await persistTurn(loc, sessionId, turn);
|
|
5256
|
+
await persistTurn(store, loc, sessionId, turn);
|
|
5234
5257
|
const count = (recordCounts.get(key) ?? 0) + 1;
|
|
5235
5258
|
recordCounts.set(key, count);
|
|
5236
5259
|
if (count % COMPACTION_CHECK_INTERVAL === 0) {
|
|
5237
|
-
await appendCompactBoundaryRecord(loc, sessionId, {
|
|
5260
|
+
await appendCompactBoundaryRecord(store, loc, sessionId, {
|
|
5238
5261
|
preTokens: 0,
|
|
5239
5262
|
trigger: "auto"
|
|
5240
5263
|
});
|
|
@@ -5257,10 +5280,10 @@ function persistTurnToTranscript(loc, sessionId, turn, onCompact) {
|
|
|
5257
5280
|
);
|
|
5258
5281
|
}
|
|
5259
5282
|
async function hydrateSession(agentId, loc) {
|
|
5260
|
-
const key = transcriptKey(loc.
|
|
5283
|
+
const key = transcriptKey(loc.cwd, agentId);
|
|
5261
5284
|
if (hydratedKeys.has(key)) return;
|
|
5262
5285
|
hydratedKeys.add(key);
|
|
5263
|
-
const persisted = await readSessionMessages(loc.
|
|
5286
|
+
const persisted = await readSessionMessages(loc.store, agentId);
|
|
5264
5287
|
if (persisted.length === 0) return;
|
|
5265
5288
|
if (!sessions.has(agentId) || sessions.get(agentId)?.length === 0) {
|
|
5266
5289
|
sessions.set(agentId, persisted);
|
|
@@ -5295,7 +5318,7 @@ async function runPostRunLifecycle(inputs) {
|
|
|
5295
5318
|
userText,
|
|
5296
5319
|
agentId,
|
|
5297
5320
|
workspaceCwd,
|
|
5298
|
-
|
|
5321
|
+
sessionStore,
|
|
5299
5322
|
model,
|
|
5300
5323
|
onRunEvent,
|
|
5301
5324
|
hooksExecutor,
|
|
@@ -5314,7 +5337,8 @@ async function runPostRunLifecycle(inputs) {
|
|
|
5314
5337
|
}
|
|
5315
5338
|
const conversation = await safeConversation(run);
|
|
5316
5339
|
persistTurnToTranscript(
|
|
5317
|
-
|
|
5340
|
+
sessionStore,
|
|
5341
|
+
{ cwd: workspaceCwd, agentId, model },
|
|
5318
5342
|
agentId,
|
|
5319
5343
|
{ userText, conversation },
|
|
5320
5344
|
onRunEvent !== void 0 ? () => emitRunEvent(onRunEvent, { type: "compact_boundary", trigger: "auto" }) : void 0
|
|
@@ -17921,6 +17945,7 @@ var init_local_agent = __esm({
|
|
|
17921
17945
|
init_errors();
|
|
17922
17946
|
init_ids();
|
|
17923
17947
|
init_cwd_mutex();
|
|
17948
|
+
init_fs_session_store();
|
|
17924
17949
|
init_session_transcript();
|
|
17925
17950
|
init_store();
|
|
17926
17951
|
init_manager();
|
|
@@ -17964,6 +17989,12 @@ var init_local_agent = __esm({
|
|
|
17964
17989
|
* `~/.theokit`; set `local.baseDir: "~/.claude"` for Claude Code CLI interop.
|
|
17965
17990
|
*/
|
|
17966
17991
|
transcriptBaseDir;
|
|
17992
|
+
/**
|
|
17993
|
+
* SE41 — the session record store. Defaults to the FS transcript store (byte-
|
|
17994
|
+
* identical to SE40); `local.sessionStore` injects an external store (Postgres /
|
|
17995
|
+
* Redis / KV) so resume works on serverless (ephemeral FS) and multi-host.
|
|
17996
|
+
*/
|
|
17997
|
+
sessionStore;
|
|
17967
17998
|
/**
|
|
17968
17999
|
* D319: lifecycle AbortController fired on `dispose()`. Composed with the
|
|
17969
18000
|
* caller's `SendOptions.signal` via `anySignal` so the LLM `fetch()`
|
|
@@ -18006,6 +18037,7 @@ var init_local_agent = __esm({
|
|
|
18006
18037
|
this.options = options;
|
|
18007
18038
|
this.workspaceCwd = resolveCwd(options.local?.cwd);
|
|
18008
18039
|
this.transcriptBaseDir = resolveBaseDir(options.local?.baseDir);
|
|
18040
|
+
this.sessionStore = options.local?.sessionStore ?? new FsSessionStore({ baseDir: this.transcriptBaseDir, cwd: this.workspaceCwd });
|
|
18009
18041
|
this.settingSourcesIncludeProject = includesSetting(options, "project");
|
|
18010
18042
|
this.settingSourcesIncludePlugins = includesSetting(options, "plugins");
|
|
18011
18043
|
const sub = bootstrapSubmanagers({
|
|
@@ -18053,7 +18085,7 @@ var init_local_agent = __esm({
|
|
|
18053
18085
|
this.settingSourcesIncludeProject,
|
|
18054
18086
|
this.options.agents
|
|
18055
18087
|
);
|
|
18056
|
-
await hydrateSession(this.agentId, {
|
|
18088
|
+
await hydrateSession(this.agentId, { store: this.sessionStore, cwd: this.workspaceCwd });
|
|
18057
18089
|
await this.personalityStore.hydrate(this.agentId);
|
|
18058
18090
|
}
|
|
18059
18091
|
/** T4.2 — expose PluginManager so agent-loop can fire pre_tool_call hooks. @internal */
|
|
@@ -18109,7 +18141,7 @@ var init_local_agent = __esm({
|
|
|
18109
18141
|
userText,
|
|
18110
18142
|
agentId: this.agentId,
|
|
18111
18143
|
workspaceCwd: this.workspaceCwd,
|
|
18112
|
-
|
|
18144
|
+
sessionStore: this.sessionStore,
|
|
18113
18145
|
model: this.model?.id ?? "unknown",
|
|
18114
18146
|
...options.onRunEvent !== void 0 ? { onRunEvent: options.onRunEvent } : {},
|
|
18115
18147
|
hooksExecutor: this.hooksExecutor,
|