@elyracode/stack-elyra-framework 0.9.18
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/CHANGELOG.md +6 -0
- package/README.md +26 -0
- package/extensions/index.ts +13 -0
- package/package.json +38 -0
- package/skills/elyra-framework/SKILL.md +184 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.9.18] - 2026-07-18
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Initial release: stack profile for Elyra Framework (Rust + Svelte 5 desktop apps). Ships a deep `elyra-framework` skill (commands, `Ctx`/container, typed bridge/codegen, `EventBus`, `Database`/`#[derive(Model)]`, `Cache`/`Storage`/`Queue` facades, the `elyra::ai` SDK, system integration, and the `rata` CLI) and a `/elyra-framework:info` command.
|
package/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# @elyracode/stack-elyra-framework
|
|
2
|
+
|
|
3
|
+
Elyra stack profile for [Elyra Framework](https://github.com/kwhorne/elyra-framework) — a Rust + Svelte 5 framework for hyper-responsive desktop apps, with Laravel-inspired ergonomics (container, providers, middleware, a typed bridge) but compiled, binary, and without runtime overhead.
|
|
4
|
+
|
|
5
|
+
Gives the agent deep, working knowledge of the framework's actual API: `#[command]` handlers, the `Ctx`/container, the typed MessagePack bridge (`rata codegen`), `EventBus`/`channel()`, `#[derive(Model)]` + the query builder, the `Cache`/`Storage`/`Queue` facades, the `elyra::ai` SDK, and the `rata` CLI workflow — so generated Rust and Svelte code matches the framework's real conventions instead of guessing at a generic Tauri-like API.
|
|
6
|
+
|
|
7
|
+
## Detection
|
|
8
|
+
|
|
9
|
+
Detected automatically by `/init` when a project has:
|
|
10
|
+
- an `elyra.toml` config file (written by `rata new`), or
|
|
11
|
+
- a `Cargo.toml` with `elyra` as a dependency
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
elyra install npm:@elyracode/stack-elyra-framework
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## What's included
|
|
20
|
+
|
|
21
|
+
- **`elyra-framework` skill**: architecture, the `#[command]` + middleware pipeline, `Ctx`/container/providers, the typed bridge (`rata codegen` → generated `api.*`), `EventBus`/`channel()`, `Database`/`#[derive(Model)]`/migrations, `Cache`/`Storage`/`Queue` facades, the `elyra::ai` SDK, system integration (dialogs, tray, shortcuts, updater), and the `rata` CLI workflow.
|
|
22
|
+
- **`/elyra-framework:info`**: quick reference to the loaded skill.
|
|
23
|
+
|
|
24
|
+
## Learn more
|
|
25
|
+
|
|
26
|
+
Full documentation lives at [elyracode.com/framework](https://elyracode.com/framework).
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@elyracode/coding-agent";
|
|
2
|
+
|
|
3
|
+
export default function (elyra: ExtensionAPI) {
|
|
4
|
+
elyra.registerCommand("elyra-framework:info", {
|
|
5
|
+
description: "Show detected Elyra Framework information",
|
|
6
|
+
handler: async (_args, ctx) => {
|
|
7
|
+
ctx.ui.notify(
|
|
8
|
+
"Elyra Framework stack profile loaded. Skills: elyra-framework. Use /skill:elyra-framework for the full reference.",
|
|
9
|
+
"info",
|
|
10
|
+
);
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@elyracode/stack-elyra-framework",
|
|
3
|
+
"version": "0.9.18",
|
|
4
|
+
"description": "Elyra stack profile for Elyra Framework (Rust + Svelte 5 desktop apps, https://github.com/kwhorne/elyra-framework)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"elyra-package",
|
|
8
|
+
"elyra-framework",
|
|
9
|
+
"rust",
|
|
10
|
+
"svelte",
|
|
11
|
+
"desktop",
|
|
12
|
+
"ratatosk"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"author": "Knut W. Horne",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/kwhorne/elyra.git",
|
|
19
|
+
"directory": "packages/stack-elyra-framework"
|
|
20
|
+
},
|
|
21
|
+
"elyra": {
|
|
22
|
+
"skills": [
|
|
23
|
+
"./skills"
|
|
24
|
+
],
|
|
25
|
+
"extensions": [
|
|
26
|
+
"./extensions/index.ts"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"@elyracode/coding-agent": "*",
|
|
31
|
+
"typebox": "*"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"clean": "echo 'nothing to clean'",
|
|
35
|
+
"build": "echo 'nothing to build'",
|
|
36
|
+
"check": "echo 'nothing to check'"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: elyra-framework
|
|
3
|
+
description: Deep knowledge of Elyra Framework - a Rust + Svelte 5 framework for compiled, binary desktop apps with Laravel-inspired ergonomics. Use when working on Elyra Framework projects, #[command] handlers, the typed MessagePack bridge, EventBus/channel(), Database models, Cache/Storage/Queue facades, the elyra::ai SDK, or the rata CLI.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Elyra Framework Reference
|
|
7
|
+
|
|
8
|
+
Elyra Framework (crate: `elyra`, CLI: `rata`/Ratatosk) is a Rust + Svelte 5 framework for desktop apps. It brings Laravel's ergonomics — container, providers, middleware, a typed bridge — to a compiled, binary app with no runtime overhead (no Electron, no Node runtime bundled).
|
|
9
|
+
|
|
10
|
+
Not to be confused with the Elyra coding agent itself (`@elyracode/coding-agent`) — this skill is about the separate Rust desktop framework of the same name, at https://github.com/kwhorne/elyra-framework, docs at elyracode.com/framework.
|
|
11
|
+
|
|
12
|
+
## Architecture
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
elyra-framework/
|
|
16
|
+
├── framework/ # crate: elyra — App, Container/Ctx, Command, events, shell (tao+wry)
|
|
17
|
+
├── macros/ # crate: elyra-macros — #[command] and #[derive(Model)]
|
|
18
|
+
├── database/ # crate: elyra-db — Database, migrations, models (GUI-free)
|
|
19
|
+
├── ratatosk/ # crate: ratatosk — the `rata` CLI
|
|
20
|
+
├── runtime/ # npm: @elyra/runtime — invoke(), channel(), generated api.*
|
|
21
|
+
└── example/ # crate: elyra-example — demo app / DX benchmark
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The Rust side (root, Yggdrasil) talks to the Svelte side (crown) over **binary IPC**: MessagePack over an `elyra://localhost` custom protocol, not JSON over stdin/HTTP. `rata` is the CLI that runs messages up and down between the two — hence "Ratatosk," the squirrel of Norse myth.
|
|
25
|
+
|
|
26
|
+
## Commands: the core request/response primitive
|
|
27
|
+
|
|
28
|
+
A command is an async function annotated `#[command]`, dispatched through a middleware pipeline with dependency injection from the container:
|
|
29
|
+
|
|
30
|
+
```rust
|
|
31
|
+
use elyra::{command, commands, App, Ctx};
|
|
32
|
+
|
|
33
|
+
#[command]
|
|
34
|
+
async fn greet(_ctx: Ctx, name: String) -> String {
|
|
35
|
+
format!("Hello, {name}!")
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
fn main() -> elyra::Result<()> {
|
|
39
|
+
App::new()
|
|
40
|
+
.commands(commands![greet])
|
|
41
|
+
.assets(elyra::asset_resolver::<Assets>())
|
|
42
|
+
.run()
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Frontend calls it through the generated, typed facade (never hand-written fetch/JSON):
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { api } from "./bindings"; // generated by `rata codegen`
|
|
50
|
+
const greeting = await api.greet("World"); // (name: string) => Promise<string>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Rules of thumb:
|
|
54
|
+
- Register every command in `commands![...]` inside `App::new()`. An un-registered `#[command]` function is dead code the frontend can't call.
|
|
55
|
+
- The first parameter is always `Ctx` (or a type resolvable from it) — the container-provided context, analogous to a Laravel controller's dependency-injected services.
|
|
56
|
+
- Errors: return `Result<T, E>` where `E` implements the framework's error trait so failures surface as typed rejections on the frontend, not opaque strings.
|
|
57
|
+
- After adding, removing, or changing the signature of a `#[command]` function, **always re-run `rata codegen`** before touching the frontend — the generated `api.*` facade and its TS types are the source of truth for what the frontend can call, and stale bindings are a common source of "why doesn't this compile" confusion.
|
|
58
|
+
|
|
59
|
+
## The typed bridge (codegen)
|
|
60
|
+
|
|
61
|
+
`rata codegen` inspects `#[command]` functions and any `specta`-derived types, then emits:
|
|
62
|
+
- TypeScript types for every command's parameters and return type
|
|
63
|
+
- A typed `api.*` facade in the frontend bindings file
|
|
64
|
+
|
|
65
|
+
Never hand-author the bridge types or the `api.*` facade — they are generated output. If a type looks wrong on the frontend, fix the Rust type (often a missing `#[derive(specta::Type)]` or an unhandled enum variant) and re-run `rata codegen`, rather than patching the generated file.
|
|
66
|
+
|
|
67
|
+
## Events: Rust → frontend push
|
|
68
|
+
|
|
69
|
+
`EventBus` plus `channel()` lets Rust push data to the frontend without the frontend polling — batched per flush over a long-poll, so the UI thread never blocks:
|
|
70
|
+
|
|
71
|
+
```rust
|
|
72
|
+
// Rust: emit
|
|
73
|
+
ctx.events().emit("progress", ProgressPayload { percent: 42 });
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
// Svelte: subscribe
|
|
78
|
+
import { channel } from "@elyra/runtime";
|
|
79
|
+
const unlisten = await channel("progress", (payload) => {
|
|
80
|
+
progress = payload.percent;
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Use events for anything long-running or streaming (file operations, background jobs, AI SDK streaming responses) — commands are request/response and block the caller until they resolve; events are the push side.
|
|
85
|
+
|
|
86
|
+
## Database: `Database`, `#[derive(Model)]`, migrations
|
|
87
|
+
|
|
88
|
+
One `Database` abstraction over SQLite/MySQL/Postgres, with Active Record-style models:
|
|
89
|
+
|
|
90
|
+
```rust
|
|
91
|
+
use elyra_db::{derive::Model, Database};
|
|
92
|
+
|
|
93
|
+
#[derive(Model)]
|
|
94
|
+
#[model(table = "users")]
|
|
95
|
+
struct User {
|
|
96
|
+
id: i64,
|
|
97
|
+
name: String,
|
|
98
|
+
email: String,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Query builder + relations, Eloquent-flavored:
|
|
102
|
+
let user = User::query().where_eq("email", &email).first(&db).await?;
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
- `rata migrate` runs migrations, mirroring `php artisan migrate`'s workflow.
|
|
106
|
+
- `database` is a Cargo feature — enable it in `Cargo.toml` before `Database`/`#[derive(Model)]`/`App::database` are available.
|
|
107
|
+
- The database layer (`elyra-db`) is GUI-free by design, so it can be tested and used headlessly (e.g. in a sidecar process) without pulling in `tao`/`wry`.
|
|
108
|
+
|
|
109
|
+
## Shared facades: `Cache`, `Storage`, `Queue`
|
|
110
|
+
|
|
111
|
+
Mirror the Askr/Laravel side's surface, over local backends — same ergonomics, different runtime:
|
|
112
|
+
|
|
113
|
+
```rust
|
|
114
|
+
Cache::put("key", value, Duration::from_secs(60)).await?;
|
|
115
|
+
let value: Option<T> = Cache::get("key").await?;
|
|
116
|
+
|
|
117
|
+
Storage::disk("local").put("path/file.txt", bytes).await?;
|
|
118
|
+
|
|
119
|
+
Queue::push(SomeJob { ... }).await?;
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Reach for these instead of hand-rolling a cache/queue/storage layer — they're the "one ecosystem, two worlds" pitch: the same facade shape whether you're on the Laravel/PHP side of a project or the Rust desktop side.
|
|
123
|
+
|
|
124
|
+
## AI SDK (`elyra::ai`, feature `ai`)
|
|
125
|
+
|
|
126
|
+
A Laravel-inspired AI SDK: agents, tools, sub-agents (`CanActAsTool`), structured output, streaming, provider tools, images, audio, embeddings, RAG, plus retries/failover/caching — over Anthropic and OpenAI.
|
|
127
|
+
|
|
128
|
+
```rust
|
|
129
|
+
use elyra::ai::{Agent, Tool};
|
|
130
|
+
|
|
131
|
+
let agent = Agent::new("assistant")
|
|
132
|
+
.instructions("You are a helpful assistant.")
|
|
133
|
+
.tools(vec![my_tool]);
|
|
134
|
+
|
|
135
|
+
let response = agent.run("What's the weather?").await?;
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Requires the `ai` Cargo feature. Prefer streaming (events, not a blocking command) for chat-style UIs so the frontend can render tokens as they arrive instead of waiting for the full response.
|
|
139
|
+
|
|
140
|
+
## System integration and UI components
|
|
141
|
+
|
|
142
|
+
Behind feature flags, `App` exposes:
|
|
143
|
+
- **`system`**: native dialogs, shell-open, clipboard, notifications, paths
|
|
144
|
+
- **`tray`**: system tray
|
|
145
|
+
- **`shortcuts`**: OS-level global keyboard shortcuts
|
|
146
|
+
- **`updater`**: ed25519-verified auto-updater
|
|
147
|
+
- Built-in UI: themed About dialog, auto-update toast, dialogs/toasts/⌘K command palette/context menu
|
|
148
|
+
- Window control + file drop + state persistence, native app menu, a settings store, autostart, sidecar processes, single-instance + deep-linking
|
|
149
|
+
|
|
150
|
+
```toml
|
|
151
|
+
[dependencies]
|
|
152
|
+
elyra = { version = "0.5", features = ["database", "tray", "updater", "system", "shortcuts"] }
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Only enable the features a project actually uses — each one pulls in its own native bindings and increases binary size.
|
|
156
|
+
|
|
157
|
+
## CLI workflow (`rata`)
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
rata new myapp # scaffold a new project (writes elyra.toml)
|
|
161
|
+
cd myapp
|
|
162
|
+
(cd app && npm install && npm run build)
|
|
163
|
+
rata codegen # generate typed bindings from #[command]s
|
|
164
|
+
cargo run # launch
|
|
165
|
+
rata migrate # run database migrations (feature: database)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
`elyra.toml` at the project root is the framework's own config file, written by `rata new` — its presence is the most reliable signal that a project uses Elyra Framework (more reliable than grepping `Cargo.toml`, which could reference the crate without the project having been scaffolded via `rata`).
|
|
169
|
+
|
|
170
|
+
To try the framework itself without scaffolding a project:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
cargo run -p elyra-example # bundled demo app, no npm needed
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Working in an Elyra Framework project — checklist
|
|
177
|
+
|
|
178
|
+
1. **New backend capability → `#[command]`.** Register it in `commands![...]`, run `rata codegen`, then wire the frontend against the generated `api.*` — never hand-write the IPC call.
|
|
179
|
+
2. **Long-running/streaming work → `EventBus`/`channel()`**, not a command that blocks until done.
|
|
180
|
+
3. **Persistent data → `Database`/`#[derive(Model)]`**, not ad-hoc file I/O — enable the `database` feature first.
|
|
181
|
+
4. **Cross-cutting cache/storage/queue needs → the shared facades**, not a bespoke implementation.
|
|
182
|
+
5. **After any change to a `#[command]` signature or a `specta`-derived type, re-run `rata codegen` before touching Svelte code.**
|
|
183
|
+
6. **Only enable the Cargo features you need** (`database`, `tray`, `updater`, `system`, `shortcuts`, `ai`) — each has a real footprint.
|
|
184
|
+
7. For deeper topics (window management specifics, the full `elyra::ai` API surface, migration syntax), point the user to elyracode.com/framework — this skill covers the architecture and the common patterns, not the exhaustive API reference.
|