@alashi/cli 0.1.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/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +148 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.mts +256 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/store-CwgDCAAx.mjs +1201 -0
- package/dist/store-CwgDCAAx.mjs.map +1 -0
- package/package.json +51 -0
- package/templates/basic-app/README.md +47 -0
- package/templates/basic-app/gitignore +1 -0
- package/templates/basic-app/index.mjs +72 -0
- package/templates/basic-app/package.json +9 -0
- package/templates/basic-app/ui/index.html +466 -0
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { a as installApp, c as addRegistry, d as removeRegistry, g as loadApp, i as resolveAppConfig, n as createServer, o as removeApp, s as updateApp, t as Store } from "./store-CwgDCAAx.mjs";
|
|
3
|
+
import { APP_NAME_PATTERN, AppSdkError } from "@alashi/apps-sdk";
|
|
4
|
+
import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
|
|
5
|
+
import { join, resolve } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { serve } from "@hono/node-server";
|
|
8
|
+
import { ClaudeCodeProvider } from "alashi-provider-claude";
|
|
9
|
+
import { Command } from "commander";
|
|
10
|
+
//#region src/create.ts
|
|
11
|
+
const TEMPLATE_DIR = fileURLToPath(new URL("../templates/basic-app", import.meta.url));
|
|
12
|
+
const RENAMES = { gitignore: ".gitignore" };
|
|
13
|
+
/**
|
|
14
|
+
* Scaffolds a new app from the basic-app template into targetDir,
|
|
15
|
+
* substituting the app name. Returns the created files, relative to
|
|
16
|
+
* targetDir. Refuses to write into a non-empty directory.
|
|
17
|
+
*/
|
|
18
|
+
async function scaffoldApp(name, targetDir) {
|
|
19
|
+
if (!APP_NAME_PATTERN.test(name)) throw new AppSdkError(`Invalid app name "${name}": use lowercase letters, digits, and hyphens (max 64 chars)`);
|
|
20
|
+
const existing = await readdir(targetDir).catch(() => void 0);
|
|
21
|
+
if (existing && existing.length > 0) throw new AppSdkError(`Directory is not empty: ${targetDir}`);
|
|
22
|
+
const written = [];
|
|
23
|
+
async function copyDir(rel) {
|
|
24
|
+
const entries = await readdir(join(TEMPLATE_DIR, rel), { withFileTypes: true });
|
|
25
|
+
await mkdir(join(targetDir, rel), { recursive: true });
|
|
26
|
+
for (const entry of entries) {
|
|
27
|
+
const relPath = join(rel, entry.name);
|
|
28
|
+
if (entry.isDirectory()) {
|
|
29
|
+
await copyDir(relPath);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const content = await readFile(join(TEMPLATE_DIR, relPath), "utf8");
|
|
33
|
+
const outPath = join(rel, RENAMES[entry.name] ?? entry.name);
|
|
34
|
+
await writeFile(join(targetDir, outPath), content.replaceAll("__APP_NAME__", name), "utf8");
|
|
35
|
+
written.push(outPath);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
await copyDir("");
|
|
39
|
+
return written.sort();
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/cli.ts
|
|
43
|
+
const program = new Command();
|
|
44
|
+
const store = new Store();
|
|
45
|
+
program.name("alashi").description("Install, manage, and run Claude Code-powered apps");
|
|
46
|
+
async function serveDashboard(portArg) {
|
|
47
|
+
const config = await store.readGlobalConfig();
|
|
48
|
+
const port = portArg ? Number(portArg) : config.port ?? 4141;
|
|
49
|
+
if (!Number.isInteger(port) || port < 0 || port > 65535) throw new Error(`Invalid port: ${portArg}`);
|
|
50
|
+
const server = createServer(store, new ClaudeCodeProvider());
|
|
51
|
+
await server.scheduler.start();
|
|
52
|
+
const httpServer = serve({
|
|
53
|
+
fetch: server.app.fetch,
|
|
54
|
+
port
|
|
55
|
+
}, (info) => {
|
|
56
|
+
console.log(`alashi dashboard at http://localhost:${info.port}`);
|
|
57
|
+
});
|
|
58
|
+
const shutdown = () => {
|
|
59
|
+
httpServer.close();
|
|
60
|
+
server.close().finally(() => process.exit(0));
|
|
61
|
+
};
|
|
62
|
+
process.on("SIGINT", shutdown);
|
|
63
|
+
process.on("SIGTERM", shutdown);
|
|
64
|
+
}
|
|
65
|
+
program.command("serve", { isDefault: true }).option("-p, --port <port>", "port to listen on (default: config port or 4141)").description("Serve the web dashboard (the default when no command is given)").action(async (options) => serveDashboard(options.port));
|
|
66
|
+
program.command("create").argument("<name>", "app name (lowercase letters, digits, hyphens)").argument("[directory]", "target directory (default: ./<name>)").description("Scaffold a new app from the basic template").action(async (name, directory) => {
|
|
67
|
+
const target = directory ?? name;
|
|
68
|
+
const files = await scaffoldApp(name, resolve(target));
|
|
69
|
+
console.log(`Created ${name}/`);
|
|
70
|
+
for (const file of files) console.log(` ${file}`);
|
|
71
|
+
console.log("\nNext steps:");
|
|
72
|
+
console.log(` cd ${target}`);
|
|
73
|
+
console.log(" npm install");
|
|
74
|
+
console.log(" alashi install .");
|
|
75
|
+
console.log(" alashi # dashboard at http://localhost:4141");
|
|
76
|
+
});
|
|
77
|
+
program.command("install").argument("<source>", "app name (via registry), git URL, or local path").description("Install an app").action(async (source) => {
|
|
78
|
+
const record = await installApp(store, source);
|
|
79
|
+
console.log(`Installed ${record.name}@${record.version} (${record.source.type})`);
|
|
80
|
+
console.log(` data: ${store.appDataDir(record.name)}`);
|
|
81
|
+
console.log(` config: ${store.appConfigPath(record.name)}`);
|
|
82
|
+
await printSetupHints(record.name);
|
|
83
|
+
});
|
|
84
|
+
/** After install: what still needs configuring, and which integrations exist. */
|
|
85
|
+
async function printSetupHints(name) {
|
|
86
|
+
let manifest;
|
|
87
|
+
try {
|
|
88
|
+
({manifest} = await loadApp(store.appRepoDir(name)));
|
|
89
|
+
} catch {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const { status } = await resolveAppConfig(store, manifest);
|
|
93
|
+
if (status.missing.length > 0) console.log(` requires: ${status.missing.join(", ")}`);
|
|
94
|
+
const optional = status.integrations.filter((i) => i.optional && !i.configured);
|
|
95
|
+
if (optional.length > 0) {
|
|
96
|
+
const list = optional.map((i) => `${i.name} (needs ${i.missing.join(", ")})`).join(", ");
|
|
97
|
+
console.log(` optional integrations: ${list}`);
|
|
98
|
+
}
|
|
99
|
+
if (status.missing.length > 0 || optional.length > 0) console.log(` configure via the dashboard settings page or the config file above`);
|
|
100
|
+
}
|
|
101
|
+
program.command("update").argument("<name>", "installed app name").description("Update an installed app").action(async (name) => {
|
|
102
|
+
const record = await updateApp(store, name);
|
|
103
|
+
console.log(`Updated ${record.name} to ${record.version}`);
|
|
104
|
+
});
|
|
105
|
+
program.command("remove").argument("<name>", "installed app name").option("--purge", "also delete the app data and config").description("Remove an installed app (keeps data unless --purge)").action(async (name, options) => {
|
|
106
|
+
await removeApp(store, name, { purge: options.purge ?? false });
|
|
107
|
+
console.log(options.purge ? `Removed ${name} (purged)` : `Removed ${name} (data kept)`);
|
|
108
|
+
});
|
|
109
|
+
program.command("list").option("--json", "machine-readable output").description("List installed apps").action(async (options) => {
|
|
110
|
+
const records = await store.listInstalled();
|
|
111
|
+
if (options.json) {
|
|
112
|
+
console.log(JSON.stringify(records, null, 2));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (records.length === 0) {
|
|
116
|
+
console.log("No apps installed. Try: alashi install <name|git-url|path>");
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
for (const record of records) {
|
|
120
|
+
const origin = record.source.type === "git" ? record.source.url : record.source.path;
|
|
121
|
+
console.log(`${record.name}@${record.version} ${record.source.type} ${origin}`);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
const registry = program.command("registry").description("Manage app registries");
|
|
125
|
+
registry.command("add").argument("<name>", "registry name").argument("<url>", "index.json URL or git repo URL").action(async (name, url) => {
|
|
126
|
+
const index = await addRegistry(store, name, url);
|
|
127
|
+
console.log(`Added registry "${name}" (${index.apps.length} apps)`);
|
|
128
|
+
});
|
|
129
|
+
registry.command("remove").argument("<name>", "registry name").action(async (name) => {
|
|
130
|
+
await removeRegistry(store, name);
|
|
131
|
+
console.log(`Removed registry "${name}"`);
|
|
132
|
+
});
|
|
133
|
+
registry.command("list").action(async () => {
|
|
134
|
+
const config = await store.readGlobalConfig();
|
|
135
|
+
if (config.registries.length === 0) {
|
|
136
|
+
console.log("No registries configured.");
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
for (const r of config.registries) console.log(`${r.name} ${r.url}`);
|
|
140
|
+
});
|
|
141
|
+
program.parseAsync().catch((err) => {
|
|
142
|
+
console.error(err instanceof Error ? err.message : err);
|
|
143
|
+
process.exitCode = 1;
|
|
144
|
+
});
|
|
145
|
+
//#endregion
|
|
146
|
+
export {};
|
|
147
|
+
|
|
148
|
+
//# sourceMappingURL=cli.mjs.map
|
package/dist/cli.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":[],"sources":["../src/create.ts","../src/cli.ts"],"sourcesContent":["import { mkdir, readdir, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { APP_NAME_PATTERN, AppSdkError } from '@alashi/apps-sdk';\n\n// Works from both src/ (tests) and dist/ (published build) — the templates\n// dir sits one level up in the package root either way.\nconst TEMPLATE_DIR = fileURLToPath(new URL('../templates/basic-app', import.meta.url));\n\n// npm strips .gitignore from published packages, so it ships unprefixed.\nconst RENAMES: Record<string, string> = { gitignore: '.gitignore' };\n\n/**\n * Scaffolds a new app from the basic-app template into targetDir,\n * substituting the app name. Returns the created files, relative to\n * targetDir. Refuses to write into a non-empty directory.\n */\nexport async function scaffoldApp(name: string, targetDir: string): Promise<string[]> {\n if (!APP_NAME_PATTERN.test(name)) {\n throw new AppSdkError(\n `Invalid app name \"${name}\": use lowercase letters, digits, and hyphens (max 64 chars)`,\n );\n }\n const existing = await readdir(targetDir).catch(() => undefined);\n if (existing && existing.length > 0) {\n throw new AppSdkError(`Directory is not empty: ${targetDir}`);\n }\n\n const written: string[] = [];\n async function copyDir(rel: string): Promise<void> {\n const entries = await readdir(join(TEMPLATE_DIR, rel), { withFileTypes: true });\n await mkdir(join(targetDir, rel), { recursive: true });\n for (const entry of entries) {\n const relPath = join(rel, entry.name);\n if (entry.isDirectory()) {\n await copyDir(relPath);\n continue;\n }\n const content = await readFile(join(TEMPLATE_DIR, relPath), 'utf8');\n const outPath = join(rel, RENAMES[entry.name] ?? entry.name);\n await writeFile(join(targetDir, outPath), content.replaceAll('__APP_NAME__', name), 'utf8');\n written.push(outPath);\n }\n }\n await copyDir('');\n return written.sort();\n}\n","#!/usr/bin/env node\nimport { resolve } from 'node:path';\nimport { serve } from '@hono/node-server';\nimport { ClaudeCodeProvider } from 'alashi-provider-claude';\nimport { Command } from 'commander';\nimport { scaffoldApp } from './create.js';\nimport { installApp, removeApp, updateApp } from './installer.js';\nimport { loadApp } from './loader.js';\nimport { addRegistry, removeRegistry } from './registry.js';\nimport { resolveAppConfig } from './runtime.js';\nimport { createServer } from './server.js';\nimport { Store } from './store.js';\n\nconst program = new Command();\nconst store = new Store();\n\nprogram.name('alashi').description('Install, manage, and run Claude Code-powered apps');\n\nasync function serveDashboard(portArg?: string): Promise<void> {\n const config = await store.readGlobalConfig();\n const port = portArg ? Number(portArg) : (config.port ?? 4141);\n if (!Number.isInteger(port) || port < 0 || port > 65535) {\n throw new Error(`Invalid port: ${portArg}`);\n }\n const server = createServer(store, new ClaudeCodeProvider());\n await server.scheduler.start();\n const httpServer = serve({ fetch: server.app.fetch, port }, (info) => {\n console.log(`alashi dashboard at http://localhost:${info.port}`);\n });\n const shutdown = (): void => {\n httpServer.close();\n void server.close().finally(() => process.exit(0));\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n}\n\nprogram\n .command('serve', { isDefault: true })\n .option('-p, --port <port>', 'port to listen on (default: config port or 4141)')\n .description('Serve the web dashboard (the default when no command is given)')\n .action(async (options: { port?: string }) => serveDashboard(options.port));\n\nprogram\n .command('create')\n .argument('<name>', 'app name (lowercase letters, digits, hyphens)')\n .argument('[directory]', 'target directory (default: ./<name>)')\n .description('Scaffold a new app from the basic template')\n .action(async (name: string, directory?: string) => {\n const target = directory ?? name;\n const files = await scaffoldApp(name, resolve(target));\n console.log(`Created ${name}/`);\n for (const file of files) console.log(` ${file}`);\n console.log('\\nNext steps:');\n console.log(` cd ${target}`);\n console.log(' npm install');\n console.log(' alashi install .');\n console.log(' alashi # dashboard at http://localhost:4141');\n });\n\nprogram\n .command('install')\n .argument('<source>', 'app name (via registry), git URL, or local path')\n .description('Install an app')\n .action(async (source: string) => {\n const record = await installApp(store, source);\n console.log(`Installed ${record.name}@${record.version} (${record.source.type})`);\n console.log(` data: ${store.appDataDir(record.name)}`);\n console.log(` config: ${store.appConfigPath(record.name)}`);\n await printSetupHints(record.name);\n });\n\n/** After install: what still needs configuring, and which integrations exist. */\nasync function printSetupHints(name: string): Promise<void> {\n let manifest: Awaited<ReturnType<typeof loadApp>>['manifest'];\n try {\n ({ manifest } = await loadApp(store.appRepoDir(name)));\n } catch {\n return; // install already succeeded; hints are best-effort\n }\n const { status } = await resolveAppConfig(store, manifest);\n if (status.missing.length > 0) {\n console.log(` requires: ${status.missing.join(', ')}`);\n }\n const optional = status.integrations.filter((i) => i.optional && !i.configured);\n if (optional.length > 0) {\n const list = optional.map((i) => `${i.name} (needs ${i.missing.join(', ')})`).join(', ');\n console.log(` optional integrations: ${list}`);\n }\n if (status.missing.length > 0 || optional.length > 0) {\n console.log(` configure via the dashboard settings page or the config file above`);\n }\n}\n\nprogram\n .command('update')\n .argument('<name>', 'installed app name')\n .description('Update an installed app')\n .action(async (name: string) => {\n const record = await updateApp(store, name);\n console.log(`Updated ${record.name} to ${record.version}`);\n });\n\nprogram\n .command('remove')\n .argument('<name>', 'installed app name')\n .option('--purge', 'also delete the app data and config')\n .description('Remove an installed app (keeps data unless --purge)')\n .action(async (name: string, options: { purge?: boolean }) => {\n await removeApp(store, name, { purge: options.purge ?? false });\n console.log(options.purge ? `Removed ${name} (purged)` : `Removed ${name} (data kept)`);\n });\n\nprogram\n .command('list')\n .option('--json', 'machine-readable output')\n .description('List installed apps')\n .action(async (options: { json?: boolean }) => {\n const records = await store.listInstalled();\n if (options.json) {\n console.log(JSON.stringify(records, null, 2));\n return;\n }\n if (records.length === 0) {\n console.log('No apps installed. Try: alashi install <name|git-url|path>');\n return;\n }\n for (const record of records) {\n const origin = record.source.type === 'git' ? record.source.url : record.source.path;\n console.log(`${record.name}@${record.version} ${record.source.type} ${origin}`);\n }\n });\n\nconst registry = program.command('registry').description('Manage app registries');\n\nregistry\n .command('add')\n .argument('<name>', 'registry name')\n .argument('<url>', 'index.json URL or git repo URL')\n .action(async (name: string, url: string) => {\n const index = await addRegistry(store, name, url);\n console.log(`Added registry \"${name}\" (${index.apps.length} apps)`);\n });\n\nregistry\n .command('remove')\n .argument('<name>', 'registry name')\n .action(async (name: string) => {\n await removeRegistry(store, name);\n console.log(`Removed registry \"${name}\"`);\n });\n\nregistry.command('list').action(async () => {\n const config = await store.readGlobalConfig();\n if (config.registries.length === 0) {\n console.log('No registries configured.');\n return;\n }\n for (const r of config.registries) console.log(`${r.name} ${r.url}`);\n});\n\nprogram.parseAsync().catch((err: unknown) => {\n console.error(err instanceof Error ? err.message : err);\n process.exitCode = 1;\n});\n"],"mappings":"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"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { AIProvider, AppContext, AppDefinition, AppManifest, ConfigObject } from "@alashi/apps-sdk";
|
|
2
|
+
import { Hono } from "hono";
|
|
3
|
+
//#region src/compat.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Enforces the manifest's declared `sdkVersion` range against the SDK
|
|
6
|
+
* this host is built with. Apps that declare nothing are accepted.
|
|
7
|
+
*/
|
|
8
|
+
declare function checkSdkCompatibility(manifest: AppManifest): void;
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/sources.d.ts
|
|
11
|
+
type AppSourceSpec = {
|
|
12
|
+
type: "git";
|
|
13
|
+
url: string;
|
|
14
|
+
ref?: string;
|
|
15
|
+
} | {
|
|
16
|
+
type: "local";
|
|
17
|
+
path: string;
|
|
18
|
+
};
|
|
19
|
+
/** How the CLI argument was understood: a source, or a name to resolve via registries. */
|
|
20
|
+
type SourceArg = AppSourceSpec | {
|
|
21
|
+
type: "registry";
|
|
22
|
+
name: string;
|
|
23
|
+
};
|
|
24
|
+
declare function parseSourceArg(arg: string): SourceArg;
|
|
25
|
+
/** Materializes a source at destDir: git clone, or symlink for local dev installs. */
|
|
26
|
+
declare function fetchSource(spec: AppSourceSpec, destDir: string): Promise<void>;
|
|
27
|
+
/** Brings an installed source up to date in place. Local symlinks are always live. */
|
|
28
|
+
declare function updateSource(spec: AppSourceSpec, repoDir: string): Promise<void>;
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/store.d.ts
|
|
31
|
+
interface RegistryRef {
|
|
32
|
+
name: string;
|
|
33
|
+
url: string;
|
|
34
|
+
}
|
|
35
|
+
interface GlobalConfig {
|
|
36
|
+
registries: RegistryRef[];
|
|
37
|
+
port?: number;
|
|
38
|
+
/** Per-app global overrides, keyed by app name (middle config layer). */
|
|
39
|
+
apps?: Record<string, ConfigObject>;
|
|
40
|
+
}
|
|
41
|
+
interface Conversation {
|
|
42
|
+
id: string;
|
|
43
|
+
/** Provider session backing this conversation; set after the first turn. */
|
|
44
|
+
sessionId?: string;
|
|
45
|
+
title?: string;
|
|
46
|
+
updatedAt: string;
|
|
47
|
+
}
|
|
48
|
+
/** Host-side chat state for an app; the transcripts themselves live with the AI provider. */
|
|
49
|
+
interface ChatState {
|
|
50
|
+
conversations: Conversation[];
|
|
51
|
+
}
|
|
52
|
+
interface JobRun {
|
|
53
|
+
job: string;
|
|
54
|
+
trigger: "schedule" | "catchup" | "manual";
|
|
55
|
+
startedAt: string;
|
|
56
|
+
finishedAt: string;
|
|
57
|
+
ok: boolean;
|
|
58
|
+
error?: string;
|
|
59
|
+
}
|
|
60
|
+
/** Host-side job state for an app: last run start per job plus a capped run log. */
|
|
61
|
+
interface JobState {
|
|
62
|
+
lastRun: Record<string, string>;
|
|
63
|
+
runs: JobRun[];
|
|
64
|
+
}
|
|
65
|
+
interface InstallRecord {
|
|
66
|
+
name: string;
|
|
67
|
+
version: string;
|
|
68
|
+
/** The SDK range the app's manifest declared at install/update time. */
|
|
69
|
+
sdkVersion?: string;
|
|
70
|
+
source: AppSourceSpec;
|
|
71
|
+
installedAt: string;
|
|
72
|
+
updatedAt: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The portable state directory ($ALASHI_HOME, default ~/.alashi).
|
|
76
|
+
* Everything the host knows lives under this root so it can be moved
|
|
77
|
+
* between machines as a unit.
|
|
78
|
+
*/
|
|
79
|
+
declare class Store {
|
|
80
|
+
readonly root: string;
|
|
81
|
+
constructor(root?: string);
|
|
82
|
+
get configPath(): string;
|
|
83
|
+
get appsDir(): string;
|
|
84
|
+
get registriesDir(): string;
|
|
85
|
+
get stagingDir(): string;
|
|
86
|
+
/** Validates the name before using it in a path (traversal guard). */
|
|
87
|
+
appDir(name: string): string;
|
|
88
|
+
appRepoDir(name: string): string;
|
|
89
|
+
appDataDir(name: string): string;
|
|
90
|
+
appConfigPath(name: string): string;
|
|
91
|
+
appRecordPath(name: string): string;
|
|
92
|
+
appChatStatePath(name: string): string;
|
|
93
|
+
appJobStatePath(name: string): string;
|
|
94
|
+
registryCachePath(name: string): string;
|
|
95
|
+
readGlobalConfig(): Promise<GlobalConfig>;
|
|
96
|
+
writeGlobalConfig(config: GlobalConfig): Promise<void>;
|
|
97
|
+
readAppRecord(name: string): Promise<InstallRecord | undefined>;
|
|
98
|
+
writeAppRecord(record: InstallRecord): Promise<void>;
|
|
99
|
+
readAppConfig(name: string): Promise<ConfigObject>;
|
|
100
|
+
writeAppConfig(name: string, config: ConfigObject): Promise<void>;
|
|
101
|
+
readChatState(name: string): Promise<ChatState>;
|
|
102
|
+
writeChatState(name: string, state: ChatState): Promise<void>;
|
|
103
|
+
readJobState(name: string): Promise<JobState>;
|
|
104
|
+
writeJobState(name: string, state: JobState): Promise<void>;
|
|
105
|
+
listInstalled(): Promise<InstallRecord[]>;
|
|
106
|
+
}
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/installer.d.ts
|
|
109
|
+
interface InstallOptions {
|
|
110
|
+
/** Expected app name (enforced against the manifest when set). */
|
|
111
|
+
expectName?: string;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Install flow: materialize the source into a staging dir, install deps
|
|
115
|
+
* (scripts disabled), import + validate the manifest, and only then move
|
|
116
|
+
* it into apps/<name>/repo. A failed validation never leaves a broken app.
|
|
117
|
+
*/
|
|
118
|
+
declare function installApp(store: Store, source: string | AppSourceSpec, options?: InstallOptions): Promise<InstallRecord>;
|
|
119
|
+
declare function updateApp(store: Store, name: string): Promise<InstallRecord>;
|
|
120
|
+
interface RemoveOptions {
|
|
121
|
+
/** Also delete the app's data/ and config (default keeps them). */
|
|
122
|
+
purge?: boolean;
|
|
123
|
+
}
|
|
124
|
+
declare function removeApp(store: Store, name: string, options?: RemoveOptions): Promise<void>;
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region src/loader.d.ts
|
|
127
|
+
interface LoadedApp {
|
|
128
|
+
definition: AppDefinition;
|
|
129
|
+
manifest: AppManifest;
|
|
130
|
+
entryPath: string;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Imports an app's entry module and validates its default export.
|
|
134
|
+
* The manifest is always re-validated here — the host never trusts
|
|
135
|
+
* that an app used defineApp().
|
|
136
|
+
*/
|
|
137
|
+
declare function loadApp(repoDir: string): Promise<LoadedApp>;
|
|
138
|
+
//#endregion
|
|
139
|
+
//#region src/registry.d.ts
|
|
140
|
+
interface RegistryApp {
|
|
141
|
+
name: string;
|
|
142
|
+
repo: string;
|
|
143
|
+
description?: string;
|
|
144
|
+
ref?: string;
|
|
145
|
+
sdkVersion?: string;
|
|
146
|
+
}
|
|
147
|
+
interface RegistryIndex {
|
|
148
|
+
apps: RegistryApp[];
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Fetches a registry index and caches it under registries/<name>.json.
|
|
152
|
+
* URLs ending in .json are fetched over HTTP; anything else is treated
|
|
153
|
+
* as a git repo containing index.json at its root (brew-tap style).
|
|
154
|
+
*/
|
|
155
|
+
declare function refreshRegistry(store: Store, registry: RegistryRef): Promise<RegistryIndex>;
|
|
156
|
+
declare function readCachedIndex(store: Store, name: string): Promise<RegistryIndex | undefined>;
|
|
157
|
+
declare function addRegistry(store: Store, name: string, url: string): Promise<RegistryIndex>;
|
|
158
|
+
declare function removeRegistry(store: Store, name: string): Promise<void>;
|
|
159
|
+
interface ResolvedApp {
|
|
160
|
+
registry: string;
|
|
161
|
+
app: RegistryApp;
|
|
162
|
+
}
|
|
163
|
+
/** Finds an app by name across configured registries (refreshing caches). */
|
|
164
|
+
declare function resolveApp(store: Store, appName: string): Promise<ResolvedApp>;
|
|
165
|
+
//#endregion
|
|
166
|
+
//#region src/runtime.d.ts
|
|
167
|
+
/**
|
|
168
|
+
* Builds the AppContext for an installed app: merges the config layers
|
|
169
|
+
* (manifest defaults < global apps[name] < per-app config), resolves
|
|
170
|
+
* `${config.*}` placeholders (with `dataDir` available as a built-in key),
|
|
171
|
+
* and scopes the AI provider to the app's manifest.
|
|
172
|
+
*
|
|
173
|
+
* Setup state shapes the session defaults: unconfigured MCP servers are
|
|
174
|
+
* dropped (with their tools) so interpolation never hits a missing key, and
|
|
175
|
+
* while required keys are missing the scoped provider fails closed.
|
|
176
|
+
*/
|
|
177
|
+
declare function buildAppContext(store: Store, manifest: AppManifest, provider: AIProvider): Promise<AppContext>;
|
|
178
|
+
//#endregion
|
|
179
|
+
//#region src/scheduler.d.ts
|
|
180
|
+
interface SchedulableApp {
|
|
181
|
+
manifest: AppManifest;
|
|
182
|
+
ctx: AppContext;
|
|
183
|
+
jobHandlers?: Record<string, (ctx: AppContext) => Promise<void>>;
|
|
184
|
+
}
|
|
185
|
+
interface JobStatus {
|
|
186
|
+
name: string;
|
|
187
|
+
schedule: string;
|
|
188
|
+
description?: string;
|
|
189
|
+
/** False when the cron expression failed to parse (job never fires). */
|
|
190
|
+
valid: boolean;
|
|
191
|
+
running: boolean;
|
|
192
|
+
nextRun?: string;
|
|
193
|
+
lastRun?: string;
|
|
194
|
+
recentRuns: JobRun[];
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Runs manifest-declared jobs on their cron schedules. One instance per host
|
|
198
|
+
* process; start() schedules every installed app's jobs, stop() cancels them.
|
|
199
|
+
* A job missed while the host was down runs once at startup ("catchup"), but
|
|
200
|
+
* only if it has run before — a fresh install waits for its first slot.
|
|
201
|
+
*/
|
|
202
|
+
declare class Scheduler {
|
|
203
|
+
private readonly store;
|
|
204
|
+
private readonly getApp;
|
|
205
|
+
private crons;
|
|
206
|
+
private runningJobs;
|
|
207
|
+
private started;
|
|
208
|
+
/** Serializes jobs.json read-modify-write across concurrently finishing jobs. */
|
|
209
|
+
private stateQueue;
|
|
210
|
+
constructor(store: Store, getApp: (name: string) => Promise<SchedulableApp | undefined>);
|
|
211
|
+
start(): Promise<void>;
|
|
212
|
+
stop(): void;
|
|
213
|
+
/**
|
|
214
|
+
* Runs one job immediately. Returns the recorded run, 'skipped' when that
|
|
215
|
+
* job is already mid-run, or undefined when the app/job doesn't exist.
|
|
216
|
+
*/
|
|
217
|
+
run(appName: string, jobName: string, trigger?: JobRun["trigger"]): Promise<JobRun | "skipped" | undefined>;
|
|
218
|
+
/** Job statuses for an app, or undefined when the app isn't installed. */
|
|
219
|
+
status(appName: string): Promise<JobStatus[] | undefined>;
|
|
220
|
+
private recordRun;
|
|
221
|
+
}
|
|
222
|
+
//#endregion
|
|
223
|
+
//#region src/server.d.ts
|
|
224
|
+
interface AppServer {
|
|
225
|
+
/** The Hono app — pass its fetch to a Node server or call request() in tests. */
|
|
226
|
+
app: Hono;
|
|
227
|
+
/** Cron scheduler for manifest-declared jobs; call start() to begin firing. */
|
|
228
|
+
scheduler: Scheduler;
|
|
229
|
+
/** Stops the scheduler and closes all warm AI sessions. */
|
|
230
|
+
close(): Promise<void>;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* The host HTTP surface:
|
|
234
|
+
* GET / dashboard of installed apps
|
|
235
|
+
* GET /settings/:name per-app settings page (config form)
|
|
236
|
+
* GET /api/apps installed apps as JSON
|
|
237
|
+
* POST /api/apps/:name/chat { message, conversationId? } -> SSE stream of AgentEvents
|
|
238
|
+
* (omit conversationId to start a new conversation; the
|
|
239
|
+
* id is echoed in the x-conversation-id response header)
|
|
240
|
+
* GET /api/apps/:name/chat/conversations conversations, most recent first
|
|
241
|
+
* GET /api/apps/:name/chat/:conversationId/history past turns from the provider transcript
|
|
242
|
+
* GET /api/apps/:name/jobs manifest-declared jobs with schedule/status
|
|
243
|
+
* POST /api/apps/:name/jobs/:job/run trigger a job now (409 while already running)
|
|
244
|
+
* GET /api/apps/:name/config declared config schema + merged values
|
|
245
|
+
* (secrets masked) + readiness/integrations
|
|
246
|
+
* PUT /api/apps/:name/config merge keys into the per-app config layer
|
|
247
|
+
* (null deletes a key) and restart the app
|
|
248
|
+
* ALL /app/:name/api/* dispatched to the app's fetch handler (prefix stripped)
|
|
249
|
+
* ALL /app/:name/* a matching static file from the app's ui dir wins,
|
|
250
|
+
* otherwise the app's fetch handler (/app/:name stripped),
|
|
251
|
+
* otherwise 404
|
|
252
|
+
*/
|
|
253
|
+
declare function createServer(store: Store, provider: AIProvider): AppServer;
|
|
254
|
+
//#endregion
|
|
255
|
+
export { type AppServer, type AppSourceSpec, type GlobalConfig, type InstallOptions, type InstallRecord, type LoadedApp, type RegistryApp, type RegistryIndex, type RegistryRef, type RemoveOptions, type ResolvedApp, type SourceArg, Store, addRegistry, buildAppContext, checkSdkCompatibility, createServer, fetchSource, installApp, loadApp, parseSourceArg, readCachedIndex, refreshRegistry, removeApp, removeRegistry, resolveApp, updateApp, updateSource };
|
|
256
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/compat.ts","../src/sources.ts","../src/store.ts","../src/installer.ts","../src/loader.ts","../src/registry.ts","../src/runtime.ts","../src/scheduler.ts","../src/server.ts"],"mappings":";;;;;;;iBAOgB,sBAAsB,UAAU;;;KCCpC;EACN;EAAa;EAAa;;EAC1B;EAAe;;;KAGT,YAAY;EAAkB;EAAkB;;iBAE5C,eAAe,cAAc;;iBAwBvB,YAAY,MAAM,eAAe,kBAAkB;;iBAanD,aAAa,MAAM,eAAe,kBAAkB;;;UC9CzD;EACf;EACA;;UAGe;EACf,YAAY;EACZ;;EAEA,OAAO,eAAe;;UAGP;EACf;;EAEA;EACA;EACA;;;UAIe;EACf,eAAe;;UAGA;EACf;EACA;EACA;EACA;EACA;EACA;;;UAIe;EACf,SAAS;EACT,MAAM;;UAGS;EACf;EACA;;EAEA;EACA,QAAQ;EACR;EACA;;;;;;;cAwBW;WACF;EAET,YAAY;MAIR;MAIA;MAIA;MAIA;;EAKJ,OAAO;EAOP,WAAW;EAIX,WAAW;EAIX,cAAc;EAId,cAAc;EAId,iBAAiB;EAIjB,gBAAgB;EAIhB,kBAAkB;EAOlB,oBAA0B,QAAQ;EAIlC,kBAAwB,QAAQ,eAAe;EAI/C,cAAoB,eAAe,QAAQ;EAI3C,eAAqB,QAAQ,gBAAgB;EAI7C,cAAoB,eAAe,QAAQ;EAI3C,eAAqB,cAAc,QAAQ,eAAe;EAI1D,cAAoB,eAAe,QAAQ;EAK3C,eAAqB,cAAc,OAAO,YAAY;EAItD,aAAmB,eAAe,QAAQ;EAK1C,cAAoB,cAAc,OAAO,WAAW;EAIpD,iBAAuB,QAAQ;;;;UC5IhB;;EAEf;;;;;;;iBAQoB,WACpB,OAAO,OACP,iBAAiB,eACjB,UAAS,iBACR,QAAQ;iBA0EW,UAAU,OAAO,OAAO,eAAe,QAAQ;UAuBpD;;EAEf;;iBAGoB,UACpB,OAAO,OACP,cACA,UAAS,gBACR;;;UCzIc;EACf,YAAY;EACZ,UAAU;EACV;;;;;;;iBAQoB,QAAQ,kBAAkB,QAAQ;;;UC5BvC;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf,MAAM;;;;;;;iBAkCc,gBAAgB,OAAO,OAAO,UAAU,cAAc,QAAQ;iBAuB9D,gBACpB,OAAO,OACP,eACC,QAAQ;iBASW,YAAY,OAAO,OAAO,cAAc,cAAc,QAAQ;iBAW9D,eAAe,OAAO,OAAO,eAAe;UAWjD;EACf;EACA,KAAK;;;iBAIe,WAAW,OAAO,OAAO,kBAAkB,QAAQ;;;;;;;;;;;;;iBCFnD,gBACpB,OAAO,OACP,UAAU,aACV,UAAU,aACT,QAAQ;;;UC/GM;EACf,UAAU;EACV,KAAK;EACL,cAAc,gBAAgB,KAAK,eAAe;;UAGnC;EACf;EACA;EACA;;EAEA;EACA;EACA;EACA;EACA,YAAY;;;;;;;;cAiBD;mBAQT;mBACA;UARM;UACA;UACA;;UAEA;EAER,YACE,OAAwB,OACxB,SAA0B,iBAAiB,QAAQ;EAGrD,SAAe;EAuCf;;;;;EAUA,IACE,iBACA,iBACA,UAAS,oBACR,QAAQ;;EAmCX,OAAa,kBAAkB,QAAQ;UA4B/B;;;;UCtHO;;EAEf,KAAK;;EAEL,WAAW;;EAEX,SAAS;;;;;;;;;;;;;;;;;;;;;;;iBAwBK,aAAa,OAAO,OAAO,UAAU,aAAa"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { _ as checkSdkCompatibility, a as installApp, c as addRegistry, d as removeRegistry, f as resolveApp, g as loadApp, h as updateSource, l as readCachedIndex, m as parseSourceArg, n as createServer, o as removeApp, p as fetchSource, r as buildAppContext, s as updateApp, t as Store, u as refreshRegistry } from "./store-CwgDCAAx.mjs";
|
|
2
|
+
export { Store, addRegistry, buildAppContext, checkSdkCompatibility, createServer, fetchSource, installApp, loadApp, parseSourceArg, readCachedIndex, refreshRegistry, removeApp, removeRegistry, resolveApp, updateApp, updateSource };
|