@sema-agent/server 1.293.0 → 1.295.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/config.d.ts +2 -0
- package/dist/config.js +2 -0
- package/dist/hooks/hook-runner.js +6 -2
- package/dist/http/server.d.ts +1 -0
- package/dist/http/server.js +7 -0
- package/dist/main.js +12 -5
- package/dist/plugins/blob-backend.d.ts +7 -1
- package/dist/plugins/blob-backend.js +16 -1
- package/dist/plugins/host-platform.js +13 -5
- package/dist/plugins/remote-env-local-docker.d.ts +3 -0
- package/dist/plugins/remote-env-local-docker.js +19 -2
- package/dist/plugins/store-backend.d.ts +1 -0
- package/dist/plugins/store-backend.js +11 -2
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
package/dist/config.js
CHANGED
|
@@ -536,6 +536,8 @@ export function loadConfig() {
|
|
|
536
536
|
...((ttl) => (ttl !== undefined ? { presignTtlSec: ttl } : {}))(optFinitePositiveEnv("SESSION_SNAPSHOT_TTL_SEC")),
|
|
537
537
|
}
|
|
538
538
|
: undefined,
|
|
539
|
+
snapshotBlobSqlMaxBytes: optFinitePositiveEnv("SNAPSHOT_BLOB_SQL_MAX_BYTES"),
|
|
540
|
+
snapshotBlobAllowSql: process.env.SNAPSHOT_BLOB_ALLOW_SQL_BYTES === "true",
|
|
539
541
|
sendUserFile: (process.env.MINIO_ENDPOINT || process.env.S3_ENDPOINT) && process.env.MINIO_ACCESS_KEY && process.env.MINIO_SECRET_KEY
|
|
540
542
|
? {
|
|
541
543
|
endpoint: (process.env.MINIO_ENDPOINT || process.env.S3_ENDPOINT),
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
+
import { hostShell, resolveHostShell } from "../plugins/host-platform.js";
|
|
2
3
|
import { HooksConfig, DEFAULT_HOOK_TIMEOUT_SECONDS, HOOK_EVENT_OWNER, } from "@sema-agent/registry-core/hooks";
|
|
3
4
|
import { redactSecrets } from "../trace/redact.js";
|
|
4
5
|
import { ccPromptSystemFor, wrapCondition, parseCcVerdict, CC_EVALUATOR_MAX_OUTPUT_TOKENS } from "./cc-stop-prompt.js";
|
|
5
6
|
import { renderBranchTranscript } from "./branch-transcript.js";
|
|
7
|
+
void resolveHostShell().catch(() => undefined);
|
|
6
8
|
export const MAX_HOOK_ENTRIES_PER_EVENT = 32;
|
|
7
9
|
export const MAX_HOOK_COMMAND_CHARS = 8_192;
|
|
8
10
|
export const MAX_HOOK_TIMEOUT_SECONDS = 600;
|
|
@@ -144,7 +146,8 @@ function runCommandHook(entry, payload, ctx) {
|
|
|
144
146
|
const timeoutMs = Math.min(entry.timeout ?? DEFAULT_HOOK_TIMEOUT_SECONDS, MAX_HOOK_TIMEOUT_SECONDS) * 1000;
|
|
145
147
|
let child;
|
|
146
148
|
try {
|
|
147
|
-
|
|
149
|
+
const sh = hostShell();
|
|
150
|
+
child = spawn(sh.shell, [...sh.args, entry.command], {
|
|
148
151
|
cwd: ctx.cwd,
|
|
149
152
|
env: hookEnv(ctx),
|
|
150
153
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -203,7 +206,8 @@ function fireAsyncCommandHook(entry, payload, ctx, event) {
|
|
|
203
206
|
try {
|
|
204
207
|
const rewake = entry.asyncRewake === true;
|
|
205
208
|
const timeoutMs = Math.min(entry.timeout ?? DEFAULT_HOOK_TIMEOUT_SECONDS, MAX_HOOK_TIMEOUT_SECONDS) * 1000;
|
|
206
|
-
const
|
|
209
|
+
const sh = hostShell();
|
|
210
|
+
const child = spawn(sh.shell, [...sh.args, entry.command], {
|
|
207
211
|
cwd: ctx.cwd,
|
|
208
212
|
env: hookEnv(ctx),
|
|
209
213
|
stdio: ["pipe", "ignore", rewake ? "pipe" : "ignore"],
|
package/dist/http/server.d.ts
CHANGED
|
@@ -63,6 +63,7 @@ export interface ServiceDeps {
|
|
|
63
63
|
approvalExemptionStore?: ApprovalExemptionStore;
|
|
64
64
|
sessionPolicyStore?: ServiceSessionPolicyStore;
|
|
65
65
|
fileSnapshotStore?: ServiceFileSnapshotStore;
|
|
66
|
+
snapshotBlobSqlCapBytes?: number;
|
|
66
67
|
backend?: StoreBackend;
|
|
67
68
|
sessionMirrorRuling?: (principal: string | undefined) => Promise<SessionMirrorRuling | undefined>;
|
|
68
69
|
approvalStore?: ApprovalStore;
|
package/dist/http/server.js
CHANGED
|
@@ -4062,6 +4062,13 @@ export function createHttpServer(deps) {
|
|
|
4062
4062
|
return;
|
|
4063
4063
|
}
|
|
4064
4064
|
const body = await readRawBody(req, SYNC_BLOB_MAX_BYTES);
|
|
4065
|
+
if (deps.snapshotBlobSqlCapBytes !== undefined && body.byteLength > deps.snapshotBlobSqlCapBytes) {
|
|
4066
|
+
sendJson(res, 413, {
|
|
4067
|
+
code: "blob_too_large_for_sql",
|
|
4068
|
+
error: `blob of ${body.byteLength} bytes exceeds this deployment's SQL snapshot-blob cap (${deps.snapshotBlobSqlCapBytes} bytes; mysql-protocol packet limit) — configure MinIO object storage (MINIO_ENDPOINT/MINIO_ACCESS_KEY/MINIO_SECRET_KEY) for large snapshot blobs`,
|
|
4069
|
+
});
|
|
4070
|
+
return;
|
|
4071
|
+
}
|
|
4065
4072
|
if (createHash("sha256").update(body).digest("hex") !== hash) {
|
|
4066
4073
|
sendJson(res, 400, { error: "blob hash mismatch" });
|
|
4067
4074
|
return;
|
package/dist/main.js
CHANGED
|
@@ -28,7 +28,7 @@ import { loadConfig, logConfigDiagnostics } from "./config.js";
|
|
|
28
28
|
import { resourceSuspendOptIn } from "./resource-suspend.js";
|
|
29
29
|
import { createSessionStore, ensureChildSessionDurableWithPromotion } from "./plugins/session-store.js";
|
|
30
30
|
import { ForkRoutingSessionStore } from "./plugins/fork-routing-session-store.js";
|
|
31
|
-
import { createStoreBackend } from "./plugins/store-backend.js";
|
|
31
|
+
import { createStoreBackend, assertCloudSnapshotBlobPosture } from "./plugins/store-backend.js";
|
|
32
32
|
import { e2bExecutionEnvFactory } from "./plugins/remote-env-e2b.js";
|
|
33
33
|
import { k8sExecutionEnvFactory } from "./plugins/remote-env-k8s.js";
|
|
34
34
|
import { sshExecutionEnvFactory } from "./plugins/remote-env-ssh.js";
|
|
@@ -80,7 +80,7 @@ import { defaultLkgPath, defaultSkillCacheDir, saveLkg, loadLkg } from "./config
|
|
|
80
80
|
import { TiDBRosterStore, PgRosterStore, ensureTiDBRosterSchema, ensurePgRosterSchema } from "./plugins/roster-store-sql.js";
|
|
81
81
|
import { TiDBTaskAttachmentStore, PgTaskAttachmentStore, ensureTiDBTaskAttachmentSchema, ensurePgTaskAttachmentSchema, bindAttachmentsForTask, materializeAttachmentsInto } from "./plugins/task-attachment-store.js";
|
|
82
82
|
import { LocalTaskAttachmentStore } from "./plugins/local-task-attachment-store.js";
|
|
83
|
-
import { MinioBlobBackend } from "./plugins/blob-backend.js";
|
|
83
|
+
import { MinioBlobBackend, SQL_BLOB_DEFAULT_MAX_BYTES } from "./plugins/blob-backend.js";
|
|
84
84
|
import { TiDBBackgroundAgentStore, PgBackgroundAgentStore, ensureTiDBBackgroundAgentSchema, ensurePgBackgroundAgentSchema } from "./plugins/background-agent-store-sql.js";
|
|
85
85
|
import { TiDBMailboxStore, PgMailboxStore, ensureTiDBMailboxSchema, ensurePgMailboxSchema } from "./plugins/mailbox-store-sql.js";
|
|
86
86
|
import { createPrincipalCapsClient, gateExecutionLane, scopedTokenNeedsWorker, applyObserverEnvOptIn } from "./runtime-caps-resolver.js";
|
|
@@ -634,10 +634,14 @@ async function main() {
|
|
|
634
634
|
"the in-memory store cannot enforce session ownership.");
|
|
635
635
|
}
|
|
636
636
|
if (config.requirePrincipal && backend?.kind === "local") {
|
|
637
|
-
throw new Error("REQUIRE_PRINCIPAL=true is not supported on the local
|
|
638
|
-
"process-local and lost on restart
|
|
639
|
-
"
|
|
637
|
+
throw new Error("REQUIRE_PRINCIPAL=true is not supported on the local file backend (DB_BACKEND=local): session/run CONTENT is " +
|
|
638
|
+
"durable there, but OWNER attribution is process-local and lost on restart (store-backend.ts §0.5 — durable " +
|
|
639
|
+
"owners = P1), so it cannot durably enforce multi-tenant session ownership. Use a SQL backend " +
|
|
640
|
+
"(DB_BACKEND=mysql|pg) for multi-tenant, or run local single-user with REQUIRE_PRINCIPAL=false (a BFF may " +
|
|
641
|
+
"still inject x-agent-principal per request for memory scoping and audit attribution).");
|
|
640
642
|
}
|
|
643
|
+
if (backend)
|
|
644
|
+
assertCloudSnapshotBlobPosture(backend.kind, config);
|
|
641
645
|
if (!config.requirePrincipal && sessionStore.ownerOf) {
|
|
642
646
|
logger.warn("principal_optional", {
|
|
643
647
|
note: "owner-aware session store with REQUIRE_PRINCIPAL=false — owned sessions are protected, but headerless callers can create/share anonymous sessions; set REQUIRE_PRINCIPAL=true for multi-tenant",
|
|
@@ -1046,6 +1050,9 @@ async function main() {
|
|
|
1046
1050
|
...(sessionPolicyStore ? { sessionPolicyStore } : {}),
|
|
1047
1051
|
...(runtimeCapsResolver ? { runtimeCapsResolver } : {}),
|
|
1048
1052
|
...(fileSnapshotStore ? { fileSnapshotStore } : {}),
|
|
1053
|
+
...(backend && backend.kind !== "local" && !config.snapshotBlobStore
|
|
1054
|
+
? ((cap) => (cap !== undefined ? { snapshotBlobSqlCapBytes: cap } : {}))(config.snapshotBlobSqlMaxBytes ?? (backend.kind === "mysql" ? SQL_BLOB_DEFAULT_MAX_BYTES : undefined))
|
|
1055
|
+
: {}),
|
|
1049
1056
|
...(executionEnvFactory ? { executionEnvFactory } : {}),
|
|
1050
1057
|
...(lspManager ? { lspManager } : {}),
|
|
1051
1058
|
onBackgroundChildEvent: fleetBackgroundChildPublisher(fleetBus, (msg, fields) => logger.info(msg, fields)),
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { Pool as MysqlPool } from "mysql2/promise";
|
|
2
2
|
import type { Pool as PgPool } from "pg";
|
|
3
|
+
export declare const SQL_BLOB_DEFAULT_MAX_BYTES = 6291456;
|
|
4
|
+
export declare class BlobTooLargeError extends Error {
|
|
5
|
+
readonly code: "blob_too_large_for_sql";
|
|
6
|
+
constructor(byteLen: number, capBytes: number);
|
|
7
|
+
}
|
|
3
8
|
export interface BlobBackend {
|
|
4
9
|
putBlob(hash: string, bytes: Uint8Array): Promise<void>;
|
|
5
10
|
getBlob(hash: string): Promise<Uint8Array | undefined>;
|
|
@@ -9,7 +14,8 @@ export interface BlobBackend {
|
|
|
9
14
|
export declare class SqlBlobBackend implements BlobBackend {
|
|
10
15
|
private readonly dialect;
|
|
11
16
|
private readonly pool;
|
|
12
|
-
|
|
17
|
+
private readonly capBytes;
|
|
18
|
+
constructor(dialect: "tidb" | "pg", pool: MysqlPool | PgPool, maxBytes?: number);
|
|
13
19
|
putBlob(hash: string, bytes: Uint8Array): Promise<void>;
|
|
14
20
|
getBlob(hash: string): Promise<Uint8Array | undefined>;
|
|
15
21
|
hasBlobs(hashes: string[]): Promise<Set<string>>;
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { presignS3Url } from "./s3-presign.js";
|
|
3
3
|
const BLOB_GC_GRACE_MS = 3_600_000;
|
|
4
|
+
export const SQL_BLOB_DEFAULT_MAX_BYTES = 6_291_456;
|
|
5
|
+
export class BlobTooLargeError extends Error {
|
|
6
|
+
code = "blob_too_large_for_sql";
|
|
7
|
+
constructor(byteLen, capBytes) {
|
|
8
|
+
super(`blob of ${byteLen} bytes exceeds the SQL snapshot-blob cap (${capBytes} bytes): a single-row INSERT this large ` +
|
|
9
|
+
`hits TiDB's txn-entry-size-limit (default 6MiB) or the mysql-protocol max_allowed_packet (~2x text-protocol ` +
|
|
10
|
+
`inflation). Configure object storage (MINIO_ENDPOINT/MINIO_ACCESS_KEY/MINIO_SECRET_KEY) for large snapshot ` +
|
|
11
|
+
`blobs, or override the cap with SNAPSHOT_BLOB_SQL_MAX_BYTES if your deployment raised those limits.`);
|
|
12
|
+
this.name = "BlobTooLargeError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
4
15
|
const MINIO_OP_CONCURRENCY = 16;
|
|
5
16
|
async function mapBounded(items, limit, fn) {
|
|
6
17
|
let i = 0;
|
|
@@ -15,11 +26,15 @@ async function mapBounded(items, limit, fn) {
|
|
|
15
26
|
export class SqlBlobBackend {
|
|
16
27
|
dialect;
|
|
17
28
|
pool;
|
|
18
|
-
|
|
29
|
+
capBytes;
|
|
30
|
+
constructor(dialect, pool, maxBytes) {
|
|
19
31
|
this.dialect = dialect;
|
|
20
32
|
this.pool = pool;
|
|
33
|
+
this.capBytes = maxBytes ?? (dialect === "tidb" ? SQL_BLOB_DEFAULT_MAX_BYTES : Number.POSITIVE_INFINITY);
|
|
21
34
|
}
|
|
22
35
|
async putBlob(hash, bytes) {
|
|
36
|
+
if (bytes.byteLength > this.capBytes)
|
|
37
|
+
throw new BlobTooLargeError(bytes.byteLength, this.capBytes);
|
|
23
38
|
if (this.dialect === "tidb") {
|
|
24
39
|
await this.pool.query("INSERT INTO snapshot_blob (blob_hash, byte_len, bytes, created_at) VALUES (?,?,?,?) ON DUPLICATE KEY UPDATE created_at = VALUES(created_at)", [hash, bytes.byteLength, Buffer.from(bytes), new Date()]);
|
|
25
40
|
}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { getShellConfig, killProcessTree, signalProcessTree } from "@sema-agent/core";
|
|
2
2
|
export const IS_WIN32 = process.platform === "win32";
|
|
3
|
-
const
|
|
3
|
+
const POSIX_SH_FALLBACK = { shell: "/bin/sh", args: ["-c"] };
|
|
4
4
|
let cachedWinShell;
|
|
5
|
+
let cachedPosixShell;
|
|
5
6
|
export async function resolveHostShell() {
|
|
6
|
-
if (!IS_WIN32)
|
|
7
|
-
|
|
7
|
+
if (!IS_WIN32) {
|
|
8
|
+
if (cachedPosixShell)
|
|
9
|
+
return cachedPosixShell;
|
|
10
|
+
const posixCfg = await getShellConfig(process.env.HOST_SHELL_PATH || undefined);
|
|
11
|
+
cachedPosixShell = posixCfg.ok ? { shell: posixCfg.value.shell, args: posixCfg.value.args } : POSIX_SH_FALLBACK;
|
|
12
|
+
return cachedPosixShell;
|
|
13
|
+
}
|
|
8
14
|
if (cachedWinShell)
|
|
9
15
|
return cachedWinShell;
|
|
10
16
|
const custom = process.env.HOST_SHELL_PATH;
|
|
@@ -18,14 +24,16 @@ export async function resolveHostShell() {
|
|
|
18
24
|
return cachedWinShell;
|
|
19
25
|
}
|
|
20
26
|
export function hostShell() {
|
|
21
|
-
if (!IS_WIN32)
|
|
22
|
-
return
|
|
27
|
+
if (!IS_WIN32) {
|
|
28
|
+
return cachedPosixShell ?? POSIX_SH_FALLBACK;
|
|
29
|
+
}
|
|
23
30
|
if (!cachedWinShell)
|
|
24
31
|
throw new Error("host shell not resolved yet — resolveHostShell() must settle before any spawn (shellReady ordering bug)");
|
|
25
32
|
return cachedWinShell;
|
|
26
33
|
}
|
|
27
34
|
export function resetHostShellCacheForTest() {
|
|
28
35
|
cachedWinShell = undefined;
|
|
36
|
+
cachedPosixShell = undefined;
|
|
29
37
|
}
|
|
30
38
|
export function spawnGroupOptions() {
|
|
31
39
|
return IS_WIN32 ? { detached: false, windowsHide: true } : { detached: true };
|
|
@@ -114,6 +114,9 @@ export declare class RemoteLocalDockerExecutionEnv implements RemoteExecutionEnv
|
|
|
114
114
|
private execArgv;
|
|
115
115
|
private execRaw;
|
|
116
116
|
private docker;
|
|
117
|
+
private containerShell;
|
|
118
|
+
private containerShellProbed;
|
|
119
|
+
private probeContainerShell;
|
|
117
120
|
private ensureConnectedExec;
|
|
118
121
|
private fsReady;
|
|
119
122
|
private tempResult;
|
|
@@ -480,7 +480,7 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
480
480
|
const mergedEnv = { ...(this.cfg.env ?? {}), ...(env ?? {}) };
|
|
481
481
|
for (const [k, v] of Object.entries(mergedEnv))
|
|
482
482
|
args.push("-e", `${k}=${v}`);
|
|
483
|
-
args.push(this.containerName,
|
|
483
|
+
args.push(this.containerName, this.containerShell, "-c", command);
|
|
484
484
|
return args;
|
|
485
485
|
}
|
|
486
486
|
execRaw(command) {
|
|
@@ -547,14 +547,31 @@ export class RemoteLocalDockerExecutionEnv {
|
|
|
547
547
|
});
|
|
548
548
|
});
|
|
549
549
|
}
|
|
550
|
+
containerShell = "/bin/sh";
|
|
551
|
+
containerShellProbed = false;
|
|
552
|
+
async probeContainerShell() {
|
|
553
|
+
if (this.containerShellProbed)
|
|
554
|
+
return;
|
|
555
|
+
this.containerShellProbed = true;
|
|
556
|
+
try {
|
|
557
|
+
const r = await this.docker(this.withHostFlag(["exec", this.containerName, "/bin/sh", "-c", "command -v bash"]), { timeoutMs: this.cfg.controlTimeoutMs });
|
|
558
|
+
if (r.ok && r.value.exitCode === 0 && r.value.stdout.trim().length > 0)
|
|
559
|
+
this.containerShell = "bash";
|
|
560
|
+
}
|
|
561
|
+
catch {
|
|
562
|
+
}
|
|
563
|
+
}
|
|
550
564
|
async ensureConnectedExec() {
|
|
551
565
|
if (this.destroyed)
|
|
552
566
|
return { ok: false, error: new ExecutionError("shell_unavailable", "execution env already destroyed") };
|
|
553
|
-
if (this.containerId)
|
|
567
|
+
if (this.containerId) {
|
|
568
|
+
await this.probeContainerShell();
|
|
554
569
|
return ok(undefined);
|
|
570
|
+
}
|
|
555
571
|
const c = await this.connect();
|
|
556
572
|
if (!c.ok)
|
|
557
573
|
return { ok: false, error: new ExecutionError("shell_unavailable", `local-docker connect failed: ${c.error.message}`, c.error) };
|
|
574
|
+
await this.probeContainerShell();
|
|
558
575
|
return ok(undefined);
|
|
559
576
|
}
|
|
560
577
|
async fsReady(p) {
|
|
@@ -93,6 +93,7 @@ export interface StoreBackend {
|
|
|
93
93
|
pgPool(): PgPool | undefined;
|
|
94
94
|
dbNowMs?(): Promise<number>;
|
|
95
95
|
}
|
|
96
|
+
export declare function assertCloudSnapshotBlobPosture(kind: "mysql" | "pg" | "local", config: Pick<ServiceConfig, "snapshotBlobStore" | "snapshotBlobAllowSql">): void;
|
|
96
97
|
export declare function snapshotBoundsFromConfig(config: ServiceConfig): FileSnapshotBounds;
|
|
97
98
|
export declare function createStoreBackend(config: ServiceConfig): StoreBackend | undefined;
|
|
98
99
|
//# sourceMappingURL=store-backend.d.ts.map
|
|
@@ -21,7 +21,7 @@ import { TiDBWorkflowJournalStore } from "./tidb-workflow-journal-store.js";
|
|
|
21
21
|
import { PgWorkflowJournalStore } from "./pg-workflow-journal-store.js";
|
|
22
22
|
import { TiDBFileSnapshotStore } from "./tidb-file-snapshot-store.js";
|
|
23
23
|
import { PgFileSnapshotStore } from "./pg-file-snapshot-store.js";
|
|
24
|
-
import { MinioBlobBackend } from "./blob-backend.js";
|
|
24
|
+
import { MinioBlobBackend, SqlBlobBackend } from "./blob-backend.js";
|
|
25
25
|
import { createTidbPool, ensureSchema as ensureTidbSchema } from "./tidb-pool.js";
|
|
26
26
|
import { createPgPool, ensurePgSchema, pgPoolOptions } from "./pg-pool.js";
|
|
27
27
|
import { TiDBRunStore } from "./tidb-run-store.js";
|
|
@@ -47,7 +47,7 @@ import { PgSessionStore } from "./pg-session-storage.js";
|
|
|
47
47
|
function snapshotBlobBackend(config, dialect, pool) {
|
|
48
48
|
const s = config.snapshotBlobStore;
|
|
49
49
|
if (!s)
|
|
50
|
-
return
|
|
50
|
+
return new SqlBlobBackend(dialect, pool, config.snapshotBlobSqlMaxBytes);
|
|
51
51
|
return new MinioBlobBackend({
|
|
52
52
|
endpoint: s.endpoint,
|
|
53
53
|
bucket: s.bucket,
|
|
@@ -58,6 +58,15 @@ function snapshotBlobBackend(config, dialect, pool) {
|
|
|
58
58
|
...(s.presignTtlSec ? { presignTtlSec: s.presignTtlSec } : {}),
|
|
59
59
|
}, { dialect, pool });
|
|
60
60
|
}
|
|
61
|
+
export function assertCloudSnapshotBlobPosture(kind, config) {
|
|
62
|
+
if (kind === "local" || config.snapshotBlobStore || config.snapshotBlobAllowSql)
|
|
63
|
+
return;
|
|
64
|
+
throw new Error("cloud deployments (DB_BACKEND=mysql|pg) must configure object storage for snapshot blobs " +
|
|
65
|
+
"(MINIO_ENDPOINT/MINIO_ACCESS_KEY/MINIO_SECRET_KEY): single-row SQL blob writes hit TiDB's " +
|
|
66
|
+
"txn-entry-size-limit (default 6MiB) / the mysql-protocol packet limit (bytes belong in object storage — " +
|
|
67
|
+
"same ruling as the D-1 attachment store). Single-box/test rigs may explicitly opt out with " +
|
|
68
|
+
"SNAPSHOT_BLOB_ALLOW_SQL_BYTES=true (a per-blob cap then applies; oversized blobs are rejected 413).");
|
|
69
|
+
}
|
|
61
70
|
export function snapshotBoundsFromConfig(config) {
|
|
62
71
|
const mb = config.rewindSnapshotMaxMb;
|
|
63
72
|
return mb !== undefined ? { ...DEFAULT_SNAPSHOT_BOUNDS, maxBytes: Math.round(mb * 1024 * 1024) } : DEFAULT_SNAPSHOT_BOUNDS;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.295.0",
|
|
4
4
|
"description": "Sema Server — the server/API implementation layer for Sema, wiring core, registry, model providers, and cloud agent execution. Built on @sema-agent/core.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BUSL-1.1",
|