@sema-agent/server 7.122.0 → 7.123.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 +77 -0
- package/README.md +5 -0
- package/README.zh-CN.md +3 -0
- package/USAGE.md +23 -5
- package/dist/audit.d.ts +1 -1
- package/dist/audit.js +52 -22
- package/dist/auto-mode-face.d.ts +12 -8
- package/dist/auto-mode-face.js +8 -7
- package/dist/boot/config-center.js +3 -0
- package/dist/config-catalog.js +1 -1
- package/dist/config-center/apply-effective.d.ts +1 -1
- package/dist/config-center/apply-effective.js +5 -3
- package/dist/config-center/http-client.js +3 -3
- package/dist/config-center/read-warnings.d.ts +56 -35
- package/dist/config-center/read-warnings.js +67 -19
- package/dist/config-center/types.d.ts +7 -8
- package/dist/config-lkg.d.ts +12 -9
- package/dist/config-lkg.js +38 -39
- package/dist/config-provider.d.ts +3 -2
- package/dist/config-provider.js +2 -2
- package/dist/config-types.d.ts +9 -1
- package/dist/config.d.ts +8 -8
- package/dist/config.js +69 -92
- package/dist/fleet/engine-signal.d.ts +54 -23
- package/dist/fleet/engine-signal.js +29 -5
- package/dist/fleet-client.d.ts +8 -6
- package/dist/fleet-client.js +4 -3
- package/dist/http/dispatch.js +5 -14
- package/dist/http/health-self-report.d.ts +3 -0
- package/dist/http/routes/capabilities.js +2 -1
- package/dist/http/routes/sessions.js +1 -4
- package/dist/http/stored-body-replay.d.ts +4 -3
- package/dist/http/stored-body-replay.js +2 -3
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/leader/leader.d.ts +7 -6
- package/dist/leader/leader.js +3 -1
- package/dist/leader/run-entry.d.ts +2 -2
- package/dist/leader/run-entry.js +3 -3
- package/dist/leader/wire.d.ts +2 -2
- package/dist/model-entry-refusal.d.ts +18 -9
- package/dist/model-entry-refusal.js +19 -14
- package/dist/model-route-endpoint.d.ts +21 -1
- package/dist/model-route-endpoint.js +9 -3
- package/dist/model-route-gap.d.ts +103 -0
- package/dist/model-route-gap.js +80 -0
- package/dist/namespaced-rule-name.d.ts +16 -30
- package/dist/namespaced-rule-name.js +2 -20
- package/dist/observability/fail-open.d.ts +0 -4
- package/dist/observability/fail-open.js +0 -4
- package/dist/plugins/one-time-migrations.js +27 -0
- package/dist/plugins/session-policy-store-sql.js +1 -2
- package/dist/plugins/workflow-run-store-sql.d.ts +4 -2
- package/dist/rule-entry-list.d.ts +3 -13
- package/dist/rule-entry-list.js +1 -12
- package/dist/run-local.js +4 -4
- package/dist/runtime-governance.d.ts +31 -8
- package/dist/runtime-governance.js +7 -2
- package/dist/session-policy-wire.d.ts +47 -49
- package/dist/session-policy-wire.js +41 -36
- package/dist/session-sync.d.ts +5 -1
- package/dist/session-sync.js +2 -1
- package/dist/spec-fields.d.ts +4 -4
- package/dist/spec-fields.js +1 -4
- package/dist/task-settings.d.ts +4 -5
- package/dist/task-settings.js +5 -8
- package/dist/unattended-permission-mode.d.ts +3 -3
- package/dist/unattended-permission-mode.js +2 -2
- package/package.json +3 -3
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { PROTOCOL_TABLE, SessionPolicyError, assertSessionRuleNamesCurrent } from "@sema-agent/core";
|
|
1
|
+
import { PROTOCOL_TABLE, SessionPolicyError, assertSessionRuleNamesCurrent, normalizeRules } from "@sema-agent/core";
|
|
2
2
|
import { displayListEntry } from "./list-entry-display.js";
|
|
3
|
-
import { describeEmptyToolSegment, emptyToolSegmentOf } from "./namespaced-rule-name.js";
|
|
4
3
|
const RULE_FIELDS = {
|
|
5
4
|
toolAllow: true,
|
|
6
5
|
toolDeny: true,
|
|
@@ -20,33 +19,18 @@ function legacyToolNameRefusalOf(rules) {
|
|
|
20
19
|
throw e;
|
|
21
20
|
}
|
|
22
21
|
}
|
|
23
|
-
const TOOL_NAME_FIELD_TABLE = { toolAllow: "toolAllow", toolDeny: "toolDeny" };
|
|
24
|
-
const TOOL_NAME_FIELDS = Object.values(TOOL_NAME_FIELD_TABLE);
|
|
25
|
-
export function unreachableSessionRuleNameOf(rules) {
|
|
26
|
-
for (const field of TOOL_NAME_FIELDS) {
|
|
27
|
-
for (const name of rules[field] ?? []) {
|
|
28
|
-
const ns = emptyToolSegmentOf(name);
|
|
29
|
-
if (ns !== undefined)
|
|
30
|
-
return { field, name, ns };
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return undefined;
|
|
34
|
-
}
|
|
35
|
-
export function assertSessionRuleNamesReachable(rules) {
|
|
36
|
-
const unreachable = unreachableSessionRuleNameOf(rules);
|
|
37
|
-
if (unreachable !== undefined)
|
|
38
|
-
throw new Error(describeUnreachableSessionRuleName(unreachable));
|
|
39
|
-
}
|
|
40
22
|
function protocolToolNameShapes() {
|
|
41
23
|
return PROTOCOL_TABLE.map((ns) => `${ns.prefix}<peer>__<tool>`).join(" or ");
|
|
42
24
|
}
|
|
25
|
+
function isRulesObject(raw) {
|
|
26
|
+
return raw !== null && typeof raw === "object" && !Array.isArray(raw);
|
|
27
|
+
}
|
|
43
28
|
export function readSessionPermissionRules(raw) {
|
|
44
|
-
if (
|
|
29
|
+
if (!isRulesObject(raw))
|
|
45
30
|
return { problem: { kind: "not-an-object" } };
|
|
46
|
-
const src = raw;
|
|
47
31
|
const rules = {};
|
|
48
32
|
for (const field of SESSION_PERMISSION_RULE_FIELDS) {
|
|
49
|
-
const v =
|
|
33
|
+
const v = raw[field];
|
|
50
34
|
if (v === undefined)
|
|
51
35
|
continue;
|
|
52
36
|
if (!Array.isArray(v) || !v.every((x) => typeof x === "string"))
|
|
@@ -55,17 +39,42 @@ export function readSessionPermissionRules(raw) {
|
|
|
55
39
|
}
|
|
56
40
|
return { rules };
|
|
57
41
|
}
|
|
42
|
+
function engineRuleListOf(field, value) {
|
|
43
|
+
let normalized;
|
|
44
|
+
try {
|
|
45
|
+
normalized = normalizeRules({ [field]: value });
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
if (e instanceof TypeError)
|
|
49
|
+
return { refusal: e.message };
|
|
50
|
+
throw e;
|
|
51
|
+
}
|
|
52
|
+
const list = normalized[field];
|
|
53
|
+
return list === undefined ? {} : { list };
|
|
54
|
+
}
|
|
55
|
+
export function unwritableRuleListOf(rules) {
|
|
56
|
+
for (const field of SESSION_PERMISSION_RULE_FIELDS) {
|
|
57
|
+
const judged = engineRuleListOf(field, rules[field]);
|
|
58
|
+
if ("refusal" in judged)
|
|
59
|
+
return { field, refusal: judged.refusal };
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
58
63
|
export function readWritableSessionPermissionRules(raw) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const
|
|
64
|
+
if (!isRulesObject(raw))
|
|
65
|
+
return { problem: { kind: "not-an-object" } };
|
|
66
|
+
const rules = {};
|
|
67
|
+
for (const field of SESSION_PERMISSION_RULE_FIELDS) {
|
|
68
|
+
const judged = engineRuleListOf(field, raw[field]);
|
|
69
|
+
if ("refusal" in judged)
|
|
70
|
+
return { problem: { kind: "field-not-rule-list", field, refusal: judged.refusal } };
|
|
71
|
+
if (judged.list !== undefined)
|
|
72
|
+
rules[field] = judged.list;
|
|
73
|
+
}
|
|
74
|
+
const refusal = legacyToolNameRefusalOf(rules);
|
|
63
75
|
if (refusal !== undefined)
|
|
64
76
|
return { problem: { kind: "legacy-tool-name", refusal } };
|
|
65
|
-
|
|
66
|
-
if (unreachable !== undefined)
|
|
67
|
-
return { problem: { kind: "unreachable-tool-name", unreachable } };
|
|
68
|
-
return read;
|
|
77
|
+
return { rules };
|
|
69
78
|
}
|
|
70
79
|
export function readSessionRulesRecords(raw) {
|
|
71
80
|
if (!Array.isArray(raw))
|
|
@@ -91,17 +100,14 @@ export function describeSessionPermissionRulesProblem(p) {
|
|
|
91
100
|
switch (p.kind) {
|
|
92
101
|
case "not-an-object": return "rules must be a SessionPermissionRules object";
|
|
93
102
|
case "field-not-string-array": return `${p.field} must be an array of strings`;
|
|
103
|
+
case "field-not-rule-list": return p.refusal;
|
|
94
104
|
case "legacy-tool-name": return describeLegacyToolName(p.refusal);
|
|
95
|
-
case "unreachable-tool-name": return describeUnreachableSessionRuleName(p.unreachable);
|
|
96
105
|
default: {
|
|
97
106
|
const unhandled = p;
|
|
98
107
|
throw new Error(`unhandled SessionPermissionRules problem: ${JSON.stringify(unhandled)}`);
|
|
99
108
|
}
|
|
100
109
|
}
|
|
101
110
|
}
|
|
102
|
-
function describeUnreachableSessionRuleName(u) {
|
|
103
|
-
return `${u.field} names ${displayListEntry(u.name)}, which can never match a tool (${describeEmptyToolSegment(u.ns)}), so nothing was written`;
|
|
104
|
-
}
|
|
105
111
|
function describeLegacyToolName(r) {
|
|
106
112
|
const why = r.guidance !== undefined ? ` (${r.guidance})` : "";
|
|
107
113
|
switch (r.verdict) {
|
|
@@ -126,8 +132,7 @@ export function legacyToolNameProblemOf(p) {
|
|
|
126
132
|
case "rules":
|
|
127
133
|
switch (p.problem.kind) {
|
|
128
134
|
case "not-an-object":
|
|
129
|
-
case "field-not-
|
|
130
|
-
case "unreachable-tool-name":
|
|
135
|
+
case "field-not-rule-list":
|
|
131
136
|
return undefined;
|
|
132
137
|
case "legacy-tool-name":
|
|
133
138
|
return p.problem.refusal;
|
package/dist/session-sync.d.ts
CHANGED
|
@@ -159,7 +159,11 @@ export declare function planSync(sessionId: string, srcBackend: StoreBackend, ds
|
|
|
159
159
|
* 无条件写都 rev+1,而 rev 是 operator 乐观锁的 CAS 令牌(`PutRulesOptions.expectedRev`),
|
|
160
160
|
* 幂等重试/无害重复同步不该把在途 CAS 打失败。归一化用 core 的 `normalizeRules`(store 落盘
|
|
161
161
|
* 前走同一函数 ⇒ 两侧同坐标);`stripRev` 去掉记录内嵌的 rev(`listBySession` 的 rules 含 rev,
|
|
162
|
-
* 它不是内容)。
|
|
162
|
+
* 它不是内容)。
|
|
163
|
+
* 🔴 core 7.48.0 起 `normalizeRules` 对「不是一列非空字符串」的桶抛 `TypeError`。`incoming` 由写口读者保证是引擎肯写的
|
|
164
|
+
* (`session-policy-wire.ts` `readSessionRulesRecords`);`stored` 可能是 7.47.x 及以前写下的空串项存量行 —— 读得出、引擎却不肯再写。
|
|
165
|
+
* 这种行与任何肯写的 `incoming` 都**不同内容**(它多一个空项),所以答 `false`(判官 = 写口读者那一只 `unwritableRuleListOf`,不拿它跑 normalize):
|
|
166
|
+
* 写照常交给店 —— 店的收紧门对它照常判(operator 照写,是清旧行的出路;非 operator 删空串 deny 项被读成放宽 ⇒ 403,与 7.122.0 同答)。 */
|
|
163
167
|
export declare function sameRulesContent(stored: StoredSessionRules | null, incoming: SessionPermissionRules): boolean;
|
|
164
168
|
/** [ref] ① 的重放腿共享实现:PUSH 路由的两条 policy 重放腿(Phase A identical 短路支 / Phase B
|
|
165
169
|
* commit 后支)都从这里走 —— 等内容跳过(rev 零漂移),真变更照常落地(E6 tighten-only 门在
|
package/dist/session-sync.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { classifySyncRelationship } from "./session-sync-kernel.js";
|
|
2
2
|
import { normalizeRules, stripRev } from "@sema-agent/core";
|
|
3
|
+
import { unwritableRuleListOf } from "./session-policy-wire.js";
|
|
3
4
|
export function fileHistoryImportFace(fs) {
|
|
4
5
|
const candidate = fs?.importHistory;
|
|
5
6
|
if (typeof candidate !== "function")
|
|
@@ -54,7 +55,7 @@ export async function planSync(sessionId, srcBackend, dstBackend) {
|
|
|
54
55
|
return classifySyncRelationship(srcEntries, dstEntries);
|
|
55
56
|
}
|
|
56
57
|
export function sameRulesContent(stored, incoming) {
|
|
57
|
-
if (stored === null)
|
|
58
|
+
if (stored === null || unwritableRuleListOf(stored) !== undefined)
|
|
58
59
|
return false;
|
|
59
60
|
const norm = (r) => JSON.stringify(normalizeRules(stripRev(r)));
|
|
60
61
|
return norm(stored) === norm(incoming);
|
package/dist/spec-fields.d.ts
CHANGED
|
@@ -51,16 +51,16 @@ export declare const MAX_TASK_AGENTS = 32;
|
|
|
51
51
|
* `ruleEntryListShapeOk`):引擎直接 `for (const entry of list)` —— 一个裸字符串 `"Bash"` 会被逐字符迭代成 `B` / `a` / `s` / `h` 四条
|
|
52
52
|
* (deny 侧 = 意图静默落空,安全轴上的放宽方向)。条目的**文法与名字**是引擎的读法:允侧读不出的条目(`*` / 写路径 / 域名 / 退役名 …)引擎在开跑时发
|
|
53
53
|
* `permission.allowed_tool_not_granted`(受众 = 用户);拒侧读成空的条目(文法或名字层)在 `resolveSpec` 拒(提交 400 / 续跑 409,`rule-entry-list.ts` 的
|
|
54
|
-
* `skillDenyInertEntryOf`,判据 = 引擎的条目读法)。形对之后两道门再问 {@link skillToolListRefusal}(条数帽
|
|
54
|
+
* `skillDenyInertEntryOf`,判据 = 引擎的条目读法)。形对之后两道门再问 {@link skillToolListRefusal}(条数帽 ⇒ 400)。
|
|
55
55
|
* 条数帽 = 条目表那一只(`rule-entry-list.ts` `allowLayerEntryCountIssue`,准备开销的界;与请求 allow 桶、运维表同一只),
|
|
56
56
|
* 在 {@link skillToolListRefusal} 里判;无长度帽([ref])。
|
|
57
57
|
*/
|
|
58
58
|
export declare const skillToolListOk: (v: unknown) => v is readonly string[];
|
|
59
59
|
/**
|
|
60
60
|
* 一条技能(形已过两道门的字符串数组判)的两只清单在受理口的拒因 —— 都过 ⇒ `undefined`。两处受理口同调:顶层 `skills[]`
|
|
61
|
-
* (`http/admission.ts` 的 `validateUserSkills`)、子代 `agents[].skills[]`({@link validateTaskAgents})
|
|
62
|
-
*
|
|
63
|
-
*
|
|
61
|
+
* (`http/admission.ts` 的 `validateUserSkills`)、子代 `agents[].skills[]`({@link validateTaskAgents})。一问:条数帽。退役名 / 对端段或工具段铸不出、为空 /
|
|
62
|
+
* 读成空的条目是引擎的读法(见上):允侧交引擎通告,拒侧由 `resolveSpec` 拒(7.116.0–7.122.x 本仓在这里另拒工具段为空的协议名,core 7.48.0 #1400 起
|
|
63
|
+
* 它是引擎判官的判词,随之退役)。
|
|
64
64
|
*/
|
|
65
65
|
export declare function skillToolListRefusal(skill: Record<string, unknown>): string | undefined;
|
|
66
66
|
/** [ref] 单条 agent 定义的形状裁决:null=合法;否则一句可 400 的英文错误(不带索引,调用方自己加)。
|
package/dist/spec-fields.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isThinkingLevel } from "@sema-agent/core";
|
|
2
2
|
import { taskWallClockSec } from "./task-workflow.js";
|
|
3
3
|
import { isValidCwd } from "./task-cwd.js";
|
|
4
|
-
import { allowLayerEntryCountIssue,
|
|
4
|
+
import { allowLayerEntryCountIssue, ruleEntryListShapeOk } from "./rule-entry-list.js";
|
|
5
5
|
export function normalizeSuggestNextPrompts(v) {
|
|
6
6
|
if (v === true)
|
|
7
7
|
return true;
|
|
@@ -76,9 +76,6 @@ export function skillToolListRefusal(skill) {
|
|
|
76
76
|
const over = allowLayerEntryCountIssue(`skill.${key}`, list);
|
|
77
77
|
if (over !== undefined)
|
|
78
78
|
return over.message;
|
|
79
|
-
const empty = emptyToolSegmentEntryOf(list);
|
|
80
|
-
if (empty !== undefined)
|
|
81
|
-
return describeEmptyToolSegmentEntry(`skill.${key}`, empty);
|
|
82
79
|
}
|
|
83
80
|
return undefined;
|
|
84
81
|
}
|
package/dist/task-settings.d.ts
CHANGED
|
@@ -108,13 +108,12 @@ export declare function planReviewDecisionExitsPlan(decision: "approve" | "edit"
|
|
|
108
108
|
/**
|
|
109
109
|
* 运维 `AUTONOMY=plan` 的**入口词地板**盖进提交体 —— 此后一条 run 的模式词只有存储体顶层 `permissionMode` 一个源。
|
|
110
110
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
111
|
+
* 入口词 = `runtime-governance.ts` `entryPermissionMode(体的生效词, 地板).effective`(「词在地板下变成什么」的唯一一只函数;秩是 core 的)。本函数只加
|
|
112
|
+
* 「写进体」这一半:地板缺席 ⇒ 体**原物**交回(零字节变化);地板在场 ⇒ 新体 `{ ...body, permissionMode: 入口词 }`,调用方的对象不改;bundle 的
|
|
113
113
|
* `settings.permissions.defaultMode` 不动 —— 顶层赢过它({@link effectivePermissionMode} 的优先序),再改它就是同一语义的第二个写者。
|
|
114
114
|
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* 装配腿与续跑腿都不读地板(两处读 = 两个源)。run-local 自建 spec、收不到客户端表态,在它的出生点直接写地板本身(同一个入口词)。
|
|
115
|
+
* 调用点一个:提交入口(`http/admission.ts` 的 `prepareSpec`:值形门全部判完之后、`resolveSpec` 之前)。那一份体就是首跑装配读的体,也是
|
|
116
|
+
* `buildCheckpointCtx` 持久化的体 ⇒ 一处盖章同时覆盖首跑与每一次续跑重建;装配腿与续跑腿都不读地板(两处读 = 两个源)。
|
|
118
117
|
* 另一个写者是 `plan_review` 写回(`http/resume-legs.ts` `drivePlanReview`,判据 {@link planReviewDecisionExitsPlan})。
|
|
119
118
|
* 热改 `AUTONOMY` 只影响之后提交的任务:在飞的 run 保持它出生时盖下的词。地板的属主是 `runtime-governance.ts` 的 `autonomyModeFloor`。
|
|
120
119
|
*/
|
package/dist/task-settings.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { combinePolicies, createFsWriteGatePolicy, parseRuleText, resolveReasoningProfile, rankOf, isThinkingLevel, CYBER_RISK, URL_SAFETY, HARNESS_SECTION_ANCHOR, RUN_WORKFLOW_TOOL_NAME, PERMISSION_MODES, isPermissionMode, ruleToolGrammarOf, } from "@sema-agent/core";
|
|
2
2
|
import { unmatchableToolNamesRefusal } from "./config.js";
|
|
3
3
|
import { MAX_PERMISSION_RULES_PER_LIST, createRuleListPolicy } from "./permission-rule-list.js";
|
|
4
|
-
import { allowLayerEntryCountIssue, describeAllowLayerOverCap,
|
|
4
|
+
import { allowLayerEntryCountIssue, describeAllowLayerOverCap, ruleEntryListShapeOk } from "./rule-entry-list.js";
|
|
5
5
|
import { tightenGoverned } from "./governance-overrides.js";
|
|
6
6
|
import { MAX_KEY_ECHO, keyClosureClause, scanKeyClosure } from "./request-key-closure.js";
|
|
7
7
|
import { parseHooksConfig } from "./hooks/hook-runner.js";
|
|
8
8
|
import { heldRuleName } from "./tool-rule-names.js";
|
|
9
|
+
import { entryPermissionMode } from "./runtime-governance.js";
|
|
9
10
|
import { policyAskStandingAnswerFacts, standingAnswerDurablyRecordable } from "./tool-approval.js";
|
|
10
11
|
export const PERMISSION_MODE_WORDS = PERMISSION_MODES.map((m) => `"${m}"`).join(" | ");
|
|
11
12
|
export function coercePermissionMode(raw) {
|
|
@@ -33,9 +34,8 @@ export function planReviewDecisionExitsPlan(decision) {
|
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
export function stampEntryPermissionMode(body, floor) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return { ...body, permissionMode: clampPermissionMode(storedBodyPermissionMode(body), floor).effective };
|
|
37
|
+
const entry = entryPermissionMode(storedBodyPermissionMode(body), floor);
|
|
38
|
+
return entry.floor === undefined ? body : { ...body, permissionMode: entry.effective };
|
|
39
39
|
}
|
|
40
40
|
export function storedBodyPermissionMode(body) {
|
|
41
41
|
return effectivePermissionMode(body, parseTaskSettings(body.settings).settings);
|
|
@@ -347,9 +347,6 @@ function rejectUnmatchableSettingsNames(perms, pathBases) {
|
|
|
347
347
|
if (unmatchable !== undefined)
|
|
348
348
|
throw new Error(unmatchable.message);
|
|
349
349
|
}
|
|
350
|
-
const emptyAllow = perms.allow !== undefined ? emptyToolSegmentEntryOf(perms.allow) : undefined;
|
|
351
|
-
if (emptyAllow !== undefined)
|
|
352
|
-
throw new Error(describeEmptyToolSegmentEntry("permissions.allow", emptyAllow));
|
|
353
350
|
}
|
|
354
351
|
export function deriveSettingsPolicy(settings, gate, workflowGate) {
|
|
355
352
|
const perms = settings.permissions;
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
* · 续跑腿上的协调器席:`http/resume-legs.ts` 只在「run 行在场 ∧ 活卡协调器在场」时给 spec 另装活席(`deps.toolApproval && taskId`)——
|
|
45
45
|
* leader worker 的会话没有 run 行,那一装今天够不着本腿;哪天够着了,活席会盖掉本层(方向 = 多问人,fail-closed),见收车档 ⑤。
|
|
46
46
|
*/
|
|
47
|
-
import {
|
|
47
|
+
import type { AskClass, AskRequest, OnAsk, PermissionMode, TaskSpec } from "@sema-agent/core";
|
|
48
48
|
/**
|
|
49
49
|
* 按类作答的**答集** —— core §4.6e 推荐形:机器只答 `ordinary`。**常量,不是旋钮**([ref]):要放更多类是部署级的安全决定,先立案候裁。
|
|
50
50
|
* 不变量(测试钉):答集 ⊆ core 每一面的可放行类 `releasableAskClassesFor(face)`(本层不读问的面,同一只答集答每一面的问),且与带 `requiresRealApproval` 的类
|
|
@@ -72,8 +72,8 @@ export type UnattendedLegSpec = {
|
|
|
72
72
|
readonly onAsk: UnattendedSeat;
|
|
73
73
|
};
|
|
74
74
|
/**
|
|
75
|
-
* 无人值守腿并进一条 spec —— 各腿的**唯一**合并口:`permissionMode` = `"default"` 钳在 spec 已有的模式词之下(
|
|
76
|
-
* `
|
|
75
|
+
* 无人值守腿并进一条 spec —— 各腿的**唯一**合并口:`permissionMode` = `"default"` 钳在 spec 已有的模式词之下(`runtime-governance.ts`
|
|
76
|
+
* `entryPermissionMode("default", spec 的词)`,与入口地板同一只函数、底下是 core 的钳;spec 无词 ⇒ `"default"`)+ `onAsk: createUnattendedOnAsk(seat)`。`seat` = 本腿的活审批席(run-local
|
|
77
77
|
* 递它的 `createLocalApprover`;leader 各腿与续跑重挂无席,不递)—— 席只经这个参数进来,从不从 spec 上读。
|
|
78
78
|
* 调用点必须在 spec 其余键(含治理折叠)**之后**调它 —— spec 自带的 `plan` 由此被读到、留住;本口不碰 `toolPolicy`(没有策略层要并:过渡形的
|
|
79
79
|
* 写保护拒层已退役)。
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { entryPermissionMode } from "./runtime-governance.js";
|
|
2
2
|
export const UNATTENDED_ANSWERED_CLASSES = new Set(["ordinary"]);
|
|
3
3
|
export const UNATTENDED_POLICY_APPROVER = "unattended_class_answer";
|
|
4
4
|
function unattendedPolicyYes() {
|
|
@@ -12,7 +12,7 @@ export function createUnattendedOnAsk(seat) {
|
|
|
12
12
|
return (req, signal) => (unattendedAnswers(req) ? unattendedPolicyYes() : seat !== undefined ? seat(req, signal) : "unavailable");
|
|
13
13
|
}
|
|
14
14
|
export function withUnattendedLeg(spec, seat) {
|
|
15
|
-
const permissionMode =
|
|
15
|
+
const permissionMode = entryPermissionMode("default", spec.permissionMode).effective;
|
|
16
16
|
return { ...spec, permissionMode, onAsk: createUnattendedOnAsk(seat) };
|
|
17
17
|
}
|
|
18
18
|
//# sourceMappingURL=unattended-permission-mode.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/server",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.123.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",
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"build:binary:run-local:darwin-arm64": "bun build --compile --target=bun-darwin-arm64 src/run-local.ts --outfile dist/run-local-darwin-arm64"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@sema-agent/core": "7.
|
|
68
|
-
"@sema-agent/settings-schema": "
|
|
67
|
+
"@sema-agent/core": "7.48.0",
|
|
68
|
+
"@sema-agent/settings-schema": "10.1.1",
|
|
69
69
|
"e2b": "^2.28.0",
|
|
70
70
|
"libsodium-wrappers": "^0.8.4",
|
|
71
71
|
"mysql2": "^3.22.4",
|