dsh-a2a-server 0.3.0 → 0.4.1
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 +45 -28
- package/CHANGELOG.zh-CN.md +45 -28
- package/README.md +42 -16
- package/README.zh-CN.md +42 -13
- package/docker/Dockerfile +5 -0
- package/docs/public-visitors.en.md +39 -0
- package/docs/public-visitors.md +86 -0
- package/docs/visitor-isolation.en.md +50 -0
- package/docs/visitor-isolation.md +74 -0
- package/lib/config.d.ts +12 -4
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +9 -0
- package/lib/config.js.map +1 -1
- package/lib/docker-executor.d.ts +11 -0
- package/lib/docker-executor.d.ts.map +1 -0
- package/lib/docker-executor.js +115 -0
- package/lib/docker-executor.js.map +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +92 -12
- package/lib/index.js.map +1 -1
- package/lib/isolation.d.ts +21 -0
- package/lib/isolation.d.ts.map +1 -0
- package/lib/isolation.js +108 -0
- package/lib/isolation.js.map +1 -0
- package/lib/live-visitors.d.ts +21 -0
- package/lib/live-visitors.d.ts.map +1 -0
- package/lib/live-visitors.js +66 -0
- package/lib/live-visitors.js.map +1 -0
- package/lib/management.d.ts.map +1 -1
- package/lib/management.js +3 -1
- package/lib/management.js.map +1 -1
- package/lib/microsandbox-executor.d.ts +39 -0
- package/lib/microsandbox-executor.d.ts.map +1 -0
- package/lib/microsandbox-executor.js +316 -0
- package/lib/microsandbox-executor.js.map +1 -0
- package/lib/microsandbox-runtime.d.ts +28 -0
- package/lib/microsandbox-runtime.d.ts.map +1 -0
- package/lib/microsandbox-runtime.js +164 -0
- package/lib/microsandbox-runtime.js.map +1 -0
- package/lib/protocol/card.d.ts +1 -0
- package/lib/protocol/card.d.ts.map +1 -1
- package/lib/protocol/card.js +3 -0
- package/lib/protocol/card.js.map +1 -1
- package/lib/public-visitors.d.ts +38 -0
- package/lib/public-visitors.d.ts.map +1 -0
- package/lib/public-visitors.js +107 -0
- package/lib/public-visitors.js.map +1 -0
- package/lib/router.d.ts +15 -0
- package/lib/router.d.ts.map +1 -1
- package/lib/router.js +122 -9
- package/lib/router.js.map +1 -1
- package/lib/sandbox-files.d.ts +16 -0
- package/lib/sandbox-files.d.ts.map +1 -0
- package/lib/sandbox-files.js +168 -0
- package/lib/sandbox-files.js.map +1 -0
- package/lib/sandbox-lifecycle.d.ts +48 -0
- package/lib/sandbox-lifecycle.d.ts.map +1 -0
- package/lib/sandbox-lifecycle.js +125 -0
- package/lib/sandbox-lifecycle.js.map +1 -0
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/visitor-read.d.ts +4 -0
- package/lib/visitor-read.d.ts.map +1 -0
- package/lib/visitor-read.js +20 -0
- package/lib/visitor-read.js.map +1 -0
- package/lib/visitor-worker.d.ts +2 -0
- package/lib/visitor-worker.d.ts.map +1 -0
- package/lib/visitor-worker.js +18 -0
- package/lib/visitor-worker.js.map +1 -0
- package/lib/visitor-worker.mjs +14686 -0
- package/lib/visitor-worker.py +78 -0
- package/package.json +14 -4
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""Trusted bounded reader. Public data and a visitor's disk are the only roots."""
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
import pathlib
|
|
5
|
+
import stat
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
def read_request(args):
|
|
9
|
+
if not isinstance(args, dict) or set(args) - {'root', 'path', 'offset', 'limit'}:
|
|
10
|
+
raise ValueError('Invalid read request')
|
|
11
|
+
root_name = args.get('root', 'public')
|
|
12
|
+
if root_name not in ('public', 'workspace'):
|
|
13
|
+
raise ValueError('Unknown data root')
|
|
14
|
+
root = pathlib.Path('/source' if root_name == 'public' else '/work')
|
|
15
|
+
requested = args.get('path')
|
|
16
|
+
offset, limit = args.get('offset', 1), args.get('limit', 200)
|
|
17
|
+
if not isinstance(requested, str) or not 1 <= len(requested) <= 4096 or any(c in requested for c in ('\0', '\\', ':')):
|
|
18
|
+
raise ValueError('Invalid file path')
|
|
19
|
+
if type(offset) is not int or not 1 <= offset <= 10000000 or type(limit) is not int or not 1 <= limit <= 500:
|
|
20
|
+
raise ValueError('Invalid read pagination')
|
|
21
|
+
target = pathlib.Path(os.path.abspath(root / requested))
|
|
22
|
+
try:
|
|
23
|
+
parts = target.relative_to(root).parts
|
|
24
|
+
except ValueError:
|
|
25
|
+
raise ValueError('Path is outside the authorized data directory')
|
|
26
|
+
current = root
|
|
27
|
+
for component in ('',) + parts:
|
|
28
|
+
current = current / component
|
|
29
|
+
if stat.S_ISLNK(current.lstat().st_mode):
|
|
30
|
+
raise ValueError('Symbolic links are not available')
|
|
31
|
+
before = target.lstat()
|
|
32
|
+
if stat.S_ISDIR(before.st_mode):
|
|
33
|
+
entries, truncated = [], False
|
|
34
|
+
with os.scandir(target) as iterator:
|
|
35
|
+
for index, entry in enumerate(iterator):
|
|
36
|
+
if index >= 1000:
|
|
37
|
+
truncated = True
|
|
38
|
+
break
|
|
39
|
+
if entry.is_symlink():
|
|
40
|
+
continue
|
|
41
|
+
if entry.is_file(follow_symlinks=False) or entry.is_dir(follow_symlinks=False):
|
|
42
|
+
entries.append(entry.name + ('/' if entry.is_dir(follow_symlinks=False) else ''))
|
|
43
|
+
entries.sort()
|
|
44
|
+
text = '\n'.join(entries[offset - 1:offset - 1 + limit])
|
|
45
|
+
truncated = truncated or len(entries) > offset - 1 + limit
|
|
46
|
+
kind = 'directory'
|
|
47
|
+
else:
|
|
48
|
+
if not stat.S_ISREG(before.st_mode) or before.st_nlink != 1:
|
|
49
|
+
raise ValueError('Only regular files without hard links can be read')
|
|
50
|
+
if before.st_size > 2 * 1024 * 1024:
|
|
51
|
+
raise ValueError('File exceeds the 2 MiB read limit')
|
|
52
|
+
fd = os.open(target, os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK)
|
|
53
|
+
with os.fdopen(fd, 'rb') as stream:
|
|
54
|
+
opened = os.fstat(stream.fileno())
|
|
55
|
+
if (opened.st_dev, opened.st_ino, opened.st_nlink) != (before.st_dev, before.st_ino, 1):
|
|
56
|
+
raise ValueError('File changed during open')
|
|
57
|
+
data = stream.read(2 * 1024 * 1024 + 1)
|
|
58
|
+
if len(data) > 2 * 1024 * 1024:
|
|
59
|
+
raise ValueError('File exceeds the 2 MiB read limit')
|
|
60
|
+
text = data.decode('utf-8', errors='strict')
|
|
61
|
+
if '\0' in text:
|
|
62
|
+
raise ValueError('Binary files are not supported by read_file')
|
|
63
|
+
lines = text.replace('\r\n', '\n').split('\n')
|
|
64
|
+
text = '\n'.join(lines[offset - 1:offset - 1 + limit])
|
|
65
|
+
truncated = len(lines) > offset - 1 + limit
|
|
66
|
+
kind = 'file'
|
|
67
|
+
after = target.lstat()
|
|
68
|
+
if (before.st_dev, before.st_ino) != (after.st_dev, after.st_ino):
|
|
69
|
+
raise ValueError('Path changed during read')
|
|
70
|
+
return {'kind': kind, 'path': str(target.relative_to(root)), 'content': text[:32000], 'truncated': truncated or len(text) > 32000}
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
if len(sys.argv[1].encode('utf-8')) > 8192:
|
|
74
|
+
raise ValueError('Read request too large')
|
|
75
|
+
print(json.dumps({'result': read_request(json.loads(sys.argv[1]))}, ensure_ascii=False))
|
|
76
|
+
except Exception as error:
|
|
77
|
+
print(json.dumps({'error': str(error)}, ensure_ascii=False))
|
|
78
|
+
sys.exit(1)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-a2a-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Inbound A2A (Agent2Agent) protocol server for DeepSeek Harness: publish an Agent Card and let any A2A-compliant peer submit tasks to a harness agent",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
|
@@ -27,7 +27,13 @@
|
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"lib",
|
|
30
|
+
"docker",
|
|
30
31
|
"cordis.patch.yml",
|
|
32
|
+
"README.zh-CN.md",
|
|
33
|
+
"docs/visitor-isolation.md",
|
|
34
|
+
"docs/visitor-isolation.en.md",
|
|
35
|
+
"docs/public-visitors.md",
|
|
36
|
+
"docs/public-visitors.en.md",
|
|
31
37
|
"CHANGELOG.md",
|
|
32
38
|
"CHANGELOG.zh-CN.md"
|
|
33
39
|
],
|
|
@@ -40,10 +46,12 @@
|
|
|
40
46
|
"dsh": ">=0.2.1-rc.2 <0.3.0"
|
|
41
47
|
},
|
|
42
48
|
"scripts": {
|
|
43
|
-
"build": "tsc -p tsconfig.build.json",
|
|
49
|
+
"build": "tsc -p tsconfig.build.json && node scripts/build-worker.mjs",
|
|
44
50
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
45
51
|
"test": "vitest run",
|
|
46
52
|
"test:watch": "vitest",
|
|
53
|
+
"test:docker": "pnpm build && node scripts/test-docker.mjs",
|
|
54
|
+
"test:microsandbox": "pnpm build && node scripts/test-microsandbox.mjs",
|
|
47
55
|
"test:package": "pnpm build && node scripts/test-package.mjs",
|
|
48
56
|
"serve": "tsx example/serve.ts",
|
|
49
57
|
"probe": "node example/probe.mjs",
|
|
@@ -57,8 +65,8 @@
|
|
|
57
65
|
"@deepseek-ai/dsh-llm": ">=0.2.1-rc.2 <0.3.0",
|
|
58
66
|
"@deepseek-ai/dsh-session": ">=0.2.1-rc.2 <0.3.0",
|
|
59
67
|
"@deepseek-ai/dsh-session-projection": ">=0.2.1-rc.2 <0.3.0",
|
|
60
|
-
"@deepseek-ai/dsh-
|
|
61
|
-
"@deepseek-ai/dsh-
|
|
68
|
+
"@deepseek-ai/dsh-system-prompt": ">=0.2.1-rc.2 <0.3.0",
|
|
69
|
+
"@deepseek-ai/dsh-tools": ">=0.2.1-rc.2 <0.3.0"
|
|
62
70
|
},
|
|
63
71
|
"dependencies": {
|
|
64
72
|
"@deepseek-ai/schemastery": "^3.18.5",
|
|
@@ -84,6 +92,8 @@
|
|
|
84
92
|
"@deepseek-ai/dsh-system-prompt": "0.2.1-rc.2",
|
|
85
93
|
"@deepseek-ai/dsh-tools": "0.2.1-rc.2",
|
|
86
94
|
"@types/node": "^22.10.0",
|
|
95
|
+
"esbuild": "0.28.2",
|
|
96
|
+
"microsandbox": "0.7.11",
|
|
87
97
|
"tsx": "^4.19.2",
|
|
88
98
|
"typescript": "^5.7.2",
|
|
89
99
|
"vitest": "^2.1.8"
|