@sema-agent/server 1.310.0 → 1.312.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/auth-keys.d.ts +14 -0
- package/dist/auth-keys.js +31 -0
- package/dist/brain.d.ts +1 -1
- package/dist/capabilities/center-prompts.d.ts +3 -28
- package/dist/capabilities/center-prompts.js +2 -107
- package/dist/capabilities/select-environment-tool.d.ts +1 -1
- package/dist/config-lkg.js +1 -1
- package/dist/config-types.d.ts +306 -0
- package/dist/config-types.js +2 -0
- package/dist/config.d.ts +4 -305
- package/dist/config.js +1 -1
- package/dist/env-facts.d.ts +1 -1
- package/dist/hooks/hook-llm.d.ts +1 -1
- package/dist/http/server.d.ts +5 -85
- package/dist/http/wire-types.d.ts +84 -0
- package/dist/http/wire-types.js +2 -0
- package/dist/images/manifest.d.ts +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/main.js +134 -143
- package/dist/per-task-image.d.ts +2 -2
- package/dist/plugins/file-run-store.d.ts +1 -1
- package/dist/plugins/local-session-store.d.ts +2 -2
- package/dist/plugins/local-session-store.js +1 -1
- package/dist/plugins/memory-run-store.d.ts +1 -1
- package/dist/plugins/pg-approval-store.js +1 -27
- package/dist/plugins/pg-checkpoint-store.js +1 -5
- package/dist/plugins/pg-image-bake.d.ts +2 -2
- package/dist/plugins/pg-image-bake.js +2 -54
- package/dist/plugins/pg-image-index.d.ts +2 -2
- package/dist/plugins/pg-image-index.js +1 -44
- package/dist/plugins/pg-pool.d.ts +1 -1
- package/dist/plugins/pg-run-store.d.ts +1 -1
- package/dist/plugins/pg-run-store.js +2 -16
- package/dist/plugins/pg-session-storage.d.ts +2 -2
- package/dist/plugins/pg-session-storage.js +3 -7
- package/dist/plugins/pg-tool-result-store.js +1 -1
- package/dist/plugins/session-store.d.ts +1 -1
- package/dist/plugins/sql-escape.d.ts +2 -0
- package/dist/plugins/sql-escape.js +4 -0
- package/dist/plugins/sql-row-helpers.d.ts +7 -0
- package/dist/plugins/sql-row-helpers.js +43 -0
- package/dist/plugins/store-backend.d.ts +1 -1
- package/dist/plugins/store-contracts.d.ts +205 -0
- package/dist/plugins/store-contracts.js +61 -0
- package/dist/plugins/tidb-approval-store.d.ts +1 -0
- package/dist/plugins/tidb-approval-store.js +2 -11
- package/dist/plugins/tidb-checkpoint-store.js +1 -5
- package/dist/plugins/tidb-image-bake.d.ts +3 -64
- package/dist/plugins/tidb-image-bake.js +3 -54
- package/dist/plugins/tidb-image-index.d.ts +3 -52
- package/dist/plugins/tidb-image-index.js +2 -43
- package/dist/plugins/tidb-pool.d.ts +1 -1
- package/dist/plugins/tidb-run-store.d.ts +2 -32
- package/dist/plugins/tidb-run-store.js +2 -16
- package/dist/plugins/tidb-session-storage.js +1 -5
- package/dist/plugins/tidb-session-store.d.ts +2 -2
- package/dist/plugins/tidb-session-store.js +2 -2
- package/dist/plugins/tidb-tool-result-store.d.ts +1 -1
- package/dist/plugins/tidb-tool-result-store.js +2 -3
- package/dist/prompts-domain-validate.d.ts +29 -0
- package/dist/prompts-domain-validate.js +109 -0
- package/dist/security.d.ts +6 -16
- package/dist/security.js +1 -30
- package/dist/sema-registry.d.ts +1 -1
- package/dist/session-sync-kernel.d.ts +47 -0
- package/dist/session-sync-kernel.js +47 -0
- package/dist/session-sync.d.ts +3 -45
- package/dist/session-sync.js +2 -46
- package/dist/trace/artifacts.d.ts +1 -1
- package/dist/trace/project.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1,49 +1,8 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { mapImageRow as mapRow, } from "./store-contracts.js";
|
|
3
|
+
export { mapImageRow as mapRow } from "./store-contracts.js";
|
|
2
4
|
const MAX_LIMIT = 200;
|
|
3
5
|
const DEFAULT_LIMIT = 50;
|
|
4
|
-
function asJson(v, fallback) {
|
|
5
|
-
if (v === null || v === undefined)
|
|
6
|
-
return fallback;
|
|
7
|
-
if (typeof v === "string") {
|
|
8
|
-
try {
|
|
9
|
-
return JSON.parse(v);
|
|
10
|
-
}
|
|
11
|
-
catch {
|
|
12
|
-
return fallback;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
return v;
|
|
16
|
-
}
|
|
17
|
-
function iso(v) {
|
|
18
|
-
if (v === null || v === undefined)
|
|
19
|
-
return null;
|
|
20
|
-
return v instanceof Date ? v.toISOString() : new Date(v).toISOString();
|
|
21
|
-
}
|
|
22
|
-
function mapRow(r) {
|
|
23
|
-
return {
|
|
24
|
-
id: r.id,
|
|
25
|
-
profile: r.profile,
|
|
26
|
-
bands: asJson(r.bands, []),
|
|
27
|
-
repo: r.repo,
|
|
28
|
-
tag: r.tag,
|
|
29
|
-
digest: r.digest,
|
|
30
|
-
toolchainVersions: asJson(r.toolchain_versions, {}),
|
|
31
|
-
capabilities: asJson(r.capabilities, {}),
|
|
32
|
-
podContract: asJson(r.pod_contract, {}),
|
|
33
|
-
sizeBytes: r.size_bytes === null ? null : Number(r.size_bytes),
|
|
34
|
-
status: r.status,
|
|
35
|
-
visibility: r.visibility,
|
|
36
|
-
tenantId: r.tenant_id,
|
|
37
|
-
manifestSha: r.manifest_sha,
|
|
38
|
-
recipeGitSha: r.recipe_git_sha,
|
|
39
|
-
generatorVersion: r.generator_version,
|
|
40
|
-
buildDate: iso(r.build_date),
|
|
41
|
-
supersedes: r.supersedes,
|
|
42
|
-
signed: !!r.signed,
|
|
43
|
-
createdAt: iso(r.created_at) ?? new Date(0).toISOString(),
|
|
44
|
-
updatedAt: iso(r.updated_at) ?? new Date(0).toISOString(),
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
6
|
function visibilityClause(viewer) {
|
|
48
7
|
if (viewer.operator)
|
|
49
8
|
return { sql: "1=1", params: [] };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import mysql from "mysql2/promise";
|
|
2
2
|
import type { Pool, PoolConnection } from "mysql2/promise";
|
|
3
|
-
import type { ServiceConfig } from "../config.js";
|
|
3
|
+
import type { ServiceConfig } from "../config-types.js";
|
|
4
4
|
export declare function tidbPoolOptions(tidb: NonNullable<ServiceConfig["tidb"]>): mysql.PoolOptions;
|
|
5
5
|
export declare function createTidbPool(config: ServiceConfig): Pool;
|
|
6
6
|
export declare const SCHEMA_STATEMENTS: readonly string[];
|
|
@@ -1,38 +1,8 @@
|
|
|
1
1
|
import type { TaskResult, TaskStatus } from "@sema-agent/core";
|
|
2
2
|
import { type UsageRow } from "../usage-analytics.js";
|
|
3
3
|
import type { Pool } from "mysql2/promise";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
sessionId: string;
|
|
7
|
-
owner: string | null;
|
|
8
|
-
status: "running" | TaskStatus;
|
|
9
|
-
result: TaskResult | null;
|
|
10
|
-
error: string | null;
|
|
11
|
-
errorCode: string | null;
|
|
12
|
-
jobId: string | null;
|
|
13
|
-
source: string | null;
|
|
14
|
-
instanceId: string | null;
|
|
15
|
-
objectivePreview: string | null;
|
|
16
|
-
createdAt: string;
|
|
17
|
-
updatedAt: string;
|
|
18
|
-
}
|
|
19
|
-
export interface SessionSummary {
|
|
20
|
-
sessionId: string;
|
|
21
|
-
owner: string | null;
|
|
22
|
-
lastActivityAt: string;
|
|
23
|
-
firstActivityAt: string;
|
|
24
|
-
runCount: number;
|
|
25
|
-
objectivePreview: string | null;
|
|
26
|
-
lastStatus: string;
|
|
27
|
-
lastRunId: string | null;
|
|
28
|
-
title: string | null;
|
|
29
|
-
}
|
|
30
|
-
export interface RunEvent {
|
|
31
|
-
seq: number;
|
|
32
|
-
type: string;
|
|
33
|
-
data: unknown;
|
|
34
|
-
ts: string;
|
|
35
|
-
}
|
|
4
|
+
import type { RunRecord, SessionSummary, RunEvent } from "./store-contracts.js";
|
|
5
|
+
export type { RunRecord, SessionSummary, RunEvent } from "./store-contracts.js";
|
|
36
6
|
export declare class TiDBRunStore {
|
|
37
7
|
private readonly pool;
|
|
38
8
|
constructor(pool: Pool);
|
|
@@ -1,23 +1,9 @@
|
|
|
1
1
|
import { projectUsageStats, USAGE_SCAN_LIMIT } from "../usage-analytics.js";
|
|
2
|
-
import { escapeLike } from "./
|
|
3
|
-
|
|
4
|
-
if (v == null)
|
|
5
|
-
return null;
|
|
6
|
-
if (typeof v !== "string")
|
|
7
|
-
return v;
|
|
8
|
-
try {
|
|
9
|
-
return JSON.parse(v);
|
|
10
|
-
}
|
|
11
|
-
catch {
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
2
|
+
import { escapeLike } from "./sql-escape.js";
|
|
3
|
+
import { parseJsonLenient as parseJson, toIso as iso } from "./sql-row-helpers.js";
|
|
15
4
|
function isDupKey(err) {
|
|
16
5
|
return Boolean(err) && err.code === "ER_DUP_ENTRY";
|
|
17
6
|
}
|
|
18
|
-
function iso(v) {
|
|
19
|
-
return v instanceof Date ? v.toISOString() : String(v);
|
|
20
|
-
}
|
|
21
7
|
export class TiDBRunStore {
|
|
22
8
|
pool;
|
|
23
9
|
constructor(pool) {
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { emitLeafAdvance } from "../session-leaf-bus.js";
|
|
2
2
|
import { BaseSessionStorage, SessionError, leafIdAfterEntry, normalizePromptEpoch, } from "@sema-agent/core";
|
|
3
|
+
import { toIso } from "./sql-row-helpers.js";
|
|
3
4
|
function isDupKey(err) {
|
|
4
5
|
return Boolean(err) && err.code === "ER_DUP_ENTRY";
|
|
5
6
|
}
|
|
6
|
-
function toIso(v) {
|
|
7
|
-
if (v instanceof Date)
|
|
8
|
-
return v.toISOString();
|
|
9
|
-
return String(v);
|
|
10
|
-
}
|
|
11
7
|
export class TiDBSessionStorage extends BaseSessionStorage {
|
|
12
8
|
pool;
|
|
13
9
|
sessionId;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type AcquiredSession, type SessionStore, type SessionTreeEntry } from "@sema-agent/core";
|
|
2
2
|
import type { Pool } from "mysql2/promise";
|
|
3
|
-
import type { SessionSummary } from "./
|
|
4
|
-
import { type StagingHandle } from "../session-sync.js";
|
|
3
|
+
import type { SessionSummary } from "./store-contracts.js";
|
|
4
|
+
import { type StagingHandle } from "../session-sync-kernel.js";
|
|
5
5
|
export declare class TiDBSessionStore implements SessionStore {
|
|
6
6
|
private readonly pool;
|
|
7
7
|
private readonly pending;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { StoredSession, SessionError, uuidv7, validateEntriesForImport, leafIdAfterEntry } from "@sema-agent/core";
|
|
2
2
|
import { TiDBSessionStorage } from "./tidb-session-storage.js";
|
|
3
|
-
import { escapeLike } from "./
|
|
4
|
-
import { classifySyncRelationshipByIds, SyncConflictError, stagingIdFor, STAGING_ID_MARKER, } from "../session-sync.js";
|
|
3
|
+
import { escapeLike } from "./sql-escape.js";
|
|
4
|
+
import { classifySyncRelationshipByIds, SyncConflictError, stagingIdFor, STAGING_ID_MARKER, } from "../session-sync-kernel.js";
|
|
5
5
|
const STAGING_GC_GRACE_MS = 3_600_000;
|
|
6
6
|
export class TiDBSessionStore {
|
|
7
7
|
pool;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ToolResultStore, ToolResultSlice } from "@sema-agent/core";
|
|
2
2
|
import type { Pool } from "mysql2/promise";
|
|
3
|
+
export { escapeLike } from "./sql-escape.js";
|
|
3
4
|
export declare class TiDBToolResultStore implements ToolResultStore {
|
|
4
5
|
private readonly pool;
|
|
5
6
|
constructor(pool: Pool);
|
|
@@ -11,5 +12,4 @@ export declare class TiDBToolResultStore implements ToolResultStore {
|
|
|
11
12
|
reapOlderThan(cutoffMs: number): Promise<number>;
|
|
12
13
|
deleteBySession(sessionId: string): Promise<number>;
|
|
13
14
|
}
|
|
14
|
-
export declare function escapeLike(s: string): string;
|
|
15
15
|
//# sourceMappingURL=tidb-tool-result-store.d.ts.map
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { escapeLike } from "./sql-escape.js";
|
|
2
|
+
export { escapeLike } from "./sql-escape.js";
|
|
1
3
|
export class TiDBToolResultStore {
|
|
2
4
|
pool;
|
|
3
5
|
constructor(pool) {
|
|
@@ -35,7 +37,4 @@ export class TiDBToolResultStore {
|
|
|
35
37
|
return res.affectedRows;
|
|
36
38
|
}
|
|
37
39
|
}
|
|
38
|
-
export function escapeLike(s) {
|
|
39
|
-
return s.replace(/[\\%_]/g, (ch) => `\\${ch}`);
|
|
40
|
-
}
|
|
41
40
|
//# sourceMappingURL=tidb-tool-result-store.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type PromptTextDeclaration, type PublishedPromptArtifactEnvelope } from "@sema-agent/core";
|
|
2
|
+
export interface EffectiveCenterPrompts {
|
|
3
|
+
packId: string;
|
|
4
|
+
contentDigest: string;
|
|
5
|
+
sections: PromptTextDeclaration[];
|
|
6
|
+
scenarioOverrides?: Record<string, PromptTextDeclaration[]>;
|
|
7
|
+
}
|
|
8
|
+
export declare function validateCenterPrompts(raw: unknown): {
|
|
9
|
+
ok: true;
|
|
10
|
+
value: EffectiveCenterPrompts;
|
|
11
|
+
} | {
|
|
12
|
+
ok: false;
|
|
13
|
+
error: string;
|
|
14
|
+
};
|
|
15
|
+
export declare const CORE_ENGINE_VERSION: string;
|
|
16
|
+
export interface PromptsDomainFaces {
|
|
17
|
+
declarations?: EffectiveCenterPrompts;
|
|
18
|
+
catalog?: PublishedPromptArtifactEnvelope;
|
|
19
|
+
identity: string;
|
|
20
|
+
axes: Array<"declarations" | "catalog">;
|
|
21
|
+
}
|
|
22
|
+
export declare function validatePromptsDomain(raw: unknown): {
|
|
23
|
+
ok: true;
|
|
24
|
+
value: PromptsDomainFaces;
|
|
25
|
+
} | {
|
|
26
|
+
ok: false;
|
|
27
|
+
error: string;
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=prompts-domain-validate.d.ts.map
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { verifyPromptArtifact } from "@sema-agent/core";
|
|
6
|
+
const ID_RE = /^[a-z0-9][a-z0-9/._-]*$/;
|
|
7
|
+
const SLOTS = new Set(["identity", "scenario", "behavior"]);
|
|
8
|
+
const HASH_RE = /^sha256:[0-9a-f]{64}$/;
|
|
9
|
+
function declarationIssue(d, where) {
|
|
10
|
+
if (d === null || typeof d !== "object")
|
|
11
|
+
return `${where}: declaration is not an object`;
|
|
12
|
+
const o = d;
|
|
13
|
+
if (typeof o.id !== "string" || o.id.length === 0 || o.id.length > 128 || !ID_RE.test(o.id))
|
|
14
|
+
return `${where}: bad id`;
|
|
15
|
+
if (o.id.startsWith("core/"))
|
|
16
|
+
return `${where}: id in the reserved core/ namespace`;
|
|
17
|
+
if (typeof o.slot !== "string" || !SLOTS.has(o.slot))
|
|
18
|
+
return `${where}: bad slot`;
|
|
19
|
+
if (typeof o.text !== "string" || o.text.length === 0)
|
|
20
|
+
return `${where}: text must be a non-empty string`;
|
|
21
|
+
if (typeof o.contentHash !== "string" || !HASH_RE.test(o.contentHash))
|
|
22
|
+
return `${where}: contentHash is required (sha256:<64hex> — the epoch declaration axis needs it for byte-level change detection)`;
|
|
23
|
+
const expected = `sha256:${createHash("sha256").update(o.text).digest("hex")}`;
|
|
24
|
+
if (o.contentHash !== expected)
|
|
25
|
+
return `${where}: contentHash does not match sha256(text) — stale or tampered declaration`;
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
export function validateCenterPrompts(raw) {
|
|
29
|
+
if (raw === null || typeof raw !== "object")
|
|
30
|
+
return { ok: false, error: "prompts is not an object" };
|
|
31
|
+
const p = raw;
|
|
32
|
+
if (typeof p.packId !== "string" || !/^center:[0-9a-f]{12}$/.test(p.packId))
|
|
33
|
+
return { ok: false, error: "bad packId form (center:<digest12>)" };
|
|
34
|
+
if (typeof p.contentDigest !== "string" || !HASH_RE.test(p.contentDigest))
|
|
35
|
+
return { ok: false, error: "bad contentDigest form" };
|
|
36
|
+
const arrayIssue = (decls, where) => {
|
|
37
|
+
if (!Array.isArray(decls))
|
|
38
|
+
return `${where} is not an array`;
|
|
39
|
+
if (decls.length === 0)
|
|
40
|
+
return `${where} is empty (an empty replacement set is not a v1 semantic — omit the key instead)`;
|
|
41
|
+
const seen = new Set();
|
|
42
|
+
for (let i = 0; i < decls.length; i++) {
|
|
43
|
+
const issue = declarationIssue(decls[i], `${where}[${i}]`);
|
|
44
|
+
if (issue)
|
|
45
|
+
return issue;
|
|
46
|
+
const id = decls[i].id;
|
|
47
|
+
if (seen.has(id))
|
|
48
|
+
return `${where}[${i}]: duplicate id "${id}" (core composer throws on duplicates)`;
|
|
49
|
+
seen.add(id);
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
};
|
|
53
|
+
const sectionsIssue = arrayIssue(p.sections, "sections");
|
|
54
|
+
if (sectionsIssue)
|
|
55
|
+
return { ok: false, error: sectionsIssue };
|
|
56
|
+
if (p.scenarioOverrides !== undefined) {
|
|
57
|
+
if (p.scenarioOverrides === null || typeof p.scenarioOverrides !== "object" || Array.isArray(p.scenarioOverrides)) {
|
|
58
|
+
return { ok: false, error: "scenarioOverrides is not an object" };
|
|
59
|
+
}
|
|
60
|
+
for (const [name, decls] of Object.entries(p.scenarioOverrides)) {
|
|
61
|
+
const issue = arrayIssue(decls, `scenarioOverrides[${name}]`);
|
|
62
|
+
if (issue)
|
|
63
|
+
return { ok: false, error: issue };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { ok: true, value: raw };
|
|
67
|
+
}
|
|
68
|
+
export const CORE_ENGINE_VERSION = (() => {
|
|
69
|
+
try {
|
|
70
|
+
const entry = createRequire(import.meta.url).resolve("@sema-agent/core");
|
|
71
|
+
return JSON.parse(readFileSync(join(dirname(entry), "..", "package.json"), "utf8")).version ?? "0.0.0";
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return "0.0.0";
|
|
75
|
+
}
|
|
76
|
+
})();
|
|
77
|
+
export function validatePromptsDomain(raw) {
|
|
78
|
+
if (raw === null || typeof raw !== "object")
|
|
79
|
+
return { ok: false, error: "prompts is not an object" };
|
|
80
|
+
const w = raw;
|
|
81
|
+
if (w.schemaVersion === undefined) {
|
|
82
|
+
const legacy = validateCenterPrompts(raw);
|
|
83
|
+
if (!legacy.ok)
|
|
84
|
+
return legacy;
|
|
85
|
+
return { ok: true, value: { declarations: legacy.value, identity: `${legacy.value.contentDigest}+-`, axes: ["declarations"] } };
|
|
86
|
+
}
|
|
87
|
+
if (w.schemaVersion !== 1)
|
|
88
|
+
return { ok: false, error: `unsupported prompts schemaVersion ${String(w.schemaVersion)}` };
|
|
89
|
+
if (w.declarations === undefined && w.catalog === undefined)
|
|
90
|
+
return { ok: false, error: "dual-axis prompts carries neither axis (at least one of declarations|catalog required)" };
|
|
91
|
+
const value = { identity: "", axes: [] };
|
|
92
|
+
if (w.declarations !== undefined) {
|
|
93
|
+
const d = validateCenterPrompts(w.declarations);
|
|
94
|
+
if (!d.ok)
|
|
95
|
+
return { ok: false, error: `declarations axis: ${d.error}` };
|
|
96
|
+
value.declarations = d.value;
|
|
97
|
+
value.axes.push("declarations");
|
|
98
|
+
}
|
|
99
|
+
if (w.catalog !== undefined) {
|
|
100
|
+
const c = verifyPromptArtifact(w.catalog, { engineVersion: CORE_ENGINE_VERSION });
|
|
101
|
+
if (!c.ok)
|
|
102
|
+
return { ok: false, error: `catalog axis: ${c.code}: ${c.reason}` };
|
|
103
|
+
value.catalog = w.catalog;
|
|
104
|
+
value.axes.push("catalog");
|
|
105
|
+
}
|
|
106
|
+
value.identity = `${value.declarations?.contentDigest ?? "-"}+${value.catalog?.artifact.artifactDigest ?? "-"}`;
|
|
107
|
+
return { ok: true, value };
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=prompts-domain-validate.js.map
|
package/dist/security.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { IncomingMessage } from "node:http";
|
|
2
2
|
import { FileMemoryEngineBackend, type SessionStore, type SessionTreeEntry } from "@sema-agent/core";
|
|
3
|
-
import type { ServiceConfig } from "./config.js";
|
|
4
|
-
import type { TaskRequestBody } from "./http/
|
|
5
|
-
import type { StagingHandle } from "./session-sync.js";
|
|
3
|
+
import type { ServiceConfig } from "./config-types.js";
|
|
4
|
+
import type { TaskRequestBody } from "./http/wire-types.js";
|
|
5
|
+
import type { StagingHandle } from "./session-sync-kernel.js";
|
|
6
|
+
import type { ApprovalHmacKey, PrincipalJwtKey } from "./auth-keys.js";
|
|
7
|
+
export { parseApprovalHmacKeys, parsePrincipalJwks } from "./auth-keys.js";
|
|
8
|
+
export type { ApprovalHmacKey, PrincipalJwtKey } from "./auth-keys.js";
|
|
6
9
|
export interface SessionListItem {
|
|
7
10
|
sessionId: string;
|
|
8
11
|
owner: string | null;
|
|
@@ -92,12 +95,6 @@ export declare function memorySpecForRequest(scope: string | undefined, memoryWr
|
|
|
92
95
|
writeScope?: string | null;
|
|
93
96
|
scopeContract?: "v2";
|
|
94
97
|
} | undefined;
|
|
95
|
-
export interface ApprovalHmacKey {
|
|
96
|
-
kid: string;
|
|
97
|
-
key: string;
|
|
98
|
-
status?: "active" | "retiring";
|
|
99
|
-
}
|
|
100
|
-
export declare function parseApprovalHmacKeys(raw: string | undefined): ApprovalHmacKey[];
|
|
101
98
|
export declare function approvalHmacMessage(env: {
|
|
102
99
|
sessionId: string;
|
|
103
100
|
boundCallId?: string | null;
|
|
@@ -113,13 +110,6 @@ export declare function verifyApprovalHmac(env: {
|
|
|
113
110
|
decision: string;
|
|
114
111
|
reason?: string | null;
|
|
115
112
|
}, mac: string, kid: string | undefined, keys: ApprovalHmacKey[]): boolean;
|
|
116
|
-
export interface PrincipalJwtKey {
|
|
117
|
-
kid: string;
|
|
118
|
-
alg: "EdDSA" | "RS256" | "ES256";
|
|
119
|
-
key: string;
|
|
120
|
-
status?: "active" | "retiring";
|
|
121
|
-
}
|
|
122
|
-
export declare function parsePrincipalJwks(raw: string | undefined): PrincipalJwtKey[];
|
|
123
113
|
export declare function verifyPrincipalJwt(token: string, keys: PrincipalJwtKey[], expect: {
|
|
124
114
|
iss: string;
|
|
125
115
|
aud: string;
|
package/dist/security.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createHash, createHmac, createPublicKey, timingSafeEqual, verify as cry
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { uuidv7, FileMemoryEngineBackend, resolveMemoryEngineRoot, deriveControlPlaneDir, formatUserScope, formatProjScope } from "@sema-agent/core";
|
|
4
4
|
import { PROJECT_ID_REGEX } from "@sema-agent/registry-core";
|
|
5
|
+
export { parseApprovalHmacKeys, parsePrincipalJwks } from "./auth-keys.js";
|
|
5
6
|
const UUIDV7_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
6
7
|
export function isUuidV7(s) {
|
|
7
8
|
return UUIDV7_RE.test(s);
|
|
@@ -162,19 +163,6 @@ export function memorySpecForRequest(scope, memoryWrite, defaultScopes) {
|
|
|
162
163
|
const v2 = isV2(scope) || extras.some(isV2) ? { scopeContract: "v2" } : {};
|
|
163
164
|
return memoryWrite === false ? { scope, ...layered, writeScope: null, ...v2 } : { scope, ...layered, ...v2 };
|
|
164
165
|
}
|
|
165
|
-
export function parseApprovalHmacKeys(raw) {
|
|
166
|
-
if (!raw)
|
|
167
|
-
return [];
|
|
168
|
-
try {
|
|
169
|
-
const v = JSON.parse(raw);
|
|
170
|
-
if (!Array.isArray(v))
|
|
171
|
-
return [];
|
|
172
|
-
return v.filter((k) => !!k && typeof k.kid === "string" && typeof k.key === "string");
|
|
173
|
-
}
|
|
174
|
-
catch {
|
|
175
|
-
return [];
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
166
|
export function approvalHmacMessage(env) {
|
|
179
167
|
return JSON.stringify([env.sessionId, env.boundCallId ?? null, env.boundInputHash ?? null, env.decision, env.reason ?? null]);
|
|
180
168
|
}
|
|
@@ -200,23 +188,6 @@ export function verifyApprovalHmac(env, mac, kid, keys) {
|
|
|
200
188
|
}
|
|
201
189
|
return false;
|
|
202
190
|
}
|
|
203
|
-
export function parsePrincipalJwks(raw) {
|
|
204
|
-
if (!raw)
|
|
205
|
-
return [];
|
|
206
|
-
const ALGS = new Set(["EdDSA", "RS256", "ES256"]);
|
|
207
|
-
try {
|
|
208
|
-
const v = JSON.parse(raw);
|
|
209
|
-
if (!Array.isArray(v))
|
|
210
|
-
return [];
|
|
211
|
-
return v.filter((k) => {
|
|
212
|
-
const e = k;
|
|
213
|
-
return !!e && typeof e.kid === "string" && typeof e.key === "string" && typeof e.alg === "string" && ALGS.has(e.alg);
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
catch {
|
|
217
|
-
return [];
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
191
|
function b64urlToBuf(s) {
|
|
221
192
|
return Buffer.from(s, "base64url");
|
|
222
193
|
}
|
package/dist/sema-registry.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { McpServerSpec } from "@sema-agent/core";
|
|
2
2
|
import { type EntitlementRuntimeCaps } from "@sema-agent/registry-core";
|
|
3
|
-
import type { ScopedMcpServer, ServiceConfig } from "./config.js";
|
|
3
|
+
import type { ScopedMcpServer, ServiceConfig } from "./config-types.js";
|
|
4
4
|
import { type SealedKeyOpener } from "./sealed-key.js";
|
|
5
5
|
import type { Autonomy, CommandRule } from "./runtime-governance.js";
|
|
6
6
|
import type { Logger } from "./observability/logger.js";
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { SessionTreeEntry } from "@sema-agent/core";
|
|
2
|
+
export interface StagingHandle {
|
|
3
|
+
readonly stagingId: string;
|
|
4
|
+
readonly realSessionId: string;
|
|
5
|
+
appendBatch(entries: SessionTreeEntry[]): Promise<void>;
|
|
6
|
+
commit(owner: string | null, opts?: {
|
|
7
|
+
resolution?: "overwrite-dst";
|
|
8
|
+
}): Promise<{
|
|
9
|
+
relation: SyncRelation["relation"];
|
|
10
|
+
}>;
|
|
11
|
+
abort(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export type ImportStagingStore = {
|
|
14
|
+
beginImportStaging(realSessionId: string, token: string): StagingHandle;
|
|
15
|
+
sweepStagingSessions?(): Promise<number>;
|
|
16
|
+
};
|
|
17
|
+
export declare function stagingIdFor(realSessionId: string, token: string): string;
|
|
18
|
+
export declare const STAGING_ID_MARKER = "#stg-";
|
|
19
|
+
export declare function realIdOfStaging(stagingId: string): string | null;
|
|
20
|
+
export type SyncRelation = {
|
|
21
|
+
relation: "fresh";
|
|
22
|
+
} | {
|
|
23
|
+
relation: "identical";
|
|
24
|
+
} | {
|
|
25
|
+
relation: "fast_forward";
|
|
26
|
+
newEntryIds: string[];
|
|
27
|
+
} | {
|
|
28
|
+
relation: "stale";
|
|
29
|
+
dstAheadBy: string[];
|
|
30
|
+
} | {
|
|
31
|
+
relation: "fork";
|
|
32
|
+
commonAncestor: string | null;
|
|
33
|
+
srcExclusive: string[];
|
|
34
|
+
dstExclusive: string[];
|
|
35
|
+
};
|
|
36
|
+
export declare function classifySyncRelationship(srcEntries: SessionTreeEntry[], dstEntries: SessionTreeEntry[] | null): SyncRelation;
|
|
37
|
+
export declare function classifySyncRelationshipByIds(srcIds: string[], dstIds: string[] | null): SyncRelation;
|
|
38
|
+
export declare class SyncConflictError extends Error {
|
|
39
|
+
readonly sessionId: string;
|
|
40
|
+
readonly relation: Extract<SyncRelation, {
|
|
41
|
+
relation: "fork" | "stale";
|
|
42
|
+
}>;
|
|
43
|
+
constructor(sessionId: string, relation: Extract<SyncRelation, {
|
|
44
|
+
relation: "fork" | "stale";
|
|
45
|
+
}>);
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=session-sync-kernel.d.ts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export function stagingIdFor(realSessionId, token) {
|
|
2
|
+
return `${realSessionId}#stg-${token}`;
|
|
3
|
+
}
|
|
4
|
+
export const STAGING_ID_MARKER = "#stg-";
|
|
5
|
+
export function realIdOfStaging(stagingId) {
|
|
6
|
+
const i = stagingId.indexOf(STAGING_ID_MARKER);
|
|
7
|
+
return i < 0 ? null : stagingId.slice(0, i);
|
|
8
|
+
}
|
|
9
|
+
export function classifySyncRelationship(srcEntries, dstEntries) {
|
|
10
|
+
return classifySyncRelationshipByIds(srcEntries.map((e) => e.id), dstEntries === null ? null : dstEntries.map((e) => e.id));
|
|
11
|
+
}
|
|
12
|
+
export function classifySyncRelationshipByIds(srcIds, dstIds) {
|
|
13
|
+
if (dstIds === null || dstIds.length === 0)
|
|
14
|
+
return { relation: "fresh" };
|
|
15
|
+
const srcSet = new Set(srcIds);
|
|
16
|
+
const dstSet = new Set(dstIds);
|
|
17
|
+
if (srcSet.size === dstSet.size && [...srcSet].every((id) => dstSet.has(id)))
|
|
18
|
+
return { relation: "identical" };
|
|
19
|
+
const allDstInSrc = [...dstSet].every((id) => srcSet.has(id));
|
|
20
|
+
const allSrcInDst = [...srcSet].every((id) => dstSet.has(id));
|
|
21
|
+
if (allDstInSrc && !allSrcInDst) {
|
|
22
|
+
const newEntryIds = srcIds.filter((id) => !dstSet.has(id));
|
|
23
|
+
return { relation: "fast_forward", newEntryIds };
|
|
24
|
+
}
|
|
25
|
+
if (allSrcInDst && !allDstInSrc) {
|
|
26
|
+
const dstAheadBy = dstIds.filter((id) => !srcSet.has(id));
|
|
27
|
+
return { relation: "stale", dstAheadBy };
|
|
28
|
+
}
|
|
29
|
+
const srcExclusive = srcIds.filter((id) => !dstSet.has(id));
|
|
30
|
+
const dstExclusive = dstIds.filter((id) => !srcSet.has(id));
|
|
31
|
+
let commonAncestor = null;
|
|
32
|
+
for (const id of srcIds)
|
|
33
|
+
if (dstSet.has(id))
|
|
34
|
+
commonAncestor = id;
|
|
35
|
+
return { relation: "fork", commonAncestor, srcExclusive, dstExclusive };
|
|
36
|
+
}
|
|
37
|
+
export class SyncConflictError extends Error {
|
|
38
|
+
sessionId;
|
|
39
|
+
relation;
|
|
40
|
+
constructor(sessionId, relation) {
|
|
41
|
+
super(`session-sync: refusing to import session ${sessionId} — ${relation.relation} (would lose destination history; resolve explicitly)`);
|
|
42
|
+
this.sessionId = sessionId;
|
|
43
|
+
this.relation = relation;
|
|
44
|
+
this.name = "SyncConflictError";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=session-sync-kernel.js.map
|
package/dist/session-sync.d.ts
CHANGED
|
@@ -1,51 +1,9 @@
|
|
|
1
1
|
import type { StoreBackend } from "./plugins/store-backend.js";
|
|
2
|
+
import { type SyncRelation } from "./session-sync-kernel.js";
|
|
2
3
|
import type { SessionTreeEntry, SessionRulesRecord } from "@sema-agent/core";
|
|
3
4
|
export type BlobGetter = (hash: string) => Promise<Uint8Array | undefined>;
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
readonly realSessionId: string;
|
|
7
|
-
appendBatch(entries: SessionTreeEntry[]): Promise<void>;
|
|
8
|
-
commit(owner: string | null, opts?: {
|
|
9
|
-
resolution?: "overwrite-dst";
|
|
10
|
-
}): Promise<{
|
|
11
|
-
relation: SyncRelation["relation"];
|
|
12
|
-
}>;
|
|
13
|
-
abort(): Promise<void>;
|
|
14
|
-
}
|
|
15
|
-
export type ImportStagingStore = {
|
|
16
|
-
beginImportStaging(realSessionId: string, token: string): StagingHandle;
|
|
17
|
-
sweepStagingSessions?(): Promise<number>;
|
|
18
|
-
};
|
|
19
|
-
export declare function stagingIdFor(realSessionId: string, token: string): string;
|
|
20
|
-
export declare const STAGING_ID_MARKER = "#stg-";
|
|
21
|
-
export declare function realIdOfStaging(stagingId: string): string | null;
|
|
22
|
-
export type SyncRelation = {
|
|
23
|
-
relation: "fresh";
|
|
24
|
-
} | {
|
|
25
|
-
relation: "identical";
|
|
26
|
-
} | {
|
|
27
|
-
relation: "fast_forward";
|
|
28
|
-
newEntryIds: string[];
|
|
29
|
-
} | {
|
|
30
|
-
relation: "stale";
|
|
31
|
-
dstAheadBy: string[];
|
|
32
|
-
} | {
|
|
33
|
-
relation: "fork";
|
|
34
|
-
commonAncestor: string | null;
|
|
35
|
-
srcExclusive: string[];
|
|
36
|
-
dstExclusive: string[];
|
|
37
|
-
};
|
|
38
|
-
export declare function classifySyncRelationship(srcEntries: SessionTreeEntry[], dstEntries: SessionTreeEntry[] | null): SyncRelation;
|
|
39
|
-
export declare function classifySyncRelationshipByIds(srcIds: string[], dstIds: string[] | null): SyncRelation;
|
|
40
|
-
export declare class SyncConflictError extends Error {
|
|
41
|
-
readonly sessionId: string;
|
|
42
|
-
readonly relation: Extract<SyncRelation, {
|
|
43
|
-
relation: "fork" | "stale";
|
|
44
|
-
}>;
|
|
45
|
-
constructor(sessionId: string, relation: Extract<SyncRelation, {
|
|
46
|
-
relation: "fork" | "stale";
|
|
47
|
-
}>);
|
|
48
|
-
}
|
|
5
|
+
export { stagingIdFor, STAGING_ID_MARKER, realIdOfStaging, classifySyncRelationship, classifySyncRelationshipByIds, SyncConflictError } from "./session-sync-kernel.js";
|
|
6
|
+
export type { StagingHandle, ImportStagingStore, SyncRelation } from "./session-sync-kernel.js";
|
|
49
7
|
export interface SessionBundle {
|
|
50
8
|
sessionId: string;
|
|
51
9
|
entries: SessionTreeEntry[];
|
package/dist/session-sync.js
CHANGED
|
@@ -1,51 +1,7 @@
|
|
|
1
1
|
import { identicalIdsAlsoIdenticalContent } from "./session-sync-content.js";
|
|
2
|
+
import { classifySyncRelationship, SyncConflictError } from "./session-sync-kernel.js";
|
|
2
3
|
import { validateEntriesForImport, normalizeRules, stripRev } from "@sema-agent/core";
|
|
3
|
-
export
|
|
4
|
-
return `${realSessionId}#stg-${token}`;
|
|
5
|
-
}
|
|
6
|
-
export const STAGING_ID_MARKER = "#stg-";
|
|
7
|
-
export function realIdOfStaging(stagingId) {
|
|
8
|
-
const i = stagingId.indexOf(STAGING_ID_MARKER);
|
|
9
|
-
return i < 0 ? null : stagingId.slice(0, i);
|
|
10
|
-
}
|
|
11
|
-
export function classifySyncRelationship(srcEntries, dstEntries) {
|
|
12
|
-
return classifySyncRelationshipByIds(srcEntries.map((e) => e.id), dstEntries === null ? null : dstEntries.map((e) => e.id));
|
|
13
|
-
}
|
|
14
|
-
export function classifySyncRelationshipByIds(srcIds, dstIds) {
|
|
15
|
-
if (dstIds === null || dstIds.length === 0)
|
|
16
|
-
return { relation: "fresh" };
|
|
17
|
-
const srcSet = new Set(srcIds);
|
|
18
|
-
const dstSet = new Set(dstIds);
|
|
19
|
-
if (srcSet.size === dstSet.size && [...srcSet].every((id) => dstSet.has(id)))
|
|
20
|
-
return { relation: "identical" };
|
|
21
|
-
const allDstInSrc = [...dstSet].every((id) => srcSet.has(id));
|
|
22
|
-
const allSrcInDst = [...srcSet].every((id) => dstSet.has(id));
|
|
23
|
-
if (allDstInSrc && !allSrcInDst) {
|
|
24
|
-
const newEntryIds = srcIds.filter((id) => !dstSet.has(id));
|
|
25
|
-
return { relation: "fast_forward", newEntryIds };
|
|
26
|
-
}
|
|
27
|
-
if (allSrcInDst && !allDstInSrc) {
|
|
28
|
-
const dstAheadBy = dstIds.filter((id) => !srcSet.has(id));
|
|
29
|
-
return { relation: "stale", dstAheadBy };
|
|
30
|
-
}
|
|
31
|
-
const srcExclusive = srcIds.filter((id) => !dstSet.has(id));
|
|
32
|
-
const dstExclusive = dstIds.filter((id) => !srcSet.has(id));
|
|
33
|
-
let commonAncestor = null;
|
|
34
|
-
for (const id of srcIds)
|
|
35
|
-
if (dstSet.has(id))
|
|
36
|
-
commonAncestor = id;
|
|
37
|
-
return { relation: "fork", commonAncestor, srcExclusive, dstExclusive };
|
|
38
|
-
}
|
|
39
|
-
export class SyncConflictError extends Error {
|
|
40
|
-
sessionId;
|
|
41
|
-
relation;
|
|
42
|
-
constructor(sessionId, relation) {
|
|
43
|
-
super(`session-sync: refusing to import session ${sessionId} — ${relation.relation} (would lose destination history; resolve explicitly)`);
|
|
44
|
-
this.sessionId = sessionId;
|
|
45
|
-
this.relation = relation;
|
|
46
|
-
this.name = "SyncConflictError";
|
|
47
|
-
}
|
|
48
|
-
}
|
|
4
|
+
export { stagingIdFor, STAGING_ID_MARKER, realIdOfStaging, classifySyncRelationship, classifySyncRelationshipByIds, SyncConflictError } from "./session-sync-kernel.js";
|
|
49
5
|
function ownerAware(backend) {
|
|
50
6
|
return backend.session();
|
|
51
7
|
}
|
package/dist/trace/project.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TaskResult } from "@sema-agent/core";
|
|
2
|
-
import type { RunEvent, RunRecord } from "../plugins/
|
|
2
|
+
import type { RunEvent, RunRecord } from "../plugins/store-contracts.js";
|
|
3
3
|
import type { ModelUsageDelta, ModelUsageTracker, PromptManifestRecord } from "../budget.js";
|
|
4
4
|
type AppendFn = (type: string, data: unknown) => Promise<void>;
|
|
5
5
|
type GetEventsFn = (taskId: string, afterSeq: number) => Promise<RunEvent[]>;
|