shennian 0.3.86 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +3 -2
  2. package/dist/bin/shennian.js +1 -1
  3. package/dist/publish-build-manifest.json +32 -27
  4. package/dist/src/agents/adapter.js +1 -19
  5. package/dist/src/agents/claude-managed-permissions.js +1 -248
  6. package/dist/src/agents/claude.js +8 -393
  7. package/dist/src/agents/codex-managed-permissions.js +1 -294
  8. package/dist/src/agents/codex-managed-room-tools.js +1 -249
  9. package/dist/src/agents/codex-utils.js +7 -200
  10. package/dist/src/agents/codex.d.ts +7 -1
  11. package/dist/src/agents/codex.js +17 -1352
  12. package/dist/src/agents/config-status.js +1 -226
  13. package/dist/src/agents/cursor-managed-permissions.js +2 -299
  14. package/dist/src/agents/cursor.js +1 -314
  15. package/dist/src/agents/custom.js +4 -418
  16. package/dist/src/agents/external-channel-instructions.js +11 -94
  17. package/dist/src/agents/gemini.js +1 -180
  18. package/dist/src/agents/manager.js +18 -250
  19. package/dist/src/agents/model-registry/cache.js +1 -37
  20. package/dist/src/agents/model-registry/discovery.js +2 -188
  21. package/dist/src/agents/model-registry/parsers.js +4 -521
  22. package/dist/src/agents/model-registry/runner.js +1 -30
  23. package/dist/src/agents/model-registry/service.js +1 -115
  24. package/dist/src/agents/model-registry/types.js +1 -8
  25. package/dist/src/agents/model-registry.js +1 -19
  26. package/dist/src/agents/native-capabilities.js +1 -237
  27. package/dist/src/agents/openclaw.js +2 -293
  28. package/dist/src/agents/opencode-managed-permissions.js +2 -187
  29. package/dist/src/agents/opencode.js +1 -298
  30. package/dist/src/agents/platform-instructions.js +17 -46
  31. package/dist/src/agents/runtime-compatibility.js +1 -44
  32. package/dist/src/agents/workbuddy-managed-permissions.js +2 -329
  33. package/dist/src/agents/workbuddy.js +3 -444
  34. package/dist/src/commands/logout.d.ts +3 -0
  35. package/dist/src/commands/logout.js +1 -0
  36. package/dist/src/daemon-ipc/paths.js +1 -1
  37. package/dist/src/fs/boundary.js +1 -185
  38. package/dist/src/fs/handler.js +1 -130
  39. package/dist/src/fs/security.js +1 -32
  40. package/dist/src/fs/text-decoder.js +1 -110
  41. package/dist/src/index.js +3 -587
  42. package/dist/src/manager/prompt.js +29 -34
  43. package/dist/src/manager/registry.js +1 -317
  44. package/dist/src/manager/retired-external-channel-compat.js +1 -40
  45. package/dist/src/manager/runtime.js +23 -1514
  46. package/dist/src/native-fusion/codex-parser.d.ts +3 -1
  47. package/dist/src/native-fusion/codex-parser.js +4 -660
  48. package/dist/src/native-fusion/codex-user-input.js +5 -102
  49. package/dist/src/native-fusion/config.js +1 -5
  50. package/dist/src/native-fusion/file-watcher.js +1 -191
  51. package/dist/src/native-fusion/local-repository.js +2 -569
  52. package/dist/src/native-fusion/opencode-parser.js +3 -130
  53. package/dist/src/native-fusion/parser-common.d.ts +6 -1
  54. package/dist/src/native-fusion/parser-common.js +4 -4
  55. package/dist/src/native-fusion/parsers.d.ts +4 -2
  56. package/dist/src/native-fusion/parsers.js +3 -140
  57. package/dist/src/native-fusion/service.js +2 -739
  58. package/dist/src/native-fusion/session-header.js +2 -101
  59. package/dist/src/native-fusion/state.js +2 -104
  60. package/dist/src/native-fusion/types.js +1 -1
  61. package/dist/src/personal-sync/machine-authority.js +1 -34
  62. package/dist/src/room/activation-audit.js +2 -45
  63. package/dist/src/room/activation-policy.js +1 -30
  64. package/dist/src/room/activation-service.js +8 -408
  65. package/dist/src/room/invite-bootstrap.js +1 -156
  66. package/dist/src/room/managed-prompt-composer.d.ts +1 -1
  67. package/dist/src/room/managed-prompt-composer.js +17 -16
  68. package/dist/src/room/managed-room-binding.js +1 -167
  69. package/dist/src/room/managed-room-ipc.d.ts +4 -0
  70. package/dist/src/room/managed-room-ipc.js +2 -2
  71. package/dist/src/room/mirror-sync-service.d.ts +1 -0
  72. package/dist/src/room/mirror-sync-service.js +1 -183
  73. package/dist/src/room/room-binding-client.js +1 -151
  74. package/dist/src/session/archive-zip.js +1 -220
  75. package/dist/src/session/deletion-sync-state.js +2 -136
  76. package/dist/src/session/handlers/agent-capabilities.js +1 -14
  77. package/dist/src/session/handlers/agent-config.js +1 -150
  78. package/dist/src/session/handlers/agents.js +1 -55
  79. package/dist/src/session/handlers/chat.js +2 -1030
  80. package/dist/src/session/handlers/control.js +1 -61
  81. package/dist/src/session/handlers/fs.js +1 -594
  82. package/dist/src/session/handlers/message-status.js +1 -15
  83. package/dist/src/session/handlers/remote-access.js +1 -43
  84. package/dist/src/session/handlers/room-managed.js +1 -101
  85. package/dist/src/session/handlers/session-refresh.js +1 -35
  86. package/dist/src/session/handlers/title.js +1 -79
  87. package/dist/src/session/handlers/tool-detail.js +1 -149
  88. package/dist/src/session/handlers/voice-window.js +1 -62
  89. package/dist/src/session/history-subscriptions.js +1 -470
  90. package/dist/src/session/manager.d.ts +1 -0
  91. package/dist/src/session/manager.js +1 -658
  92. package/dist/src/session/native-cleanup-outbox.js +2 -287
  93. package/dist/src/session/native-session-lifecycle.js +6 -327
  94. package/dist/src/session/queue.d.ts +8 -0
  95. package/dist/src/session/queue.js +6 -6
  96. package/dist/src/upgrade/scheduler.js +1 -126
  97. package/node_modules/@shennian/wire/dist/agent-workspace.js +2 -2
  98. 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
  ## 开发
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import '../src/index.js';
2
+ import"../src/index.js";
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 1,
3
3
  "jsMinified": true,
4
4
  "minifier": "esbuild",
5
- "fileCount": 144,
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": 58249,
50
- "afterBytes": 30328
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": 2006,
265
- "afterBytes": 902
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": 25818,
315
- "afterBytes": 13311
319
+ "beforeBytes": 27137,
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": 29358,
355
- "afterBytes": 12136
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": 9178,
390
- "afterBytes": 4005
394
+ "beforeBytes": 11340,
395
+ "afterBytes": 4643
391
396
  },
392
397
  {
393
398
  "file": "src/native-fusion/parsers.js",
394
- "beforeBytes": 5850,
395
- "afterBytes": 3235
399
+ "beforeBytes": 6594,
400
+ "afterBytes": 3602
396
401
  },
397
402
  {
398
403
  "file": "src/native-fusion/service.js",
399
- "beforeBytes": 32663,
400
- "afterBytes": 14792
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": 21587,
465
- "afterBytes": 10726
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": 8751,
505
- "afterBytes": 8603
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": 11997,
515
- "afterBytes": 5784
519
+ "beforeBytes": 12245,
520
+ "afterBytes": 5867
516
521
  },
517
522
  {
518
523
  "file": "src/room/mirror-sync-service.js",
519
- "beforeBytes": 7714,
520
- "afterBytes": 3498
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": 30970,
670
- "afterBytes": 16083
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": 30478,
690
- "afterBytes": 13987
694
+ "beforeBytes": 33159,
695
+ "afterBytes": 14816
691
696
  },
692
697
  {
693
698
  "file": "src/session/store.js",
@@ -1,19 +1 @@
1
- // @arch docs/architecture/cli/agent-adapters.md
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
- // @arch docs/features/managed-agent-restricted-runtime.md
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};