@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
package/dist/a2a/index.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
|
|
@@ -17755,6 +17779,7 @@ var init_local_agent = __esm({
|
|
|
17755
17779
|
init_errors();
|
|
17756
17780
|
init_ids();
|
|
17757
17781
|
init_cwd_mutex();
|
|
17782
|
+
init_fs_session_store();
|
|
17758
17783
|
init_session_transcript();
|
|
17759
17784
|
init_store();
|
|
17760
17785
|
init_manager();
|
|
@@ -17798,6 +17823,12 @@ var init_local_agent = __esm({
|
|
|
17798
17823
|
* `~/.theokit`; set `local.baseDir: "~/.claude"` for Claude Code CLI interop.
|
|
17799
17824
|
*/
|
|
17800
17825
|
transcriptBaseDir;
|
|
17826
|
+
/**
|
|
17827
|
+
* SE41 — the session record store. Defaults to the FS transcript store (byte-
|
|
17828
|
+
* identical to SE40); `local.sessionStore` injects an external store (Postgres /
|
|
17829
|
+
* Redis / KV) so resume works on serverless (ephemeral FS) and multi-host.
|
|
17830
|
+
*/
|
|
17831
|
+
sessionStore;
|
|
17801
17832
|
/**
|
|
17802
17833
|
* D319: lifecycle AbortController fired on `dispose()`. Composed with the
|
|
17803
17834
|
* caller's `SendOptions.signal` via `anySignal` so the LLM `fetch()`
|
|
@@ -17840,6 +17871,7 @@ var init_local_agent = __esm({
|
|
|
17840
17871
|
this.options = options;
|
|
17841
17872
|
this.workspaceCwd = resolveCwd(options.local?.cwd);
|
|
17842
17873
|
this.transcriptBaseDir = resolveBaseDir(options.local?.baseDir);
|
|
17874
|
+
this.sessionStore = options.local?.sessionStore ?? new FsSessionStore({ baseDir: this.transcriptBaseDir, cwd: this.workspaceCwd });
|
|
17843
17875
|
this.settingSourcesIncludeProject = includesSetting(options, "project");
|
|
17844
17876
|
this.settingSourcesIncludePlugins = includesSetting(options, "plugins");
|
|
17845
17877
|
const sub = bootstrapSubmanagers({
|
|
@@ -17887,7 +17919,7 @@ var init_local_agent = __esm({
|
|
|
17887
17919
|
this.settingSourcesIncludeProject,
|
|
17888
17920
|
this.options.agents
|
|
17889
17921
|
);
|
|
17890
|
-
await hydrateSession(this.agentId, {
|
|
17922
|
+
await hydrateSession(this.agentId, { store: this.sessionStore, cwd: this.workspaceCwd });
|
|
17891
17923
|
await this.personalityStore.hydrate(this.agentId);
|
|
17892
17924
|
}
|
|
17893
17925
|
/** T4.2 — expose PluginManager so agent-loop can fire pre_tool_call hooks. @internal */
|
|
@@ -17943,7 +17975,7 @@ var init_local_agent = __esm({
|
|
|
17943
17975
|
userText,
|
|
17944
17976
|
agentId: this.agentId,
|
|
17945
17977
|
workspaceCwd: this.workspaceCwd,
|
|
17946
|
-
|
|
17978
|
+
sessionStore: this.sessionStore,
|
|
17947
17979
|
model: this.model?.id ?? "unknown",
|
|
17948
17980
|
...options.onRunEvent !== void 0 ? { onRunEvent: options.onRunEvent } : {},
|
|
17949
17981
|
hooksExecutor: this.hooksExecutor,
|