@dsh-edge/dsh-edge-agent 0.0.0-stage → 0.1.2
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/CHANGELOG.md +158 -0
- package/LICENSE +21 -0
- package/README.md +181 -2
- package/config/edge.example.json +179 -0
- package/config/privacy-policy.json +202 -0
- package/cordis.desktop-safe.patch.yml +129 -0
- package/cordis.patch.yml +382 -0
- package/cordis.yml +374 -0
- package/lib/attestation.d.ts +2 -0
- package/lib/attestation.d.ts.map +1 -0
- package/lib/attestation.js +2 -0
- package/lib/audit-log.d.ts +2 -0
- package/lib/audit-log.d.ts.map +1 -0
- package/lib/audit-log.js +2 -0
- package/lib/client.js +87 -0
- package/lib/cloud-llm-adapter.d.ts +2 -0
- package/lib/cloud-llm-adapter.d.ts.map +1 -0
- package/lib/cloud-llm-adapter.js +2 -0
- package/lib/dsh-adapter/attestation.d.ts +42 -0
- package/lib/dsh-adapter/attestation.d.ts.map +1 -0
- package/lib/dsh-adapter/attestation.js +40 -0
- package/lib/dsh-adapter/audit-log.d.ts +139 -0
- package/lib/dsh-adapter/audit-log.d.ts.map +1 -0
- package/lib/dsh-adapter/audit-log.js +376 -0
- package/lib/dsh-adapter/cloud-egress.d.ts +181 -0
- package/lib/dsh-adapter/cloud-egress.d.ts.map +1 -0
- package/lib/dsh-adapter/cloud-egress.js +257 -0
- package/lib/dsh-adapter/cloud-llm-adapter.d.ts +416 -0
- package/lib/dsh-adapter/cloud-llm-adapter.d.ts.map +1 -0
- package/lib/dsh-adapter/cloud-llm-adapter.js +1472 -0
- package/lib/dsh-adapter/contract.d.ts +80 -0
- package/lib/dsh-adapter/contract.d.ts.map +1 -0
- package/lib/dsh-adapter/contract.js +194 -0
- package/lib/dsh-adapter/desktop-cookie-janitor.d.ts +214 -0
- package/lib/dsh-adapter/desktop-cookie-janitor.d.ts.map +1 -0
- package/lib/dsh-adapter/desktop-cookie-janitor.js +409 -0
- package/lib/dsh-adapter/dsh-edge-agent.d.ts +48 -0
- package/lib/dsh-adapter/dsh-edge-agent.d.ts.map +1 -0
- package/lib/dsh-adapter/dsh-edge-agent.js +64 -0
- package/lib/dsh-adapter/edge-config.d.ts +484 -0
- package/lib/dsh-adapter/edge-config.d.ts.map +1 -0
- package/lib/dsh-adapter/edge-config.js +898 -0
- package/lib/dsh-adapter/edge-context-view.d.ts +184 -0
- package/lib/dsh-adapter/edge-context-view.d.ts.map +1 -0
- package/lib/dsh-adapter/edge-context-view.js +483 -0
- package/lib/dsh-adapter/effective-model.d.ts +85 -0
- package/lib/dsh-adapter/effective-model.d.ts.map +1 -0
- package/lib/dsh-adapter/effective-model.js +171 -0
- package/lib/dsh-adapter/etscli-shell-guard.d.ts +244 -0
- package/lib/dsh-adapter/etscli-shell-guard.d.ts.map +1 -0
- package/lib/dsh-adapter/etscli-shell-guard.js +420 -0
- package/lib/dsh-adapter/etscli-tools.d.ts +112 -0
- package/lib/dsh-adapter/etscli-tools.d.ts.map +1 -0
- package/lib/dsh-adapter/etscli-tools.js +393 -0
- package/lib/dsh-adapter/file-logger.d.ts +294 -0
- package/lib/dsh-adapter/file-logger.d.ts.map +1 -0
- package/lib/dsh-adapter/file-logger.js +564 -0
- package/lib/dsh-adapter/function-call-external.d.ts +357 -0
- package/lib/dsh-adapter/function-call-external.d.ts.map +1 -0
- package/lib/dsh-adapter/function-call-external.js +1005 -0
- package/lib/dsh-adapter/host-egress-guard.d.ts +161 -0
- package/lib/dsh-adapter/host-egress-guard.d.ts.map +1 -0
- package/lib/dsh-adapter/host-egress-guard.js +213 -0
- package/lib/dsh-adapter/host-llm-trace.d.ts +198 -0
- package/lib/dsh-adapter/host-llm-trace.d.ts.map +1 -0
- package/lib/dsh-adapter/host-llm-trace.js +344 -0
- package/lib/dsh-adapter/http-api-routes.d.ts +61 -0
- package/lib/dsh-adapter/http-api-routes.d.ts.map +1 -0
- package/lib/dsh-adapter/http-api-routes.js +79 -0
- package/lib/dsh-adapter/http-api-sessions.d.ts +105 -0
- package/lib/dsh-adapter/http-api-sessions.d.ts.map +1 -0
- package/lib/dsh-adapter/http-api-sessions.js +173 -0
- package/lib/dsh-adapter/http-api.d.ts +221 -0
- package/lib/dsh-adapter/http-api.d.ts.map +1 -0
- package/lib/dsh-adapter/http-api.js +1811 -0
- package/lib/dsh-adapter/index.d.ts +62 -0
- package/lib/dsh-adapter/index.d.ts.map +1 -0
- package/lib/dsh-adapter/index.js +97 -0
- package/lib/dsh-adapter/input-guard-messages.d.ts +56 -0
- package/lib/dsh-adapter/input-guard-messages.d.ts.map +1 -0
- package/lib/dsh-adapter/input-guard-messages.js +136 -0
- package/lib/dsh-adapter/input-guard.d.ts +508 -0
- package/lib/dsh-adapter/input-guard.d.ts.map +1 -0
- package/lib/dsh-adapter/input-guard.js +2174 -0
- package/lib/dsh-adapter/intent-prompts.d.ts +77 -0
- package/lib/dsh-adapter/intent-prompts.d.ts.map +1 -0
- package/lib/dsh-adapter/intent-prompts.js +97 -0
- package/lib/dsh-adapter/intent-router.d.ts +710 -0
- package/lib/dsh-adapter/intent-router.d.ts.map +1 -0
- package/lib/dsh-adapter/intent-router.js +2802 -0
- package/lib/dsh-adapter/intent-signals.d.ts +208 -0
- package/lib/dsh-adapter/intent-signals.d.ts.map +1 -0
- package/lib/dsh-adapter/intent-signals.js +391 -0
- package/lib/dsh-adapter/invariant-install.d.ts +16 -0
- package/lib/dsh-adapter/invariant-install.d.ts.map +1 -0
- package/lib/dsh-adapter/invariant-install.js +15 -0
- package/lib/dsh-adapter/invariant.d.ts +16 -0
- package/lib/dsh-adapter/invariant.d.ts.map +1 -0
- package/lib/dsh-adapter/invariant.js +22 -0
- package/lib/dsh-adapter/llm-adapters.d.ts +19 -0
- package/lib/dsh-adapter/llm-adapters.d.ts.map +1 -0
- package/lib/dsh-adapter/llm-adapters.js +16 -0
- package/lib/dsh-adapter/llm-internal-caller.d.ts +92 -0
- package/lib/dsh-adapter/llm-internal-caller.d.ts.map +1 -0
- package/lib/dsh-adapter/llm-internal-caller.js +100 -0
- package/lib/dsh-adapter/llm-max-turns.d.ts +55 -0
- package/lib/dsh-adapter/llm-max-turns.d.ts.map +1 -0
- package/lib/dsh-adapter/llm-max-turns.js +127 -0
- package/lib/dsh-adapter/llm-trace-store.d.ts +131 -0
- package/lib/dsh-adapter/llm-trace-store.d.ts.map +1 -0
- package/lib/dsh-adapter/llm-trace-store.js +205 -0
- package/lib/dsh-adapter/llm-trace.d.ts +450 -0
- package/lib/dsh-adapter/llm-trace.d.ts.map +1 -0
- package/lib/dsh-adapter/llm-trace.js +463 -0
- package/lib/dsh-adapter/local-llm-adapter.d.ts +141 -0
- package/lib/dsh-adapter/local-llm-adapter.d.ts.map +1 -0
- package/lib/dsh-adapter/local-llm-adapter.js +787 -0
- package/lib/dsh-adapter/local-storage.d.ts +96 -0
- package/lib/dsh-adapter/local-storage.d.ts.map +1 -0
- package/lib/dsh-adapter/local-storage.js +198 -0
- package/lib/dsh-adapter/model-router.d.ts +79 -0
- package/lib/dsh-adapter/model-router.d.ts.map +1 -0
- package/lib/dsh-adapter/model-router.js +107 -0
- package/lib/dsh-adapter/ohttp-gateway.d.ts +49 -0
- package/lib/dsh-adapter/ohttp-gateway.d.ts.map +1 -0
- package/lib/dsh-adapter/ohttp-gateway.js +32 -0
- package/lib/dsh-adapter/openai-sse.d.ts +85 -0
- package/lib/dsh-adapter/openai-sse.d.ts.map +1 -0
- package/lib/dsh-adapter/openai-sse.js +462 -0
- package/lib/dsh-adapter/pii-utils.d.ts +96 -0
- package/lib/dsh-adapter/pii-utils.d.ts.map +1 -0
- package/lib/dsh-adapter/pii-utils.js +324 -0
- package/lib/dsh-adapter/plugin-host.d.ts +38 -0
- package/lib/dsh-adapter/plugin-host.d.ts.map +1 -0
- package/lib/dsh-adapter/plugin-host.js +38 -0
- package/lib/dsh-adapter/plugin.d.ts +46 -0
- package/lib/dsh-adapter/plugin.d.ts.map +1 -0
- package/lib/dsh-adapter/plugin.js +100 -0
- package/lib/dsh-adapter/privacy-policy.d.ts +237 -0
- package/lib/dsh-adapter/privacy-policy.d.ts.map +1 -0
- package/lib/dsh-adapter/privacy-policy.js +391 -0
- package/lib/dsh-adapter/prompt-guard.d.ts +152 -0
- package/lib/dsh-adapter/prompt-guard.d.ts.map +1 -0
- package/lib/dsh-adapter/prompt-guard.js +872 -0
- package/lib/dsh-adapter/realm-skill-bridge.d.ts +365 -0
- package/lib/dsh-adapter/realm-skill-bridge.d.ts.map +1 -0
- package/lib/dsh-adapter/realm-skill-bridge.js +1180 -0
- package/lib/dsh-adapter/sanitizer-pipeline.d.ts +140 -0
- package/lib/dsh-adapter/sanitizer-pipeline.d.ts.map +1 -0
- package/lib/dsh-adapter/sanitizer-pipeline.js +431 -0
- package/lib/dsh-adapter/secure-bridge.d.ts +47 -0
- package/lib/dsh-adapter/secure-bridge.d.ts.map +1 -0
- package/lib/dsh-adapter/secure-bridge.js +35 -0
- package/lib/dsh-adapter/session-attribution.d.ts +70 -0
- package/lib/dsh-adapter/session-attribution.d.ts.map +1 -0
- package/lib/dsh-adapter/session-attribution.js +76 -0
- package/lib/dsh-adapter/sessions.d.ts +86 -0
- package/lib/dsh-adapter/sessions.d.ts.map +1 -0
- package/lib/dsh-adapter/sessions.js +179 -0
- package/lib/dsh-adapter/tcm.d.ts +55 -0
- package/lib/dsh-adapter/tcm.d.ts.map +1 -0
- package/lib/dsh-adapter/tcm.js +94 -0
- package/lib/dsh-adapter/td-bus.d.ts +87 -0
- package/lib/dsh-adapter/td-bus.d.ts.map +1 -0
- package/lib/dsh-adapter/td-bus.js +196 -0
- package/lib/dsh-adapter/tool-runner.d.ts +185 -0
- package/lib/dsh-adapter/tool-runner.d.ts.map +1 -0
- package/lib/dsh-adapter/tool-runner.js +271 -0
- package/lib/dsh-adapter/tools.d.ts +118 -0
- package/lib/dsh-adapter/tools.d.ts.map +1 -0
- package/lib/dsh-adapter/tools.js +292 -0
- package/lib/dsh-adapter/types.d.ts +23 -0
- package/lib/dsh-adapter/types.d.ts.map +1 -0
- package/lib/dsh-adapter/types.js +16 -0
- package/lib/dsh-adapter/voice-input.d.ts +30 -0
- package/lib/dsh-adapter/voice-input.d.ts.map +1 -0
- package/lib/dsh-adapter/voice-input.js +34 -0
- package/lib/dsh-adapter/web-search-tavily-bocha.d.ts +152 -0
- package/lib/dsh-adapter/web-search-tavily-bocha.d.ts.map +1 -0
- package/lib/dsh-adapter/web-search-tavily-bocha.js +289 -0
- package/lib/http-api.d.ts +2 -0
- package/lib/http-api.d.ts.map +1 -0
- package/lib/http-api.js +2 -0
- package/lib/index.d.ts +48 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +49 -0
- package/lib/intent-router.d.ts +2 -0
- package/lib/intent-router.d.ts.map +1 -0
- package/lib/intent-router.js +2 -0
- package/lib/llm-adapters.d.ts +2 -0
- package/lib/llm-adapters.d.ts.map +1 -0
- package/lib/llm-adapters.js +2 -0
- package/lib/local-llm-adapter.d.ts +2 -0
- package/lib/local-llm-adapter.d.ts.map +1 -0
- package/lib/local-llm-adapter.js +2 -0
- package/lib/local-storage.d.ts +2 -0
- package/lib/local-storage.d.ts.map +1 -0
- package/lib/local-storage.js +2 -0
- package/lib/model-router.d.ts +2 -0
- package/lib/model-router.d.ts.map +1 -0
- package/lib/model-router.js +2 -0
- package/lib/ohttp-gateway.d.ts +2 -0
- package/lib/ohttp-gateway.d.ts.map +1 -0
- package/lib/ohttp-gateway.js +2 -0
- package/lib/plugin-host.d.ts +2 -0
- package/lib/plugin-host.d.ts.map +1 -0
- package/lib/plugin-host.js +2 -0
- package/lib/privacy-policy.d.ts +2 -0
- package/lib/privacy-policy.d.ts.map +1 -0
- package/lib/privacy-policy.js +2 -0
- package/lib/prompt-guard.d.ts +2 -0
- package/lib/prompt-guard.d.ts.map +1 -0
- package/lib/prompt-guard.js +2 -0
- package/lib/sanitizer-pipeline.d.ts +2 -0
- package/lib/sanitizer-pipeline.d.ts.map +1 -0
- package/lib/sanitizer-pipeline.js +2 -0
- package/lib/secure-bridge.d.ts +2 -0
- package/lib/secure-bridge.d.ts.map +1 -0
- package/lib/secure-bridge.js +2 -0
- package/lib/sessions.d.ts +2 -0
- package/lib/sessions.d.ts.map +1 -0
- package/lib/sessions.js +2 -0
- package/lib/tcm.d.ts +2 -0
- package/lib/tcm.d.ts.map +1 -0
- package/lib/tcm.js +2 -0
- package/lib/td-bus.d.ts +2 -0
- package/lib/td-bus.d.ts.map +1 -0
- package/lib/td-bus.js +2 -0
- package/lib/tools.d.ts +2 -0
- package/lib/tools.d.ts.map +1 -0
- package/lib/tools.js +2 -0
- package/lib/voice-input.d.ts +2 -0
- package/lib/voice-input.d.ts.map +1 -0
- package/lib/voice-input.js +2 -0
- package/package.json +253 -3
- package/presets/agent-preset-edge.json +50 -0
- package/presets/edge.desktop-safe.patch.yml +503 -0
- package/presets/edge.patch.yml +557 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* realm-skill-bridge — Realm-aware skill and tool isolation for dsh-edge-agent.
|
|
3
|
+
*
|
|
4
|
+
* Reads a user-editable JSON config (`skill-realms.json`) that maps skill/tool
|
|
5
|
+
* names (or glob patterns) to LOCAL | CLOUD realms. Tags every discovered skill
|
|
6
|
+
* and tool accordingly, then enforces the mapping at three enforcement points:
|
|
7
|
+
*
|
|
8
|
+
* Layer 1 (agent/pre-step): filter the <available_skills> catalog so each
|
|
9
|
+
* agent only sees skills in its own realm. Skills tagged `hidden` are
|
|
10
|
+
* invisible to every agent.
|
|
11
|
+
*
|
|
12
|
+
* Layer 1.5-replacement (system-prompt/assemble): filter the tool schema
|
|
13
|
+
* list BEFORE dsh-agent-loop wraps it in deepFreeze and passes to the
|
|
14
|
+
* LLM. Replaces the deleted `llm/stream` tools probe — `payload.tools`
|
|
15
|
+
* at llm/stream is already frozen (dsh-agent-loop/lib/index.js:729
|
|
16
|
+
* `markAgentLoopRequest(deepFreeze({ ... tools: header.tools, ... }))`)
|
|
17
|
+
* so splice/defineProperty mutations silently fail there. The
|
|
18
|
+
* system-prompt/assemble waterfall value IS authoritative (per the dsh
|
|
19
|
+
* type declaration: "the returned value is authoritative") and tools are
|
|
20
|
+
* a plain array at that point. After this layer the LLM never sees
|
|
21
|
+
* out-of-realm tools.
|
|
22
|
+
*
|
|
23
|
+
* Layer 3 (tools/pre-execute): deny tool execution when the tool's realm
|
|
24
|
+
* does not match the calling agent's realm (defense-in-depth — also
|
|
25
|
+
* catches tools added via runtime registrations that bypass assembly).
|
|
26
|
+
*
|
|
27
|
+
* The config file is hot-reloaded via stat-polling (same pattern as
|
|
28
|
+
* privacy-policy.ts) so changes take effect without a restart.
|
|
29
|
+
*
|
|
30
|
+
* @module dsh-edge-agent/realm-skill-bridge
|
|
31
|
+
*/
|
|
32
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
33
|
+
import { Service } from '@deepseek-ai/cordis';
|
|
34
|
+
import Schema from '@deepseek-ai/schemastery';
|
|
35
|
+
export declare const name = "realm-skill-bridge";
|
|
36
|
+
export declare const inject: readonly ["auditLog", "skills", "edgeTools", "tools"];
|
|
37
|
+
/** Realm tag for skills and tools. 'hidden' means invisible to all agents. */
|
|
38
|
+
export type RealmTag = 'LOCAL' | 'CLOUD' | 'SANITIZED' | 'hidden';
|
|
39
|
+
/**
|
|
40
|
+
* §7.93 Phase 2 (2026-09-24,§7.93.1 通用化 2026-09-25): intent categories
|
|
41
|
+
* function-call-external may request tool schemas for. REJECT never reaches
|
|
42
|
+
* the external caller (4xx before dispatch) and 'hidden' agents get no tools
|
|
43
|
+
* at all, so both are excluded from the input type; CLOUD is included for
|
|
44
|
+
* completeness even though the external path skips CLOUD intents
|
|
45
|
+
* (decision #4) — callers gate, this method stays total.
|
|
46
|
+
*/
|
|
47
|
+
export type ExternalToolCallIntent = 'LOCAL' | 'CLOUD' | 'SANITIZED';
|
|
48
|
+
/**
|
|
49
|
+
* §7.93 Phase 2 (§7.93.1 通用化): one tool schema in the external caller's
|
|
50
|
+
* flat wire format (cactus-needle 3.0.1 / `~/work/needle/API.md` v1.1 §4.5:
|
|
51
|
+
* `{name, description, parameters}` —
|
|
52
|
+
* NOT the OpenAI `{type:'function', function:{...}}` envelope). This matches
|
|
53
|
+
* dsh-llm's own `ToolSchema` projection (`schemas()` whitelists exactly
|
|
54
|
+
* name/description/parameters), so the conversion is a shape check, not a
|
|
55
|
+
* translation.
|
|
56
|
+
*/
|
|
57
|
+
export interface ExternalToolSchema {
|
|
58
|
+
name: string;
|
|
59
|
+
description: string;
|
|
60
|
+
parameters: Record<string, unknown>;
|
|
61
|
+
}
|
|
62
|
+
export interface Config {
|
|
63
|
+
/** Path to the skill-realms.json config file. */
|
|
64
|
+
configPath: string;
|
|
65
|
+
/** Whether to hot-reload the config on file change (via stat polling). */
|
|
66
|
+
hotReload: boolean;
|
|
67
|
+
/** Polling interval in ms for config change detection. */
|
|
68
|
+
watchIntervalMs: number;
|
|
69
|
+
}
|
|
70
|
+
export declare const Config: Schema<Config>;
|
|
71
|
+
/**
|
|
72
|
+
* Parsed shape of skill-realms.json.
|
|
73
|
+
*
|
|
74
|
+
* `skills` maps skill name or glob pattern (e.g. "lark-*") to a realm.
|
|
75
|
+
* `tools` maps tool name to a realm (overrides hard-coded DSH_NATIVE_REALM_MAP).
|
|
76
|
+
* `defaultRealm` applies to anything not explicitly matched. "hidden" = invisible.
|
|
77
|
+
*
|
|
78
|
+
* §7.150: `tools` 的值**允许** 'hidden'。运行时一直支持(既有测试就写着
|
|
79
|
+
* `tools: { secret_admin: 'hidden' }`,`loadConfig` 也不校验取值),只是这里
|
|
80
|
+
* 的类型比实际用法窄 —— 于是任何想屏蔽一个工具的写法都编译不过。类型跟实际
|
|
81
|
+
* 对齐,而不是让调用方绕道。
|
|
82
|
+
*/
|
|
83
|
+
export interface RealmConfig {
|
|
84
|
+
skills: Record<string, RealmTag>;
|
|
85
|
+
tools: Record<string, RealmTag>;
|
|
86
|
+
defaultRealm: RealmTag;
|
|
87
|
+
}
|
|
88
|
+
interface AuditLogLike {
|
|
89
|
+
log(entry: {
|
|
90
|
+
level: string;
|
|
91
|
+
kind: string;
|
|
92
|
+
source: string;
|
|
93
|
+
payload?: Record<string, unknown>;
|
|
94
|
+
}): void;
|
|
95
|
+
}
|
|
96
|
+
/** Module augmentation: expose the service on ctx. */
|
|
97
|
+
declare module '@deepseek-ai/cordis' {
|
|
98
|
+
interface Context {
|
|
99
|
+
realmSkillBridge: RealmSkillBridgeService;
|
|
100
|
+
/** From @deepseek-ai/dsh-skill — augmented here to avoid importing the package. */
|
|
101
|
+
skills: {
|
|
102
|
+
list(options?: unknown): Promise<ReadonlyArray<{
|
|
103
|
+
name: string;
|
|
104
|
+
description?: string;
|
|
105
|
+
}>>;
|
|
106
|
+
snapshot(options?: unknown): Promise<{
|
|
107
|
+
skills: ReadonlyArray<{
|
|
108
|
+
name: string;
|
|
109
|
+
description?: string;
|
|
110
|
+
}>;
|
|
111
|
+
complete: boolean;
|
|
112
|
+
}>;
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Minimal glob matcher — supports `*` as "any sequence of characters".
|
|
118
|
+
* We do not pull in the `minimatch` dependency for this; the only patterns
|
|
119
|
+
* used in skill-realms.json are simple suffix globs like "lark-*".
|
|
120
|
+
*/
|
|
121
|
+
export declare function globMatch(pattern: string, value: string): boolean;
|
|
122
|
+
/**
|
|
123
|
+
* 把工具返回的 error message 变成一行可读的摘要。
|
|
124
|
+
*
|
|
125
|
+
* §7.151(2026-10-29)修:原来只有 `typeof message === 'string'` 才记内容,
|
|
126
|
+
* 否则一律打 `'unknown'`。但宿主的工具失败**大多数不是字符串** ——
|
|
127
|
+
* `deepseek-harness/docs/subsystems/user-questions.md:212` 明确写着
|
|
128
|
+
* `UserQuestionError` 继承 `HarnessError`,`ctx.tools.execute()` 保留
|
|
129
|
+
* `{ name, code }`(`NO_PROVIDER` / `BAD_INTENT` / `EMPTY_QUESTIONS` /
|
|
130
|
+
* `ASK_ABORTED`)。这些是**对象**,于是每一次这类失败在 ops log 里都只留下
|
|
131
|
+
* `errorKind=unknown` —— 真实错误码被吞掉,排查时无从下手
|
|
132
|
+
* (本轮就是这样误判了 ask_user_question 的失败原因)。
|
|
133
|
+
*
|
|
134
|
+
* 现在:字符串直接截断;对象/数组 JSON 序列化后截断;取不到就退回
|
|
135
|
+
* `String(message)`。**信息不能因为形态不是字符串就丢。**
|
|
136
|
+
*/
|
|
137
|
+
export declare function describeToolError(message: unknown): string;
|
|
138
|
+
export declare class RealmSkillBridgeService extends Service {
|
|
139
|
+
private readonly config;
|
|
140
|
+
private readonly auditLog;
|
|
141
|
+
/** Skill name → realm tag (including 'hidden'). */
|
|
142
|
+
private readonly skillRealms;
|
|
143
|
+
/** Tool name → set of realm tags. A tool can belong to multiple realms. */
|
|
144
|
+
private readonly toolRealms;
|
|
145
|
+
/** Session id → realm. Written by http-api after intent classification. */
|
|
146
|
+
private readonly sessionRealms;
|
|
147
|
+
/** sessionRealms 的 LRU 上限;活跃会话远小于此(http-api 默认 8)。 */
|
|
148
|
+
private static readonly SESSION_REALMS_CAP;
|
|
149
|
+
/** Parsed realm config. Refreshed on hot-reload. */
|
|
150
|
+
private realmConfig;
|
|
151
|
+
/** mtime of the config file at last load (for stat-polling). */
|
|
152
|
+
private lastMtime;
|
|
153
|
+
/** Hot-reload timer handle. */
|
|
154
|
+
private watchTimer;
|
|
155
|
+
constructor(ctx: Context, config: Config, auditLog: AuditLogLike | undefined);
|
|
156
|
+
/** Boot: ensure config file exists, load it, tag skills/tools. */
|
|
157
|
+
start(): Promise<void>;
|
|
158
|
+
/** Stop hot-reload timer. */
|
|
159
|
+
stop(): void;
|
|
160
|
+
/** Drop all per-session realm tags (plugin dispose path). */
|
|
161
|
+
clearSessionRealms(): void;
|
|
162
|
+
/** Set the realm for a session (called by http-api after intent classification). */
|
|
163
|
+
setSessionRealm(sessionId: string, realm: RealmTag): void;
|
|
164
|
+
/** Resolve the realm for an agent by looking up its session.
|
|
165
|
+
* §7.36 / §7.37 (2026-09-04): prefer `session.id` — input-guard registers
|
|
166
|
+
* via `payload.agent.session.id` (input-guard.ts:537) and that is the
|
|
167
|
+
* only key under which sessionRealms holds the realm. Reading
|
|
168
|
+
* `session.header.id` first was a wrong assumption that caused layer-1.5
|
|
169
|
+
* (llm/stream tools filter) to silently no-op: getAgentRealm returned
|
|
170
|
+
* undefined → filterToolsField skipped → tools.filtered never fired. */
|
|
171
|
+
getAgentRealm(agent: AgentLike | undefined): RealmTag | undefined;
|
|
172
|
+
/**
|
|
173
|
+
* Resolve realm directly from a sessionId string. Used by llm/stream hook
|
|
174
|
+
* where the agent's session.id path is unreliable and payload.sessionId
|
|
175
|
+
* is the canonical key.
|
|
176
|
+
*/
|
|
177
|
+
getSessionRealm(sessionId: string | undefined): RealmTag | undefined;
|
|
178
|
+
/** Look up the realm tag for a skill name.
|
|
179
|
+
* Prefers the cached tag (populated by tagSkills on skills/change), but
|
|
180
|
+
* falls back to resolveSkillRealm so skills not yet discovered still get
|
|
181
|
+
* the correct realm from the config file. */
|
|
182
|
+
skillRealm(name: string): RealmTag;
|
|
183
|
+
/** Look up the realm tags for a tool name. Returns undefined if no realm
|
|
184
|
+
* constraint is configured (tool is unconstrained). */
|
|
185
|
+
toolRealm(name: string): Set<RealmTag> | undefined;
|
|
186
|
+
private reloadConfig;
|
|
187
|
+
private checkForUpdates;
|
|
188
|
+
/**
|
|
189
|
+
* Resolve the realm for a skill by name.
|
|
190
|
+
* Priority:
|
|
191
|
+
* 1. skill-realms.json exact name match
|
|
192
|
+
* 2. skill-realms.json glob match (in declaration order)
|
|
193
|
+
* 3. defaultRealm
|
|
194
|
+
*
|
|
195
|
+
* Note: SKILL.md frontmatter `metadata.realm` is intentionally NOT consumed
|
|
196
|
+
* here — the config file is the single source of truth. This avoids a
|
|
197
|
+
* dependency on `ctx.skills.get()` (which reads the full markdown body)
|
|
198
|
+
* during the hot-path tag loop.
|
|
199
|
+
*/
|
|
200
|
+
private resolveSkillRealm;
|
|
201
|
+
/** Re-scan ctx.skills.list() and tag each skill by realm. */
|
|
202
|
+
private tagSkills;
|
|
203
|
+
/** Synchronous variant for await contexts. */
|
|
204
|
+
private tagSkillsAsync;
|
|
205
|
+
private logTaggingResult;
|
|
206
|
+
/** Apply tool realm tags from skill-realms.json to ctx.edgeTools. */
|
|
207
|
+
private tagToolsFromConfig;
|
|
208
|
+
/**
|
|
209
|
+
* Filter the <available_skills> catalog so the agent only sees skills in
|
|
210
|
+
* its realm. Skills tagged 'hidden' are removed from every agent's catalog.
|
|
211
|
+
*
|
|
212
|
+
* §7.37 (2026-09-04): Two message shapes carry the catalog:
|
|
213
|
+
* (a) standalone UserMessage with source.kind === 'skill-catalog'
|
|
214
|
+
* (string content).
|
|
215
|
+
* (b) dsh-system-prompt plugin snapshot with
|
|
216
|
+
* source.kind === 'plugin' && source.plugin ===
|
|
217
|
+
* '@deepseek-ai/dsh-system-prompt' (array content blocks,
|
|
218
|
+
* one of which is type:'text' containing `<available_skills>`).
|
|
219
|
+
* Both must be filtered or the catalog leaks. (a) is the canonical
|
|
220
|
+
* skill-catalog shape; (b) is what TUI / WebUI actually see because
|
|
221
|
+
* dsh-system-prompt co-locates the catalog with sandbox/approval policy
|
|
222
|
+
* snapshots — without this filter, LLM sees ALL 32 skills regardless
|
|
223
|
+
* of realm.
|
|
224
|
+
*
|
|
225
|
+
* We parse each ` - \`skill-name\`: Description` line, look up the skill's
|
|
226
|
+
* realm, and drop disallowed ones.
|
|
227
|
+
*/
|
|
228
|
+
filterSkillCatalog(messages: readonly MessageLike[], agentRealm: RealmTag): readonly MessageLike[];
|
|
229
|
+
/**
|
|
230
|
+
* §7.46 (2026-09-11): 返回 `{ messages, droppedCount }` 让 pre-step
|
|
231
|
+
* listener 能 emit `catalogDropped=N` 到 ops log(§7.44.1 chat-finished
|
|
232
|
+
* line 加 realm/duration 时同步加的;详见 PROGRESS §7.46)。返回 messages
|
|
233
|
+
* 是 filterSkillCatalog 的同一引用,方便测试不破坏。
|
|
234
|
+
*/
|
|
235
|
+
filterSkillCatalogDetailed(messages: readonly MessageLike[], agentRealm: RealmTag): {
|
|
236
|
+
messages: readonly MessageLike[];
|
|
237
|
+
droppedCount: number;
|
|
238
|
+
};
|
|
239
|
+
/**
|
|
240
|
+
* Pure function: parse `<available_skills>` content, drop lines whose
|
|
241
|
+
* skill name resolves to a realm other than `agentRealm` (or 'hidden').
|
|
242
|
+
* Returns `{ text, changed }` so the caller can short-circuit on no-op.
|
|
243
|
+
*
|
|
244
|
+
* §7.45 (2026-09-11): SANITIZED agents see every non-hidden skill —
|
|
245
|
+
* matches `filterToolsField`'s SANITIZED branch below. Before this
|
|
246
|
+
* fix, `skillRealm(name)` only returns `LOCAL`/`CLOUD`/`hidden` (never
|
|
247
|
+
* `'SANITIZED'`), so `realm !== agentRealm` was always true for SANITIZED
|
|
248
|
+
* agents and the entire catalog was dropped (audit observed
|
|
249
|
+
* `droppedCount=33` for a session whose agentRealm=SANITIZED — LLM saw
|
|
250
|
+
* zero skills and silently answered "no mibao tool available"). Skill
|
|
251
|
+
* realm tag is fail-closed (default 'hidden'), so SANITIZED must
|
|
252
|
+
* explicitly opt out of the strict-equality check.
|
|
253
|
+
*
|
|
254
|
+
* §7.47.1 (2026-09-12): Same dual fix for LOCAL/CLOUD. The catalog
|
|
255
|
+
* filter uses `skillRealm` (single realm), but tools are tagged with a
|
|
256
|
+
* realm SET (`toolRealms: Set<RealmTag>`). `bash` skill.realm = 'LOCAL'
|
|
257
|
+
* yet bash.toolRealms = {LOCAL, CLOUD}. Before this fix, a CLOUD agent
|
|
258
|
+
* (e.g. news query) saw every LOCAL skill dropped — `droppedCount=11`
|
|
259
|
+
* for news session, identical to the SANITIZED bug. Symmetric for
|
|
260
|
+
* LOCAL agent: CLOUD skill (e.g. web_search, web_fetch) was dropped.
|
|
261
|
+
* The fix extends SANITIZED's opt-in to ALL agent realms: any
|
|
262
|
+
* non-'hidden' skill is kept in the catalog. Layer 3 (tools/pre-execute)
|
|
263
|
+
* remains the authoritative gate, mirroring `filterToolsField`'s
|
|
264
|
+
* semantics where any non-hidden tool is offered to the LLM and only
|
|
265
|
+
* blocked at execution time.
|
|
266
|
+
*/
|
|
267
|
+
private filterCatalogText;
|
|
268
|
+
/**
|
|
269
|
+
* Pure function: filter the `tools` array carried on llm/stream payload so
|
|
270
|
+
* that the LLM does not see tools whose realm set does not include
|
|
271
|
+
* `agentRealm`. Tools whose realm is undefined (not in our config) are
|
|
272
|
+
* preserved (fail-closed: we only restrict what we explicitly tagged).
|
|
273
|
+
* Returns `{ tools, changed, removed }` so callers can short-circuit.
|
|
274
|
+
*
|
|
275
|
+
* SANITIZED special case: an agent whose input was sanitized may safely
|
|
276
|
+
* use both LOCAL tools (file ops don't leak) and CLOUD tools (input was
|
|
277
|
+
* already redacted). So SANITIZED agents see every non-hidden tool.
|
|
278
|
+
*
|
|
279
|
+
* §7.93 Phase 2 (§7.93.1 通用化): `options.audit === false` suppresses the
|
|
280
|
+
* `realm-skill-bridge.tools.filtered` audit entry. Used by
|
|
281
|
+
* getToolSchemasForExternal() so the LLM-path filter audit isn't duplicated
|
|
282
|
+
* per external call — function-call-external emits its own `external.*`
|
|
283
|
+
* audit kinds. Default (omitted) keeps the existing audited behavior.
|
|
284
|
+
*/
|
|
285
|
+
filterToolsField(tools: ReadonlyArray<unknown>, agentRealm: RealmTag, options?: {
|
|
286
|
+
audit?: boolean;
|
|
287
|
+
sessionId?: string;
|
|
288
|
+
}): {
|
|
289
|
+
tools: unknown[];
|
|
290
|
+
changed: boolean;
|
|
291
|
+
removed: string[];
|
|
292
|
+
};
|
|
293
|
+
/**
|
|
294
|
+
* Build the external caller's wire-format tool schemas for one intent's realm.
|
|
295
|
+
*
|
|
296
|
+
* Pipeline: registry projection → realm filter (filterToolsField semantics,
|
|
297
|
+
* audit suppressed — caller emits `external.*` audit) → shape normalization.
|
|
298
|
+
*
|
|
299
|
+
* Failure contract: registry unavailable (cordis proxy throw before the
|
|
300
|
+
* `tools` service mounts, §7.92.2 trap) or empty → returns []. Callers MUST
|
|
301
|
+
* treat [] as "no external caller" and fall through to the LLM
|
|
302
|
+
* self-extraction path — never POST an empty tools array to the external
|
|
303
|
+
* caller (it would echo/hallucinate).
|
|
304
|
+
*/
|
|
305
|
+
getToolSchemasForExternal(intent: ExternalToolCallIntent): ExternalToolSchema[];
|
|
306
|
+
/**
|
|
307
|
+
* Defensive read of `ctx.tools.schemas()` (global view). Returns [] when
|
|
308
|
+
* the service is not mounted yet or throws — the cordis proxy raises
|
|
309
|
+
* "cannot get property tools without inject" on unbound fibers, and
|
|
310
|
+
* tools/change re-fires tagging once available (same pattern as
|
|
311
|
+
* tagToolsFromConfig, §7.92.2).
|
|
312
|
+
*/
|
|
313
|
+
private readRegistrySchemas;
|
|
314
|
+
/**
|
|
315
|
+
* Check whether a tool call is allowed in the calling agent's realm.
|
|
316
|
+
* Returns a deny reason string, or undefined if the call is allowed.
|
|
317
|
+
* A tool can belong to multiple realms (e.g. bash → LOCAL+CLOUD); the call
|
|
318
|
+
* is allowed if the agent's realm is in the tool's realm set.
|
|
319
|
+
*/
|
|
320
|
+
checkToolRealm(toolName: string, agentRealm: RealmTag | undefined): string | undefined;
|
|
321
|
+
/** Log a realm denial to the audit log (security level). */
|
|
322
|
+
private auditDeny;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Normalize registry projections onto the external caller's flat wire contract
|
|
326
|
+
* (`{name, description, parameters}`; current cactus-needle 3.0.1 impl follows
|
|
327
|
+
* `~/work/needle/API.md` v1.1 §4.5):
|
|
328
|
+
*
|
|
329
|
+
* - entries without a non-empty string `name` are dropped (caller keys
|
|
330
|
+
* function_calls by name — a nameless schema is unexecutable)
|
|
331
|
+
* - missing/non-string `description` → '' (caller tolerates it; the tool
|
|
332
|
+
* name + parameters carry the selection signal)
|
|
333
|
+
* - missing/non-object `parameters` → permissive `{type:'object',
|
|
334
|
+
* properties:{}}` root (an unconstrained-args tool, e.g. no-arg status
|
|
335
|
+
* probes; JSON Schema semantics: absent properties = any object)
|
|
336
|
+
*
|
|
337
|
+
* Defensive by design: the registry projection is already whitelisted
|
|
338
|
+
* upstream, but a runtime-registered tool with a hand-rolled shape must not
|
|
339
|
+
* crash the external path — worst case it is dropped and the LLM path covers it.
|
|
340
|
+
*/
|
|
341
|
+
export declare function normalizeExternalToolSchemas(tools: ReadonlyArray<unknown>): ExternalToolSchema[];
|
|
342
|
+
interface AgentLike {
|
|
343
|
+
session?: {
|
|
344
|
+
header?: {
|
|
345
|
+
id?: string;
|
|
346
|
+
cwd?: string;
|
|
347
|
+
};
|
|
348
|
+
id?: string;
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
interface MessageLike {
|
|
352
|
+
content?: unknown;
|
|
353
|
+
source?: {
|
|
354
|
+
kind?: string;
|
|
355
|
+
form?: string;
|
|
356
|
+
plugin?: string;
|
|
357
|
+
entries?: ReadonlyArray<{
|
|
358
|
+
name?: string;
|
|
359
|
+
}>;
|
|
360
|
+
};
|
|
361
|
+
role?: string;
|
|
362
|
+
}
|
|
363
|
+
export declare function apply(ctx: Context, config: Config): Promise<() => Promise<void>>;
|
|
364
|
+
export {};
|
|
365
|
+
//# sourceMappingURL=realm-skill-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realm-skill-bridge.d.ts","sourceRoot":"","sources":["../../src/dsh-adapter/realm-skill-bridge.ts"],"names":[],"mappings":"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"}
|