@ryuhq/sdk 0.1.14 → 0.2.2
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 +69 -7
- package/dist/action.cjs +839 -0
- package/dist/action.d.cts +88 -0
- package/dist/action.d.ts +88 -0
- package/dist/action.js +8 -0
- package/dist/agent-plugin.cjs +46 -0
- package/dist/agent-plugin.d.cts +43 -33
- package/dist/agent-plugin.d.ts +43 -33
- package/dist/agent-plugin.js +1 -1
- package/dist/agent.cjs +16 -0
- package/dist/agent.d.cts +377 -1
- package/dist/agent.d.ts +377 -1
- package/dist/agent.js +4 -2
- package/dist/app-B0Z9Ew_R.d.cts +141 -0
- package/dist/app-C-BDJwfG.d.ts +141 -0
- package/dist/builder.cjs +1194 -0
- package/dist/builder.d.cts +217 -0
- package/dist/builder.d.ts +217 -0
- package/dist/builder.js +29 -0
- package/dist/chunk-4TPUZDTI.js +94 -0
- package/dist/chunk-BC3A7HMO.js +164 -0
- package/dist/chunk-FZSFZOIN.js +200 -0
- package/dist/{chunk-ODFEUVPW.js → chunk-HACAGK65.js} +1 -18
- package/dist/chunk-HLKJZAFK.js +361 -0
- package/dist/chunk-IKEDLLFY.js +19 -0
- package/dist/{chunk-G6FLVEC4.js → chunk-JX6DDRXV.js} +46 -0
- package/dist/{chunk-AO2KJRDD.js → chunk-NZKVOSC2.js} +192 -3
- package/dist/chunk-QYFUNJOH.js +83 -0
- package/dist/chunk-SN2QBJUF.js +148 -0
- package/dist/chunk-TLDPEGC7.js +21 -0
- package/dist/chunk-TXSHHZF2.js +0 -0
- package/dist/chunk-VLIRNNAE.js +154 -0
- package/dist/{chunk-MTUBUPIV.js → chunk-Z57QDDJR.js} +8 -227
- package/dist/chunk-ZTJWBRUL.js +282 -0
- package/dist/cli.cjs +347 -18
- package/dist/cli.js +128 -23
- package/dist/client-D5U6ssPc.d.cts +84 -0
- package/dist/client-D5U6ssPc.d.ts +84 -0
- package/dist/index.cjs +810 -86
- package/dist/index.d.cts +19 -634
- package/dist/index.d.ts +19 -634
- package/dist/index.js +82 -699
- package/dist/manifest.cjs +200 -4
- package/dist/manifest.d.cts +260 -5
- package/dist/manifest.d.ts +260 -5
- package/dist/manifest.js +15 -1
- package/dist/mcp/client.cjs +180 -0
- package/dist/mcp/client.d.cts +49 -0
- package/dist/mcp/client.d.ts +49 -0
- package/dist/mcp/client.js +10 -0
- package/dist/mcp/server.cjs +370 -0
- package/dist/mcp/server.d.cts +127 -0
- package/dist/mcp/server.d.ts +127 -0
- package/dist/mcp/server.js +9 -0
- package/dist/mcp.cjs +376 -0
- package/dist/mcp.d.cts +2 -0
- package/dist/mcp.d.ts +2 -0
- package/dist/mcp.js +17 -0
- package/dist/model.cjs +141 -0
- package/dist/model.d.cts +33 -0
- package/dist/model.d.ts +33 -0
- package/dist/model.js +18 -0
- package/dist/plugin.cjs +46 -0
- package/dist/plugin.d.cts +215 -0
- package/dist/plugin.d.ts +215 -0
- package/dist/plugin.js +8 -0
- package/dist/runnable.cjs +1438 -0
- package/dist/runnable.d.cts +274 -0
- package/dist/runnable.d.ts +274 -0
- package/dist/runnable.js +34 -0
- package/dist/{index-B6SkaAjJ.d.ts → tool-AjkdFvhE.d.ts} +88 -461
- package/dist/{index-BvAB5eMk.d.cts → tool-CgzW92O_.d.cts} +88 -461
- package/package.json +48 -3
- package/src/agent/loop.test.ts +4 -4
- package/src/agent/tools.ts +3 -3
- package/src/agent-plugin.test.ts +58 -0
- package/src/agent-plugin.ts +109 -36
- package/src/builder.ts +9 -0
- package/src/cli/dev.test.ts +26 -47
- package/src/cli/dev.ts +10 -2
- package/src/cli-security.test.ts +109 -0
- package/src/cli.ts +141 -25
- package/src/contracts-lockstep.test.ts +16 -2
- package/src/exports-lockstep.test.ts +93 -0
- package/src/generated/plugin-manifest.ts +322 -29
- package/src/index.ts +53 -0
- package/src/manifest-schema.test.ts +30 -1
- package/src/manifest.fixtures.test.ts +22 -6
- package/src/manifest.test.ts +165 -10
- package/src/manifest.ts +454 -188
- package/src/mcp/index.ts +18 -0
- package/src/mcp/server.ts +2 -1
- package/src/model/index.ts +22 -0
- package/src/plugin/ryu-plugin.ts +82 -0
- package/src/runnable/action.test.ts +128 -0
- package/src/runnable/action.ts +202 -0
- package/src/runnable/app.test.ts +2 -0
- package/src/runnable/app.ts +50 -14
- package/src/runnable/index.ts +20 -3
- package/src/runnable/primitives.test.ts +34 -0
- package/src/runnable/primitives.ts +116 -0
- package/src/runnable/runnable-types.ts +3 -0
- package/src/runnable/tool.ts +36 -5
- package/src/runnable/turn-hook.ts +8 -3
- package/src/slash-command.test.ts +69 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PluginManifestSchema
|
|
3
|
+
} from "./chunk-NZKVOSC2.js";
|
|
4
|
+
|
|
5
|
+
// src/runnable/agent.ts
|
|
6
|
+
var CAPABILITY_SLOTS = ["rag", "memory", "tts", "stt"];
|
|
7
|
+
function lowerChatSlot(chat) {
|
|
8
|
+
if (chat === void 0) {
|
|
9
|
+
return {};
|
|
10
|
+
}
|
|
11
|
+
if (typeof chat === "string") {
|
|
12
|
+
return { model: chat };
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
model: chat.model,
|
|
16
|
+
engine: chat.engine,
|
|
17
|
+
persona: chat.persona,
|
|
18
|
+
modelPrefKey: chat.modelPrefKey
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function lowerCapabilitySlot(capability, slot, card) {
|
|
22
|
+
if (slot === void 0 || slot === false) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (slot === true) {
|
|
26
|
+
card.capabilities.push({ capability });
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (typeof slot === "string") {
|
|
30
|
+
card.capabilities.push({ capability });
|
|
31
|
+
card.providers[capability] = slot;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
card.capabilities.push(
|
|
35
|
+
slot.minVersion ? { capability, min_version: slot.minVersion } : { capability }
|
|
36
|
+
);
|
|
37
|
+
if (slot.provider) {
|
|
38
|
+
card.providers[capability] = slot.provider;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function lowerSlots(options) {
|
|
42
|
+
const card = {
|
|
43
|
+
...lowerChatSlot(options.chat),
|
|
44
|
+
capabilities: [],
|
|
45
|
+
providers: {},
|
|
46
|
+
tools: []
|
|
47
|
+
};
|
|
48
|
+
for (const capability of CAPABILITY_SLOTS) {
|
|
49
|
+
lowerCapabilitySlot(capability, options[capability], card);
|
|
50
|
+
}
|
|
51
|
+
for (const t of options.tools ?? []) {
|
|
52
|
+
card.tools.push(typeof t === "string" ? t : t.id);
|
|
53
|
+
}
|
|
54
|
+
return card;
|
|
55
|
+
}
|
|
56
|
+
function defaultRun(card) {
|
|
57
|
+
return async (input, ctx) => {
|
|
58
|
+
const content = typeof input === "string" ? input : JSON.stringify(input ?? "");
|
|
59
|
+
const messages = card.persona ? [
|
|
60
|
+
{ role: "system", content: card.persona },
|
|
61
|
+
{ role: "user", content }
|
|
62
|
+
] : [{ role: "user", content }];
|
|
63
|
+
const result = await ctx.gateway.chat(messages);
|
|
64
|
+
return result.content;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function cardConfig(card) {
|
|
68
|
+
const config = {};
|
|
69
|
+
if (card.model) {
|
|
70
|
+
config.model = card.model;
|
|
71
|
+
}
|
|
72
|
+
if (card.engine) {
|
|
73
|
+
config.engine = card.engine;
|
|
74
|
+
}
|
|
75
|
+
if (card.persona) {
|
|
76
|
+
config.persona = card.persona;
|
|
77
|
+
}
|
|
78
|
+
if (card.modelPrefKey) {
|
|
79
|
+
config.model_pref_key = card.modelPrefKey;
|
|
80
|
+
}
|
|
81
|
+
if (Object.keys(card.providers).length > 0) {
|
|
82
|
+
config.capability_providers = card.providers;
|
|
83
|
+
}
|
|
84
|
+
if (card.tools.length > 0) {
|
|
85
|
+
config.tools = card.tools;
|
|
86
|
+
}
|
|
87
|
+
return config;
|
|
88
|
+
}
|
|
89
|
+
function agentToManifest(agent, options) {
|
|
90
|
+
const config = cardConfig(agent.card);
|
|
91
|
+
const meta = {
|
|
92
|
+
id: agent.id,
|
|
93
|
+
name: agent.name,
|
|
94
|
+
kind: "agent",
|
|
95
|
+
...Object.keys(config).length > 0 ? { config } : {}
|
|
96
|
+
};
|
|
97
|
+
const hasRequires = agent.card.capabilities.length > 0 || (options.grants?.length ?? 0) > 0;
|
|
98
|
+
const raw = {
|
|
99
|
+
id: options.id,
|
|
100
|
+
name: options.name ?? agent.name,
|
|
101
|
+
version: options.version,
|
|
102
|
+
runnables: [meta],
|
|
103
|
+
...hasRequires ? {
|
|
104
|
+
requires: {
|
|
105
|
+
apps: [],
|
|
106
|
+
capabilities: agent.card.capabilities,
|
|
107
|
+
grants: options.grants ?? []
|
|
108
|
+
}
|
|
109
|
+
} : {}
|
|
110
|
+
};
|
|
111
|
+
const result = PluginManifestSchema.safeParse(raw);
|
|
112
|
+
if (!result.success) {
|
|
113
|
+
const first = result.error.issues[0];
|
|
114
|
+
const field = first?.path.join(".") ?? "unknown";
|
|
115
|
+
const message = first?.message ?? "validation failed";
|
|
116
|
+
throw new Error(
|
|
117
|
+
`agent manifest validation failed at '${field}': ${message}`
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
return result.data;
|
|
121
|
+
}
|
|
122
|
+
function defineAgent(options) {
|
|
123
|
+
const { id, name } = options;
|
|
124
|
+
const card = lowerSlots(options);
|
|
125
|
+
const run = options.run ?? defaultRun(card);
|
|
126
|
+
return {
|
|
127
|
+
id,
|
|
128
|
+
name,
|
|
129
|
+
kind: "agent",
|
|
130
|
+
run,
|
|
131
|
+
card,
|
|
132
|
+
toManifest(manifestOptions) {
|
|
133
|
+
return agentToManifest(this, manifestOptions);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// src/runnable/skill.ts
|
|
139
|
+
function defineSkill(options) {
|
|
140
|
+
const { id, name, run } = options;
|
|
141
|
+
return {
|
|
142
|
+
id,
|
|
143
|
+
name,
|
|
144
|
+
kind: "skill",
|
|
145
|
+
run
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/runnable/workflow.ts
|
|
150
|
+
function defineWorkflow(options) {
|
|
151
|
+
const { id, name, run } = options;
|
|
152
|
+
return {
|
|
153
|
+
id,
|
|
154
|
+
name,
|
|
155
|
+
kind: "workflow",
|
|
156
|
+
run
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export {
|
|
161
|
+
defineAgent,
|
|
162
|
+
defineSkill,
|
|
163
|
+
defineWorkflow
|
|
164
|
+
};
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MCP_PROTOCOL_VERSION,
|
|
3
|
+
callTool,
|
|
4
|
+
listTools
|
|
5
|
+
} from "./chunk-VLIRNNAE.js";
|
|
6
|
+
|
|
7
|
+
// src/mcp/server.ts
|
|
8
|
+
import { createInterface } from "readline";
|
|
9
|
+
function respond(id, result) {
|
|
10
|
+
return { jsonrpc: "2.0", id: id ?? null, result };
|
|
11
|
+
}
|
|
12
|
+
function respondError(id, code, message) {
|
|
13
|
+
return { jsonrpc: "2.0", id: id ?? null, error: { code, message } };
|
|
14
|
+
}
|
|
15
|
+
function wrapContent(value) {
|
|
16
|
+
return {
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: "text",
|
|
20
|
+
text: typeof value === "string" ? value : JSON.stringify(value)
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function unwrapContent(raw) {
|
|
26
|
+
const r = raw;
|
|
27
|
+
const text = r?.content?.[0]?.text;
|
|
28
|
+
if (text === void 0) {
|
|
29
|
+
return raw;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
return JSON.parse(text);
|
|
33
|
+
} catch {
|
|
34
|
+
return text;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
var McpServer = class {
|
|
38
|
+
runnables = /* @__PURE__ */ new Map();
|
|
39
|
+
passthroughs = [];
|
|
40
|
+
/**
|
|
41
|
+
* Register an SDK Runnable as an MCP tool.
|
|
42
|
+
* Returns `this` for chaining.
|
|
43
|
+
*/
|
|
44
|
+
register(runnable) {
|
|
45
|
+
this.runnables.set(runnable.name, runnable);
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Register a passthrough to an external MCP stdio server (e.g. Ghost or
|
|
50
|
+
* Shadow). Tools from that server are fetched lazily and re-advertised.
|
|
51
|
+
* Returns `this` for chaining.
|
|
52
|
+
*/
|
|
53
|
+
passthrough(registration) {
|
|
54
|
+
this.passthroughs.push(registration);
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
/** Fetch all tools: local Runnables + passthrough tools. */
|
|
58
|
+
async allTools() {
|
|
59
|
+
const local = [...this.runnables.values()].map((r) => ({
|
|
60
|
+
name: r.name,
|
|
61
|
+
description: r.description,
|
|
62
|
+
inputSchema: r.inputSchema
|
|
63
|
+
}));
|
|
64
|
+
const remote = [];
|
|
65
|
+
for (const pt of this.passthroughs) {
|
|
66
|
+
try {
|
|
67
|
+
const tools = await listTools(pt.command);
|
|
68
|
+
remote.push(...tools);
|
|
69
|
+
} catch (err) {
|
|
70
|
+
process.stderr.write(
|
|
71
|
+
`[mcp-server] passthrough '${pt.label}' list_tools failed: ${err}
|
|
72
|
+
`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return [...local, ...remote];
|
|
77
|
+
}
|
|
78
|
+
/** Handle a `tools/call` request. */
|
|
79
|
+
async handleCallTool(name, args) {
|
|
80
|
+
const local = this.runnables.get(name);
|
|
81
|
+
if (local) {
|
|
82
|
+
const result = await local.run(args);
|
|
83
|
+
return wrapContent(result);
|
|
84
|
+
}
|
|
85
|
+
for (const pt of this.passthroughs) {
|
|
86
|
+
try {
|
|
87
|
+
const tools = await listTools(pt.command);
|
|
88
|
+
if (tools.some((t) => t.name === name)) {
|
|
89
|
+
return await callTool(pt.command, name, args);
|
|
90
|
+
}
|
|
91
|
+
} catch {
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Handle a single parsed JSON-RPC request line. Returns the response to write
|
|
98
|
+
* (or null for notifications that require no response).
|
|
99
|
+
*/
|
|
100
|
+
async handleRequest(req, initialized, write) {
|
|
101
|
+
const { id, method, params } = req;
|
|
102
|
+
if (method === "initialize") {
|
|
103
|
+
initialized.value = true;
|
|
104
|
+
write(
|
|
105
|
+
respond(id, {
|
|
106
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
107
|
+
capabilities: { tools: {} },
|
|
108
|
+
serverInfo: { name: "ryu-sdk-server", version: "0.0.1" }
|
|
109
|
+
})
|
|
110
|
+
);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (method === "notifications/initialized") {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (!initialized.value) {
|
|
117
|
+
write(respondError(id, -32002, "Server not initialized"));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (method === "tools/list") {
|
|
121
|
+
try {
|
|
122
|
+
const tools = await this.allTools();
|
|
123
|
+
write(respond(id, { tools }));
|
|
124
|
+
} catch (err) {
|
|
125
|
+
write(respondError(id, -32603, String(err)));
|
|
126
|
+
}
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (method === "tools/call") {
|
|
130
|
+
await this.handleToolsCall(id, params, write);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
write(respondError(id, -32601, `Method not found: ${method}`));
|
|
134
|
+
}
|
|
135
|
+
/** Handle a `tools/call` JSON-RPC request. */
|
|
136
|
+
async handleToolsCall(id, params, write) {
|
|
137
|
+
const p = params;
|
|
138
|
+
const toolName = p?.name;
|
|
139
|
+
const toolArgs = p?.arguments ?? {};
|
|
140
|
+
if (typeof toolName !== "string") {
|
|
141
|
+
write(respondError(id, -32602, "tools/call requires 'name'"));
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
const result = await this.handleCallTool(toolName, toolArgs);
|
|
146
|
+
write(respond(id, result));
|
|
147
|
+
} catch (err) {
|
|
148
|
+
write(
|
|
149
|
+
respond(id, {
|
|
150
|
+
content: [{ type: "text", text: String(err) }],
|
|
151
|
+
isError: true
|
|
152
|
+
})
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Start reading JSON-RPC requests from the given readable stream and writing
|
|
158
|
+
* responses to the given writable stream.
|
|
159
|
+
*
|
|
160
|
+
* Defaults to `process.stdin` / `process.stdout`. Passing explicit streams
|
|
161
|
+
* lets tests inject a pair of in-process pipes.
|
|
162
|
+
*
|
|
163
|
+
* Resolves when the input stream ends (EOF).
|
|
164
|
+
*/
|
|
165
|
+
serve(input = process.stdin, output = process.stdout) {
|
|
166
|
+
const write = (obj) => {
|
|
167
|
+
output.write(`${JSON.stringify(obj)}
|
|
168
|
+
`);
|
|
169
|
+
};
|
|
170
|
+
const initialized = { value: false };
|
|
171
|
+
return new Promise((resolve) => {
|
|
172
|
+
const rl = createInterface({
|
|
173
|
+
input,
|
|
174
|
+
crlfDelay: Number.POSITIVE_INFINITY
|
|
175
|
+
});
|
|
176
|
+
rl.on("line", (rawLine) => {
|
|
177
|
+
const line = rawLine.trim();
|
|
178
|
+
if (!line) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
let req;
|
|
182
|
+
try {
|
|
183
|
+
req = JSON.parse(line);
|
|
184
|
+
} catch {
|
|
185
|
+
write(respondError(null, -32700, "Parse error"));
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
this.handleRequest(req, initialized, write).catch((err) => {
|
|
189
|
+
write(respondError(req.id, -32603, String(err)));
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
rl.on("close", resolve);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
export {
|
|
198
|
+
unwrapContent,
|
|
199
|
+
McpServer
|
|
200
|
+
};
|
|
@@ -77,24 +77,7 @@ function defineModel(modelId, options = {}) {
|
|
|
77
77
|
return new ModelClient2(modelId, options);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
// src/model/gateway.ts
|
|
81
|
-
import * as native2 from "@ryuhq/sdk-native";
|
|
82
|
-
var DEFAULT_GATEWAY_URL = "http://127.0.0.1:7981";
|
|
83
|
-
function resolveGatewayUrl3() {
|
|
84
|
-
return native2.resolveGatewayUrl();
|
|
85
|
-
}
|
|
86
|
-
function resolveGatewayToken2() {
|
|
87
|
-
return native2.resolveGatewayToken() ?? void 0;
|
|
88
|
-
}
|
|
89
|
-
function assertAllowedEgressUrl(baseUrl) {
|
|
90
|
-
native2.assertAllowedEgress(baseUrl);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
80
|
export {
|
|
94
81
|
ModelClient2 as ModelClient,
|
|
95
|
-
defineModel
|
|
96
|
-
DEFAULT_GATEWAY_URL,
|
|
97
|
-
resolveGatewayUrl3 as resolveGatewayUrl,
|
|
98
|
-
resolveGatewayToken2 as resolveGatewayToken,
|
|
99
|
-
assertAllowedEgressUrl
|
|
82
|
+
defineModel
|
|
100
83
|
};
|