@theokit/sdk 4.30.0 → 4.31.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 +43 -0
- package/dist/{agent-LD76RI74.cjs → agent-6GQBOHHA.cjs} +8 -8
- package/dist/{agent-LD76RI74.cjs.map → agent-6GQBOHHA.cjs.map} +1 -1
- package/dist/{agent-7YUGJJTU.js → agent-DY5LGZ5E.js} +7 -7
- package/dist/{agent-7YUGJJTU.js.map → agent-DY5LGZ5E.js.map} +1 -1
- package/dist/agent.d.ts +15 -2
- package/dist/{chunk-5YCAR23S.js → chunk-4JWZRASX.js} +3 -3
- package/dist/{chunk-5YCAR23S.js.map → chunk-4JWZRASX.js.map} +1 -1
- package/dist/{chunk-GWMQ5CS3.cjs → chunk-CYTAM3E6.cjs} +70 -40
- package/dist/chunk-CYTAM3E6.cjs.map +1 -0
- package/dist/{chunk-NG6B2PMA.cjs → chunk-FDGRQQWX.cjs} +5 -5
- package/dist/{chunk-NG6B2PMA.cjs.map → chunk-FDGRQQWX.cjs.map} +1 -1
- package/dist/{chunk-ISZ3MBUD.js → chunk-FZ75EZR5.js} +41 -11
- package/dist/chunk-FZ75EZR5.js.map +1 -0
- package/dist/chunk-ICSCKB3N.js +140 -0
- package/dist/chunk-ICSCKB3N.js.map +1 -0
- package/dist/{chunk-U6QGZHPN.js → chunk-PORDVVJS.js} +5 -6
- package/dist/chunk-PORDVVJS.js.map +1 -0
- package/dist/{chunk-NRSH7RJY.js → chunk-TLG444A6.js} +61 -13
- package/dist/chunk-TLG444A6.js.map +1 -0
- package/dist/{chunk-2HRYBRD7.cjs → chunk-U447MTG4.cjs} +5 -6
- package/dist/chunk-U447MTG4.cjs.map +1 -0
- package/dist/{chunk-2MF3IE2D.cjs → chunk-UKNMWCPZ.cjs} +63 -15
- package/dist/chunk-UKNMWCPZ.cjs.map +1 -0
- package/dist/{chunk-SQLZ7ONU.js → chunk-VUXLNVX7.js} +3 -3
- package/dist/{chunk-SQLZ7ONU.js.map → chunk-VUXLNVX7.js.map} +1 -1
- package/dist/{chunk-HK7ZHSAX.cjs → chunk-WQEQCJTZ.cjs} +64 -3
- package/dist/chunk-WQEQCJTZ.cjs.map +1 -0
- package/dist/{chunk-YU6KON2I.cjs → chunk-XJT5VACT.cjs} +3 -3
- package/dist/{chunk-YU6KON2I.cjs.map → chunk-XJT5VACT.cjs.map} +1 -1
- package/dist/{compact-session-OO7NVWPB.cjs → compact-session-2BFNMENR.cjs} +11 -11
- package/dist/{compact-session-OO7NVWPB.cjs.map → compact-session-2BFNMENR.cjs.map} +1 -1
- package/dist/{compact-session-OO2GD76G.js → compact-session-2JONXHLR.js} +3 -3
- package/dist/{compact-session-OO2GD76G.js.map → compact-session-2JONXHLR.js.map} +1 -1
- package/dist/cron.cjs +7 -7
- package/dist/cron.js +6 -6
- package/dist/eval.cjs +10 -11
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +6 -7
- package/dist/eval.js.map +1 -1
- package/dist/fs-session-store-26WVVMC4.cjs +17 -0
- package/dist/{fs-session-store-KAUQYSGI.cjs.map → fs-session-store-26WVVMC4.cjs.map} +1 -1
- package/dist/fs-session-store-7AEI4STY.js +8 -0
- package/dist/{fs-session-store-ZKB5NN37.js.map → fs-session-store-7AEI4STY.js.map} +1 -1
- package/dist/index.cjs +28 -28
- package/dist/index.d.cts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +8 -8
- package/dist/{inject-session-6MJUSGZP.cjs → inject-session-MIFEKATN.cjs} +4 -4
- package/dist/{inject-session-6MJUSGZP.cjs.map → inject-session-MIFEKATN.cjs.map} +1 -1
- package/dist/{inject-session-KOFHS5K3.js → inject-session-NNSCCIVP.js} +3 -3
- package/dist/{inject-session-KOFHS5K3.js.map → inject-session-NNSCCIVP.js.map} +1 -1
- package/dist/internal/llm/retrying-client.d.ts +29 -0
- package/dist/internal/persistence/index.cjs +18 -19
- package/dist/internal/persistence/index.cjs.map +1 -1
- package/dist/internal/persistence/index.js +1 -2
- package/dist/internal/persistence/index.js.map +1 -1
- package/dist/persistence.cjs +10 -11
- package/dist/persistence.cjs.map +1 -1
- package/dist/persistence.js +1 -2
- package/dist/persistence.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-2HRYBRD7.cjs.map +0 -1
- package/dist/chunk-2MF3IE2D.cjs.map +0 -1
- package/dist/chunk-C7PICHRF.cjs +0 -68
- package/dist/chunk-C7PICHRF.cjs.map +0 -1
- package/dist/chunk-GWMQ5CS3.cjs.map +0 -1
- package/dist/chunk-HK7ZHSAX.cjs.map +0 -1
- package/dist/chunk-HZQEDNF6.js +0 -66
- package/dist/chunk-HZQEDNF6.js.map +0 -1
- package/dist/chunk-ISZ3MBUD.js.map +0 -1
- package/dist/chunk-NRSH7RJY.js.map +0 -1
- package/dist/chunk-R6ZP6KNB.js +0 -80
- package/dist/chunk-R6ZP6KNB.js.map +0 -1
- package/dist/chunk-U6QGZHPN.js.map +0 -1
- package/dist/fs-session-store-KAUQYSGI.cjs +0 -17
- package/dist/fs-session-store-ZKB5NN37.js +0 -8
package/dist/index.cjs
CHANGED
|
@@ -8,14 +8,14 @@ require('./chunk-EPYZOCOL.cjs');
|
|
|
8
8
|
var chunkZ2OC3UIW_cjs = require('./chunk-Z2OC3UIW.cjs');
|
|
9
9
|
require('./chunk-BWT67BI4.cjs');
|
|
10
10
|
require('./chunk-PNVDQL5Y.cjs');
|
|
11
|
-
var
|
|
12
|
-
var
|
|
11
|
+
var chunkFDGRQQWX_cjs = require('./chunk-FDGRQQWX.cjs');
|
|
12
|
+
var chunkCYTAM3E6_cjs = require('./chunk-CYTAM3E6.cjs');
|
|
13
13
|
require('./chunk-BV2MWEMV.cjs');
|
|
14
14
|
var chunkMZ5ZRORA_cjs = require('./chunk-MZ5ZRORA.cjs');
|
|
15
|
-
require('./chunk-
|
|
15
|
+
require('./chunk-XJT5VACT.cjs');
|
|
16
16
|
require('./chunk-BUUUWQMB.cjs');
|
|
17
|
-
require('./chunk-
|
|
18
|
-
var
|
|
17
|
+
require('./chunk-U447MTG4.cjs');
|
|
18
|
+
var chunkUKNMWCPZ_cjs = require('./chunk-UKNMWCPZ.cjs');
|
|
19
19
|
require('./chunk-LUSXDZPV.cjs');
|
|
20
20
|
require('./chunk-IT3PWBW4.cjs');
|
|
21
21
|
var chunkJLMXKTBX_cjs = require('./chunk-JLMXKTBX.cjs');
|
|
@@ -30,7 +30,7 @@ require('./chunk-YPEPCZHF.cjs');
|
|
|
30
30
|
require('./chunk-VJ26EKGJ.cjs');
|
|
31
31
|
require('./chunk-GIW4L6HY.cjs');
|
|
32
32
|
require('./chunk-7S7KKUO6.cjs');
|
|
33
|
-
require('./chunk-
|
|
33
|
+
require('./chunk-WQEQCJTZ.cjs');
|
|
34
34
|
require('./chunk-JD74LN7R.cjs');
|
|
35
35
|
var chunkYLQQX5W2_cjs = require('./chunk-YLQQX5W2.cjs');
|
|
36
36
|
require('./chunk-4SXHEZIV.cjs');
|
|
@@ -57,8 +57,8 @@ var fs = require('fs');
|
|
|
57
57
|
// src/agent-factory.ts
|
|
58
58
|
function createAgentFactory(common) {
|
|
59
59
|
return {
|
|
60
|
-
forSession: (agentId, overrides) =>
|
|
61
|
-
getOrCreate: (agentId, overrides) =>
|
|
60
|
+
forSession: (agentId, overrides) => chunkCYTAM3E6_cjs.Agent.create(mergeAgentOptions(common, overrides, agentId)),
|
|
61
|
+
getOrCreate: (agentId, overrides) => chunkCYTAM3E6_cjs.Agent.getOrCreate(agentId, mergeAgentOptions(common, overrides, agentId))
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
64
|
function mergeAgentOptions(common, overrides, agentId) {
|
|
@@ -1145,7 +1145,7 @@ var Memory = {
|
|
|
1145
1145
|
return await peer.IndexManager.open(openArgs);
|
|
1146
1146
|
}
|
|
1147
1147
|
const { IndexManager } = await import('./index-manager-H7HUMW52.cjs');
|
|
1148
|
-
openArgs.embedding = await resolveEmbedding(opts.embedding,
|
|
1148
|
+
openArgs.embedding = await resolveEmbedding(opts.embedding, chunkCYTAM3E6_cjs.MEMORY_EMBEDDING_ADAPTERS);
|
|
1149
1149
|
return await IndexManager.open(openArgs);
|
|
1150
1150
|
},
|
|
1151
1151
|
/**
|
|
@@ -1156,7 +1156,7 @@ var Memory = {
|
|
|
1156
1156
|
*/
|
|
1157
1157
|
async runDreamingSweep(opts) {
|
|
1158
1158
|
const peer = await tryLoadSdkMemoryPeer();
|
|
1159
|
-
const catalog = peer !== null ? peer.MEMORY_EMBEDDING_ADAPTERS :
|
|
1159
|
+
const catalog = peer !== null ? peer.MEMORY_EMBEDDING_ADAPTERS : chunkCYTAM3E6_cjs.MEMORY_EMBEDDING_ADAPTERS;
|
|
1160
1160
|
const sweepArgs = await buildDreamingSweepArgs(opts, catalog);
|
|
1161
1161
|
const result = peer !== null ? (
|
|
1162
1162
|
// biome-ignore lint/suspicious/noExplicitAny: peer is dynamically loaded — structural compat ensured by sdk-memory
|
|
@@ -1578,7 +1578,7 @@ function ehAgenteConstruido(m) {
|
|
|
1578
1578
|
return typeof m.send === "function";
|
|
1579
1579
|
}
|
|
1580
1580
|
async function materializar(def, indice) {
|
|
1581
|
-
const { Agent: Agent2 } = await import('./agent-
|
|
1581
|
+
const { Agent: Agent2 } = await import('./agent-6GQBOHHA.cjs');
|
|
1582
1582
|
return Agent2.create({
|
|
1583
1583
|
// `AgentDefinition.model` admite o sentinel `'inherit'`, que não é um id de modelo. Herdar
|
|
1584
1584
|
// aqui significa "não declare nada e deixe o default valer" — passar o literal adiante criaria
|
|
@@ -1720,7 +1720,7 @@ var FIXTURE_USER = {
|
|
|
1720
1720
|
};
|
|
1721
1721
|
var FIXTURE_MODELS = [
|
|
1722
1722
|
{
|
|
1723
|
-
id:
|
|
1723
|
+
id: chunkCYTAM3E6_cjs.DEFAULT_AGENTIC_MODEL_ID,
|
|
1724
1724
|
name: "Gemini 2.0 Flash",
|
|
1725
1725
|
displayName: "Gemini 2.0 Flash",
|
|
1726
1726
|
parameters: [
|
|
@@ -1796,7 +1796,7 @@ async function listLocalModelsViaOpenAiCompat(baseUrl) {
|
|
|
1796
1796
|
try {
|
|
1797
1797
|
response = await fetch(url, { method: "GET" });
|
|
1798
1798
|
} catch (fetchErr) {
|
|
1799
|
-
const mapped =
|
|
1799
|
+
const mapped = chunkUKNMWCPZ_cjs.mapOllamaTransportError({
|
|
1800
1800
|
providerId: "ollama",
|
|
1801
1801
|
cause: fetchErr,
|
|
1802
1802
|
endpoint: "/v1/models"
|
|
@@ -1814,7 +1814,7 @@ async function listLocalModelsViaOpenAiCompat(baseUrl) {
|
|
|
1814
1814
|
body = JSON.parse(text);
|
|
1815
1815
|
} catch {
|
|
1816
1816
|
}
|
|
1817
|
-
const mapped =
|
|
1817
|
+
const mapped = chunkUKNMWCPZ_cjs.mapOllamaHttpError({
|
|
1818
1818
|
providerId: "ollama",
|
|
1819
1819
|
status: response.status,
|
|
1820
1820
|
body,
|
|
@@ -1928,7 +1928,7 @@ var Theokit = class {
|
|
|
1928
1928
|
envVars: p.envVars
|
|
1929
1929
|
}));
|
|
1930
1930
|
},
|
|
1931
|
-
embeddingAdapters: () => Object.entries(
|
|
1931
|
+
embeddingAdapters: () => Object.entries(chunkCYTAM3E6_cjs.MEMORY_EMBEDDING_ADAPTERS).map(([id, adapter]) => ({
|
|
1932
1932
|
id,
|
|
1933
1933
|
transport: adapter.transport,
|
|
1934
1934
|
defaultModel: adapter.defaultModel
|
|
@@ -1946,7 +1946,7 @@ var Theokit = class {
|
|
|
1946
1946
|
};
|
|
1947
1947
|
async function maybeListLocalModels(providerName) {
|
|
1948
1948
|
chunkD42XHI4O_cjs.registerBuiltins();
|
|
1949
|
-
await
|
|
1949
|
+
await chunkUKNMWCPZ_cjs.discoverProviderPlugins();
|
|
1950
1950
|
const profile = chunkD42XHI4O_cjs.getProviderProfile(providerName);
|
|
1951
1951
|
if (profile === void 0) return void 0;
|
|
1952
1952
|
if (profile.authType !== "none") return void 0;
|
|
@@ -1960,17 +1960,17 @@ function resolveLocalProviderBaseUrl(providerName, fallback) {
|
|
|
1960
1960
|
return fallback;
|
|
1961
1961
|
}
|
|
1962
1962
|
async function executeCatalogRequest(request) {
|
|
1963
|
-
const apiKey =
|
|
1963
|
+
const apiKey = chunkCYTAM3E6_cjs.resolveApiKey(request.apiKey);
|
|
1964
1964
|
if (apiKey === void 0) {
|
|
1965
1965
|
throw new chunkA44COQJJ_cjs.AuthenticationError("Missing API key", { code: "missing_api_key" });
|
|
1966
1966
|
}
|
|
1967
|
-
if (
|
|
1967
|
+
if (chunkCYTAM3E6_cjs.shouldUseFixtureMode(apiKey)) {
|
|
1968
1968
|
return request.fixture;
|
|
1969
1969
|
}
|
|
1970
|
-
if (!
|
|
1970
|
+
if (!chunkCYTAM3E6_cjs.isFixtureApiKey(apiKey) && process.env.THEOKIT_API_BASE_URL === void 0) {
|
|
1971
1971
|
throw new chunkA44COQJJ_cjs.AuthenticationError("Invalid API key", { code: "authentication_error" });
|
|
1972
1972
|
}
|
|
1973
|
-
return
|
|
1973
|
+
return chunkCYTAM3E6_cjs.httpRequest(request.path, { apiKey });
|
|
1974
1974
|
}
|
|
1975
1975
|
|
|
1976
1976
|
// src/trajectory-helpers.ts
|
|
@@ -2086,35 +2086,35 @@ Object.defineProperty(exports, "GenerateObjectError", {
|
|
|
2086
2086
|
});
|
|
2087
2087
|
Object.defineProperty(exports, "Cron", {
|
|
2088
2088
|
enumerable: true,
|
|
2089
|
-
get: function () { return
|
|
2089
|
+
get: function () { return chunkFDGRQQWX_cjs.Cron; }
|
|
2090
2090
|
});
|
|
2091
2091
|
Object.defineProperty(exports, "Agent", {
|
|
2092
2092
|
enumerable: true,
|
|
2093
|
-
get: function () { return
|
|
2093
|
+
get: function () { return chunkCYTAM3E6_cjs.Agent; }
|
|
2094
2094
|
});
|
|
2095
2095
|
Object.defineProperty(exports, "AgentBuilder", {
|
|
2096
2096
|
enumerable: true,
|
|
2097
|
-
get: function () { return
|
|
2097
|
+
get: function () { return chunkCYTAM3E6_cjs.AgentBuilder; }
|
|
2098
2098
|
});
|
|
2099
2099
|
Object.defineProperty(exports, "Tool", {
|
|
2100
2100
|
enumerable: true,
|
|
2101
|
-
get: function () { return
|
|
2101
|
+
get: function () { return chunkCYTAM3E6_cjs.Tool; }
|
|
2102
2102
|
});
|
|
2103
2103
|
Object.defineProperty(exports, "ToolError", {
|
|
2104
2104
|
enumerable: true,
|
|
2105
|
-
get: function () { return
|
|
2105
|
+
get: function () { return chunkCYTAM3E6_cjs.ToolError; }
|
|
2106
2106
|
});
|
|
2107
2107
|
Object.defineProperty(exports, "UsageAccumulator", {
|
|
2108
2108
|
enumerable: true,
|
|
2109
|
-
get: function () { return
|
|
2109
|
+
get: function () { return chunkCYTAM3E6_cjs.UsageAccumulator; }
|
|
2110
2110
|
});
|
|
2111
2111
|
Object.defineProperty(exports, "computeCost", {
|
|
2112
2112
|
enumerable: true,
|
|
2113
|
-
get: function () { return
|
|
2113
|
+
get: function () { return chunkCYTAM3E6_cjs.computeCost; }
|
|
2114
2114
|
});
|
|
2115
2115
|
Object.defineProperty(exports, "getPricingEntry", {
|
|
2116
2116
|
enumerable: true,
|
|
2117
|
-
get: function () { return
|
|
2117
|
+
get: function () { return chunkCYTAM3E6_cjs.getPricingEntry; }
|
|
2118
2118
|
});
|
|
2119
2119
|
Object.defineProperty(exports, "emitRunEvent", {
|
|
2120
2120
|
enumerable: true,
|
package/dist/index.d.cts
CHANGED
|
@@ -590,8 +590,21 @@ declare class Agent {
|
|
|
590
590
|
* Caveats:
|
|
591
591
|
* - The function-level `agentId` always wins over `options.agentId`.
|
|
592
592
|
* - Options differ between calls? Last-call-wins for this handle (matches `Agent.resume`).
|
|
593
|
-
* -
|
|
594
|
-
*
|
|
593
|
+
* - A DISPOSED agent is replaced automatically. `dispose()` evicts the id from the
|
|
594
|
+
* live cache (`liveAgentRegistry.forget`), so the next `getOrCreate(id)` builds a
|
|
595
|
+
* fresh handle — no `Agent.delete(agentId)` needed.
|
|
596
|
+
*
|
|
597
|
+
* This bullet used to say the opposite ("Disposed agents are NOT auto-deleted...
|
|
598
|
+
* call `Agent.delete(agentId)` first"). It was measured false in M91:
|
|
599
|
+
* `tests/m91-getorcreate-apos-dispose.test.ts` builds an agent, disposes it, and
|
|
600
|
+
* gets a different instance back. The claim was about the PERSISTENT registry and
|
|
601
|
+
* read as being about the live cache — and consumers built around the wrong half.
|
|
602
|
+
* The agent-builder's M85 interrupt rotates the session id to work around a
|
|
603
|
+
* constraint that does not exist.
|
|
604
|
+
*
|
|
605
|
+
* - `close()` marks the handle disposed WITHOUT evicting the cache entry. It is
|
|
606
|
+
* internal and unused today; if it becomes reachable, this bullet stops being true
|
|
607
|
+
* for that path.
|
|
595
608
|
*
|
|
596
609
|
* @public
|
|
597
610
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -590,8 +590,21 @@ declare class Agent {
|
|
|
590
590
|
* Caveats:
|
|
591
591
|
* - The function-level `agentId` always wins over `options.agentId`.
|
|
592
592
|
* - Options differ between calls? Last-call-wins for this handle (matches `Agent.resume`).
|
|
593
|
-
* -
|
|
594
|
-
*
|
|
593
|
+
* - A DISPOSED agent is replaced automatically. `dispose()` evicts the id from the
|
|
594
|
+
* live cache (`liveAgentRegistry.forget`), so the next `getOrCreate(id)` builds a
|
|
595
|
+
* fresh handle — no `Agent.delete(agentId)` needed.
|
|
596
|
+
*
|
|
597
|
+
* This bullet used to say the opposite ("Disposed agents are NOT auto-deleted...
|
|
598
|
+
* call `Agent.delete(agentId)` first"). It was measured false in M91:
|
|
599
|
+
* `tests/m91-getorcreate-apos-dispose.test.ts` builds an agent, disposes it, and
|
|
600
|
+
* gets a different instance back. The claim was about the PERSISTENT registry and
|
|
601
|
+
* read as being about the live cache — and consumers built around the wrong half.
|
|
602
|
+
* The agent-builder's M85 interrupt rotates the session id to work around a
|
|
603
|
+
* constraint that does not exist.
|
|
604
|
+
*
|
|
605
|
+
* - `close()` marks the handle disposed WITHOUT evicting the cache entry. It is
|
|
606
|
+
* internal and unused today; if it becomes reachable, this bullet stops being true
|
|
607
|
+
* for that path.
|
|
595
608
|
*
|
|
596
609
|
* @public
|
|
597
610
|
*/
|
package/dist/index.js
CHANGED
|
@@ -6,16 +6,16 @@ import './chunk-GJAGKFTR.js';
|
|
|
6
6
|
import { Workflow, agentStep } from './chunk-BFWPZMG7.js';
|
|
7
7
|
import './chunk-UVNG67DG.js';
|
|
8
8
|
import './chunk-CAH3G4IS.js';
|
|
9
|
-
export { Cron } from './chunk-
|
|
10
|
-
import { MEMORY_EMBEDDING_ADAPTERS, resolveApiKey, shouldUseFixtureMode, isFixtureApiKey, httpRequest, DEFAULT_AGENTIC_MODEL_ID, Agent } from './chunk-
|
|
11
|
-
export { Agent, AgentBuilder, Tool, ToolError, UsageAccumulator, computeCost, getPricingEntry } from './chunk-
|
|
9
|
+
export { Cron } from './chunk-4JWZRASX.js';
|
|
10
|
+
import { MEMORY_EMBEDDING_ADAPTERS, resolveApiKey, shouldUseFixtureMode, isFixtureApiKey, httpRequest, DEFAULT_AGENTIC_MODEL_ID, Agent } from './chunk-FZ75EZR5.js';
|
|
11
|
+
export { Agent, AgentBuilder, Tool, ToolError, UsageAccumulator, computeCost, getPricingEntry } from './chunk-FZ75EZR5.js';
|
|
12
12
|
import './chunk-2SFBB54R.js';
|
|
13
13
|
import { configure, submit, list, get, cancel, subscribe } from './chunk-HRA3CPGG.js';
|
|
14
14
|
export { emitRunEvent } from './chunk-HRA3CPGG.js';
|
|
15
|
-
import './chunk-
|
|
15
|
+
import './chunk-VUXLNVX7.js';
|
|
16
16
|
import './chunk-K2BQQ445.js';
|
|
17
|
-
import './chunk-
|
|
18
|
-
import { discoverProviderPlugins, mapOllamaTransportError, mapOllamaHttpError } from './chunk-
|
|
17
|
+
import './chunk-PORDVVJS.js';
|
|
18
|
+
import { discoverProviderPlugins, mapOllamaTransportError, mapOllamaHttpError } from './chunk-TLG444A6.js';
|
|
19
19
|
import './chunk-6CLRANZA.js';
|
|
20
20
|
import './chunk-EEZ7CFMM.js';
|
|
21
21
|
import { lanceStoragePath, LanceIndex, readFactsFromMarkdown, defaultIndexPath, openMemoryDb, memoryDir } from './chunk-XAUBQMQU.js';
|
|
@@ -30,7 +30,7 @@ import './chunk-UJ7IQJAG.js';
|
|
|
30
30
|
import './chunk-7AD3ZTZL.js';
|
|
31
31
|
import './chunk-V4XRLPEF.js';
|
|
32
32
|
import './chunk-5PZMMF4H.js';
|
|
33
|
-
import './chunk-
|
|
33
|
+
import './chunk-ICSCKB3N.js';
|
|
34
34
|
import './chunk-77FOZCOT.js';
|
|
35
35
|
import { withCwdMutex } from './chunk-2XLKLVVR.js';
|
|
36
36
|
export { withCwdMutex } from './chunk-2XLKLVVR.js';
|
|
@@ -1580,7 +1580,7 @@ function ehAgenteConstruido(m) {
|
|
|
1580
1580
|
return typeof m.send === "function";
|
|
1581
1581
|
}
|
|
1582
1582
|
async function materializar(def, indice) {
|
|
1583
|
-
const { Agent: Agent2 } = await import('./agent-
|
|
1583
|
+
const { Agent: Agent2 } = await import('./agent-DY5LGZ5E.js');
|
|
1584
1584
|
return Agent2.create({
|
|
1585
1585
|
// `AgentDefinition.model` admite o sentinel `'inherit'`, que não é um id de modelo. Herdar
|
|
1586
1586
|
// aqui significa "não declare nada e deixe o default valer" — passar o literal adiante criaria
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkXJT5VACT_cjs = require('./chunk-XJT5VACT.cjs');
|
|
4
4
|
var chunkIT3PWBW4_cjs = require('./chunk-IT3PWBW4.cjs');
|
|
5
5
|
var chunk4SXHEZIV_cjs = require('./chunk-4SXHEZIV.cjs');
|
|
6
6
|
require('./chunk-TIZ4TS5V.cjs');
|
|
@@ -8,7 +8,7 @@ require('./chunk-BEURCLDV.cjs');
|
|
|
8
8
|
|
|
9
9
|
// src/internal/session/inject-session.ts
|
|
10
10
|
async function injectSessionTurn(opts) {
|
|
11
|
-
await
|
|
11
|
+
await chunkXJT5VACT_cjs.enqueueSessionWrite(opts.loc.cwd, opts.loc.agentId, async () => {
|
|
12
12
|
const prior = await opts.store.readRecords(opts.loc.agentId);
|
|
13
13
|
const transcript = chunk4SXHEZIV_cjs.SessionTranscript.fromRecords(prior, {
|
|
14
14
|
cwd: opts.loc.cwd,
|
|
@@ -23,5 +23,5 @@ async function injectSessionTurn(opts) {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
exports.injectSessionTurn = injectSessionTurn;
|
|
26
|
-
//# sourceMappingURL=inject-session-
|
|
27
|
-
//# sourceMappingURL=inject-session-
|
|
26
|
+
//# sourceMappingURL=inject-session-MIFEKATN.cjs.map
|
|
27
|
+
//# sourceMappingURL=inject-session-MIFEKATN.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/session/inject-session.ts"],"names":["enqueueSessionWrite","SessionTranscript","invalidateSessionCache"],"mappings":";;;;;;;;;AAWA,eAAsB,kBAAkB,IAAA,EAMtB;AAChB,EAAA,MAAMA,sCAAoB,IAAA,CAAK,GAAA,CAAI,KAAK,IAAA,CAAK,GAAA,CAAI,SAAS,YAAY;AACpE,IAAA,MAAM,QAAQ,MAAM,IAAA,CAAK,MAAM,WAAA,CAAY,IAAA,CAAK,IAAI,OAAO,CAAA;AAC3D,IAAA,MAAM,UAAA,GAAaC,mCAAA,CAAkB,WAAA,CAAY,KAAA,EAAO;AAAA,MACtD,GAAA,EAAK,KAAK,GAAA,CAAI,GAAA;AAAA,MACd,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,KAAA,EAAO,IAAA,CAAK,GAAA,CAAI,KAAA,IAAS;AAAA,KAC1B,CAAA;AACD,IAAA,UAAA,CAAW,cAAA,CAAe,KAAK,QAAQ,CAAA;AACvC,IAAA,UAAA,CAAW,mBAAA,CAAoB,EAAE,IAAA,EAAM,IAAA,CAAK,eAAe,CAAA;AAC3D,IAAA,MAAM,IAAA,CAAK,KAAA,CAAM,aAAA,CAAc,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,UAAA,CAAW,OAAA,EAAQ,CAAE,KAAA,CAAM,KAAA,CAAM,MAAM,CAAC,CAAA;AACzF,IAAAC,wCAAA,CAAuB,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,IAAI,OAAO,CAAA;AAAA,EACvD,CAAC,CAAA;AACH","file":"inject-session-
|
|
1
|
+
{"version":3,"sources":["../src/internal/session/inject-session.ts"],"names":["enqueueSessionWrite","SessionTranscript","invalidateSessionCache"],"mappings":";;;;;;;;;AAWA,eAAsB,kBAAkB,IAAA,EAMtB;AAChB,EAAA,MAAMA,sCAAoB,IAAA,CAAK,GAAA,CAAI,KAAK,IAAA,CAAK,GAAA,CAAI,SAAS,YAAY;AACpE,IAAA,MAAM,QAAQ,MAAM,IAAA,CAAK,MAAM,WAAA,CAAY,IAAA,CAAK,IAAI,OAAO,CAAA;AAC3D,IAAA,MAAM,UAAA,GAAaC,mCAAA,CAAkB,WAAA,CAAY,KAAA,EAAO;AAAA,MACtD,GAAA,EAAK,KAAK,GAAA,CAAI,GAAA;AAAA,MACd,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,KAAA,EAAO,IAAA,CAAK,GAAA,CAAI,KAAA,IAAS;AAAA,KAC1B,CAAA;AACD,IAAA,UAAA,CAAW,cAAA,CAAe,KAAK,QAAQ,CAAA;AACvC,IAAA,UAAA,CAAW,mBAAA,CAAoB,EAAE,IAAA,EAAM,IAAA,CAAK,eAAe,CAAA;AAC3D,IAAA,MAAM,IAAA,CAAK,KAAA,CAAM,aAAA,CAAc,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,UAAA,CAAW,OAAA,EAAQ,CAAE,KAAA,CAAM,KAAA,CAAM,MAAM,CAAC,CAAA;AACzF,IAAAC,wCAAA,CAAuB,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,IAAI,OAAO,CAAA;AAAA,EACvD,CAAC,CAAA;AACH","file":"inject-session-MIFEKATN.cjs","sourcesContent":["/**\n * M51 (agent-builder) — inject a SYNTHETIC user+assistant pair into a session's persisted transcript\n * WITHOUT running an LLM turn. This is the Codex review-exit mechanism (`exit_success.xml` appended to\n * the parent thread history so follow-ups like \"fix finding 2\" work): the pair chains onto the DAG\n * leaf (M50 pattern) and the in-memory cache is invalidated so the NEXT send re-hydrates with it.\n */\nimport type { SessionStore } from \"../../types/session-store.js\";\nimport { SessionTranscript } from \"../persistence/session-transcript.js\";\nimport { enqueueSessionWrite, invalidateSessionCache } from \"./agent-session.js\";\nimport type { CompactLocation } from \"./compact-session.js\";\n\nexport async function injectSessionTurn(opts: {\n store: SessionStore;\n loc: CompactLocation;\n sessionId: string;\n userText: string;\n assistantText: string;\n}): Promise<void> {\n await enqueueSessionWrite(opts.loc.cwd, opts.loc.agentId, async () => {\n const prior = await opts.store.readRecords(opts.loc.agentId);\n const transcript = SessionTranscript.fromRecords(prior, {\n cwd: opts.loc.cwd,\n sessionId: opts.sessionId,\n model: opts.loc.model ?? \"unknown\",\n });\n transcript.appendUserTurn(opts.userText);\n transcript.appendAssistantTurn({ text: opts.assistantText });\n await opts.store.appendRecords(opts.loc.agentId, transcript.records().slice(prior.length));\n invalidateSessionCache(opts.loc.cwd, opts.loc.agentId);\n });\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { enqueueSessionWrite } from './chunk-
|
|
1
|
+
import { enqueueSessionWrite } from './chunk-VUXLNVX7.js';
|
|
2
2
|
import { invalidateSessionCache } from './chunk-EEZ7CFMM.js';
|
|
3
3
|
import { SessionTranscript } from './chunk-ZZWTY3RX.js';
|
|
4
4
|
import './chunk-S2BBRVQX.js';
|
|
@@ -21,5 +21,5 @@ async function injectSessionTurn(opts) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export { injectSessionTurn };
|
|
24
|
-
//# sourceMappingURL=inject-session-
|
|
25
|
-
//# sourceMappingURL=inject-session-
|
|
24
|
+
//# sourceMappingURL=inject-session-NNSCCIVP.js.map
|
|
25
|
+
//# sourceMappingURL=inject-session-NNSCCIVP.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/session/inject-session.ts"],"names":[],"mappings":";;;;;;;AAWA,eAAsB,kBAAkB,IAAA,EAMtB;AAChB,EAAA,MAAM,oBAAoB,IAAA,CAAK,GAAA,CAAI,KAAK,IAAA,CAAK,GAAA,CAAI,SAAS,YAAY;AACpE,IAAA,MAAM,QAAQ,MAAM,IAAA,CAAK,MAAM,WAAA,CAAY,IAAA,CAAK,IAAI,OAAO,CAAA;AAC3D,IAAA,MAAM,UAAA,GAAa,iBAAA,CAAkB,WAAA,CAAY,KAAA,EAAO;AAAA,MACtD,GAAA,EAAK,KAAK,GAAA,CAAI,GAAA;AAAA,MACd,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,KAAA,EAAO,IAAA,CAAK,GAAA,CAAI,KAAA,IAAS;AAAA,KAC1B,CAAA;AACD,IAAA,UAAA,CAAW,cAAA,CAAe,KAAK,QAAQ,CAAA;AACvC,IAAA,UAAA,CAAW,mBAAA,CAAoB,EAAE,IAAA,EAAM,IAAA,CAAK,eAAe,CAAA;AAC3D,IAAA,MAAM,IAAA,CAAK,KAAA,CAAM,aAAA,CAAc,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,UAAA,CAAW,OAAA,EAAQ,CAAE,KAAA,CAAM,KAAA,CAAM,MAAM,CAAC,CAAA;AACzF,IAAA,sBAAA,CAAuB,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,IAAI,OAAO,CAAA;AAAA,EACvD,CAAC,CAAA;AACH","file":"inject-session-
|
|
1
|
+
{"version":3,"sources":["../src/internal/session/inject-session.ts"],"names":[],"mappings":";;;;;;;AAWA,eAAsB,kBAAkB,IAAA,EAMtB;AAChB,EAAA,MAAM,oBAAoB,IAAA,CAAK,GAAA,CAAI,KAAK,IAAA,CAAK,GAAA,CAAI,SAAS,YAAY;AACpE,IAAA,MAAM,QAAQ,MAAM,IAAA,CAAK,MAAM,WAAA,CAAY,IAAA,CAAK,IAAI,OAAO,CAAA;AAC3D,IAAA,MAAM,UAAA,GAAa,iBAAA,CAAkB,WAAA,CAAY,KAAA,EAAO;AAAA,MACtD,GAAA,EAAK,KAAK,GAAA,CAAI,GAAA;AAAA,MACd,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,KAAA,EAAO,IAAA,CAAK,GAAA,CAAI,KAAA,IAAS;AAAA,KAC1B,CAAA;AACD,IAAA,UAAA,CAAW,cAAA,CAAe,KAAK,QAAQ,CAAA;AACvC,IAAA,UAAA,CAAW,mBAAA,CAAoB,EAAE,IAAA,EAAM,IAAA,CAAK,eAAe,CAAA;AAC3D,IAAA,MAAM,IAAA,CAAK,KAAA,CAAM,aAAA,CAAc,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,UAAA,CAAW,OAAA,EAAQ,CAAE,KAAA,CAAM,KAAA,CAAM,MAAM,CAAC,CAAA;AACzF,IAAA,sBAAA,CAAuB,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,IAAI,OAAO,CAAA;AAAA,EACvD,CAAC,CAAA;AACH","file":"inject-session-NNSCCIVP.js","sourcesContent":["/**\n * M51 (agent-builder) — inject a SYNTHETIC user+assistant pair into a session's persisted transcript\n * WITHOUT running an LLM turn. This is the Codex review-exit mechanism (`exit_success.xml` appended to\n * the parent thread history so follow-ups like \"fix finding 2\" work): the pair chains onto the DAG\n * leaf (M50 pattern) and the in-memory cache is invalidated so the NEXT send re-hydrates with it.\n */\nimport type { SessionStore } from \"../../types/session-store.js\";\nimport { SessionTranscript } from \"../persistence/session-transcript.js\";\nimport { enqueueSessionWrite, invalidateSessionCache } from \"./agent-session.js\";\nimport type { CompactLocation } from \"./compact-session.js\";\n\nexport async function injectSessionTurn(opts: {\n store: SessionStore;\n loc: CompactLocation;\n sessionId: string;\n userText: string;\n assistantText: string;\n}): Promise<void> {\n await enqueueSessionWrite(opts.loc.cwd, opts.loc.agentId, async () => {\n const prior = await opts.store.readRecords(opts.loc.agentId);\n const transcript = SessionTranscript.fromRecords(prior, {\n cwd: opts.loc.cwd,\n sessionId: opts.sessionId,\n model: opts.loc.model ?? \"unknown\",\n });\n transcript.appendUserTurn(opts.userText);\n transcript.appendAssistantTurn({ text: opts.assistantText });\n await opts.store.appendRecords(opts.loc.agentId, transcript.records().slice(prior.length));\n invalidateSessionCache(opts.loc.cwd, opts.loc.agentId);\n });\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { LlmClient, LlmEvent, LlmFinish, LlmRequest } from "./types.js";
|
|
2
|
+
/** Teto de tentativas. Fixo em 3 — o DoD do M93 nomeia o número. */
|
|
3
|
+
export declare const MAX_TENTATIVAS = 3;
|
|
4
|
+
/**
|
|
5
|
+
* O erro é transitório, isto é: reexecutar pode mudar o resultado?
|
|
6
|
+
*
|
|
7
|
+
* `RateLimitError` cobre 429 **e** 402 (billing). 402 NÃO é transitório — cota de faturamento não se
|
|
8
|
+
* resolve em milissegundos, e é por isso que o `classifyAndDecide` do pool rotaciona em vez de esperar.
|
|
9
|
+
* Aqui, sem para onde rotacionar, 402 propaga.
|
|
10
|
+
*/
|
|
11
|
+
export declare function ehTransitorio(err: unknown): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* ## Por que NÃO há circuit breaker aqui
|
|
14
|
+
*
|
|
15
|
+
* O `CircuitBreaker` do pacote é **chaveado por credencial** (`recordSuccess(key)` /
|
|
16
|
+
* `recordTimeout(key)`): existe para o pool marcar uma chave como insalubre e **pular** para outra. Com
|
|
17
|
+
* uma chave só não há para onde pular, então um breaker aqui registraria estado que ninguém consulta.
|
|
18
|
+
*
|
|
19
|
+
* Rung 1 da parcimônia — "isto precisa existir?". Não: seria cerimônia com nome de resiliência. O que
|
|
20
|
+
* protege o caminho de chave única é o teto de tentativas e o backoff, e os dois estão abaixo.
|
|
21
|
+
*/
|
|
22
|
+
export declare class RetryingLlmClient implements LlmClient {
|
|
23
|
+
#private;
|
|
24
|
+
constructor(inner: LlmClient, opts?: {
|
|
25
|
+
rng?: () => number;
|
|
26
|
+
});
|
|
27
|
+
get name(): string;
|
|
28
|
+
stream(request: LlmRequest, signal: AbortSignal): AsyncGenerator<LlmEvent, LlmFinish, void>;
|
|
29
|
+
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var chunkHK7ZHSAX_cjs = require('../../chunk-HK7ZHSAX.cjs');
|
|
4
3
|
var chunkPNVDQL5Y_cjs = require('../../chunk-PNVDQL5Y.cjs');
|
|
5
4
|
var chunkOIYQBUW4_cjs = require('../../chunk-OIYQBUW4.cjs');
|
|
6
|
-
var
|
|
5
|
+
var chunkWQEQCJTZ_cjs = require('../../chunk-WQEQCJTZ.cjs');
|
|
7
6
|
var chunkJD74LN7R_cjs = require('../../chunk-JD74LN7R.cjs');
|
|
8
7
|
var chunkYLQQX5W2_cjs = require('../../chunk-YLQQX5W2.cjs');
|
|
9
8
|
var chunkTIZ4TS5V_cjs = require('../../chunk-TIZ4TS5V.cjs');
|
|
@@ -36,22 +35,6 @@ function casUpdate(db, sql, params, expectedChanges = 1) {
|
|
|
36
35
|
return result.changes === expectedChanges;
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
Object.defineProperty(exports, "JsonlParseError", {
|
|
40
|
-
enumerable: true,
|
|
41
|
-
get: function () { return chunkHK7ZHSAX_cjs.JsonlParseError; }
|
|
42
|
-
});
|
|
43
|
-
Object.defineProperty(exports, "appendJsonl", {
|
|
44
|
-
enumerable: true,
|
|
45
|
-
get: function () { return chunkHK7ZHSAX_cjs.appendJsonl; }
|
|
46
|
-
});
|
|
47
|
-
Object.defineProperty(exports, "loadJsonl", {
|
|
48
|
-
enumerable: true,
|
|
49
|
-
get: function () { return chunkHK7ZHSAX_cjs.loadJsonl; }
|
|
50
|
-
});
|
|
51
|
-
Object.defineProperty(exports, "readJsonlIds", {
|
|
52
|
-
enumerable: true,
|
|
53
|
-
get: function () { return chunkHK7ZHSAX_cjs.readJsonlIds; }
|
|
54
|
-
});
|
|
55
38
|
Object.defineProperty(exports, "PersistenceSchema", {
|
|
56
39
|
enumerable: true,
|
|
57
40
|
get: function () { return chunkPNVDQL5Y_cjs.PersistenceSchema; }
|
|
@@ -80,9 +63,25 @@ Object.defineProperty(exports, "writeVersionedJson", {
|
|
|
80
63
|
enumerable: true,
|
|
81
64
|
get: function () { return chunkOIYQBUW4_cjs.writeVersionedJson; }
|
|
82
65
|
});
|
|
66
|
+
Object.defineProperty(exports, "JsonlParseError", {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
get: function () { return chunkWQEQCJTZ_cjs.JsonlParseError; }
|
|
69
|
+
});
|
|
70
|
+
Object.defineProperty(exports, "appendJsonl", {
|
|
71
|
+
enumerable: true,
|
|
72
|
+
get: function () { return chunkWQEQCJTZ_cjs.appendJsonl; }
|
|
73
|
+
});
|
|
74
|
+
Object.defineProperty(exports, "loadJsonl", {
|
|
75
|
+
enumerable: true,
|
|
76
|
+
get: function () { return chunkWQEQCJTZ_cjs.loadJsonl; }
|
|
77
|
+
});
|
|
78
|
+
Object.defineProperty(exports, "readJsonlIds", {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
get: function () { return chunkWQEQCJTZ_cjs.readJsonlIds; }
|
|
81
|
+
});
|
|
83
82
|
Object.defineProperty(exports, "withFileLock", {
|
|
84
83
|
enumerable: true,
|
|
85
|
-
get: function () { return
|
|
84
|
+
get: function () { return chunkWQEQCJTZ_cjs.withFileLock; }
|
|
86
85
|
});
|
|
87
86
|
Object.defineProperty(exports, "applyWalWithFallback", {
|
|
88
87
|
enumerable: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internal/persistence/exclusive-create.ts","../../../src/internal/persistence/sqlite-cas.ts"],"names":["open"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/internal/persistence/exclusive-create.ts","../../../src/internal/persistence/sqlite-cas.ts"],"names":["open"],"mappings":";;;;;;;;;;;;AAgCA,eAAsB,eAAA,CACpB,IAAA,EACA,IAAA,EACA,OAAA,EACkB;AAClB,EAAA,MAAM,IAAA,GAAO,SAAS,IAAA,IAAQ,GAAA;AAC9B,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,MAAMA,aAAA,CAAK,IAAA,EAAM,MAAM,IAAI,CAAA;AAC1C,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,CAAO,UAAU,IAAI,CAAA;AAC3B,MAAA,OAAO,IAAA;AAAA,IACT,CAAA,SAAE;AACA,MAAA,MAAM,OAAO,KAAA,EAAM;AAAA,IACrB;AAAA,EACF,SAAS,GAAA,EAAK;AACZ,IAAA,IAAK,GAAA,CAA8B,SAAS,QAAA,EAAU;AACpD,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,GAAA;AAAA,EACR;AACF;;;ACjBO,SAAS,SAAA,CACd,EAAA,EACA,GAAA,EACA,MAAA,EACA,kBAA0B,CAAA,EACjB;AACT,EAAA,MAAM,IAAA,GAAO,EAAA,CAAG,OAAA,CAAQ,GAAG,CAAA;AAC3B,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,GAAI,MAAoB,CAAA;AAChD,EAAA,OAAO,OAAO,OAAA,KAAY,eAAA;AAC5B","file":"index.cjs","sourcesContent":["/**\n * O_EXCL exclusive file creation (ADR D82).\n *\n * `createExclusive(path, data, { mode })` creates a file in a single\n * syscall (`open(path, \"wx\", mode)`). Returns `true` if created, `false`\n * if it already existed (EEXIST swallowed — caller decides). All other\n * errors propagate.\n *\n * Default mode is 0o600 (owner-only) — EC-2 fix from edge-case review:\n * token files, lockfiles, and PID files MUST NOT default to world-\n * readable 0o644 under typical umask 022. Callers writing non-sensitive\n * files can pass `mode: 0o644` explicitly.\n *\n * NFS sem honor de O_EXCL é documentado (D61 — mesma postura do\n * `withFileLock`); SDK target é ext4/APFS/NTFS.\n *\n * @internal\n */\n\nimport { open } from \"node:fs/promises\";\n\nexport interface CreateExclusiveOptions {\n /** Unix mode for the new file (default 0o600 — owner-only). */\n mode?: number;\n}\n\n/**\n * Atomically create `path` with `data`. Returns true iff this call\n * created the file (race-free under POSIX-compliant filesystems).\n *\n * @internal\n */\nexport async function createExclusive(\n path: string,\n data: string | Uint8Array,\n options?: CreateExclusiveOptions,\n): Promise<boolean> {\n const mode = options?.mode ?? 0o600;\n try {\n const handle = await open(path, \"wx\", mode);\n try {\n await handle.writeFile(data);\n return true;\n } finally {\n await handle.close();\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"EEXIST\") {\n return false;\n }\n throw err;\n }\n}\n","/**\n * SQLite optimistic compare-and-swap (ADR D83).\n *\n * `casUpdate(db, sql, params, expectedChanges)` executes a prepared\n * UPDATE and returns true if `result.changes === expectedChanges`.\n * Caller provides the full SQL (including `WHERE version = ?` predicate);\n * helper does NOT generate SQL — DRY at the level of \"wrap the\n * convention\", not \"build queries\".\n *\n * Use case canonical (Hermes `kanban_db.py:1922-1934`):\n *\n * const won = casUpdate(\n * db,\n * \"UPDATE registry SET status = ?, version = version + 1 WHERE id = ? AND version = ?\",\n * [\"running\", \"agent-foo\", 3],\n * );\n * if (!won) { ... re-read and retry ... }\n *\n * Helper does NOT retry — caller responsible for backoff (avoids hidden\n * loops). Helper does NOT cache prepared statements — `better-sqlite3`\n * caches internally; SDK use is one-shot per mutation, not hot loops.\n *\n * @internal\n */\n\nimport type Database from \"better-sqlite3\";\n\ntype DatabaseInstance = InstanceType<typeof Database>;\n\n/**\n * Execute a CAS UPDATE. Returns true iff the actual changes count matches\n * `expectedChanges`. SQL errors (invalid syntax, closed db) propagate.\n *\n * @internal\n */\nexport function casUpdate(\n db: DatabaseInstance,\n sql: string,\n params: ReadonlyArray<unknown>,\n expectedChanges: number = 1,\n): boolean {\n const stmt = db.prepare(sql);\n const result = stmt.run(...(params as unknown[]));\n return result.changes === expectedChanges;\n}\n"]}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
export { JsonlParseError, appendJsonl, loadJsonl, readJsonlIds } from '../../chunk-R6ZP6KNB.js';
|
|
2
1
|
export { PersistenceSchema } from '../../chunk-CAH3G4IS.js';
|
|
3
2
|
export { displayTheokitHome, getProfilesRoot, getTheokitHome, migrateSchema, readVersionedJson, writeVersionedJson } from '../../chunk-DGRZNMTU.js';
|
|
4
|
-
export { withFileLock } from '../../chunk-
|
|
3
|
+
export { JsonlParseError, appendJsonl, loadJsonl, readJsonlIds, withFileLock } from '../../chunk-ICSCKB3N.js';
|
|
5
4
|
export { applyWalWithFallback, containsCjk, isCorruptionError, openSqliteResilient, sanitizeFts5Query } from '../../chunk-77FOZCOT.js';
|
|
6
5
|
export { withCwdMutex } from '../../chunk-2XLKLVVR.js';
|
|
7
6
|
export { atomicWriteJson, atomicWriteText, replaceFileAtomic } from '../../chunk-S2BBRVQX.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internal/persistence/exclusive-create.ts","../../../src/internal/persistence/sqlite-cas.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/internal/persistence/exclusive-create.ts","../../../src/internal/persistence/sqlite-cas.ts"],"names":[],"mappings":";;;;;;;;;;AAgCA,eAAsB,eAAA,CACpB,IAAA,EACA,IAAA,EACA,OAAA,EACkB;AAClB,EAAA,MAAM,IAAA,GAAO,SAAS,IAAA,IAAQ,GAAA;AAC9B,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,IAAA,EAAM,MAAM,IAAI,CAAA;AAC1C,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,CAAO,UAAU,IAAI,CAAA;AAC3B,MAAA,OAAO,IAAA;AAAA,IACT,CAAA,SAAE;AACA,MAAA,MAAM,OAAO,KAAA,EAAM;AAAA,IACrB;AAAA,EACF,SAAS,GAAA,EAAK;AACZ,IAAA,IAAK,GAAA,CAA8B,SAAS,QAAA,EAAU;AACpD,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,GAAA;AAAA,EACR;AACF;;;ACjBO,SAAS,SAAA,CACd,EAAA,EACA,GAAA,EACA,MAAA,EACA,kBAA0B,CAAA,EACjB;AACT,EAAA,MAAM,IAAA,GAAO,EAAA,CAAG,OAAA,CAAQ,GAAG,CAAA;AAC3B,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,GAAI,MAAoB,CAAA;AAChD,EAAA,OAAO,OAAO,OAAA,KAAY,eAAA;AAC5B","file":"index.js","sourcesContent":["/**\n * O_EXCL exclusive file creation (ADR D82).\n *\n * `createExclusive(path, data, { mode })` creates a file in a single\n * syscall (`open(path, \"wx\", mode)`). Returns `true` if created, `false`\n * if it already existed (EEXIST swallowed — caller decides). All other\n * errors propagate.\n *\n * Default mode is 0o600 (owner-only) — EC-2 fix from edge-case review:\n * token files, lockfiles, and PID files MUST NOT default to world-\n * readable 0o644 under typical umask 022. Callers writing non-sensitive\n * files can pass `mode: 0o644` explicitly.\n *\n * NFS sem honor de O_EXCL é documentado (D61 — mesma postura do\n * `withFileLock`); SDK target é ext4/APFS/NTFS.\n *\n * @internal\n */\n\nimport { open } from \"node:fs/promises\";\n\nexport interface CreateExclusiveOptions {\n /** Unix mode for the new file (default 0o600 — owner-only). */\n mode?: number;\n}\n\n/**\n * Atomically create `path` with `data`. Returns true iff this call\n * created the file (race-free under POSIX-compliant filesystems).\n *\n * @internal\n */\nexport async function createExclusive(\n path: string,\n data: string | Uint8Array,\n options?: CreateExclusiveOptions,\n): Promise<boolean> {\n const mode = options?.mode ?? 0o600;\n try {\n const handle = await open(path, \"wx\", mode);\n try {\n await handle.writeFile(data);\n return true;\n } finally {\n await handle.close();\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"EEXIST\") {\n return false;\n }\n throw err;\n }\n}\n","/**\n * SQLite optimistic compare-and-swap (ADR D83).\n *\n * `casUpdate(db, sql, params, expectedChanges)` executes a prepared\n * UPDATE and returns true if `result.changes === expectedChanges`.\n * Caller provides the full SQL (including `WHERE version = ?` predicate);\n * helper does NOT generate SQL — DRY at the level of \"wrap the\n * convention\", not \"build queries\".\n *\n * Use case canonical (Hermes `kanban_db.py:1922-1934`):\n *\n * const won = casUpdate(\n * db,\n * \"UPDATE registry SET status = ?, version = version + 1 WHERE id = ? AND version = ?\",\n * [\"running\", \"agent-foo\", 3],\n * );\n * if (!won) { ... re-read and retry ... }\n *\n * Helper does NOT retry — caller responsible for backoff (avoids hidden\n * loops). Helper does NOT cache prepared statements — `better-sqlite3`\n * caches internally; SDK use is one-shot per mutation, not hot loops.\n *\n * @internal\n */\n\nimport type Database from \"better-sqlite3\";\n\ntype DatabaseInstance = InstanceType<typeof Database>;\n\n/**\n * Execute a CAS UPDATE. Returns true iff the actual changes count matches\n * `expectedChanges`. SQL errors (invalid syntax, closed db) propagate.\n *\n * @internal\n */\nexport function casUpdate(\n db: DatabaseInstance,\n sql: string,\n params: ReadonlyArray<unknown>,\n expectedChanges: number = 1,\n): boolean {\n const stmt = db.prepare(sql);\n const result = stmt.run(...(params as unknown[]));\n return result.changes === expectedChanges;\n}\n"]}
|
package/dist/persistence.cjs
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var chunkHK7ZHSAX_cjs = require('./chunk-HK7ZHSAX.cjs');
|
|
4
3
|
var chunkPNVDQL5Y_cjs = require('./chunk-PNVDQL5Y.cjs');
|
|
5
|
-
var
|
|
4
|
+
var chunkWQEQCJTZ_cjs = require('./chunk-WQEQCJTZ.cjs');
|
|
6
5
|
var chunkJD74LN7R_cjs = require('./chunk-JD74LN7R.cjs');
|
|
7
6
|
var chunkYLQQX5W2_cjs = require('./chunk-YLQQX5W2.cjs');
|
|
8
7
|
var chunk4SXHEZIV_cjs = require('./chunk-4SXHEZIV.cjs');
|
|
@@ -110,29 +109,29 @@ function readJsonlTail(path, options = {}) {
|
|
|
110
109
|
return options._stats === true ? Object.assign(out, { bytesRead }) : out;
|
|
111
110
|
}
|
|
112
111
|
|
|
112
|
+
Object.defineProperty(exports, "PersistenceSchema", {
|
|
113
|
+
enumerable: true,
|
|
114
|
+
get: function () { return chunkPNVDQL5Y_cjs.PersistenceSchema; }
|
|
115
|
+
});
|
|
113
116
|
Object.defineProperty(exports, "JsonlParseError", {
|
|
114
117
|
enumerable: true,
|
|
115
|
-
get: function () { return
|
|
118
|
+
get: function () { return chunkWQEQCJTZ_cjs.JsonlParseError; }
|
|
116
119
|
});
|
|
117
120
|
Object.defineProperty(exports, "appendJsonl", {
|
|
118
121
|
enumerable: true,
|
|
119
|
-
get: function () { return
|
|
122
|
+
get: function () { return chunkWQEQCJTZ_cjs.appendJsonl; }
|
|
120
123
|
});
|
|
121
124
|
Object.defineProperty(exports, "loadJsonl", {
|
|
122
125
|
enumerable: true,
|
|
123
|
-
get: function () { return
|
|
126
|
+
get: function () { return chunkWQEQCJTZ_cjs.loadJsonl; }
|
|
124
127
|
});
|
|
125
128
|
Object.defineProperty(exports, "readJsonlIds", {
|
|
126
129
|
enumerable: true,
|
|
127
|
-
get: function () { return
|
|
128
|
-
});
|
|
129
|
-
Object.defineProperty(exports, "PersistenceSchema", {
|
|
130
|
-
enumerable: true,
|
|
131
|
-
get: function () { return chunkPNVDQL5Y_cjs.PersistenceSchema; }
|
|
130
|
+
get: function () { return chunkWQEQCJTZ_cjs.readJsonlIds; }
|
|
132
131
|
});
|
|
133
132
|
Object.defineProperty(exports, "withFileLock", {
|
|
134
133
|
enumerable: true,
|
|
135
|
-
get: function () { return
|
|
134
|
+
get: function () { return chunkWQEQCJTZ_cjs.withFileLock; }
|
|
136
135
|
});
|
|
137
136
|
Object.defineProperty(exports, "applyWalWithFallback", {
|
|
138
137
|
enumerable: true,
|
package/dist/persistence.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/persistence/session-writer.ts","../src/internal/persistence/transcript-ops.ts"],"names":["TheokitAgentError","openSync","closeSync","rmSync","readFileSync","writeSync","statSync","readSync"],"mappings":"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","file":"persistence.cjs","sourcesContent":["/**\n * M81 — single-writer lease for a session transcript.\n *\n * ## The problem\n *\n * Nothing stops two processes appending to the same JSONL transcript. The concrete case: `exec\n * resume --last` can write into the TUI's live session. Two interleaved appends to an append-only\n * file produce lines that are each individually valid and whose SEQUENCE is fiction — and nothing\n * reports it, because every line parses.\n *\n * ## Why an exclusive lockfile rather than `withFileLock`\n *\n * The plan's ADR D2 said to compose `withFileLock`, and that was the right instinct — do not build a\n * second lock mechanism. It turned out not to fit the SHAPE: `withFileLock(path, fn)` is\n * scope-based — it holds the lock for the duration of a callback. A session lease is **held across\n * turns**, for as long as the process owns the session, with an explicit `release()`. Wrapping the\n * whole session lifetime in a callback would invert control of the entire agent loop.\n *\n * So this uses the same underlying primitive `withFileLock` uses (an exclusive-create lockfile,\n * `wx`) with lease semantics on top. That keeps the mechanism single — the file-existence lock —\n * while giving it the lifetime the caller needs. The deviation from D2 is recorded here because the\n * plan's rationale (no second mechanism) still holds; only its shape assumption did not.\n *\n * ## Fail fast, never wait\n *\n * A second writer that WAITED would block `exec` behind a TUI session that can last hours. The typed\n * error lets the caller choose: fork to a new id, or give up with a real diagnosis.\n *\n * @internal\n */\n\nimport { closeSync, openSync, rmSync } from \"node:fs\";\n\nimport { TheokitAgentError } from \"../../errors.js\";\n\n/**\n * M81 — another process already holds the writer lease for this session.\n *\n * Carries `sessionPath` because knowing WHICH session is busy is what lets the caller decide between\n * forking and waiting for the user to close the TUI (`rules/error-handling.md § 2` — context enough\n * to act on).\n */\nexport class SessionBusyError extends TheokitAgentError {\n override readonly name = \"SessionBusyError\";\n\n constructor(readonly sessionPath: string) {\n super(\n `another process is already writing this session: ${sessionPath}. ` +\n \"Fork it to a new id instead of appending — two writers interleave lines into a sequence \" +\n \"that parses but is not what either process wrote.\",\n { code: \"session_busy\", isRetryable: false },\n );\n }\n}\n\n/** A held writer lease. `release()` is idempotent. */\nexport interface SessionWriterLease {\n readonly sessionPath: string;\n release(): Promise<void>;\n}\n\n/**\n * Take the exclusive writer lease for `sessionPath`, or reject with {@link SessionBusyError}.\n *\n * The lock is a sibling `.lock` file created with `wx` — the same file-existence primitive the\n * SDK's `withFileLock` builds on. Exclusivity comes from the filesystem, so it holds across\n * processes, not just across async tasks in one process.\n */\nexport async function acquireSessionWriter(sessionPath: string): Promise<SessionWriterLease> {\n const lockPath = `${sessionPath}.lock`;\n let fd: number;\n try {\n fd = openSync(lockPath, \"wx\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"EEXIST\") {\n throw new SessionBusyError(sessionPath);\n }\n throw err;\n }\n closeSync(fd);\n\n let released = false;\n return {\n sessionPath,\n release: async (): Promise<void> => {\n if (released) return;\n released = true;\n rmSync(lockPath, { force: true });\n },\n };\n}\n","/**\n * M81 — transcript operations the consumer was doing by hand INSIDE the framework's own store.\n *\n * ## What this replaces\n *\n * `agents/lib/session/backtrack.ts:188` (agent-builder) wrote straight into the session store with a\n * bare `writeFileSync` — no atomicity, no lock, no API. 243 lines re-implementing parse, cut and\n * write for a format the framework owns. The consumer is not at fault: nothing here was reachable.\n *\n * ## The rule that travels WITH the operation\n *\n * `rules/audit-trail-rotation.md § Session transcripts (M60)` defines a NEVER-delete list — the live\n * pointer, the most recent transcript, and any active registry entry. That rule lived in the\n * CONSUMER. Moving the operation here without moving the rule would ship an API able to destroy\n * exactly what the rule protects — the same shape of defect as M80's `reconcileUpdateGoalStatus`:\n * critical knowledge outside the module that needs it, applied by convention.\n *\n * So `forkTranscript` takes `liveSessionPaths` and refuses, with a TYPED error, to write over any of\n * them. The caller supplies the list because only the caller knows which session is live; the\n * enforcement lives here because that is where the write happens.\n *\n * @internal\n */\n\nimport { closeSync, openSync, readFileSync, readSync, statSync, writeSync } from \"node:fs\";\n\nimport { TheokitAgentError } from \"../../errors.js\";\n\n/**\n * M81 — the target is a protected session (live pointer / most-recent transcript / active entry).\n *\n * Typed rather than a bare `Error` because the caller must distinguish \"this session is protected\"\n * from \"the disk is full\": the first is a correct refusal, the second is an incident.\n */\nexport class LiveSessionError extends TheokitAgentError {\n override readonly name = \"LiveSessionError\";\n\n constructor(readonly path: string) {\n super(\n `refusing to write over a live session transcript: ${path}. ` +\n \"Fork to a new id instead — the live pointer, the most recent transcript and any active \" +\n \"registry entry are never overwritten (audit-trail rotation, M60).\",\n { code: \"live_session_protected\", isRetryable: false },\n );\n }\n}\n\n/** Options for {@link forkTranscript}. */\nexport interface ForkTranscriptOptions {\n /** Keep records `[0, beforeRecordIndex)`. Omit to copy the whole transcript. */\n readonly beforeRecordIndex?: number;\n /**\n * Paths that must never be written over — the live pointer, the most recent transcript, any active\n * registry entry. The caller supplies them because only the caller knows which session is live.\n */\n readonly liveSessionPaths?: readonly string[];\n}\n\n/**\n * Copy `src` into `dst`, keeping the first `beforeRecordIndex` records. The SOURCE is never touched.\n *\n * Atomicity comes from `wx` (exclusive create): two concurrent forks to the same destination cannot\n * both succeed — the loser gets `EEXIST` rather than writing over a half-written file. That is also\n * why an existing destination is a refusal, not a silent overwrite: losing a transcript without an\n * error is the worst failure mode for an operation that touches user sessions.\n */\nexport function forkTranscript(\n src: string,\n dst: string,\n options: ForkTranscriptOptions = {},\n): void {\n for (const live of options.liveSessionPaths ?? []) {\n if (live === dst) throw new LiveSessionError(dst);\n }\n\n const lines = readFileSync(src, \"utf8\")\n .split(\"\\n\")\n .filter((l) => l.trim().length > 0);\n const kept =\n options.beforeRecordIndex === undefined ? lines : lines.slice(0, options.beforeRecordIndex);\n const body = kept.length > 0 ? `${kept.join(\"\\n\")}\\n` : \"\";\n\n // `wx` — fails with EEXIST instead of truncating. The exclusivity IS the concurrency guarantee.\n const fd = openSync(dst, \"wx\");\n try {\n writeSync(fd, body);\n } finally {\n closeSync(fd);\n }\n}\n\n/** Options for {@link readJsonlTail}. */\nexport interface ReadJsonlTailOptions {\n /** Maximum records to return, counted from the END. */\n readonly maxRecords?: number;\n /** Stop once a line contains this marker (exclusive). */\n readonly sinceMarker?: string;\n /** Test-only: also report how many bytes were read, to prove the read is not whole-file. */\n readonly _stats?: boolean;\n}\n\nconst TAIL_CHUNK = 64 * 1024;\n\n/**\n * Lê chunks de trás para frente até acumular linhas completas suficientes.\n *\n * Extraído de `readJsonlTail` porque o laço de leitura e a seleção de registros são duas\n * responsabilidades — e juntas passavam do teto de complexidade. A primeira linha do buffer pode\n * estar cortada ao meio quando a leitura parou antes do início do arquivo; por isso ela é descartada.\n */\nfunction lerCaudaBruta(path: string, want: number): { linhas: string[]; bytesRead: number } {\n const size = statSync(path).size;\n const fd = openSync(path, \"r\");\n let bytesRead = 0;\n let tail = \"\";\n let pos = size;\n try {\n while (pos > 0) {\n const len = Math.min(TAIL_CHUNK, pos);\n pos -= len;\n const buf = Buffer.alloc(len);\n readSync(fd, buf, 0, len, pos);\n bytesRead += len;\n tail = buf.toString(\"utf8\") + tail;\n if (naoVazias(tail).length > want) break;\n }\n } finally {\n closeSync(fd);\n }\n const linhas = naoVazias(tail);\n return { linhas: pos > 0 ? linhas.slice(1) : linhas, bytesRead };\n}\n\n/** Linhas com conteúdo, na ordem do arquivo. */\nfunction naoVazias(texto: string): string[] {\n return texto.split(\"\\n\").filter((l) => l.trim().length > 0);\n}\n\n/**\n * Read the LAST records of a JSONL file without loading the whole thing.\n *\n * Reads fixed-size chunks backwards from EOF until enough newlines have been seen. A session\n * transcript grows without bound; loading megabytes to show the last three turns is the cost this\n * exists to avoid — and a `slice` over a full read would be that same cost with a better name.\n */\nexport function readJsonlTail<T = Record<string, unknown>>(\n path: string,\n options: ReadJsonlTailOptions = {},\n): T[] {\n const want = options.maxRecords ?? Number.POSITIVE_INFINITY;\n const { linhas, bytesRead } = lerCaudaBruta(path, want);\n\n let sel = linhas;\n if (options.sinceMarker !== undefined) {\n const marcador = options.sinceMarker;\n const idx = sel.findLastIndex((l) => l.includes(marcador));\n if (idx >= 0) sel = sel.slice(idx + 1);\n }\n if (Number.isFinite(want)) sel = sel.slice(-want);\n\n const out = sel.map((l) => JSON.parse(l) as T);\n return options._stats === true ? (Object.assign(out, { bytesRead }) as T[]) : out;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/persistence/session-writer.ts","../src/internal/persistence/transcript-ops.ts"],"names":["TheokitAgentError","openSync","closeSync","rmSync","readFileSync","writeSync","statSync","readSync"],"mappings":"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","file":"persistence.cjs","sourcesContent":["/**\n * M81 — single-writer lease for a session transcript.\n *\n * ## The problem\n *\n * Nothing stops two processes appending to the same JSONL transcript. The concrete case: `exec\n * resume --last` can write into the TUI's live session. Two interleaved appends to an append-only\n * file produce lines that are each individually valid and whose SEQUENCE is fiction — and nothing\n * reports it, because every line parses.\n *\n * ## Why an exclusive lockfile rather than `withFileLock`\n *\n * The plan's ADR D2 said to compose `withFileLock`, and that was the right instinct — do not build a\n * second lock mechanism. It turned out not to fit the SHAPE: `withFileLock(path, fn)` is\n * scope-based — it holds the lock for the duration of a callback. A session lease is **held across\n * turns**, for as long as the process owns the session, with an explicit `release()`. Wrapping the\n * whole session lifetime in a callback would invert control of the entire agent loop.\n *\n * So this uses the same underlying primitive `withFileLock` uses (an exclusive-create lockfile,\n * `wx`) with lease semantics on top. That keeps the mechanism single — the file-existence lock —\n * while giving it the lifetime the caller needs. The deviation from D2 is recorded here because the\n * plan's rationale (no second mechanism) still holds; only its shape assumption did not.\n *\n * ## Fail fast, never wait\n *\n * A second writer that WAITED would block `exec` behind a TUI session that can last hours. The typed\n * error lets the caller choose: fork to a new id, or give up with a real diagnosis.\n *\n * @internal\n */\n\nimport { closeSync, openSync, rmSync } from \"node:fs\";\n\nimport { TheokitAgentError } from \"../../errors.js\";\n\n/**\n * M81 — another process already holds the writer lease for this session.\n *\n * Carries `sessionPath` because knowing WHICH session is busy is what lets the caller decide between\n * forking and waiting for the user to close the TUI (`rules/error-handling.md § 2` — context enough\n * to act on).\n */\nexport class SessionBusyError extends TheokitAgentError {\n override readonly name = \"SessionBusyError\";\n\n constructor(readonly sessionPath: string) {\n super(\n `another process is already writing this session: ${sessionPath}. ` +\n \"Fork it to a new id instead of appending — two writers interleave lines into a sequence \" +\n \"that parses but is not what either process wrote.\",\n { code: \"session_busy\", isRetryable: false },\n );\n }\n}\n\n/** A held writer lease. `release()` is idempotent. */\nexport interface SessionWriterLease {\n readonly sessionPath: string;\n release(): Promise<void>;\n}\n\n/**\n * Take the exclusive writer lease for `sessionPath`, or reject with {@link SessionBusyError}.\n *\n * The lock is a sibling `.lock` file created with `wx` — the same file-existence primitive the\n * SDK's `withFileLock` builds on. Exclusivity comes from the filesystem, so it holds across\n * processes, not just across async tasks in one process.\n */\nexport async function acquireSessionWriter(sessionPath: string): Promise<SessionWriterLease> {\n const lockPath = `${sessionPath}.lock`;\n let fd: number;\n try {\n fd = openSync(lockPath, \"wx\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"EEXIST\") {\n throw new SessionBusyError(sessionPath);\n }\n throw err;\n }\n closeSync(fd);\n\n let released = false;\n return {\n sessionPath,\n release: async (): Promise<void> => {\n if (released) return;\n released = true;\n rmSync(lockPath, { force: true });\n },\n };\n}\n","/**\n * M81 — transcript operations the consumer was doing by hand INSIDE the framework's own store.\n *\n * ## What this replaces\n *\n * `agents/lib/session/backtrack.ts:188` (agent-builder) wrote straight into the session store with a\n * bare `writeFileSync` — no atomicity, no lock, no API. 243 lines re-implementing parse, cut and\n * write for a format the framework owns. The consumer is not at fault: nothing here was reachable.\n *\n * ## The rule that travels WITH the operation\n *\n * `rules/audit-trail-rotation.md § Session transcripts (M60)` defines a NEVER-delete list — the live\n * pointer, the most recent transcript, and any active registry entry. That rule lived in the\n * CONSUMER. Moving the operation here without moving the rule would ship an API able to destroy\n * exactly what the rule protects — the same shape of defect as M80's `reconcileUpdateGoalStatus`:\n * critical knowledge outside the module that needs it, applied by convention.\n *\n * So `forkTranscript` takes `liveSessionPaths` and refuses, with a TYPED error, to write over any of\n * them. The caller supplies the list because only the caller knows which session is live; the\n * enforcement lives here because that is where the write happens.\n *\n * @internal\n */\n\nimport { closeSync, openSync, readFileSync, readSync, statSync, writeSync } from \"node:fs\";\n\nimport { TheokitAgentError } from \"../../errors.js\";\n\n/**\n * M81 — the target is a protected session (live pointer / most-recent transcript / active entry).\n *\n * Typed rather than a bare `Error` because the caller must distinguish \"this session is protected\"\n * from \"the disk is full\": the first is a correct refusal, the second is an incident.\n */\nexport class LiveSessionError extends TheokitAgentError {\n override readonly name = \"LiveSessionError\";\n\n constructor(readonly path: string) {\n super(\n `refusing to write over a live session transcript: ${path}. ` +\n \"Fork to a new id instead — the live pointer, the most recent transcript and any active \" +\n \"registry entry are never overwritten (audit-trail rotation, M60).\",\n { code: \"live_session_protected\", isRetryable: false },\n );\n }\n}\n\n/** Options for {@link forkTranscript}. */\nexport interface ForkTranscriptOptions {\n /** Keep records `[0, beforeRecordIndex)`. Omit to copy the whole transcript. */\n readonly beforeRecordIndex?: number;\n /**\n * Paths that must never be written over — the live pointer, the most recent transcript, any active\n * registry entry. The caller supplies them because only the caller knows which session is live.\n */\n readonly liveSessionPaths?: readonly string[];\n}\n\n/**\n * Copy `src` into `dst`, keeping the first `beforeRecordIndex` records. The SOURCE is never touched.\n *\n * Atomicity comes from `wx` (exclusive create): two concurrent forks to the same destination cannot\n * both succeed — the loser gets `EEXIST` rather than writing over a half-written file. That is also\n * why an existing destination is a refusal, not a silent overwrite: losing a transcript without an\n * error is the worst failure mode for an operation that touches user sessions.\n */\nexport function forkTranscript(\n src: string,\n dst: string,\n options: ForkTranscriptOptions = {},\n): void {\n for (const live of options.liveSessionPaths ?? []) {\n if (live === dst) throw new LiveSessionError(dst);\n }\n\n const lines = readFileSync(src, \"utf8\")\n .split(\"\\n\")\n .filter((l) => l.trim().length > 0);\n const kept =\n options.beforeRecordIndex === undefined ? lines : lines.slice(0, options.beforeRecordIndex);\n const body = kept.length > 0 ? `${kept.join(\"\\n\")}\\n` : \"\";\n\n // `wx` — fails with EEXIST instead of truncating. The exclusivity IS the concurrency guarantee.\n const fd = openSync(dst, \"wx\");\n try {\n writeSync(fd, body);\n } finally {\n closeSync(fd);\n }\n}\n\n/** Options for {@link readJsonlTail}. */\nexport interface ReadJsonlTailOptions {\n /** Maximum records to return, counted from the END. */\n readonly maxRecords?: number;\n /** Stop once a line contains this marker (exclusive). */\n readonly sinceMarker?: string;\n /** Test-only: also report how many bytes were read, to prove the read is not whole-file. */\n readonly _stats?: boolean;\n}\n\nconst TAIL_CHUNK = 64 * 1024;\n\n/**\n * Lê chunks de trás para frente até acumular linhas completas suficientes.\n *\n * Extraído de `readJsonlTail` porque o laço de leitura e a seleção de registros são duas\n * responsabilidades — e juntas passavam do teto de complexidade. A primeira linha do buffer pode\n * estar cortada ao meio quando a leitura parou antes do início do arquivo; por isso ela é descartada.\n */\nfunction lerCaudaBruta(path: string, want: number): { linhas: string[]; bytesRead: number } {\n const size = statSync(path).size;\n const fd = openSync(path, \"r\");\n let bytesRead = 0;\n let tail = \"\";\n let pos = size;\n try {\n while (pos > 0) {\n const len = Math.min(TAIL_CHUNK, pos);\n pos -= len;\n const buf = Buffer.alloc(len);\n readSync(fd, buf, 0, len, pos);\n bytesRead += len;\n tail = buf.toString(\"utf8\") + tail;\n if (naoVazias(tail).length > want) break;\n }\n } finally {\n closeSync(fd);\n }\n const linhas = naoVazias(tail);\n return { linhas: pos > 0 ? linhas.slice(1) : linhas, bytesRead };\n}\n\n/** Linhas com conteúdo, na ordem do arquivo. */\nfunction naoVazias(texto: string): string[] {\n return texto.split(\"\\n\").filter((l) => l.trim().length > 0);\n}\n\n/**\n * Read the LAST records of a JSONL file without loading the whole thing.\n *\n * Reads fixed-size chunks backwards from EOF until enough newlines have been seen. A session\n * transcript grows without bound; loading megabytes to show the last three turns is the cost this\n * exists to avoid — and a `slice` over a full read would be that same cost with a better name.\n */\nexport function readJsonlTail<T = Record<string, unknown>>(\n path: string,\n options: ReadJsonlTailOptions = {},\n): T[] {\n const want = options.maxRecords ?? Number.POSITIVE_INFINITY;\n const { linhas, bytesRead } = lerCaudaBruta(path, want);\n\n let sel = linhas;\n if (options.sinceMarker !== undefined) {\n const marcador = options.sinceMarker;\n const idx = sel.findLastIndex((l) => l.includes(marcador));\n if (idx >= 0) sel = sel.slice(idx + 1);\n }\n if (Number.isFinite(want)) sel = sel.slice(-want);\n\n const out = sel.map((l) => JSON.parse(l) as T);\n return options._stats === true ? (Object.assign(out, { bytesRead }) as T[]) : out;\n}\n"]}
|
package/dist/persistence.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
export { JsonlParseError, appendJsonl, loadJsonl, readJsonlIds } from './chunk-R6ZP6KNB.js';
|
|
2
1
|
export { PersistenceSchema } from './chunk-CAH3G4IS.js';
|
|
3
|
-
export { withFileLock } from './chunk-
|
|
2
|
+
export { JsonlParseError, appendJsonl, loadJsonl, readJsonlIds, withFileLock } from './chunk-ICSCKB3N.js';
|
|
4
3
|
export { applyWalWithFallback, isCorruptionError, openSqliteResilient, sanitizeFts5Query } from './chunk-77FOZCOT.js';
|
|
5
4
|
export { withCwdMutex } from './chunk-2XLKLVVR.js';
|
|
6
5
|
export { encodeProjectDir, transcriptPath } from './chunk-ZZWTY3RX.js';
|