@sema-agent/server 7.139.0 → 7.140.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/MIGRATION.md +181 -0
- package/USAGE.md +19 -13
- package/dist/adoption/runner.js +1 -1
- package/dist/adoption/sql.js +1 -1
- package/dist/approval-card.d.ts +6 -6
- package/dist/bench/s1/live-deps.js +3 -2
- package/dist/bench/s1/row.d.ts +5 -2
- package/dist/bench/s1/row.js +2 -22
- package/dist/boot/adoption.js +1 -1
- package/dist/boot/execution-env.js +12 -10
- package/dist/boot/execution-lane.d.ts +8 -0
- package/dist/boot/execution-lane.js +6 -1
- package/dist/boot/memory-boundary.d.ts +14 -51
- package/dist/boot/memory-boundary.js +10 -20
- package/dist/boot/memory-consolidation.d.ts +15 -11
- package/dist/boot/memory-consolidation.js +23 -12
- package/dist/boot/resolve-spec.d.ts +3 -5
- package/dist/boot/resolve-spec.js +2 -4
- package/dist/boot/runner-deps.d.ts +3 -3
- package/dist/boot/runner-deps.js +1 -0
- package/dist/boot/stage-03-store-backend.d.ts +2 -6
- package/dist/boot/stage-03-store-backend.js +2 -3
- package/dist/boot/stage-04-stores.d.ts +2 -6
- package/dist/boot/stage-04-stores.js +5 -5
- package/dist/boot/stage-05-execution-env.d.ts +2 -6
- package/dist/boot/stage-06-runners.d.ts +2 -6
- package/dist/boot/stage-06-runners.js +2 -2
- package/dist/boot/stage-07-capability-layer.d.ts +2 -6
- package/dist/boot/stage-08-reapers.d.ts +2 -6
- package/dist/boot/stage-09-leader.d.ts +2 -6
- package/dist/boot/stage-10-http-server.d.ts +2 -6
- package/dist/boot/stage-10-http-server.js +5 -4
- package/dist/boot/stores.d.ts +3 -6
- package/dist/boot/stores.js +27 -40
- package/dist/boot/task-list-lane.d.ts +1 -1
- package/dist/boot/task-list-lane.js +1 -1
- package/dist/boot/web-admin.js +35 -9
- package/dist/capabilities/execution-lane.d.ts +2 -2
- package/dist/config-catalog.js +2 -1
- package/dist/config-provider.d.ts +14 -13
- package/dist/config-provider.js +24 -18
- package/dist/config-types.d.ts +11 -2
- package/dist/config.js +2 -1
- package/dist/delegated-session-owner.d.ts +2 -1
- package/dist/delegated-session-owner.js +1 -1
- package/dist/deployment-shape.d.ts +9 -8
- package/dist/deployment-shape.js +4 -4
- package/dist/execution-lane-caps.d.ts +97 -106
- package/dist/execution-lane-caps.js +67 -83
- package/dist/http/memory-compliance-failure-reply.d.ts +3 -1
- package/dist/http/memory-compliance-failure-reply.js +5 -0
- package/dist/http/memory-layer-reply.d.ts +30 -0
- package/dist/http/memory-layer-reply.js +24 -0
- package/dist/http/resume-legs.js +13 -16
- package/dist/http/retired-service-deps.d.ts +1 -1
- package/dist/http/retired-service-deps.js +1 -1
- package/dist/http/routes/adoption.js +1 -1
- package/dist/http/routes/memory-bundle.js +3 -0
- package/dist/http/routes/memory-compliance.js +8 -1
- package/dist/http/routes/memory-consolidation.js +12 -1
- package/dist/http/routes/memory-origin.js +14 -2
- package/dist/http/routes/memory-policy.js +5 -0
- package/dist/http/routes/sessions.js +28 -11
- package/dist/http/routes/tasks.js +4 -2
- package/dist/http/server.d.ts +5 -25
- package/dist/http/server.js +2 -2
- package/dist/identity-source.d.ts +1 -1
- package/dist/identity-source.js +1 -1
- package/dist/lane-home-probe.d.ts +68 -42
- package/dist/lane-home-probe.js +53 -30
- package/dist/leader/wire.js +5 -4
- package/dist/memory-bundle-engine.d.ts +16 -9
- package/dist/memory-bundle-engine.js +29 -6
- package/dist/memory-operator-faces.d.ts +85 -30
- package/dist/memory-operator-faces.js +136 -30
- package/dist/memory-project-layer.d.ts +3 -21
- package/dist/memory-project-layer.js +11 -8
- package/dist/memory-scope-stores.d.ts +73 -0
- package/dist/memory-scope-stores.js +86 -0
- package/dist/memory-scope.d.ts +29 -5
- package/dist/memory-scope.js +16 -4
- package/dist/memory-sync-client.d.ts +20 -7
- package/dist/memory-sync-client.js +31 -13
- package/dist/plugins/adoption-log-sql.js +4 -4
- package/dist/plugins/approval-ask-store-sql.js +14 -14
- package/dist/plugins/approval-nonce-store.js +4 -4
- package/dist/plugins/blob-backend.d.ts +4 -4
- package/dist/plugins/blob-backend.js +7 -7
- package/dist/plugins/breaker-state-sql.js +2 -2
- package/dist/plugins/checkpoint-index-columns.js +2 -2
- package/dist/plugins/checkpoint-store-sql.js +16 -16
- package/dist/plugins/device-store-sql.js +19 -19
- package/dist/plugins/ensure-index.d.ts +1 -2
- package/dist/plugins/execution-placement-sql.d.ts +8 -8
- package/dist/plugins/execution-placement-sql.js +8 -8
- package/dist/plugins/file-history-store-sql.d.ts +2 -2
- package/dist/plugins/file-history-store-sql.js +4 -4
- package/dist/plugins/image-bake-store-sql.js +9 -9
- package/dist/plugins/image-index-sql.js +11 -11
- package/dist/plugins/leader-run-store-sql.js +4 -4
- package/dist/plugins/mailbox-store-sql.d.ts +2 -1
- package/dist/plugins/mailbox-store-sql.js +4 -4
- package/dist/plugins/memory-engine-tidb.js +5 -5
- package/dist/plugins/memory-optout-grant-store-sql.js +1 -1
- package/dist/plugins/memory-sync-store-tidb.js +3 -3
- package/dist/plugins/one-time-migrations.d.ts +10 -9
- package/dist/plugins/one-time-migrations.js +36 -36
- package/dist/plugins/org-delivery-quota-store.js +2 -2
- package/dist/plugins/outcome-ledger-sql.js +2 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +4 -4
- package/dist/plugins/permission-rule-store-sql.js +16 -16
- package/dist/plugins/remote-env-adb.d.ts +7 -24
- package/dist/plugins/remote-env-adb.js +22 -5
- package/dist/plugins/remote-env-device.d.ts +2 -28
- package/dist/plugins/remote-env-device.js +2 -1
- package/dist/plugins/remote-env-e2b.d.ts +18 -26
- package/dist/plugins/remote-env-e2b.js +51 -4
- package/dist/plugins/remote-env-file-error.d.ts +1 -1
- package/dist/plugins/remote-env-file-error.js +8 -2
- package/dist/plugins/remote-env-host.d.ts +19 -35
- package/dist/plugins/remote-env-host.js +26 -3
- package/dist/plugins/remote-env-k8s.d.ts +3 -14
- package/dist/plugins/remote-env-k8s.js +3 -2
- package/dist/plugins/remote-env-local-docker.d.ts +4 -15
- package/dist/plugins/remote-env-local-docker.js +5 -4
- package/dist/plugins/remote-env-ssh.d.ts +4 -24
- package/dist/plugins/remote-env-ssh.js +4 -3
- package/dist/plugins/resume-anchor-store-sql.js +2 -2
- package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
- package/dist/plugins/retention-lane-store-sql.js +2 -2
- package/dist/plugins/retention-store-sql.d.ts +1 -1
- package/dist/plugins/retention-store-sql.js +6 -6
- package/dist/plugins/run-store-sql.js +15 -15
- package/dist/plugins/schema-consistency.d.ts +6 -6
- package/dist/plugins/schema-consistency.js +1 -1
- package/dist/plugins/schema-ensure-legs.d.ts +2 -3
- package/dist/plugins/schema-ensure-legs.js +2 -2
- package/dist/plugins/schema-live-columns.d.ts +1 -1
- package/dist/plugins/session-capture-record-store-sql.js +1 -1
- package/dist/plugins/session-rules-column.d.ts +1 -1
- package/dist/plugins/session-rules-column.js +1 -1
- package/dist/plugins/session-workspace-cell.d.ts +1 -1
- package/dist/plugins/session-workspace-cell.js +1 -1
- package/dist/plugins/shared-memory-store-sql.js +2 -2
- package/dist/plugins/sql-driver.d.ts +10 -5
- package/dist/plugins/sql-driver.js +6 -6
- package/dist/plugins/sql-errors.js +1 -1
- package/dist/plugins/store-backend.d.ts +4 -6
- package/dist/plugins/store-backend.js +6 -6
- package/dist/plugins/task-list-store-sql.js +11 -11
- package/dist/plugins/tidb-pool.js +5 -5
- package/dist/plugins/tidb-session-storage.js +4 -4
- package/dist/plugins/tidb-session-store.js +13 -13
- package/dist/plugins/tool-result-store-sql.d.ts +2 -2
- package/dist/plugins/tool-result-store-sql.js +3 -3
- package/dist/plugins/user-input-ledger-sql.js +2 -2
- package/dist/plugins/workflow-journal-store-sql.js +5 -5
- package/dist/plugins/workflow-run-store-sql.js +19 -19
- package/dist/plugins/write-behind-counter.d.ts +2 -3
- package/dist/plugins/write-behind-counter.js +5 -5
- package/dist/resource-suspend.d.ts +14 -12
- package/dist/resource-suspend.js +1 -1
- package/dist/resource-window.d.ts +4 -3
- package/dist/run-local.js +14 -19
- package/dist/runs.d.ts +8 -4
- package/dist/runs.js +49 -65
- package/dist/session-incarnation.d.ts +1 -1
- package/dist/session-incarnation.js +1 -1
- package/dist/session-policy-wire.d.ts +1 -1
- package/dist/sql-engine-posture.d.ts +1 -1
- package/dist/sql-engine-posture.js +1 -1
- package/dist/{plugins → stores-sql}/background-agent-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/background-agent-store-sql.js +8 -8
- package/dist/{plugins → stores-sql}/session-policy-store-sql.d.ts +7 -5
- package/dist/{plugins → stores-sql}/session-policy-store-sql.js +12 -12
- package/dist/{plugins → stores-sql}/usage-window-store-sql.d.ts +1 -1
- package/dist/{plugins → stores-sql}/usage-window-store-sql.js +3 -3
- package/dist/task-a2a.js +5 -6
- package/dist/task-mcp.d.ts +20 -7
- package/dist/task-mcp.js +17 -9
- package/dist/terminal.d.ts +27 -0
- package/dist/terminal.js +6 -0
- package/dist/trace/redact.d.ts +3 -1
- package/dist/trace/redact.js +80 -28
- package/dist/trace/self-minted-wire.d.ts +58 -0
- package/dist/trace/self-minted-wire.js +16 -0
- package/dist/web-admin-client/candidate-gate.d.ts +11 -7
- package/dist/web-admin-client/candidate-gate.js +1 -1
- package/dist/web-admin-client/http-client.d.ts +5 -4
- package/dist/web-admin-client/http-client.js +2 -2
- package/dist/web-admin-client/read-warnings.d.ts +7 -17
- package/dist/web-admin-client/read-warnings.js +5 -9
- package/package.json +2 -2
- package/wire-changes/server@7.140.0.json +184 -0
|
@@ -1,39 +1,53 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 执行环境的家目录:**主张 × 实测**的唯一判官与唯一的座(纯叶:零值依赖)。
|
|
3
3
|
*
|
|
4
|
-
* ## 病(一)——
|
|
5
|
-
* `REMOTE_EXEC_HOME_DIR
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* ## 病(一)—— 给了家目录却对不上
|
|
5
|
+
* 部署事先给每只执行环境一个家目录:运维声明 `REMOTE_EXEC_HOME_DIR`,或车道自己的出厂答案(声明缺席时 host = 本进程的家目录、e2b = 平台固定用户的
|
|
6
|
+
* `/home/user`;`execution-lane-caps.ts` `executionLaneHomeDir` 一只属主)。它是 `~/` 形权限规则的基、引擎家锚拒读行(`~/.ssh` / `~/.npmrc` …)的落点。
|
|
7
|
+
* 给的是 `/home/y` 而环境里命令真看到的 `$HOME` 是 `/home/x` 时,`Edit(~/.ssh/**)` 守的是 `/home/y`,`/home/x/.ssh` 照读照写,运维与用户零告警:
|
|
8
|
+
* 限制写了不生效且无人知(镜像换代换了用户、e2b 自定义模板换了用户、host 上会话 `settings.env` 改了 `HOME` —— 都是这一形)。
|
|
9
9
|
*
|
|
10
|
-
* ## 病(二)——
|
|
11
|
-
*
|
|
10
|
+
* ## 病(二)—— 没给就恒问人
|
|
11
|
+
* 执行环境没有家目录时,引擎的家锚拒读行放不下 ⇒ 每一次泄内容的递归读(`grep -r` / `rg` / `git grep` / `tar c`)在全 shell 面恒问人、只读面直接拒。
|
|
12
12
|
* 家目录是执行环境自己的事实,车道开环境那一拍问一次就知道 —— 不必要运维手填。
|
|
13
13
|
*
|
|
14
|
-
* ## 律(
|
|
15
|
-
* ·
|
|
16
|
-
* `printf %s "$HOME"
|
|
17
|
-
*
|
|
18
|
-
* ·
|
|
19
|
-
* · **实测也缺席**(问不出 / 答的不是绝对路径,含空串)⇒ 座缺席(引擎失败关闭,不猜、不补 `/`),环境照开(
|
|
20
|
-
*
|
|
14
|
+
* ## 律(一条:读得出就读,读数是真源 —— {@link LaneHomeSeat},每只读得出家目录的适配器各持一只,不各写一份)
|
|
15
|
+
* · **有主张 ⇒ 证**:座 = 主张原样(下单门与引擎 prepare 在环境开起来之前就要基);开环境那一拍读一次(与命令同一条 shell、同一份 env:
|
|
16
|
+
* `printf %s "$HOME"`;host 直接读它自己组合给子进程的那份 env),两者不一致 ⇒ 这只执行环境不开(拒句点名两值与改法),环境答了的判定记在环境上
|
|
17
|
+
* (同一镜像 / 同一目标机再问也是同一个答案,不重试成风暴);读不出同样不开(证不了主张 = 不拿一个没证过的目录去守),但不记 —— 与任何一次建连失败同,下一次重问。
|
|
18
|
+
* · **没主张 ⇒ 实测**:同一拍问同一句;答出绝对路径 ⇒ 座 = 它,之后不再问;
|
|
19
|
+
* · **实测也缺席**(问不出 / 答的不是绝对路径,含空串)⇒ 座缺席(引擎失败关闭,不猜、不补 `/`),环境照开(没主张就没有主张可拒),一行 warn(点名读到了什么与出路)。
|
|
20
|
+
* 读不了家目录的车道(device:设备协议没有读数)不持座 —— 声明就是座,起服披露「来自声明、未实测」(`execution-lane-caps.ts` `buildLaneHomeBootNote`)。
|
|
21
|
+
* 规则基与 422 门在下单那一刻就要家目录,而那一刻执行环境还没开 —— 它们只读主张(`executionLaneHomeDir`);环境开起来时主张被证,证不了的环境不开。
|
|
21
22
|
*/
|
|
22
|
-
/** 探针答案的行首标记:登录脚本 / profile 往 stdout 打的横幅不会被读成家目录 —— 只认带这个标记的那一行(
|
|
23
|
+
/** 探针答案的行首标记:登录脚本 / profile 往 stdout 打的横幅不会被读成家目录 —— 只认带这个标记的那一行(恰一条,见 `markedHome`)。 */
|
|
23
24
|
export declare const LANE_HOME_PROBE_MARKER = "sema-lane-home=";
|
|
24
25
|
/**
|
|
25
26
|
* 执行环境里问家目录的那一句 —— 经车道自己的命令通道跑(同一条 shell、同一份 env),答的就是命令看到的 `$HOME`。
|
|
26
27
|
* 先换一行再打标记行:横幅没以换行收尾时,标记行照样从行首开始。
|
|
27
28
|
*/
|
|
28
29
|
export declare const LANE_HOME_PROBE_COMMAND = "printf '\\nsema-lane-home=%s\\n' \"$HOME\"";
|
|
29
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* 一次问家目录的读数:探针的 stdout 原文(经车道命令通道跑 {@link LANE_HOME_PROBE_COMMAND})/ 直接读到的值(适配器自己组合子进程 env 的车道 —— host:
|
|
32
|
+
* 那份 env 里的 `HOME`;缺席时读子进程 shell 对 `~` 的展开,见 `remote-env-host.ts` `childHome`)/ 没问到(原因)。
|
|
33
|
+
*/
|
|
30
34
|
export type LaneHomeProbe = {
|
|
31
35
|
readonly ok: true;
|
|
32
36
|
readonly stdout: string;
|
|
37
|
+
} | {
|
|
38
|
+
readonly ok: true;
|
|
39
|
+
readonly value: string;
|
|
33
40
|
} | {
|
|
34
41
|
readonly ok: false;
|
|
35
42
|
readonly reason: string;
|
|
36
43
|
};
|
|
44
|
+
/** 主张的来源 —— 只进拒句(改法随它):运维声明(`REMOTE_EXEC_HOME_DIR`)/ 车道自己的出厂答案(声明缺席时;没有「删声明」这条路)。 */
|
|
45
|
+
export type LaneHomeSource = "declared" | "lane";
|
|
46
|
+
/** 部署交给一只执行环境的家目录主张:值 + 来源。 */
|
|
47
|
+
export interface LaneHomeClaim {
|
|
48
|
+
readonly home: string;
|
|
49
|
+
readonly source: LaneHomeSource;
|
|
50
|
+
}
|
|
37
51
|
/**
|
|
38
52
|
* 判定:`undefined` = 一致,照开;否则这只环境不开 —— `refusal` 是拒句,`answered` = 环境**答了**它的家目录(不一致 / 不是绝对路径;同一镜像 / 同一登录用户
|
|
39
53
|
* 再问也是同一个答案 ⇒ 调用方记在环境上),`false` = 没答上(探针失败 / 超时 / 非零退出 / 输出里没有标记行 ⇒ 这一次不开、不记、下一次重问)。
|
|
@@ -43,9 +57,17 @@ export type LaneHomeVerdict = {
|
|
|
43
57
|
readonly answered: boolean;
|
|
44
58
|
} | undefined;
|
|
45
59
|
/**
|
|
46
|
-
*
|
|
60
|
+
* 执行环境的路径平台 —— 「绝对」与「同一个目录」两条判据随它:远端车道(k8s / local-docker / ssh / adb / e2b,Linux / Android 的 POSIX shell)= `posix`;
|
|
61
|
+
* win32 宿主上的 host 车道 = `win32`(子进程的 `HOME` 是盘符形)。车道没得选:是环境自己的平台,由持座的适配器说(缺省 `posix`)。
|
|
47
62
|
*/
|
|
48
|
-
export
|
|
63
|
+
export type LanePathFlavor = "posix" | "win32";
|
|
64
|
+
/**
|
|
65
|
+
* 主张 × 实测的判官(全仓唯一一只:每只读得出家目录的适配器经 {@link LaneHomeSeat} 用它,自己不比)。`lane` 只进句子。
|
|
66
|
+
* 拒句闭集 3 形 × 2 来源:实测与主张不一致 / 实测不是绝对路径(含空)/ 没问到;每一句都点名主张(与实测值,有就点名)和改法,不回显任何别的东西。
|
|
67
|
+
* 改法随来源:声明 ⇒「改成实测值或删掉声明」;出厂答案 ⇒ 只有「设成实测值」(没有声明可删)。另一条路两种来源同:让环境的 `HOME` 读主张那个值。
|
|
68
|
+
* 次序:读不出 → 不是绝对路径 → 一致 → 不一致(「绝对」先于「一致」:主张自己是相对串时,一个同样相对的读数也不放行)。
|
|
69
|
+
*/
|
|
70
|
+
export declare function judgeLaneHome(lane: string, claim: LaneHomeClaim, probe: LaneHomeProbe, paths?: LanePathFlavor): LaneHomeVerdict;
|
|
49
71
|
/** 起服与每只环境「家目录答不出」那一行 warn 的事件名 —— 一只 code,起服(车道读不了)与环境(实测缺席)共用。 */
|
|
50
72
|
export declare const LANE_HOME_UNDECLARED_EVENT = "execution_lane_home_undeclared";
|
|
51
73
|
/**
|
|
@@ -55,52 +77,56 @@ export declare const LANE_HOME_UNDECLARED_EVENT = "execution_lane_home_undeclare
|
|
|
55
77
|
export declare function buildHomeAbsentNote(lane: string, cause: string, remedy: string): string;
|
|
56
78
|
/** 车道读不了家目录时的出路(起服那一行):声明它。 */
|
|
57
79
|
export declare const DECLARE_HOME_REMEDY = "Declare the home: REMOTE_EXEC_HOME_DIR=<the absolute path the environment's $HOME reads>";
|
|
80
|
+
/** 读不了家目录的车道(今天只有 device)上声明在场时,起服那一行 warn 的事件名:座 = 声明,没有任何读数证过它。 */
|
|
81
|
+
export declare const LANE_HOME_UNMEASURED_EVENT = "execution_lane_home_unmeasured";
|
|
82
|
+
/**
|
|
83
|
+
* 「这条车道的家目录来自声明、未实测」的一句(纯字符串 ⇒ `build*`)—— 读得出的车道由 {@link judgeLaneHome} 证主张,读不了的车道没有那一步,起服把这件事说出来:
|
|
84
|
+
* 规则落在哪、对不上时会怎样、运维要守住什么。
|
|
85
|
+
*/
|
|
86
|
+
export declare function buildHomeUnmeasuredNote(lane: string, declared: string): string;
|
|
58
87
|
/** 一行「这只环境没有家目录」的事实:交给运维的那一行 warn 的两个字段。 */
|
|
59
88
|
export interface LaneHomeAbsence {
|
|
60
89
|
readonly provider: string;
|
|
61
90
|
readonly note: string;
|
|
62
91
|
}
|
|
63
|
-
/** 这条车道的座怎么长出来:`declared` = 运维声明(`REMOTE_EXEC_HOME_DIR`,boot 期的唯一属主 `executionLaneHomeDir` 的答案);`verifiesDeclared` = 车道对声明对证。 */
|
|
64
|
-
export interface LaneHomeSeatOptions {
|
|
65
|
-
readonly lane: string;
|
|
66
|
-
readonly declared: string | undefined;
|
|
67
|
-
readonly verifiesDeclared: boolean;
|
|
68
|
-
/** 实测缺席时交出那一行 warn(缺席 = 不交;生产装配由 boot 递一只带去重的报告座,见 {@link createLaneHomeAbsenceReporter})。 */
|
|
69
|
-
readonly onAbsent?: ((absence: LaneHomeAbsence) => void) | undefined;
|
|
70
|
-
}
|
|
71
92
|
/**
|
|
72
|
-
*
|
|
93
|
+
* 会读家目录的车道(k8s / local-docker / ssh / adb / e2b / host)的适配器配置里与家目录有关的三个键 —— 文字只写这一处,各配置接口 `extends` 它;
|
|
94
|
+
* {@link LaneHomeSeat} 直接吃它。
|
|
73
95
|
*/
|
|
74
96
|
export interface LaneHomeConfig {
|
|
75
97
|
/**
|
|
76
|
-
* [ref]④ / core [ref] ——
|
|
77
|
-
*
|
|
78
|
-
*
|
|
98
|
+
* [ref]④ / core [ref] —— 部署给本执行环境的 **home 目录主张**(绝对路径,本环境自己的命名空间里):运维声明 `REMOTE_EXEC_HOME_DIR`,或车道出厂答案。
|
|
99
|
+
* `~/…` 形权限规则(`Edit(~/.ssh/**)`)对**跑在本 env 里的调用**就以它为基。值由 `boot/execution-env.ts` 从**唯一属主** `execution-lane-caps.ts` 的
|
|
100
|
+
* `buildLaneHomeClaim` 递进来;adapter 不自算(两处各算一份 = 422 门与引擎对同一条规则给相反答案)。在场 ⇒ 环境开起来时与 `$HOME` 对证,不一致 ⇒ 这只环境不开。
|
|
101
|
+
* 缺席 ⇒ 车道建环境时自己问执行环境的 `$HOME`({@link LaneHomeSeat});实测也缺席 ⇒ 本 env 的 `homeDir` 座缺席,core 对 `~/` 规则判 `unreadable`
|
|
79
102
|
* (fail-closed 的 ask),绝不回落引擎进程自己的 home(那在远端腿上是另一个用户的另一个目录 —— 静默守错目录正是 [ref] 的病)。
|
|
80
103
|
*/
|
|
81
104
|
homeDir?: string;
|
|
82
|
-
/**
|
|
105
|
+
/** {@link homeDir} 的来源(只进拒句的改法):`declared` = `REMOTE_EXEC_HOME_DIR`;`lane` = 车道出厂答案。缺席读作 `declared`。 */
|
|
106
|
+
homeDirSource?: LaneHomeSource;
|
|
107
|
+
/** 实测缺席(没主张、也没问到绝对路径)时交出那一行 warn;缺席 = 不交。生产装配由 boot 递一只带去重的报告座({@link createLaneHomeAbsenceReporter})。 */
|
|
83
108
|
onHomeAbsent?: (absence: LaneHomeAbsence) => void;
|
|
84
109
|
}
|
|
85
110
|
/**
|
|
86
|
-
* 一只执行环境的家目录座 —— `ExecutionEnv.homeDir`
|
|
87
|
-
*
|
|
111
|
+
* 一只执行环境的家目录座 —— `ExecutionEnv.homeDir` 的**唯一取值律**:主张在场 ⇒ 主张(并在开环境时被证);否则 ⇒ 车道开环境时实测到的绝对路径;
|
|
112
|
+
* 实测也缺席 ⇒ `undefined`(引擎失败关闭)。车道只做两件事:`asks` 为真时读一次(命令通道跑 {@link LANE_HOME_PROBE_COMMAND},或直接读自己组合的 env),
|
|
113
|
+
* 把读数交给 {@link settle};`homeDir` 读 {@link home}。
|
|
88
114
|
*/
|
|
89
115
|
export declare class LaneHomeSeat {
|
|
90
116
|
private measured;
|
|
91
117
|
private readonly lane;
|
|
92
|
-
private readonly
|
|
93
|
-
private readonly verifiesDeclared;
|
|
118
|
+
private readonly claim;
|
|
94
119
|
private readonly onAbsent;
|
|
95
|
-
|
|
96
|
-
/**
|
|
120
|
+
private readonly paths;
|
|
121
|
+
/** `paths` = 执行环境自己的路径平台({@link LanePathFlavor};缺省 POSIX —— 只有 win32 宿主上的 host 适配器说 `win32`)。 */
|
|
122
|
+
constructor(lane: string, config: LaneHomeConfig, paths?: LanePathFlavor);
|
|
123
|
+
/** 座:主张胜,否则实测,否则缺席。 */
|
|
97
124
|
get home(): string | undefined;
|
|
98
|
-
/**
|
|
125
|
+
/** 这一拍还要不要问:主张在场 ⇒ 每只新环境 / 每条新连接都问(对证);没主张 ⇒ 问到量出绝对路径为止。 */
|
|
99
126
|
get asks(): boolean;
|
|
100
127
|
/**
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* 不对证的车道声明在场时不该来问(`asks` 为假),来了照单全收。
|
|
128
|
+
* 收一次读数。主张在场 ⇒ {@link judgeLaneHome}:`undefined` = 一致,否则这只环境不开(拒句 + 记不记见 {@link LaneHomeVerdict});
|
|
129
|
+
* 没主张 ⇒ 读到绝对路径就记下;读不到 / 不是绝对路径 ⇒ 座缺席、交一行 warn、**不拒环境**(`undefined`)—— 没主张就没有主张可拒,引擎对缺席座失败关闭。
|
|
104
130
|
*/
|
|
105
131
|
settle(probe: LaneHomeProbe): LaneHomeVerdict;
|
|
106
132
|
}
|
package/dist/lane-home-probe.js
CHANGED
|
@@ -2,7 +2,13 @@ export const LANE_HOME_PROBE_MARKER = "sema-lane-home=";
|
|
|
2
2
|
export const LANE_HOME_PROBE_COMMAND = `printf '\\n${LANE_HOME_PROBE_MARKER}%s\\n' "$HOME"`;
|
|
3
3
|
const SHOWN_MAX = 256;
|
|
4
4
|
const shown = (raw) => JSON.stringify(raw.length > SHOWN_MAX ? `${raw.slice(0, SHOWN_MAX)}…` : raw);
|
|
5
|
-
const
|
|
5
|
+
const isAbsoluteHome = (p, paths) => (paths === "win32" ? /^[A-Za-z]:[\\/]/.test(p) || /^[\\/]{2}[^\\/]/.test(p) : p.startsWith("/"));
|
|
6
|
+
const comparable = (p, paths) => {
|
|
7
|
+
if (paths === "posix")
|
|
8
|
+
return p.length > 1 ? p.replace(/\/+$/, "") : p;
|
|
9
|
+
const q = p.replace(/\//g, "\\").toLowerCase();
|
|
10
|
+
return /^[a-z]:\\$/.test(q) ? q : q.replace(/\\+$/, "");
|
|
11
|
+
};
|
|
6
12
|
function markedHome(stdout) {
|
|
7
13
|
const lines = stdout.split("\n").map((l) => l.replace(/\r$/, ""));
|
|
8
14
|
const marked = lines.flatMap((l, i) => (l.startsWith(LANE_HOME_PROBE_MARKER) ? [i] : []));
|
|
@@ -13,34 +19,45 @@ function markedHome(stdout) {
|
|
|
13
19
|
return { why: "the probe output holds more than one home line or text after it, so it cannot be read as one path" };
|
|
14
20
|
return { home: lines[at].slice(LANE_HOME_PROBE_MARKER.length) };
|
|
15
21
|
}
|
|
16
|
-
function readLaneHome(probe) {
|
|
22
|
+
function readLaneHome(probe, paths) {
|
|
17
23
|
if (!probe.ok)
|
|
18
24
|
return { kind: "unread", reason: probe.reason };
|
|
19
|
-
|
|
20
|
-
if ("
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
let home;
|
|
26
|
+
if ("value" in probe)
|
|
27
|
+
home = probe.value;
|
|
28
|
+
else {
|
|
29
|
+
const marked = markedHome(probe.stdout);
|
|
30
|
+
if ("why" in marked)
|
|
31
|
+
return { kind: "unread", reason: marked.why };
|
|
32
|
+
home = marked.home;
|
|
33
|
+
}
|
|
34
|
+
return isAbsoluteHome(home, paths) ? { kind: "home", home } : { kind: "not_absolute", value: home };
|
|
23
35
|
}
|
|
24
|
-
export function judgeLaneHome(lane,
|
|
25
|
-
const
|
|
26
|
-
const
|
|
36
|
+
export function judgeLaneHome(lane, claim, probe, paths = "posix") {
|
|
37
|
+
const declared = claim.source === "declared";
|
|
38
|
+
const head = declared
|
|
39
|
+
? `REMOTE_EXEC_HOME_DIR=${shown(claim.home)} is the home "~/" permission rules and the engine's home-anchored read-deny rows are placed under on the ${lane} execution lane`
|
|
40
|
+
: `${shown(claim.home)} — the ${lane} execution lane's own home, used because REMOTE_EXEC_HOME_DIR is unset — is the home "~/" permission rules and the engine's home-anchored read-deny rows are placed under`;
|
|
41
|
+
const unconfirmed = declared ? "the declaration cannot be confirmed" : "that home cannot be confirmed";
|
|
42
|
+
const reading = readLaneHome(probe, paths);
|
|
27
43
|
if (reading.kind === "unread") {
|
|
28
44
|
return {
|
|
29
|
-
refusal: `${head}, but the home of this execution environment could not be read (${reading.reason}) —
|
|
45
|
+
refusal: `${head}, but the home of this execution environment could not be read (${reading.reason}) — ${unconfirmed}, so this environment is not started. ${declared ? "Fix the lane, or unset REMOTE_EXEC_HOME_DIR." : "Fix the lane so the environment answers its $HOME."}`,
|
|
30
46
|
answered: false,
|
|
31
47
|
};
|
|
32
48
|
}
|
|
33
49
|
if (reading.kind === "not_absolute") {
|
|
34
50
|
return {
|
|
35
|
-
refusal: `${head}, but this execution environment reports HOME=${shown(reading.value)}, not an absolute path —
|
|
51
|
+
refusal: `${head}, but this execution environment reports HOME=${shown(reading.value)}, not an absolute path — ${unconfirmed}, so this environment is not started. ${declared ? "Give the environment's user a home (HOME), or unset REMOTE_EXEC_HOME_DIR." : "Give the environment's user a home (HOME)."}`,
|
|
36
52
|
answered: true,
|
|
37
53
|
};
|
|
38
54
|
}
|
|
39
|
-
if (comparable(reading.home) === comparable(
|
|
55
|
+
if (comparable(reading.home, paths) === comparable(claim.home, paths))
|
|
40
56
|
return undefined;
|
|
57
|
+
const measured = shown(reading.home);
|
|
41
58
|
return {
|
|
42
|
-
refusal: `${head}, but its commands run with HOME=${
|
|
43
|
-
`so this environment is not started. Set REMOTE_EXEC_HOME_DIR to ${
|
|
59
|
+
refusal: `${head}, but its commands run with HOME=${measured} — rules would guard ${shown(claim.home)} while ${measured} stays readable and writable, ` +
|
|
60
|
+
`so this environment is not started. Set REMOTE_EXEC_HOME_DIR to ${measured}${declared ? " or remove it" : ""}, or make the environment's HOME read ${shown(claim.home)}.`,
|
|
44
61
|
answered: true,
|
|
45
62
|
};
|
|
46
63
|
}
|
|
@@ -52,37 +69,43 @@ export function buildHomeAbsentNote(lane, cause, remedy) {
|
|
|
52
69
|
}
|
|
53
70
|
const DECLARE_ARG = "REMOTE_EXEC_HOME_DIR=<the absolute path the environment's $HOME reads>";
|
|
54
71
|
export const DECLARE_HOME_REMEDY = `Declare the home: ${DECLARE_ARG}`;
|
|
72
|
+
export const LANE_HOME_UNMEASURED_EVENT = "execution_lane_home_unmeasured";
|
|
73
|
+
export function buildHomeUnmeasuredNote(lane, declared) {
|
|
74
|
+
return (`the ${lane} lane cannot read its execution environment's home, so REMOTE_EXEC_HOME_DIR=${shown(declared)} is taken as declared, not measured: ` +
|
|
75
|
+
`"~/" permission rules and the engine's home-anchored read-deny rows are placed under it. If the environment's $HOME is another directory, those rules guard ${shown(declared)} ` +
|
|
76
|
+
`while the real home stays readable and writable — keep REMOTE_EXEC_HOME_DIR equal to the $HOME the environment's commands see.`);
|
|
77
|
+
}
|
|
55
78
|
export class LaneHomeSeat {
|
|
56
79
|
measured;
|
|
57
80
|
lane;
|
|
58
|
-
|
|
59
|
-
verifiesDeclared;
|
|
81
|
+
claim;
|
|
60
82
|
onAbsent;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this.
|
|
64
|
-
this.
|
|
65
|
-
this.
|
|
83
|
+
paths;
|
|
84
|
+
constructor(lane, config, paths = "posix") {
|
|
85
|
+
this.lane = lane;
|
|
86
|
+
this.paths = paths;
|
|
87
|
+
this.claim = config.homeDir === undefined ? undefined : { home: config.homeDir, source: config.homeDirSource ?? "declared" };
|
|
88
|
+
this.onAbsent = config.onHomeAbsent;
|
|
66
89
|
}
|
|
67
90
|
get home() {
|
|
68
|
-
return this.
|
|
91
|
+
return this.claim?.home ?? this.measured;
|
|
69
92
|
}
|
|
70
93
|
get asks() {
|
|
71
|
-
return this.
|
|
94
|
+
return this.claim !== undefined || this.measured === undefined;
|
|
72
95
|
}
|
|
73
96
|
settle(probe) {
|
|
74
|
-
if (this.
|
|
75
|
-
return
|
|
76
|
-
const reading = readLaneHome(probe);
|
|
97
|
+
if (this.claim !== undefined)
|
|
98
|
+
return judgeLaneHome(this.lane, this.claim, probe, this.paths);
|
|
99
|
+
const reading = readLaneHome(probe, this.paths);
|
|
77
100
|
if (reading.kind === "home") {
|
|
78
101
|
this.measured = reading.home;
|
|
79
102
|
return undefined;
|
|
80
103
|
}
|
|
81
104
|
const because = reading.kind === "unread" ? `could not be read (${reading.reason})` : `reads ${shown(reading.value)}, not an absolute path`;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
: `Give the environment's user an absolute HOME,
|
|
85
|
-
|
|
105
|
+
this.onAbsent?.({
|
|
106
|
+
provider: this.lane,
|
|
107
|
+
note: buildHomeAbsentNote(this.lane, `REMOTE_EXEC_HOME_DIR is unset and the environment's own $HOME ${because}`, "Give the environment's user an absolute HOME (a declared REMOTE_EXEC_HOME_DIR is checked against it, so declaring cannot stand in for it)."),
|
|
108
|
+
});
|
|
86
109
|
return undefined;
|
|
87
110
|
}
|
|
88
111
|
}
|
package/dist/leader/wire.js
CHANGED
|
@@ -9,7 +9,8 @@ import { leaderEntryRefusal, leaderRunEntry } from "./run-entry.js";
|
|
|
9
9
|
import { buildCheckpointCtx } from "../http/checkpoint-ctx.js";
|
|
10
10
|
import { serviceVersion } from "../service-version.js";
|
|
11
11
|
import { RemoteContainerExecutionEnv } from "../plugins/remote-env-e2b.js";
|
|
12
|
-
import {
|
|
12
|
+
import { buildLaneHomeClaim } from "../execution-lane-caps.js";
|
|
13
|
+
const e2bBaseTemplateHomeSeat = buildLaneHomeClaim({ remoteExec: { provider: "e2b" } });
|
|
13
14
|
import { createDurableAskPolicy } from "../approval.js";
|
|
14
15
|
import { gitSubprocessEnv } from "../server-secret-env.js";
|
|
15
16
|
import { presignS3Url } from "../plugins/s3-presign.js";
|
|
@@ -366,7 +367,7 @@ export function createLeaderRunner(cfg) {
|
|
|
366
367
|
}
|
|
367
368
|
if (!cfg.e2bApiKey)
|
|
368
369
|
throw new Error("leader wire: no envFactory+s3 (factory mode) and no e2bApiKey (static mode)");
|
|
369
|
-
const env = new RemoteContainerExecutionEnv({ apiKey: cfg.e2bApiKey, timeoutMs: leaderTimeoutMs,
|
|
370
|
+
const env = new RemoteContainerExecutionEnv({ apiKey: cfg.e2bApiKey, timeoutMs: leaderTimeoutMs, ...e2bBaseTemplateHomeSeat });
|
|
370
371
|
if (!(await env.connect()).ok)
|
|
371
372
|
throw new Error(`connect failed for ${sub.workerId}`);
|
|
372
373
|
await sh(env)(`${body.seedCmd}; cd ${repo}; git checkout -q -b ${sub.branch}`);
|
|
@@ -399,7 +400,7 @@ export function createLeaderRunner(cfg) {
|
|
|
399
400
|
}
|
|
400
401
|
if (!cfg.e2bApiKey)
|
|
401
402
|
throw new Error("leader wire: no envFactory and no e2bApiKey");
|
|
402
|
-
const env = new RemoteContainerExecutionEnv({ apiKey: cfg.e2bApiKey, timeoutMs: leaderTimeoutMs,
|
|
403
|
+
const env = new RemoteContainerExecutionEnv({ apiKey: cfg.e2bApiKey, timeoutMs: leaderTimeoutMs, ...e2bBaseTemplateHomeSeat });
|
|
403
404
|
if (!(await env.connect()).ok) {
|
|
404
405
|
await env.destroy().catch(() => { });
|
|
405
406
|
throw new Error("integ connect failed");
|
|
@@ -439,7 +440,7 @@ export function createLeaderRunner(cfg) {
|
|
|
439
440
|
else {
|
|
440
441
|
if (!cfg.e2bApiKey)
|
|
441
442
|
throw new Error("leader wire: repair-loop grader needs an envFactory or e2bApiKey");
|
|
442
|
-
const e2b = new RemoteContainerExecutionEnv({ apiKey: cfg.e2bApiKey, timeoutMs: leaderTimeoutMs,
|
|
443
|
+
const e2b = new RemoteContainerExecutionEnv({ apiKey: cfg.e2bApiKey, timeoutMs: leaderTimeoutMs, ...e2bBaseTemplateHomeSeat });
|
|
443
444
|
if (!(await e2b.connect()).ok) {
|
|
444
445
|
await e2b.destroy().catch(() => { });
|
|
445
446
|
throw new Error("repair-loop grader connect failed");
|
|
@@ -4,11 +4,18 @@
|
|
|
4
4
|
* ## 为什么需要这个模块(而不是在 main.ts 里直接 new)
|
|
5
5
|
*
|
|
6
6
|
* 本仓**没有**一个长命的 `MemoryEngine` 实例:`boot/stores.ts` 装配出来的 `memoryEngine` 是
|
|
7
|
-
* `
|
|
7
|
+
* 记忆作用域店(`memory-scope-stores.ts`:部署的店 + 引擎根 + 「一层住哪只店」的唯一读者),真正的引擎由 **core 的 Runner 每任务现构**
|
|
8
8
|
* (`core/runner/prepare-memory.js`),而且构出来的 `memoryDir` 是**按任务的 scope 平面**决定的
|
|
9
9
|
* (personal / project / dual-root 三形,还要看仓根、项目标记、pinned 目录)。
|
|
10
10
|
* 也就是说「这个部署的那一个记忆引擎」这个东西**在本仓不存在** —— HTTP 面若要一个引擎,必须自己构。
|
|
11
11
|
*
|
|
12
|
+
* ## 引擎建在哪只店上:包点名的层住的那只
|
|
13
|
+
* 导出按请求的 `scopes` 定店,导入按包自己的 `bundle.scopes` 定店(core 的整包判决保证包里每一条的层都在 `bundle.scopes` 里 —— 自洽是它的校验项);
|
|
14
|
+
* 几层分住两只店 ⇒ 拒(`request.memory_layer`):一只包是**一只店**单锁复合面里的一个 epoch,两只店封不出一只包。规则唯一属主
|
|
15
|
+
* `memory-scope-stores.ts` 的 {@link memoryStoreForRequest}。`bundle.scopes` 读不成「非空的非空串数组」的包,本来就过不了 core 的整包判决
|
|
16
|
+
* (结构项第一条),交部署的店那只引擎去判 —— 拒是包本身的函数,哪只引擎判都一样,什么都不落。
|
|
17
|
+
* 修前两面都在部署的店上建引擎:目录钉住的部署上,类型化个人层的条目在个人挂载上的另一只店里 —— 导出的包里没有会话写的条目,导入的落在会话不读的店。
|
|
18
|
+
*
|
|
12
19
|
* ## 为什么自己构是安全的:这两个面是 **backend-scoped**,不碰 `memoryDir`
|
|
13
20
|
*
|
|
14
21
|
* 亲读 core 5.40.0 的 `memory-engine/engine.js`(不信 JSDoc,读实现):
|
|
@@ -41,7 +48,9 @@
|
|
|
41
48
|
* `memory.export_incomplete` —— 那是诚实的运行期拒,附录 A 单列一条。绝不在这里回落到「用通用读面拼
|
|
42
49
|
* 一个包」:core 明写那正是它拒绝生产的形(a governance-less export is the laundering shape)。
|
|
43
50
|
*/
|
|
44
|
-
import { type
|
|
51
|
+
import { type MemoryExportBundle, type MemoryImportReport } from "@sema-agent/core";
|
|
52
|
+
import { type MemoryScopeStores } from "./memory-scope-stores.js";
|
|
53
|
+
import type { SessionCaptureRecordSource } from "./plugins/store-backend.js";
|
|
45
54
|
/** 两口 HTTP 面消费的窄能力面(`ServiceDeps.memoryBundle{Export,Import}` 的实参来源)。 */
|
|
46
55
|
export interface MemoryBundleFaces {
|
|
47
56
|
exportScopes: (scopes: readonly string[]) => Promise<MemoryExportBundle>;
|
|
@@ -51,17 +60,15 @@ export interface MemoryBundleFaces {
|
|
|
51
60
|
}) => Promise<MemoryImportReport>;
|
|
52
61
|
}
|
|
53
62
|
/**
|
|
54
|
-
*
|
|
63
|
+
* 在**记忆作用域店**上建 bundle 两面。命名照 CLAUDE.md 工厂律:返回的是带行为的活对象 ⇒ `create*`。
|
|
55
64
|
*
|
|
56
|
-
*
|
|
65
|
+
* 店:见文件头「引擎建在哪只店上」;一只店一只引擎。
|
|
66
|
+
* `memoryDir` = 那只店的**挂载平面**(`memoryMountRootOf(store, root)` 单铸点;全仓自构引擎同一条规则,
|
|
57
67
|
* 由 `test/memory-layout-plane.test.ts` 的归一门咬住)。见文件头:这两条路径**不读它**(机器钉在
|
|
58
68
|
* `test/memory-bundle-engine.test.ts`:给一个不存在的 `memoryDir` 也照样工作),传对的那一只是为了
|
|
59
69
|
* 万一 core 日后真用上时,它拿到的是本部署真正的挂载平面,而不是高一层的配置根。
|
|
60
70
|
*/
|
|
61
|
-
export declare function createMemoryBundleFaces(
|
|
62
|
-
|
|
63
|
-
root: string;
|
|
64
|
-
}, opts?: {
|
|
65
|
-
captureRecordStore?: SessionCaptureRecordStore;
|
|
71
|
+
export declare function createMemoryBundleFaces(stores: MemoryScopeStores, opts?: {
|
|
72
|
+
captureRecords?: SessionCaptureRecordSource;
|
|
66
73
|
}): MemoryBundleFaces | undefined;
|
|
67
74
|
//# sourceMappingURL=memory-bundle-engine.d.ts.map
|
|
@@ -1,13 +1,36 @@
|
|
|
1
1
|
import { MemoryEngine } from "@sema-agent/core";
|
|
2
2
|
import { memoryMountRootOf } from "./memory-scope.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import { memoryStoreForRequest } from "./memory-scope-stores.js";
|
|
4
|
+
import { captureRecordStoreOf } from "./memory-operator-faces.js";
|
|
5
|
+
export function createMemoryBundleFaces(stores, opts) {
|
|
6
|
+
if (!carriesBundleComposite(stores.backend))
|
|
6
7
|
return undefined;
|
|
7
|
-
const
|
|
8
|
+
const engines = new Map();
|
|
9
|
+
const engineOf = (store) => {
|
|
10
|
+
const known = engines.get(store);
|
|
11
|
+
if (known !== undefined)
|
|
12
|
+
return known;
|
|
13
|
+
if (!carriesBundleComposite(store))
|
|
14
|
+
throw new Error("the memory store that holds these layers implements no v2-c bundle composite (exportSnapshotOf / importBundleCommit) — a bundle is never assembled outside one");
|
|
15
|
+
const records = captureRecordStoreOf(opts?.captureRecords, store);
|
|
16
|
+
const engine = new MemoryEngine({ backend: store, memoryDir: memoryMountRootOf(store, stores.root), ...(records !== undefined ? { captureRecordStore: records } : {}) });
|
|
17
|
+
engines.set(store, engine);
|
|
18
|
+
return engine;
|
|
19
|
+
};
|
|
8
20
|
return {
|
|
9
|
-
exportScopes: (scopes) =>
|
|
10
|
-
importBundle: (bundle, opts) =>
|
|
21
|
+
exportScopes: async (scopes) => engineOf(memoryStoreForRequest(stores, scopes)).exportMemoryScopes(scopes),
|
|
22
|
+
importBundle: async (bundle, opts) => {
|
|
23
|
+
const layers = bundleLayersOf(bundle);
|
|
24
|
+
return engineOf(layers.length > 0 ? memoryStoreForRequest(stores, layers) : stores.backend).importMemoryBundle(bundle, opts);
|
|
25
|
+
},
|
|
11
26
|
};
|
|
12
27
|
}
|
|
28
|
+
function carriesBundleComposite(store) {
|
|
29
|
+
const b = store;
|
|
30
|
+
return typeof b.exportSnapshotOf === "function" && typeof b.importBundleCommit === "function";
|
|
31
|
+
}
|
|
32
|
+
function bundleLayersOf(bundle) {
|
|
33
|
+
const scopes = typeof bundle === "object" && bundle !== null ? bundle.scopes : undefined;
|
|
34
|
+
return Array.isArray(scopes) && scopes.length > 0 && scopes.every((s) => typeof s === "string" && s.length > 0) ? scopes : [];
|
|
35
|
+
}
|
|
13
36
|
//# sourceMappingURL=memory-bundle-engine.js.map
|