@ryuhq/sdk 0.1.13 → 0.2.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.
Files changed (90) hide show
  1. package/README.md +19 -6
  2. package/dist/agent-plugin.cjs +46 -0
  3. package/dist/agent-plugin.d.cts +42 -32
  4. package/dist/agent-plugin.d.ts +42 -32
  5. package/dist/agent-plugin.js +1 -1
  6. package/dist/agent.cjs +9 -0
  7. package/dist/agent.d.cts +377 -1
  8. package/dist/agent.d.ts +377 -1
  9. package/dist/agent.js +4 -2
  10. package/dist/app-Bkw7LlCK.d.ts +129 -0
  11. package/dist/app-DNaGmLVf.d.cts +129 -0
  12. package/dist/builder.cjs +1095 -0
  13. package/dist/builder.d.cts +212 -0
  14. package/dist/builder.d.ts +212 -0
  15. package/dist/builder.js +28 -0
  16. package/dist/chunk-A3RGEPDG.js +250 -0
  17. package/dist/chunk-FZSFZOIN.js +200 -0
  18. package/dist/{chunk-ODFEUVPW.js → chunk-HACAGK65.js} +1 -18
  19. package/dist/{chunk-AO2KJRDD.js → chunk-IEUQ3CDG.js} +125 -2
  20. package/dist/chunk-IKEDLLFY.js +19 -0
  21. package/dist/chunk-IOLP5FFE.js +354 -0
  22. package/dist/{chunk-G6FLVEC4.js → chunk-JX6DDRXV.js} +46 -0
  23. package/dist/chunk-T5676WL2.js +240 -0
  24. package/dist/chunk-TLDPEGC7.js +21 -0
  25. package/dist/chunk-TXSHHZF2.js +0 -0
  26. package/dist/{chunk-MTUBUPIV.js → chunk-ULSVL7EC.js} +8 -227
  27. package/dist/chunk-VLIRNNAE.js +154 -0
  28. package/dist/chunk-W3KPP4WN.js +135 -0
  29. package/dist/cli.cjs +258 -14
  30. package/dist/cli.js +96 -16
  31. package/dist/client-D5U6ssPc.d.cts +84 -0
  32. package/dist/client-D5U6ssPc.d.ts +84 -0
  33. package/dist/index.cjs +519 -5
  34. package/dist/index.d.cts +16 -632
  35. package/dist/index.d.ts +16 -632
  36. package/dist/index.js +63 -695
  37. package/dist/manifest.cjs +129 -3
  38. package/dist/manifest.d.cts +105 -2
  39. package/dist/manifest.d.ts +105 -2
  40. package/dist/manifest.js +7 -1
  41. package/dist/mcp/client.cjs +180 -0
  42. package/dist/mcp/client.d.cts +49 -0
  43. package/dist/mcp/client.d.ts +49 -0
  44. package/dist/mcp/client.js +10 -0
  45. package/dist/mcp/server.cjs +370 -0
  46. package/dist/mcp/server.d.cts +126 -0
  47. package/dist/mcp/server.d.ts +126 -0
  48. package/dist/mcp/server.js +9 -0
  49. package/dist/mcp.cjs +376 -0
  50. package/dist/mcp.d.cts +2 -0
  51. package/dist/mcp.d.ts +2 -0
  52. package/dist/mcp.js +17 -0
  53. package/dist/model.cjs +141 -0
  54. package/dist/model.d.cts +33 -0
  55. package/dist/model.d.ts +33 -0
  56. package/dist/model.js +18 -0
  57. package/dist/plugin.cjs +46 -0
  58. package/dist/plugin.d.cts +215 -0
  59. package/dist/plugin.d.ts +215 -0
  60. package/dist/plugin.js +8 -0
  61. package/dist/runnable.cjs +1230 -0
  62. package/dist/runnable.d.cts +271 -0
  63. package/dist/runnable.d.ts +271 -0
  64. package/dist/runnable.js +28 -0
  65. package/dist/{index-B6SkaAjJ.d.ts → tool-DSx2bFx8.d.ts} +35 -458
  66. package/dist/{index-BvAB5eMk.d.cts → tool-u-VR0fLF.d.cts} +35 -458
  67. package/package.json +38 -2
  68. package/src/agent/loop.test.ts +4 -4
  69. package/src/agent/tools.ts +3 -3
  70. package/src/agent-plugin.test.ts +58 -0
  71. package/src/agent-plugin.ts +108 -35
  72. package/src/cli/dev.test.ts +26 -47
  73. package/src/cli/dev.ts +10 -2
  74. package/src/cli.ts +98 -15
  75. package/src/exports-lockstep.test.ts +92 -0
  76. package/src/generated/plugin-manifest.ts +243 -27
  77. package/src/index.ts +35 -0
  78. package/src/manifest-schema.test.ts +30 -1
  79. package/src/manifest.fixtures.test.ts +13 -3
  80. package/src/manifest.test.ts +96 -10
  81. package/src/manifest.ts +334 -187
  82. package/src/mcp/index.ts +18 -0
  83. package/src/model/index.ts +22 -0
  84. package/src/plugin/ryu-plugin.ts +82 -0
  85. package/src/runnable/app.test.ts +2 -0
  86. package/src/runnable/app.ts +5 -2
  87. package/src/runnable/index.ts +2 -0
  88. package/src/runnable/primitives.ts +57 -0
  89. package/src/runnable/tool.ts +1 -1
  90. package/src/runnable/turn-hook.ts +4 -1
@@ -125,6 +125,27 @@ export interface ThemeContribution {
125
125
  * are RPCs over the postMessage bridge; the plugin never holds a Core token or
126
126
  * Tauri IPC handle directly. */
127
127
  export interface RyuHostServices {
128
+ /** Read and cooperatively stop Core-visible background processes. */
129
+ background: {
130
+ list(input?: { producer?: string; running_only?: boolean }): Promise<
131
+ {
132
+ process_id: string;
133
+ command: string;
134
+ cwd: string;
135
+ elapsed_ms: number;
136
+ running: boolean;
137
+ [key: string]: unknown;
138
+ }[]
139
+ >;
140
+ stop(input: { process_id: string }): Promise<{
141
+ ok: boolean;
142
+ requested: boolean;
143
+ process_id: string;
144
+ }>;
145
+ };
146
+ /** Read-only feature discovery. Older hosts may omit this method; treat that
147
+ * as an empty capability set rather than assuming a native surface exists. */
148
+ capabilities?(): Promise<RyuHostCapabilities>;
128
149
  /** Run a registered command by id (built-in or contributed). */
129
150
  commands: { execute(id: string, ...args: unknown[]): Promise<unknown> };
130
151
  /** Gateway-governed model access (chat/embed). Mirrors `@ryuhq/sdk` model
@@ -140,6 +161,21 @@ export interface RyuHostServices {
140
161
  * or any other agent field (invariant: no capability returns a secret). Gated
141
162
  * by the `core:list_agents` grant. */
142
163
  listAgents(): Promise<{ id: string; name: string }[]>;
164
+ /** Mobile-native effects. These methods remain optional at the type boundary
165
+ * because desktop, web, extension, and terminal hosts fail closed. */
166
+ native?: {
167
+ haptics(input: RyuNativeHapticsInput): Promise<RyuNativeHapticsResult>;
168
+ notifications: {
169
+ create(
170
+ input: RyuNativeNotificationInput
171
+ ): Promise<RyuNativeNotificationResult>;
172
+ };
173
+ liveActivities: {
174
+ update(
175
+ input: RyuNativeLiveActivityInput
176
+ ): Promise<RyuNativeLiveActivityResult>;
177
+ };
178
+ };
143
179
  /** Open a tab at a path (built-in or a route this plugin contributed). */
144
180
  openTab(path: string): void;
145
181
  /** Read/write the plugin's own Spaces docs (scoped by grant). */
@@ -152,6 +188,52 @@ export interface RyuHostServices {
152
188
  };
153
189
  }
154
190
 
191
+ /** The token-free, read-only native feature inventory returned by a host. */
192
+ export interface RyuHostCapabilities {
193
+ androidOngoingNotifications: boolean;
194
+ browserNotifications: boolean;
195
+ dynamicIsland: boolean;
196
+ haptics: boolean;
197
+ hardwareBleRelay: boolean;
198
+ liveActivities: boolean;
199
+ localNotifications: boolean;
200
+ platform: "android" | "browser" | "ios" | "unknown";
201
+ pushRegistration: boolean;
202
+ quickActions: boolean;
203
+ sounds: boolean;
204
+ }
205
+
206
+ export type RyuNativeHapticStyle = "light" | "success" | "warning" | "error";
207
+
208
+ export interface RyuNativeHapticsInput {
209
+ style: RyuNativeHapticStyle;
210
+ }
211
+
212
+ export interface RyuNativeNotificationInput {
213
+ body: string;
214
+ title: string;
215
+ }
216
+
217
+ export interface RyuNativeLiveActivityInput {
218
+ conversationId: string;
219
+ detail: string;
220
+ status: "running" | "waiting" | "review" | "done" | "error";
221
+ title: string;
222
+ }
223
+
224
+ export interface RyuNativeHapticsResult {
225
+ signaled: true;
226
+ }
227
+
228
+ export interface RyuNativeNotificationResult {
229
+ id: string;
230
+ scheduled: true;
231
+ }
232
+
233
+ export interface RyuNativeLiveActivityResult {
234
+ updated: true;
235
+ }
236
+
155
237
  // ── The host API a plugin's activate() receives ───────────────────────────────
156
238
 
157
239
  /** Everything a plugin can contribute. Each `register*` returns a
@@ -9,6 +9,7 @@ function checklistApp(grants?: string[]) {
9
9
  slug: "checklist",
10
10
  title: "Checklist",
11
11
  version: "1.0.0",
12
+ uiEntry: "src/checklist.tsx",
12
13
  ...(grants ? { grants } : {}),
13
14
  tools: [{ name: "render", description: "Render a checklist" }],
14
15
  });
@@ -48,6 +49,7 @@ describe("defineApp widget grant", () => {
48
49
  slug: "tools",
49
50
  title: "Tools",
50
51
  version: "1.0.0",
52
+ uiEntry: "src/tools.tsx",
51
53
  tools: [{ name: "toggle", description: "Toggle", accessible: true }],
52
54
  });
53
55
  expect(manifest.contributes?.widgets ?? []).toHaveLength(0);
@@ -74,7 +74,7 @@ export interface AppToolSpec {
74
74
  invoked?: string;
75
75
  /** Status label shown while a render tool runs (e.g. `"Plotting chart…"`). */
76
76
  invoking?: string;
77
- /** Tool name (unqualified). The wire id is `<server>__<name>`. */
77
+ /** Tool name (unqualified). The wire id is `<server>.<name>`. */
78
78
  name: string;
79
79
  }
80
80
 
@@ -141,7 +141,7 @@ export interface DefineAppOptions {
141
141
 
142
142
  /** Build a fully-qualified tool id from a server namespace and tool name. */
143
143
  export function appToolId(server: string, name: string): string {
144
- return `${server}__${name}`;
144
+ return `${server}.${name}`;
145
145
  }
146
146
 
147
147
  /**
@@ -213,6 +213,7 @@ export function defineApp(options: DefineAppOptions): PluginManifest {
213
213
 
214
214
  const contributes: Contributes = {
215
215
  turn_hooks: [],
216
+ chat_features: [],
216
217
  // This builder synthesises an app from its runnables; an app that emits
217
218
  // events declares them in a hand-authored `manifest.json`, same as
218
219
  // `lsp_servers` below.
@@ -223,6 +224,7 @@ export function defineApp(options: DefineAppOptions): PluginManifest {
223
224
  sidebar_sections: [],
224
225
  sidebar_buttons: [],
225
226
  dock_panels: [],
227
+ live_activities: [],
226
228
  // Empty for the same reason as every sibling family above: this builder
227
229
  // synthesises `widgets` from the app's own runnables and nothing else, and
228
230
  // takes no `contributes` passthrough. An app that wants to declare language
@@ -235,6 +237,7 @@ export function defineApp(options: DefineAppOptions): PluginManifest {
235
237
  data_categories: [],
236
238
  pi_extensions: [],
237
239
  output_styles: [],
240
+ message_actions: [],
238
241
  widgets,
239
242
  };
240
243
 
@@ -26,6 +26,8 @@ export { defineAgent } from "./agent.ts";
26
26
  export type { AppToolSpec, DefineAppOptions } from "./app.ts";
27
27
  export { appToolId, defineApp } from "./app.ts";
28
28
  export type {
29
+ BackgroundClient,
30
+ BackgroundProcess,
29
31
  DurableClient,
30
32
  EnginesClient,
31
33
  HttpPrimitiveTransportOptions,
@@ -316,6 +316,16 @@ export const PRIMITIVE_BINDINGS: Record<string, PrimitiveBinding> = {
316
316
  method: "model.complete",
317
317
  grant: "hook:side-model",
318
318
  },
319
+ "background.list": {
320
+ transport: "bridge",
321
+ method: "background.list",
322
+ grant: "background:control",
323
+ },
324
+ "background.stop": {
325
+ transport: "bridge",
326
+ method: "background.stop",
327
+ grant: "background:control",
328
+ },
319
329
  // Host-direct media data-path (the host holds the node token; returns data: URLs).
320
330
  "image.generate": {
321
331
  transport: "direct",
@@ -468,6 +478,37 @@ export interface EnginesClient {
468
478
  }): Promise<number[][]>;
469
479
  }
470
480
 
481
+ /** One process visible through the shared Core background registry. */
482
+ export interface BackgroundProcess {
483
+ command: string;
484
+ cwd: string;
485
+ description?: string | null;
486
+ elapsed_ms: number;
487
+ exit_code?: number | null;
488
+ exit_signal?: string | null;
489
+ kind: string;
490
+ label?: string | null;
491
+ pid?: number | null;
492
+ process_id: string;
493
+ producer: string;
494
+ running: boolean;
495
+ shell_id?: string | null;
496
+ started_at: number;
497
+ }
498
+
499
+ /** Background-process registry and cooperative stop requests. */
500
+ export interface BackgroundClient {
501
+ list(input?: {
502
+ producer?: string;
503
+ runningOnly?: boolean;
504
+ }): Promise<BackgroundProcess[]>;
505
+ stop(input: { processId: string }): Promise<{
506
+ ok: boolean;
507
+ requested: boolean;
508
+ process_id: string;
509
+ }>;
510
+ }
511
+
471
512
  /** TTS primitive — speech synthesis (`crates/ryu-tts`). */
472
513
  export interface TtsClient {
473
514
  /**
@@ -513,6 +554,7 @@ export interface ImageClient {
513
554
  * Core node) — the same "what runs vs what is allowed" split as `ctx.gateway`.
514
555
  */
515
556
  export interface RyuPrimitives {
557
+ background: BackgroundClient;
516
558
  durable: DurableClient;
517
559
  engines: EnginesClient;
518
560
  image: ImageClient;
@@ -542,6 +584,21 @@ function brokerCall(
542
584
  */
543
585
  export function createPrimitives(transport: PrimitiveTransport): RyuPrimitives {
544
586
  return {
587
+ background: {
588
+ list: (input) =>
589
+ transport.bridge("background.list", {
590
+ producer: input?.producer,
591
+ running_only: input?.runningOnly,
592
+ }) as Promise<BackgroundProcess[]>,
593
+ stop: (input) =>
594
+ transport.bridge("background.stop", {
595
+ process_id: input.processId,
596
+ }) as Promise<{
597
+ ok: boolean;
598
+ requested: boolean;
599
+ process_id: string;
600
+ }>,
601
+ },
545
602
  rag: {
546
603
  retrieve: (input) =>
547
604
  brokerCall(transport, "rag", "retrieve", input) as Promise<RagChunk[]>,
@@ -236,7 +236,7 @@ export function defineTool<
236
236
  * ships its `run` body as Core's `inline_deno` backend. The emitted config
237
237
  * mirrors Core's `ToolConfig` (`apps/core/src/plugin_manifest/schema.rs`):
238
238
  * `{ slug, backend:"inline_deno", code, description?, input_schema }`. Core
239
- * registers it as `app__<slug>` — discoverable via `/api/tools/search` and
239
+ * registers it as `app.<slug>` — discoverable via `/api/tools/search` and
240
240
  * executed in the grant-gated sandbox.
241
241
  *
242
242
  * The plugin must declare the `tool:execute` grant (see `definePlugin`).
@@ -154,7 +154,7 @@ export interface DefinePluginOptions {
154
154
  /**
155
155
  * Inline tools the plugin ships — each a {@link ToolRunnable} from `defineTool`
156
156
  * whose `run` body is bundled as Core's `inline_deno` backend (registered as
157
- * `app__<tool.id>`). Shipping any tool auto-adds the `tool:execute` grant.
157
+ * `app.<tool.id>`). Shipping any tool auto-adds the `tool:execute` grant.
158
158
  */
159
159
  tools?: ToolRunnable[];
160
160
  /** Turn hooks the plugin contributes. */
@@ -173,6 +173,7 @@ export function definePlugin(options: DefinePluginOptions): PluginManifest {
173
173
  turn_hooks: options.turnHooks ?? [],
174
174
  hook_events: options.hookEvents ?? [],
175
175
  composer_controls: options.composerControls ?? [],
176
+ chat_features: [],
176
177
  settings_tabs: options.settingsTabs ?? [],
177
178
  slash_commands: options.slashCommands ?? [],
178
179
  lsp_servers: options.lspServers ?? {},
@@ -184,9 +185,11 @@ export function definePlugin(options: DefinePluginOptions): PluginManifest {
184
185
  sidebar_sections: [],
185
186
  sidebar_buttons: [],
186
187
  dock_panels: [],
188
+ live_activities: [],
187
189
  data_categories: [],
188
190
  pi_extensions: [],
189
191
  output_styles: [],
192
+ message_actions: [],
190
193
  };
191
194
  // Ship each inline tool as a `kind:"tool"` runnable (Core's `inline_deno`
192
195
  // backend). Shipping tools requires the `tool:execute` grant; add it once.