@alashi/cli 0.2.0 → 0.3.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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alashi/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "alashi host: install, manage, and run Claude Code-powered apps",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"templates"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@alashi/apps-sdk": "^0.
|
|
32
|
+
"@alashi/apps-sdk": "^0.2.0",
|
|
33
33
|
"@hono/node-server": "^2.1.1",
|
|
34
34
|
"commander": "^14.0.0",
|
|
35
35
|
"croner": "^10.0.1",
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Agent guide: __APP_NAME__ (an alashi app)
|
|
2
|
+
|
|
3
|
+
This repo is an **alashi app**: one directory the [alashi](https://github.com/alashi-dev/alashi)
|
|
4
|
+
host installs and runs. The default export of `index.mjs` is `defineApp({...})`
|
|
5
|
+
from `@alashi/apps-sdk`. The full annotated guide lives in
|
|
6
|
+
`node_modules/@alashi/apps-sdk/README.md`; exact types in
|
|
7
|
+
`node_modules/@alashi/apps-sdk/dist/index.d.mts`. Read those before adding
|
|
8
|
+
manifest surface — the schema is strict (unknown keys are rejected at install).
|
|
9
|
+
|
|
10
|
+
## The contract (`defineApp` fields)
|
|
11
|
+
|
|
12
|
+
Manifest (all optional except name/version):
|
|
13
|
+
|
|
14
|
+
| Field | What it is |
|
|
15
|
+
|---|---|
|
|
16
|
+
| `name` | `^[a-z0-9][a-z0-9-]{0,63}$`; becomes `/app/<name>/` |
|
|
17
|
+
| `version`, `description`, `sdkVersion` | semver; `sdkVersion` is an engines-style range checked at install |
|
|
18
|
+
| `ui` | static assets dir (default `ui/`), served at `/app/<name>/` |
|
|
19
|
+
| `instructions` | system prompt applied to **every** AI session the app opens |
|
|
20
|
+
| `config` | declared user-facing keys: `{ description, label?, required?, secret?, default?, group? }` — rendered on the host settings page (`group` makes sections, `secret` masks, boolean defaults render checkboxes) |
|
|
21
|
+
| `configDefaults` | lowest layer of the config merge (defaults < global < per-app user config) |
|
|
22
|
+
| `mcpServers` | stdio (`{command, args?, env?}`) or remote (`{type: 'http'\|'sse', url, headers?}`); values may use `${config.*}` placeholders; `optional: true` = integration is absent until its config keys are set (app must degrade gracefully) |
|
|
23
|
+
| `skills` | relative dirs each containing a `SKILL.md` the engine loads |
|
|
24
|
+
| `agents` | subagent definition files, e.g. `['agents/analyst.md']` — `.md` with YAML frontmatter (`description`, `model?`, `tools?`), body = prompt, name = filename |
|
|
25
|
+
| `permissions.allowedTools` | tool allowlist, e.g. `mcp__grafana__*`; deny by default, never interactive |
|
|
26
|
+
| `jobs` | `[{ name, schedule (cron), description? }]` — host runs them; every job needs a matching `jobHandlers[name]` |
|
|
27
|
+
|
|
28
|
+
Beside the manifest: `routes` (fetch-style `(Request, ctx) => Response`) and
|
|
29
|
+
`jobHandlers` (`{ [name]: (ctx) => Promise<void> }`).
|
|
30
|
+
|
|
31
|
+
Known gap: `onInstall`/`onUpdate` exist in the SDK but the host never calls
|
|
32
|
+
them — create DB schema lazily (`CREATE TABLE IF NOT EXISTS` on first open).
|
|
33
|
+
|
|
34
|
+
## Runtime surface (`ctx`)
|
|
35
|
+
|
|
36
|
+
- `ctx.dataDir` — the **only** writable directory. SQLite DB and files go
|
|
37
|
+
here (`node:sqlite` `DatabaseSync`). Treat the repo itself as read-only at
|
|
38
|
+
runtime.
|
|
39
|
+
- `ctx.config` — merged config (readonly).
|
|
40
|
+
- `ctx.state` — small key/value store; `ctx.logger` — log here, not console.
|
|
41
|
+
- `ctx.ai.createSession()` — an agent session, pre-scoped by the host
|
|
42
|
+
(instructions, configured mcpServers, allowedTools, agents, skills,
|
|
43
|
+
cwd = dataDir). Works from routes **and** job handlers; chat is just one
|
|
44
|
+
caller. `session.send(text)` yields `AgentEvent`s:
|
|
45
|
+
`session | text | thinking | tool_use | tool_result | result (ok, costUsd, error)`.
|
|
46
|
+
Always `close()` in a `finally`. Resume with `createSession({ resume: id })`.
|
|
47
|
+
- Persist **session id pointers only**, never transcripts — the engine owns
|
|
48
|
+
those (the host's history endpoint reads them back).
|
|
49
|
+
|
|
50
|
+
## What the host already provides (do not rebuild)
|
|
51
|
+
|
|
52
|
+
- `POST /api/apps/<name>/chat` — SSE chat turns (`x-conversation-id` header)
|
|
53
|
+
- `GET/POST /api/apps/<name>/chat/conversations` — list; POST
|
|
54
|
+
`{sessionId, title?}` adopts an existing engine session as a conversation
|
|
55
|
+
- `GET /api/apps/<name>/chat/<id>/history` — transcript view
|
|
56
|
+
- `GET /api/apps/<name>/jobs`, `POST .../jobs/<name>/run` — job state + manual runs
|
|
57
|
+
- `/settings/<name>` — generated settings page from declared `config`
|
|
58
|
+
- **System UI, served not bundled**: `/assets/v1/system.css` (theme via
|
|
59
|
+
`:root { --accent: ... }` token overrides only) and `/assets/v1/chat.js` —
|
|
60
|
+
the `<alashi-chat>` web component (conversations, SSE streaming, safe
|
|
61
|
+
markdown incl. images, tool status, cost). Attributes: `app`,
|
|
62
|
+
`placeholder`. Methods: `adoptSession(sessionId, title?)`,
|
|
63
|
+
`openConversation(id)`, `newChat()`. Bubbling events: `alashi-chat:turn`
|
|
64
|
+
(`{ok, costUsd, error, conversationId}`), `alashi-chat:conversation`.
|
|
65
|
+
Never vendor or fork system UI; breaking changes ship as `/assets/v2/`.
|
|
66
|
+
|
|
67
|
+
## App routes
|
|
68
|
+
|
|
69
|
+
`routes` is mounted at `/app/<name>/api/*` (prefix stripped). Static files in
|
|
70
|
+
`ui/` win; unmatched paths fall through to `routes`, so server-rendering works.
|
|
71
|
+
|
|
72
|
+
## Conventions
|
|
73
|
+
|
|
74
|
+
- Never `innerHTML` external or model-derived data in the UI — build DOM via
|
|
75
|
+
the `el()` helper / `textContent`. Markdown rendering belongs to
|
|
76
|
+
`<alashi-chat>`, which is escape-first.
|
|
77
|
+
- Validate at boundaries (webhooks, user input): JSON only, cap body sizes,
|
|
78
|
+
4xx on garbage. Model output is a boundary too — parse defensively.
|
|
79
|
+
- Secrets come from declared `config` keys (`secret: true`), referenced as
|
|
80
|
+
`${config.key}` in `mcpServers` env/headers. Never read them from env or
|
|
81
|
+
commit them.
|
|
82
|
+
- AI calls from webhooks/routes should be fire-and-forget with error capture
|
|
83
|
+
(`void run().catch(...)`), status tracked in the app's DB.
|
|
84
|
+
|
|
85
|
+
## Dev loop
|
|
86
|
+
|
|
87
|
+
```sh
|
|
88
|
+
npm install
|
|
89
|
+
alashi install . # local installs are symlinked in place
|
|
90
|
+
alashi # http://localhost:4141
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
UI edits are live on refresh. `index.mjs` changes need an `alashi` restart.
|
|
94
|
+
The app's container lives at `~/.alashi/apps/<name>/` (`data/`, `config.json`);
|
|
95
|
+
deleting that directory uninstalls it cleanly.
|
|
@@ -19,6 +19,7 @@ your changes are live.
|
|
|
19
19
|
|---|---|
|
|
20
20
|
| `index.mjs` | The app: manifest, API routes, job handlers |
|
|
21
21
|
| `ui/index.html` | The web UI, served at `/app/__APP_NAME__/` |
|
|
22
|
+
| `AGENTS.md` | The platform contract, written for coding agents working in this repo |
|
|
22
23
|
|
|
23
24
|
Static files in `ui/` win; any path without a matching file falls through to
|
|
24
25
|
your `routes` handler, so you can also server-render pages.
|