shennian 0.3.86 → 0.3.88
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/bin/shennian.js +1 -1
- package/dist/publish-build-manifest.json +32 -27
- package/dist/src/agents/adapter.js +1 -19
- package/dist/src/agents/claude-managed-permissions.js +1 -248
- package/dist/src/agents/claude.js +8 -393
- package/dist/src/agents/codex-managed-permissions.js +1 -294
- package/dist/src/agents/codex-managed-room-tools.js +1 -249
- package/dist/src/agents/codex-utils.js +7 -200
- package/dist/src/agents/codex.d.ts +7 -1
- package/dist/src/agents/codex.js +17 -1352
- package/dist/src/agents/config-status.js +1 -226
- package/dist/src/agents/cursor-managed-permissions.js +2 -299
- package/dist/src/agents/cursor.js +1 -314
- package/dist/src/agents/custom.js +4 -418
- package/dist/src/agents/external-channel-instructions.js +11 -94
- package/dist/src/agents/gemini.js +1 -180
- package/dist/src/agents/manager.js +18 -250
- package/dist/src/agents/model-registry/cache.js +1 -37
- package/dist/src/agents/model-registry/discovery.js +2 -188
- package/dist/src/agents/model-registry/parsers.js +4 -521
- package/dist/src/agents/model-registry/runner.js +1 -30
- package/dist/src/agents/model-registry/service.js +1 -115
- package/dist/src/agents/model-registry/types.js +1 -8
- package/dist/src/agents/model-registry.js +1 -19
- package/dist/src/agents/native-capabilities.js +1 -237
- package/dist/src/agents/openclaw.js +2 -293
- package/dist/src/agents/opencode-managed-permissions.js +2 -187
- package/dist/src/agents/opencode.js +1 -298
- package/dist/src/agents/platform-instructions.js +17 -46
- package/dist/src/agents/runtime-compatibility.js +1 -44
- package/dist/src/agents/workbuddy-managed-permissions.js +2 -329
- package/dist/src/agents/workbuddy.js +3 -444
- package/dist/src/commands/logout.d.ts +3 -0
- package/dist/src/commands/logout.js +1 -0
- package/dist/src/daemon-ipc/paths.js +1 -1
- package/dist/src/fs/boundary.js +1 -185
- package/dist/src/fs/handler.js +1 -130
- package/dist/src/fs/security.js +1 -32
- package/dist/src/fs/text-decoder.js +1 -110
- package/dist/src/index.js +3 -587
- package/dist/src/manager/prompt.js +29 -34
- package/dist/src/manager/registry.js +1 -317
- package/dist/src/manager/retired-external-channel-compat.js +1 -40
- package/dist/src/manager/runtime.js +23 -1514
- package/dist/src/native-fusion/codex-parser.d.ts +3 -1
- package/dist/src/native-fusion/codex-parser.js +4 -660
- package/dist/src/native-fusion/codex-user-input.js +5 -102
- package/dist/src/native-fusion/config.js +1 -5
- package/dist/src/native-fusion/file-watcher.js +1 -191
- package/dist/src/native-fusion/local-repository.js +2 -569
- package/dist/src/native-fusion/opencode-parser.js +3 -130
- package/dist/src/native-fusion/parser-common.d.ts +6 -1
- package/dist/src/native-fusion/parser-common.js +4 -4
- package/dist/src/native-fusion/parsers.d.ts +4 -2
- package/dist/src/native-fusion/parsers.js +3 -140
- package/dist/src/native-fusion/service.js +2 -739
- package/dist/src/native-fusion/session-header.js +2 -101
- package/dist/src/native-fusion/state.js +2 -104
- package/dist/src/native-fusion/types.js +1 -1
- package/dist/src/personal-sync/machine-authority.js +1 -34
- package/dist/src/room/activation-audit.js +2 -45
- package/dist/src/room/activation-policy.js +1 -30
- package/dist/src/room/activation-service.js +8 -408
- package/dist/src/room/invite-bootstrap.js +1 -156
- package/dist/src/room/managed-prompt-composer.d.ts +1 -1
- package/dist/src/room/managed-prompt-composer.js +17 -16
- package/dist/src/room/managed-room-binding.js +1 -167
- package/dist/src/room/managed-room-ipc.d.ts +4 -0
- package/dist/src/room/managed-room-ipc.js +2 -2
- package/dist/src/room/mirror-sync-service.d.ts +1 -0
- package/dist/src/room/mirror-sync-service.js +1 -183
- package/dist/src/room/room-binding-client.js +1 -151
- package/dist/src/session/archive-zip.js +1 -220
- package/dist/src/session/deletion-sync-state.js +2 -136
- package/dist/src/session/handlers/agent-capabilities.js +1 -14
- package/dist/src/session/handlers/agent-config.js +1 -150
- package/dist/src/session/handlers/agents.js +1 -55
- package/dist/src/session/handlers/chat.js +2 -1030
- package/dist/src/session/handlers/control.js +1 -61
- package/dist/src/session/handlers/fs.js +1 -594
- package/dist/src/session/handlers/message-status.js +1 -15
- package/dist/src/session/handlers/remote-access.js +1 -43
- package/dist/src/session/handlers/room-managed.js +1 -101
- package/dist/src/session/handlers/session-refresh.js +1 -35
- package/dist/src/session/handlers/title.js +1 -79
- package/dist/src/session/handlers/tool-detail.js +1 -149
- package/dist/src/session/handlers/voice-window.js +1 -62
- package/dist/src/session/history-subscriptions.js +1 -470
- package/dist/src/session/manager.d.ts +1 -0
- package/dist/src/session/manager.js +1 -658
- package/dist/src/session/native-cleanup-outbox.js +2 -287
- package/dist/src/session/native-session-lifecycle.js +6 -327
- package/dist/src/session/queue.d.ts +8 -0
- package/dist/src/session/queue.js +6 -6
- package/dist/src/upgrade/scheduler.js +1 -126
- package/node_modules/@shennian/wire/dist/agent-workspace.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
| `shennian pair --browser` | 浏览器授权配对;打不开时会保留 URL |
|
|
20
20
|
| `shennian pair --token` | 使用现有二维码 / Token 配对,适合 SSH / headless |
|
|
21
21
|
| `shennian start` | 启动后台服务 |
|
|
22
|
-
| `shennian stop` |
|
|
22
|
+
| `shennian stop` | 停止后台服务,保留登录 |
|
|
23
|
+
| `shennian logout` | 停止服务并清除本机神念登录与配对凭据,保留模型配置与历史 |
|
|
23
24
|
| `shennian status` | 查看后台服务状态 |
|
|
24
25
|
| `shennian logs -n 100` | 查看最近日志 |
|
|
25
26
|
| `shennian config` | 查看本地配置 |
|
|
@@ -28,7 +29,7 @@
|
|
|
28
29
|
| `shennian runtime add/list/remove` | 管理自定义 Agent Runtime |
|
|
29
30
|
| `shennian upgrade` | 升级 CLI |
|
|
30
31
|
|
|
31
|
-
`start`、`stop`、`status` 可选加 `--json`。`logs` 输出日志文本,不支持 `--json`。
|
|
32
|
+
`start`、`stop`、`status`、`logout` 可选加 `--json`。`logs` 输出日志文本,不支持 `--json`。
|
|
32
33
|
切换节点后运行 `shennian stop && shennian start` 让后台服务重新连接。
|
|
33
34
|
|
|
34
35
|
## 开发
|
package/dist/bin/shennian.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
2
|
+
import"../src/index.js";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"jsMinified": true,
|
|
4
4
|
"minifier": "esbuild",
|
|
5
|
-
"fileCount":
|
|
5
|
+
"fileCount": 145,
|
|
6
6
|
"files": [
|
|
7
7
|
{
|
|
8
8
|
"file": "bin/shennian.js",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"file": "src/agents/codex.js",
|
|
49
|
-
"beforeBytes":
|
|
50
|
-
"afterBytes":
|
|
49
|
+
"beforeBytes": 64672,
|
|
50
|
+
"afterBytes": 33374
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
"file": "src/agents/command-spec.js",
|
|
@@ -199,6 +199,11 @@
|
|
|
199
199
|
"beforeBytes": 827,
|
|
200
200
|
"afterBytes": 468
|
|
201
201
|
},
|
|
202
|
+
{
|
|
203
|
+
"file": "src/commands/logout.js",
|
|
204
|
+
"beforeBytes": 3040,
|
|
205
|
+
"afterBytes": 1558
|
|
206
|
+
},
|
|
202
207
|
{
|
|
203
208
|
"file": "src/commands/manager.js",
|
|
204
209
|
"beforeBytes": 6845,
|
|
@@ -261,8 +266,8 @@
|
|
|
261
266
|
},
|
|
262
267
|
{
|
|
263
268
|
"file": "src/daemon-ipc/paths.js",
|
|
264
|
-
"beforeBytes":
|
|
265
|
-
"afterBytes":
|
|
269
|
+
"beforeBytes": 2796,
|
|
270
|
+
"afterBytes": 997
|
|
266
271
|
},
|
|
267
272
|
{
|
|
268
273
|
"file": "src/daemon-ipc/protocol.js",
|
|
@@ -311,8 +316,8 @@
|
|
|
311
316
|
},
|
|
312
317
|
{
|
|
313
318
|
"file": "src/index.js",
|
|
314
|
-
"beforeBytes":
|
|
315
|
-
"afterBytes":
|
|
319
|
+
"beforeBytes": 26931,
|
|
320
|
+
"afterBytes": 13804
|
|
316
321
|
},
|
|
317
322
|
{
|
|
318
323
|
"file": "src/log-redaction.js",
|
|
@@ -351,8 +356,8 @@
|
|
|
351
356
|
},
|
|
352
357
|
{
|
|
353
358
|
"file": "src/native-fusion/codex-parser.js",
|
|
354
|
-
"beforeBytes":
|
|
355
|
-
"afterBytes":
|
|
359
|
+
"beforeBytes": 30250,
|
|
360
|
+
"afterBytes": 12466
|
|
356
361
|
},
|
|
357
362
|
{
|
|
358
363
|
"file": "src/native-fusion/codex-user-input.js",
|
|
@@ -386,18 +391,18 @@
|
|
|
386
391
|
},
|
|
387
392
|
{
|
|
388
393
|
"file": "src/native-fusion/parser-common.js",
|
|
389
|
-
"beforeBytes":
|
|
390
|
-
"afterBytes":
|
|
394
|
+
"beforeBytes": 11340,
|
|
395
|
+
"afterBytes": 4643
|
|
391
396
|
},
|
|
392
397
|
{
|
|
393
398
|
"file": "src/native-fusion/parsers.js",
|
|
394
|
-
"beforeBytes":
|
|
395
|
-
"afterBytes":
|
|
399
|
+
"beforeBytes": 6594,
|
|
400
|
+
"afterBytes": 3602
|
|
396
401
|
},
|
|
397
402
|
{
|
|
398
403
|
"file": "src/native-fusion/service.js",
|
|
399
|
-
"beforeBytes":
|
|
400
|
-
"afterBytes":
|
|
404
|
+
"beforeBytes": 34698,
|
|
405
|
+
"afterBytes": 15552
|
|
401
406
|
},
|
|
402
407
|
{
|
|
403
408
|
"file": "src/native-fusion/session-header.js",
|
|
@@ -461,8 +466,8 @@
|
|
|
461
466
|
},
|
|
462
467
|
{
|
|
463
468
|
"file": "src/room/activation-service.js",
|
|
464
|
-
"beforeBytes":
|
|
465
|
-
"afterBytes":
|
|
469
|
+
"beforeBytes": 21713,
|
|
470
|
+
"afterBytes": 10792
|
|
466
471
|
},
|
|
467
472
|
{
|
|
468
473
|
"file": "src/room/attachment-cache.js",
|
|
@@ -501,8 +506,8 @@
|
|
|
501
506
|
},
|
|
502
507
|
{
|
|
503
508
|
"file": "src/room/managed-prompt-composer.js",
|
|
504
|
-
"beforeBytes":
|
|
505
|
-
"afterBytes":
|
|
509
|
+
"beforeBytes": 9264,
|
|
510
|
+
"afterBytes": 9441
|
|
506
511
|
},
|
|
507
512
|
{
|
|
508
513
|
"file": "src/room/managed-room-binding.js",
|
|
@@ -511,13 +516,13 @@
|
|
|
511
516
|
},
|
|
512
517
|
{
|
|
513
518
|
"file": "src/room/managed-room-ipc.js",
|
|
514
|
-
"beforeBytes":
|
|
515
|
-
"afterBytes":
|
|
519
|
+
"beforeBytes": 12245,
|
|
520
|
+
"afterBytes": 5867
|
|
516
521
|
},
|
|
517
522
|
{
|
|
518
523
|
"file": "src/room/mirror-sync-service.js",
|
|
519
|
-
"beforeBytes":
|
|
520
|
-
"afterBytes":
|
|
524
|
+
"beforeBytes": 7894,
|
|
525
|
+
"afterBytes": 3589
|
|
521
526
|
},
|
|
522
527
|
{
|
|
523
528
|
"file": "src/room/public-attachment-cache.js",
|
|
@@ -666,8 +671,8 @@
|
|
|
666
671
|
},
|
|
667
672
|
{
|
|
668
673
|
"file": "src/session/manager.js",
|
|
669
|
-
"beforeBytes":
|
|
670
|
-
"afterBytes":
|
|
674
|
+
"beforeBytes": 31103,
|
|
675
|
+
"afterBytes": 16179
|
|
671
676
|
},
|
|
672
677
|
{
|
|
673
678
|
"file": "src/session/native-cleanup-outbox.js",
|
|
@@ -686,8 +691,8 @@
|
|
|
686
691
|
},
|
|
687
692
|
{
|
|
688
693
|
"file": "src/session/queue.js",
|
|
689
|
-
"beforeBytes":
|
|
690
|
-
"afterBytes":
|
|
694
|
+
"beforeBytes": 33159,
|
|
695
|
+
"afterBytes": 14816
|
|
691
696
|
},
|
|
692
697
|
{
|
|
693
698
|
"file": "src/session/store.js",
|
|
@@ -1,19 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// @test src/__tests__/agents-e2e.ts
|
|
3
|
-
import { EventEmitter } from 'node:events';
|
|
4
|
-
export class AgentAdapter extends EventEmitter {
|
|
5
|
-
}
|
|
6
|
-
const registry = new Map();
|
|
7
|
-
export function registerAgent(type, factory) {
|
|
8
|
-
registry.set(type, factory);
|
|
9
|
-
}
|
|
10
|
-
export function unregisterAgent(type) {
|
|
11
|
-
registry.delete(type);
|
|
12
|
-
}
|
|
13
|
-
export function createAgent(type) {
|
|
14
|
-
const factory = registry.get(type);
|
|
15
|
-
return factory ? factory() : null;
|
|
16
|
-
}
|
|
17
|
-
export function getRegisteredAgents() {
|
|
18
|
-
return [...registry.keys()];
|
|
19
|
-
}
|
|
1
|
+
import{EventEmitter as r}from"node:events";class s extends r{}const n=new Map;function g(e,t){n.set(e,t)}function i(e){n.delete(e)}function c(e){const t=n.get(e);return t?t():null}function p(){return[...n.keys()]}export{s as AgentAdapter,c as createAgent,p as getRegisteredAgents,g as registerAgent,i as unregisterAgent};
|
|
@@ -1,248 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// @test src/__tests__/claude-managed-permissions.test.ts
|
|
3
|
-
import fs from 'node:fs';
|
|
4
|
-
import path from 'node:path';
|
|
5
|
-
import { resolveProtectedShennianDirectories } from '../security/managed-agent-credential-paths.js';
|
|
6
|
-
const fullExternalCapabilitySupport = {
|
|
7
|
-
commandNetwork: { allow: true, deny: true },
|
|
8
|
-
webSearch: { allow: true, deny: true },
|
|
9
|
-
browser: { allow: true, deny: true },
|
|
10
|
-
// Claude Code's computer-use surface controls the real desktop and does not
|
|
11
|
-
// currently expose a Shennian-verifiable, non-interactive permission gate.
|
|
12
|
-
computerUse: { allow: false, deny: true },
|
|
13
|
-
mcp: { allow: true, deny: true },
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* v2.1.260 is the first evidence baseline used by Shennian: it includes
|
|
17
|
-
* restricted mode, source isolation, fail-closed sandbox startup, credential
|
|
18
|
-
* scrubbing, outside-workspace read blocking, and the macOS fix for that read
|
|
19
|
-
* boundary. Unknown and older builds therefore resolve as unverified.
|
|
20
|
-
*/
|
|
21
|
-
export const CLAUDE_MANAGED_RUNTIME_SECURITY = {
|
|
22
|
-
minimumRuntimeVersion: '2.1.260',
|
|
23
|
-
maximumRuntimeVersionExclusive: '2.2.0',
|
|
24
|
-
platforms: {
|
|
25
|
-
darwin: {
|
|
26
|
-
level: 'hard',
|
|
27
|
-
fileAccess: { 'workspace-read': true, 'workspace-write': true, 'host-full': true },
|
|
28
|
-
externalCapabilities: fullExternalCapabilitySupport,
|
|
29
|
-
},
|
|
30
|
-
linux: {
|
|
31
|
-
level: 'partial',
|
|
32
|
-
fileAccess: { 'workspace-read': true, 'workspace-write': true, 'host-full': true },
|
|
33
|
-
externalCapabilities: fullExternalCapabilitySupport,
|
|
34
|
-
knownGaps: ['internalTransport.unixSocketGranularity'],
|
|
35
|
-
},
|
|
36
|
-
wsl: {
|
|
37
|
-
level: 'partial',
|
|
38
|
-
fileAccess: { 'workspace-read': true, 'workspace-write': true, 'host-full': true },
|
|
39
|
-
externalCapabilities: fullExternalCapabilitySupport,
|
|
40
|
-
knownGaps: ['internalTransport.unixSocketGranularity'],
|
|
41
|
-
},
|
|
42
|
-
win32: {
|
|
43
|
-
level: 'partial',
|
|
44
|
-
fileAccess: { 'workspace-read': false, 'workspace-write': false, 'host-full': true },
|
|
45
|
-
externalCapabilities: {
|
|
46
|
-
commandNetwork: { allow: true, deny: false },
|
|
47
|
-
webSearch: { allow: true, deny: true },
|
|
48
|
-
browser: { allow: true, deny: true },
|
|
49
|
-
computerUse: { allow: false, deny: true },
|
|
50
|
-
mcp: { allow: true, deny: true },
|
|
51
|
-
},
|
|
52
|
-
knownGaps: ['sandbox.nativeWindowsUnavailable'],
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
const SENSITIVE_PERMISSION_PATHS = [
|
|
57
|
-
'//**/.env',
|
|
58
|
-
'//**/.env.*',
|
|
59
|
-
'//**/*.key',
|
|
60
|
-
'//**/*.pem',
|
|
61
|
-
'~/.ssh/**',
|
|
62
|
-
'~/.aws/**',
|
|
63
|
-
'~/.azure/**',
|
|
64
|
-
'~/.config/gcloud/**',
|
|
65
|
-
'~/.netrc',
|
|
66
|
-
'~/.npmrc',
|
|
67
|
-
'~/.shennian/**',
|
|
68
|
-
];
|
|
69
|
-
const SENSITIVE_SANDBOX_PATHS = [
|
|
70
|
-
'/**/.env',
|
|
71
|
-
'/**/.env.*',
|
|
72
|
-
'/**/*.key',
|
|
73
|
-
'/**/*.pem',
|
|
74
|
-
'~/.ssh',
|
|
75
|
-
'~/.aws',
|
|
76
|
-
'~/.azure',
|
|
77
|
-
'~/.config/gcloud',
|
|
78
|
-
'~/.netrc',
|
|
79
|
-
'~/.npmrc',
|
|
80
|
-
];
|
|
81
|
-
const SHENNIAN_HOME_SANDBOX_PATH = '~/.shennian';
|
|
82
|
-
const READ_TOOLS = ['Read', 'Glob', 'Grep', 'LSP'];
|
|
83
|
-
const WRITE_TOOLS = ['Edit', 'Write', 'NotebookEdit'];
|
|
84
|
-
/**
|
|
85
|
-
* Converts the daemon-verified effective policy into Claude Code's native,
|
|
86
|
-
* invocation-scoped permission and sandbox configuration. It never writes to
|
|
87
|
-
* ~/.claude or the project's .claude directory.
|
|
88
|
-
*/
|
|
89
|
-
export function compileClaudeManagedPermissions(enforcement, resolvedWorkDir, options = {}) {
|
|
90
|
-
const workDir = validateResolvedWorkDir(resolvedWorkDir);
|
|
91
|
-
const policy = enforcement.effectivePolicy;
|
|
92
|
-
const hardSandbox = enforcement.platform !== 'win32';
|
|
93
|
-
const internalReadPaths = normalizeAbsolutePaths(options.internalReadPaths);
|
|
94
|
-
const internalUnixSockets = normalizeAbsolutePaths(options.internalUnixSockets);
|
|
95
|
-
const fileRoot = normalizeForClaude(path.parse(workDir).root);
|
|
96
|
-
const normalizedWorkDir = normalizeForClaude(workDir);
|
|
97
|
-
const hostFull = policy.fileAccess === 'host-full';
|
|
98
|
-
const workspaceWritable = policy.fileAccess === 'workspace-write';
|
|
99
|
-
const shennianDirectories = resolveProtectedShennianDirectories();
|
|
100
|
-
const allowRules = [];
|
|
101
|
-
if (workspaceWritable)
|
|
102
|
-
allowRules.push('Edit(/**)');
|
|
103
|
-
if (hostFull)
|
|
104
|
-
allowRules.push('Read', 'Edit');
|
|
105
|
-
if (policy.externalCapabilities.webSearch)
|
|
106
|
-
allowRules.push('WebSearch', 'WebFetch');
|
|
107
|
-
if (policy.externalCapabilities.mcp)
|
|
108
|
-
allowRules.push('mcp__*');
|
|
109
|
-
// Native Windows has no Bash sandbox. The compiler has already widened the
|
|
110
|
-
// effective policy and required limited-protection confirmation before this
|
|
111
|
-
// unsandboxed command surface can be reached.
|
|
112
|
-
if (!hardSandbox)
|
|
113
|
-
allowRules.push('Bash', 'PowerShell');
|
|
114
|
-
const denyRules = [
|
|
115
|
-
...SENSITIVE_PERMISSION_PATHS.flatMap((entry) => [`Read(${entry})`, `Edit(${entry})`]),
|
|
116
|
-
...shennianDirectories.flatMap((entry) => [
|
|
117
|
-
`Read(${toClaudeAbsolutePermissionPattern(entry)}/**)`,
|
|
118
|
-
`Edit(${toClaudeAbsolutePermissionPattern(entry)}/**)`,
|
|
119
|
-
]),
|
|
120
|
-
...(!policy.externalCapabilities.webSearch ? ['WebSearch', 'WebFetch'] : []),
|
|
121
|
-
...(!policy.externalCapabilities.mcp ? ['mcp__*'] : []),
|
|
122
|
-
];
|
|
123
|
-
const filesystem = hardSandbox
|
|
124
|
-
? {
|
|
125
|
-
disabled: false,
|
|
126
|
-
// Claude's sandbox allowRead entries take precedence over denyRead.
|
|
127
|
-
// This keeps the product-owned directory opaque while restoring only
|
|
128
|
-
// the exact daemon transport files needed by the scoped Room CLI.
|
|
129
|
-
allowRead: [...new Set([normalizedWorkDir, ...internalReadPaths])],
|
|
130
|
-
allowWrite: hostFull ? [fileRoot] : workspaceWritable ? [normalizedWorkDir] : [],
|
|
131
|
-
denyRead: [
|
|
132
|
-
...SENSITIVE_SANDBOX_PATHS,
|
|
133
|
-
SHENNIAN_HOME_SANDBOX_PATH,
|
|
134
|
-
...shennianDirectories,
|
|
135
|
-
],
|
|
136
|
-
denyWrite: [
|
|
137
|
-
...SENSITIVE_SANDBOX_PATHS,
|
|
138
|
-
SHENNIAN_HOME_SANDBOX_PATH,
|
|
139
|
-
...shennianDirectories,
|
|
140
|
-
...(!hostFull && !workspaceWritable ? [normalizedWorkDir] : []),
|
|
141
|
-
],
|
|
142
|
-
}
|
|
143
|
-
: undefined;
|
|
144
|
-
const network = hardSandbox
|
|
145
|
-
? {
|
|
146
|
-
allowedDomains: policy.externalCapabilities.commandNetwork ? ['*'] : [],
|
|
147
|
-
deniedDomains: policy.externalCapabilities.commandNetwork ? [] : ['*'],
|
|
148
|
-
strictAllowlist: true,
|
|
149
|
-
allowLocalBinding: policy.externalCapabilities.commandNetwork,
|
|
150
|
-
allowUnixSockets: enforcement.platform === 'darwin' ? internalUnixSockets : [],
|
|
151
|
-
// Linux/WSL only expose an all-or-nothing AF_UNIX switch. The
|
|
152
|
-
// filesystem layer still exposes only the exact daemon path, but the
|
|
153
|
-
// runtime declaration reports this platform as partial.
|
|
154
|
-
allowAllUnixSockets: (enforcement.platform === 'linux' || enforcement.platform === 'wsl') &&
|
|
155
|
-
internalUnixSockets.length > 0,
|
|
156
|
-
}
|
|
157
|
-
: undefined;
|
|
158
|
-
const settings = {
|
|
159
|
-
permissions: {
|
|
160
|
-
defaultMode: 'dontAsk',
|
|
161
|
-
disableBypassPermissionsMode: 'disable',
|
|
162
|
-
disableAutoMode: 'disable',
|
|
163
|
-
blockReadsOutsideWorkingDirectories: !hostFull,
|
|
164
|
-
allow: [...new Set(allowRules)].sort(),
|
|
165
|
-
deny: [...new Set(denyRules)].sort(),
|
|
166
|
-
},
|
|
167
|
-
disableArtifact: true,
|
|
168
|
-
disableRemoteControl: true,
|
|
169
|
-
disableWorkflows: true,
|
|
170
|
-
disableClaudeAiConnectors: !policy.externalCapabilities.mcp,
|
|
171
|
-
...(hardSandbox
|
|
172
|
-
? {
|
|
173
|
-
sandbox: {
|
|
174
|
-
enabled: true,
|
|
175
|
-
failIfUnavailable: true,
|
|
176
|
-
autoAllowBashIfSandboxed: true,
|
|
177
|
-
allowUnsandboxedCommands: false,
|
|
178
|
-
excludedCommands: [],
|
|
179
|
-
allowAppleEvents: false,
|
|
180
|
-
filesystem,
|
|
181
|
-
network,
|
|
182
|
-
credentials: {
|
|
183
|
-
files: SENSITIVE_SANDBOX_PATHS.map((entry) => ({ path: entry, mode: 'deny' })),
|
|
184
|
-
envVars: normalizeEnvKeys(options.shellSubprocessPolicy?.deniedEnvKeys).map((name) => ({ name, mode: 'deny' })),
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
}
|
|
188
|
-
: {}),
|
|
189
|
-
};
|
|
190
|
-
const tools = [
|
|
191
|
-
'Bash',
|
|
192
|
-
...READ_TOOLS,
|
|
193
|
-
...(workspaceWritable || hostFull ? WRITE_TOOLS : []),
|
|
194
|
-
...(policy.externalCapabilities.webSearch ? ['WebSearch', 'WebFetch'] : []),
|
|
195
|
-
];
|
|
196
|
-
const args = [
|
|
197
|
-
'--restricted',
|
|
198
|
-
'--setting-sources',
|
|
199
|
-
'',
|
|
200
|
-
'--settings',
|
|
201
|
-
JSON.stringify(settings),
|
|
202
|
-
'--permission-mode',
|
|
203
|
-
'dontAsk',
|
|
204
|
-
'--tools',
|
|
205
|
-
[...new Set(tools)].join(','),
|
|
206
|
-
policy.externalCapabilities.browser ? '--chrome' : '--no-chrome',
|
|
207
|
-
];
|
|
208
|
-
if (hostFull)
|
|
209
|
-
args.push('--add-dir', fileRoot);
|
|
210
|
-
if (!policy.externalCapabilities.mcp) {
|
|
211
|
-
args.push('--strict-mcp-config', '--mcp-config', JSON.stringify({ mcpServers: {} }));
|
|
212
|
-
}
|
|
213
|
-
return { settings, args };
|
|
214
|
-
}
|
|
215
|
-
function validateResolvedWorkDir(value) {
|
|
216
|
-
const normalized = path.normalize(value.trim());
|
|
217
|
-
if (!normalized || !path.isAbsolute(normalized)) {
|
|
218
|
-
throw new Error('claude_managed_workdir_invalid');
|
|
219
|
-
}
|
|
220
|
-
let realPath;
|
|
221
|
-
try {
|
|
222
|
-
realPath = fs.realpathSync(normalized);
|
|
223
|
-
}
|
|
224
|
-
catch {
|
|
225
|
-
throw new Error('claude_managed_workdir_unavailable');
|
|
226
|
-
}
|
|
227
|
-
if (path.normalize(realPath) !== normalized) {
|
|
228
|
-
throw new Error('claude_managed_workdir_not_realpath');
|
|
229
|
-
}
|
|
230
|
-
return normalized;
|
|
231
|
-
}
|
|
232
|
-
function normalizeAbsolutePaths(values) {
|
|
233
|
-
return [...new Set(values ?? [])]
|
|
234
|
-
.map((entry) => path.normalize(entry.trim()))
|
|
235
|
-
.filter((entry) => entry && path.isAbsolute(entry))
|
|
236
|
-
.map(normalizeForClaude)
|
|
237
|
-
.sort();
|
|
238
|
-
}
|
|
239
|
-
function normalizeForClaude(value) {
|
|
240
|
-
return value.replaceAll('\\', '/');
|
|
241
|
-
}
|
|
242
|
-
function toClaudeAbsolutePermissionPattern(value) {
|
|
243
|
-
const normalized = normalizeForClaude(value);
|
|
244
|
-
return normalized.startsWith('/') ? `/${normalized}` : `//${normalized}`;
|
|
245
|
-
}
|
|
246
|
-
function normalizeEnvKeys(values) {
|
|
247
|
-
return [...new Set(values ?? [])].filter((value) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(value)).sort();
|
|
248
|
-
}
|
|
1
|
+
import g from"node:fs";import n from"node:path";import{resolveProtectedShennianDirectories as N}from"../security/managed-agent-credential-paths.js";const m={commandNetwork:{allow:!0,deny:!0},webSearch:{allow:!0,deny:!0},browser:{allow:!0,deny:!0},computerUse:{allow:!1,deny:!0},mcp:{allow:!0,deny:!0}},M={minimumRuntimeVersion:"2.1.260",maximumRuntimeVersionExclusive:"2.2.0",platforms:{darwin:{level:"hard",fileAccess:{"workspace-read":!0,"workspace-write":!0,"host-full":!0},externalCapabilities:m},linux:{level:"partial",fileAccess:{"workspace-read":!0,"workspace-write":!0,"host-full":!0},externalCapabilities:m,knownGaps:["internalTransport.unixSocketGranularity"]},wsl:{level:"partial",fileAccess:{"workspace-read":!0,"workspace-write":!0,"host-full":!0},externalCapabilities:m,knownGaps:["internalTransport.unixSocketGranularity"]},win32:{level:"partial",fileAccess:{"workspace-read":!1,"workspace-write":!1,"host-full":!0},externalCapabilities:{commandNetwork:{allow:!0,deny:!1},webSearch:{allow:!0,deny:!0},browser:{allow:!0,deny:!0},computerUse:{allow:!1,deny:!0},mcp:{allow:!0,deny:!0}},knownGaps:["sandbox.nativeWindowsUnavailable"]}}},P=["//**/.env","//**/.env.*","//**/*.key","//**/*.pem","~/.ssh/**","~/.aws/**","~/.azure/**","~/.config/gcloud/**","~/.netrc","~/.npmrc","~/.shennian/**"],f=["/**/.env","/**/.env.*","/**/*.key","/**/*.pem","~/.ssh","~/.aws","~/.azure","~/.config/gcloud","~/.netrc","~/.npmrc"],x="~/.shennian",W=["Read","Glob","Grep","LSP"],z=["Edit","Write","NotebookEdit"];function G(a,e,l={}){const b=D(e),t=a.effectivePolicy,s=a.platform!=="win32",_=A(l.internalReadPaths),h=A(l.internalUnixSockets),S=d(n.parse(b).root),u=d(b),i=t.fileAccess==="host-full",c=t.fileAccess==="workspace-write",p=N(),o=[];c&&o.push("Edit(/**)"),i&&o.push("Read","Edit"),t.externalCapabilities.webSearch&&o.push("WebSearch","WebFetch"),t.externalCapabilities.mcp&&o.push("mcp__*"),s||o.push("Bash","PowerShell");const E=[...P.flatMap(r=>[`Read(${r})`,`Edit(${r})`]),...p.flatMap(r=>[`Read(${y(r)}/**)`,`Edit(${y(r)}/**)`]),...t.externalCapabilities.webSearch?[]:["WebSearch","WebFetch"],...t.externalCapabilities.mcp?[]:["mcp__*"]],C=s?{disabled:!1,allowRead:[...new Set([u,..._])],allowWrite:i?[S]:c?[u]:[],denyRead:[...f,x,...p],denyWrite:[...f,x,...p,...!i&&!c?[u]:[]]}:void 0,v=s?{allowedDomains:t.externalCapabilities.commandNetwork?["*"]:[],deniedDomains:t.externalCapabilities.commandNetwork?[]:["*"],strictAllowlist:!0,allowLocalBinding:t.externalCapabilities.commandNetwork,allowUnixSockets:a.platform==="darwin"?h:[],allowAllUnixSockets:(a.platform==="linux"||a.platform==="wsl")&&h.length>0}:void 0,k={permissions:{defaultMode:"dontAsk",disableBypassPermissionsMode:"disable",disableAutoMode:"disable",blockReadsOutsideWorkingDirectories:!i,allow:[...new Set(o)].sort(),deny:[...new Set(E)].sort()},disableArtifact:!0,disableRemoteControl:!0,disableWorkflows:!0,disableClaudeAiConnectors:!t.externalCapabilities.mcp,...s?{sandbox:{enabled:!0,failIfUnavailable:!0,autoAllowBashIfSandboxed:!0,allowUnsandboxedCommands:!1,excludedCommands:[],allowAppleEvents:!1,filesystem:C,network:v,credentials:{files:f.map(r=>({path:r,mode:"deny"})),envVars:I(l.shellSubprocessPolicy?.deniedEnvKeys).map(r=>({name:r,mode:"deny"}))}}}:{}},R=["Bash",...W,...c||i?z:[],...t.externalCapabilities.webSearch?["WebSearch","WebFetch"]:[]],w=["--restricted","--setting-sources","","--settings",JSON.stringify(k),"--permission-mode","dontAsk","--tools",[...new Set(R)].join(","),t.externalCapabilities.browser?"--chrome":"--no-chrome"];return i&&w.push("--add-dir",S),t.externalCapabilities.mcp||w.push("--strict-mcp-config","--mcp-config",JSON.stringify({mcpServers:{}})),{settings:k,args:w}}function D(a){const e=n.normalize(a.trim());if(!e||!n.isAbsolute(e))throw new Error("claude_managed_workdir_invalid");let l;try{l=g.realpathSync(e)}catch{throw new Error("claude_managed_workdir_unavailable")}if(n.normalize(l)!==e)throw new Error("claude_managed_workdir_not_realpath");return e}function A(a){return[...new Set(a??[])].map(e=>n.normalize(e.trim())).filter(e=>e&&n.isAbsolute(e)).map(d).sort()}function d(a){return a.replaceAll("\\","/")}function y(a){const e=d(a);return e.startsWith("/")?`/${e}`:`//${e}`}function I(a){return[...new Set(a??[])].filter(e=>/^[A-Za-z_][A-Za-z0-9_]*$/.test(e)).sort()}export{M as CLAUDE_MANAGED_RUNTIME_SECURITY,G as compileClaudeManagedPermissions};
|