@flowy-agent-store/sdk 0.1.0-beta.4 → 0.1.0-beta.6
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 +14 -11
- package/dist/index.cjs +16 -8
- package/dist/index.d.cts +36 -7
- package/dist/index.d.mts +36 -7
- package/dist/index.mjs +16 -8
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -3,32 +3,35 @@
|
|
|
3
3
|
Node.js host for the Agent Store runtime (`docs/agent-store/12-sdk-packaging.md P1-3`): spawn `agent-store`, wait for its stdout readiness line, connect over loopback with `@flowy-agent-store/client`.
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
|
-
import {
|
|
6
|
+
import { launchHarness } from "@flowy-agent-store/sdk";
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const harness = await launchHarness({
|
|
9
9
|
client: { name: "my-app", version: "0.1.0" },
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
// 获取:浏览 / 搜索目录(含每个条目的安装状态)
|
|
13
|
-
const items = await
|
|
13
|
+
const items = await harness.store.search("software");
|
|
14
14
|
|
|
15
15
|
// 安装:导入 + 注册,并等到组件真的可用(默认 waitForReady: true)
|
|
16
|
-
const outcome = await
|
|
16
|
+
const outcome = await harness.store.install(items[0]);
|
|
17
17
|
if (outcome.readyIssue === "authorization_required") {
|
|
18
|
-
await
|
|
18
|
+
await harness.connectors.authStart(outcome.readyComponentId!);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
// 禁用 / 启用:连接器改 mcp_servers.enabled,专家/专家团改 Preset.enabled
|
|
22
|
-
await
|
|
22
|
+
await harness.store.setEnabled(items[0], false);
|
|
23
23
|
|
|
24
24
|
// 卸载:真的释放运行时产物(技能目录 / Preset / MCP server 行),再清记录
|
|
25
|
-
const released = await
|
|
25
|
+
const released = await harness.store.uninstall(items[0]);
|
|
26
26
|
if (!released.ok) console.warn(released.components.filter((c) => !c.ok));
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
// 一次 close 收掉传输与子进程(退订 → 关传输 → 杀进程 → 删临时 data-dir)
|
|
29
|
+
await harness.close();
|
|
29
30
|
```
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
**`launchHarness` 解析出的对象就是那个 client**(`docs/agent-store/31` §5 方案 B):`harness.store` / `harness.conversations` / `harness.models` 直接可用,没有 `.client` 一跳;子进程是 `harness.server`(`readiness` / `dataDir` / `exited`),握手响应是 `harness.handshake`。
|
|
33
|
+
|
|
34
|
+
五个动词都在 SDK 里可用,但**它们不是 `@flowy-agent-store/sdk` 自己实现的**:本包只负责进程与传输,返回的对象就是一个 `@flowy-agent-store/client` 的 `AppServerClient`(sdk 另挂 `server` / `handshake` / `close()`),其中 `store` 子客户端把 `install` / `uninstall` / `setEnabled` 编排成一条状态机(`search → install → … → uninstall`)。这样分层是刻意的——见 `docs/agent-store/12-sdk-packaging.md` §2 的职责划分。
|
|
32
35
|
|
|
33
36
|
几条使用上的事实(都是实测结论,不是约定):
|
|
34
37
|
|
|
@@ -44,7 +47,7 @@ await session.close();
|
|
|
44
47
|
- 工具面不用改宿主自己的 `~/.agent-store/config.toml`:`env.AGENT_STORE_TOOLS` 直接指定,值是 JSON(形状同 `[tools]` 表),**整份替换**文件里的策略,`{}` = 全开。它只在 Store 宿主生效(桌面 / Web 宿主不采纳 `[tools]`),且子进程启动时读一次。
|
|
45
48
|
|
|
46
49
|
```ts
|
|
47
|
-
const
|
|
50
|
+
const harness = await launchHarness({
|
|
48
51
|
client: { name: "my-app", version: "0.1.0" },
|
|
49
52
|
env: {
|
|
50
53
|
// 只要基础能力:关掉桌面控制/浏览器与几个域
|
|
@@ -61,4 +64,4 @@ await session.close();
|
|
|
61
64
|
- 二进制定位:`bin` 参数 → `AGENT_STORE_BIN` → 平台 runtime 包的 `vendor/` → `PATH`;找不到直接报错(**不下载**,见 P2)。
|
|
62
65
|
- 就绪行 `protocol_version` 与 SDK 不一致时杀掉子进程并报错(含两端版本)。该值是**契约指纹**,不是版本号:任何 wire 变更都会 bump。
|
|
63
66
|
|
|
64
|
-
不在本包范围内(`07-typescript-sdk.md` §非目标):`config/*` 与 `skill/*` 写面。它们的**类型**在 `@flowy-agent-store/protocol`(wire 上存在的方法就有形状),但**没有** typed 方法——因为这些面跟着宿主自己的设置文件与技能目录走,是最易变的部分。这是可发现性边界,不是权限边界:`
|
|
67
|
+
不在本包范围内(`07-typescript-sdk.md` §非目标):`config/*` 与 `skill/*` 写面。它们的**类型**在 `@flowy-agent-store/protocol`(wire 上存在的方法就有形状),但**没有** typed 方法——因为这些面跟着宿主自己的设置文件与技能目录走,是最易变的部分。这是可发现性边界,不是权限边界:`harness.transport` 是公开的,服务端按磁盘归属判定可写性。要用就直连 `transport.request`,并自担变动。
|
package/dist/index.cjs
CHANGED
|
@@ -260,13 +260,21 @@ function waitForReadiness(child, timeoutMs) {
|
|
|
260
260
|
/**
|
|
261
261
|
* `@flowy-agent-store/sdk` — spawn the runtime, connect over loopback, hand back
|
|
262
262
|
* a ready `AppServerClient`.
|
|
263
|
+
*
|
|
264
|
+
* The object `launchHarness` resolves to **is** that client (doc `31`): the
|
|
265
|
+
* `conversations` / `store` / `agents` surface sits on it directly, and the
|
|
266
|
+
* process it owns is reachable as `server` / `handshake` / `close()`. That is
|
|
267
|
+
* the shape both external references use — Codex's
|
|
268
|
+
* `with Codex(...) as codex: codex.thread_start(...)` and Kimi Code's
|
|
269
|
+
* `const harness = createKimiHarness(...); harness.createSession(...)` — the
|
|
270
|
+
* factory returns the main object, lifecycle included, with no `.client` hop.
|
|
263
271
|
*/
|
|
264
272
|
/**
|
|
265
273
|
* Spawn a loopback runtime with its own data dir and return a connected,
|
|
266
274
|
* initialized client. Rejects non-loopback contact outright (P0-4): this
|
|
267
275
|
* entry point only ever dials the process it just spawned.
|
|
268
276
|
*/
|
|
269
|
-
async function
|
|
277
|
+
async function launchHarness(options) {
|
|
270
278
|
const server = await spawnAppServer(options);
|
|
271
279
|
const wsUrl = `ws://${server.readiness.host}:${server.readiness.port}/api/app-server/ws`;
|
|
272
280
|
if (!(0, _flowy_agent_store_client.isLoopbackUrl)(wsUrl)) {
|
|
@@ -281,20 +289,20 @@ async function launchClient(options) {
|
|
|
281
289
|
client: options.client,
|
|
282
290
|
capabilities: options.capabilities
|
|
283
291
|
});
|
|
292
|
+
const closeTransport = client.close.bind(client);
|
|
284
293
|
try {
|
|
285
|
-
const
|
|
294
|
+
const handshake = await client.connect();
|
|
286
295
|
let closed = false;
|
|
287
|
-
return {
|
|
296
|
+
return Object.assign(client, {
|
|
288
297
|
server,
|
|
289
|
-
|
|
290
|
-
initializeResult,
|
|
298
|
+
handshake,
|
|
291
299
|
close: async () => {
|
|
292
300
|
if (closed) return;
|
|
293
301
|
closed = true;
|
|
294
|
-
|
|
302
|
+
closeTransport();
|
|
295
303
|
await server.close();
|
|
296
304
|
}
|
|
297
|
-
};
|
|
305
|
+
});
|
|
298
306
|
} catch (error) {
|
|
299
307
|
client.close();
|
|
300
308
|
await server.close();
|
|
@@ -303,7 +311,7 @@ async function launchClient(options) {
|
|
|
303
311
|
}
|
|
304
312
|
//#endregion
|
|
305
313
|
exports.assertProtocolCompatible = assertProtocolCompatible;
|
|
306
|
-
exports.
|
|
314
|
+
exports.launchHarness = launchHarness;
|
|
307
315
|
exports.parseReadinessLine = parseReadinessLine;
|
|
308
316
|
exports.resolveAppServerBin = resolveAppServerBin;
|
|
309
317
|
exports.spawnAppServer = spawnAppServer;
|
package/dist/index.d.cts
CHANGED
|
@@ -65,17 +65,46 @@ interface SpawnedServer {
|
|
|
65
65
|
export declare function spawnAppServer(options?: SpawnOptions): Promise<SpawnedServer>;
|
|
66
66
|
//#endregion
|
|
67
67
|
//#region src/index.d.ts
|
|
68
|
-
export interface
|
|
68
|
+
export interface HarnessOptions extends SpawnOptions {
|
|
69
69
|
client: ClientInfo;
|
|
70
70
|
capabilities?: ClientCapabilities;
|
|
71
71
|
token?: string;
|
|
72
72
|
requestTimeoutMs?: number;
|
|
73
73
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
/**
|
|
75
|
+
* A connected `AppServerClient` that **owns the runtime process it spawned**
|
|
76
|
+
* (doc `31` §5 方案 B).
|
|
77
|
+
*
|
|
78
|
+
* Every `AppServerClient` member is available directly — `conversations`,
|
|
79
|
+
* `store`, `agents`, `onNotification`, … — because a factory that returned a
|
|
80
|
+
* *wrapper* was the lie this shape removes.
|
|
81
|
+
*
|
|
82
|
+
* Named after the external reference this shape follows (doc `31` §3.2):
|
|
83
|
+
* Kimi Code's `const harness = createKimiHarness(...)` hands back a `harness`
|
|
84
|
+
* you keep for the whole life of the run, not a one-shot launcher.
|
|
85
|
+
*/
|
|
86
|
+
export interface Harness extends AppServerClient {
|
|
87
|
+
/** The child process: `readiness` / `dataDir` / `exited` / `close`. */
|
|
88
|
+
readonly server: SpawnedServer;
|
|
89
|
+
/**
|
|
90
|
+
* The handshake response captured at launch (**never null**).
|
|
91
|
+
*
|
|
92
|
+
* Not named `initializeResult`: that is a private field of the base class
|
|
93
|
+
* (`client.ts`), and the base's public `initializeInfo` is the *current*
|
|
94
|
+
* connection state — it goes back to `null` after `close()`. This member is
|
|
95
|
+
* the snapshot that proves which protocol fingerprint the session was
|
|
96
|
+
* admitted under.
|
|
97
|
+
*/
|
|
98
|
+
readonly handshake: InitializeResult;
|
|
99
|
+
/**
|
|
100
|
+
* Unsubscribe → close the transport → terminate the child → remove an
|
|
101
|
+
* auto-created data dir. Idempotent.
|
|
102
|
+
*
|
|
103
|
+
* Deliberately widens the base's synchronous `close(): void`: awaiting a
|
|
104
|
+
* void-returning call is legal, so callers holding a plain `AppServerClient`
|
|
105
|
+
* are unaffected, while a launched session needs the promise to know the
|
|
106
|
+
* process is actually gone.
|
|
107
|
+
*/
|
|
79
108
|
close(): Promise<void>;
|
|
80
109
|
}
|
|
81
110
|
/**
|
|
@@ -83,6 +112,6 @@ export interface LaunchedClient {
|
|
|
83
112
|
* initialized client. Rejects non-loopback contact outright (P0-4): this
|
|
84
113
|
* entry point only ever dials the process it just spawned.
|
|
85
114
|
*/
|
|
86
|
-
export declare function
|
|
115
|
+
export declare function launchHarness(options: HarnessOptions): Promise<Harness>;
|
|
87
116
|
//#endregion
|
|
88
117
|
export type { ReadinessInfo, SpawnExitInfo, SpawnOptions, SpawnedServer };
|
package/dist/index.d.mts
CHANGED
|
@@ -65,17 +65,46 @@ interface SpawnedServer {
|
|
|
65
65
|
export declare function spawnAppServer(options?: SpawnOptions): Promise<SpawnedServer>;
|
|
66
66
|
//#endregion
|
|
67
67
|
//#region src/index.d.ts
|
|
68
|
-
export interface
|
|
68
|
+
export interface HarnessOptions extends SpawnOptions {
|
|
69
69
|
client: ClientInfo;
|
|
70
70
|
capabilities?: ClientCapabilities;
|
|
71
71
|
token?: string;
|
|
72
72
|
requestTimeoutMs?: number;
|
|
73
73
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
/**
|
|
75
|
+
* A connected `AppServerClient` that **owns the runtime process it spawned**
|
|
76
|
+
* (doc `31` §5 方案 B).
|
|
77
|
+
*
|
|
78
|
+
* Every `AppServerClient` member is available directly — `conversations`,
|
|
79
|
+
* `store`, `agents`, `onNotification`, … — because a factory that returned a
|
|
80
|
+
* *wrapper* was the lie this shape removes.
|
|
81
|
+
*
|
|
82
|
+
* Named after the external reference this shape follows (doc `31` §3.2):
|
|
83
|
+
* Kimi Code's `const harness = createKimiHarness(...)` hands back a `harness`
|
|
84
|
+
* you keep for the whole life of the run, not a one-shot launcher.
|
|
85
|
+
*/
|
|
86
|
+
export interface Harness extends AppServerClient {
|
|
87
|
+
/** The child process: `readiness` / `dataDir` / `exited` / `close`. */
|
|
88
|
+
readonly server: SpawnedServer;
|
|
89
|
+
/**
|
|
90
|
+
* The handshake response captured at launch (**never null**).
|
|
91
|
+
*
|
|
92
|
+
* Not named `initializeResult`: that is a private field of the base class
|
|
93
|
+
* (`client.ts`), and the base's public `initializeInfo` is the *current*
|
|
94
|
+
* connection state — it goes back to `null` after `close()`. This member is
|
|
95
|
+
* the snapshot that proves which protocol fingerprint the session was
|
|
96
|
+
* admitted under.
|
|
97
|
+
*/
|
|
98
|
+
readonly handshake: InitializeResult;
|
|
99
|
+
/**
|
|
100
|
+
* Unsubscribe → close the transport → terminate the child → remove an
|
|
101
|
+
* auto-created data dir. Idempotent.
|
|
102
|
+
*
|
|
103
|
+
* Deliberately widens the base's synchronous `close(): void`: awaiting a
|
|
104
|
+
* void-returning call is legal, so callers holding a plain `AppServerClient`
|
|
105
|
+
* are unaffected, while a launched session needs the promise to know the
|
|
106
|
+
* process is actually gone.
|
|
107
|
+
*/
|
|
79
108
|
close(): Promise<void>;
|
|
80
109
|
}
|
|
81
110
|
/**
|
|
@@ -83,6 +112,6 @@ export interface LaunchedClient {
|
|
|
83
112
|
* initialized client. Rejects non-loopback contact outright (P0-4): this
|
|
84
113
|
* entry point only ever dials the process it just spawned.
|
|
85
114
|
*/
|
|
86
|
-
export declare function
|
|
115
|
+
export declare function launchHarness(options: HarnessOptions): Promise<Harness>;
|
|
87
116
|
//#endregion
|
|
88
117
|
export type { ReadinessInfo, SpawnExitInfo, SpawnOptions, SpawnedServer };
|
package/dist/index.mjs
CHANGED
|
@@ -259,13 +259,21 @@ function waitForReadiness(child, timeoutMs) {
|
|
|
259
259
|
/**
|
|
260
260
|
* `@flowy-agent-store/sdk` — spawn the runtime, connect over loopback, hand back
|
|
261
261
|
* a ready `AppServerClient`.
|
|
262
|
+
*
|
|
263
|
+
* The object `launchHarness` resolves to **is** that client (doc `31`): the
|
|
264
|
+
* `conversations` / `store` / `agents` surface sits on it directly, and the
|
|
265
|
+
* process it owns is reachable as `server` / `handshake` / `close()`. That is
|
|
266
|
+
* the shape both external references use — Codex's
|
|
267
|
+
* `with Codex(...) as codex: codex.thread_start(...)` and Kimi Code's
|
|
268
|
+
* `const harness = createKimiHarness(...); harness.createSession(...)` — the
|
|
269
|
+
* factory returns the main object, lifecycle included, with no `.client` hop.
|
|
262
270
|
*/
|
|
263
271
|
/**
|
|
264
272
|
* Spawn a loopback runtime with its own data dir and return a connected,
|
|
265
273
|
* initialized client. Rejects non-loopback contact outright (P0-4): this
|
|
266
274
|
* entry point only ever dials the process it just spawned.
|
|
267
275
|
*/
|
|
268
|
-
async function
|
|
276
|
+
async function launchHarness(options) {
|
|
269
277
|
const server = await spawnAppServer(options);
|
|
270
278
|
const wsUrl = `ws://${server.readiness.host}:${server.readiness.port}/api/app-server/ws`;
|
|
271
279
|
if (!isLoopbackUrl(wsUrl)) {
|
|
@@ -280,20 +288,20 @@ async function launchClient(options) {
|
|
|
280
288
|
client: options.client,
|
|
281
289
|
capabilities: options.capabilities
|
|
282
290
|
});
|
|
291
|
+
const closeTransport = client.close.bind(client);
|
|
283
292
|
try {
|
|
284
|
-
const
|
|
293
|
+
const handshake = await client.connect();
|
|
285
294
|
let closed = false;
|
|
286
|
-
return {
|
|
295
|
+
return Object.assign(client, {
|
|
287
296
|
server,
|
|
288
|
-
|
|
289
|
-
initializeResult,
|
|
297
|
+
handshake,
|
|
290
298
|
close: async () => {
|
|
291
299
|
if (closed) return;
|
|
292
300
|
closed = true;
|
|
293
|
-
|
|
301
|
+
closeTransport();
|
|
294
302
|
await server.close();
|
|
295
303
|
}
|
|
296
|
-
};
|
|
304
|
+
});
|
|
297
305
|
} catch (error) {
|
|
298
306
|
client.close();
|
|
299
307
|
await server.close();
|
|
@@ -301,4 +309,4 @@ async function launchClient(options) {
|
|
|
301
309
|
}
|
|
302
310
|
}
|
|
303
311
|
//#endregion
|
|
304
|
-
export { assertProtocolCompatible,
|
|
312
|
+
export { assertProtocolCompatible, launchHarness, parseReadinessLine, resolveAppServerBin, spawnAppServer };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowy-agent-store/sdk",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.6",
|
|
4
4
|
"description": "Node.js host for the Agent Store App Server: spawn the runtime binary and connect over loopback (docs/agent-store/12 P1-3)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"dist"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@flowy-agent-store/client": "0.1.0-beta.
|
|
29
|
-
"@flowy-agent-store/protocol": "0.1.0-beta.
|
|
28
|
+
"@flowy-agent-store/client": "0.1.0-beta.6",
|
|
29
|
+
"@flowy-agent-store/protocol": "0.1.0-beta.6"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "tsdown",
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
"module": "./dist/index.mjs",
|
|
41
41
|
"types": "./dist/index.d.mts",
|
|
42
42
|
"optionalDependencies": {
|
|
43
|
-
"@flowy-agent-store/runtime-win32-x64": "0.1.0-beta.
|
|
44
|
-
"@flowy-agent-store/runtime-linux-x64": "0.1.0-beta.
|
|
45
|
-
"@flowy-agent-store/runtime-linux-arm64": "0.1.0-beta.
|
|
46
|
-
"@flowy-agent-store/runtime-darwin-x64": "0.1.0-beta.
|
|
47
|
-
"@flowy-agent-store/runtime-darwin-arm64": "0.1.0-beta.
|
|
43
|
+
"@flowy-agent-store/runtime-win32-x64": "0.1.0-beta.6",
|
|
44
|
+
"@flowy-agent-store/runtime-linux-x64": "0.1.0-beta.6",
|
|
45
|
+
"@flowy-agent-store/runtime-linux-arm64": "0.1.0-beta.6",
|
|
46
|
+
"@flowy-agent-store/runtime-darwin-x64": "0.1.0-beta.6",
|
|
47
|
+
"@flowy-agent-store/runtime-darwin-arm64": "0.1.0-beta.6"
|
|
48
48
|
}
|
|
49
49
|
}
|