@theokit/sdk 4.0.1 → 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 +12 -0
- package/README.md +16 -1
- 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 +3 -3
package/dist/eval.js
CHANGED
|
@@ -3503,6 +3503,72 @@ var init_cloud_tool_parity = __esm({
|
|
|
3503
3503
|
init_errors();
|
|
3504
3504
|
}
|
|
3505
3505
|
});
|
|
3506
|
+
|
|
3507
|
+
// src/internal/persistence/file-lock.ts
|
|
3508
|
+
async function getProperLockfile() {
|
|
3509
|
+
if (cached !== void 0) return cached;
|
|
3510
|
+
try {
|
|
3511
|
+
const mod = await import('proper-lockfile');
|
|
3512
|
+
if (!validateLockModule(mod)) {
|
|
3513
|
+
if (!warnedStructural) {
|
|
3514
|
+
warnedStructural = true;
|
|
3515
|
+
process.stderr.write(
|
|
3516
|
+
"[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"
|
|
3517
|
+
);
|
|
3518
|
+
}
|
|
3519
|
+
cached = null;
|
|
3520
|
+
return cached;
|
|
3521
|
+
}
|
|
3522
|
+
cached = mod;
|
|
3523
|
+
} catch {
|
|
3524
|
+
cached = null;
|
|
3525
|
+
}
|
|
3526
|
+
return cached;
|
|
3527
|
+
}
|
|
3528
|
+
function validateLockModule(mod) {
|
|
3529
|
+
if (mod === null || mod === void 0 || typeof mod !== "object") return false;
|
|
3530
|
+
const m = mod;
|
|
3531
|
+
return typeof m.lock === "function" && typeof m.unlock === "function";
|
|
3532
|
+
}
|
|
3533
|
+
async function withFileLock(path, fn, options) {
|
|
3534
|
+
const lib = await getProperLockfile();
|
|
3535
|
+
if (lib === null) {
|
|
3536
|
+
if (!warnedMissing) {
|
|
3537
|
+
warnedMissing = true;
|
|
3538
|
+
process.stderr.write(
|
|
3539
|
+
"[theokit-sdk] proper-lockfile not installed; cross-process file lock unavailable. Install with: pnpm add proper-lockfile\n"
|
|
3540
|
+
);
|
|
3541
|
+
}
|
|
3542
|
+
return withCwdMutex(`file-lock:${path}`, fn);
|
|
3543
|
+
}
|
|
3544
|
+
return withCwdMutex(`file-lock:${path}`, async () => {
|
|
3545
|
+
const release = await lib.lock(path, {
|
|
3546
|
+
// EC-1: companion lockfile, target path may not exist yet.
|
|
3547
|
+
lockfilePath: `${path}.lock`,
|
|
3548
|
+
realpath: false,
|
|
3549
|
+
stale: 3e4,
|
|
3550
|
+
retries: {
|
|
3551
|
+
retries: 5,
|
|
3552
|
+
factor: 1.5,
|
|
3553
|
+
minTimeout: 100,
|
|
3554
|
+
maxTimeout: 5e3
|
|
3555
|
+
}
|
|
3556
|
+
});
|
|
3557
|
+
try {
|
|
3558
|
+
return await fn();
|
|
3559
|
+
} finally {
|
|
3560
|
+
await release();
|
|
3561
|
+
}
|
|
3562
|
+
});
|
|
3563
|
+
}
|
|
3564
|
+
var cached, warnedMissing, warnedStructural;
|
|
3565
|
+
var init_file_lock = __esm({
|
|
3566
|
+
"src/internal/persistence/file-lock.ts"() {
|
|
3567
|
+
init_cwd_mutex();
|
|
3568
|
+
warnedMissing = false;
|
|
3569
|
+
warnedStructural = false;
|
|
3570
|
+
}
|
|
3571
|
+
});
|
|
3506
3572
|
function encodeProjectDir(cwd) {
|
|
3507
3573
|
return cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
3508
3574
|
}
|
|
@@ -3729,70 +3795,31 @@ var init_session_transcript = __esm({
|
|
|
3729
3795
|
};
|
|
3730
3796
|
}
|
|
3731
3797
|
});
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
if (mod === null || mod === void 0 || typeof mod !== "object") return false;
|
|
3756
|
-
const m = mod;
|
|
3757
|
-
return typeof m.lock === "function" && typeof m.unlock === "function";
|
|
3758
|
-
}
|
|
3759
|
-
async function withFileLock(path, fn, options) {
|
|
3760
|
-
const lib = await getProperLockfile();
|
|
3761
|
-
if (lib === null) {
|
|
3762
|
-
if (!warnedMissing) {
|
|
3763
|
-
warnedMissing = true;
|
|
3764
|
-
process.stderr.write(
|
|
3765
|
-
"[theokit-sdk] proper-lockfile not installed; cross-process file lock unavailable. Install with: pnpm add proper-lockfile\n"
|
|
3766
|
-
);
|
|
3767
|
-
}
|
|
3768
|
-
return withCwdMutex(`file-lock:${path}`, fn);
|
|
3769
|
-
}
|
|
3770
|
-
return withCwdMutex(`file-lock:${path}`, async () => {
|
|
3771
|
-
const release = await lib.lock(path, {
|
|
3772
|
-
// EC-1: companion lockfile, target path may not exist yet.
|
|
3773
|
-
lockfilePath: `${path}.lock`,
|
|
3774
|
-
realpath: false,
|
|
3775
|
-
stale: 3e4,
|
|
3776
|
-
retries: {
|
|
3777
|
-
retries: 5,
|
|
3778
|
-
factor: 1.5,
|
|
3779
|
-
minTimeout: 100,
|
|
3780
|
-
maxTimeout: 5e3
|
|
3798
|
+
var FsSessionStore;
|
|
3799
|
+
var init_fs_session_store = __esm({
|
|
3800
|
+
"src/internal/persistence/fs-session-store.ts"() {
|
|
3801
|
+
init_file_lock();
|
|
3802
|
+
init_session_transcript();
|
|
3803
|
+
FsSessionStore = class {
|
|
3804
|
+
#baseDir;
|
|
3805
|
+
#cwd;
|
|
3806
|
+
constructor(options) {
|
|
3807
|
+
this.#baseDir = options.baseDir;
|
|
3808
|
+
this.#cwd = options.cwd;
|
|
3809
|
+
}
|
|
3810
|
+
async readRecords(agentId) {
|
|
3811
|
+
return readTranscript(transcriptPath(this.#baseDir, this.#cwd, agentId));
|
|
3812
|
+
}
|
|
3813
|
+
async appendRecords(agentId, records) {
|
|
3814
|
+
if (records.length === 0) return;
|
|
3815
|
+
const path = transcriptPath(this.#baseDir, this.#cwd, agentId);
|
|
3816
|
+
await mkdir(dirname(path), { recursive: true });
|
|
3817
|
+
await withFileLock(path, async () => {
|
|
3818
|
+
const prior = await readTranscript(path);
|
|
3819
|
+
await writeTranscript(path, [...prior, ...records]);
|
|
3820
|
+
});
|
|
3781
3821
|
}
|
|
3782
|
-
}
|
|
3783
|
-
try {
|
|
3784
|
-
return await fn();
|
|
3785
|
-
} finally {
|
|
3786
|
-
await release();
|
|
3787
|
-
}
|
|
3788
|
-
});
|
|
3789
|
-
}
|
|
3790
|
-
var cached, warnedMissing, warnedStructural;
|
|
3791
|
-
var init_file_lock = __esm({
|
|
3792
|
-
"src/internal/persistence/file-lock.ts"() {
|
|
3793
|
-
init_cwd_mutex();
|
|
3794
|
-
warnedMissing = false;
|
|
3795
|
-
warnedStructural = false;
|
|
3822
|
+
};
|
|
3796
3823
|
}
|
|
3797
3824
|
});
|
|
3798
3825
|
function getTheokitHome(cwd) {
|
|
@@ -5124,6 +5151,8 @@ var init_memory_path_selector = __esm({
|
|
|
5124
5151
|
PORT_MEMORY_PATH_ENV_VAR = "THEOKIT_PORT_MEMORY_PATH";
|
|
5125
5152
|
}
|
|
5126
5153
|
});
|
|
5154
|
+
|
|
5155
|
+
// src/internal/runtime/session/agent-session-store.ts
|
|
5127
5156
|
function seedTranscript(prior, opts) {
|
|
5128
5157
|
return SessionTranscript.fromRecords(prior, opts);
|
|
5129
5158
|
}
|
|
@@ -5161,8 +5190,8 @@ function appendConversation(transcript, conversation) {
|
|
|
5161
5190
|
if (toolResults.length > 0) transcript.appendToolResults(toolResults);
|
|
5162
5191
|
}
|
|
5163
5192
|
}
|
|
5164
|
-
async function readSessionMessages(
|
|
5165
|
-
const records = await
|
|
5193
|
+
async function readSessionMessages(store, agentId) {
|
|
5194
|
+
const records = await store.readRecords(agentId);
|
|
5166
5195
|
return reconstructMessages(records).map(narrowToSessionMessage);
|
|
5167
5196
|
}
|
|
5168
5197
|
function partToText(p) {
|
|
@@ -5179,37 +5208,31 @@ function narrowToSessionMessage(m) {
|
|
|
5179
5208
|
const text = m.content.map(partToText).filter((s) => s.length > 0).join("\n");
|
|
5180
5209
|
return { role, text };
|
|
5181
5210
|
}
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
await mkdir(dirname(path), { recursive: true });
|
|
5185
|
-
await withFileLock(path, async () => {
|
|
5186
|
-
const prior = await readTranscript(path);
|
|
5187
|
-
const transcript = seedTranscript(prior, { cwd: loc.cwd, sessionId, model: loc.model });
|
|
5188
|
-
transcript.appendUserTurn(turn.userText);
|
|
5189
|
-
appendConversation(transcript, turn.conversation);
|
|
5190
|
-
await writeTranscript(path, transcript.records());
|
|
5191
|
-
});
|
|
5211
|
+
function deltaRecords(transcript, priorLength) {
|
|
5212
|
+
return transcript.records().slice(priorLength);
|
|
5192
5213
|
}
|
|
5193
|
-
async function
|
|
5194
|
-
const
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5214
|
+
async function persistTurn(store, loc, sessionId, turn) {
|
|
5215
|
+
const prior = await store.readRecords(loc.agentId);
|
|
5216
|
+
const transcript = seedTranscript(prior, { cwd: loc.cwd, sessionId, model: loc.model });
|
|
5217
|
+
transcript.appendUserTurn(turn.userText);
|
|
5218
|
+
appendConversation(transcript, turn.conversation);
|
|
5219
|
+
await store.appendRecords(loc.agentId, deltaRecords(transcript, prior.length));
|
|
5220
|
+
}
|
|
5221
|
+
async function appendCompactBoundaryRecord(store, loc, sessionId, meta) {
|
|
5222
|
+
const prior = await store.readRecords(loc.agentId);
|
|
5223
|
+
const transcript = seedTranscript(prior, { cwd: loc.cwd, sessionId, model: loc.model });
|
|
5224
|
+
transcript.appendCompactBoundary(meta);
|
|
5225
|
+
await store.appendRecords(loc.agentId, deltaRecords(transcript, prior.length));
|
|
5202
5226
|
}
|
|
5203
5227
|
var init_agent_session_store = __esm({
|
|
5204
5228
|
"src/internal/runtime/session/agent-session-store.ts"() {
|
|
5205
|
-
init_file_lock();
|
|
5206
5229
|
init_session_transcript();
|
|
5207
5230
|
}
|
|
5208
5231
|
});
|
|
5209
5232
|
|
|
5210
5233
|
// src/internal/runtime/session/agent-session.ts
|
|
5211
|
-
function transcriptKey(
|
|
5212
|
-
return `${
|
|
5234
|
+
function transcriptKey(cwd, agentId) {
|
|
5235
|
+
return `${cwd}::${agentId}`;
|
|
5213
5236
|
}
|
|
5214
5237
|
function appendSessionMessage(agentId, message) {
|
|
5215
5238
|
const existing = sessions.get(agentId) ?? [];
|
|
@@ -5219,15 +5242,15 @@ function appendSessionMessage(agentId, message) {
|
|
|
5219
5242
|
function getSessionMessages(agentId) {
|
|
5220
5243
|
return sessions.get(agentId) ?? [];
|
|
5221
5244
|
}
|
|
5222
|
-
function persistTurnToTranscript(loc, sessionId, turn, onCompact) {
|
|
5223
|
-
const key = transcriptKey(loc.
|
|
5245
|
+
function persistTurnToTranscript(store, loc, sessionId, turn, onCompact) {
|
|
5246
|
+
const key = transcriptKey(loc.cwd, loc.agentId);
|
|
5224
5247
|
const chained = (pendingWrites.get(key) ?? Promise.resolve()).then(async () => {
|
|
5225
5248
|
try {
|
|
5226
|
-
await persistTurn(loc, sessionId, turn);
|
|
5249
|
+
await persistTurn(store, loc, sessionId, turn);
|
|
5227
5250
|
const count = (recordCounts.get(key) ?? 0) + 1;
|
|
5228
5251
|
recordCounts.set(key, count);
|
|
5229
5252
|
if (count % COMPACTION_CHECK_INTERVAL === 0) {
|
|
5230
|
-
await appendCompactBoundaryRecord(loc, sessionId, {
|
|
5253
|
+
await appendCompactBoundaryRecord(store, loc, sessionId, {
|
|
5231
5254
|
preTokens: 0,
|
|
5232
5255
|
trigger: "auto"
|
|
5233
5256
|
});
|
|
@@ -5250,10 +5273,10 @@ function persistTurnToTranscript(loc, sessionId, turn, onCompact) {
|
|
|
5250
5273
|
);
|
|
5251
5274
|
}
|
|
5252
5275
|
async function hydrateSession(agentId, loc) {
|
|
5253
|
-
const key = transcriptKey(loc.
|
|
5276
|
+
const key = transcriptKey(loc.cwd, agentId);
|
|
5254
5277
|
if (hydratedKeys.has(key)) return;
|
|
5255
5278
|
hydratedKeys.add(key);
|
|
5256
|
-
const persisted = await readSessionMessages(loc.
|
|
5279
|
+
const persisted = await readSessionMessages(loc.store, agentId);
|
|
5257
5280
|
if (persisted.length === 0) return;
|
|
5258
5281
|
if (!sessions.has(agentId) || sessions.get(agentId)?.length === 0) {
|
|
5259
5282
|
sessions.set(agentId, persisted);
|
|
@@ -5288,7 +5311,7 @@ async function runPostRunLifecycle(inputs) {
|
|
|
5288
5311
|
userText,
|
|
5289
5312
|
agentId,
|
|
5290
5313
|
workspaceCwd,
|
|
5291
|
-
|
|
5314
|
+
sessionStore,
|
|
5292
5315
|
model,
|
|
5293
5316
|
onRunEvent,
|
|
5294
5317
|
hooksExecutor,
|
|
@@ -5307,7 +5330,8 @@ async function runPostRunLifecycle(inputs) {
|
|
|
5307
5330
|
}
|
|
5308
5331
|
const conversation = await safeConversation(run);
|
|
5309
5332
|
persistTurnToTranscript(
|
|
5310
|
-
|
|
5333
|
+
sessionStore,
|
|
5334
|
+
{ cwd: workspaceCwd, agentId, model },
|
|
5311
5335
|
agentId,
|
|
5312
5336
|
{ userText, conversation },
|
|
5313
5337
|
onRunEvent !== void 0 ? () => emitRunEvent(onRunEvent, { type: "compact_boundary", trigger: "auto" }) : void 0
|
|
@@ -17914,6 +17938,7 @@ var init_local_agent = __esm({
|
|
|
17914
17938
|
init_errors();
|
|
17915
17939
|
init_ids();
|
|
17916
17940
|
init_cwd_mutex();
|
|
17941
|
+
init_fs_session_store();
|
|
17917
17942
|
init_session_transcript();
|
|
17918
17943
|
init_store();
|
|
17919
17944
|
init_manager();
|
|
@@ -17957,6 +17982,12 @@ var init_local_agent = __esm({
|
|
|
17957
17982
|
* `~/.theokit`; set `local.baseDir: "~/.claude"` for Claude Code CLI interop.
|
|
17958
17983
|
*/
|
|
17959
17984
|
transcriptBaseDir;
|
|
17985
|
+
/**
|
|
17986
|
+
* SE41 — the session record store. Defaults to the FS transcript store (byte-
|
|
17987
|
+
* identical to SE40); `local.sessionStore` injects an external store (Postgres /
|
|
17988
|
+
* Redis / KV) so resume works on serverless (ephemeral FS) and multi-host.
|
|
17989
|
+
*/
|
|
17990
|
+
sessionStore;
|
|
17960
17991
|
/**
|
|
17961
17992
|
* D319: lifecycle AbortController fired on `dispose()`. Composed with the
|
|
17962
17993
|
* caller's `SendOptions.signal` via `anySignal` so the LLM `fetch()`
|
|
@@ -17999,6 +18030,7 @@ var init_local_agent = __esm({
|
|
|
17999
18030
|
this.options = options;
|
|
18000
18031
|
this.workspaceCwd = resolveCwd(options.local?.cwd);
|
|
18001
18032
|
this.transcriptBaseDir = resolveBaseDir(options.local?.baseDir);
|
|
18033
|
+
this.sessionStore = options.local?.sessionStore ?? new FsSessionStore({ baseDir: this.transcriptBaseDir, cwd: this.workspaceCwd });
|
|
18002
18034
|
this.settingSourcesIncludeProject = includesSetting(options, "project");
|
|
18003
18035
|
this.settingSourcesIncludePlugins = includesSetting(options, "plugins");
|
|
18004
18036
|
const sub = bootstrapSubmanagers({
|
|
@@ -18046,7 +18078,7 @@ var init_local_agent = __esm({
|
|
|
18046
18078
|
this.settingSourcesIncludeProject,
|
|
18047
18079
|
this.options.agents
|
|
18048
18080
|
);
|
|
18049
|
-
await hydrateSession(this.agentId, {
|
|
18081
|
+
await hydrateSession(this.agentId, { store: this.sessionStore, cwd: this.workspaceCwd });
|
|
18050
18082
|
await this.personalityStore.hydrate(this.agentId);
|
|
18051
18083
|
}
|
|
18052
18084
|
/** T4.2 — expose PluginManager so agent-loop can fire pre_tool_call hooks. @internal */
|
|
@@ -18102,7 +18134,7 @@ var init_local_agent = __esm({
|
|
|
18102
18134
|
userText,
|
|
18103
18135
|
agentId: this.agentId,
|
|
18104
18136
|
workspaceCwd: this.workspaceCwd,
|
|
18105
|
-
|
|
18137
|
+
sessionStore: this.sessionStore,
|
|
18106
18138
|
model: this.model?.id ?? "unknown",
|
|
18107
18139
|
...options.onRunEvent !== void 0 ? { onRunEvent: options.onRunEvent } : {},
|
|
18108
18140
|
hooksExecutor: this.hooksExecutor,
|