@cursor/july 0.1.40 → 0.1.41
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/AGENTS.md +4 -3
- package/dist/bin/agent-serve.js +28 -9
- package/dist/channels/slack/attachments.d.ts +82 -0
- package/dist/channels/slack/attachments.d.ts.map +1 -0
- package/dist/channels/slack/attachments.js +520 -0
- package/dist/channels/slack/cursor-account.d.ts +7 -1
- package/dist/channels/slack/cursor-account.d.ts.map +1 -1
- package/dist/channels/slack/cursor-account.js +2 -2
- package/dist/channels/slack/dispatch.d.ts +4 -3
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +84 -21
- package/dist/channels/slack/inbound.d.ts +6 -0
- package/dist/channels/slack/inbound.d.ts.map +1 -1
- package/dist/channels/slack/inbound.js +48 -2
- package/dist/channels/slack/index.d.ts +1 -0
- package/dist/channels/slack/index.d.ts.map +1 -1
- package/dist/channels/slack/index.js +1 -0
- package/dist/channels/slack/manifest.d.ts.map +1 -1
- package/dist/channels/slack/manifest.js +1 -0
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +7 -4
- package/dist/channels/slack/types.d.ts +49 -1
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +6 -6
- package/dist/docs/assets/{ab.md.6cLOW7--.js → ab.md.hdxsvX5M.js} +2 -2
- package/dist/docs/assets/{app.DpGLSiym.js → app.mIw24pb1.js} +1 -1
- package/dist/docs/assets/{building-with-agents.md.txrcGU2B.js → building-with-agents.md.PeZaZA1P.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.BA7V8dEJ.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.B11XEMST.js → VPLocalSearchBox.hOzpPwrG.js} +1 -1
- package/dist/docs/assets/chunks/{theme.iTidHsAx.js → theme.BtFhUYmh.js} +2 -2
- package/dist/docs/assets/{deployment.md.CuK5SNjN.js → deployment.md.BHVjVqRa.js} +4 -4
- package/dist/docs/assets/{deployment.md.CuK5SNjN.lean.js → deployment.md.BHVjVqRa.lean.js} +1 -1
- package/dist/docs/assets/{evals.md.BQXI3rXy.js → evals.md.qeoGgPw0.js} +3 -3
- package/dist/docs/assets/example-agents_index.md.xmJ87d_3.js +2 -0
- package/dist/docs/assets/{guides_webhooks.md.BERuBSJW.js → guides_webhooks.md.DB-r_er9.js} +47 -4
- package/dist/docs/assets/{guides_webhooks.md.BERuBSJW.lean.js → guides_webhooks.md.DB-r_er9.lean.js} +1 -1
- package/dist/docs/assets/index.md.BKpbkCa6.js +24 -0
- package/dist/docs/assets/{index.md.CmhptOmN.lean.js → index.md.BKpbkCa6.lean.js} +1 -1
- package/dist/docs/assets/{quickstart.md.C_b6ESpD.js → quickstart.md.rIbfahJM.js} +4 -4
- package/dist/docs/assets/{reference_cli.md.Byvrg8eu.js → reference_cli.md.DqEqQpGn.js} +5 -5
- package/dist/docs/assets/{reference_cli.md.Byvrg8eu.lean.js → reference_cli.md.DqEqQpGn.lean.js} +1 -1
- package/dist/docs/assets/{reference_hooks.md.BGDw4VLm.js → reference_hooks.md.BHeG-vjK.js} +2 -2
- package/dist/docs/assets/{reference_hooks.md.BGDw4VLm.lean.js → reference_hooks.md.BHeG-vjK.lean.js} +1 -1
- package/dist/docs/assets/{storage.md.mQDtIULc.js → storage.md.DcGSnIxX.js} +10 -4
- package/dist/docs/assets/{storage.md.mQDtIULc.lean.js → storage.md.DcGSnIxX.lean.js} +1 -1
- package/dist/docs/assets/troubleshooting.md.CkgwmVI0.js +1 -0
- package/dist/docs/assets/{troubleshooting.md.B5RVX_tL.lean.js → troubleshooting.md.CkgwmVI0.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +5 -5
- package/dist/docs/concepts.html +3 -3
- package/dist/docs/deployment.html +6 -6
- package/dist/docs/evals.html +7 -7
- package/dist/docs/example-agents/approval-buddy.html +3 -3
- package/dist/docs/example-agents/benny.html +3 -3
- package/dist/docs/example-agents/bugbot.html +3 -3
- package/dist/docs/example-agents/codebase-wiki.html +3 -3
- package/dist/docs/example-agents/codeowners-review.html +3 -3
- package/dist/docs/example-agents/concierge.html +3 -3
- package/dist/docs/example-agents/fsd.html +3 -3
- package/dist/docs/example-agents/index.html +5 -5
- package/dist/docs/example-agents/knowledge-base.html +3 -3
- package/dist/docs/example-agents/oncall.html +3 -3
- package/dist/docs/example-agents/security-reviewer.html +3 -3
- package/dist/docs/example-agents/slack-agent.html +3 -3
- package/dist/docs/example-agents/weather-agent.html +3 -3
- package/dist/docs/guides/agent-to-agent.html +3 -3
- package/dist/docs/guides/cloud-runtime.html +3 -3
- package/dist/docs/guides/github.html +3 -3
- package/dist/docs/guides/human-in-the-loop.html +3 -3
- package/dist/docs/guides/mcp-oauth.html +3 -3
- package/dist/docs/guides/slack.html +3 -3
- package/dist/docs/guides/webhooks.html +49 -6
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +3 -3
- package/dist/docs/index.html +7 -7
- package/dist/docs/quickstart.html +8 -8
- package/dist/docs/reference/agent-config.html +3 -3
- package/dist/docs/reference/artifacts.html +3 -3
- package/dist/docs/reference/channels.html +3 -3
- package/dist/docs/reference/cli.html +8 -8
- package/dist/docs/reference/connections.html +3 -3
- package/dist/docs/reference/hooks.html +5 -5
- package/dist/docs/reference/http-api.html +3 -3
- package/dist/docs/reference/instructions.html +3 -3
- package/dist/docs/reference/playground.html +3 -3
- package/dist/docs/reference/project-layout.html +3 -3
- package/dist/docs/reference/prompt.html +3 -3
- package/dist/docs/reference/schedules.html +3 -3
- package/dist/docs/reference/sessions.html +3 -3
- package/dist/docs/reference/skills.html +3 -3
- package/dist/docs/reference/subagents.html +3 -3
- package/dist/docs/reference/tools.html +3 -3
- package/dist/docs/scaffolding-agents.html +3 -3
- package/dist/docs/storage.html +14 -8
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +22 -2
- package/dist/internal/cli-deploy.d.ts +6 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +14 -4
- package/dist/internal/cli-mcp.js +4 -4
- package/dist/internal/deploy-client.js +1 -1
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +35 -7
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +3 -1
- package/dist/internal/durable-session-store.d.ts +48 -0
- package/dist/internal/durable-session-store.d.ts.map +1 -0
- package/dist/internal/durable-session-store.js +86 -0
- package/dist/internal/hosting.d.ts +1 -1
- package/dist/internal/hosting.js +2 -2
- package/dist/internal/init-project.d.ts +34 -0
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +121 -2
- package/dist/internal/ledger-serving.d.ts +101 -0
- package/dist/internal/ledger-serving.d.ts.map +1 -0
- package/dist/internal/ledger-serving.js +174 -0
- package/dist/internal/listen-port.d.ts +22 -0
- package/dist/internal/listen-port.d.ts.map +1 -0
- package/dist/internal/listen-port.js +77 -0
- package/dist/internal/playground/static.d.ts +21 -4
- package/dist/internal/playground/static.d.ts.map +1 -1
- package/dist/internal/playground/static.js +82 -18
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +10 -1
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +61 -47
- package/dist/internal/session-engine.d.ts +57 -1
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +117 -28
- package/dist/internal/slack-provision-client.js +1 -1
- package/dist/internal/workspace.d.ts +6 -2
- package/dist/internal/workspace.d.ts.map +1 -1
- package/dist/internal/workspace.js +10 -2
- package/dist/kv/memory-kv.d.ts +23 -0
- package/dist/kv/memory-kv.d.ts.map +1 -0
- package/dist/kv/memory-kv.js +103 -0
- package/dist/kv.d.ts +22 -0
- package/dist/kv.d.ts.map +1 -0
- package/dist/kv.js +20 -0
- package/dist/ledger/session-ledger.d.ts +204 -0
- package/dist/ledger/session-ledger.d.ts.map +1 -0
- package/dist/ledger/session-ledger.js +382 -0
- package/dist/ledger.d.ts +11 -0
- package/dist/ledger.d.ts.map +1 -0
- package/dist/ledger.js +9 -0
- package/dist/playground/assets/index-B3HBneZZ.js +85 -0
- package/dist/playground/assets/index-Bqk9nplh.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted.d.ts +25 -3
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +50 -2
- package/dist/storage-backends/file-kv.d.ts +5 -2
- package/dist/storage-backends/file-kv.d.ts.map +1 -1
- package/dist/storage-backends/file-kv.js +107 -7
- package/dist/storage.d.ts +60 -5
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +28 -4
- package/dist/types.d.ts +123 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +14 -0
- package/docs/README.md +10 -7
- package/docs/ab.md +2 -2
- package/docs/building-with-agents.md +1 -1
- package/docs/deployment.md +34 -11
- package/docs/evals.md +3 -3
- package/docs/example-agents/index.md +1 -1
- package/docs/guides/webhooks.md +87 -0
- package/docs/quickstart.md +7 -8
- package/docs/reference/cli.md +15 -6
- package/docs/reference/hooks.md +8 -2
- package/docs/storage.md +67 -7
- package/docs/troubleshooting.md +10 -2
- package/package.json +20 -7
- package/skills/create-agent/SKILL.md +1 -1
- package/src/bin/agent-serve.ts +27 -11
- package/src/channels/slack/attachments.ts +635 -0
- package/src/channels/slack/cursor-account.ts +8 -0
- package/src/channels/slack/dispatch.ts +121 -6
- package/src/channels/slack/inbound.ts +60 -0
- package/src/channels/slack/index.ts +1 -0
- package/src/channels/slack/manifest.ts +1 -0
- package/src/channels/slack/slack-channel.ts +7 -0
- package/src/channels/slack/types.ts +47 -1
- package/src/index.ts +9 -0
- package/src/internal/cli-ax.ts +25 -1
- package/src/internal/cli-deploy.ts +22 -4
- package/src/internal/cli-mcp.ts +4 -4
- package/src/internal/deploy-client.ts +1 -1
- package/src/internal/discovery.ts +42 -5
- package/src/internal/distribution.ts +3 -1
- package/src/internal/durable-session-store.ts +95 -0
- package/src/internal/hosting.ts +2 -2
- package/src/internal/init-project.ts +151 -2
- package/src/internal/ledger-serving.ts +240 -0
- package/src/internal/listen-port.ts +85 -0
- package/src/internal/playground/static.ts +111 -20
- package/src/internal/sdk-runner.ts +11 -1
- package/src/internal/server.ts +68 -61
- package/src/internal/session-engine.ts +192 -16
- package/src/internal/slack-provision-client.ts +1 -1
- package/src/internal/workspace.ts +14 -3
- package/src/kv/memory-kv.ts +99 -0
- package/src/kv.ts +27 -0
- package/src/ledger/session-ledger.ts +535 -0
- package/src/ledger.ts +29 -0
- package/src/storage-backends/cursor-hosted.ts +108 -3
- package/src/storage-backends/file-kv.ts +128 -12
- package/src/storage.ts +90 -6
- package/src/types.ts +130 -4
- package/dist/channels/slack/post-update-delivery.d.ts +0 -85
- package/dist/channels/slack/post-update-delivery.d.ts.map +0 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.D82_RVtF.js +0 -1
- package/dist/docs/assets/example-agents_index.md.DgGBwckv.js +0 -2
- package/dist/docs/assets/index.md.CmhptOmN.js +0 -24
- package/dist/docs/assets/troubleshooting.md.B5RVX_tL.js +0 -1
- package/dist/internal/json-dir-store.d.ts +0 -32
- package/dist/internal/json-dir-store.d.ts.map +0 -1
- package/dist/internal/persistence-coordinator.d.ts +0 -127
- package/dist/internal/persistence-coordinator.d.ts.map +0 -1
- package/dist/multi-tenant.d.ts +0 -80
- package/dist/multi-tenant.d.ts.map +0 -1
- package/dist/multi-tenant.js +0 -69
- package/dist/persistence.d.ts +0 -184
- package/dist/persistence.d.ts.map +0 -1
- package/dist/playground/assets/index-BRhBbnd4.css +0 -1
- package/dist/playground/assets/index-Bc1oFgFG.js +0 -85
- package/dist/storage-backends/postgres-kv.d.ts +0 -82
- package/dist/storage-backends/postgres-kv.d.ts.map +0 -1
- package/dist/storage-backends/postgres-kv.js +0 -185
- package/src/storage-backends/postgres-kv.ts +0 -253
- /package/dist/docs/assets/{ab.md.6cLOW7--.lean.js → ab.md.hdxsvX5M.lean.js} +0 -0
- /package/dist/docs/assets/{building-with-agents.md.txrcGU2B.lean.js → building-with-agents.md.PeZaZA1P.lean.js} +0 -0
- /package/dist/docs/assets/{evals.md.BQXI3rXy.lean.js → evals.md.qeoGgPw0.lean.js} +0 -0
- /package/dist/docs/assets/{example-agents_index.md.DgGBwckv.lean.js → example-agents_index.md.xmJ87d_3.lean.js} +0 -0
- /package/dist/docs/assets/{quickstart.md.C_b6ESpD.lean.js → quickstart.md.rIbfahJM.lean.js} +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory {@link HostKvCasApi} — the test/dev implementation of the
|
|
3
|
+
* interface module (`@cursor/july/kv`), exported at
|
|
4
|
+
* `@cursor/july/kv/memory`.
|
|
5
|
+
*
|
|
6
|
+
* The memory KV *is* the dev shim: tests and local runs exercise the
|
|
7
|
+
* same CAS coordination paths that hosted serving uses, not a mock of an
|
|
8
|
+
* RPC. Values are deep-copied on both write and
|
|
9
|
+
* read so callers can never observe (or cause) shared-reference mutation.
|
|
10
|
+
*/
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
/** Create an empty in-memory CAS-capable KV. */
|
|
21
|
+
export function createMemoryKv() {
|
|
22
|
+
const entries = new Map();
|
|
23
|
+
let versionCounter = 0;
|
|
24
|
+
const nextVersion = () => {
|
|
25
|
+
versionCounter += 1;
|
|
26
|
+
return `v${versionCounter}`;
|
|
27
|
+
};
|
|
28
|
+
const snapshot = (key) => {
|
|
29
|
+
const entry = entries.get(key);
|
|
30
|
+
if (entry === undefined) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
return { value: structuredClone(entry.value), version: entry.version };
|
|
34
|
+
};
|
|
35
|
+
return {
|
|
36
|
+
get(key) {
|
|
37
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
38
|
+
var _a;
|
|
39
|
+
return (_a = snapshot(key)) === null || _a === void 0 ? void 0 : _a.value;
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
put(key, value) {
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
+
entries.set(key, {
|
|
45
|
+
value: structuredClone(value),
|
|
46
|
+
version: nextVersion(),
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
delete(key) {
|
|
51
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
entries.delete(key);
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
getWithVersion(key) {
|
|
56
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
57
|
+
return snapshot(key);
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
putIfAbsent(key, value) {
|
|
61
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
62
|
+
if (entries.has(key)) {
|
|
63
|
+
return { ok: false, current: snapshot(key) };
|
|
64
|
+
}
|
|
65
|
+
const version = nextVersion();
|
|
66
|
+
entries.set(key, { value: structuredClone(value), version });
|
|
67
|
+
return { ok: true, version };
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
putIfVersion(key, value, expectedVersion) {
|
|
71
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
72
|
+
const entry = entries.get(key);
|
|
73
|
+
if (entry === undefined || entry.version !== expectedVersion) {
|
|
74
|
+
return { ok: false, current: snapshot(key) };
|
|
75
|
+
}
|
|
76
|
+
const version = nextVersion();
|
|
77
|
+
entries.set(key, { value: structuredClone(value), version });
|
|
78
|
+
return { ok: true, version };
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
listKeys(prefix) {
|
|
82
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
83
|
+
return [...entries.keys()].filter((key) => key.startsWith(prefix)).sort();
|
|
84
|
+
});
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* In-memory `cas` group for `defineStorage` — a complete conditional-write
|
|
90
|
+
* group for sinks whose plain methods are inert or live elsewhere (test
|
|
91
|
+
* fixtures, an off-hosting no-op sink). Non-durable and process-local by
|
|
92
|
+
* construction; a real deployment backend should implement CAS against
|
|
93
|
+
* its own store instead.
|
|
94
|
+
*/
|
|
95
|
+
export function memoryCasTable() {
|
|
96
|
+
const kv = createMemoryKv();
|
|
97
|
+
return {
|
|
98
|
+
getWithVersion: (key) => kv.getWithVersion(key),
|
|
99
|
+
putIfAbsent: (key, value) => kv.putIfAbsent(key, value),
|
|
100
|
+
putIfVersion: (key, value, expectedVersion) => kv.putIfVersion(key, value, expectedVersion),
|
|
101
|
+
listKeys: (prefix) => kv.listKeys(prefix),
|
|
102
|
+
};
|
|
103
|
+
}
|
package/dist/kv.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CAS-capable KV **interface** — `@cursor/july/kv`.
|
|
3
|
+
*
|
|
4
|
+
* This module is implementation-free on purpose: it is the contract a
|
|
5
|
+
* bring-your-own KV implements so coordination protocols (conditional
|
|
6
|
+
* writes are the substrate for the upcoming session ledger) can run on
|
|
7
|
+
* it. {@link HostKvCasApi} is the conditional-write superset of the plain
|
|
8
|
+
* {@link HostKvApi}; {@link supportsKvCas} is the runtime probe for
|
|
9
|
+
* stores of unknown provenance — a `defineStorage` backend declares CAS
|
|
10
|
+
* through its `cas` group instead, so it never needs probing.
|
|
11
|
+
*
|
|
12
|
+
* Implementations live elsewhere:
|
|
13
|
+
*
|
|
14
|
+
* - `@cursor/july/kv/memory` — `createMemoryKv`, the test/dev shim.
|
|
15
|
+
* - The storage backends implement the same operations as the `cas`
|
|
16
|
+
* group on `defineStorage` (see `StorageCasTable` in
|
|
17
|
+
* `@cursor/july/storage`): `fileKv` (single-process) and
|
|
18
|
+
* `cursorHostedStorage` (control-plane proxy). See `docs/storage.md`.
|
|
19
|
+
*/
|
|
20
|
+
export type { HostKvApi, HostKvCasApi, KvCasResult, KvVersionedEntry, } from "./types.js";
|
|
21
|
+
export { supportsKvCas } from "./types.js";
|
|
22
|
+
//# sourceMappingURL=kv.d.ts.map
|
package/dist/kv.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kv.d.ts","sourceRoot":"","sources":["../src/kv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,YAAY,EACV,SAAS,EACT,YAAY,EACZ,WAAW,EACX,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/kv.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CAS-capable KV **interface** — `@cursor/july/kv`.
|
|
3
|
+
*
|
|
4
|
+
* This module is implementation-free on purpose: it is the contract a
|
|
5
|
+
* bring-your-own KV implements so coordination protocols (conditional
|
|
6
|
+
* writes are the substrate for the upcoming session ledger) can run on
|
|
7
|
+
* it. {@link HostKvCasApi} is the conditional-write superset of the plain
|
|
8
|
+
* {@link HostKvApi}; {@link supportsKvCas} is the runtime probe for
|
|
9
|
+
* stores of unknown provenance — a `defineStorage` backend declares CAS
|
|
10
|
+
* through its `cas` group instead, so it never needs probing.
|
|
11
|
+
*
|
|
12
|
+
* Implementations live elsewhere:
|
|
13
|
+
*
|
|
14
|
+
* - `@cursor/july/kv/memory` — `createMemoryKv`, the test/dev shim.
|
|
15
|
+
* - The storage backends implement the same operations as the `cas`
|
|
16
|
+
* group on `defineStorage` (see `StorageCasTable` in
|
|
17
|
+
* `@cursor/july/storage`): `fileKv` (single-process) and
|
|
18
|
+
* `cursorHostedStorage` (control-plane proxy). See `docs/storage.md`.
|
|
19
|
+
*/
|
|
20
|
+
export { supportsKvCas } from "./types.js";
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session ledger — coordination only (no inbox).
|
|
3
|
+
*
|
|
4
|
+
* Two key families, driven with CAS over a {@link SessionLedgerKv};
|
|
5
|
+
* agents never touch these keys directly:
|
|
6
|
+
*
|
|
7
|
+
* ```
|
|
8
|
+
* session/<continuationKey> identity, created with put-if-absent
|
|
9
|
+
* ledger/<sessionId> head + lease — every mutation one CAS
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* The keys are deliberately bare: namespacing (per agent, per
|
|
13
|
+
* deployment) is not the ledger's concern. The store handle it is given
|
|
14
|
+
* must already be scoped — the engine applies the namespace exactly once
|
|
15
|
+
* where it constructs the handle (see `durable-session-store.ts`), the
|
|
16
|
+
* same boundary where `host.kv` gets its agent scoping.
|
|
17
|
+
*
|
|
18
|
+
* This is a coordination ledger: session identity, one writer per
|
|
19
|
+
* session (leases with generation fencing), and a fenced,
|
|
20
|
+
* ambiguity-safe commit sequence (`head`). It deliberately has **no
|
|
21
|
+
* durable inbox** — no pending list, no payload blobs, no append/drain,
|
|
22
|
+
* no janitor. An event that arrives while the lease is held waits
|
|
23
|
+
* *in-process* on the delivering pod; a crash loses that in-flight
|
|
24
|
+
* event exactly as resident serving does. What ledger mode adds over
|
|
25
|
+
* resident is cross-pod mutual exclusion, zombie fencing, and the
|
|
26
|
+
* committed head sequence. A dead pod needs no janitor: its lease
|
|
27
|
+
* simply expires (~30s) and the next delivery claims at generation+1.
|
|
28
|
+
*
|
|
29
|
+
* The commit is one CAS carrying the read version, the expected `head`,
|
|
30
|
+
* and the holder's `generation` — one committed transition per turn,
|
|
31
|
+
* atomic by construction. Commit always releases the lease: with no
|
|
32
|
+
* pending list there is nothing to keep it for.
|
|
33
|
+
*
|
|
34
|
+
* Clocks: lease expiry compares `expiresAt` against {@link
|
|
35
|
+
* SessionLedgerOptions.clock} (default `Date.now`). Self-hosted N-pod
|
|
36
|
+
* deployments accept NTP-synced pods as a documented requirement; a
|
|
37
|
+
* backend-clock primitive can replace the default without touching the
|
|
38
|
+
* protocol code.
|
|
39
|
+
*/
|
|
40
|
+
import type { HostKvCasApi } from "../types.js";
|
|
41
|
+
export declare const LEASE_TTL_MS = 30000;
|
|
42
|
+
export declare const HEARTBEAT_INTERVAL_MS = 10000;
|
|
43
|
+
/**
|
|
44
|
+
* Exactly the KV surface the coordination-only ledger uses. `listKeys`
|
|
45
|
+
* is deliberately absent: nothing here scans, so a store must not be
|
|
46
|
+
* rejected for lacking it.
|
|
47
|
+
*/
|
|
48
|
+
export type SessionLedgerKv = Pick<HostKvCasApi, "getWithVersion" | "putIfAbsent" | "putIfVersion">;
|
|
49
|
+
/** Runtime probe for {@link SessionLedgerKv} on stores of unknown shape. */
|
|
50
|
+
export declare function supportsSessionLedgerKv(kv: object): kv is SessionLedgerKv;
|
|
51
|
+
/** `session/<continuationKey>` value. Immutable after creation. */
|
|
52
|
+
export interface SessionIdentity {
|
|
53
|
+
sessionId: string;
|
|
54
|
+
sdkSessionRef: string | null;
|
|
55
|
+
createdAt: number;
|
|
56
|
+
}
|
|
57
|
+
export interface LedgerLease {
|
|
58
|
+
holder: string;
|
|
59
|
+
generation: number;
|
|
60
|
+
expiresAt: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* `ledger/<sessionId>` value: `{ sessionId, head, lease, generation,
|
|
64
|
+
* lastCommitId }`. `sessionId` lets a future scan address sessions
|
|
65
|
+
* without inverting digested key segments; `generation` is a monotonic
|
|
66
|
+
* acquisition counter that must survive lease release, or a zombie of a
|
|
67
|
+
* cleanly released lease could reuse its generation; `lastCommitId` is
|
|
68
|
+
* the ambiguous-commit recovery token.
|
|
69
|
+
*/
|
|
70
|
+
export interface LedgerSnapshot {
|
|
71
|
+
sessionId: string;
|
|
72
|
+
head: number;
|
|
73
|
+
lease: LedgerLease | null;
|
|
74
|
+
generation: number;
|
|
75
|
+
lastCommitId: string | null;
|
|
76
|
+
}
|
|
77
|
+
export type EnsureSessionResult = {
|
|
78
|
+
created: boolean;
|
|
79
|
+
session: SessionIdentity;
|
|
80
|
+
};
|
|
81
|
+
export type ClaimResult = {
|
|
82
|
+
claimed: true;
|
|
83
|
+
lease: LedgerLease;
|
|
84
|
+
head: number;
|
|
85
|
+
} | {
|
|
86
|
+
claimed: false;
|
|
87
|
+
reason: "held";
|
|
88
|
+
holder: string;
|
|
89
|
+
expiresAt: number;
|
|
90
|
+
};
|
|
91
|
+
export type HeartbeatResult = {
|
|
92
|
+
ok: true;
|
|
93
|
+
expiresAt: number;
|
|
94
|
+
} | {
|
|
95
|
+
ok: false;
|
|
96
|
+
reason: "not-found" | "fenced";
|
|
97
|
+
};
|
|
98
|
+
export interface CommitArgs {
|
|
99
|
+
/** The holder's lease generation (fences zombies). */
|
|
100
|
+
generation: number;
|
|
101
|
+
/** `head` observed at claim time (fences concurrent turns). */
|
|
102
|
+
expectedHead: number;
|
|
103
|
+
/** Unique per commit attempt; enables ambiguous-outcome recovery. */
|
|
104
|
+
commitId: string;
|
|
105
|
+
}
|
|
106
|
+
export interface CommitResult {
|
|
107
|
+
head: number;
|
|
108
|
+
/**
|
|
109
|
+
* Whether this holder's lease is gone — for the caller's purposes, not
|
|
110
|
+
* the record's: `true` also when the re-read of an ambiguous commit
|
|
111
|
+
* finds a *new claimant's* lease, since we no longer hold the session
|
|
112
|
+
* either way and continuing the turn loop would duplicate the new
|
|
113
|
+
* holder's work. On this coordination-only stage every commit
|
|
114
|
+
* releases, so this is always `true`; it exists so callers already
|
|
115
|
+
* branch on it before the inbox makes keep-the-lease outcomes real.
|
|
116
|
+
*/
|
|
117
|
+
leaseReleased: boolean;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* The turn was fenced: a stale generation, a moved head, or a missing
|
|
121
|
+
* ledger. The caller must abort the turn and discard warm state.
|
|
122
|
+
*/
|
|
123
|
+
export declare class LedgerFencedError extends Error {
|
|
124
|
+
constructor(message: string);
|
|
125
|
+
}
|
|
126
|
+
/** A CAS retry loop ran out of attempts (sustained contention or outage). */
|
|
127
|
+
export declare class LedgerCasExhaustedError extends Error {
|
|
128
|
+
constructor(operation: string, attempts: number);
|
|
129
|
+
}
|
|
130
|
+
export interface SessionLedgerOptions {
|
|
131
|
+
/** Already-scoped store handle; the ledger writes bare keys into it. */
|
|
132
|
+
kv: SessionLedgerKv;
|
|
133
|
+
/** Stable identity of this pod/process — the lease `holder`. */
|
|
134
|
+
podId: string;
|
|
135
|
+
/** Lease TTL (default {@link LEASE_TTL_MS}). */
|
|
136
|
+
leaseTtlMs?: number;
|
|
137
|
+
/** Time source for lease expiry (default `Date.now`). */
|
|
138
|
+
clock?: () => number;
|
|
139
|
+
/** Max attempts per CAS loop (default 16). */
|
|
140
|
+
maxCasAttempts?: number;
|
|
141
|
+
/**
|
|
142
|
+
* Wait between CAS retries. Default: immediate for the first retries,
|
|
143
|
+
* then a jittered exponential capped at 250ms.
|
|
144
|
+
*/
|
|
145
|
+
backoff?: (attempt: number) => Promise<void>;
|
|
146
|
+
/** Session id mint (default `ses_<24 hex>` like the session engine). */
|
|
147
|
+
newSessionId?: () => string;
|
|
148
|
+
}
|
|
149
|
+
/** Drives the `session/` and `ledger/` key families over a CAS KV. */
|
|
150
|
+
export declare class SessionLedger {
|
|
151
|
+
private readonly kv;
|
|
152
|
+
private readonly podId;
|
|
153
|
+
private readonly leaseTtlMs;
|
|
154
|
+
private readonly clock;
|
|
155
|
+
private readonly maxCasAttempts;
|
|
156
|
+
private readonly backoff;
|
|
157
|
+
private readonly mintSessionId;
|
|
158
|
+
constructor(options: SessionLedgerOptions);
|
|
159
|
+
private sessionKey;
|
|
160
|
+
private ledgerKey;
|
|
161
|
+
/**
|
|
162
|
+
* Create-or-read the session identity for a continuation key. The create
|
|
163
|
+
* race has one winner (put-if-absent); losers read the winner's identity.
|
|
164
|
+
*/
|
|
165
|
+
ensureSession(continuationKey: string, init?: {
|
|
166
|
+
sdkSessionRef?: string | null;
|
|
167
|
+
}): Promise<EnsureSessionResult>;
|
|
168
|
+
/**
|
|
169
|
+
* Try to take the session lease, creating the ledger record on first
|
|
170
|
+
* contact. Succeeds only when the lease is null or expired; the CAS
|
|
171
|
+
* bumps the acquisition generation, fencing every prior holder. A
|
|
172
|
+
* losing caller gets `reason: "held"` and decides whether to wait.
|
|
173
|
+
*/
|
|
174
|
+
claim(sessionId: string): Promise<ClaimResult>;
|
|
175
|
+
/**
|
|
176
|
+
* Extend the lease. Fails when the generation is no longer ours — the
|
|
177
|
+
* caller must abort the turn and discard warm state; the session has a
|
|
178
|
+
* new legitimate holder.
|
|
179
|
+
*/
|
|
180
|
+
heartbeat(sessionId: string, generation: number): Promise<HeartbeatResult>;
|
|
181
|
+
/**
|
|
182
|
+
* Commit one turn. The single CAS is the commit point: it bumps `head`,
|
|
183
|
+
* releases the lease, and records `commitId` — atomically.
|
|
184
|
+
*
|
|
185
|
+
* Ambiguous outcomes (the KV threw and we never saw the CAS result) are
|
|
186
|
+
* resolved by re-reading, never by blind-retrying: `head` advanced to
|
|
187
|
+
* `expectedHead + 1` with our `commitId` ⇒ our write landed, report
|
|
188
|
+
* success; `head` still at `expectedHead` with our lease ⇒ it did not,
|
|
189
|
+
* retry against the fresh version; anything else ⇒ fenced.
|
|
190
|
+
*/
|
|
191
|
+
commit(sessionId: string, args: CommitArgs): Promise<CommitResult>;
|
|
192
|
+
/**
|
|
193
|
+
* Release a held lease without committing — graceful shutdown, or a
|
|
194
|
+
* turn that failed before its commit. Fenced by generation: a stale
|
|
195
|
+
* holder's release is a no-op (the session has moved on). `head` and
|
|
196
|
+
* the acquisition counter are untouched, so prior holders stay fenced.
|
|
197
|
+
*/
|
|
198
|
+
release(sessionId: string, generation: number): Promise<{
|
|
199
|
+
released: boolean;
|
|
200
|
+
}>;
|
|
201
|
+
/** Parsed ledger value for one session, or `undefined` when never created. */
|
|
202
|
+
readLedger(sessionId: string): Promise<LedgerSnapshot | undefined>;
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=session-ledger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-ledger.d.ts","sourceRoot":"","sources":["../../src/ledger/session-ledger.ts"],"names":[],"mappings":"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"}
|