@hirey/hi-mcp-server 0.1.11 → 0.1.13
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/README.md +10 -1
- package/dist/defaultReplyRoute.d.ts +11 -0
- package/dist/defaultReplyRoute.d.ts.map +1 -1
- package/dist/defaultReplyRoute.js +15 -0
- package/dist/server.js +33 -8
- package/dist/state.d.ts +7 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +32 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -86,6 +86,8 @@ npm install -g @hirey/hi-mcp-server
|
|
|
86
86
|
}
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
+
这里的 `HI_MCP_STATE_DIR` 必须直接指向 profile 对应的叶子目录;不要只写父目录 `/Users/you/.openclaw/hi-mcp`,否则虽然 `openclaw-main.json` 还能落盘,但 receiver config 和 doctor 会把它识别成非 canonical OpenClaw 布局。
|
|
90
|
+
|
|
89
91
|
普通用户首次接入后的典型顺序:
|
|
90
92
|
|
|
91
93
|
1. 用宿主把 `hi-mcp-server` 作为 `stdio` MCP server 挂上
|
|
@@ -100,7 +102,7 @@ npm install -g @hirey/hi-mcp-server
|
|
|
100
102
|
|
|
101
103
|
对 OpenClaw 的普通用户本地 vendor 安装,不要显式传 `receiver_command="hi-agent-receiver"` 或 `receiver_command_argv=["hi-agent-receiver"]`。这两种旧形态都会重新把启动语义写回“按 PATH 找全局命令”。OpenClaw 要么不传 receiver 启动覆盖,让安装流默认落到 `~/.openclaw/vendor/hi/node_modules/.bin/hi-agent-receiver`,要么只传指向该本地 vendor binary 的精确 `receiver_command_argv`。
|
|
102
104
|
|
|
103
|
-
|
|
105
|
+
对 OpenClaw 的普通用户安装,默认就应该把当前聊天绑成 Hi 以后回来的默认线程。因此 `hi_agent_install` 应直接带上 `host_session_key`、`default_reply_channel`、`default_reply_to`、`default_reply_account_id`、`default_reply_thread_id`、`route_missing_policy`。这组字段会同时写进 installation 的 `delivery_capabilities` 和本地 receiver config,避免出现 gateway 已经知道默认 route、但本地 receiver 还沿旧配置投递的漂移。如果拿不到当前聊天的 canonical `host_session_key`,OpenClaw 安装不应宣告成功,而应先把 continuity blocker 说明白。
|
|
104
106
|
|
|
105
107
|
安装后如果要显式验证 continuation route,可以用 `hi_agent_test_delivery`:既可以直接传 `host_session_key` / `reply_*` 做一次显式 route probe,也可以在 installation 已设置 `default_reply_route` 时不传这些字段,让 gateway 自动沿当前 installation 的默认 route 发 probe。
|
|
106
108
|
|
|
@@ -124,11 +126,18 @@ npm install -g @hirey/hi-mcp-server
|
|
|
124
126
|
- `HI_MCP_STATE_DIR`
|
|
125
127
|
- 本地 state 目录。未显式指定时,默认落到稳定 home 目录:`~/.hirey/hi-mcp/<profile>`。
|
|
126
128
|
- OpenClaw 普通用户建议显式固定到 canonical 目录,例如 `/Users/you/.openclaw/hi-mcp/openclaw-main`,方便后续 `hi-agent-receiver` 直接复用同一份身份 state。
|
|
129
|
+
- 不要把它设置成 bare parent dir `/Users/you/.openclaw/hi-mcp`;OpenClaw 场景下必须把 profile 叶子目录也包含进去。
|
|
127
130
|
|
|
128
131
|
### 本地 state
|
|
129
132
|
|
|
130
133
|
state 会按 profile 落到 `HI_MCP_STATE_DIR/<profile>.json`。
|
|
131
134
|
|
|
135
|
+
对 OpenClaw 而言,推荐的 canonical 形态就是:
|
|
136
|
+
|
|
137
|
+
- `HI_MCP_PROFILE=openclaw-main`
|
|
138
|
+
- `HI_MCP_STATE_DIR=/Users/you/.openclaw/hi-mcp/openclaw-main`
|
|
139
|
+
- 最终 state file = `/Users/you/.openclaw/hi-mcp/openclaw-main/openclaw-main.json`
|
|
140
|
+
|
|
132
141
|
文件内部明确分成两块:
|
|
133
142
|
|
|
134
143
|
- `identity`
|
|
@@ -12,4 +12,15 @@ export declare function resolveInstallDefaultReplyDeliveryContext(args: {
|
|
|
12
12
|
defaultReplyAccountId?: unknown;
|
|
13
13
|
defaultReplyThreadId?: unknown;
|
|
14
14
|
}): DefaultReplyDeliveryContext | null;
|
|
15
|
+
export declare function resolveInstallRouteMissingPolicy(args: {
|
|
16
|
+
hostKind: 'openclaw' | 'generic';
|
|
17
|
+
explicitRouteMissingPolicy?: unknown;
|
|
18
|
+
defaultReplyRoute?: Record<string, unknown> | null;
|
|
19
|
+
}): {
|
|
20
|
+
ok: true;
|
|
21
|
+
routeMissingPolicy: string;
|
|
22
|
+
} | {
|
|
23
|
+
ok: false;
|
|
24
|
+
error: 'missing_openclaw_default_reply_route';
|
|
25
|
+
};
|
|
15
26
|
//# sourceMappingURL=defaultReplyRoute.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultReplyRoute.d.ts","sourceRoot":"","sources":["../src/defaultReplyRoute.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,2BAA2B,GAAG;IACxC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF,wBAAgB,yCAAyC,CAAC,IAAI,EAAE;IAC9D,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAC;IACjC,aAAa,EAAE,OAAO,CAAC;IACvB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,GAAG,2BAA2B,GAAG,IAAI,CAyBrC"}
|
|
1
|
+
{"version":3,"file":"defaultReplyRoute.d.ts","sourceRoot":"","sources":["../src/defaultReplyRoute.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,2BAA2B,GAAG;IACxC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF,wBAAgB,yCAAyC,CAAC,IAAI,EAAE;IAC9D,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAC;IACjC,aAAa,EAAE,OAAO,CAAC;IACvB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,GAAG,2BAA2B,GAAG,IAAI,CAyBrC;AAED,wBAAgB,gCAAgC,CAAC,IAAI,EAAE;IACrD,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAC;IACjC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACpD,GAAG;IACF,EAAE,EAAE,IAAI,CAAC;IACT,kBAAkB,EAAE,MAAM,CAAC;CAC5B,GAAG;IACF,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,sCAAsC,CAAC;CAC/C,CAcA"}
|
|
@@ -26,3 +26,18 @@ export function resolveInstallDefaultReplyDeliveryContext(args) {
|
|
|
26
26
|
}
|
|
27
27
|
return null;
|
|
28
28
|
}
|
|
29
|
+
export function resolveInstallRouteMissingPolicy(args) {
|
|
30
|
+
const explicitRouteMissingPolicy = normalizeText(args.explicitRouteMissingPolicy);
|
|
31
|
+
// OpenClaw 安装默认就要把当前聊天绑成默认续聊入口;否则安装不该继续宣告成功。
|
|
32
|
+
if (args.hostKind === 'openclaw' && !args.defaultReplyRoute) {
|
|
33
|
+
return {
|
|
34
|
+
ok: false,
|
|
35
|
+
error: 'missing_openclaw_default_reply_route',
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
ok: true,
|
|
40
|
+
routeMissingPolicy: explicitRouteMissingPolicy
|
|
41
|
+
|| (args.defaultReplyRoute ? 'use_explicit_default_route' : ''),
|
|
42
|
+
};
|
|
43
|
+
}
|
package/dist/server.js
CHANGED
|
@@ -11,11 +11,11 @@ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/
|
|
|
11
11
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
12
12
|
import { AGENT_GATEWAY_EVENT_TOPICS, normalizeAgentEndpointList, normalizeAgentInstallationDeliveryDeclaration, normalizeAgentSubscriptionList, normalizeText, } from '@hirey/hi-agent-contracts';
|
|
13
13
|
import { createHiAgentClients, exchangeHiAgentClientCredentialsToken, HiAgentGatewayClient, HiAgentPlatformClient, } from '@hirey/hi-agent-sdk';
|
|
14
|
-
import { readState, resolveCanonicalOpenClawStateDir, resolveDefaultStateDir, resolveLegacyStateFiles, resolveStateFile, updateState, normalizeStateProfile, } from './state.js';
|
|
14
|
+
import { readState, resolveCanonicalOpenClawStateDir, resolveDefaultStateDir, resolveLegacyStateFiles, resolveStateFile, validateOpenClawStateDir, updateState, normalizeStateProfile, } from './state.js';
|
|
15
15
|
import { looksLikeOpenClawSessionKey, validateOpenClawSessionKey, } from './openclaw-session-key.js';
|
|
16
16
|
import { buildInstallReceiverCommandArgv, } from './receiver-command.js';
|
|
17
17
|
import { applyReceiverRuntimeSnapshot, receiverConfigMaterialEquals, } from './receiver-config-material.js';
|
|
18
|
-
import { resolveInstallDefaultReplyDeliveryContext, } from './defaultReplyRoute.js';
|
|
18
|
+
import { resolveInstallDefaultReplyDeliveryContext, resolveInstallRouteMissingPolicy, } from './defaultReplyRoute.js';
|
|
19
19
|
const CAPABILITY_CACHE_TTL_MS = 30_000;
|
|
20
20
|
const RECEIVER_STOP_TIMEOUT_MS = 3_000;
|
|
21
21
|
const RECEIVER_STOP_POLL_MS = 100;
|
|
@@ -113,8 +113,8 @@ function controlTools() {
|
|
|
113
113
|
host_adapter_url: { type: 'string', description: 'enable_local_receiver=true 时可选:宿主本地接收入口。OpenClaw 默认 full endpoint 为 http://127.0.0.1:18789/hooks/agent;注意 OpenClaw 配置里的 hooks.path 应保持 /hooks,而不是 /hooks/agent。' },
|
|
114
114
|
host_adapter_bearer_token: { type: 'string', description: 'host_adapter_kind=openclaw_hooks 时必填:本地 hooks bearer token。' },
|
|
115
115
|
openresponses_model: { type: 'string', description: 'host_adapter_kind=openresponses 时必填:receiver 发给本地入口使用的 model。' },
|
|
116
|
-
host_session_key: { type: 'string', description: '
|
|
117
|
-
route_missing_policy: { type: 'string', description: "可选:'use_explicit_default_route'|'fail_closed'
|
|
116
|
+
host_session_key: { type: 'string', description: 'OpenClaw 安装默认应传:把当前 OpenClaw 当前会话设为 default continuation route 的 canonical full session_key。只能使用结构化宿主来源返回的完整 key;不要从 openclaw status / openclaw sessions / TUI footer 这类展示文本里抄值。' },
|
|
117
|
+
route_missing_policy: { type: 'string', description: "可选:'use_explicit_default_route'|'fail_closed'。OpenClaw 安装默认要求当前聊天 ready,因此在提供 host_session_key/default_reply_* 时应使用 use_explicit_default_route;缺失 default route 时安装会直接失败,而不是继续留下 continuity_not_ready。" },
|
|
118
118
|
default_reply_channel: { type: 'string', description: '可选:default continuation route 的 channel。' },
|
|
119
119
|
default_reply_to: { type: 'string', description: '可选:default continuation route 的宿主 target。' },
|
|
120
120
|
default_reply_account_id: { type: 'string', description: '可选:default continuation route 的 account_id。' },
|
|
@@ -836,6 +836,7 @@ function buildDoctorSummary(args) {
|
|
|
836
836
|
route_missing_policy: routeMissingPolicy,
|
|
837
837
|
default_reply_route: defaultReplyRoute,
|
|
838
838
|
default_reply_route_validation: args.defaultReplyRouteValidation,
|
|
839
|
+
openclaw_state_dir_validation: args.openClawStateDirValidation,
|
|
839
840
|
delivery_probe: args.deliveryProbe,
|
|
840
841
|
delivery_probe_diagnostics: args.deliveryProbeDiagnostics,
|
|
841
842
|
};
|
|
@@ -1087,11 +1088,23 @@ async function handleDoctor(args) {
|
|
|
1087
1088
|
reason: null,
|
|
1088
1089
|
session_key: null,
|
|
1089
1090
|
};
|
|
1091
|
+
let openClawStateDirValidation = null;
|
|
1090
1092
|
if (!state.identity) {
|
|
1091
1093
|
blockers.push('missing_agent_identity');
|
|
1092
1094
|
}
|
|
1093
|
-
if (installState.host_kind === 'openclaw'
|
|
1094
|
-
|
|
1095
|
+
if (installState.host_kind === 'openclaw') {
|
|
1096
|
+
const validation = validateOpenClawStateDir(config.stateDir, config.profile);
|
|
1097
|
+
openClawStateDirValidation = {
|
|
1098
|
+
configured_state_dir: validation.configured_state_dir,
|
|
1099
|
+
canonical_state_dir: validation.canonical_state_dir,
|
|
1100
|
+
reason: validation.reason,
|
|
1101
|
+
};
|
|
1102
|
+
if (!validation.is_canonical) {
|
|
1103
|
+
warnings.push('openclaw_state_dir_not_canonical');
|
|
1104
|
+
if (validation.reason === 'missing_profile_leaf') {
|
|
1105
|
+
warnings.push('openclaw_state_dir_missing_profile_leaf');
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1095
1108
|
}
|
|
1096
1109
|
if (includeRemote && state.identity) {
|
|
1097
1110
|
try {
|
|
@@ -1198,6 +1211,7 @@ async function handleDoctor(args) {
|
|
|
1198
1211
|
deliveryProbe,
|
|
1199
1212
|
deliveryProbeDiagnostics,
|
|
1200
1213
|
defaultReplyRouteValidation,
|
|
1214
|
+
openClawStateDirValidation,
|
|
1201
1215
|
}));
|
|
1202
1216
|
}
|
|
1203
1217
|
async function handleInstall(args) {
|
|
@@ -1261,8 +1275,19 @@ async function handleInstall(args) {
|
|
|
1261
1275
|
requireOpenClawSessionKey: hostKind === 'openclaw',
|
|
1262
1276
|
hostKind,
|
|
1263
1277
|
});
|
|
1264
|
-
const
|
|
1265
|
-
|
|
1278
|
+
const routeMissingPolicyResolution = resolveInstallRouteMissingPolicy({
|
|
1279
|
+
hostKind,
|
|
1280
|
+
explicitRouteMissingPolicy: args.route_missing_policy,
|
|
1281
|
+
defaultReplyRoute,
|
|
1282
|
+
});
|
|
1283
|
+
if (!routeMissingPolicyResolution.ok) {
|
|
1284
|
+
return fail(routeMissingPolicyResolution.error, {
|
|
1285
|
+
host_kind: hostKind,
|
|
1286
|
+
hint: 'OpenClaw installs must bind the current chat as the default continuation route. Read the canonical full current session key from a structured OpenClaw host source and pass it as host_session_key.',
|
|
1287
|
+
expected_route_missing_policy: 'use_explicit_default_route',
|
|
1288
|
+
});
|
|
1289
|
+
}
|
|
1290
|
+
const routeMissingPolicy = routeMissingPolicyResolution.routeMissingPolicy;
|
|
1266
1291
|
const desiredDeliveryCapabilities = buildInstallationDeliveryDeclaration({
|
|
1267
1292
|
enableLocalReceiver,
|
|
1268
1293
|
receiverTransport,
|
package/dist/state.d.ts
CHANGED
|
@@ -40,6 +40,13 @@ export declare const DEFAULT_HI_MCP_PROFILE = "default";
|
|
|
40
40
|
export declare function normalizeStateProfile(raw: unknown): string;
|
|
41
41
|
export declare function resolveDefaultStateDir(profileRaw: unknown): string;
|
|
42
42
|
export declare function resolveCanonicalOpenClawStateDir(profileRaw?: unknown): string;
|
|
43
|
+
export type OpenClawStateDirValidation = {
|
|
44
|
+
configured_state_dir: string;
|
|
45
|
+
canonical_state_dir: string;
|
|
46
|
+
is_canonical: boolean;
|
|
47
|
+
reason: 'canonical' | 'missing_profile_leaf' | 'non_canonical';
|
|
48
|
+
};
|
|
49
|
+
export declare function validateOpenClawStateDir(stateDirRaw: unknown, profileRaw?: unknown): OpenClawStateDirValidation;
|
|
43
50
|
export declare function resolveLegacyStateFiles(profileRaw: unknown): string[];
|
|
44
51
|
export declare function buildDefaultState(profile: string): HiAgentPersistedState;
|
|
45
52
|
export declare function resolveStateFile(args: {
|
package/dist/state.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACvD,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,wBAAwB,EAAE,MAAM,CAAC;IACjC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;QACpC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,wBAAwB,EAAE,MAAM,GAAG,IAAI,CAAC;QACxC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;KACpC,CAAC;IACF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,OAAO,EAAE,mBAAmB,CAAC;CAC9B,CAAC;AAeF,eAAO,MAAM,sBAAsB,YAAY,CAAC;AAEhD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAE1D;
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
|
package/dist/state.js
CHANGED
|
@@ -17,6 +17,10 @@ export const DEFAULT_HI_MCP_PROFILE = 'default';
|
|
|
17
17
|
export function normalizeStateProfile(raw) {
|
|
18
18
|
return String(raw || '').trim() || DEFAULT_HI_MCP_PROFILE;
|
|
19
19
|
}
|
|
20
|
+
function normalizeStateDirPath(raw) {
|
|
21
|
+
const text = typeof raw === 'string' ? String(raw).trim() : '';
|
|
22
|
+
return text ? path.resolve(text) : '';
|
|
23
|
+
}
|
|
20
24
|
export function resolveDefaultStateDir(profileRaw) {
|
|
21
25
|
const profile = normalizeStateProfile(profileRaw);
|
|
22
26
|
// 本地 installation state 必须落到稳定 home 目录,不能继续跟着 cwd 漂。
|
|
@@ -26,6 +30,34 @@ export function resolveCanonicalOpenClawStateDir(profileRaw = 'openclaw-main') {
|
|
|
26
30
|
const profile = normalizeStateProfile(profileRaw);
|
|
27
31
|
return path.join(os.homedir(), '.openclaw', 'hi-mcp', profile);
|
|
28
32
|
}
|
|
33
|
+
export function validateOpenClawStateDir(stateDirRaw, profileRaw = 'openclaw-main') {
|
|
34
|
+
const canonicalStateDir = resolveCanonicalOpenClawStateDir(profileRaw);
|
|
35
|
+
const configuredStateDir = normalizeStateDirPath(stateDirRaw) || canonicalStateDir;
|
|
36
|
+
if (configuredStateDir === canonicalStateDir) {
|
|
37
|
+
return {
|
|
38
|
+
configured_state_dir: configuredStateDir,
|
|
39
|
+
canonical_state_dir: canonicalStateDir,
|
|
40
|
+
is_canonical: true,
|
|
41
|
+
reason: 'canonical',
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const bareOpenClawStateDir = path.join(os.homedir(), '.openclaw', 'hi-mcp');
|
|
45
|
+
if (configuredStateDir === bareOpenClawStateDir) {
|
|
46
|
+
// OpenClaw 的 canonical 布局要求 stateDir 自己就是 profile 叶子目录,不能只指向父目录。
|
|
47
|
+
return {
|
|
48
|
+
configured_state_dir: configuredStateDir,
|
|
49
|
+
canonical_state_dir: canonicalStateDir,
|
|
50
|
+
is_canonical: false,
|
|
51
|
+
reason: 'missing_profile_leaf',
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
configured_state_dir: configuredStateDir,
|
|
56
|
+
canonical_state_dir: canonicalStateDir,
|
|
57
|
+
is_canonical: false,
|
|
58
|
+
reason: 'non_canonical',
|
|
59
|
+
};
|
|
60
|
+
}
|
|
29
61
|
export function resolveLegacyStateFiles(profileRaw) {
|
|
30
62
|
const profile = normalizeStateProfile(profileRaw);
|
|
31
63
|
return [
|