@sentropic/h2a-runtime 0.81.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/dist/account-pool.d.ts +168 -0
- package/dist/account-pool.d.ts.map +1 -0
- package/dist/account-pool.js +385 -0
- package/dist/account-pool.js.map +1 -0
- package/dist/agents-projection.d.ts +56 -0
- package/dist/agents-projection.d.ts.map +1 -0
- package/dist/agents-projection.js +82 -0
- package/dist/agents-projection.js.map +1 -0
- package/dist/attach.d.ts +75 -0
- package/dist/attach.d.ts.map +1 -0
- package/dist/attach.js +432 -0
- package/dist/attach.js.map +1 -0
- package/dist/auth-bundle.d.ts +21 -0
- package/dist/auth-bundle.d.ts.map +1 -0
- package/dist/auth-bundle.js +112 -0
- package/dist/auth-bundle.js.map +1 -0
- package/dist/auth-diagnostics.d.ts +18 -0
- package/dist/auth-diagnostics.d.ts.map +1 -0
- package/dist/auth-diagnostics.js +23 -0
- package/dist/auth-diagnostics.js.map +1 -0
- package/dist/auth-login.d.ts +9 -0
- package/dist/auth-login.d.ts.map +1 -0
- package/dist/auth-login.js +21 -0
- package/dist/auth-login.js.map +1 -0
- package/dist/auth-refresh.d.ts +32 -0
- package/dist/auth-refresh.d.ts.map +1 -0
- package/dist/auth-refresh.js +83 -0
- package/dist/auth-refresh.js.map +1 -0
- package/dist/auth-tools.d.ts +55 -0
- package/dist/auth-tools.d.ts.map +1 -0
- package/dist/auth-tools.js +163 -0
- package/dist/auth-tools.js.map +1 -0
- package/dist/browser-bridge-local.d.ts +27 -0
- package/dist/browser-bridge-local.d.ts.map +1 -0
- package/dist/browser-bridge-local.js +51 -0
- package/dist/browser-bridge-local.js.map +1 -0
- package/dist/browser.d.ts +53 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +61 -0
- package/dist/browser.js.map +1 -0
- package/dist/conductor-launch.d.ts +179 -0
- package/dist/conductor-launch.d.ts.map +1 -0
- package/dist/conductor-launch.js +414 -0
- package/dist/conductor-launch.js.map +1 -0
- package/dist/config.d.ts +182 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +334 -0
- package/dist/config.js.map +1 -0
- package/dist/conv-guard.d.ts +76 -0
- package/dist/conv-guard.d.ts.map +1 -0
- package/dist/conv-guard.js +131 -0
- package/dist/conv-guard.js.map +1 -0
- package/dist/convsync.d.ts +24 -0
- package/dist/convsync.d.ts.map +1 -0
- package/dist/convsync.js +108 -0
- package/dist/convsync.js.map +1 -0
- package/dist/cred-health.d.ts +96 -0
- package/dist/cred-health.d.ts.map +1 -0
- package/dist/cred-health.js +170 -0
- package/dist/cred-health.js.map +1 -0
- package/dist/delegate.d.ts +406 -0
- package/dist/delegate.d.ts.map +1 -0
- package/dist/delegate.js +739 -0
- package/dist/delegate.js.map +1 -0
- package/dist/enroll.d.ts +91 -0
- package/dist/enroll.d.ts.map +1 -0
- package/dist/enroll.js +248 -0
- package/dist/enroll.js.map +1 -0
- package/dist/fanout.d.ts +63 -0
- package/dist/fanout.d.ts.map +1 -0
- package/dist/fanout.js +115 -0
- package/dist/fanout.js.map +1 -0
- package/dist/forward.d.ts +66 -0
- package/dist/forward.d.ts.map +1 -0
- package/dist/forward.js +141 -0
- package/dist/forward.js.map +1 -0
- package/dist/gitdiff.d.ts +31 -0
- package/dist/gitdiff.d.ts.map +1 -0
- package/dist/gitdiff.js +133 -0
- package/dist/gitdiff.js.map +1 -0
- package/dist/h2a-bridge.d.ts +102 -0
- package/dist/h2a-bridge.d.ts.map +1 -0
- package/dist/h2a-bridge.js +333 -0
- package/dist/h2a-bridge.js.map +1 -0
- package/dist/h2a-jobs.d.ts +235 -0
- package/dist/h2a-jobs.d.ts.map +1 -0
- package/dist/h2a-jobs.js +388 -0
- package/dist/h2a-jobs.js.map +1 -0
- package/dist/h2a-ping.d.ts +38 -0
- package/dist/h2a-ping.d.ts.map +1 -0
- package/dist/h2a-ping.js +58 -0
- package/dist/h2a-ping.js.map +1 -0
- package/dist/index.d.ts +98 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5887 -0
- package/dist/index.js.map +1 -0
- package/dist/interactive-throttle.d.ts +164 -0
- package/dist/interactive-throttle.d.ts.map +1 -0
- package/dist/interactive-throttle.js +194 -0
- package/dist/interactive-throttle.js.map +1 -0
- package/dist/lineage-client.d.ts +77 -0
- package/dist/lineage-client.d.ts.map +1 -0
- package/dist/lineage-client.js +117 -0
- package/dist/lineage-client.js.map +1 -0
- package/dist/lineage-lease.d.ts +152 -0
- package/dist/lineage-lease.d.ts.map +1 -0
- package/dist/lineage-lease.js +303 -0
- package/dist/lineage-lease.js.map +1 -0
- package/dist/llm-gateway-runtime/accounts.d.ts +48 -0
- package/dist/llm-gateway-runtime/accounts.d.ts.map +1 -0
- package/dist/llm-gateway-runtime/accounts.js +226 -0
- package/dist/llm-gateway-runtime/accounts.js.map +1 -0
- package/dist/llm-gateway-runtime/index.d.ts +4 -0
- package/dist/llm-gateway-runtime/index.d.ts.map +1 -0
- package/dist/llm-gateway-runtime/index.js +58 -0
- package/dist/llm-gateway-runtime/index.js.map +1 -0
- package/dist/llm-gateway-runtime/model-catalog.d.ts +36 -0
- package/dist/llm-gateway-runtime/model-catalog.d.ts.map +1 -0
- package/dist/llm-gateway-runtime/model-catalog.js +146 -0
- package/dist/llm-gateway-runtime/model-catalog.js.map +1 -0
- package/dist/llm-gateway-runtime/proxy-anthropic.d.ts +3 -0
- package/dist/llm-gateway-runtime/proxy-anthropic.d.ts.map +1 -0
- package/dist/llm-gateway-runtime/proxy-anthropic.js +139 -0
- package/dist/llm-gateway-runtime/proxy-anthropic.js.map +1 -0
- package/dist/llm-gateway-runtime/proxy-openai.d.ts +117 -0
- package/dist/llm-gateway-runtime/proxy-openai.d.ts.map +1 -0
- package/dist/llm-gateway-runtime/proxy-openai.js +1132 -0
- package/dist/llm-gateway-runtime/proxy-openai.js.map +1 -0
- package/dist/llm-gateway-runtime/session-ledger.d.ts +32 -0
- package/dist/llm-gateway-runtime/session-ledger.d.ts.map +1 -0
- package/dist/llm-gateway-runtime/session-ledger.js +62 -0
- package/dist/llm-gateway-runtime/session-ledger.js.map +1 -0
- package/dist/llm-gateway-runtime/sticky.d.ts +40 -0
- package/dist/llm-gateway-runtime/sticky.d.ts.map +1 -0
- package/dist/llm-gateway-runtime/sticky.js +254 -0
- package/dist/llm-gateway-runtime/sticky.js.map +1 -0
- package/dist/llm-mesh.d.ts +102 -0
- package/dist/llm-mesh.d.ts.map +1 -0
- package/dist/llm-mesh.js +433 -0
- package/dist/llm-mesh.js.map +1 -0
- package/dist/migrate-candidates.d.ts +35 -0
- package/dist/migrate-candidates.d.ts.map +1 -0
- package/dist/migrate-candidates.js +128 -0
- package/dist/migrate-candidates.js.map +1 -0
- package/dist/migrate.d.ts +125 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +561 -0
- package/dist/migrate.js.map +1 -0
- package/dist/plugin-manifest.d.ts +143 -0
- package/dist/plugin-manifest.d.ts.map +1 -0
- package/dist/plugin-manifest.js +233 -0
- package/dist/plugin-manifest.js.map +1 -0
- package/dist/plugin.d.ts +274 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +919 -0
- package/dist/plugin.js.map +1 -0
- package/dist/pod-liveness.d.ts +51 -0
- package/dist/pod-liveness.d.ts.map +1 -0
- package/dist/pod-liveness.js +80 -0
- package/dist/pod-liveness.js.map +1 -0
- package/dist/profile-menu.d.ts +7 -0
- package/dist/profile-menu.d.ts.map +1 -0
- package/dist/profile-menu.js +52 -0
- package/dist/profile-menu.js.map +1 -0
- package/dist/profiles.d.ts +23 -0
- package/dist/profiles.d.ts.map +1 -0
- package/dist/profiles.js +66 -0
- package/dist/profiles.js.map +1 -0
- package/dist/protocol-local.d.ts +27 -0
- package/dist/protocol-local.d.ts.map +1 -0
- package/dist/protocol-local.js +12 -0
- package/dist/protocol-local.js.map +1 -0
- package/dist/pty.d.ts +26 -0
- package/dist/pty.d.ts.map +1 -0
- package/dist/pty.js +45 -0
- package/dist/pty.js.map +1 -0
- package/dist/readiness.d.ts +38 -0
- package/dist/readiness.d.ts.map +1 -0
- package/dist/readiness.js +169 -0
- package/dist/readiness.js.map +1 -0
- package/dist/registry.d.ts +258 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +570 -0
- package/dist/registry.js.map +1 -0
- package/dist/relaunch.d.ts +52 -0
- package/dist/relaunch.d.ts.map +1 -0
- package/dist/relaunch.js +76 -0
- package/dist/relaunch.js.map +1 -0
- package/dist/restore.d.ts +165 -0
- package/dist/restore.d.ts.map +1 -0
- package/dist/restore.js +530 -0
- package/dist/restore.js.map +1 -0
- package/dist/run.d.ts +29 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +206 -0
- package/dist/run.js.map +1 -0
- package/dist/secrets.d.ts +25 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +98 -0
- package/dist/secrets.js.map +1 -0
- package/dist/session-restore.d.ts +26 -0
- package/dist/session-restore.d.ts.map +1 -0
- package/dist/session-restore.js +122 -0
- package/dist/session-restore.js.map +1 -0
- package/dist/skills-sync.d.ts +126 -0
- package/dist/skills-sync.d.ts.map +1 -0
- package/dist/skills-sync.js +255 -0
- package/dist/skills-sync.js.map +1 -0
- package/dist/smoke.d.ts +23 -0
- package/dist/smoke.d.ts.map +1 -0
- package/dist/smoke.js +138 -0
- package/dist/smoke.js.map +1 -0
- package/dist/soft-refresh.d.ts +107 -0
- package/dist/soft-refresh.d.ts.map +1 -0
- package/dist/soft-refresh.js +426 -0
- package/dist/soft-refresh.js.map +1 -0
- package/dist/sync-status.d.ts +22 -0
- package/dist/sync-status.d.ts.map +1 -0
- package/dist/sync-status.js +41 -0
- package/dist/sync-status.js.map +1 -0
- package/dist/sync.d.ts +77 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +302 -0
- package/dist/sync.js.map +1 -0
- package/dist/throttle-signatures.d.ts +43 -0
- package/dist/throttle-signatures.d.ts.map +1 -0
- package/dist/throttle-signatures.js +116 -0
- package/dist/throttle-signatures.js.map +1 -0
- package/dist/tmux.d.ts +286 -0
- package/dist/tmux.d.ts.map +1 -0
- package/dist/tmux.js +970 -0
- package/dist/tmux.js.map +1 -0
- package/dist/tunnel.d.ts +25 -0
- package/dist/tunnel.d.ts.map +1 -0
- package/dist/tunnel.js +127 -0
- package/dist/tunnel.js.map +1 -0
- package/dist/workspace-merge.d.ts +17 -0
- package/dist/workspace-merge.d.ts.map +1 -0
- package/dist/workspace-merge.js +153 -0
- package/dist/workspace-merge.js.map +1 -0
- package/dist/workspace-sync-incremental.d.ts +64 -0
- package/dist/workspace-sync-incremental.d.ts.map +1 -0
- package/dist/workspace-sync-incremental.js +199 -0
- package/dist/workspace-sync-incremental.js.map +1 -0
- package/dist/workspace-sync.d.ts +3 -0
- package/dist/workspace-sync.d.ts.map +1 -0
- package/dist/workspace-sync.js +187 -0
- package/dist/workspace-sync.js.map +1 -0
- package/dist/workspace.d.ts +70 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +173 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lineage-lease.ts — Phase A0a
|
|
3
|
+
*
|
|
4
|
+
* Pure module: lineage identity + lease/epoch/fencing.
|
|
5
|
+
* No pods, no sync, no secrets, no kubectl. Only node:fs / node:path / node:crypto.
|
|
6
|
+
*
|
|
7
|
+
* Invariants
|
|
8
|
+
* ----------
|
|
9
|
+
* - Every mutating lease operation verifies epoch === expectedEpoch.
|
|
10
|
+
* A stale epoch is rejected — no exception, typed error return.
|
|
11
|
+
* - Write-rename atomicity: write to <file>.tmp then renameSync to <file>.
|
|
12
|
+
* Atomicity relies on POSIX rename (best-effort on NFS).
|
|
13
|
+
* - No external dependencies.
|
|
14
|
+
*
|
|
15
|
+
* Root path
|
|
16
|
+
* ---------
|
|
17
|
+
* All files live under `root` (default: process.cwd()).
|
|
18
|
+
* Leases: <root>/.remote/leases/<lineageId>.json
|
|
19
|
+
* Lineages: <root>/.remote/lineages/<lineageId>.json
|
|
20
|
+
*/
|
|
21
|
+
/** Opaque lineage identity: `lin_<uuidv7-style>`. Struck once, persisted, derived from nothing. */
|
|
22
|
+
export type LineageId = `lin_${string}`;
|
|
23
|
+
/**
|
|
24
|
+
* Full lineage record persisted in `.remote/lineages/<id>.json`.
|
|
25
|
+
* One file per lineage — supports multiple sessions / fanout on the same workspace.
|
|
26
|
+
*/
|
|
27
|
+
export interface LineageRecord {
|
|
28
|
+
lineage: LineageId;
|
|
29
|
+
profile: string;
|
|
30
|
+
kind: "local" | "remote";
|
|
31
|
+
incarnation: {
|
|
32
|
+
local: {
|
|
33
|
+
tmux: string;
|
|
34
|
+
pid: number;
|
|
35
|
+
} | null;
|
|
36
|
+
remote: {
|
|
37
|
+
sessionId: string;
|
|
38
|
+
} | null;
|
|
39
|
+
};
|
|
40
|
+
/** ws:<hex> values accumulated over the lineage's lifetime (one per ws move) */
|
|
41
|
+
wsHistory: string[];
|
|
42
|
+
createdAt: string;
|
|
43
|
+
updatedAt: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Lease record persisted in `.remote/leases/<lineageId>.json`.
|
|
47
|
+
* `epoch` is the fencing token: every mutation must present the current epoch.
|
|
48
|
+
*/
|
|
49
|
+
export interface LineageLease {
|
|
50
|
+
lineageId: LineageId;
|
|
51
|
+
/** Monotone fencing token — incremented on handoff, rejected when stale. */
|
|
52
|
+
epoch: number;
|
|
53
|
+
/** Instance id of the current holder, e.g. "claude:remote:181cda7ac333". */
|
|
54
|
+
holder: string;
|
|
55
|
+
/** Tmux slug (local) or sessionId (remote). */
|
|
56
|
+
incarnationId: string;
|
|
57
|
+
location: "local" | "remote";
|
|
58
|
+
/** ISO timestamp after which this lease is considered expired. */
|
|
59
|
+
expiresAt: string;
|
|
60
|
+
}
|
|
61
|
+
export type AcquireResult = LineageLease | {
|
|
62
|
+
error: "conflict";
|
|
63
|
+
current: LineageLease;
|
|
64
|
+
};
|
|
65
|
+
export type RenewResult = LineageLease | {
|
|
66
|
+
error: "stale_epoch" | "not_holder";
|
|
67
|
+
};
|
|
68
|
+
export type HandoffResult = LineageLease | {
|
|
69
|
+
error: "stale_epoch" | "not_holder";
|
|
70
|
+
};
|
|
71
|
+
export type ReleaseResult = void | {
|
|
72
|
+
error: "stale_epoch" | "not_holder";
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Read the current lease for a lineage without mutating it.
|
|
76
|
+
*/
|
|
77
|
+
export declare function readLease(lineageId: LineageId, root?: string): LineageLease | null;
|
|
78
|
+
/**
|
|
79
|
+
* Returns true when the lease's `expiresAt` is in the past.
|
|
80
|
+
*/
|
|
81
|
+
export declare function isLeaseExpired(lease: LineageLease): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Acquire (or take over an expired) lease.
|
|
84
|
+
*
|
|
85
|
+
* - If no lease exists → creates one at epoch 0.
|
|
86
|
+
* - If the existing lease is expired → takes over, keeps epoch (no increment).
|
|
87
|
+
* - If the existing lease is held and not expired → returns { error: "conflict" }.
|
|
88
|
+
*/
|
|
89
|
+
export declare function acquireLease(lineageId: LineageId, holder: string, incarnationId: string, location: "local" | "remote", ttlMs: number, root?: string): AcquireResult;
|
|
90
|
+
/**
|
|
91
|
+
* Renew a held lease (push expiry forward).
|
|
92
|
+
*
|
|
93
|
+
* Rejects with `stale_epoch` when expectedEpoch !== current epoch.
|
|
94
|
+
* Rejects with `not_holder` when holder doesn't match.
|
|
95
|
+
*/
|
|
96
|
+
export declare function renewLease(lineageId: LineageId, holder: string, expectedEpoch: number, ttlMs: number, root?: string): RenewResult;
|
|
97
|
+
/**
|
|
98
|
+
* Hand off the lease from one holder to another.
|
|
99
|
+
*
|
|
100
|
+
* Increments epoch (+1) on success — the old epoch is now invalid for any
|
|
101
|
+
* mutation (fencing: the old holder becomes a zombie and will be rejected on
|
|
102
|
+
* any future renew/handoff/release attempt).
|
|
103
|
+
*
|
|
104
|
+
* Rejects with `stale_epoch` when expectedEpoch !== current epoch.
|
|
105
|
+
* Rejects with `not_holder` when fromHolder doesn't match.
|
|
106
|
+
*/
|
|
107
|
+
export declare function handoffLease(lineageId: LineageId, fromHolder: string, expectedEpoch: number, toHolder: string, toIncarnationId: string, toLocation: "local" | "remote", ttlMs: number, root?: string): HandoffResult;
|
|
108
|
+
/**
|
|
109
|
+
* Release (delete) a held lease.
|
|
110
|
+
*
|
|
111
|
+
* Rejects with `stale_epoch` when expectedEpoch !== current epoch.
|
|
112
|
+
* Rejects with `not_holder` when holder doesn't match.
|
|
113
|
+
* No-ops if the lease file doesn't exist (idempotent on double-release).
|
|
114
|
+
*/
|
|
115
|
+
export declare function releaseLease(lineageId: LineageId, holder: string, expectedEpoch: number, root?: string): ReleaseResult;
|
|
116
|
+
/**
|
|
117
|
+
* Create and persist a new LineageRecord.
|
|
118
|
+
* Does NOT create a lease — that is a separate step.
|
|
119
|
+
*/
|
|
120
|
+
export declare function createLineage(profile: string, kind: "local" | "remote", wsHex: string, root?: string): LineageRecord;
|
|
121
|
+
/**
|
|
122
|
+
* Read a lineage record by id.
|
|
123
|
+
*/
|
|
124
|
+
export declare function readLineage(lineageId: LineageId, root?: string): LineageRecord | null;
|
|
125
|
+
/**
|
|
126
|
+
* Patch a lineage record. `updatedAt` is always refreshed.
|
|
127
|
+
* Throws if the lineage doesn't exist.
|
|
128
|
+
*/
|
|
129
|
+
export declare function updateLineage(lineageId: LineageId, patch: Partial<Omit<LineageRecord, "lineage" | "createdAt">>, root?: string): LineageRecord;
|
|
130
|
+
/**
|
|
131
|
+
* List all lineage records under <root>/.remote/lineages/.
|
|
132
|
+
* Returns an empty array if the directory doesn't exist yet.
|
|
133
|
+
*/
|
|
134
|
+
export declare function listLineages(root?: string): LineageRecord[];
|
|
135
|
+
/**
|
|
136
|
+
* Suspend the local incarnation: write a sentinel file that the agent checks
|
|
137
|
+
* before starting a new turn. Does NOT kill the process.
|
|
138
|
+
*
|
|
139
|
+
* File path: <root>/.remote/lineages/<lineageId>.suspended
|
|
140
|
+
*/
|
|
141
|
+
export declare function suspendLocalIncarnation(lineageId: LineageId, root?: string): void;
|
|
142
|
+
/**
|
|
143
|
+
* Returns true when the sentinel file exists (incarnation is suspended).
|
|
144
|
+
*/
|
|
145
|
+
export declare function isIncarnationSuspended(lineageId: LineageId, root?: string): boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Resume the local incarnation: remove the sentinel file.
|
|
148
|
+
* No-op if the file doesn't exist.
|
|
149
|
+
*/
|
|
150
|
+
export declare function resumeLocalIncarnation(lineageId: LineageId, root?: string): void;
|
|
151
|
+
export { computeDurableWorkspaceId, normalizeRootCommits, } from "./conductor-launch.js";
|
|
152
|
+
//# sourceMappingURL=lineage-lease.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lineage-lease.d.ts","sourceRoot":"","sources":["../src/lineage-lease.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lineage-lease.ts — Phase A0a
|
|
3
|
+
*
|
|
4
|
+
* Pure module: lineage identity + lease/epoch/fencing.
|
|
5
|
+
* No pods, no sync, no secrets, no kubectl. Only node:fs / node:path / node:crypto.
|
|
6
|
+
*
|
|
7
|
+
* Invariants
|
|
8
|
+
* ----------
|
|
9
|
+
* - Every mutating lease operation verifies epoch === expectedEpoch.
|
|
10
|
+
* A stale epoch is rejected — no exception, typed error return.
|
|
11
|
+
* - Write-rename atomicity: write to <file>.tmp then renameSync to <file>.
|
|
12
|
+
* Atomicity relies on POSIX rename (best-effort on NFS).
|
|
13
|
+
* - No external dependencies.
|
|
14
|
+
*
|
|
15
|
+
* Root path
|
|
16
|
+
* ---------
|
|
17
|
+
* All files live under `root` (default: process.cwd()).
|
|
18
|
+
* Leases: <root>/.remote/leases/<lineageId>.json
|
|
19
|
+
* Lineages: <root>/.remote/lineages/<lineageId>.json
|
|
20
|
+
*/
|
|
21
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
22
|
+
import { mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
|
|
23
|
+
import { join } from "node:path";
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Filesystem helpers
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
function leasesDir(root) {
|
|
28
|
+
return join(root, ".remote", "leases");
|
|
29
|
+
}
|
|
30
|
+
function lineagesDir(root) {
|
|
31
|
+
return join(root, ".remote", "lineages");
|
|
32
|
+
}
|
|
33
|
+
function leaseFile(root, lineageId) {
|
|
34
|
+
return join(leasesDir(root), `${lineageId}.json`);
|
|
35
|
+
}
|
|
36
|
+
function lineageFile(root, lineageId) {
|
|
37
|
+
return join(lineagesDir(root), `${lineageId}.json`);
|
|
38
|
+
}
|
|
39
|
+
function ensureDir(dir) {
|
|
40
|
+
mkdirSync(dir, { recursive: true });
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Atomic write: serialize to JSON, write to <path>.tmp, then rename to <path>.
|
|
44
|
+
* Relies on POSIX rename semantics (best-effort on NFS).
|
|
45
|
+
*/
|
|
46
|
+
function atomicWrite(filePath, data) {
|
|
47
|
+
const tmp = `${filePath}.tmp`;
|
|
48
|
+
writeFileSync(tmp, JSON.stringify(data, null, 2), "utf8");
|
|
49
|
+
renameSync(tmp, filePath);
|
|
50
|
+
}
|
|
51
|
+
function readJson(filePath) {
|
|
52
|
+
try {
|
|
53
|
+
const raw = readFileSync(filePath, "utf8");
|
|
54
|
+
return JSON.parse(raw);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
// Lease operations
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
/**
|
|
64
|
+
* Read the current lease for a lineage without mutating it.
|
|
65
|
+
*/
|
|
66
|
+
export function readLease(lineageId, root = process.cwd()) {
|
|
67
|
+
return readJson(leaseFile(root, lineageId));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Returns true when the lease's `expiresAt` is in the past.
|
|
71
|
+
*/
|
|
72
|
+
export function isLeaseExpired(lease) {
|
|
73
|
+
return new Date(lease.expiresAt).getTime() <= Date.now();
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Acquire (or take over an expired) lease.
|
|
77
|
+
*
|
|
78
|
+
* - If no lease exists → creates one at epoch 0.
|
|
79
|
+
* - If the existing lease is expired → takes over, keeps epoch (no increment).
|
|
80
|
+
* - If the existing lease is held and not expired → returns { error: "conflict" }.
|
|
81
|
+
*/
|
|
82
|
+
export function acquireLease(lineageId, holder, incarnationId, location, ttlMs, root = process.cwd()) {
|
|
83
|
+
ensureDir(leasesDir(root));
|
|
84
|
+
const existing = readLease(lineageId, root);
|
|
85
|
+
if (existing !== null && !isLeaseExpired(existing)) {
|
|
86
|
+
return { error: "conflict", current: existing };
|
|
87
|
+
}
|
|
88
|
+
const epoch = existing?.epoch ?? 0;
|
|
89
|
+
const lease = {
|
|
90
|
+
lineageId,
|
|
91
|
+
epoch,
|
|
92
|
+
holder,
|
|
93
|
+
incarnationId,
|
|
94
|
+
location,
|
|
95
|
+
expiresAt: new Date(Date.now() + ttlMs).toISOString(),
|
|
96
|
+
};
|
|
97
|
+
atomicWrite(leaseFile(root, lineageId), lease);
|
|
98
|
+
return lease;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Renew a held lease (push expiry forward).
|
|
102
|
+
*
|
|
103
|
+
* Rejects with `stale_epoch` when expectedEpoch !== current epoch.
|
|
104
|
+
* Rejects with `not_holder` when holder doesn't match.
|
|
105
|
+
*/
|
|
106
|
+
export function renewLease(lineageId, holder, expectedEpoch, ttlMs, root = process.cwd()) {
|
|
107
|
+
const current = readLease(lineageId, root);
|
|
108
|
+
if (current === null) {
|
|
109
|
+
return { error: "stale_epoch" };
|
|
110
|
+
}
|
|
111
|
+
if (current.epoch !== expectedEpoch) {
|
|
112
|
+
return { error: "stale_epoch" };
|
|
113
|
+
}
|
|
114
|
+
if (current.holder !== holder) {
|
|
115
|
+
return { error: "not_holder" };
|
|
116
|
+
}
|
|
117
|
+
const renewed = {
|
|
118
|
+
...current,
|
|
119
|
+
expiresAt: new Date(Date.now() + ttlMs).toISOString(),
|
|
120
|
+
};
|
|
121
|
+
atomicWrite(leaseFile(root, lineageId), renewed);
|
|
122
|
+
return renewed;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Hand off the lease from one holder to another.
|
|
126
|
+
*
|
|
127
|
+
* Increments epoch (+1) on success — the old epoch is now invalid for any
|
|
128
|
+
* mutation (fencing: the old holder becomes a zombie and will be rejected on
|
|
129
|
+
* any future renew/handoff/release attempt).
|
|
130
|
+
*
|
|
131
|
+
* Rejects with `stale_epoch` when expectedEpoch !== current epoch.
|
|
132
|
+
* Rejects with `not_holder` when fromHolder doesn't match.
|
|
133
|
+
*/
|
|
134
|
+
export function handoffLease(lineageId, fromHolder, expectedEpoch, toHolder, toIncarnationId, toLocation, ttlMs, root = process.cwd()) {
|
|
135
|
+
const current = readLease(lineageId, root);
|
|
136
|
+
if (current === null) {
|
|
137
|
+
return { error: "stale_epoch" };
|
|
138
|
+
}
|
|
139
|
+
if (current.epoch !== expectedEpoch) {
|
|
140
|
+
return { error: "stale_epoch" };
|
|
141
|
+
}
|
|
142
|
+
if (current.holder !== fromHolder) {
|
|
143
|
+
return { error: "not_holder" };
|
|
144
|
+
}
|
|
145
|
+
const next = {
|
|
146
|
+
lineageId,
|
|
147
|
+
epoch: current.epoch + 1,
|
|
148
|
+
holder: toHolder,
|
|
149
|
+
incarnationId: toIncarnationId,
|
|
150
|
+
location: toLocation,
|
|
151
|
+
expiresAt: new Date(Date.now() + ttlMs).toISOString(),
|
|
152
|
+
};
|
|
153
|
+
atomicWrite(leaseFile(root, lineageId), next);
|
|
154
|
+
return next;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Release (delete) a held lease.
|
|
158
|
+
*
|
|
159
|
+
* Rejects with `stale_epoch` when expectedEpoch !== current epoch.
|
|
160
|
+
* Rejects with `not_holder` when holder doesn't match.
|
|
161
|
+
* No-ops if the lease file doesn't exist (idempotent on double-release).
|
|
162
|
+
*/
|
|
163
|
+
export function releaseLease(lineageId, holder, expectedEpoch, root = process.cwd()) {
|
|
164
|
+
const current = readLease(lineageId, root);
|
|
165
|
+
if (current === null) {
|
|
166
|
+
// Already gone — idempotent.
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (current.epoch !== expectedEpoch) {
|
|
170
|
+
return { error: "stale_epoch" };
|
|
171
|
+
}
|
|
172
|
+
if (current.holder !== holder) {
|
|
173
|
+
return { error: "not_holder" };
|
|
174
|
+
}
|
|
175
|
+
rmSync(leaseFile(root, lineageId), { force: true });
|
|
176
|
+
}
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
// Lineage record CRUD
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
/**
|
|
181
|
+
* Generate a fresh `lin_<uuid>` lineage id. Uses crypto.randomUUID() (v4),
|
|
182
|
+
* prefixed with "lin_".
|
|
183
|
+
*/
|
|
184
|
+
function newLineageId() {
|
|
185
|
+
return `lin_${randomUUID().replace(/-/g, "")}`;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Create and persist a new LineageRecord.
|
|
189
|
+
* Does NOT create a lease — that is a separate step.
|
|
190
|
+
*/
|
|
191
|
+
export function createLineage(profile, kind, wsHex, root = process.cwd()) {
|
|
192
|
+
ensureDir(lineagesDir(root));
|
|
193
|
+
const now = new Date().toISOString();
|
|
194
|
+
const record = {
|
|
195
|
+
lineage: newLineageId(),
|
|
196
|
+
profile,
|
|
197
|
+
kind,
|
|
198
|
+
incarnation: {
|
|
199
|
+
local: null,
|
|
200
|
+
remote: null,
|
|
201
|
+
},
|
|
202
|
+
wsHistory: [wsHex],
|
|
203
|
+
createdAt: now,
|
|
204
|
+
updatedAt: now,
|
|
205
|
+
};
|
|
206
|
+
atomicWrite(lineageFile(root, record.lineage), record);
|
|
207
|
+
return record;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Read a lineage record by id.
|
|
211
|
+
*/
|
|
212
|
+
export function readLineage(lineageId, root = process.cwd()) {
|
|
213
|
+
return readJson(lineageFile(root, lineageId));
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Patch a lineage record. `updatedAt` is always refreshed.
|
|
217
|
+
* Throws if the lineage doesn't exist.
|
|
218
|
+
*/
|
|
219
|
+
export function updateLineage(lineageId, patch, root = process.cwd()) {
|
|
220
|
+
const existing = readLineage(lineageId, root);
|
|
221
|
+
if (existing === null) {
|
|
222
|
+
throw new Error(`lineage not found: ${lineageId}`);
|
|
223
|
+
}
|
|
224
|
+
const updated = {
|
|
225
|
+
...existing,
|
|
226
|
+
...patch,
|
|
227
|
+
lineage: existing.lineage, // immutable
|
|
228
|
+
createdAt: existing.createdAt, // immutable
|
|
229
|
+
updatedAt: new Date().toISOString(),
|
|
230
|
+
};
|
|
231
|
+
atomicWrite(lineageFile(root, lineageId), updated);
|
|
232
|
+
return updated;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* List all lineage records under <root>/.remote/lineages/.
|
|
236
|
+
* Returns an empty array if the directory doesn't exist yet.
|
|
237
|
+
*/
|
|
238
|
+
export function listLineages(root = process.cwd()) {
|
|
239
|
+
const dir = lineagesDir(root);
|
|
240
|
+
let entries;
|
|
241
|
+
try {
|
|
242
|
+
entries = readdirSync(dir);
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
return [];
|
|
246
|
+
}
|
|
247
|
+
const results = [];
|
|
248
|
+
for (const entry of entries) {
|
|
249
|
+
if (!entry.endsWith(".json"))
|
|
250
|
+
continue;
|
|
251
|
+
const rec = readJson(join(dir, entry));
|
|
252
|
+
if (rec !== null) {
|
|
253
|
+
results.push(rec);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return results;
|
|
257
|
+
}
|
|
258
|
+
// ---------------------------------------------------------------------------
|
|
259
|
+
// Incarnation suspension — Phase A0c
|
|
260
|
+
// ---------------------------------------------------------------------------
|
|
261
|
+
/**
|
|
262
|
+
* Path of the sentinel file that signals a local incarnation is suspended.
|
|
263
|
+
* Written by `suspendLocalIncarnation`, checked by `isIncarnationSuspended`,
|
|
264
|
+
* removed by `resumeLocalIncarnation`.
|
|
265
|
+
*/
|
|
266
|
+
function suspendedFile(lineageId, root) {
|
|
267
|
+
return join(lineagesDir(root), `${lineageId}.suspended`);
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Suspend the local incarnation: write a sentinel file that the agent checks
|
|
271
|
+
* before starting a new turn. Does NOT kill the process.
|
|
272
|
+
*
|
|
273
|
+
* File path: <root>/.remote/lineages/<lineageId>.suspended
|
|
274
|
+
*/
|
|
275
|
+
export function suspendLocalIncarnation(lineageId, root = process.cwd()) {
|
|
276
|
+
ensureDir(lineagesDir(root));
|
|
277
|
+
writeFileSync(suspendedFile(lineageId, root), new Date().toISOString(), "utf8");
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Returns true when the sentinel file exists (incarnation is suspended).
|
|
281
|
+
*/
|
|
282
|
+
export function isIncarnationSuspended(lineageId, root = process.cwd()) {
|
|
283
|
+
try {
|
|
284
|
+
// Just check existence — readFileSync throws on ENOENT.
|
|
285
|
+
readFileSync(suspendedFile(lineageId, root));
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Resume the local incarnation: remove the sentinel file.
|
|
294
|
+
* No-op if the file doesn't exist.
|
|
295
|
+
*/
|
|
296
|
+
export function resumeLocalIncarnation(lineageId, root = process.cwd()) {
|
|
297
|
+
rmSync(suspendedFile(lineageId, root), { force: true });
|
|
298
|
+
}
|
|
299
|
+
// ---------------------------------------------------------------------------
|
|
300
|
+
// Re-export ws:<hex> utility (avoid duplication)
|
|
301
|
+
// ---------------------------------------------------------------------------
|
|
302
|
+
export { computeDurableWorkspaceId, normalizeRootCommits, } from "./conductor-launch.js";
|
|
303
|
+
//# sourceMappingURL=lineage-lease.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lineage-lease.js","sourceRoot":"","sources":["../src/lineage-lease.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type ModelCatalogEntry, type RoutingTarget } from "./model-catalog.js";
|
|
2
|
+
export interface AccountDescriptor {
|
|
3
|
+
id: string;
|
|
4
|
+
provider: string;
|
|
5
|
+
label: string;
|
|
6
|
+
token: string;
|
|
7
|
+
authType?: "api-key" | "bearer";
|
|
8
|
+
refreshToken?: string;
|
|
9
|
+
expiresAt?: string;
|
|
10
|
+
modelIds?: string[];
|
|
11
|
+
models?: string[];
|
|
12
|
+
status?: "active" | "disabled";
|
|
13
|
+
}
|
|
14
|
+
export interface PublicAccountDescriptor {
|
|
15
|
+
id: string;
|
|
16
|
+
provider: string;
|
|
17
|
+
label: string;
|
|
18
|
+
authType?: AccountDescriptor["authType"];
|
|
19
|
+
expiresAt?: string;
|
|
20
|
+
modelIds: string[];
|
|
21
|
+
status: "active" | "disabled";
|
|
22
|
+
}
|
|
23
|
+
export declare function getAccounts(): AccountDescriptor[];
|
|
24
|
+
export declare function publicAccountDescriptor(account: AccountDescriptor): PublicAccountDescriptor;
|
|
25
|
+
export declare function listAccountDescriptors(): PublicAccountDescriptor[];
|
|
26
|
+
export type AccountProviderFamily = "anthropic" | "openai" | "other";
|
|
27
|
+
export declare function providerFamily(provider: string): AccountProviderFamily;
|
|
28
|
+
export declare const DEFAULT_QUOTA_EXHAUSTION_MS: number;
|
|
29
|
+
export declare function markAccountExhausted(accountId: string, reason?: string, windowMs?: number, nowMs?: number): void;
|
|
30
|
+
export declare function isAccountExhausted(accountId: string, nowMs?: number): boolean;
|
|
31
|
+
export declare function accountExhaustionReason(accountId: string): string | undefined;
|
|
32
|
+
export declare function resetAccountsCache(): void;
|
|
33
|
+
export declare function accountSupportsRoute(account: AccountDescriptor, route: RoutingTarget): boolean;
|
|
34
|
+
export declare function eligibleAccountsForRoute(route?: RoutingTarget): AccountDescriptor[];
|
|
35
|
+
export declare function selectAccount(): AccountDescriptor;
|
|
36
|
+
export declare function selectAccountForRoute(route: RoutingTarget): AccountDescriptor;
|
|
37
|
+
export declare function findAccount(accountId: string): AccountDescriptor | undefined;
|
|
38
|
+
export declare function listRoutableModels(): ModelCatalogEntry[];
|
|
39
|
+
export declare function selectFallbackAccount(exhaustedAccountId: string, nowMs?: number): AccountDescriptor | undefined;
|
|
40
|
+
/** Update the in-memory token for an account (after OAuth refresh). */
|
|
41
|
+
export declare function updateAccountToken(accountId: string, newToken: string, expiresAt?: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* Refresh the OAuth access token for an account using its refresh_token.
|
|
44
|
+
* Updates the in-memory account on success. No-op if no refresh_token.
|
|
45
|
+
* Returns the new token, or null if refresh is not applicable.
|
|
46
|
+
*/
|
|
47
|
+
export declare function refreshOAuthToken(accountId: string): Promise<string | null>;
|
|
48
|
+
//# sourceMappingURL=accounts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../src/llm-gateway-runtime/accounts.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;CAChC;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,iBAAiB,CAAC,UAAU,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,QAAQ,GAAG,UAAU,CAAC;CAC/B;AA6BD,wBAAgB,WAAW,IAAI,iBAAiB,EAAE,CAGjD;AAUD,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,iBAAiB,GACzB,uBAAuB,CAUzB;AAED,wBAAgB,sBAAsB,IAAI,uBAAuB,EAAE,CAElE;AAED,MAAM,MAAM,qBAAqB,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAErE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,qBAAqB,CAKtE;AAED,eAAO,MAAM,2BAA2B,QAAqB,CAAC;AAoB9D,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,EACf,QAAQ,GAAE,MAAkC,EAC5C,KAAK,GAAE,MAAmB,GACzB,IAAI,CAMN;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,MAAmB,GACzB,OAAO,CAQT;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE7E;AAGD,wBAAgB,kBAAkB,IAAI,IAAI,CAKzC;AAKD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,iBAAiB,EAC1B,KAAK,EAAE,aAAa,GACnB,OAAO,CAiBT;AAED,wBAAgB,wBAAwB,CACtC,KAAK,CAAC,EAAE,aAAa,GACpB,iBAAiB,EAAE,CAOrB;AAED,wBAAgB,aAAa,IAAI,iBAAiB,CAOjD;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,GAAG,iBAAiB,CAY7E;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAE5E;AAED,wBAAgB,kBAAkB,IAAI,iBAAiB,EAAE,CASxD;AAED,wBAAgB,qBAAqB,CACnC,kBAAkB,EAAE,MAAM,EAC1B,KAAK,GAAE,MAAmB,GACzB,iBAAiB,GAAG,SAAS,CAqB/B;AAED,uEAAuE;AACvE,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,IAAI,CAON;AA0BD;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6CxB"}
|