@1agents/dreammate-network 0.2.0 → 0.3.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.
@@ -8,7 +8,11 @@
8
8
  *
9
9
  * @packageDocumentation
10
10
  */
11
- export declare const PROTOCOL_VERSION = "0.1.0";
11
+ /**
12
+ * 协议版本,与本包的 package.json 版本保持一致——两个版本号会让人永远猜不准
13
+ * 该看哪个。服务在 `manifest.metadata.protocol_version` 里报告它遵循的版本。
14
+ */
15
+ export declare const PROTOCOL_VERSION = "0.3.0";
12
16
  /** `session://<node>/<runtime>/<session_id>` */
13
17
  export type SessionURI = `session://${string}/${string}/${string}`;
14
18
  /** 资源寻址,如 `recording://tingqi-01/abc`、`speaker://tingqi-001/speaker-23` */
@@ -57,6 +61,11 @@ export interface AccessDescriptor {
57
61
  * 与 docs/protocol.md §6 的表格一一对应,改动必须同步两边。
58
62
  */
59
63
  export declare const DEFAULT_PORTS: {
64
+ /**
65
+ * 本机 node agent(`@1agents/dreammate-node`)。**固定端口**,不可改:
66
+ * 它是整台机器对网络的唯一入口,外部节点靠"探 36908"找到这台机器上的一切。
67
+ */
68
+ readonly "node-agent": 36908;
60
69
  readonly "session-registry": 7777;
61
70
  readonly "data-service": 7778;
62
71
  readonly "control-plane": 7779;
@@ -82,6 +91,8 @@ export type ServiceKind = "generic" | "agent_runtime" | "session_registry" | "re
82
91
  * 三层结构是 Node → Service → Capability / Resource,
83
92
  * 不要把 Capability 扁平铺到 Node 上。
84
93
  */
94
+ /** 这个 Service 能被谁连上。省略时按 `network` 理解。 */
95
+ export type Reachability = "localhost" | "network";
85
96
  export interface Service {
86
97
  id: string;
87
98
  name?: string | null;
@@ -91,6 +102,15 @@ export interface Service {
91
102
  capabilities: Capability[];
92
103
  resources?: ResourceDescriptor[];
93
104
  access?: AccessDescriptor[];
105
+ /**
106
+ * 只监听回环的服务,外部节点发现得了但连不上。node agent 如实转述这个
107
+ * 声明而**不做代理**——调用方看到 `localhost` 就知道不用白跑一趟。
108
+ */
109
+ reachability?: Reachability;
110
+ /** 实际监听端口。不必等于 {@link DEFAULT_PORTS} 里的默认值。 */
111
+ port?: number | null;
112
+ /** 存活探测路径,默认 `/health`。 */
113
+ health?: string | null;
94
114
  metadata?: Record<string, unknown>;
95
115
  }
96
116
  /**
@@ -8,7 +8,11 @@
8
8
  *
9
9
  * @packageDocumentation
10
10
  */
11
- export const PROTOCOL_VERSION = "0.1.0";
11
+ /**
12
+ * 协议版本,与本包的 package.json 版本保持一致——两个版本号会让人永远猜不准
13
+ * 该看哪个。服务在 `manifest.metadata.protocol_version` 里报告它遵循的版本。
14
+ */
15
+ export const PROTOCOL_VERSION = "0.3.0";
12
16
  /* ------------------------------------------------------------------ *
13
17
  * 发现
14
18
  * ------------------------------------------------------------------ */
@@ -22,6 +26,11 @@ export const PROTOCOL_VERSION = "0.1.0";
22
26
  * 与 docs/protocol.md §6 的表格一一对应,改动必须同步两边。
23
27
  */
24
28
  export const DEFAULT_PORTS = {
29
+ /**
30
+ * 本机 node agent(`@1agents/dreammate-node`)。**固定端口**,不可改:
31
+ * 它是整台机器对网络的唯一入口,外部节点靠"探 36908"找到这台机器上的一切。
32
+ */
33
+ "node-agent": 36908,
25
34
  "session-registry": 7777,
26
35
  "data-service": 7778,
27
36
  "control-plane": 7779,
package/docs/protocol.md CHANGED
@@ -142,6 +142,7 @@ pull 要知道探哪儿,所以端口是公共词汇的一部分:
142
142
 
143
143
  | 端口 | Service | 层 |
144
144
  |------|---------|-----|
145
+ | **36908** | **`node-agent`(dreammate-node)** | **本机基础设施** |
145
146
  | 7777 | `session-registry`(session-reader) | L2 |
146
147
  | 7778 | `data-service` | L2 |
147
148
  | 7779 | `control-plane` | L3 |
@@ -152,6 +153,61 @@ pull 要知道探哪儿,所以端口是公共词汇的一部分:
152
153
  得由它自己 `POST /nodes/register` 告知——register 因此是可选的加速/兜底,
153
154
  不是必需品。
154
155
 
156
+ ### 本机 node agent
157
+
158
+ 每台机器跑一个 `@1agents/dreammate-node`,固定监听 **36908**。它是这台机器
159
+ 对网络的唯一入口:
160
+
161
+ ```
162
+ Control Plane / 任意节点
163
+ │ 探 36908(每台机器只探一个端口)
164
+
165
+ node-agent :36908
166
+ ├─ GET /manifest 本机聚合视图:节点身份 + 所有已报备的服务
167
+ ├─ GET /health
168
+ ├─ GET /services 各服务的存活与可达性
169
+ └─ POST /services 服务报备(**仅接受 localhost**)
170
+
171
+ ┌───────────┴───────────┐ localhost 报备
172
+ session-reader :7777 task-service :xxxx
173
+ ```
174
+
175
+ 这把 pull 探测的成本从「N 个节点 × M 个端口」降到「N × 1」。
176
+
177
+ **报备是可选的。** 服务不报备也能工作,只是外部得靠约定端口才找得到它。
178
+ 报备时必须声明**可达性**:
179
+
180
+ | `reachability` | 含义 |
181
+ |---|---|
182
+ | `localhost` | 只监听回环,外部节点发现得了但连不上 |
183
+ | `network` | 监听 0.0.0.0 或 tailnet 地址,外部可直连 |
184
+
185
+ agent 如实转述这个声明,**不做代理**。调用方看到 `localhost` 就知道这个能力
186
+ 只对本机开放,不用白跑一趟。
187
+
188
+ > ⚠️ `POST /services` 只接受来自回环的请求。否则网络上任何人都能往你的节点
189
+ > 里塞一个假服务,把调用方引到别处去。
190
+
191
+ ### Control Plane 不是一个进程
192
+
193
+ node 注册与探活下沉成了每台机器的基础设施(就是上面的 agent),原本设想中
194
+ Control Plane 的其余职责——Task、Agent 编排、Execution 账本——**降级为平级的
195
+ 普通服务**,各自独立起进程、各自向本机 agent 报备。
196
+
197
+ ```
198
+ 以前:Control Plane = Node Registry + Execution Ledger + Task + Orchestrator
199
+ (一个大进程)
200
+
201
+ 现在:node-agent = Node Registry + 探活 (每机一个,基础设施)
202
+ task-service ┐
203
+ agent-service ├ 平级服务,各自解耦运行,都向本机 agent 报备
204
+ execution-* ┘
205
+ ```
206
+
207
+ 好处是任何一个服务挂掉都不会让整个控制面消失,也不存在"必须先起 Control Plane
208
+ 才能用"的启动顺序。代价是全网视图需要有人聚合——那也只是另一个服务,它靠
209
+ tailnet + 探 36908 自己拼出来。
210
+
155
211
  ### 节点身份取自 tailnet
156
212
 
157
213
  节点的 `node_id` / `name` / `type` 应该直接用 tailnet 的事实,而不是自己生成:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1agents/dreammate-network",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "DreamMate Network L0 协议包:schema + types,零运行时依赖,不含业务逻辑。",
5
5
  "keywords": [
6
6
  "dreammate",
@@ -4,82 +4,165 @@
4
4
  "title": "DreamMate Service",
5
5
  "description": "Node 上的一组能力聚合。三层结构是 Node → Service → Capability / Resource,不要把 Capability 扁平铺到 Node 上。Agent Runtime 是 Service 的一种特殊 kind。",
6
6
  "type": "object",
7
- "required": ["id", "capabilities"],
7
+ "required": [
8
+ "id",
9
+ "capabilities"
10
+ ],
8
11
  "properties": {
9
12
  "id": {
10
13
  "type": "string",
11
14
  "description": "Service 在所属 Node 内唯一。",
12
15
  "minLength": 1,
13
- "examples": ["session-registry", "reminders", "recordings", "agent-runtime"]
16
+ "examples": [
17
+ "session-registry",
18
+ "reminders",
19
+ "recordings",
20
+ "agent-runtime"
21
+ ]
14
22
  },
15
23
  "name": {
16
- "type": ["string", "null"],
24
+ "type": [
25
+ "string",
26
+ "null"
27
+ ],
17
28
  "description": "人类可读名称,可省略。"
18
29
  },
19
30
  "kind": {
20
31
  "type": "string",
21
32
  "description": "Service 类型。generic 之外的几种在传输层保留原生协议(见 protocol.md §5),不强行塞进 /capabilities/:name/invoke。",
22
- "enum": ["generic", "agent_runtime", "session_registry", "resource_provider", "mcp"],
33
+ "enum": [
34
+ "generic",
35
+ "agent_runtime",
36
+ "session_registry",
37
+ "resource_provider",
38
+ "mcp"
39
+ ],
23
40
  "default": "generic"
24
41
  },
25
42
  "capabilities": {
26
43
  "type": "array",
27
44
  "description": "该 Service 能做什么。第一版就是点分命名的字符串,不带权限/可用性等元数据。可以为空数组(纯 Resource Provider)。",
28
- "items": { "type": "string", "minLength": 1 },
29
- "examples": [["sessions.list", "sessions.read"], ["reminders.create"], ["recordings.list", "recording.read"]]
45
+ "items": {
46
+ "type": "string",
47
+ "minLength": 1
48
+ },
49
+ "examples": [
50
+ [
51
+ "sessions.list",
52
+ "sessions.read"
53
+ ],
54
+ [
55
+ "reminders.create"
56
+ ],
57
+ [
58
+ "recordings.list",
59
+ "recording.read"
60
+ ]
61
+ ]
30
62
  },
31
63
  "resources": {
32
64
  "type": "array",
33
65
  "description": "该 Service 拥有什么(可选,声明资源 URI 的 scheme 而非逐条枚举)。Capability=能做什么,Resource=拥有什么,两者不要混:检索侧走 resource.search/read,调度侧走 capability.invoke。",
34
66
  "items": {
35
67
  "type": "object",
36
- "required": ["scheme"],
68
+ "required": [
69
+ "scheme"
70
+ ],
37
71
  "properties": {
38
72
  "scheme": {
39
73
  "type": "string",
40
74
  "description": "资源 URI 的 scheme。",
41
- "examples": ["recording", "transcript", "speaker", "session"]
75
+ "examples": [
76
+ "recording",
77
+ "transcript",
78
+ "speaker",
79
+ "session"
80
+ ]
42
81
  },
43
- "description": { "type": ["string", "null"] }
82
+ "description": {
83
+ "type": [
84
+ "string",
85
+ "null"
86
+ ]
87
+ }
44
88
  }
45
89
  }
46
90
  },
47
91
  "access": {
48
92
  "type": "array",
49
93
  "description": "怎么访问这个 Service。传输方式只出现在这里,绝不进数据模型——不存在所谓 MCP Capability / CLI Capability。同一组能力可以同时有多种 access,调用方不必关心底层是谁。包装优先级 MCP > CLI > HTTP,但第一版不做自动 fallback 编排,手工声明即可。",
50
- "items": { "$ref": "#/$defs/access" }
94
+ "items": {
95
+ "$ref": "#/$defs/access"
96
+ }
51
97
  },
52
98
  "metadata": {
53
99
  "type": "object",
54
100
  "description": "Service 级自由扩展字段。协议不解释其内容。",
55
101
  "additionalProperties": true
102
+ },
103
+ "reachability": {
104
+ "type": "string",
105
+ "enum": [
106
+ "localhost",
107
+ "network"
108
+ ],
109
+ "description": "这个 Service 能被谁连上。localhost=只监听回环,外部节点发现得了但连不上;network=监听 0.0.0.0 或 tailnet 地址,外部可直连。node agent 如实转述服务自己的声明,不做代理——调用方看到 localhost 就知道不用白跑一趟。省略时按 network 理解。"
110
+ },
111
+ "port": {
112
+ "type": [
113
+ "integer",
114
+ "null"
115
+ ],
116
+ "minimum": 1,
117
+ "maximum": 65535,
118
+ "description": "服务实际监听的端口。向本机 node agent 报备时带上,外部才知道该连哪儿;它不必等于 DEFAULT_PORTS 里的默认值。"
119
+ },
120
+ "health": {
121
+ "type": [
122
+ "string",
123
+ "null"
124
+ ],
125
+ "description": "存活探测路径,默认 /health。node agent 定期探它来判断服务死活——注意 Node 在线不代表 Service 在线。"
56
126
  }
57
127
  },
58
128
  "$defs": {
59
129
  "access": {
60
130
  "type": "object",
61
131
  "title": "Access Descriptor",
62
- "required": ["protocol"],
132
+ "required": [
133
+ "protocol"
134
+ ],
63
135
  "properties": {
64
136
  "protocol": {
65
137
  "type": "string",
66
- "enum": ["mcp", "http", "cli", "acp"],
138
+ "enum": [
139
+ "mcp",
140
+ "http",
141
+ "cli",
142
+ "acp"
143
+ ],
67
144
  "description": "acp 只用于 kind=agent_runtime 的 Session 控制,与前三者不是一回事:MCP/CLI/HTTP 面向 Capability / Resource,ACP 面向 Agent Runtime / Session Control。"
68
145
  },
69
146
  "base_url": {
70
147
  "type": "string",
71
148
  "description": "protocol=http 时的服务基址。",
72
- "examples": ["http://scott-mac:7777/v1"]
149
+ "examples": [
150
+ "http://scott-mac:7777/v1"
151
+ ]
73
152
  },
74
153
  "endpoint": {
75
154
  "type": "string",
76
155
  "description": "protocol=http 时单个 capability 的相对路由。",
77
- "examples": ["GET /transcripts/:id"]
156
+ "examples": [
157
+ "GET /transcripts/:id"
158
+ ]
78
159
  },
79
160
  "tool": {
80
161
  "type": "string",
81
162
  "description": "protocol=mcp 时对应的 tool 名。",
82
- "examples": ["transcript_read"]
163
+ "examples": [
164
+ "transcript_read"
165
+ ]
83
166
  },
84
167
  "server": {
85
168
  "type": "string",
@@ -88,7 +171,10 @@
88
171
  "command": {
89
172
  "type": "string",
90
173
  "description": "protocol=cli 时的命令。",
91
- "examples": ["tingqi transcript get", "1session overview"]
174
+ "examples": [
175
+ "tingqi transcript get",
176
+ "1session overview"
177
+ ]
92
178
  }
93
179
  }
94
180
  }
@@ -96,11 +182,22 @@
96
182
  "examples": [
97
183
  {
98
184
  "id": "transcripts",
99
- "capabilities": ["transcript.read"],
185
+ "capabilities": [
186
+ "transcript.read"
187
+ ],
100
188
  "access": [
101
- { "protocol": "mcp", "tool": "transcript_read" },
102
- { "protocol": "http", "endpoint": "GET /transcripts/:id" },
103
- { "protocol": "cli", "command": "tingqi transcript get" }
189
+ {
190
+ "protocol": "mcp",
191
+ "tool": "transcript_read"
192
+ },
193
+ {
194
+ "protocol": "http",
195
+ "endpoint": "GET /transcripts/:id"
196
+ },
197
+ {
198
+ "protocol": "cli",
199
+ "command": "tingqi transcript get"
200
+ }
104
201
  ]
105
202
  },
106
203
  {
@@ -113,7 +210,11 @@
113
210
  "agent.session.status",
114
211
  "agent.session.resume"
115
212
  ],
116
- "access": [{ "protocol": "acp" }]
213
+ "access": [
214
+ {
215
+ "protocol": "acp"
216
+ }
217
+ ]
117
218
  }
118
219
  ]
119
220
  }