@ryuhq/sdk 0.2.0 → 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 +51 -2
- 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.d.cts +1 -1
- package/dist/agent-plugin.d.ts +1 -1
- package/dist/agent.cjs +7 -0
- package/dist/agent.d.cts +1 -1
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +2 -2
- package/dist/{app-DNaGmLVf.d.cts → app-B0Z9Ew_R.d.cts} +18 -6
- package/dist/{app-Bkw7LlCK.d.ts → app-C-BDJwfG.d.ts} +18 -6
- package/dist/builder.cjs +110 -11
- package/dist/builder.d.cts +7 -2
- package/dist/builder.d.ts +7 -2
- package/dist/builder.js +4 -3
- package/dist/chunk-4TPUZDTI.js +94 -0
- package/dist/{chunk-T5676WL2.js → chunk-BC3A7HMO.js} +1 -77
- package/dist/{chunk-IOLP5FFE.js → chunk-HLKJZAFK.js} +9 -2
- package/dist/{chunk-IEUQ3CDG.js → chunk-NZKVOSC2.js} +71 -5
- package/dist/chunk-QYFUNJOH.js +83 -0
- package/dist/{chunk-W3KPP4WN.js → chunk-SN2QBJUF.js} +20 -7
- package/dist/{chunk-ULSVL7EC.js → chunk-Z57QDDJR.js} +1 -1
- package/dist/{chunk-A3RGEPDG.js → chunk-ZTJWBRUL.js} +32 -0
- package/dist/cli.cjs +93 -8
- package/dist/cli.js +33 -8
- package/dist/index.cjs +297 -87
- package/dist/index.d.cts +10 -9
- package/dist/index.d.ts +10 -9
- package/dist/index.js +34 -19
- package/dist/manifest.cjs +76 -6
- package/dist/manifest.d.cts +157 -5
- package/dist/manifest.d.ts +157 -5
- package/dist/manifest.js +9 -1
- package/dist/mcp/server.d.cts +2 -1
- package/dist/mcp/server.d.ts +2 -1
- package/dist/runnable.cjs +279 -71
- package/dist/runnable.d.cts +6 -3
- package/dist/runnable.d.ts +6 -3
- package/dist/runnable.js +11 -5
- package/dist/{tool-DSx2bFx8.d.ts → tool-AjkdFvhE.d.ts} +54 -4
- package/dist/{tool-u-VR0fLF.d.cts → tool-CgzW92O_.d.cts} +54 -4
- package/package.json +12 -3
- package/src/agent-plugin.ts +1 -1
- package/src/builder.ts +9 -0
- package/src/cli-security.test.ts +109 -0
- package/src/cli.ts +43 -10
- package/src/contracts-lockstep.test.ts +16 -2
- package/src/exports-lockstep.test.ts +1 -0
- package/src/generated/plugin-manifest.ts +82 -5
- package/src/index.ts +18 -0
- package/src/manifest.fixtures.test.ts +9 -3
- package/src/manifest.test.ts +69 -0
- package/src/manifest.ts +137 -18
- package/src/mcp/server.ts +2 -1
- package/src/runnable/action.test.ts +128 -0
- package/src/runnable/action.ts +202 -0
- package/src/runnable/app.ts +45 -12
- package/src/runnable/index.ts +18 -3
- package/src/runnable/primitives.test.ts +34 -0
- package/src/runnable/primitives.ts +59 -0
- package/src/runnable/runnable-types.ts +3 -0
- package/src/runnable/tool.ts +35 -4
- package/src/runnable/turn-hook.ts +4 -2
- package/src/slash-command.test.ts +69 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Surface, PluginManifest } from './manifest.cjs';
|
|
2
|
+
import { SdkRunnable } from './mcp/server.cjs';
|
|
3
|
+
import { k as RunnableContext, o as ToolSchema, T as ToolRunnable } from './tool-CgzW92O_.cjs';
|
|
4
|
+
import 'zod';
|
|
5
|
+
import './mcp/client.cjs';
|
|
6
|
+
import './client-D5U6ssPc.cjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Canonical Ryu Action authoring API.
|
|
10
|
+
*
|
|
11
|
+
* An Action is the semantic contract for a business operation: one description,
|
|
12
|
+
* input schema, output schema, implementation, and effect declaration. It lowers
|
|
13
|
+
* to Ryu's existing governed `inline_deno` Tool backend, so this adds a coherent
|
|
14
|
+
* authoring seam without introducing a second Core execution runtime.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** The two effects Core can enforce from tool annotations. */
|
|
18
|
+
type ActionEffect = "mutate" | "read";
|
|
19
|
+
/** MCP-compatible effect hints plus any future provider-neutral boolean hints. */
|
|
20
|
+
interface ActionAnnotations {
|
|
21
|
+
destructiveHint?: boolean;
|
|
22
|
+
idempotentHint?: boolean;
|
|
23
|
+
openWorldHint?: boolean;
|
|
24
|
+
readOnlyHint?: boolean;
|
|
25
|
+
[key: string]: boolean | undefined;
|
|
26
|
+
}
|
|
27
|
+
/** Options for defining a canonical Action. */
|
|
28
|
+
interface ActionOptions<TInput extends Record<string, unknown>, TOutput> {
|
|
29
|
+
/** Additional MCP-compatible effect hints. */
|
|
30
|
+
annotations?: ActionAnnotations;
|
|
31
|
+
/** Description the agent reads when deciding whether to call the action. */
|
|
32
|
+
description: string;
|
|
33
|
+
/** Explicit effect used by read-only and approval enforcement. */
|
|
34
|
+
effect: ActionEffect;
|
|
35
|
+
/** Stable action id, also used as the generated Core tool slug. */
|
|
36
|
+
id: string;
|
|
37
|
+
/** Human-readable action name. */
|
|
38
|
+
name: string;
|
|
39
|
+
/** Require human approval even when global smart mode would not classify it. */
|
|
40
|
+
needsApproval?: boolean;
|
|
41
|
+
/** JSON Schema for the structured action result. */
|
|
42
|
+
outputSchema?: Record<string, unknown>;
|
|
43
|
+
/** The one implementation used by local callers and the packaged tool body. */
|
|
44
|
+
run(input: TInput, ctx: RunnableContext): Promise<TOutput>;
|
|
45
|
+
/** JSON Schema for all action inputs. */
|
|
46
|
+
schema: ToolSchema;
|
|
47
|
+
}
|
|
48
|
+
/** Options for lowering one Action into a standalone Ryu plugin manifest. */
|
|
49
|
+
interface ActionManifestOptions {
|
|
50
|
+
/** Plugin activation events; defaults to eager activation. */
|
|
51
|
+
activationEvents?: readonly string[];
|
|
52
|
+
/** Extra Gateway grants required by the action body. */
|
|
53
|
+
grants?: readonly string[];
|
|
54
|
+
/** Reverse-domain plugin id (for example `com.acme.support`). */
|
|
55
|
+
id: string;
|
|
56
|
+
/** Display name; defaults to the Action name. */
|
|
57
|
+
name?: string;
|
|
58
|
+
/** Host surfaces this plugin targets. */
|
|
59
|
+
targets?: readonly Surface[];
|
|
60
|
+
/** Plugin semver. */
|
|
61
|
+
version: string;
|
|
62
|
+
}
|
|
63
|
+
/** A ToolRunnable with Action semantics and manifest/MCP adapters. */
|
|
64
|
+
interface ActionRunnable<TInput extends Record<string, unknown> = Record<string, unknown>, TOutput = unknown> extends ToolRunnable<TInput, TOutput> {
|
|
65
|
+
/** Discriminates this semantic contract from an ordinary ToolRunnable. */
|
|
66
|
+
readonly action: true;
|
|
67
|
+
/** Effect hints lowered into Core's existing tool metadata. */
|
|
68
|
+
readonly annotations: ActionAnnotations;
|
|
69
|
+
/** Required action description. */
|
|
70
|
+
readonly description: string;
|
|
71
|
+
/** Declared effect. */
|
|
72
|
+
readonly effect: ActionEffect;
|
|
73
|
+
/** Whether Core must queue approval before execution. */
|
|
74
|
+
readonly needsApproval: boolean;
|
|
75
|
+
/** Structured result schema, when the action returns one. */
|
|
76
|
+
readonly outputSchema?: Record<string, unknown>;
|
|
77
|
+
/** Lower this Action to a validated, installable plugin manifest. */
|
|
78
|
+
toManifest(options: ActionManifestOptions): PluginManifest;
|
|
79
|
+
/** Adapt this Action to the SDK MCP server using the same implementation. */
|
|
80
|
+
toMcpTool(context: RunnableContext): SdkRunnable;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Define one business operation that can be run locally, packaged as a Core
|
|
84
|
+
* tool, or registered on an SDK MCP server without rewriting its implementation.
|
|
85
|
+
*/
|
|
86
|
+
declare function defineAction<TInput extends Record<string, unknown> = Record<string, unknown>, TOutput = unknown>(options: ActionOptions<TInput, TOutput>): ActionRunnable<TInput, TOutput>;
|
|
87
|
+
|
|
88
|
+
export { type ActionAnnotations, type ActionEffect, type ActionManifestOptions, type ActionOptions, type ActionRunnable, defineAction };
|
package/dist/action.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Surface, PluginManifest } from './manifest.js';
|
|
2
|
+
import { SdkRunnable } from './mcp/server.js';
|
|
3
|
+
import { k as RunnableContext, o as ToolSchema, T as ToolRunnable } from './tool-AjkdFvhE.js';
|
|
4
|
+
import 'zod';
|
|
5
|
+
import './mcp/client.js';
|
|
6
|
+
import './client-D5U6ssPc.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Canonical Ryu Action authoring API.
|
|
10
|
+
*
|
|
11
|
+
* An Action is the semantic contract for a business operation: one description,
|
|
12
|
+
* input schema, output schema, implementation, and effect declaration. It lowers
|
|
13
|
+
* to Ryu's existing governed `inline_deno` Tool backend, so this adds a coherent
|
|
14
|
+
* authoring seam without introducing a second Core execution runtime.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** The two effects Core can enforce from tool annotations. */
|
|
18
|
+
type ActionEffect = "mutate" | "read";
|
|
19
|
+
/** MCP-compatible effect hints plus any future provider-neutral boolean hints. */
|
|
20
|
+
interface ActionAnnotations {
|
|
21
|
+
destructiveHint?: boolean;
|
|
22
|
+
idempotentHint?: boolean;
|
|
23
|
+
openWorldHint?: boolean;
|
|
24
|
+
readOnlyHint?: boolean;
|
|
25
|
+
[key: string]: boolean | undefined;
|
|
26
|
+
}
|
|
27
|
+
/** Options for defining a canonical Action. */
|
|
28
|
+
interface ActionOptions<TInput extends Record<string, unknown>, TOutput> {
|
|
29
|
+
/** Additional MCP-compatible effect hints. */
|
|
30
|
+
annotations?: ActionAnnotations;
|
|
31
|
+
/** Description the agent reads when deciding whether to call the action. */
|
|
32
|
+
description: string;
|
|
33
|
+
/** Explicit effect used by read-only and approval enforcement. */
|
|
34
|
+
effect: ActionEffect;
|
|
35
|
+
/** Stable action id, also used as the generated Core tool slug. */
|
|
36
|
+
id: string;
|
|
37
|
+
/** Human-readable action name. */
|
|
38
|
+
name: string;
|
|
39
|
+
/** Require human approval even when global smart mode would not classify it. */
|
|
40
|
+
needsApproval?: boolean;
|
|
41
|
+
/** JSON Schema for the structured action result. */
|
|
42
|
+
outputSchema?: Record<string, unknown>;
|
|
43
|
+
/** The one implementation used by local callers and the packaged tool body. */
|
|
44
|
+
run(input: TInput, ctx: RunnableContext): Promise<TOutput>;
|
|
45
|
+
/** JSON Schema for all action inputs. */
|
|
46
|
+
schema: ToolSchema;
|
|
47
|
+
}
|
|
48
|
+
/** Options for lowering one Action into a standalone Ryu plugin manifest. */
|
|
49
|
+
interface ActionManifestOptions {
|
|
50
|
+
/** Plugin activation events; defaults to eager activation. */
|
|
51
|
+
activationEvents?: readonly string[];
|
|
52
|
+
/** Extra Gateway grants required by the action body. */
|
|
53
|
+
grants?: readonly string[];
|
|
54
|
+
/** Reverse-domain plugin id (for example `com.acme.support`). */
|
|
55
|
+
id: string;
|
|
56
|
+
/** Display name; defaults to the Action name. */
|
|
57
|
+
name?: string;
|
|
58
|
+
/** Host surfaces this plugin targets. */
|
|
59
|
+
targets?: readonly Surface[];
|
|
60
|
+
/** Plugin semver. */
|
|
61
|
+
version: string;
|
|
62
|
+
}
|
|
63
|
+
/** A ToolRunnable with Action semantics and manifest/MCP adapters. */
|
|
64
|
+
interface ActionRunnable<TInput extends Record<string, unknown> = Record<string, unknown>, TOutput = unknown> extends ToolRunnable<TInput, TOutput> {
|
|
65
|
+
/** Discriminates this semantic contract from an ordinary ToolRunnable. */
|
|
66
|
+
readonly action: true;
|
|
67
|
+
/** Effect hints lowered into Core's existing tool metadata. */
|
|
68
|
+
readonly annotations: ActionAnnotations;
|
|
69
|
+
/** Required action description. */
|
|
70
|
+
readonly description: string;
|
|
71
|
+
/** Declared effect. */
|
|
72
|
+
readonly effect: ActionEffect;
|
|
73
|
+
/** Whether Core must queue approval before execution. */
|
|
74
|
+
readonly needsApproval: boolean;
|
|
75
|
+
/** Structured result schema, when the action returns one. */
|
|
76
|
+
readonly outputSchema?: Record<string, unknown>;
|
|
77
|
+
/** Lower this Action to a validated, installable plugin manifest. */
|
|
78
|
+
toManifest(options: ActionManifestOptions): PluginManifest;
|
|
79
|
+
/** Adapt this Action to the SDK MCP server using the same implementation. */
|
|
80
|
+
toMcpTool(context: RunnableContext): SdkRunnable;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Define one business operation that can be run locally, packaged as a Core
|
|
84
|
+
* tool, or registered on an SDK MCP server without rewriting its implementation.
|
|
85
|
+
*/
|
|
86
|
+
declare function defineAction<TInput extends Record<string, unknown> = Record<string, unknown>, TOutput = unknown>(options: ActionOptions<TInput, TOutput>): ActionRunnable<TInput, TOutput>;
|
|
87
|
+
|
|
88
|
+
export { type ActionAnnotations, type ActionEffect, type ActionManifestOptions, type ActionOptions, type ActionRunnable, defineAction };
|
package/dist/action.js
ADDED
package/dist/agent-plugin.d.cts
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* is deliberately NOT a copy of the whole native manifest — that would be a second
|
|
30
30
|
* source of truth with a stale-copy failure mode.
|
|
31
31
|
*
|
|
32
|
-
* Both `plugins-store/*` and `apps-store/*` use this one `PluginManifest` shape, so
|
|
32
|
+
* Both `plugins-store/{plugins,lsp,external_plugins}/*` and `apps-store/*` use this one `PluginManifest` shape, so
|
|
33
33
|
* one converter covers both stores.
|
|
34
34
|
*/
|
|
35
35
|
/** Agent Plugins spec version this module targets. */
|
package/dist/agent-plugin.d.ts
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* is deliberately NOT a copy of the whole native manifest — that would be a second
|
|
30
30
|
* source of truth with a stale-copy failure mode.
|
|
31
31
|
*
|
|
32
|
-
* Both `plugins-store/*` and `apps-store/*` use this one `PluginManifest` shape, so
|
|
32
|
+
* Both `plugins-store/{plugins,lsp,external_plugins}/*` and `apps-store/*` use this one `PluginManifest` shape, so
|
|
33
33
|
* one converter covers both stores.
|
|
34
34
|
*/
|
|
35
35
|
/** Agent Plugins spec version this module targets. */
|
package/dist/agent.cjs
CHANGED
|
@@ -282,6 +282,13 @@ function createPrimitives(transport) {
|
|
|
282
282
|
process_id: input.processId
|
|
283
283
|
})
|
|
284
284
|
},
|
|
285
|
+
storage: {
|
|
286
|
+
get: (input) => transport.bridge("storage.get", input),
|
|
287
|
+
set: (input) => transport.bridge("storage.set", input).then(() => void 0),
|
|
288
|
+
delete: (input) => transport.bridge("storage.delete", input).then(() => void 0),
|
|
289
|
+
keys: (input) => transport.bridge("storage.keys", input ?? {}).then((value) => Array.isArray(value) ? value : []),
|
|
290
|
+
compareAndSet: (input) => transport.bridge("storage.compareAndSet", input)
|
|
291
|
+
},
|
|
285
292
|
rag: {
|
|
286
293
|
retrieve: (input) => brokerCall(transport, "rag", "retrieve", input),
|
|
287
294
|
embed: (input) => brokerCall(transport, "rag", "embed", input),
|
package/dist/agent.d.cts
CHANGED
package/dist/agent.d.ts
CHANGED
package/dist/agent.js
CHANGED
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
resolveToolDefs,
|
|
9
9
|
runAgentLoop,
|
|
10
10
|
ryuTool
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-Z57QDDJR.js";
|
|
12
|
+
import "./chunk-ZTJWBRUL.js";
|
|
13
13
|
import "./chunk-HACAGK65.js";
|
|
14
14
|
import "./chunk-IKEDLLFY.js";
|
|
15
15
|
export {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Requires, Surface, PluginManifest } from './manifest.cjs';
|
|
1
|
+
import { Requires, SlashCommandContribution, Surface, PluginManifest } from './manifest.cjs';
|
|
2
|
+
import { T as ToolRunnable } from './tool-CgzW92O_.cjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Ryu App authoring factory — `defineApp`.
|
|
@@ -16,11 +17,13 @@ import { Requires, Surface, PluginManifest } from './manifest.cjs';
|
|
|
16
17
|
* - A **companion** tool (`accessible:true`) is a call target a mounted widget
|
|
17
18
|
* may invoke: it carries `widget_accessible:true` and gets no widget template.
|
|
18
19
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* `
|
|
20
|
+
* A tool may also attach a `ToolRunnable`. When present, its self-contained run
|
|
21
|
+
* body is emitted as Core's grant-gated `inline_deno` backend, so the widget and
|
|
22
|
+
* the behavior ship in one bundle. Without a runnable, the tool remains the
|
|
23
|
+
* declarative pass-through form: the widget renders from
|
|
24
|
+
* `window.openai.toolInput`/`toolOutput` and Core echoes the validated arguments
|
|
25
|
+
* as `structuredContent`. `ryu pack` bundles the `uiEntry` source into the
|
|
26
|
+
* manifest's `ui_code`.
|
|
24
27
|
*/
|
|
25
28
|
|
|
26
29
|
/** One tool a Ryu App declares. */
|
|
@@ -40,6 +43,13 @@ interface AppToolSpec {
|
|
|
40
43
|
invoking?: string;
|
|
41
44
|
/** Tool name (unqualified). The wire id is `<server>.<name>`. */
|
|
42
45
|
name: string;
|
|
46
|
+
/**
|
|
47
|
+
* Optional executable body for this tool. Core receives it as an
|
|
48
|
+
* `inline_deno` runnable and runs it in the deny-by-default tool sandbox.
|
|
49
|
+
* The body must be self-contained; use the injected `host` capability surface
|
|
50
|
+
* for governed model calls and other platform primitives.
|
|
51
|
+
*/
|
|
52
|
+
runnable?: Pick<ToolRunnable, "code" | "id" | "name" | "schema">;
|
|
43
53
|
}
|
|
44
54
|
/**
|
|
45
55
|
* The `requires` block as an AUTHOR writes it: both members optional. Distinct
|
|
@@ -78,6 +88,8 @@ interface DefineAppOptions {
|
|
|
78
88
|
requires?: DefineAppRequires;
|
|
79
89
|
/** MCP server namespace for the tool ids. Defaults to `slug`. */
|
|
80
90
|
server?: string;
|
|
91
|
+
/** Slash commands this app exposes in the chat composer. */
|
|
92
|
+
slashCommands?: SlashCommandContribution[];
|
|
81
93
|
/**
|
|
82
94
|
* App slug — used to build the widget uri (`ui://widget/<slug>.html`) and, when
|
|
83
95
|
* `server` is omitted, the MCP server namespace that qualifies each tool id.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Requires, Surface, PluginManifest } from './manifest.js';
|
|
1
|
+
import { Requires, SlashCommandContribution, Surface, PluginManifest } from './manifest.js';
|
|
2
|
+
import { T as ToolRunnable } from './tool-AjkdFvhE.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Ryu App authoring factory — `defineApp`.
|
|
@@ -16,11 +17,13 @@ import { Requires, Surface, PluginManifest } from './manifest.js';
|
|
|
16
17
|
* - A **companion** tool (`accessible:true`) is a call target a mounted widget
|
|
17
18
|
* may invoke: it carries `widget_accessible:true` and gets no widget template.
|
|
18
19
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* `
|
|
20
|
+
* A tool may also attach a `ToolRunnable`. When present, its self-contained run
|
|
21
|
+
* body is emitted as Core's grant-gated `inline_deno` backend, so the widget and
|
|
22
|
+
* the behavior ship in one bundle. Without a runnable, the tool remains the
|
|
23
|
+
* declarative pass-through form: the widget renders from
|
|
24
|
+
* `window.openai.toolInput`/`toolOutput` and Core echoes the validated arguments
|
|
25
|
+
* as `structuredContent`. `ryu pack` bundles the `uiEntry` source into the
|
|
26
|
+
* manifest's `ui_code`.
|
|
24
27
|
*/
|
|
25
28
|
|
|
26
29
|
/** One tool a Ryu App declares. */
|
|
@@ -40,6 +43,13 @@ interface AppToolSpec {
|
|
|
40
43
|
invoking?: string;
|
|
41
44
|
/** Tool name (unqualified). The wire id is `<server>.<name>`. */
|
|
42
45
|
name: string;
|
|
46
|
+
/**
|
|
47
|
+
* Optional executable body for this tool. Core receives it as an
|
|
48
|
+
* `inline_deno` runnable and runs it in the deny-by-default tool sandbox.
|
|
49
|
+
* The body must be self-contained; use the injected `host` capability surface
|
|
50
|
+
* for governed model calls and other platform primitives.
|
|
51
|
+
*/
|
|
52
|
+
runnable?: Pick<ToolRunnable, "code" | "id" | "name" | "schema">;
|
|
43
53
|
}
|
|
44
54
|
/**
|
|
45
55
|
* The `requires` block as an AUTHOR writes it: both members optional. Distinct
|
|
@@ -78,6 +88,8 @@ interface DefineAppOptions {
|
|
|
78
88
|
requires?: DefineAppRequires;
|
|
79
89
|
/** MCP server namespace for the tool ids. Defaults to `slug`. */
|
|
80
90
|
server?: string;
|
|
91
|
+
/** Slash commands this app exposes in the chat composer. */
|
|
92
|
+
slashCommands?: SlashCommandContribution[];
|
|
81
93
|
/**
|
|
82
94
|
* App slug — used to build the widget uri (`ui://widget/<slug>.html`) and, when
|
|
83
95
|
* `server` is omitted, the MCP server namespace that qualifies each tool id.
|
package/dist/builder.cjs
CHANGED
|
@@ -177,10 +177,18 @@ var ChatWidgetTemplateSchema = import_zod.z.object({
|
|
|
177
177
|
}).superRefine((value, ctx) => {
|
|
178
178
|
const count = Number(Boolean(value.backing.tool_id)) + Number(Boolean(value.backing.view_id));
|
|
179
179
|
if (count !== 1 && value.availability === "available") {
|
|
180
|
-
ctx.addIssue({
|
|
180
|
+
ctx.addIssue({
|
|
181
|
+
code: "custom",
|
|
182
|
+
path: ["backing"],
|
|
183
|
+
message: "available templates need exactly one backing tool_id or view_id"
|
|
184
|
+
});
|
|
181
185
|
}
|
|
182
186
|
if (count > 1) {
|
|
183
|
-
ctx.addIssue({
|
|
187
|
+
ctx.addIssue({
|
|
188
|
+
code: "custom",
|
|
189
|
+
path: ["backing"],
|
|
190
|
+
message: "backing must declare at most one of tool_id or view_id"
|
|
191
|
+
});
|
|
184
192
|
}
|
|
185
193
|
});
|
|
186
194
|
var ToolAppConfigSchema = import_zod.z.object({
|
|
@@ -203,6 +211,33 @@ var ToolAppConfigSchema = import_zod.z.object({
|
|
|
203
211
|
/** Optional status label shown when the render tool finishes. */
|
|
204
212
|
invoked: import_zod.z.string().optional()
|
|
205
213
|
});
|
|
214
|
+
var SlashCommandOptionSchema = import_zod.z.object({
|
|
215
|
+
description: import_zod.z.string().optional(),
|
|
216
|
+
label: import_zod.z.string().min(1),
|
|
217
|
+
value: import_zod.z.string().min(1)
|
|
218
|
+
}).passthrough();
|
|
219
|
+
var SlashCommandCustomOptionSchema = import_zod.z.union([
|
|
220
|
+
import_zod.z.literal(true),
|
|
221
|
+
import_zod.z.object({
|
|
222
|
+
description: import_zod.z.string().optional(),
|
|
223
|
+
label: import_zod.z.string().min(1).optional()
|
|
224
|
+
}).passthrough()
|
|
225
|
+
]);
|
|
226
|
+
var SlashCommandArgumentSchema = import_zod.z.object({
|
|
227
|
+
allow_custom: import_zod.z.boolean().optional(),
|
|
228
|
+
custom: SlashCommandCustomOptionSchema.optional(),
|
|
229
|
+
description: import_zod.z.string().optional(),
|
|
230
|
+
name: import_zod.z.string().min(1),
|
|
231
|
+
options: import_zod.z.array(SlashCommandOptionSchema).optional()
|
|
232
|
+
}).passthrough();
|
|
233
|
+
var SlashCommandContributionSchema = import_zod.z.object({
|
|
234
|
+
args: import_zod.z.array(SlashCommandArgumentSchema).optional(),
|
|
235
|
+
body: import_zod.z.string().optional(),
|
|
236
|
+
command: import_zod.z.string().min(1),
|
|
237
|
+
description: import_zod.z.string().optional(),
|
|
238
|
+
id: import_zod.z.string().optional(),
|
|
239
|
+
parameters: import_zod.z.array(SlashCommandArgumentSchema).optional()
|
|
240
|
+
}).passthrough();
|
|
206
241
|
var ContributesSchema = import_zod.z.object({
|
|
207
242
|
turn_hooks: import_zod.z.array(TurnHookContributionSchema).default([]),
|
|
208
243
|
/** App events this plugin EMITS — the provider half of the hook system, whose
|
|
@@ -217,7 +252,7 @@ var ContributesSchema = import_zod.z.object({
|
|
|
217
252
|
* feature declaration before signing. */
|
|
218
253
|
chat_features: import_zod.z.array(import_zod.z.record(import_zod.z.string(), import_zod.z.unknown())).default([]),
|
|
219
254
|
settings_tabs: import_zod.z.array(import_zod.z.record(import_zod.z.string(), import_zod.z.unknown())).default([]),
|
|
220
|
-
slash_commands: import_zod.z.array(
|
|
255
|
+
slash_commands: import_zod.z.array(SlashCommandContributionSchema).default([]),
|
|
221
256
|
/** App widgets (Ryu Apps). Each binds a render tool id to its
|
|
222
257
|
* `ui://widget/<slug>.html` template. Mirrors the Rust-side
|
|
223
258
|
* `Contributes.widgets` field, without which the CLI's zod parse would strip
|
|
@@ -284,7 +319,10 @@ var ContributesSchema = import_zod.z.object({
|
|
|
284
319
|
output_styles: import_zod.z.array(OutputStyleContributionSchema).default([]),
|
|
285
320
|
/** Per-message actions contributed by an enabled plugin. Kept as loose records
|
|
286
321
|
* so renderer-specific `kind`/`args` payloads survive `ryu pack` unchanged. */
|
|
287
|
-
message_actions: import_zod.z.array(import_zod.z.record(import_zod.z.string(), import_zod.z.unknown())).default([])
|
|
322
|
+
message_actions: import_zod.z.array(import_zod.z.record(import_zod.z.string(), import_zod.z.unknown())).default([]),
|
|
323
|
+
/** Buttons contributed to the floating text-selection toolbar. Kept as loose
|
|
324
|
+
* records so host-owned dispatch args survive `ryu pack` unchanged. */
|
|
325
|
+
selection_actions: import_zod.z.array(import_zod.z.record(import_zod.z.string(), import_zod.z.unknown())).default([])
|
|
288
326
|
});
|
|
289
327
|
var SetupStepSchema = import_zod.z.object({
|
|
290
328
|
/** Card heading (e.g. the companion app name). */
|
|
@@ -434,6 +472,9 @@ var PluginManifestSchema = import_zod.z.object({
|
|
|
434
472
|
/^\d+\.\d+\.\d+(?:-[\w.]+)?(?:\+[\w.]+)?$/,
|
|
435
473
|
"version must be a valid semver string (e.g. 1.0.0)"
|
|
436
474
|
),
|
|
475
|
+
/** Core-owned release maturity metadata. The Rust contract validates the
|
|
476
|
+
* richer shape; the SDK authoring parser must preserve it for pack/publish. */
|
|
477
|
+
stability: import_zod.z.unknown().optional(),
|
|
437
478
|
/**
|
|
438
479
|
* Lower-case hex `sha256(utf8_bytes(ui_code))` binding the plugin's bundled
|
|
439
480
|
* sandboxed-UI code to this manifest. `ryu pack` / `ryu publish` compute it and
|
|
@@ -451,8 +492,26 @@ var PluginManifestSchema = import_zod.z.object({
|
|
|
451
492
|
* Declarations only — grant enforcement is the Gateway's responsibility.
|
|
452
493
|
*/
|
|
453
494
|
permission_grants: import_zod.z.array(import_zod.z.string()).default([]),
|
|
495
|
+
/** Deny-by-default sandbox permissions. Core remains authoritative; this
|
|
496
|
+
* schema mirrors the fields so `ryu pack` cannot strip them. */
|
|
497
|
+
permissions: import_zod.z.object({
|
|
498
|
+
fs: import_zod.z.object({
|
|
499
|
+
read: import_zod.z.array(import_zod.z.string()).default([]),
|
|
500
|
+
write: import_zod.z.array(import_zod.z.string()).default([])
|
|
501
|
+
}).optional(),
|
|
502
|
+
child_process: import_zod.z.boolean().optional(),
|
|
503
|
+
run: import_zod.z.array(import_zod.z.string()).default([]),
|
|
504
|
+
network: import_zod.z.union([import_zod.z.boolean(), import_zod.z.array(import_zod.z.string())]).optional(),
|
|
505
|
+
tool: import_zod.z.array(import_zod.z.string()).default([])
|
|
506
|
+
}).optional(),
|
|
507
|
+
/** Core-owned permission presentation levels. Preserved verbatim here and
|
|
508
|
+
* validated by Core's authoritative manifest contract. */
|
|
509
|
+
permission_levels: import_zod.z.unknown().optional(),
|
|
454
510
|
/** Remote or stdio MCP servers registered by this plugin. */
|
|
455
511
|
mcp_servers: import_zod.z.record(import_zod.z.string(), McpServerDeclSchema).optional(),
|
|
512
|
+
/** Core-owned sidecar declarations. Their full process/HTTP schema stays in
|
|
513
|
+
* the Rust contract; this authoring layer must never strip them. */
|
|
514
|
+
sidecars: import_zod.z.unknown().optional(),
|
|
456
515
|
/**
|
|
457
516
|
* Optional Companion surface (an in-desktop overlay or sidebar panel).
|
|
458
517
|
* Absent when the plugin has no Companion surface.
|
|
@@ -488,6 +547,9 @@ var PluginManifestSchema = import_zod.z.object({
|
|
|
488
547
|
* an unsupported-target plugin stays installable and inspectable.
|
|
489
548
|
*/
|
|
490
549
|
targets: import_zod.z.array(SurfaceSchema).default([]),
|
|
550
|
+
/** Rich per-surface declarations (`support`, UI, contributed commands, …).
|
|
551
|
+
* Core owns and validates the nested vocabulary. */
|
|
552
|
+
surfaces: import_zod.z.unknown().optional(),
|
|
491
553
|
/**
|
|
492
554
|
* Host version floors — the semver requirement each surface must satisfy for
|
|
493
555
|
* this plugin to install. Mirrors Core's `EnginesReq`
|
|
@@ -602,7 +664,7 @@ var PluginManifestSchema = import_zod.z.object({
|
|
|
602
664
|
* array of steps guiding the user through post-install configuration.
|
|
603
665
|
*/
|
|
604
666
|
setup: import_zod.z.union([SetupStepSchema, import_zod.z.array(SetupStepSchema)]).optional()
|
|
605
|
-
}).superRefine((manifest, context) => {
|
|
667
|
+
}).passthrough().superRefine((manifest, context) => {
|
|
606
668
|
const hasOAuthServer = Object.values(manifest.mcp_servers ?? {}).some(
|
|
607
669
|
(server) => server.auth?.type === "oauth"
|
|
608
670
|
);
|
|
@@ -620,6 +682,26 @@ var PluginManifestSchema = import_zod.z.object({
|
|
|
620
682
|
}
|
|
621
683
|
});
|
|
622
684
|
|
|
685
|
+
// src/runnable/tool.ts
|
|
686
|
+
function inlineToolRunnable(tool2, options) {
|
|
687
|
+
return {
|
|
688
|
+
id: tool2.id,
|
|
689
|
+
name: tool2.name,
|
|
690
|
+
kind: "tool",
|
|
691
|
+
config: {
|
|
692
|
+
slug: tool2.id,
|
|
693
|
+
backend: "inline_deno",
|
|
694
|
+
code: tool2.code,
|
|
695
|
+
input_schema: tool2.schema,
|
|
696
|
+
...options?.description === void 0 ? tool2.description === void 0 ? {} : { description: tool2.description } : { description: options.description },
|
|
697
|
+
...options?.outputSchema ? { output_schema: options.outputSchema } : {},
|
|
698
|
+
...options?.annotations ? { annotations: options.annotations } : {},
|
|
699
|
+
...options?.action === void 0 ? {} : { action: options.action },
|
|
700
|
+
...options?.needsApproval === void 0 ? {} : { needs_approval: options.needsApproval }
|
|
701
|
+
}
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
|
|
623
705
|
// src/runnable/app.ts
|
|
624
706
|
var DEFAULT_APP_WIDGET_MIME = "text/html+skybridge";
|
|
625
707
|
var DEFAULT_APP_DISPLAY_MODE = "inline";
|
|
@@ -631,6 +713,13 @@ function withWidgetRenderGrant(grants, widgets) {
|
|
|
631
713
|
}
|
|
632
714
|
return out;
|
|
633
715
|
}
|
|
716
|
+
function withToolExecuteGrant(grants, tools) {
|
|
717
|
+
const out = [...grants];
|
|
718
|
+
if (tools.some((tool2) => tool2.runnable !== void 0) && !out.includes("tool:execute")) {
|
|
719
|
+
out.push("tool:execute");
|
|
720
|
+
}
|
|
721
|
+
return out;
|
|
722
|
+
}
|
|
634
723
|
function appToolId(server, name) {
|
|
635
724
|
return `${server}.${name}`;
|
|
636
725
|
}
|
|
@@ -645,7 +734,9 @@ function defineApp(options) {
|
|
|
645
734
|
for (const spec of options.tools) {
|
|
646
735
|
const isRender = spec.accessible !== true;
|
|
647
736
|
const id = appToolId(server, spec.name);
|
|
737
|
+
const executable = spec.runnable ? inlineToolRunnable(spec.runnable) : void 0;
|
|
648
738
|
const config = {
|
|
739
|
+
...executable?.config ?? {},
|
|
649
740
|
slug: id,
|
|
650
741
|
description: spec.description,
|
|
651
742
|
widget: isRender,
|
|
@@ -679,7 +770,7 @@ function defineApp(options) {
|
|
|
679
770
|
hook_events: [],
|
|
680
771
|
composer_controls: [],
|
|
681
772
|
settings_tabs: [],
|
|
682
|
-
slash_commands: [],
|
|
773
|
+
slash_commands: options.slashCommands ?? [],
|
|
683
774
|
sidebar_sections: [],
|
|
684
775
|
sidebar_buttons: [],
|
|
685
776
|
dock_panels: [],
|
|
@@ -697,6 +788,7 @@ function defineApp(options) {
|
|
|
697
788
|
pi_extensions: [],
|
|
698
789
|
output_styles: [],
|
|
699
790
|
message_actions: [],
|
|
791
|
+
selection_actions: [],
|
|
700
792
|
widgets
|
|
701
793
|
};
|
|
702
794
|
const raw = {
|
|
@@ -710,15 +802,15 @@ function defineApp(options) {
|
|
|
710
802
|
// Core gates widget promotion on declared-AND-enabled-AND-granted, and a
|
|
711
803
|
// missing grant fails as `DeniedNoGrant` — which is an `info!` log and
|
|
712
804
|
// nothing else. The widget silently renders as plain text, with no error
|
|
713
|
-
// in the UI and nothing pointing at the manifest.
|
|
714
|
-
// through `defineApp` hit that, because the only fix was a grant string
|
|
715
|
-
// the templates never mention and the builder never added; the one
|
|
716
|
-
// working example on disk hand-writes it.
|
|
805
|
+
// in the UI and nothing pointing at the manifest.
|
|
717
806
|
//
|
|
718
807
|
// Added only when there is a widget to render, and unioned rather than
|
|
719
808
|
// overwritten so an author's own `grants` list survives and re-declaring
|
|
720
809
|
// it is not an error.
|
|
721
|
-
permission_grants:
|
|
810
|
+
permission_grants: withToolExecuteGrant(
|
|
811
|
+
withWidgetRenderGrant(options.grants ?? [], widgets),
|
|
812
|
+
options.tools
|
|
813
|
+
),
|
|
722
814
|
activation_events: options.activationEvents ?? ["*"],
|
|
723
815
|
contributes,
|
|
724
816
|
// `targets: []` means EVERY surface, so an app that declares none is
|
|
@@ -959,6 +1051,7 @@ var AppBuilder = class {
|
|
|
959
1051
|
_dependencies = [];
|
|
960
1052
|
_requiredCapabilities = [];
|
|
961
1053
|
_requiredGrants = [];
|
|
1054
|
+
_slashCommands = [];
|
|
962
1055
|
_targets = [];
|
|
963
1056
|
/** Set the reverse-domain app id (e.g. `"com.example.checklist"`). */
|
|
964
1057
|
id(value) {
|
|
@@ -1015,6 +1108,11 @@ var AppBuilder = class {
|
|
|
1015
1108
|
this._tools.push(spec);
|
|
1016
1109
|
return this;
|
|
1017
1110
|
}
|
|
1111
|
+
/** Add a slash command and its optional sequential argument choices. */
|
|
1112
|
+
slashCommand(command) {
|
|
1113
|
+
this._slashCommands.push(command);
|
|
1114
|
+
return this;
|
|
1115
|
+
}
|
|
1018
1116
|
/**
|
|
1019
1117
|
* Declare a **plugin-to-plugin dependency** (auto-enabled, in dependency order,
|
|
1020
1118
|
* before this app). `minVersion` is a MINIMUM (`"1.2.0"` = `">=1.2.0"`).
|
|
@@ -1062,6 +1160,7 @@ var AppBuilder = class {
|
|
|
1062
1160
|
uiEntry: this._uiEntry,
|
|
1063
1161
|
tools: this._tools,
|
|
1064
1162
|
grants: this._grants,
|
|
1163
|
+
slashCommands: this._slashCommands,
|
|
1065
1164
|
...this._server ? { server: this._server } : {},
|
|
1066
1165
|
...this._displayMode ? { displayMode: this._displayMode } : {},
|
|
1067
1166
|
...this._mime ? { mime: this._mime } : {},
|
package/dist/builder.d.cts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { RunnableMeta, Surface, PluginManifest, CompanionSurface } from './manifest.cjs';
|
|
2
|
-
import { A as AppToolSpec } from './app-
|
|
1
|
+
import { RunnableMeta, SlashCommandContribution, Surface, PluginManifest, CompanionSurface } from './manifest.cjs';
|
|
2
|
+
import { A as AppToolSpec } from './app-B0Z9Ew_R.cjs';
|
|
3
3
|
import 'zod';
|
|
4
|
+
import './tool-CgzW92O_.cjs';
|
|
5
|
+
import './client-D5U6ssPc.cjs';
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* Ryu SDK typed builders — one builder per RunnableKind plus a PluginBuilder that
|
|
@@ -160,6 +162,7 @@ declare class AppBuilder {
|
|
|
160
162
|
private readonly _dependencies;
|
|
161
163
|
private readonly _requiredCapabilities;
|
|
162
164
|
private readonly _requiredGrants;
|
|
165
|
+
private readonly _slashCommands;
|
|
163
166
|
private readonly _targets;
|
|
164
167
|
/** Set the reverse-domain app id (e.g. `"com.example.checklist"`). */
|
|
165
168
|
id(value: string): this;
|
|
@@ -183,6 +186,8 @@ declare class AppBuilder {
|
|
|
183
186
|
activationEvent(event: string): this;
|
|
184
187
|
/** Append a tool spec (render tool unless `accessible:true`). */
|
|
185
188
|
tool(spec: AppToolSpec): this;
|
|
189
|
+
/** Add a slash command and its optional sequential argument choices. */
|
|
190
|
+
slashCommand(command: SlashCommandContribution): this;
|
|
186
191
|
/**
|
|
187
192
|
* Declare a **plugin-to-plugin dependency** (auto-enabled, in dependency order,
|
|
188
193
|
* before this app). `minVersion` is a MINIMUM (`"1.2.0"` = `">=1.2.0"`).
|
package/dist/builder.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { RunnableMeta, Surface, PluginManifest, CompanionSurface } from './manifest.js';
|
|
2
|
-
import { A as AppToolSpec } from './app-
|
|
1
|
+
import { RunnableMeta, SlashCommandContribution, Surface, PluginManifest, CompanionSurface } from './manifest.js';
|
|
2
|
+
import { A as AppToolSpec } from './app-C-BDJwfG.js';
|
|
3
3
|
import 'zod';
|
|
4
|
+
import './tool-AjkdFvhE.js';
|
|
5
|
+
import './client-D5U6ssPc.js';
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* Ryu SDK typed builders — one builder per RunnableKind plus a PluginBuilder that
|
|
@@ -160,6 +162,7 @@ declare class AppBuilder {
|
|
|
160
162
|
private readonly _dependencies;
|
|
161
163
|
private readonly _requiredCapabilities;
|
|
162
164
|
private readonly _requiredGrants;
|
|
165
|
+
private readonly _slashCommands;
|
|
163
166
|
private readonly _targets;
|
|
164
167
|
/** Set the reverse-domain app id (e.g. `"com.example.checklist"`). */
|
|
165
168
|
id(value: string): this;
|
|
@@ -183,6 +186,8 @@ declare class AppBuilder {
|
|
|
183
186
|
activationEvent(event: string): this;
|
|
184
187
|
/** Append a tool spec (render tool unless `accessible:true`). */
|
|
185
188
|
tool(spec: AppToolSpec): this;
|
|
189
|
+
/** Add a slash command and its optional sequential argument choices. */
|
|
190
|
+
slashCommand(command: SlashCommandContribution): this;
|
|
186
191
|
/**
|
|
187
192
|
* Declare a **plugin-to-plugin dependency** (auto-enabled, in dependency order,
|
|
188
193
|
* before this app). `minVersion` is a MINIMUM (`"1.2.0"` = `">=1.2.0"`).
|
package/dist/builder.js
CHANGED
|
@@ -10,9 +10,10 @@ import {
|
|
|
10
10
|
skill,
|
|
11
11
|
tool,
|
|
12
12
|
workflow
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-HLKJZAFK.js";
|
|
14
|
+
import "./chunk-SN2QBJUF.js";
|
|
15
|
+
import "./chunk-QYFUNJOH.js";
|
|
16
|
+
import "./chunk-NZKVOSC2.js";
|
|
16
17
|
export {
|
|
17
18
|
AgentBuilder,
|
|
18
19
|
AppBuilder,
|