@ryuhq/sdk 0.0.5

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 (61) hide show
  1. package/LICENSE +179 -0
  2. package/README.md +31 -0
  3. package/dist/agent.cjs +761 -0
  4. package/dist/agent.d.cts +3 -0
  5. package/dist/agent.d.ts +3 -0
  6. package/dist/agent.js +23 -0
  7. package/dist/chunk-GXHL5CO7.js +353 -0
  8. package/dist/chunk-KPKMMGVC.js +671 -0
  9. package/dist/chunk-ODFEUVPW.js +100 -0
  10. package/dist/cli.cjs +858 -0
  11. package/dist/cli.d.cts +1 -0
  12. package/dist/cli.d.ts +1 -0
  13. package/dist/cli.js +454 -0
  14. package/dist/index-CEbS1SlS.d.cts +988 -0
  15. package/dist/index-DAxq7Y0R.d.ts +988 -0
  16. package/dist/index.cjs +1900 -0
  17. package/dist/index.d.cts +759 -0
  18. package/dist/index.d.ts +759 -0
  19. package/dist/index.js +771 -0
  20. package/dist/manifest.cjs +399 -0
  21. package/dist/manifest.d.cts +355 -0
  22. package/dist/manifest.d.ts +355 -0
  23. package/dist/manifest.js +38 -0
  24. package/package.json +56 -0
  25. package/src/agent/agent.ts +208 -0
  26. package/src/agent/index.ts +51 -0
  27. package/src/agent/loop.test.ts +261 -0
  28. package/src/agent/loop.ts +259 -0
  29. package/src/agent/model-call.ts +190 -0
  30. package/src/agent/query.ts +40 -0
  31. package/src/agent/tools.ts +295 -0
  32. package/src/builder.ts +473 -0
  33. package/src/cli/dev.test.ts +178 -0
  34. package/src/cli/dev.ts +425 -0
  35. package/src/cli.ts +390 -0
  36. package/src/contracts-lockstep.test.ts +77 -0
  37. package/src/generated/plugin-manifest.ts +1121 -0
  38. package/src/index.ts +141 -0
  39. package/src/manifest.test.ts +610 -0
  40. package/src/manifest.ts +589 -0
  41. package/src/mcp/bridge.test.ts +196 -0
  42. package/src/mcp/client.ts +253 -0
  43. package/src/mcp/fixture-server.ts +23 -0
  44. package/src/mcp/server.ts +351 -0
  45. package/src/model/client.test.ts +107 -0
  46. package/src/model/client.ts +179 -0
  47. package/src/model/gateway.ts +41 -0
  48. package/src/plugin/ryu-plugin.ts +191 -0
  49. package/src/runnable/agent.ts +338 -0
  50. package/src/runnable/app.ts +233 -0
  51. package/src/runnable/index.ts +61 -0
  52. package/src/runnable/primitives-hostapi.test.ts +73 -0
  53. package/src/runnable/primitives.test.ts +286 -0
  54. package/src/runnable/primitives.ts +610 -0
  55. package/src/runnable/runnable-types.ts +113 -0
  56. package/src/runnable/runnable.test.ts +397 -0
  57. package/src/runnable/skill.ts +60 -0
  58. package/src/runnable/tool.ts +260 -0
  59. package/src/runnable/turn-hook.test.ts +81 -0
  60. package/src/runnable/turn-hook.ts +191 -0
  61. package/src/runnable/workflow.ts +76 -0
@@ -0,0 +1,355 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * Ryu SDK manifest types — TypeScript mirror of the Core `plugin_manifest` and
5
+ * `runnable` schemas (`apps/core/src/plugin_manifest/mod.rs` and
6
+ * `apps/core/src/runnable/mod.rs`).
7
+ *
8
+ * These types must stay in sync with the Rust serde shapes so that a manifest
9
+ * authored here deserialises cleanly by `PluginManifestLoader::load()` in Core.
10
+ *
11
+ * Design note on engine/model fields: every field that holds an engine name,
12
+ * model id, or provider reference is typed as `string` — never a union of
13
+ * known provider literals. A new provider must never require an SDK change.
14
+ */
15
+
16
+ /**
17
+ * The kind of a Runnable. Mirrors `RunnableKind` in
18
+ * `apps/core/src/runnable/mod.rs`.
19
+ */
20
+ declare const RunnableKindSchema: z.ZodEnum<{
21
+ agent: "agent";
22
+ workflow: "workflow";
23
+ tool: "tool";
24
+ skill: "skill";
25
+ companion: "companion";
26
+ }>;
27
+ type RunnableKind = z.infer<typeof RunnableKindSchema>;
28
+ /**
29
+ * Kind-agnostic identity snapshot of a Runnable. Mirrors `RunnableMeta` in
30
+ * `apps/core/src/runnable/mod.rs`.
31
+ */
32
+ declare const RunnableMetaSchema: z.ZodObject<{
33
+ id: z.ZodString;
34
+ name: z.ZodString;
35
+ kind: z.ZodEnum<{
36
+ agent: "agent";
37
+ workflow: "workflow";
38
+ tool: "tool";
39
+ skill: "skill";
40
+ companion: "companion";
41
+ }>;
42
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
43
+ }, z.core.$strip>;
44
+ type RunnableMeta = z.infer<typeof RunnableMetaSchema>;
45
+ /**
46
+ * True when a companion `label` impersonates first-party Ryu/system chrome.
47
+ *
48
+ * Mirrors Core's `label_impersonates_system_chrome`
49
+ * (`apps/core/src/plugin_manifest/schema.rs`) and the desktop `validatePluginRoute`
50
+ * title gate (`apps/desktop/src/contributions/host/rpc.ts`): a plugin's visible
51
+ * label may not contain `"ryu"` or `"system"` (case-insensitive), so a third-party
52
+ * companion can never pose as built-in UI. The desktop host's mandatory,
53
+ * non-removable `"Plugin ·"` attribution prefix is the primary guarantee; this is
54
+ * defense in depth enforced at the authoring seam so a hostile label is rejected
55
+ * before `ryu pack`/publish rather than at load.
56
+ */
57
+ declare function labelImpersonatesSystemChrome(label: string): boolean;
58
+ /**
59
+ * Optional in-desktop overlay / sidebar panel descriptor. Mirrors
60
+ * `CompanionSurface` in `apps/core/src/plugin_manifest/mod.rs`.
61
+ */
62
+ declare const CompanionSurfaceSchema: z.ZodObject<{
63
+ label: z.ZodString;
64
+ icon: z.ZodOptional<z.ZodString>;
65
+ shortcut: z.ZodOptional<z.ZodString>;
66
+ }, z.core.$strip>;
67
+ type CompanionSurface = z.infer<typeof CompanionSurfaceSchema>;
68
+ /**
69
+ * A server-side chat turn hook. Mirrors `TurnHookContribution` in
70
+ * `apps/core/src/plugin_manifest/mod.rs`. `code` is a JS body run in the plugin
71
+ * sandbox with `ctx` + `host` in scope; it returns a directive. Authors usually
72
+ * build this via `defineTurnHook` rather than writing the string by hand.
73
+ */
74
+ declare const TurnHookContributionSchema: z.ZodObject<{
75
+ id: z.ZodString;
76
+ on: z.ZodDefault<z.ZodString>;
77
+ code: z.ZodString;
78
+ }, z.core.$strip>;
79
+ type TurnHookContribution = z.infer<typeof TurnHookContributionSchema>;
80
+ /**
81
+ * One app-widget contribution (Ryu Apps). Binds the render tool that produces the
82
+ * widget to its `ui://widget/<slug>.html` template. Shape-identical to Core's
83
+ * `WidgetContribution` (`apps/core/src/plugin_manifest/mod.rs`): built-in apps
84
+ * serve the HTML from the in-process provider and leave `ui_entry` unset, while a
85
+ * third-party app authored here sets `ui_entry` so `ryu pack` bundles the source
86
+ * into the manifest's `ui_code`.
87
+ */
88
+ declare const WidgetContributionSchema: z.ZodObject<{
89
+ tool_id: z.ZodString;
90
+ uri: z.ZodString;
91
+ ui_entry: z.ZodOptional<z.ZodString>;
92
+ mime: z.ZodDefault<z.ZodString>;
93
+ default_display_mode: z.ZodDefault<z.ZodString>;
94
+ }, z.core.$strip>;
95
+ type WidgetContribution = z.infer<typeof WidgetContributionSchema>;
96
+ /**
97
+ * The `config` blob carried by a Ryu App's `kind:"tool"` runnable. Core's strict
98
+ * `ToolConfig` (`apps/core/src/plugin_manifest/schema.rs`) requires `slug` and
99
+ * ignores unknown fields on the current shape; the widget flags below are read by
100
+ * Core's `register_app_tool_with_widget` synthesis path (a separate Core unit) to
101
+ * rebuild the `_meta` binding, mirroring how the in-process `apps::tools()`
102
+ * derives `outputTemplate` / `toolInvocation` / `widgetAccessible`.
103
+ */
104
+ declare const ToolAppConfigSchema: z.ZodObject<{
105
+ slug: z.ZodString;
106
+ description: z.ZodString;
107
+ input_schema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
108
+ widget: z.ZodDefault<z.ZodBoolean>;
109
+ widget_accessible: z.ZodDefault<z.ZodBoolean>;
110
+ invoking: z.ZodOptional<z.ZodString>;
111
+ invoked: z.ZodOptional<z.ZodString>;
112
+ }, z.core.$strip>;
113
+ type ToolAppConfig = z.infer<typeof ToolAppConfigSchema>;
114
+ /**
115
+ * The `contributes` block. Mirrors `Contributes` in
116
+ * `apps/core/src/plugin_manifest/mod.rs`. The declarative UI surfaces
117
+ * (`composer_controls` / `settings_tabs` / `slash_commands`) are passed verbatim
118
+ * to the desktop renderer, so they are typed loosely here (records).
119
+ */
120
+ declare const ContributesSchema: z.ZodObject<{
121
+ turn_hooks: z.ZodDefault<z.ZodArray<z.ZodObject<{
122
+ id: z.ZodString;
123
+ on: z.ZodDefault<z.ZodString>;
124
+ code: z.ZodString;
125
+ }, z.core.$strip>>>;
126
+ composer_controls: z.ZodDefault<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
127
+ settings_tabs: z.ZodDefault<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
128
+ slash_commands: z.ZodDefault<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
129
+ widgets: z.ZodDefault<z.ZodArray<z.ZodObject<{
130
+ tool_id: z.ZodString;
131
+ uri: z.ZodString;
132
+ ui_entry: z.ZodOptional<z.ZodString>;
133
+ mime: z.ZodDefault<z.ZodString>;
134
+ default_display_mode: z.ZodDefault<z.ZodString>;
135
+ }, z.core.$strip>>>;
136
+ }, z.core.$strip>;
137
+ type Contributes = z.infer<typeof ContributesSchema>;
138
+ /**
139
+ * One optional post-install setup/companion card step surfaced on the
140
+ * marketplace detail dialog (Phase 1.5 Ryu extension). All fields optional so a
141
+ * card can be a bare call-to-action or a labelled instruction. `ryu publish`
142
+ * forwards this into the publish body's `setup` field.
143
+ */
144
+ declare const SetupStepSchema: z.ZodObject<{
145
+ title: z.ZodOptional<z.ZodString>;
146
+ description: z.ZodOptional<z.ZodString>;
147
+ actionLabel: z.ZodOptional<z.ZodString>;
148
+ actionUrl: z.ZodOptional<z.ZodString>;
149
+ }, z.core.$strip>;
150
+ type SetupStep = z.infer<typeof SetupStepSchema>;
151
+ /**
152
+ * A single plugin-to-plugin dependency edge. Mirrors `AppDependency` in
153
+ * `apps/core/src/plugin_manifest/mod.rs`.
154
+ *
155
+ * `min_version` is snake_case on the wire (Core declares no serde rename) and is
156
+ * a **minimum**, not a caret range: a bare `"1.2.0"` means `">=1.2.0"`, so an
157
+ * installed `2.0.0` satisfies it. Explicit comparator syntax (`">=1.2, <2"`,
158
+ * `"^1.2"`, `"~1.2"`) is honoured verbatim by Core's `parse_min_version`.
159
+ */
160
+ declare const AppDependencySchema: z.ZodObject<{
161
+ id: z.ZodString;
162
+ min_version: z.ZodOptional<z.ZodString>;
163
+ }, z.core.$strip>;
164
+ type AppDependency = z.infer<typeof AppDependencySchema>;
165
+ /**
166
+ * A single **capability** edge — the layered, provider-agnostic dependency
167
+ * (`requires: [{ capability: "rag" }]`) the capability broker resolves to a
168
+ * concrete provider app at bind time. Mirrors `CapabilityReq` in
169
+ * `crates/ryu-kernel-contracts/src/manifest.rs` (the canonical contract):
170
+ * `{ capability, min_version? }`. Distinct from an `apps` edge (which names a
171
+ * specific plugin id); a `capabilities` edge names an abstract capability and
172
+ * lets the binding registry pick — or the user override — which enabled provider
173
+ * serves it. This is the field the composable `defineAgent` slots lower to.
174
+ */
175
+ declare const CapabilityReqSchema: z.ZodObject<{
176
+ capability: z.ZodString;
177
+ min_version: z.ZodOptional<z.ZodString>;
178
+ }, z.core.$strip>;
179
+ type CapabilityReq = z.infer<typeof CapabilityReqSchema>;
180
+ /**
181
+ * The `requires` block — this plugin's dependencies. Mirrors `Requires` in
182
+ * `apps/core/src/plugin_manifest/mod.rs`.
183
+ *
184
+ * Core resolves `apps` into a topological enable order (`plugins::graph`):
185
+ * enabling this plugin auto-enables its dependencies first, and disabling a
186
+ * dependency is REFUSED (409) while an enabled dependent still needs it.
187
+ *
188
+ * **Absent = no dependencies** — the backward-compatible default every manifest
189
+ * predating this field carries.
190
+ */
191
+ declare const RequiresSchema: z.ZodObject<{
192
+ apps: z.ZodDefault<z.ZodArray<z.ZodObject<{
193
+ id: z.ZodString;
194
+ min_version: z.ZodOptional<z.ZodString>;
195
+ }, z.core.$strip>>>;
196
+ capabilities: z.ZodDefault<z.ZodArray<z.ZodObject<{
197
+ capability: z.ZodString;
198
+ min_version: z.ZodOptional<z.ZodString>;
199
+ }, z.core.$strip>>>;
200
+ grants: z.ZodDefault<z.ZodArray<z.ZodString>>;
201
+ }, z.core.$strip>;
202
+ type Requires = z.infer<typeof RequiresSchema>;
203
+ /**
204
+ * A host surface a plugin can declare support for via `targets`. Mirrors Core's
205
+ * `Surface` enum (`#[serde(rename_all = "kebab-case")]`), so these eight tokens
206
+ * are the exact wire values — also the vocabulary of the `x-ryu-surface` request
207
+ * header Core filters listings on.
208
+ */
209
+ declare const SurfaceSchema: z.ZodEnum<{
210
+ gateway: "gateway";
211
+ core: "core";
212
+ desktop: "desktop";
213
+ island: "island";
214
+ mobile: "mobile";
215
+ extension: "extension";
216
+ web: "web";
217
+ cli: "cli";
218
+ }>;
219
+ type Surface = z.infer<typeof SurfaceSchema>;
220
+ /**
221
+ * Full schema for a `plugin.json` Plugin manifest. Mirrors `PluginManifest` in
222
+ * `apps/core/src/plugin_manifest/mod.rs`.
223
+ *
224
+ * Validation rules (matching Core's `PluginManifestLoader`):
225
+ * - `id` must be non-empty
226
+ * - `version` must be a valid semver string (MAJOR.MINOR.PATCH)
227
+ * - `runnables` may be empty for a "surface-only" plugin, but each entry must be
228
+ * a valid `RunnableMeta`
229
+ */
230
+ declare const PluginManifestSchema: z.ZodObject<{
231
+ id: z.ZodString;
232
+ name: z.ZodString;
233
+ version: z.ZodString;
234
+ ui_code_sha256: z.ZodOptional<z.ZodNullable<z.ZodString>>;
235
+ runnables: z.ZodDefault<z.ZodArray<z.ZodObject<{
236
+ id: z.ZodString;
237
+ name: z.ZodString;
238
+ kind: z.ZodEnum<{
239
+ agent: "agent";
240
+ workflow: "workflow";
241
+ tool: "tool";
242
+ skill: "skill";
243
+ companion: "companion";
244
+ }>;
245
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
246
+ }, z.core.$strip>>>;
247
+ permission_grants: z.ZodDefault<z.ZodArray<z.ZodString>>;
248
+ companion: z.ZodOptional<z.ZodObject<{
249
+ label: z.ZodString;
250
+ icon: z.ZodOptional<z.ZodString>;
251
+ shortcut: z.ZodOptional<z.ZodString>;
252
+ }, z.core.$strip>>;
253
+ activation_events: z.ZodDefault<z.ZodArray<z.ZodString>>;
254
+ contributes: z.ZodOptional<z.ZodObject<{
255
+ turn_hooks: z.ZodDefault<z.ZodArray<z.ZodObject<{
256
+ id: z.ZodString;
257
+ on: z.ZodDefault<z.ZodString>;
258
+ code: z.ZodString;
259
+ }, z.core.$strip>>>;
260
+ composer_controls: z.ZodDefault<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
261
+ settings_tabs: z.ZodDefault<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
262
+ slash_commands: z.ZodDefault<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
263
+ widgets: z.ZodDefault<z.ZodArray<z.ZodObject<{
264
+ tool_id: z.ZodString;
265
+ uri: z.ZodString;
266
+ ui_entry: z.ZodOptional<z.ZodString>;
267
+ mime: z.ZodDefault<z.ZodString>;
268
+ default_display_mode: z.ZodDefault<z.ZodString>;
269
+ }, z.core.$strip>>>;
270
+ }, z.core.$strip>>;
271
+ requires: z.ZodOptional<z.ZodObject<{
272
+ apps: z.ZodDefault<z.ZodArray<z.ZodObject<{
273
+ id: z.ZodString;
274
+ min_version: z.ZodOptional<z.ZodString>;
275
+ }, z.core.$strip>>>;
276
+ capabilities: z.ZodDefault<z.ZodArray<z.ZodObject<{
277
+ capability: z.ZodString;
278
+ min_version: z.ZodOptional<z.ZodString>;
279
+ }, z.core.$strip>>>;
280
+ grants: z.ZodDefault<z.ZodArray<z.ZodString>>;
281
+ }, z.core.$strip>>;
282
+ targets: z.ZodDefault<z.ZodArray<z.ZodEnum<{
283
+ gateway: "gateway";
284
+ core: "core";
285
+ desktop: "desktop";
286
+ island: "island";
287
+ mobile: "mobile";
288
+ extension: "extension";
289
+ web: "web";
290
+ cli: "cli";
291
+ }>>>;
292
+ affiliate: z.ZodOptional<z.ZodObject<{
293
+ enabled: z.ZodDefault<z.ZodBoolean>;
294
+ rule: z.ZodOptional<z.ZodObject<{
295
+ type: z.ZodEnum<{
296
+ flat: "flat";
297
+ percent: "percent";
298
+ }>;
299
+ value: z.ZodNumber;
300
+ recurring: z.ZodDefault<z.ZodBoolean>;
301
+ durationMonths: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
302
+ fundedBy: z.ZodDefault<z.ZodEnum<{
303
+ platform: "platform";
304
+ seller: "seller";
305
+ }>>;
306
+ }, z.core.$strip>>;
307
+ }, z.core.$strip>>;
308
+ description: z.ZodOptional<z.ZodString>;
309
+ tagline: z.ZodOptional<z.ZodString>;
310
+ author: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
311
+ name: z.ZodString;
312
+ email: z.ZodOptional<z.ZodString>;
313
+ url: z.ZodOptional<z.ZodString>;
314
+ }, z.core.$strip>]>>;
315
+ homepage: z.ZodOptional<z.ZodString>;
316
+ keywords: z.ZodOptional<z.ZodArray<z.ZodString>>;
317
+ category: z.ZodOptional<z.ZodString>;
318
+ license: z.ZodOptional<z.ZodString>;
319
+ iconUrl: z.ZodOptional<z.ZodString>;
320
+ screenshots: z.ZodOptional<z.ZodArray<z.ZodString>>;
321
+ privacyPolicyUrl: z.ZodOptional<z.ZodString>;
322
+ termsOfServiceUrl: z.ZodOptional<z.ZodString>;
323
+ capabilities: z.ZodOptional<z.ZodArray<z.ZodString>>;
324
+ examplePrompts: z.ZodOptional<z.ZodArray<z.ZodString>>;
325
+ setup: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
326
+ title: z.ZodOptional<z.ZodString>;
327
+ description: z.ZodOptional<z.ZodString>;
328
+ actionLabel: z.ZodOptional<z.ZodString>;
329
+ actionUrl: z.ZodOptional<z.ZodString>;
330
+ }, z.core.$strip>, z.ZodArray<z.ZodObject<{
331
+ title: z.ZodOptional<z.ZodString>;
332
+ description: z.ZodOptional<z.ZodString>;
333
+ actionLabel: z.ZodOptional<z.ZodString>;
334
+ actionUrl: z.ZodOptional<z.ZodString>;
335
+ }, z.core.$strip>>]>>;
336
+ }, z.core.$strip>;
337
+ type PluginManifest = z.infer<typeof PluginManifestSchema>;
338
+ /**
339
+ * Validate a plugin id with Core's strict reverse-domain, path-traversal-safe
340
+ * rules. Throws a descriptive `Error` when invalid.
341
+ */
342
+ declare function validatePluginId(id: string): void;
343
+ /**
344
+ * Validate a full `plugin.json` string against Core's authoritative rules
345
+ * (id, semver, per-kind runnable config contracts). Returns the normalized
346
+ * manifest JSON string, or throws.
347
+ */
348
+ declare function validateManifestStrict(manifestJson: string): string;
349
+ /**
350
+ * The Core-derived JSON Schema for a `plugin.json`, as a parsed object. Stays in
351
+ * lockstep with the Rust types because it is emitted from them.
352
+ */
353
+ declare function coreManifestJsonSchema(): unknown;
354
+
355
+ export { type AppDependency, AppDependencySchema, type CapabilityReq, CapabilityReqSchema, type CompanionSurface, CompanionSurfaceSchema, type Contributes, ContributesSchema, type PluginManifest, PluginManifestSchema, type Requires, RequiresSchema, type RunnableKind, RunnableKindSchema, type RunnableMeta, RunnableMetaSchema, type SetupStep, SetupStepSchema, type Surface, SurfaceSchema, type ToolAppConfig, ToolAppConfigSchema, type TurnHookContribution, TurnHookContributionSchema, type WidgetContribution, WidgetContributionSchema, coreManifestJsonSchema, labelImpersonatesSystemChrome, validateManifestStrict, validatePluginId };
@@ -0,0 +1,38 @@
1
+ import {
2
+ AppDependencySchema,
3
+ CapabilityReqSchema,
4
+ CompanionSurfaceSchema,
5
+ ContributesSchema,
6
+ PluginManifestSchema,
7
+ RequiresSchema,
8
+ RunnableKindSchema,
9
+ RunnableMetaSchema,
10
+ SetupStepSchema,
11
+ SurfaceSchema,
12
+ ToolAppConfigSchema,
13
+ TurnHookContributionSchema,
14
+ WidgetContributionSchema,
15
+ coreManifestJsonSchema,
16
+ labelImpersonatesSystemChrome,
17
+ validateManifestStrict,
18
+ validatePluginId
19
+ } from "./chunk-GXHL5CO7.js";
20
+ export {
21
+ AppDependencySchema,
22
+ CapabilityReqSchema,
23
+ CompanionSurfaceSchema,
24
+ ContributesSchema,
25
+ PluginManifestSchema,
26
+ RequiresSchema,
27
+ RunnableKindSchema,
28
+ RunnableMetaSchema,
29
+ SetupStepSchema,
30
+ SurfaceSchema,
31
+ ToolAppConfigSchema,
32
+ TurnHookContributionSchema,
33
+ WidgetContributionSchema,
34
+ coreManifestJsonSchema,
35
+ labelImpersonatesSystemChrome,
36
+ validateManifestStrict,
37
+ validatePluginId
38
+ };
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@ryuhq/sdk",
3
+ "version": "0.0.5",
4
+ "type": "module",
5
+ "description": "Ryu developer SDK: typed builders and CLI for authoring plugin.json Plugin bundles",
6
+ "main": "./dist/index.cjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
13
+ },
14
+ "./manifest": {
15
+ "types": "./dist/manifest.d.ts",
16
+ "import": "./dist/manifest.js",
17
+ "require": "./dist/manifest.cjs"
18
+ },
19
+ "./agent": {
20
+ "types": "./dist/agent.d.ts",
21
+ "import": "./dist/agent.js",
22
+ "require": "./dist/agent.cjs"
23
+ },
24
+ "./cli": {
25
+ "import": "./dist/cli.js"
26
+ }
27
+ },
28
+ "bin": {
29
+ "ryu": "./dist/cli.js"
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "src",
34
+ "README.md"
35
+ ],
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "scripts": {
40
+ "build": "tsup",
41
+ "check-types": "tsc --noEmit",
42
+ "generate:contracts": "bun run scripts/generate-contracts.ts",
43
+ "test": "bun test",
44
+ "clean": "rm -rf dist"
45
+ },
46
+ "dependencies": {
47
+ "@ryuhq/sdk-native": "0.1.0",
48
+ "zod": "^4.1.13"
49
+ },
50
+ "devDependencies": {
51
+ "@types/bun": "^1.3.4",
52
+ "json-schema-to-typescript": "^15.0.4",
53
+ "tsup": "^8.5.1",
54
+ "typescript": "^5"
55
+ }
56
+ }
@@ -0,0 +1,208 @@
1
+ /**
2
+ * `Agent` — the declarative agent runtime for `@ryu/sdk`.
3
+ *
4
+ * Unlike `defineAgent` (a declaration wrapper whose `run()` you write by hand),
5
+ * `Agent` OWNS the loop: give it instructions, a model, a target node, and a
6
+ * set of tools, then call `generate()` / `stream()`. Inference is pointed at the
7
+ * node's gateway; tool calls resolve to local `defineTool` runnables or existing
8
+ * Ryu tools (`ryuTool`) executed through Core.
9
+ *
10
+ * Mirrors Mastra's config-object + `.generate()`/`.stream()` shape; `query()`
11
+ * (see query.ts) wraps the same runtime in a Claude-Agent-SDK-style streaming
12
+ * call.
13
+ */
14
+
15
+ import { defineModel } from "../model/client.ts";
16
+ import { resolveGatewayToken, resolveGatewayUrl } from "../model/gateway.ts";
17
+ import {
18
+ createPrimitives,
19
+ httpPrimitiveTransport,
20
+ } from "../runnable/primitives.ts";
21
+ import type { GatewayClient } from "../runnable/runnable-types.ts";
22
+ import {
23
+ type AgentEvent,
24
+ type AgentEventAuthRequired,
25
+ type LoopConfig,
26
+ runAgentLoop,
27
+ } from "./loop.ts";
28
+ import type { LoopMessage, ModelUsage } from "./model-call.ts";
29
+ import type { AgentTool, ToolExecContext } from "./tools.ts";
30
+
31
+ const DEFAULT_MAX_STEPS = 10;
32
+ const DEFAULT_CORE_URL = "http://127.0.0.1:7980";
33
+
34
+ /** A target node for inference / tool execution: a base URL + optional token. */
35
+ export interface Endpoint {
36
+ baseUrl?: string;
37
+ token?: string;
38
+ }
39
+
40
+ /** Declarative configuration for an `Agent`. */
41
+ export interface AgentConfig {
42
+ /** Core agent id — REQUIRED when using `ryuTool` remote tools (governance). */
43
+ agentId?: string;
44
+ /** Core endpoint for tool discovery/execution. Defaults to env/localhost. */
45
+ core?: Endpoint;
46
+ /** System prompt / persona. */
47
+ instructions?: string;
48
+ /** Hard ceiling on model→tool rounds (default 10). */
49
+ maxSteps?: number;
50
+ /** Model id routed by the node's gateway. */
51
+ model: string;
52
+ /** Display name. */
53
+ name: string;
54
+ /** Target node for inference. Defaults to the local gateway. */
55
+ node?: Endpoint;
56
+ /**
57
+ * Reverse-domain plugin id. When set, the composable primitive surface
58
+ * (`ctx.rag`, `ctx.memory`, `ctx.engines`, …) is mounted on the run context,
59
+ * routed through this node via the governed host bridge / capability broker.
60
+ * Omitted = no primitives mounted (the bridge families authenticate a plugin
61
+ * id, so a half-wired transport is never attached).
62
+ */
63
+ pluginId?: string;
64
+ /** Tools keyed by the model-facing name. */
65
+ tools?: Record<string, AgentTool>;
66
+ /** Composio connected-account entity selector. */
67
+ userId?: string;
68
+ }
69
+
70
+ /** Result of a non-streaming `generate()`. */
71
+ export interface GenerateResult {
72
+ /** Present when the run paused for an account connection. */
73
+ authRequired?: AgentEventAuthRequired;
74
+ /** Number of model→tool rounds taken. */
75
+ steps: number;
76
+ /** Final assistant text. */
77
+ text: string;
78
+ /** Aggregate token usage across all rounds (when reported). */
79
+ usage?: ModelUsage;
80
+ }
81
+
82
+ /** Read `process.env` defensively (SDK may run outside Node typings). */
83
+ function env(key: string): string | undefined {
84
+ const value = (globalThis as { process?: { env?: Record<string, string> } })
85
+ .process?.env?.[key];
86
+ return value && value !== "" ? value : undefined;
87
+ }
88
+
89
+ /**
90
+ * Build a `GatewayClient` for local tools that lazily constructs the native
91
+ * `ModelClient` only on first use — so an agent with no gateway-calling local
92
+ * tools never touches the native addon.
93
+ */
94
+ function lazyGatewayClient(
95
+ model: string,
96
+ baseUrl: string,
97
+ token?: string
98
+ ): GatewayClient {
99
+ let client: ReturnType<typeof defineModel> | null = null;
100
+ const get = () => {
101
+ client ??= defineModel(model, { baseUrl, token });
102
+ return client;
103
+ };
104
+ return {
105
+ chat: (messages) => get().chat(messages),
106
+ stream: (messages) => get().stream(messages),
107
+ };
108
+ }
109
+
110
+ /** A declarative, loop-owning agent. */
111
+ export class Agent {
112
+ readonly config: AgentConfig;
113
+
114
+ constructor(config: AgentConfig) {
115
+ this.config = config;
116
+ }
117
+
118
+ /** Assemble the loop config for a given prompt. */
119
+ private buildLoopConfig(prompt: string, signal?: AbortSignal): LoopConfig {
120
+ const gatewayBaseUrl = this.config.node?.baseUrl ?? resolveGatewayUrl();
121
+ const gatewayToken = this.config.node?.token ?? resolveGatewayToken();
122
+ const coreBaseUrl =
123
+ this.config.core?.baseUrl ?? env("RYU_CORE_URL") ?? DEFAULT_CORE_URL;
124
+ const coreToken = this.config.core?.token ?? env("RYU_TOKEN");
125
+
126
+ const messages: LoopMessage[] = [];
127
+ if (this.config.instructions) {
128
+ messages.push({ role: "system", content: this.config.instructions });
129
+ }
130
+ messages.push({ role: "user", content: prompt });
131
+
132
+ const toolCtx: ToolExecContext = {
133
+ agentId: this.config.agentId,
134
+ coreBaseUrl,
135
+ coreToken,
136
+ userId: this.config.userId,
137
+ signal,
138
+ runnableContext: {
139
+ gateway: lazyGatewayClient(
140
+ this.config.model,
141
+ gatewayBaseUrl,
142
+ gatewayToken
143
+ ),
144
+ signal,
145
+ // Mount the composable primitive surface only when a plugin id is
146
+ // present — the bridge families authenticate it, so we never attach a
147
+ // half-wired transport (advisor guidance / §6b).
148
+ ...(this.config.pluginId
149
+ ? createPrimitives(
150
+ httpPrimitiveTransport({
151
+ nodeUrl: coreBaseUrl,
152
+ token: coreToken,
153
+ pluginId: this.config.pluginId,
154
+ })
155
+ )
156
+ : {}),
157
+ },
158
+ };
159
+
160
+ return {
161
+ model: this.config.model,
162
+ gatewayBaseUrl,
163
+ gatewayToken,
164
+ messages,
165
+ tools: this.config.tools ?? {},
166
+ toolCtx,
167
+ maxSteps: this.config.maxSteps ?? DEFAULT_MAX_STEPS,
168
+ signal,
169
+ };
170
+ }
171
+
172
+ /** Stream loop events (text / tool_call / tool_result / auth_required / …). */
173
+ stream(prompt: string, signal?: AbortSignal): AsyncGenerator<AgentEvent> {
174
+ return runAgentLoop(this.buildLoopConfig(prompt, signal));
175
+ }
176
+
177
+ /** Run to completion and return the final text, step count, and usage. */
178
+ async generate(
179
+ prompt: string,
180
+ signal?: AbortSignal
181
+ ): Promise<GenerateResult> {
182
+ let text = "";
183
+ let steps = 0;
184
+ let usage: ModelUsage | undefined;
185
+ let authRequired: AgentEventAuthRequired | undefined;
186
+
187
+ for await (const event of this.stream(prompt, signal)) {
188
+ if (event.type === "result") {
189
+ text = event.text;
190
+ steps = event.steps;
191
+ usage = event.usage;
192
+ } else if (event.type === "auth_required") {
193
+ authRequired = event;
194
+ } else if (event.type === "error") {
195
+ throw new Error(
196
+ `[ryu-sdk] agent "${this.config.name}": ${event.message}`
197
+ );
198
+ }
199
+ }
200
+
201
+ return { text, steps, usage, authRequired };
202
+ }
203
+ }
204
+
205
+ /** Factory alias for `new Agent(config)`. */
206
+ export function createAgent(config: AgentConfig): Agent {
207
+ return new Agent(config);
208
+ }