@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
package/cordis.yml
ADDED
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
# dsh-edge-agent — edge-side private agent built on the DSH Cordis plugin
|
|
2
|
+
# mechanism. Run with: dsh --config cordis.yml
|
|
3
|
+
#
|
|
4
|
+
# Boot a session:
|
|
5
|
+
# pnpm install
|
|
6
|
+
# pnpm compile
|
|
7
|
+
# DEEPSEEK_API_KEY=... pnpm dsh -- --profile edge-standard "你好"
|
|
8
|
+
#
|
|
9
|
+
# Layout:
|
|
10
|
+
# 1. User-interaction / approval seams (model-facing)
|
|
11
|
+
# 2. Core DSH services: sessions, agent-spine, llm, subagent, tools, fs
|
|
12
|
+
# 3. The dsh-edge-agent plugin tree (19 core + 1 http-api)
|
|
13
|
+
# 4. Sandbox + telemetry
|
|
14
|
+
|
|
15
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
16
|
+
# 1. user-interaction / approval seams
|
|
17
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
# User-interaction service: hosts `ctx.userQuestions`. dsh-edge-agent mounts
|
|
20
|
+
# the same DSH default provider that any other bundle would.
|
|
21
|
+
- id: user-questions
|
|
22
|
+
name: '@deepseek-ai/dsh-user-questions'
|
|
23
|
+
|
|
24
|
+
# Approval waterfall. The edge-agent does NOT auto-approve by default;
|
|
25
|
+
# users opt into danger-full-access through DSH_EDGE_PERMISSION_MODE.
|
|
26
|
+
- id: approval
|
|
27
|
+
name: '@deepseek-ai/dsh-user-approval'
|
|
28
|
+
config:
|
|
29
|
+
policy: !!js "process.platform === 'win32' ? 'never' : ((process.env.DSH_EDGE_PERMISSION_MODE ?? 'ask') === 'danger-full-access' ? 'never' : 'ask')"
|
|
30
|
+
|
|
31
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
32
|
+
# 2. Core DSH services (sessions, agent, llm, subagent, tools, fs)
|
|
33
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
34
|
+
|
|
35
|
+
# Durable session log (JSONL) — every session event is appended here so
|
|
36
|
+
# /resume, /compact, and the threat-detection bus can replay.
|
|
37
|
+
- id: sessions
|
|
38
|
+
name: '@deepseek-ai/dsh-session-persistence-jsonl'
|
|
39
|
+
config:
|
|
40
|
+
root: !!js (process.env.DSH_EDGE_SESSION_ROOT ?? (process.env.USERPROFILE ?? process.env.HOME) + '/.dsh-edge-agent/sessions')
|
|
41
|
+
|
|
42
|
+
- id: session-query
|
|
43
|
+
name: '@deepseek-ai/dsh-session-query'
|
|
44
|
+
|
|
45
|
+
# Token accounting + manual /compact.
|
|
46
|
+
- id: token-meter
|
|
47
|
+
name: '@deepseek-ai/dsh-token-meter'
|
|
48
|
+
|
|
49
|
+
- id: compact
|
|
50
|
+
name: '@deepseek-ai/dsh-compaction-basic'
|
|
51
|
+
|
|
52
|
+
# Subagent registry, fork provider, and delegation tools.
|
|
53
|
+
- id: subagent
|
|
54
|
+
name: '@deepseek-ai/dsh-subagent'
|
|
55
|
+
|
|
56
|
+
- id: subagent-fork
|
|
57
|
+
name: '@deepseek-ai/dsh-subagent-fork-in-process'
|
|
58
|
+
config:
|
|
59
|
+
providerName: fork
|
|
60
|
+
|
|
61
|
+
- id: tool-subagent
|
|
62
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
63
|
+
config:
|
|
64
|
+
provider: fork
|
|
65
|
+
toolName: subagent_fork
|
|
66
|
+
backgroundMode: continuable
|
|
67
|
+
maxDepth: 1
|
|
68
|
+
|
|
69
|
+
# Filesystem service + observation policy + model-facing fs tools.
|
|
70
|
+
- id: fs
|
|
71
|
+
name: '@deepseek-ai/dsh-fs-local'
|
|
72
|
+
config:
|
|
73
|
+
cwd: !!js process.cwd()
|
|
74
|
+
|
|
75
|
+
- id: fs-policy
|
|
76
|
+
name: '@deepseek-ai/dsh-fs-observation-policy'
|
|
77
|
+
|
|
78
|
+
# Model-facing filesystem tools (read/write/edit/read_image)
|
|
79
|
+
- id: tool-fs
|
|
80
|
+
name: '@deepseek-ai/dsh-tool-fs'
|
|
81
|
+
config:
|
|
82
|
+
readLimit: 2000
|
|
83
|
+
readMaxBytes: 51200
|
|
84
|
+
|
|
85
|
+
# todo_write tool (mirrors the dsh-base bundle default).
|
|
86
|
+
- id: tool-todo
|
|
87
|
+
name: '@deepseek-ai/dsh-tool-todo'
|
|
88
|
+
config:
|
|
89
|
+
allowParallelInProgress: true
|
|
90
|
+
|
|
91
|
+
# Compaction basic — only one row; the dsh-edge-agent plugin tree is
|
|
92
|
+
# responsible for its own realm-aware tool registry (`tools`).
|
|
93
|
+
|
|
94
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
95
|
+
# 3. dsh-edge-agent plugin tree
|
|
96
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
97
|
+
|
|
98
|
+
# The main aggregator plugin: mounts every sub-plugin in boot order and
|
|
99
|
+
# registers the model-facing `services` namespace. The subpath exports
|
|
100
|
+
# pattern lets each row below be reused independently of this aggregator.
|
|
101
|
+
- id: dsh-edge-agent
|
|
102
|
+
name: '@dsh-edge/dsh-edge-agent'
|
|
103
|
+
inject: [agents, llm, sessions, invariants]
|
|
104
|
+
config:
|
|
105
|
+
teeType: !!js process.env.DSH_EDGE_TEE_TYPE ?? 'simulated'
|
|
106
|
+
storageRoot: !!js process.env.DSH_EDGE_STORAGE_ROOT ?? ((process.env.USERPROFILE ?? process.env.HOME) + '/.dsh-edge-agent')
|
|
107
|
+
policyPath: !!js process.env.DSH_EDGE_POLICY_PATH ?? ((process.env.USERPROFILE ?? process.env.HOME) + '/.dsh-edge-agent/policy.json')
|
|
108
|
+
defaultDataLevel: !!js process.env.DSH_EDGE_DEFAULT_DATA_LEVEL ?? 'sanitized'
|
|
109
|
+
allowFallbackTls: !!js process.env.DSH_EDGE_ALLOW_FALLBACK_TLS === 'true'
|
|
110
|
+
sessionWindowSize: !!js parseInt(process.env.DSH_EDGE_SESSION_WINDOW_SIZE ?? '32', 10)
|
|
111
|
+
|
|
112
|
+
# Trusted Computing Module — TEE-aware key management, encryption, sealing,
|
|
113
|
+
# and remote-attestation primitives. MUST mount first (every privacy/security
|
|
114
|
+
# plugin depends on its key store).
|
|
115
|
+
- id: tcm
|
|
116
|
+
name: '@dsh-edge/dsh-edge-agent/tcm'
|
|
117
|
+
config:
|
|
118
|
+
teeType: !!js process.env.DSH_EDGE_TEE_TYPE ?? 'simulated'
|
|
119
|
+
keyStorePath: !!js (process.env.DSH_EDGE_STORAGE_ROOT ?? ((process.env.USERPROFILE ?? process.env.HOME) + '/.dsh-edge-agent')) + '/keys'
|
|
120
|
+
teeInference: !!js process.env.DSH_EDGE_TEE_INFERENCE === 'true'
|
|
121
|
+
secureMemoryLimit: !!js parseInt(process.env.DSH_EDGE_SECURE_MEM ?? String(64 * 1024 * 1024), 10)
|
|
122
|
+
|
|
123
|
+
# Encrypted SQLite-backed key/value. Each value is AES-256-GCM encrypted via
|
|
124
|
+
# the TCM service before being written to disk.
|
|
125
|
+
- id: local-storage
|
|
126
|
+
name: '@dsh-edge/dsh-edge-agent/local-storage'
|
|
127
|
+
inject: [tcm]
|
|
128
|
+
config:
|
|
129
|
+
root: !!js (process.env.DSH_EDGE_STORAGE_ROOT ?? ((process.env.USERPROFILE ?? process.env.HOME) + '/.dsh-edge-agent')) + '/storage'
|
|
130
|
+
filename: !!js process.env.DSH_EDGE_STORAGE_FILE ?? 'storage.enc.db'
|
|
131
|
+
|
|
132
|
+
# Encrypted session lifecycle.
|
|
133
|
+
- id: sessions-edge
|
|
134
|
+
name: '@dsh-edge/dsh-edge-agent/sessions'
|
|
135
|
+
inject: [tcm, localStorage]
|
|
136
|
+
config:
|
|
137
|
+
defaultTtlSeconds: !!js parseInt(process.env.DSH_EDGE_SESSION_TTL ?? String(60 * 60), 10)
|
|
138
|
+
maxConcurrentSessions: !!js parseInt(process.env.DSH_EDGE_MAX_SESSIONS ?? '8', 10)
|
|
139
|
+
|
|
140
|
+
# Tamper-evident audit log. HMAC-chained so any tampering is detected.
|
|
141
|
+
- id: audit-log
|
|
142
|
+
name: '@dsh-edge/dsh-edge-agent/audit-log'
|
|
143
|
+
inject: [tcm, localStorage]
|
|
144
|
+
config:
|
|
145
|
+
minLevel: !!js process.env.DSH_EDGE_AUDIT_LEVEL ?? 'info'
|
|
146
|
+
sensitiveFields: !!js (process.env.DSH_EDGE_AUDIT_SENSITIVE_FIELDS ?? '').split(',').filter(Boolean)
|
|
147
|
+
enableAlerts: !!js process.env.DSH_EDGE_AUDIT_ALERTS !== 'false'
|
|
148
|
+
alertThresholds:
|
|
149
|
+
cloudRequestsPerMinute: !!js parseInt(process.env.DSH_EDGE_AUDIT_CLOUD_RATE ?? '20', 10)
|
|
150
|
+
sanitizationFailures: !!js parseInt(process.env.DSH_EDGE_AUDIT_SAN_FAIL ?? '3', 10)
|
|
151
|
+
permissionDenied: !!js parseInt(process.env.DSH_EDGE_AUDIT_PERM_DENIED ?? '5', 10)
|
|
152
|
+
flushIntervalMs: !!js parseInt(process.env.DSH_EDGE_AUDIT_FLUSH_MS ?? '500', 10)
|
|
153
|
+
|
|
154
|
+
# Hot-reloadable privacy policy engine.
|
|
155
|
+
- id: privacy-policy
|
|
156
|
+
name: '@dsh-edge/dsh-edge-agent/privacy-policy'
|
|
157
|
+
inject: [tcm, localStorage, auditLog]
|
|
158
|
+
config:
|
|
159
|
+
policyPath: !!js process.env.DSH_EDGE_POLICY_PATH ?? ((process.env.USERPROFILE ?? process.env.HOME) + '/.dsh-edge-agent/policy.json')
|
|
160
|
+
hotReload: !!js process.env.DSH_EDGE_POLICY_HOT_RELOAD !== 'false'
|
|
161
|
+
watchIntervalMs: !!js parseInt(process.env.DSH_EDGE_POLICY_WATCH_MS ?? '5000', 10)
|
|
162
|
+
|
|
163
|
+
# Realm-aware tool registry (LOCAL / CLOUD / SANITIZED).
|
|
164
|
+
- id: tools
|
|
165
|
+
name: '@dsh-edge/dsh-edge-agent/tools'
|
|
166
|
+
inject: [auditLog]
|
|
167
|
+
config:
|
|
168
|
+
defaultRateLimitPerMinute: !!js parseInt(process.env.DSH_EDGE_TOOL_RATE ?? '60', 10)
|
|
169
|
+
enableToolIsolation: !!js process.env.DSH_EDGE_TOOL_ISOLATION !== 'false'
|
|
170
|
+
|
|
171
|
+
# Realm-aware skill + tool isolation bridge. Reads skill-realms.json to tag
|
|
172
|
+
# every discovered skill/tool as LOCAL | CLOUD | hidden, then enforces the
|
|
173
|
+
# mapping at agent/pre-step (catalog filtering) and tools/pre-execute (deny
|
|
174
|
+
# cross-realm calls). Hot-reloads the config file without restart.
|
|
175
|
+
- id: realm-skill-bridge
|
|
176
|
+
name: '@dsh-edge/dsh-edge-agent/realm-skill-bridge'
|
|
177
|
+
inject: [auditLog]
|
|
178
|
+
config:
|
|
179
|
+
configPath: !!js process.env.DSH_EDGE_REALM_CONFIG ?? ((process.env.USERPROFILE ?? process.env.HOME) + '/.dsh-edge-agent/skill-realms.json')
|
|
180
|
+
hotReload: !!js process.env.DSH_EDGE_REALM_HOT_RELOAD !== 'false'
|
|
181
|
+
watchIntervalMs: !!js parseInt(process.env.DSH_EDGE_REALM_WATCH_MS ?? '5000', 10)
|
|
182
|
+
|
|
183
|
+
# Input/output safety scanning. MVP: checkInput only with 4 default rules.
|
|
184
|
+
- id: prompt-guard
|
|
185
|
+
name: '@dsh-edge/dsh-edge-agent/prompt-guard'
|
|
186
|
+
inject: [tcm, privacyPolicy, auditLog, llm]
|
|
187
|
+
config:
|
|
188
|
+
rules: []
|
|
189
|
+
enableModelDetection: !!js process.env.DSH_EDGE_GUARD_MODEL !== 'false'
|
|
190
|
+
modelDetectionProvider: !!js process.env.DSH_EDGE_GUARD_MODEL_PROVIDER ?? 'local-llm'
|
|
191
|
+
modelDetectionModel: !!js process.env.DSH_EDGE_GUARD_MODEL_MODEL ?? 'qwen3-4b'
|
|
192
|
+
modelDetectionTimeoutMs: !!js parseInt(process.env.DSH_EDGE_GUARD_MODEL_TIMEOUT_MS ?? '4000', 10)
|
|
193
|
+
modelDetectionMaxInputLength: !!js parseInt(process.env.DSH_EDGE_GUARD_MODEL_MAX_INPUT ?? '2000', 10)
|
|
194
|
+
|
|
195
|
+
# Intent classification → routing decision.
|
|
196
|
+
- id: intent-router
|
|
197
|
+
name: '@dsh-edge/dsh-edge-agent/intent-router'
|
|
198
|
+
inject: [llm, promptGuard, privacyPolicy, auditLog, sessions, localStorage]
|
|
199
|
+
config:
|
|
200
|
+
confidenceThreshold: !!js parseFloat(process.env.DSH_EDGE_INTENT_CONFIDENCE_THRESHOLD ?? '0.6')
|
|
201
|
+
llmTimeoutMs: !!js parseInt(process.env.DSH_EDGE_INTENT_LLM_TIMEOUT_MS ?? '4000', 10)
|
|
202
|
+
recentMessagesLimit: !!js parseInt(process.env.DSH_EDGE_INTENT_RECENT_LIMIT ?? '3', 10)
|
|
203
|
+
maxInputLength: !!js parseInt(process.env.DSH_EDGE_INTENT_MAX_INPUT ?? '2000', 10)
|
|
204
|
+
fallbackKeywords: !!js (process.env.DSH_EDGE_INTENT_FALLBACK_KEYWORDS ?? '').split(',').filter(Boolean)
|
|
205
|
+
cloudKeywords: !!js (process.env.DSH_EDGE_INTENT_CLOUD_KEYWORDS ?? '').split(',').filter(Boolean)
|
|
206
|
+
|
|
207
|
+
# Model router — single `llm` surface, routes to local/cloud adapters.
|
|
208
|
+
- id: model-router
|
|
209
|
+
name: '@dsh-edge/dsh-edge-agent/model-router'
|
|
210
|
+
inject: [llm, privacyPolicy, auditLog]
|
|
211
|
+
config:
|
|
212
|
+
defaultModel: !!js process.env.DSH_EDGE_DEFAULT_MODEL ?? 'local-llm'
|
|
213
|
+
localModels: !!js (process.env.DSH_EDGE_LOCAL_MODELS ?? 'local-llm,local-llm-llama3').split(',').filter(Boolean)
|
|
214
|
+
cloudModels: !!js (process.env.DSH_EDGE_CLOUD_MODELS ?? 'cloud-llm,cloud-llm-v3').split(',').filter(Boolean)
|
|
215
|
+
|
|
216
|
+
# Local LLM adapter (OpenAI-compatible endpoint).
|
|
217
|
+
#
|
|
218
|
+
# NOTE: Pre-fix (2026-09-11), this row passed `modelPath` / `contextSize` /
|
|
219
|
+
# `threads` which are NOT in the plugin's Schema — Schemastery silently dropped
|
|
220
|
+
# them. Meanwhile `baseUrl` / `defaultModel` / `apiKeyEnv` were never wired,
|
|
221
|
+
# so .env.sh's DSH_EDGE_LOCAL_LLM_BASEURL etc. never reached the adapter.
|
|
222
|
+
# Rewritten to match `Schema.object({providers, baseUrl, defaultModel, apiKeyEnv})`
|
|
223
|
+
# in src/dsh-adapter/local-llm-adapter.ts.
|
|
224
|
+
#
|
|
225
|
+
# `apiKeyEnv` lets the adapter read a bearer from any env var (e.g. for
|
|
226
|
+
# cloud-hosted OpenAI-compatible endpoints like DashScope, OpenRouter, etc).
|
|
227
|
+
# Leave undefined to skip the Authorization header (plain llama.cpp server).
|
|
228
|
+
- id: local-llm-adapter
|
|
229
|
+
name: '@dsh-edge/dsh-edge-agent/local-llm-adapter'
|
|
230
|
+
config:
|
|
231
|
+
providers: !!js (process.env.DSH_EDGE_LOCAL_MODELS ?? 'local-llm').split(',').filter(Boolean)
|
|
232
|
+
baseUrl: !!js process.env.DSH_EDGE_LOCAL_LLM_BASEURL ?? 'http://127.0.0.1:8080/v1'
|
|
233
|
+
defaultModel: !!js process.env.DSH_EDGE_LOCAL_LLM_MODEL ?? 'qwen3-4b'
|
|
234
|
+
apiKeyEnv: !!js process.env.DSH_EDGE_LOCAL_LLM_APIKEY_ENV ?? undefined
|
|
235
|
+
|
|
236
|
+
# Cloud LLM adapter (DeepSeek / other providers). Routes through secure-bridge.
|
|
237
|
+
- id: cloud-llm-adapter
|
|
238
|
+
name: '@dsh-edge/dsh-edge-agent/cloud-llm-adapter'
|
|
239
|
+
inject: [secureBridge, auditLog]
|
|
240
|
+
config:
|
|
241
|
+
providers: !!js (process.env.DSH_EDGE_CLOUD_MODELS ?? 'cloud-llm').split(',').filter(Boolean)
|
|
242
|
+
# §7.100: 空 = DELEGATE 模式(继承宿主 profile 提供商);显式配端点才直连
|
|
243
|
+
baseUrl: !!js process.env.DEEPSEEK_BASE_URL || ''
|
|
244
|
+
apiKeyEnv: !!js process.env.DSH_EDGE_CLOUD_KEY_ENV ?? 'DEEPSEEK_API_KEY'
|
|
245
|
+
|
|
246
|
+
# Forward / reverse PII sanitization (SANITIZED realm).
|
|
247
|
+
- id: sanitizer-pipeline
|
|
248
|
+
name: '@dsh-edge/dsh-edge-agent/sanitizer-pipeline'
|
|
249
|
+
inject: [localStorage, privacyPolicy]
|
|
250
|
+
config:
|
|
251
|
+
enableAutoDetection: !!js process.env.DSH_EDGE_SAN_AUTO !== 'false'
|
|
252
|
+
maxReplacementsPerSession: !!js parseInt(process.env.DSH_EDGE_SAN_MAX ?? '1024', 10)
|
|
253
|
+
# 会话映射表持有明文 PII,必须有生命周期上限。http-api 删会话时会主动
|
|
254
|
+
# purge;以下两项是防止调用方漏调的兜底(2026-08-30)。
|
|
255
|
+
sessionTtlMs: !!js parseInt(process.env.DSH_EDGE_SAN_TTL_MS ?? '900000', 10)
|
|
256
|
+
maxSessions: !!js parseInt(process.env.DSH_EDGE_SAN_MAX_SESSIONS ?? '1000', 10)
|
|
257
|
+
sweepIntervalMs: !!js parseInt(process.env.DSH_EDGE_SAN_SWEEP_MS ?? '60000', 10)
|
|
258
|
+
|
|
259
|
+
# OHTTP gateway (RFC 9458) — HPKE ciphertext to a relay that cannot link
|
|
260
|
+
# user identity to request content.
|
|
261
|
+
- id: ohttp-gateway
|
|
262
|
+
name: '@dsh-edge/dsh-edge-agent/ohttp-gateway'
|
|
263
|
+
inject: [tcm, auditLog]
|
|
264
|
+
config:
|
|
265
|
+
relayUrl: !!js process.env.DSH_EDGE_OHTTP_RELAY ?? ''
|
|
266
|
+
targetUrl: !!js process.env.DSH_EDGE_OHTTP_TARGET ?? ''
|
|
267
|
+
publicKey: !!js process.env.DSH_EDGE_OHTTP_PUBKEY ?? ''
|
|
268
|
+
keyId: !!js process.env.DSH_EDGE_OHTTP_KEY_ID ?? ''
|
|
269
|
+
allowFallbackTls: !!js process.env.DSH_EDGE_ALLOW_FALLBACK_TLS === 'true'
|
|
270
|
+
|
|
271
|
+
# Outbound channel for cloud-bound requests.
|
|
272
|
+
- id: secure-bridge
|
|
273
|
+
name: '@dsh-edge/dsh-edge-agent/secure-bridge'
|
|
274
|
+
inject: [tcm, ohttp, privacyPolicy, auditLog]
|
|
275
|
+
config:
|
|
276
|
+
mode: !!js process.env.DSH_EDGE_BRIDGE_MODE ?? 'ohttp'
|
|
277
|
+
domainAllowList: !!js (process.env.DSH_EDGE_BRIDGE_ALLOW ?? '').split(',').filter(Boolean)
|
|
278
|
+
domainDenyList: !!js (process.env.DSH_EDGE_BRIDGE_DENY ?? '').split(',').filter(Boolean)
|
|
279
|
+
requestTimeoutMs: !!js parseInt(process.env.DSH_EDGE_BRIDGE_TIMEOUT_MS ?? '30000', 10)
|
|
280
|
+
|
|
281
|
+
# TEE attestation token generation + verification.
|
|
282
|
+
- id: attestation
|
|
283
|
+
name: '@dsh-edge/dsh-edge-agent/attestation'
|
|
284
|
+
inject: [tcm, auditLog]
|
|
285
|
+
config:
|
|
286
|
+
verifierUrl: !!js process.env.DSH_EDGE_ATTEST_VERIFIER ?? undefined
|
|
287
|
+
nonceTtlSeconds: !!js parseInt(process.env.DSH_EDGE_ATTEST_NONCE_TTL ?? '60', 10)
|
|
288
|
+
|
|
289
|
+
# Threat detection bus. Subscribes to high-volume events and raises a
|
|
290
|
+
# quarantine action when patterns indicate abuse. Phase D: real state
|
|
291
|
+
# machine; http-api reads getThreatLevel() and blocks at blockLevel.
|
|
292
|
+
- id: td-bus
|
|
293
|
+
name: '@dsh-edge/dsh-edge-agent/td-bus'
|
|
294
|
+
inject: [auditLog, privacyPolicy]
|
|
295
|
+
config:
|
|
296
|
+
windowSeconds: !!js parseInt(process.env.DSH_EDGE_TD_WINDOW ?? '60', 10)
|
|
297
|
+
thresholds:
|
|
298
|
+
cloudRequestsPerMinute: !!js parseInt(process.env.DSH_EDGE_TD_CLOUD_RATE ?? '20', 10)
|
|
299
|
+
failedSanitizationStreak: !!js parseInt(process.env.DSH_EDGE_TD_SAN ?? '3', 10)
|
|
300
|
+
permissionDeniedStreak: !!js parseInt(process.env.DSH_EDGE_TD_PERM ?? '5', 10)
|
|
301
|
+
blockLevel: !!js process.env.DSH_EDGE_TD_BLOCK_LEVEL ?? 'critical'
|
|
302
|
+
|
|
303
|
+
# Voice input (Whisper-tiny). MVP off by default.
|
|
304
|
+
- id: voice-input
|
|
305
|
+
name: '@dsh-edge/dsh-edge-agent/voice-input'
|
|
306
|
+
inject: [sessions, auditLog]
|
|
307
|
+
config:
|
|
308
|
+
modelPath: !!js process.env.DSH_EDGE_VOICE_MODEL ?? ((process.env.USERPROFILE ?? process.env.HOME) + '/.dsh-edge-agent/models/whisper-tiny.bin')
|
|
309
|
+
vadSilenceThreshold: !!js parseFloat(process.env.DSH_EDGE_VOICE_VAD ?? '0.6')
|
|
310
|
+
sampleRate: !!js parseInt(process.env.DSH_EDGE_VOICE_SR ?? '16000', 10)
|
|
311
|
+
|
|
312
|
+
# Plugin-interop anchor (Community Consensus v0.15 unified grant store,
|
|
313
|
+
# runtime generation id, Host Descriptor). Mounted ahead of any third-party
|
|
314
|
+
# plugin row.
|
|
315
|
+
- id: plugin-host
|
|
316
|
+
name: '@dsh-edge/dsh-edge-agent/plugin-host'
|
|
317
|
+
inject: [agents, sessions]
|
|
318
|
+
config:
|
|
319
|
+
enableThirdParty: !!js process.env.DSH_EDGE_PLUGINS_THIRD_PARTY === 'true'
|
|
320
|
+
grantStorePath: !!js (process.env.DSH_EDGE_STORAGE_ROOT ?? ((process.env.USERPROFILE ?? process.env.HOME) + '/.dsh-edge-agent')) + '/grants.json'
|
|
321
|
+
|
|
322
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
323
|
+
# 4. Sandbox + telemetry
|
|
324
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
325
|
+
|
|
326
|
+
# Sandbox confinement. The edge agent defaults to workspace-write; cloud
|
|
327
|
+
# requests are gated by secure-bridge, not the sandbox.
|
|
328
|
+
- id: sandbox-policy
|
|
329
|
+
name: '@deepseek-ai/dsh-sandbox-local'
|
|
330
|
+
config:
|
|
331
|
+
mode: !!js "process.platform === 'win32' ? 'danger-full-access' : (process.env.DSH_EDGE_PERMISSION_MODE ?? 'workspace-write')"
|
|
332
|
+
workspaceRoot: !!js process.cwd()
|
|
333
|
+
|
|
334
|
+
# Subprocess + bash capability. Edge agent uses a tighter timeout than the
|
|
335
|
+
# default coding agent (60s vs the dsh-base 10min) because edge sessions are
|
|
336
|
+
# shorter-lived.
|
|
337
|
+
- id: subprocess
|
|
338
|
+
name: '@deepseek-ai/dsh-subprocess-local'
|
|
339
|
+
|
|
340
|
+
- id: bash
|
|
341
|
+
name: '@deepseek-ai/dsh-bash-local'
|
|
342
|
+
config:
|
|
343
|
+
cwd: !!js process.cwd()
|
|
344
|
+
timeoutMs: !!js parseInt(process.env.DSH_EDGE_BASH_TIMEOUT_MS ?? '60000', 10)
|
|
345
|
+
|
|
346
|
+
# Model-facing bash tool
|
|
347
|
+
- id: tool-bash
|
|
348
|
+
name: '@deepseek-ai/dsh-tool-bash'
|
|
349
|
+
config:
|
|
350
|
+
enableRunInBackground: false
|
|
351
|
+
|
|
352
|
+
# Model-facing web tools (web_search + web_fetch)
|
|
353
|
+
- id: tool-web
|
|
354
|
+
name: '@deepseek-ai/dsh-tool-web'
|
|
355
|
+
config:
|
|
356
|
+
search: true
|
|
357
|
+
fetch: true
|
|
358
|
+
searchMaxResults: 8
|
|
359
|
+
fetchTimeoutMs: 30000
|
|
360
|
+
searchTimeoutMs: 30000
|
|
361
|
+
|
|
362
|
+
# DeepSeek web search provider (Anthropic-compatible API)
|
|
363
|
+
- id: web-search-deepseek
|
|
364
|
+
name: '@deepseek-ai/dsh-web-search-deepseek'
|
|
365
|
+
config:
|
|
366
|
+
apiKeyEnv: DEEPSEEK_API_KEY
|
|
367
|
+
baseURL: https://api.deepseek.com/anthropic/v1
|
|
368
|
+
model: deepseek-v4-flash
|
|
369
|
+
|
|
370
|
+
# Telemetry (DSH built-in).
|
|
371
|
+
- id: telemetry
|
|
372
|
+
name: '@deepseek-ai/dsh-telemetry'
|
|
373
|
+
config:
|
|
374
|
+
enabled: !!js process.env.DSH_EDGE_TELEMETRY === 'true'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attestation.d.ts","sourceRoot":"","sources":["../src/attestation.ts"],"names":[],"mappings":"AACA,cAAc,8BAA8B,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-log.d.ts","sourceRoot":"","sources":["../src/audit-log.ts"],"names":[],"mappings":"AACA,cAAc,4BAA4B,CAAA"}
|
package/lib/audit-log.js
ADDED
package/lib/client.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/* dsh-edge-agent client bundle — generated by scripts/build-client.mjs.
|
|
2
|
+
Format: DSH webview module-system registration (classic script). */
|
|
3
|
+
window.__ModuleLoader__.load({
|
|
4
|
+
id: "@dsh-edge/dsh-edge-agent",
|
|
5
|
+
factory: function (require) {
|
|
6
|
+
var module = { exports: {} };
|
|
7
|
+
var exports = module.exports;
|
|
8
|
+
(function () {
|
|
9
|
+
"use strict";var re=Object.defineProperty;var Fe=Object.getOwnPropertyDescriptor;var De=Object.getOwnPropertyNames;var Oe=Object.prototype.hasOwnProperty;var _e=(e,n)=>{for(var o in n)re(e,o,{get:n[o],enumerable:!0})},Ne=(e,n,o,i)=>{if(n&&typeof n=="object"||typeof n=="function")for(let s of De(n))!Oe.call(e,s)&&s!==o&&re(e,s,{get:()=>n[s],enumerable:!(i=Fe(n,s))||i.enumerable});return e};var Ae=e=>Ne(re({},"__esModule",{value:!0}),e);var Lt={};_e(Lt,{EdgeView:()=>Me,apply:()=>Tt,h:()=>L.createElement,inject:()=>Rt,name:()=>xt,render:()=>Ct});module.exports=Ae(Lt);var L=require("react"),je=require("react-dom/client");var fe="api/dsh-edge/context",pe="api/dsh-edge/trace";var We=2e3,le=200,U=new Map,ie=new Set,H,Y=0;function Be(){for(let e of[...ie])try{e()}catch{}}function we(e){let n=U.get(e);return n||(n={cursor:0,rows:[],summary:{sessionId:e,turns:0},failures:0},U.set(e,n)),n}async function ge(e){for(let n of e){let o=we(n);try{let i=await fetch(fe,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({sessionId:n,cursor:o.cursor})});if(!i.ok){o.failures+=1;continue}let s=await i.json();o.failures=0,typeof s.cursor=="number"&&s.cursor>o.cursor&&(o.cursor=s.cursor),Array.isArray(s.rows)&&(o.rows=[...o.rows,...s.rows.filter(r=>r&&typeof r.kind=="string"&&typeof r.panel=="string")],o.rows.length>le*4&&(o.rows=o.rows.slice(-le*4))),s.summary&&typeof s.summary=="object"&&(o.summary=s.summary)}catch{o.failures+=1}}Be()}function Ge(){H===void 0&&(ge([...U.keys()]),H=setInterval(()=>{Y!==0&&ge([...U.keys()])},We))}function Ue(){Y>0||H===void 0||(clearInterval(H),H=void 0)}async function be(e){try{let n=await fetch(pe,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({traceId:e})});if(!n.ok){let s=`HTTP ${n.status}`;try{let r=await n.json();typeof r?.error=="string"&&r.error.length>0&&(s=r.error)}catch{}return{ok:!1,error:s}}let o=await n.json(),i;try{i=JSON.stringify(o,null,2)??String(o)}catch{i=String(o)}return{ok:!0,text:i}}catch(n){return{ok:!1,error:n instanceof Error?n.message:String(n)}}}var V={attach(e,n){return Y+=1,we(e),ie.add(n),Ge(),n(),()=>{Y-=1,ie.delete(n),Ue()}},rowsFor(e,n,o,i){return this.currentRows(e,o,i).filter(s=>s.panel===n)},currentRows(e,n,o){let i=U.get(e);if(!i)return[];let s=[];for(let r of i.rows)o!==void 0&&r.ts<o||s.push(r);return s.slice(-le)},summaryFor(e){return U.get(e)?.summary??{sessionId:e,turns:0}},failing(e){return(U.get(e)?.failures??0)>=3}};var he="dsh-edge-agent-styles",qe=`
|
|
10
|
+
/* The host's tab body is overflow:hidden (SidebarRight.module.css .tabBody) and
|
|
11
|
+
hands scrolling to the occupant \u2014 without an explicit scroll container here
|
|
12
|
+
the flow + panels below the fold were simply clipped (observed desktop
|
|
13
|
+
10-23: threat panel unreachable). flex:none keeps sections at natural height
|
|
14
|
+
inside the scroller instead of shrinking. */
|
|
15
|
+
.dsh-edge-view { font-size: 12px; line-height: 1.5; padding: 8px 10px; display: flex; flex-direction: column; gap: 10px; height: 100%; overflow-y: auto; box-sizing: border-box; }
|
|
16
|
+
.dsh-edge-view > * { flex: none; }
|
|
17
|
+
.dsh-edge-tab-title { font-weight: 500; }
|
|
18
|
+
.dsh-edge-flow { display: flex; flex-direction: column; padding: 6px 8px; border-radius: 6px; background: color-mix(in srgb, currentColor 4%, transparent); }
|
|
19
|
+
/* \xA77.107: every node renders with the same three levels \u2014 label line,
|
|
20
|
+
verdict line, evidence lines. The label used to share a baseline with
|
|
21
|
+
the verdict, so a long verdict wrapped under the label and the column
|
|
22
|
+
lost its grid. */
|
|
23
|
+
.dsh-edge-flow-node { display: flex; flex-direction: column; font-size: 12px; line-height: 1.5; }
|
|
24
|
+
.dsh-edge-flow-head { display: flex; align-items: center; gap: 6px; }
|
|
25
|
+
.dsh-edge-flow-arrow { width: 8px; text-align: center; opacity: 0.35; font-size: 10px; line-height: 1.1; margin-left: 3px; }
|
|
26
|
+
.dsh-edge-flow-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; align-self: center; background: color-mix(in srgb, currentColor 25%, transparent); }
|
|
27
|
+
.dsh-edge-flow-label { flex: none; font-weight: 600; }
|
|
28
|
+
.dsh-edge-flow-detail { padding-left: 14px; opacity: 0.85; overflow-wrap: anywhere; }
|
|
29
|
+
.dsh-edge-flow-sub { font-size: 11px; line-height: 1.5; opacity: 0.55; padding-left: 26px; overflow-wrap: anywhere; }
|
|
30
|
+
.dsh-edge-flow-node--ok .dsh-edge-flow-dot { background: #16a34a; }
|
|
31
|
+
.dsh-edge-flow-node--warn .dsh-edge-flow-dot { background: #d97706; }
|
|
32
|
+
.dsh-edge-flow-node--stop .dsh-edge-flow-dot { background: #dc2626; }
|
|
33
|
+
.dsh-edge-flow-node--run .dsh-edge-flow-dot { background: #2563eb; }
|
|
34
|
+
.dsh-edge-flow-node--info .dsh-edge-flow-dot { background: #64748b; }
|
|
35
|
+
.dsh-edge-flow-node--wait { opacity: 0.5; }
|
|
36
|
+
.dsh-edge-verdict { font-size: 12px; font-weight: 600; padding: 5px 8px; border-radius: 6px; border-left: 2px solid currentColor; background: color-mix(in srgb, currentColor 5%, transparent); }
|
|
37
|
+
.dsh-edge-verdict--local { color: #16a34a; }
|
|
38
|
+
.dsh-edge-verdict--cloud { color: inherit; }
|
|
39
|
+
.dsh-edge-verdict--wait { opacity: 0.55; font-weight: 400; }
|
|
40
|
+
/* \xA77.145: \u672A\u7ED1\u5B9A\u4F1A\u8BDD \u2014\u2014 \u660E\u8BF4\u300C\u73B0\u5728\u6CA1\u6709\u4F1A\u8BDD\u300D\uFF0C\u5168\u5C40\u4FE1\u53F7\u53E6\u8D77\u4E00\u7EC4\u3002 */
|
|
41
|
+
.dsh-edge-unbound { display: flex; flex-direction: column; gap: 3px; padding: 6px 8px; border-radius: 6px; border-left: 2px solid color-mix(in srgb, currentColor 35%, transparent); background: color-mix(in srgb, currentColor 5%, transparent); }
|
|
42
|
+
.dsh-edge-unbound b { font-weight: 600; }
|
|
43
|
+
.dsh-edge-unbound span { opacity: 0.7; font-size: 11px; line-height: 1.5; }
|
|
44
|
+
.dsh-edge-groups { display: flex; flex-direction: column; gap: 8px; }
|
|
45
|
+
.dsh-edge-summary { display: flex; flex-wrap: wrap; gap: 10px; padding: 6px 8px; border-radius: 6px; background: color-mix(in srgb, currentColor 6%, transparent); }
|
|
46
|
+
.dsh-edge-summary b { font-weight: 600; }
|
|
47
|
+
.dsh-edge-panel h4 { margin: 0 0 4px 0; font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; opacity: 0.65; font-weight: 600; }
|
|
48
|
+
.dsh-edge-rows { display: flex; flex-direction: column; gap: 3px; max-height: 240px; overflow-y: auto; }
|
|
49
|
+
.dsh-edge-row { padding: 3px 6px; border-radius: 4px; background: color-mix(in srgb, currentColor 4%, transparent); }
|
|
50
|
+
.dsh-edge-row-head { display: flex; gap: 6px; align-items: baseline; }
|
|
51
|
+
.dsh-edge-row .ts { opacity: 0.5; flex: none; font-variant-numeric: tabular-nums; font-size: 11px; }
|
|
52
|
+
.dsh-edge-row .k { font-weight: 600; overflow-wrap: anywhere; }
|
|
53
|
+
.dsh-edge-row .f { opacity: 0.75; font-size: 11px; line-height: 1.35; margin-top: 1px; overflow-wrap: anywhere; }
|
|
54
|
+
.dsh-edge-row.warn { background: color-mix(in srgb, #d97706 14%, transparent); }
|
|
55
|
+
.dsh-edge-row.error, .dsh-edge-row.security { background: color-mix(in srgb, #dc2626 14%, transparent); }
|
|
56
|
+
.dsh-edge-empty, .dsh-edge-stale { opacity: 0.5; font-style: italic; }
|
|
57
|
+
.dsh-edge-stale { color: #dc2626; opacity: 0.8; }
|
|
58
|
+
/* \xA77.133: the LLM call log \u2014 one line per call, body on demand. */
|
|
59
|
+
.dsh-edge-trace { display: flex; flex-direction: column; gap: 4px; }
|
|
60
|
+
.dsh-edge-trace-count { margin-left: auto; opacity: 0.5; font-variant-numeric: tabular-nums; }
|
|
61
|
+
.dsh-edge-trace-list { display: flex; flex-direction: column; gap: 4px; }
|
|
62
|
+
.dsh-edge-trace-item { padding: 4px 6px; border-radius: 4px; background: color-mix(in srgb, currentColor 4%, transparent); }
|
|
63
|
+
.dsh-edge-trace-head { display: flex; gap: 6px; align-items: baseline; width: 100%; text-align: left; background: none; border: none; color: inherit; font: inherit; padding: 0; cursor: pointer; }
|
|
64
|
+
.dsh-edge-trace-badge { flex: none; font-size: 10px; font-weight: 700; letter-spacing: 0.03em; padding: 0 3px; border-radius: 3px; background: color-mix(in srgb, currentColor 15%, transparent); }
|
|
65
|
+
.dsh-edge-trace-badge--req { color: #2563eb; }
|
|
66
|
+
.dsh-edge-trace-badge--resp { color: #16a34a; }
|
|
67
|
+
.dsh-edge-trace-model { flex: 1 1 auto; font-weight: 600; overflow-wrap: anywhere; }
|
|
68
|
+
.dsh-edge-trace-caller { flex: none; font-size: 10px; opacity: 0.65; border: 1px solid color-mix(in srgb, currentColor 25%, transparent); border-radius: 3px; padding: 0 3px; }
|
|
69
|
+
.dsh-edge-trace-caller--main { opacity: 0.9; }
|
|
70
|
+
.dsh-edge-trace-sum { font-size: 11px; opacity: 0.8; padding-left: 2px; overflow-wrap: anywhere; }
|
|
71
|
+
.dsh-edge-trace-meta { font-size: 10px; opacity: 0.45; overflow-wrap: anywhere; }
|
|
72
|
+
.dsh-edge-trace-body { margin-top: 4px; }
|
|
73
|
+
.dsh-edge-trace-body-err { font-size: 11px; color: #d97706; }
|
|
74
|
+
.dsh-edge-trace-pre { margin: 0; max-height: 260px; overflow: auto; padding: 5px 6px; border-radius: 4px; background: color-mix(in srgb, currentColor 6%, transparent); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
75
|
+
/* \xA77.134: \u6309\u7C7B\u522B\u5206\u7EC4 + \u8BF7\u6C42/\u54CD\u5E94\u6210\u5BF9\uFF08\u4E0A\u8BF7\u6C42\u3001\u4E0B\u54CD\u5E94\uFF09\u3002 */
|
|
76
|
+
.dsh-edge-trace-group { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }
|
|
77
|
+
.dsh-edge-trace-group-head { display: flex; gap: 6px; align-items: baseline; padding: 1px 2px; border-bottom: 1px solid color-mix(in srgb, currentColor 15%, transparent); }
|
|
78
|
+
.dsh-edge-trace-group-name { font-size: 11px; font-weight: 700; letter-spacing: 0.02em; }
|
|
79
|
+
.dsh-edge-trace-pair { display: flex; flex-direction: column; gap: 2px; padding: 4px 6px; border-radius: 4px; background: color-mix(in srgb, currentColor 4%, transparent); }
|
|
80
|
+
.dsh-edge-trace-half { padding-left: 6px; border-left: 2px solid transparent; }
|
|
81
|
+
.dsh-edge-trace-half--req { border-left-color: #2563eb; }
|
|
82
|
+
.dsh-edge-trace-half--resp { border-left-color: #16a34a; }
|
|
83
|
+
`;function me(e){let n=e??(typeof document<"u"?document:void 0);if(n===void 0||n.getElementById(he)!==null)return;let o=n.createElement("style");o.id=he,o.textContent=qe,n.head.appendChild(o)}var Z={"tab.title":"Edge","panel.intent":"Intent","panel.route":"Route","panel.interception":"Interception","panel.threat":"Threat","summary.turns":"turns","summary.tokens":"tokens","summary.noTokens":"no usage reported","summary.age":"age","row.empty":"no events yet","row.stale":"edge host unreachable","guide.description":"Intent classification \xB7 model routing \xB7 guard / sanitizer events \xB7 threat levels","verdict.local":"This turn: answered locally \u2014 data never left the device","verdict.cloud":"This turn: answered by the cloud route","verdict.sanitized":" (PII sanitized first)","verdict.waiting":"This turn: awaiting classification","flow.guard":"attack check","flow.intent":"intent verdict","flow.sanitize":"PII scrub","flow.route":"routing","flow.answer":"answer egress","flow.wait":"waiting","flow.running":"running\u2026","flow.guard.injection":"injection pattern hit (warned, passed)","flow.guard.failopen":"model check failed \u2192 regex tier held","flow.guard.public":"clean (public data)","flow.guard.skipped":"rules tier only","flow.guard.running":"model judging\u2026","flow.intent.rejected":"policy denied","flow.intent.viaEntity":"entity rule","flow.intent.viaLlm":"LLM verdict","flow.intent.viaDefault":"default fallback (classifier silent)","flow.intent.viaPolicy":"privacy rule decided (classifier skipped)","flow.intent.noWebNeed":"no public-web need \u2192 kept on device","flow.intent.noWebNeedWhy":"the classifier asked for the cloud, but the request was not a public-web search","flow.intent.defaultNoCause":"classifier silent \u2014 defaultCategory applied","flow.answer.carried":"carried from last route","flow.answer.running":"answering\u2026","flow.answer.failed":"answer failed","flow.sanitize.hits":"scrubbed","flow.sanitize.done":"scrubbed","flow.sanitize.failed":"scrub failed \u2192 answered locally","flow.sanitize.localSkip":"not needed (local)","flow.sanitize.clean":"no PII found","flow.route.blocked":"blocked","flow.route.fallback":"answered locally (cloud unavailable)","flow.route.kept":"as selected","flow.answer.pending":"route not settled yet","flow.answer.local":"local model \xB7 stayed on device","flow.answer.cloud":"cloud:","flow.lbl.cause":"cause","flow.lbl.judge":"verdict","flow.lbl.model":"model","flow.lbl.input":"input","flow.lbl.elapsed":"took","flow.lbl.scanned":"scanned","flow.lbl.chars":"chars","flow.lbl.msgs":"messages","flow.lbl.rule":"rule","flow.lbl.confidence":"confidence","flow.lbl.pool":"cloud pool","flow.lbl.verdict":"verdict","flow.lbl.override":"override","flow.lbl.entity":"entity","flow.lbl.llmSay":"LLM said","flow.lbl.overridden":"\u2014 overridden by rule","flow.lbl.classifier":"classifier","flow.lbl.reason":"reason","flow.lbl.entry":"entry","flow.lbl.edgePool":"edge cloud pool","flow.lbl.used":"used","flow.lbl.hostOwn":"not used (host route)","flow.lbl.steps":"steps","flow.lbl.total":"total","flow.lbl.context":"last context","flow.lbl.in":"in","flow.lbl.out":"out","flow.lbl.route":"route","flow.class.public":"public","flow.class.internal":"internal","flow.class.confidential":"confidential","flow.class.secret":"secret","flow.g.guardrule":"warn-tier pattern hit","flow.g.regexOn":"regex tier still on duty","flow.s.done":"scrubbed","flow.sanitize.unit":"spans","flow.s.localWhy":"answer never leaves the device \u2014 nothing to scrub","flow.s.cleanWhy":"checked, no PII in the outbound text","flow.s.desanitized":"placeholders restored in the answer","flow.a.localKeep":"question, context and answer all stayed on this machine","flow.a.cloudSend":"outbound text was checked / scrubbed first","flow.lbl.risk":"risk","flow.lbl.why":"why","flow.lbl.hit":"hit","flow.lbl.regex":"regex","flow.lbl.keyword":"keyword","flow.lbl.semantic":"meaning","flow.lbl.path":"path","flow.lbl.jev":"decision model","flow.lbl.ph":"placeholder","flow.lbl.raw":"raw","flow.lbl.scope":"scope","flow.lbl.global":"global","flow.lbl.session":"session","flow.lbl.watched":"signals watched","flow.lbl.decidedBy":"decided by","flow.lbl.endpoint":"endpoint","flow.lbl.rerouted":"selection \u2192 actual","flow.lbl.onDevice":"on this device","flow.lbl.offDevice":"OFF-DEVICE","flow.intent.byJev":"decision model (LLM classifier not called)","flow.intent.byDeviceCommand":"device-command regex (classifier not called)","flow.intent.byLlm":"LLM classifier","flow.intent.byCache":"cached verdict","flow.intent.byRules":"keyword rules","flow.intent.byGate":"public-web gate","flow.intent.byUnknown":"unknown path","flow.intent.viaJev":"decision model","flow.intent.viaDeviceCommand":"device-command regex verdict","flow.intent.viaCache":"cached verdict","flow.intent.viaRules":"keyword rules","flow.guard.unsafe":"unsafe","flow.threat":"threat watch","flow.threat.calm":"quiet in this window","flow.threat.escalated":"threat escalated","flow.threat.rate":"rate limit hit","flow.threat.blocked":"blocked as threat","trace.title":"LLM calls","trace.empty":"no LLM call recorded in this turn","trace.req":"REQ","trace.resp":"RESP","trace.caller.guard":"guard check","trace.caller.classifier":"classifier","trace.caller.host":"host internal call","trace.caller.conversation":"conversation","trace.lbl.messages":"msgs","trace.lbl.chars":"chars","trace.lbl.dropped":"dropped","trace.lbl.toolCalls":"tool calls","trace.lbl.tools":"tools","trace.body.loading":"loading body\u2026","trace.body.gone":"body no longer in memory (only the latest calls are kept)","trace.body.error":"could not load body","trace.group.other":"other calls","unbound.title":"not bound to a session yet","unbound.hint":"No turn of this session is on the page yet \u2014 what follows are global signals, not one round. Start a turn and this becomes that session's record.","unbound.globalTitle":"global signals","unbound.empty":"no global signals right now"},ee={"tab.title":"Edge","panel.intent":"\u610F\u56FE","panel.route":"\u8DEF\u7531","panel.interception":"\u62E6\u622A","panel.threat":"\u5A01\u80C1","summary.turns":"\u8F6E\u6B21","summary.tokens":"token","summary.noTokens":"\u672A\u4E0A\u62A5\u7528\u91CF","summary.age":"\u65F6\u957F","row.empty":"\u6682\u65E0\u4E8B\u4EF6","row.stale":"edge \u670D\u52A1\u4E0D\u53EF\u8FBE","guide.description":"\u610F\u56FE\u5206\u7C7B \xB7 \u6A21\u578B\u8DEF\u7531 \xB7 \u9632\u62A4/\u8131\u654F\u4E8B\u4EF6 \xB7 \u5A01\u80C1\u6863\u4F4D","verdict.local":"\u672C\u8F6E\uFF1A\u672C\u5730\u6A21\u578B\u4F5C\u7B54 \u2014\u2014 \u6570\u636E\u672A\u79BB\u5F00\u8BBE\u5907","verdict.cloud":"\u672C\u8F6E\uFF1A\u4E91\u7AEF\u4F5C\u7B54","verdict.sanitized":"\uFF08\u5DF2\u5148\u8131\u654F\uFF09","verdict.waiting":"\u672C\u8F6E\uFF1A\u7B49\u5F85\u610F\u56FE\u5224\u5B9A","flow.guard":"\u653B\u51FB\u68C0\u6D4B","flow.intent":"\u610F\u56FE\u5224\u5B9A","flow.sanitize":"PII \u8131\u654F","flow.route":"\u8DEF\u7531\u51B3\u7B56","flow.answer":"\u7B54\u6848\u51FA\u53E3","flow.wait":"\u7B49\u5F85","flow.running":"\u8FDB\u884C\u4E2D\u2026","flow.guard.injection":"\u547D\u4E2D\u6CE8\u5165\u7279\u5F81\uFF08\u544A\u8B66\u653E\u884C\uFF09","flow.guard.failopen":"\u6A21\u578B\u68C0\u6D4B\u5931\u8D25 \u2192 \u6B63\u5219\u6863\u515C\u5E95","flow.guard.public":"\u5E72\u51C0\uFF08\u516C\u5F00\u7EA7\uFF09","flow.guard.skipped":"\u4EC5\u89C4\u5219\u6863","flow.guard.running":"\u6A21\u578B\u5224\u5B9A\u4E2D\u2026","flow.intent.rejected":"\u7B56\u7565\u62D2\u7EDD","flow.intent.viaEntity":"\u5B9E\u4F53\u89C4\u5219\u88C1\u51B3","flow.intent.viaLlm":"LLM \u88C1\u51B3","flow.intent.viaDefault":"\u9ED8\u8BA4\u6863\u515C\u5E95\uFF08\u5206\u7C7B\u5668\u672A\u56DE\u8BDD\uFF09","flow.intent.viaPolicy":"\u9690\u79C1\u89C4\u5219\u547D\u4E2D\uFF08\u672A\u8D70\u5206\u7C7B\u5668\uFF09","flow.intent.noWebNeed":"\u65E0\u516C\u7F51\u68C0\u7D22\u9700\u6C42 \u2192 \u7559\u5728\u672C\u5730","flow.intent.noWebNeedWhy":"\u5206\u7C7B\u5668\u5224\u4E86\u4E91\u7AEF\uFF0C\u4F46\u672C\u8F6E\u4E0D\u662F\u516C\u7F51\u68C0\u7D22\uFF0C\u62A4\u680F\u628A\u5B83\u6309\u56DE\u672C\u5730","flow.intent.defaultNoCause":"\u5206\u7C7B\u5668\u672A\u56DE\u8BDD\uFF0C\u8D70 defaultCategory \u515C\u5E95","flow.answer.carried":"\u6CBF\u7528\u4E0A\u4E00\u8F6E\u8DEF\u7531","flow.answer.running":"\u4F5C\u7B54\u4E2D\u2026","flow.answer.failed":"\u4F5C\u7B54\u5931\u8D25","flow.sanitize.hits":"\u5DF2\u66FF\u6362","flow.sanitize.done":"\u5DF2\u8131\u654F","flow.sanitize.failed":"\u8131\u654F\u5931\u8D25 \u2192 \u8F6C\u672C\u5730\u4F5C\u7B54","flow.sanitize.localSkip":"\u65E0\u9700\uFF08\u672C\u5730\u4F5C\u7B54\uFF09","flow.sanitize.clean":"\u672A\u53D1\u73B0 PII","flow.route.blocked":"\u5DF2\u62E6\u622A","flow.route.fallback":"\u8F6C\u672C\u5730\u4F5C\u7B54\uFF08\u4E91\u4E0D\u53EF\u7528\uFF09","flow.route.kept":"\u6309\u539F\u9009\u62E9","flow.answer.pending":"\u8DEF\u7531\u672A\u5B9A","flow.answer.local":"\u672C\u5730\u6A21\u578B \xB7 \u672A\u51FA\u8BBE\u5907","flow.answer.cloud":"\u4E91\u7AEF\uFF1A","flow.lbl.cause":"\u539F\u56E0","flow.lbl.judge":"\u5224\u5B9A","flow.lbl.model":"\u6A21\u578B","flow.lbl.input":"\u8F93\u5165","flow.lbl.elapsed":"\u7528\u65F6","flow.lbl.scanned":"\u68C0\u6D4B","flow.lbl.chars":"\u5B57","flow.lbl.msgs":"\u6761\u6D88\u606F","flow.lbl.rule":"\u547D\u4E2D\u89C4\u5219","flow.lbl.confidence":"\u7F6E\u4FE1","flow.lbl.pool":"\u4E91\u6C60","flow.lbl.verdict":"\u88C1\u51B3","flow.lbl.override":"\u6539\u5224","flow.lbl.entity":"\u5B9E\u4F53","flow.lbl.llmSay":"LLM \u539F\u5224","flow.lbl.overridden":"\u2014\u2014\u88AB\u89C4\u5219\u6539\u5224","flow.lbl.classifier":"\u5206\u7C7B\u5668","flow.lbl.reason":"\u7406\u7531","flow.lbl.entry":"\u5165\u53E3","flow.lbl.edgePool":"edge \u4E91\u6C60","flow.lbl.used":"\u5DF2\u4F7F\u7528","flow.lbl.hostOwn":"\u672A\u4F7F\u7528\uFF08\u8D70\u5BBF\u4E3B\u8DEF\u7531\uFF09","flow.lbl.steps":"\u6B65\u6570","flow.lbl.total":"\u7528\u65F6\u5408\u8BA1","flow.lbl.context":"\u672B\u8F6E\u4E0A\u4E0B\u6587","flow.lbl.in":"\u5165","flow.lbl.out":"\u51FA","flow.lbl.route":"\u8DEF\u7531","flow.class.public":"\u516C\u5F00\u7EA7","flow.class.internal":"\u5185\u90E8\u7EA7","flow.class.confidential":"\u673A\u5BC6\u7EA7","flow.class.secret":"\u654F\u611F\u7EA7","flow.g.guardrule":"\u547D\u4E2D\u544A\u8B66\u7EA7\u6CE8\u5165\u7279\u5F81","flow.g.regexOn":"\u6B63\u5219\u6863\u4ECD\u5728\u6267\u52E4","flow.s.done":"\u5DF2\u8131\u654F","flow.sanitize.unit":"\u5904","flow.s.localWhy":"\u7B54\u6848\u4E0D\u51FA\u8BBE\u5907\uFF0C\u65E0\u9700\u8131\u654F","flow.s.cleanWhy":"\u5DF2\u68C0\u67E5\uFF0C\u51FA\u5411\u6587\u672C\u65E0 PII","flow.s.desanitized":"\u7B54\u6848\u4E2D\u7684\u5360\u4F4D\u7B26\u5DF2\u8FD8\u539F","flow.a.localKeep":"\u95EE\u9898\u3001\u4E0A\u4E0B\u6587\u3001\u7B54\u6848\u5168\u90E8\u7559\u5728\u672C\u673A","flow.a.cloudSend":"\u51FA\u7F51\u6587\u672C\u5DF2\u5148\u884C\u68C0\u67E5/\u8131\u654F","flow.lbl.risk":"\u98CE\u9669\u7B49\u7EA7","flow.lbl.why":"\u7406\u7531","flow.lbl.hit":"\u547D\u4E2D","flow.lbl.regex":"\u6B63\u5219","flow.lbl.keyword":"\u5173\u952E\u5B57","flow.lbl.semantic":"\u8BED\u4E49","flow.lbl.path":"\u8DEF\u5F84","flow.lbl.jev":"\u51B3\u7B56\u6A21\u578B","flow.lbl.ph":"\u5360\u4F4D\u7B26","flow.lbl.raw":"\u539F\u59CB","flow.lbl.scope":"\u8303\u56F4","flow.lbl.global":"\u5168\u5C40","flow.lbl.session":"\u4F1A\u8BDD","flow.lbl.watched":"\u5DF2\u68C0\u4FE1\u53F7","flow.lbl.decidedBy":"\u88C1\u51B3\u8005","flow.lbl.endpoint":"\u771F\u5B9E\u843D\u70B9","flow.lbl.rerouted":"\u4F1A\u8BDD\u9009\u578B \u2192 \u5B9E\u9645\u843D\u70B9","flow.lbl.onDevice":"\u672C\u673A","flow.lbl.offDevice":"\u4E0D\u5728\u672C\u673A","flow.intent.byJev":"\u51B3\u7B56\u6A21\u578B\uFF08LLM \u5206\u7C7B\u5668\u672A\u8C03\u7528\uFF09","flow.intent.byDeviceCommand":"\u8BBE\u5907\u6307\u4EE4\u6B63\u5219\uFF08\u5206\u7C7B\u5668\u672A\u8C03\u7528\uFF09","flow.intent.byLlm":"LLM \u5206\u7C7B\u5668","flow.intent.byCache":"\u7F13\u5B58\u547D\u4E2D","flow.intent.byRules":"\u5173\u952E\u8BCD\u89C4\u5219","flow.intent.byGate":"\u516C\u7F51\u68C0\u7D22\u95F8\u95E8","flow.intent.byUnknown":"\u672A\u77E5\u8DEF\u5F84","flow.intent.viaJev":"\u51B3\u7B56\u6A21\u578B\u88C1\u51B3","flow.intent.viaDeviceCommand":"\u8BBE\u5907\u6307\u4EE4\u6B63\u5219\u88C1\u51B3","flow.intent.viaCache":"\u7F13\u5B58\u547D\u4E2D","flow.intent.viaRules":"\u5173\u952E\u8BCD\u89C4\u5219\u88C1\u51B3","flow.guard.unsafe":"\u5224\u5B9A\u4E0D\u5B89\u5168","flow.threat":"\u5A01\u80C1\u76D1\u63A7","flow.threat.calm":"\u672C\u8F6E\u7A97\u53E3\u65E0\u5F02\u5E38","flow.threat.escalated":"\u5A01\u80C1\u7B49\u7EA7\u5347\u7EA7","flow.threat.rate":"\u9891\u7387\u9650\u5236\u89E6\u53D1","flow.threat.blocked":"\u5A01\u80C1\u8BF7\u6C42\u5DF2\u963B\u65AD","trace.title":"LLM \u8C03\u7528","trace.empty":"\u672C\u8F6E\u6CA1\u6709\u8BB0\u5F55\u5230 LLM \u8C03\u7528","trace.req":"\u8BF7\u6C42","trace.resp":"\u54CD\u5E94","trace.caller.guard":"\u5B89\u68C0","trace.caller.classifier":"\u5206\u7C7B\u5668","trace.caller.host":"\u5BBF\u4E3B\u5185\u90E8\u8C03\u7528","trace.caller.conversation":"\u4E3B\u5BF9\u8BDD","trace.lbl.messages":"\u6761\u6D88\u606F","trace.lbl.chars":"\u5B57\u7B26","trace.lbl.dropped":"\u5DF2\u4E22\u5F03","trace.lbl.toolCalls":"\u5DE5\u5177\u8C03\u7528","trace.lbl.tools":"\u5DE5\u5177","trace.body.loading":"\u62C9\u53D6\u6B63\u6587\u4E2D\u2026","trace.body.gone":"\u6B63\u6587\u5DF2\u4E0D\u5728\u5185\u5B58\uFF08\u53EA\u4FDD\u7559\u6700\u8FD1\u7684\u8C03\u7528\uFF09","trace.body.error":"\u53D6\u6B63\u6587\u5931\u8D25","trace.group.other":"\u5176\u4ED6\u8C03\u7528","unbound.title":"\u5C1A\u672A\u7ED1\u5B9A\u4F1A\u8BDD","unbound.hint":"\u8FD9\u4E00\u9875\u8FD8\u6CA1\u6709\u5C5E\u4E8E\u8FD9\u4E2A\u4F1A\u8BDD\u7684\u4E00\u8F6E \u2014\u2014 \u4E0B\u9762\u662F\u5168\u5C40\u4FE1\u53F7\uFF0C\u4E0D\u662F\u67D0\u4E00\u8F6E\u3002\u5F00\u59CB\u4E00\u8F6E\u5BF9\u8BDD\u540E\uFF0C\u8FD9\u91CC\u4F1A\u53D8\u6210\u8BE5\u4F1A\u8BDD\u7684\u8BB0\u5F55\u3002","unbound.globalTitle":"\u5168\u5C40\u4FE1\u53F7","unbound.empty":"\u6682\u65E0\u5168\u5C40\u4FE1\u53F7"},ye=e=>ee[e]??Z[e]??e;function ve(e){typeof e=="function"&&(ye=n=>{try{let o=e(n);return o===n?ee[n]??Z[n]??n:o}catch{return ee[n]??Z[n]??n}})}function t(e){return ye(e)}var te="dsh-edge-agent",ke={zh:ee,en:Z};var A=require("react");function Je(e,n){if(e===void 0||n===void 0)return"\u2014";let o=Math.max(0,Math.round((n-e)/1e3));if(o<60)return`${o}s`;let i=Math.floor(o/60);return i<60?`${i}m${o%60}s`:`${Math.floor(i/60)}h${i%60}m`}function Ve(e){if(e===void 0)return t("summary.noTokens");let n=e.input??0,o=e.output??0;return`${n} in / ${o} out`}function $e(e){let{summary:n}=e;return(0,A.createElement)("div",{class:"dsh-edge-summary"},(0,A.createElement)("span",null,t("summary.turns")," ",(0,A.createElement)("b",null,String(n.turns))),(0,A.createElement)("span",null,t("summary.tokens")," ",(0,A.createElement)("b",null,Ve(n.tokens))),(0,A.createElement)("span",null,t("summary.age")," ",(0,A.createElement)("b",null,Je(n.startedAt,n.lastSeenAt))))}var F=require("react");var m=(e,n)=>[...e].reverse().find(n),l=(e,n)=>e?.payload[n],xe=e=>typeof e.payload.rationale=="string"?e.payload.rationale:"",Q=e=>typeof e=="number"?`${(e/1e3).toFixed(1)}s`:"?",g=e=>typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"?String(e):"?",se=e=>typeof e=="number"?e:void 0,ne=e=>typeof e=="number"?`${(e*100).toFixed(0)}%`:"?";function Ke(e){let n=`flow.class.${e}`,o=t(n);return o===n?e:`${o}\uFF08${e}\uFF09`}function W(e,n=44){return e.length<=n?e:`${e.slice(0,n-1)}\u2026`}function K(e){return Array.isArray(e)?e.filter(n=>typeof n=="string"):[]}function Qe(e){return e.length>0?e:t("flow.intent.byUnknown")}function He(e){let n=m(e,a=>a.kind==="guard.model-detect.end"),o=m(e,a=>a.kind==="guard.model-detect.unsafe"),i=m(e,a=>/^guard\.model-detect\.(error|timeout|provider_error)$/.test(a.kind)),s=m(e,a=>/^guard\.model-detect\.skip/.test(a.kind)),r=m(e,a=>a.kind==="guard.model-detect.start"),u=m(e,a=>a.kind==="input.injection.warned"||a.kind==="input.injection");if(u!==void 0&&o===void 0&&n===void 0){let a=K(l(u,"patterns")),p=K(l(u,"patternSources")),d=[];return a.length>0&&d.push(`${t("flow.lbl.hit")} ${a.join(", ")}`),p.length>0&&d.push(`${t("flow.lbl.regex")} ${W(p[0],40)}`),d.length===0&&d.push(t("flow.g.guardrule")),{label:t("flow.guard"),tone:"warn",detail:t("flow.guard.injection"),sub:d}}if(i!==void 0&&(n===void 0||i.ts>n.ts))return{label:t("flow.guard"),tone:"warn",detail:t("flow.guard.failopen"),sub:[`${t("flow.lbl.cause")} ${g(l(i,"reason"))} \xB7 ${Q(l(i,"durationMs"))}`,t("flow.g.regexOn")]};if(o!==void 0){let a=K(l(o,"threats")),p=[];a.length>0&&p.push(`${t("flow.lbl.hit")} ${a.join(", ")}`);let d=l(o,"rationale");return typeof d=="string"&&d.length>0&&p.push(`${t("flow.lbl.why")} ${W(d,40)}`),p.push(`${t("flow.lbl.model")} ${g(l(o,"provider"))}/${g(l(o,"model"))} \xB7 ${Q(l(o,"durationMs"))}`),{label:t("flow.guard"),tone:"stop",detail:`${t("flow.guard.unsafe")} \xB7 ${g(l(o,"dataClass"))}`,sub:p}}if(n!==void 0){let a=typeof n.payload.dataClass=="string"?n.payload.dataClass:"?",p=[`${t("flow.lbl.model")} ${g(l(n,"modelProvider")??l(n,"provider"))}/${g(l(n,"model"))}`,`${t("flow.lbl.elapsed")} ${Q(l(n,"durationMs"))} \xB7 ${t("flow.lbl.scanned")} ${g(l(n,"textLen"))} ${t("flow.lbl.chars")}`],d=l(n,"rationale");if(typeof d=="string"&&d.length>0&&p.push(`${t("flow.lbl.why")} ${W(d,40)}`),u!==void 0){let y=K(l(u,"patterns"));y.length>0&&p.push(`${t("flow.lbl.hit")} ${y.join(", ")}`)}return{label:t("flow.guard"),tone:"ok",detail:a==="public"?t("flow.guard.public"):Ke(a),sub:p}}if(s!==void 0){let a=[],p=l(s,"reason");typeof p=="string"&&p.length>0&&a.push(`${t("flow.lbl.cause")} ${p}`);let d=l(s,"rationale");return typeof d=="string"&&d.length>0&&a.push(`${t("flow.lbl.why")} ${W(d,40)}`),{label:t("flow.guard"),tone:"ok",detail:t("flow.guard.skipped"),sub:a}}return r!==void 0?{label:t("flow.guard"),tone:"run",detail:t("flow.guard.running"),sub:[]}:{label:t("flow.guard"),tone:"wait",detail:t("flow.wait"),sub:[]}}function Xe(e){let n=m(e,a=>a.kind==="intent.classify.end"),o=m(e,a=>a.kind==="intent.classify.entity_override"),i=m(e,a=>a.kind==="intent.rules.rejected"),s=m(e,a=>a.kind==="intent.classify.start"),r=m(e,a=>a.kind==="intent.jev.response"),u=m(e,a=>a.kind==="input-guard.policy.route-applied");if(i!==void 0&&(n===void 0||i.ts>n.ts)){let a=[],p=l(i,"riskScore");typeof p=="number"&&a.push(`${t("flow.lbl.risk")} ${p.toFixed(2)}`);let d=l(i,"intent");return typeof d=="string"&&d.length>0&&a.push(`${t("flow.lbl.hit")} ${d}`),{label:t("flow.intent"),tone:"stop",detail:t("flow.intent.rejected"),sub:a}}if(n!==void 0){let a=g(l(n,"category")),p=ne(l(n,"confidence")),d=[`${t("flow.lbl.verdict")} ${a} \xB7 ${p} \xB7 ${g(l(n,"rationale"))}`];o!==void 0&&o.ts<=n.ts&&(d.push(`${t("flow.lbl.override")} ${g(l(o,"from"))} \u2192 ${g(l(o,"to"))} \xB7 ${t("flow.lbl.entity")} ${g(l(o,"entity"))}`),d.push(`${t("flow.lbl.llmSay")} ${g(l(o,"llmRationale"))} \xB7 ${ne(l(o,"llmConfidence"))} ${t("flow.lbl.overridden")}`));let y=m(e,P=>P.kind==="intent.classify.start"),c=l(n,"textLen")??l(y,"textLen"),v=l(n,"path"),$=typeof v=="string"?v:"",T=g(l(y,"classifier")),w=g(l(y,"modelProvider")??T),h=l(y,"classifierEndpoint"),b=l(y,"classifierIsLocal"),R=$.startsWith("jev-adopt")||$.startsWith("jev-reject"),x=$.startsWith("llm"),G=R?t("flow.intent.byJev"):x?t("flow.intent.byLlm"):$==="cache"?t("flow.intent.byCache"):$.startsWith("rules-")?t("flow.intent.byRules"):$==="gate-no-web-need"?t("flow.intent.byGate"):$==="device-command"?t("flow.intent.byDeviceCommand"):Qe($),M=g(l(y,"model")),N=x&&M!=="?"?` ${w}/${M}`:x?` ${w}`:"";if(d.push(`${t("flow.lbl.decidedBy")} ${G}${N}`),typeof h=="string"&&h.length>0){let P=b===!0?t("flow.lbl.onDevice"):t("flow.lbl.offDevice");d.push(`${t("flow.lbl.endpoint")} ${W(h,34)} \xB7 ${P}`)}d.push(`${t("flow.lbl.elapsed")} ${Q(l(n,"durationMs"))} \xB7 ${t("flow.lbl.scanned")} ${g(c)} ${t("flow.lbl.chars")}`);let I=l(n,"keyword");typeof I=="string"&&I.length>0&&d.push(`${t("flow.lbl.keyword")} ${W(I,30)}`);let D=l(n,"semantic");typeof D=="string"&&D.length>0&&d.push(`${t("flow.lbl.semantic")} ${W(D,40)}`),typeof v=="string"&&v.length>0&&!R&&!x&&$!=="cache"&&d.push(`${t("flow.lbl.path")} ${v}`);let O=l(n,"jevIntent"),f=l(n,"jevConfidence"),E=l(n,"jevRiskScore"),S=[];if(typeof O=="string"&&O.length>0&&S.push(`intent=${O}`),typeof f=="number"&&S.push(`confidence=${f.toFixed(2)}`),typeof E=="number"&&S.push(`riskScore=${E.toFixed(2)}`),S.length>0){let P=r!==void 0?g(l(r,"provider")):"?",oe=r!==void 0?g(l(r,"model")):"?";d.push(`${t("flow.lbl.jev")} ${P}/${oe} \xB7 ${S.join(" \xB7 ")}`)}let C=xe(n).startsWith("default:"),j=xe(n)==="no-web-need";if(C){let P=m(e,oe=>/^intent\.(classify\.llm_error|llm\.(timeout|error|provider_error))$/u.test(oe.kind));P!==void 0?d.push(`${t("flow.lbl.cause")} ${g(l(P,"error")??l(P,"reason"))} \u2192 ${g(P.kind)}`):d.push(t("flow.intent.defaultNoCause"))}j&&d.push(t("flow.intent.noWebNeedWhy"));let _=C?t("flow.intent.viaDefault"):o!==void 0&&o.ts<=n.ts?t("flow.intent.viaEntity"):R?t("flow.intent.viaJev"):x?t("flow.intent.viaLlm"):$==="cache"?t("flow.intent.viaCache"):$.startsWith("rules-")?t("flow.intent.viaRules"):$==="device-command"?t("flow.intent.viaDeviceCommand"):t("flow.intent.viaLlm");return{label:t("flow.intent"),tone:C?"warn":"ok",detail:j?`${a} ${p} \xB7 ${t("flow.intent.noWebNeed")}`:`${a} ${p} \xB7 ${_}`,sub:d}}if(u!==void 0){let a=g(l(u,"policyRealm")),p=ne(l(u,"policyConfidence")),d=g(l(u,"policyPattern")),y=g(l(u,"policyRationale")),c=[];return d!=="?"&&c.push(`${t("flow.lbl.rule")} ${W(d)}`),y!=="?"&&c.push(`${t("flow.lbl.reason")} ${y}`),c.push(`${t("flow.lbl.confidence")} ${p}`),{label:t("flow.intent"),tone:"ok",detail:`${a} \xB7 ${t("flow.intent.viaPolicy")}`,sub:c}}return s!==void 0?{label:t("flow.intent"),tone:"run",detail:t("flow.running"),sub:[]}:{label:t("flow.intent"),tone:"wait",detail:t("flow.wait"),sub:[]}}function Ye(e,n){let o=m(e,r=>r.kind==="sanitizer.sanitized"||r.kind==="input-guard.sanitized"||r.kind==="guard.rule.sanitized"),i=m(e,r=>/^input-guard\.sanitize\.(downgraded|failed)$/.test(r.kind)),s=m(e,r=>r.kind==="sanitizer.desanitized");if(i!==void 0)return{label:t("flow.sanitize"),tone:"warn",detail:t("flow.sanitize.failed"),sub:[`${t("flow.lbl.cause")} ${g(l(i,"reason"))??"-"}`]};if(o!==void 0){let r=typeof o.payload.count=="number"?o.payload.count:typeof o.payload.replacementCount=="number"?o.payload.replacementCount:typeof o.payload.replacements=="number"?o.payload.replacements:void 0,u=[typeof r=="number"?`${t("flow.sanitize.hits")} ${r} ${t("flow.sanitize.unit")}`:t("flow.sanitize.done")],a=K(l(o,"piiTypes"));a.length>0&&u.push(`${t("flow.lbl.hit")} ${a.join(", ")}`);let p=K(l(o,"placeholders"));return p.length>0&&u.push(`${t("flow.lbl.ph")} ${p.join(", ")}`),s!==void 0&&u.push(t("flow.s.desanitized")),{label:t("flow.sanitize"),tone:"ok",detail:t("flow.s.done"),sub:u}}return n==="LOCAL"?{label:t("flow.sanitize"),tone:"ok",detail:t("flow.sanitize.localSkip"),sub:[t("flow.s.localWhy")]}:n!==void 0?{label:t("flow.sanitize"),tone:"ok",detail:t("flow.sanitize.clean"),sub:[t("flow.s.cleanWhy")]}:{label:t("flow.sanitize"),tone:"wait",detail:t("flow.wait"),sub:[]}}function Ze(e){let n=m(e,r=>r.kind==="input-guard.routed"),o=m(e,r=>r.kind==="input-guard.intent.local"),i=m(e,r=>/^input-guard\.blocked\./.test(r.kind)),s=m(e,r=>/route-missing/.test(r.kind));if(i!==void 0){let r=i.kind.replace("input-guard.blocked.",""),u=g(l(i,"reason")),a=g(l(i,"rationale")),p=g(l(i,"riskLevel")),d=u!=="?"?u:a!=="?"?a:"?",y=[`${t("flow.lbl.cause")} ${d}`],c=[p!=="?"?`${t("flow.lbl.risk")} ${p}`:null,se(l(i,"confidence"))!==void 0?`${t("flow.lbl.confidence")} ${ne(l(i,"confidence"))}`:null].filter(v=>v!==null);return c.length>0&&y.push(c.join(" \xB7 ")),{label:t("flow.route"),tone:"stop",detail:`${t("flow.route.blocked")} \xB7 ${r}`,sub:y}}if(s!==void 0)return{label:t("flow.route"),tone:"warn",detail:t("flow.route.fallback"),sub:[`${t("flow.lbl.cause")} ${g(l(s,"reason"))}`]};if(n!==void 0){let r=g(l(n,"category")),u=[];if(o!==void 0){let a=g(l(o,"provider")),p=g(l(o,"model"));(a!=="?"||p!=="?")&&u.push(`${t("flow.lbl.route")} ${a}/${p}`)}return u.push(`${t("flow.lbl.entry")} ${g(l(n,"routeSource"))} \xB7 ${t("flow.lbl.pool")} ${n.payload.edgeRouteUsed===!0?t("flow.lbl.used"):t("flow.lbl.hostOwn")}`),{label:t("flow.route"),tone:"ok",detail:`${r} \xB7 ${t("flow.route.kept")}`,sub:u}}return et(e)?{label:t("flow.route"),tone:"run",detail:t("flow.running"),sub:[]}:{label:t("flow.route"),tone:"wait",detail:t("flow.wait"),sub:[]}}var et=e=>e.some(n=>n.kind.startsWith("intent.classify."));function tt(e){let n=m(e,r=>r.kind==="td-bus.escalated"),o=m(e,r=>r.kind==="input.rate-limit"||r.kind==="input.global-rate-limit"),i=m(e,r=>r.kind==="http.chat.threat-blocked");if(i!==void 0)return{label:t("flow.threat"),tone:"stop",detail:t("flow.threat.blocked"),sub:[`${t("flow.lbl.cause")} ${g(l(i,"reason"))??"-"}`]};if(n!==void 0)return{label:t("flow.threat"),tone:"warn",detail:t("flow.threat.escalated"),sub:[`${g(l(n,"from"))} \u2192 ${g(l(n,"to"))} \xB7 ${g(l(n,"count"))}/${g(l(n,"threshold"))}`]};if(o!==void 0){let r=o.kind==="input.global-rate-limit";return{label:t("flow.threat"),tone:"warn",detail:t("flow.threat.rate"),sub:[`${t("flow.lbl.scope")} ${r?t("flow.lbl.global"):t("flow.lbl.session")}`]}}let s=e.filter(r=>r.kind.startsWith("guard.")||r.kind.startsWith("input.")||r.kind.startsWith("td-bus.")).length;return{label:t("flow.threat"),tone:"ok",detail:t("flow.threat.calm"),sub:[`${t("flow.lbl.watched")} ${s}`]}}function nt(e,n){let o=f=>{let E=l(f,"internal");if(E!=null)return!1;let S=l(f,"tools");return!(typeof S=="number"&&S===0)},i=f=>f.kind==="llm.local.end"||f.kind==="llm.cloud.end",s=f=>f.kind==="llm.local.start"||f.kind==="llm.cloud.start",r=f=>/^llm\.(local|cloud)\.delegate\.end$/.test(f.kind),u=f=>/^llm\.(local|cloud)\.delegate\.resolved$/.test(f.kind),a=f=>{let E=g(l(f,"from"));if(E!=="?")return{pool:E,provider:g(l(f,"toProvider")),model:g(l(f,"toModel"))};let S=g(l(f,"provider"));return{pool:S,provider:S,model:g(l(f,"model")??l(f,"route"))}},p=m(e,f=>f.kind==="llm.host.route"),d=m(e,f=>(i(f)||r(f))&&o(f)),y=m(e,f=>(s(f)||u(f))&&o(f)),c=m(e,f=>/^llm\.(local|cloud)\.(http_error|network_error|sse_interrupted)$/.test(f.kind)&&o(f));if(y!==void 0&&(d===void 0||y.ts>d.ts)&&(c===void 0||c.ts<y.ts)&&y!==void 0){let{provider:f,model:E}=a(y),S=[`${t("flow.lbl.route")} ${f}/${E}`],C=[],j=l(y,"messageCount");typeof j=="number"&&C.push(`messageCount=${j}`);let _=l(y,"promptLen");return typeof _=="number"&&C.push(`promptLen=${_}`),C.length>0&&S.push(`${t("flow.lbl.raw")} ${C.join(" \xB7 ")}`),{label:t("flow.answer"),tone:"run",detail:t("flow.answer.running"),sub:S}}if(c!==void 0&&(d===void 0||c.ts>d.ts)){let f=g(l(c,"provider")),E=g(l(c,"model")??l(c,"route")),S=l(c,"status"),C=l(c,"error"),j=typeof S=="number"?`status=${S}`:typeof C=="string"&&C.length>0&&C!=="[object Object]"?C:c.kind;return{label:t("flow.answer"),tone:"warn",detail:t("flow.answer.failed"),sub:[`${t("flow.lbl.route")} ${f}/${E}`,`${t("flow.lbl.cause")} ${j} \xB7 ${t("flow.lbl.elapsed")} ${Q(l(c,"durationMs"))}`]}}let $=m(e,f=>f.kind==="input-guard.reroute.local"),T=$!==void 0?l($,"from"):void 0,w=$!==void 0?l($,"to"):void 0,h=d!==void 0?{...a(d),carried:!1}:p!==void 0?{pool:g(l(p,"provider")),provider:g(l(p,"provider")),model:g(l(p,"model")),carried:!1}:w!==void 0&&g(w.provider)!=="?"?{pool:g(w.provider),provider:g(w.provider),model:g(w.model),carried:!1}:n.lastRoute!==void 0?{pool:n.lastRoute.provider,provider:n.lastRoute.provider,model:n.lastRoute.model,carried:!0}:void 0;if(h===void 0)return{label:t("flow.answer"),tone:"wait",detail:t("flow.answer.pending"),sub:[]};let{pool:b,provider:R,model:x,carried:G}=h,M=b.startsWith("local-llm"),N=e.filter(f=>(f.kind==="llm.local.end"||f.kind==="llm.local.delegate.end")&&o(f)),I=[`${t("flow.lbl.route")} ${b}/${x}${G?` \xB7 ${t("flow.answer.carried")}`:""}`,M?t("flow.a.localKeep"):t("flow.a.cloudSend")];R!=="?"&&R!==b&&I.push(`${t("flow.lbl.endpoint")} ${R}/${x}`);{let f=g(T?.provider),E=g(w?.provider);f!=="?"&&E!=="?"&&I.push(`${t("flow.lbl.rerouted")} ${f}/${g(T?.model)} \u2192 ${E}/${g(w?.model)}`)}if(M&&N.length>0){let f=N.reduce((_,P)=>_+(typeof P.payload.durationMs=="number"?P.payload.durationMs:0),0),E=N.at(-1),S=r(E),C=se(S?l(m(e,_=>u(_)&&o(_)),"messageCount"):l(E,"promptLen")),j=C===void 0?"":` \xB7 ${t("flow.lbl.context")} ${C} ${S?t("flow.lbl.msgs"):t("flow.lbl.chars")}`;I.push(`${t("flow.lbl.steps")} \xD7${N.length} \xB7 ${t("flow.lbl.total")} ${Q(f)}${j}`)}let D=d??p;if(D!==void 0){let f=[],E=l(D,"route");typeof E=="string"&&E.length>0&&E!==x&&f.push(`route=${E}`);let S=l(D,"durationMs");typeof S=="number"&&f.push(`durationMs=${S}`);let C=l(D,"promptLen");typeof C=="number"&&f.push(`promptLen=${C}`);let j=l(D,"resultLen");typeof j=="number"&&f.push(`resultLen=${j}`),f.length>0&&I.push(`${t("flow.lbl.raw")} ${f.join(" \xB7 ")}`)}let O=n.tokens;return O!==void 0&&(O.input!==void 0||O.output!==void 0)&&I.push(`token ${O.input??0} ${t("flow.lbl.in")} / ${O.output??0} ${t("flow.lbl.out")}`),{label:t("flow.answer"),tone:M?"ok":"info",detail:M?`${t("flow.answer.local")} \xB7 ${x}`:`${t("flow.answer.cloud")} ${R}/${x}`,sub:I}}var ot="\u2502";function Re(e){let{rows:n,summary:o}=e,i=m(n,p=>p.kind==="intent.classify.end"),s=m(n,p=>p.kind==="input-guard.policy.route-applied"),r=i!==void 0?String(i.payload.category??""):s!==void 0?String(s.payload.policyRealm??""):void 0,u=[He(n),Xe(n),Ye(n,r),Ze(n),nt(n,o),tt(n)],a=u.flatMap((p,d)=>[(0,F.createElement)("div",{key:`n${d}`,class:`dsh-edge-flow-node dsh-edge-flow-node--${p.tone}`},(0,F.createElement)("div",{class:"dsh-edge-flow-head"},(0,F.createElement)("span",{class:"dsh-edge-flow-dot"}),(0,F.createElement)("span",{class:"dsh-edge-flow-label"},p.label)),(0,F.createElement)("div",{class:"dsh-edge-flow-detail"},p.detail),p.sub.length>0?(0,F.createElement)("div",{class:"dsh-edge-flow-sub"},...p.sub.map((y,c)=>(0,F.createElement)("div",{key:c},y))):null),...d<u.length-1?[(0,F.createElement)("div",{key:`a${d}`,class:"dsh-edge-flow-arrow"},ot)]:[]]);return(0,F.createElement)("div",{class:"dsh-edge-flow"},...a)}var k=require("react");var rt=["guard","intent","route","host","other"];function lt(e){return e.caller==="prompt-guard"?"guard":e.caller==="intent-classifier"?"intent":typeof e.caller=="string"&&e.caller.length>0?"other":e.toolCount===0?"host":"route"}function it(e){switch(e){case"guard":return t("flow.guard");case"intent":return t("flow.intent");case"route":return t("flow.route");case"host":return t("trace.caller.host");case"other":return t("trace.group.other")}}var Ee=e=>typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"?String(e):"?",st=e=>typeof e=="number"?e:void 0;function at(e){if(e.kind!=="llm.trace.index")return;let n=e.payload??{},o=typeof n.traceId=="string"?n.traceId:"";if(o.length===0)return;let i=n.kind==="RESP"?"RESP":"REQ",s={traceId:o,kind:i,provider:Ee(n.provider),model:Ee(n.model)};typeof n.caller=="string"&&(s.caller=n.caller);for(let r of["messageCount","droppedMessages","promptLength","contentLength","toolCallCount","toolCount","durationMs","bodyBytes"]){let u=st(n[r]);u!==void 0&&(s[r]=u)}for(let r of["finishReason","error","baseUrl","callId"])typeof n[r]=="string"&&(s[r]=n[r]);return s}function dt(e){let n=new Map;for(let o of e){let i=o.callId!==void 0&&o.callId.length>0?o.callId:`solo:${o.traceId}`,s=n.get(i);s===void 0&&(s={key:i,group:lt(o)},n.set(i,s)),o.kind==="REQ"?s.req=o:s.resp=o}return[...n.values()]}function ct(e){return e.caller==="prompt-guard"?t("trace.caller.guard"):e.caller==="intent-classifier"?t("trace.caller.classifier"):typeof e.caller=="string"&&e.caller.length>0?e.caller:e.toolCount===0?t("trace.caller.host"):t("trace.caller.conversation")}function ut(e){return e===void 0?"":e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/1024/1024).toFixed(1)} MB`}function ft(e){let n=[];return e.kind==="REQ"?(e.messageCount!==void 0&&n.push(`${e.messageCount} ${t("trace.lbl.messages")}`),e.promptLength!==void 0&&n.push(`${e.promptLength} ${t("trace.lbl.chars")}`),e.droppedMessages!==void 0&&e.droppedMessages>0&&n.push(`${t("trace.lbl.dropped")} ${e.droppedMessages}`)):(e.contentLength!==void 0&&n.push(`${e.contentLength} ${t("trace.lbl.chars")}`),e.toolCallCount!==void 0&&n.push(`${t("trace.lbl.toolCalls")} ${e.toolCallCount}`),e.durationMs!==void 0&&n.push(`${t("flow.lbl.elapsed")} ${(e.durationMs/1e3).toFixed(1)}s`)),n.join(" \xB7 ")}function Se(e){let{rows:n}=e,[o,i]=(0,k.useState)(void 0),[s,r]=(0,k.useState)(void 0),u=[];for(let c of n){let v=at(c);v!==void 0&&u.push(v)}u.reverse(),(0,k.useEffect)(()=>{if(o===void 0){r(void 0);return}let c=!1;return r({id:o}),be(o).then(v=>{c||r(v.ok?{id:o,text:v.text}:{id:o,error:v.error})}),()=>{c=!0}},[o]);let a=(0,k.createElement)("div",{class:"dsh-edge-flow-head"},(0,k.createElement)("span",{class:"dsh-edge-flow-dot"}),(0,k.createElement)("span",{class:"dsh-edge-flow-label"},t("trace.title")),(0,k.createElement)("span",{class:"dsh-edge-trace-count"},`${u.length}`));if(u.length===0)return(0,k.createElement)("div",{class:"dsh-edge-panel dsh-edge-trace"},a,(0,k.createElement)("div",{class:"dsh-edge-empty"},t("trace.empty")));let p=new Map;for(let c of dt(u)){let v=p.get(c.group);v===void 0?p.set(c.group,[c]):v.push(c)}let d=c=>{let v=o===c.traceId,$=s?.id===c.traceId?s:void 0,T=[];c.baseUrl!==void 0&&c.baseUrl.length>0&&T.push(c.baseUrl),c.toolCount!==void 0&&c.toolCount>0&&T.push(`${t("trace.lbl.tools")} ${c.toolCount}`),c.finishReason!==void 0&&c.finishReason.length>0&&T.push(c.finishReason),c.error!==void 0&&c.error.length>0&&T.push(`${t("flow.lbl.cause")} ${c.error}`);let w=ut(c.bodyBytes);return w.length>0&&T.push(w),(0,k.createElement)("div",{class:`dsh-edge-trace-half dsh-edge-trace-half--${c.kind.toLowerCase()}`},(0,k.createElement)("button",{class:"dsh-edge-trace-head",type:"button",onClick:()=>i(v?void 0:c.traceId)},(0,k.createElement)("span",{class:`dsh-edge-trace-badge dsh-edge-trace-badge--${c.kind.toLowerCase()}`},c.kind==="REQ"?t("trace.req"):t("trace.resp")),(0,k.createElement)("span",{class:"dsh-edge-trace-model"},`${c.provider}/${c.model}`),(0,k.createElement)("span",{class:`dsh-edge-trace-caller${c.caller===void 0&&c.toolCount!==0?" dsh-edge-trace-caller--main":""}`},ct(c))),(0,k.createElement)("div",{class:"dsh-edge-trace-sum"},ft(c)),T.length>0?(0,k.createElement)("div",{class:"dsh-edge-trace-meta"},T.join(" \xB7 ")):null,v?(0,k.createElement)("div",{class:"dsh-edge-trace-body"},$===void 0?(0,k.createElement)("div",{class:"dsh-edge-empty"},t("trace.body.loading")):$.error!==void 0?(0,k.createElement)("div",{class:"dsh-edge-trace-body-err"},$.error==="trace-not-found"?t("trace.body.gone"):`${t("trace.body.error")} \xB7 ${$.error}`):(0,k.createElement)("pre",{class:"dsh-edge-trace-pre"},$.text??"")):null)},y=[];for(let c of rt){let v=p.get(c);if(v===void 0||v.length===0)continue;let $=v.map(T=>{let w=[];return T.req!==void 0&&w.push(d(T.req)),T.resp!==void 0&&w.push(d(T.resp)),(0,k.createElement)("div",{key:T.key,class:"dsh-edge-trace-pair"},...w)});y.push((0,k.createElement)("div",{key:c,class:"dsh-edge-trace-group"},(0,k.createElement)("div",{class:"dsh-edge-trace-group-head"},(0,k.createElement)("span",{class:"dsh-edge-trace-group-name"},it(c)),(0,k.createElement)("span",{class:"dsh-edge-trace-count"},`${v.length}`)),(0,k.createElement)("div",{class:"dsh-edge-trace-list"},...$)))}return(0,k.createElement)("div",{class:"dsh-edge-panel dsh-edge-trace"},a,...y)}var z=require("react");var B=require("react");function pt(e){let n=new Date(e),o=(i,s=2)=>String(i).padStart(s,"0");return`${o(n.getHours())}:${o(n.getMinutes())}:${o(n.getSeconds())}`}function gt(e){let n=e.indexOf(".");return n>0?e.slice(n+1):e}var wt={intent:["category","keyword","semantic","targetRealm","confidence","rationale","classifier","textLen"],route:["provider","model","toProvider","toModel","resolved","baseUrl","status","durationMs","promptLen"],interception:["reason","realm","targetRealm","rule","count","confidence","rationale","category","edgeRouteUsed","routeSource","dataClass","provider","model","textLen","durationMs"],threat:["from","to","count","threshold","reason"]},bt=24,ht={semantic:60};function mt(e,n){let o=wt[n]??[],i=[];for(let s of o){let r=e.payload[s];if(typeof r=="number")i.push(`${s}=${Math.round(r*100)/100}`);else if(typeof r=="boolean")i.push(`${s}=${r}`);else if(typeof r=="string"&&r.length>0){let u=ht[s]??bt;i.push(`${s}=${r.length>u?`${r.slice(0,u-1)}\u2026`:r}`)}}return i.join(" ")}function yt(e){return e==="warn"?"warn":e==="error"||e==="security"?"security":""}function Te(e){let{rows:n,panel:o,empty:i}=e;if(n.length===0)return(0,B.createElement)("div",{class:"dsh-edge-empty"},i);let s=[...n].reverse();return(0,B.createElement)("div",{class:"dsh-edge-rows"},...s.map(r=>{let u=mt(r,o);return(0,B.createElement)("div",{class:`dsh-edge-row ${yt(r.level)}`,key:`${r.seq}`},(0,B.createElement)("div",{class:"dsh-edge-row-head"},(0,B.createElement)("span",{class:"ts"},pt(r.ts)),(0,B.createElement)("span",{class:"k"},gt(r.kind))),u.length>0?(0,B.createElement)("div",{class:"f"},u):null)}))}var ae="_global",vt=-1;function de(e){return e.turn===vt}function ce(e){return typeof e!="string"||e.length===0?!1:e!==ae}function Ce(e,n,o){return ce(e)?o>0?!1:!n.some(i=>!de(i)):!0}function kt(e){let n=[],o=new Map;for(let i of e){let s=typeof i.panel=="string"&&i.panel.length>0?i.panel:"other",r=o.get(s);r===void 0&&(r=[],o.set(s,r),n.push(s)),r.push(i)}return n.map(i=>({panel:i,rows:o.get(i)??[]}))}var $t={intent:"panel.intent",route:"panel.route",interception:"panel.interception",threat:"panel.threat"};function Le(e){let n=kt(e.rows);return(0,z.createElement)("div",{class:"dsh-edge-view"},(0,z.createElement)("div",{class:"dsh-edge-unbound"},(0,z.createElement)("b",null,t("unbound.title")),(0,z.createElement)("span",null,t("unbound.hint"))),n.length===0?(0,z.createElement)("div",{class:"dsh-edge-empty"},t("unbound.empty")):(0,z.createElement)("div",{class:"dsh-edge-groups"},...n.map(o=>(0,z.createElement)("div",{class:"dsh-edge-panel",key:o.panel},(0,z.createElement)("h4",null,t($t[o.panel]??"unbound.globalTitle")),(0,z.createElement)(Te,{rows:o.rows,panel:o.panel,empty:t("unbound.empty")})))),e.failing===!0?(0,z.createElement)("div",{class:"dsh-edge-stale"},t("row.stale")):null)}function Ie(e){let n=d=>d.at(-1),o=n(e.filter(d=>d.kind==="intent.classify.end")),i=n(e.filter(d=>d.kind==="input-guard.policy.route-applied")),s=n(e.filter(d=>d.kind==="input-guard.routed")),r=n(e.filter(d=>d.kind==="llm.host.route")),u=e.some(d=>d.kind==="sanitizer.sanitized"||d.kind==="guard.rule.sanitized"),a=o?.payload.category??i?.payload.policyRealm??s?.payload.category;return a===void 0&&r===void 0?{text:t("verdict.waiting"),tone:"wait"}:a==="LOCAL"||r!==void 0&&String(r.payload.provider??"").startsWith("local-llm")?{text:t("verdict.local"),tone:"local"}:{text:t("verdict.cloud")+(u?t("verdict.sanitized"):""),tone:"cloud"}}var xt="dsh-edge-agent-client",Rt=["slots","locale"],q="dsh-edge-agent",ue="edge",Et=5e3,Pe=[0,80,300,900,2500];function X(e,n){if(!(e===null||typeof e!="object"))try{return e[n]}catch{return}}function ze(e){if(e===null||typeof e!="object")return;if(typeof X(e,"list")=="function")return e;let n=[];n.push(X(e,"agentPresets"));let o=X(e,"remote");o!==void 0&&n.push(X(o,"agentPresets"));for(let i of n)if(i!=null&&typeof X(i,"list")=="function")return i}function St(e){try{let n=e.remote;return ze(n)}catch{return}}function Me(e){let o=ce(e.sessionId)?e.sessionId:ae,[,i]=(0,L.useState)(0);(0,L.useEffect)(()=>(me(),V.attach(o,()=>i(a=>a+1))),[o]);let s=V.summaryFor(o),r=V.currentRows(o,s.turns,s.turnStartTs);if(Ce(e.sessionId,r,s.turns))return(0,L.createElement)(Le,{rows:r.filter(de),failing:V.failing(o)});let u=Ie(r);return(0,L.createElement)("div",{class:"dsh-edge-view"},(0,L.createElement)($e,{summary:s}),(0,L.createElement)("div",{class:`dsh-edge-verdict dsh-edge-verdict--${u.tone}`},u.text),(0,L.createElement)(Re,{rows:r,summary:s}),(0,L.createElement)(Se,{rows:r}),V.failing(o)?(0,L.createElement)("div",{class:"dsh-edge-stale"},t("row.stale")):null)}function J(e,n){let o=n instanceof Error?n.message:String(n);console.error(`[dsh-edge-agent] ${e} failed: ${o}`)}function Tt(e){e.inject(["locale"],w=>{let b=w.locale;if(!(b===void 0||typeof b.register!="function"||typeof b.bind!="function"))try{b.register(te,ke),ve(b.bind(te))}catch(R){J("locale registration",R)}});let n=!1,o,i=!0,s=!1,r=new Set,u,a,p=w=>{if(!(u===void 0||typeof u.tabsIn!="function"))try{return u.tabsIn(w).find(h=>h.kind===q)}catch(h){J("edge tab lookup",h);return}},d=w=>{let h;try{h=e.get?.("sessions")}catch{return}let b=h;if(!(b===void 0||typeof b.list?.getSnapshot!="function"))try{let x=b.list.getSnapshot()?.byId?.[w]?.projectionValues?.agentPreset;return typeof x=="string"?x:void 0}catch(R){J("session preset lookup",R);return}},y=w=>{let h=d(w);return h!==void 0?h===ue:s},c=(w,h)=>{let b=setTimeout(()=>{if(a=void 0,!(!n||u===void 0)&&u.mounted?.getSnapshot()===w&&!(!i||!y(w))){if(p(w)!==void 0){r.add(w);return}try{u.openTab(q),r.add(w)}catch(R){let x=h+1;if(x>=Pe.length){J("edge tab auto-open",R);return}c(w,x)}}},Pe[h]);a={sessionId:w,attempt:h,timer:b}},v=()=>{if(!n||u===void 0)return;let w=u.mounted?.getSnapshot();if(!(typeof w!="string"||w==="")&&!r.has(w)&&!(!i||!y(w))){if(a!==void 0){if(a.sessionId===w)return;clearTimeout(a.timer),a=void 0}c(w,0)}},$=()=>{if(u!==void 0)return;let w;try{w=e.get?.("sidebarRight")}catch{return}let h=w;if(h===void 0||typeof h.openTab!="function")return;u=h;let b=h.mounted;b!==void 0&&typeof b.subscribe=="function"&&b.subscribe(()=>{v()}),v()},T=()=>{o===void 0&&e.inject(["sidebarRightTabs"],w=>{if(o!==void 0)return;let b=w.sidebarRightTabs;if(!(b===void 0||typeof b.register!="function")){try{o=b.register({id:q,kind:q,title:()=>t("tab.title"),guide:[{id:`${q}-guide`,order:30,title:()=>t("tab.title"),description:()=>t("guide.description")}]}),n=!0}catch(R){J("sidebar tab type registration",R)}v()}})};e.inject(["remote","remote.agentPresets"],w=>{let h=ze(w)??St(e);if(h===void 0||typeof h.list!="function")return;let b=async()=>{try{$();let x=await h.list();if(!x.ok)return;let G=x.value?.presets;if(!Array.isArray(G))return;let M=G.find(I=>I.id===ue),N=G.find(I=>I.isDefault===!0);i=M!==void 0&&M.broken===void 0,s=N?.id===ue,v()}catch(x){J("preset roster read",x)}};b();let R=setInterval(()=>{b()},Et);e.effect?.(()=>()=>{clearInterval(R);let x=o;o=void 0,n=!1,typeof x=="function"&&x()},"dsh-edge-agent: preset roster watcher")}),T(),e.inject(["slots"],w=>{let b=w.slots;if(!(b===void 0||typeof b.register!="function"||typeof b.inject!="function"))try{b.inject("sidebar.right.pane.tab",()=>b.register({name:"sidebar.right.pane.tab",key:q,locale:te},R=>(0,L.createElement)(Me,{...R}))),b.inject("sidebar.right.pane.tab.title",()=>b.register({name:"sidebar.right.pane.tab.title",key:q},()=>(0,L.createElement)("span",{className:"dsh-edge-tab-title"},t("tab.title"))))}catch(R){J("sidebar tab body registration",R)}})}function Ct(e,n){let o=(0,je.createRoot)(n);return o.render(e),()=>o.unmount()}
|
|
84
|
+
})();
|
|
85
|
+
return module.exports;
|
|
86
|
+
},
|
|
87
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud-llm-adapter.d.ts","sourceRoot":"","sources":["../src/cloud-llm-adapter.ts"],"names":[],"mappings":"AACA,cAAc,oCAAoC,CAAA"}
|