acrylblends 0.8.0 → 0.8.1
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 +1 -1
- package/shared/DEFAULTS.md +1 -1
- package/templates/chat/blend.yaml +3 -0
- package/templates/chat/src/app.ts +17 -16
- package/templates/chat/template.json +1 -0
- package/templates/nodejs/blend.yaml +3 -0
- package/templates/nodejs/src/app.ts +18 -15
- package/templates/nodejs/template.json +9 -1
- package/templates/notes/blend.yaml +3 -0
- package/templates/notes/src/app.ts +17 -16
- package/templates/notes/template.json +1 -0
package/package.json
CHANGED
package/shared/DEFAULTS.md
CHANGED
|
@@ -42,4 +42,4 @@ The door is a command in this folder, `.acryl/bin/acryl`, that lets you look at
|
|
|
42
42
|
- `look` and `act` need the app's page open in a browser (`brief` says `Page: not open` when it is not). Look again before each `act`: refs belong to the latest `look`.
|
|
43
43
|
- A password field is not shown and cannot be typed into through the door; sign in by hand, or test the sign-in with a test.
|
|
44
44
|
- Every verb takes `--json`. The exit code is 0 for done, 1 when the verb failed, 2 for a usage error and 3 when no app is running in this folder.
|
|
45
|
-
- `plugin add plugins/<name>` checks the plugin, installs it and makes it live without a restart (
|
|
45
|
+
- `plugin add plugins/<name>` checks the plugin, installs it and makes it live without a restart (the `extensions` plugin does this; every template that has the door has it, in development only: it is left out with `NODE_ENV=production`). `tool call` reaches only the tools on the door's allowlist (empty by default). On Windows the command is `.acryl\bin\acryl.cmd`.
|
|
@@ -20,6 +20,9 @@ spec:
|
|
|
20
20
|
name: acryl-db-sqlite
|
|
21
21
|
- id: routes
|
|
22
22
|
name: routes
|
|
23
|
+
# Plugins installed while the app runs (the door's `plugin add`): development only, src/app.ts leaves it out when NODE_ENV=production.
|
|
24
|
+
- id: extensions
|
|
25
|
+
name: extensions
|
|
23
26
|
- id: server
|
|
24
27
|
name: acryl-node-server
|
|
25
28
|
config:
|
|
@@ -5,6 +5,7 @@ import * as db from '../plugins/acryl-db-sqlite/src/index.ts'
|
|
|
5
5
|
import * as door from '../plugins/acryl-door/src/index.ts'
|
|
6
6
|
import * as nodeServer from '../plugins/acryl-node-server/src/index.ts'
|
|
7
7
|
import * as router from '../plugins/acryl-router/src/index.ts'
|
|
8
|
+
import { extensions } from '../plugins/extensions/index.ts'
|
|
8
9
|
import { type AppInstance, instance } from '../plugins/instance/index.ts'
|
|
9
10
|
import {
|
|
10
11
|
blueprintsIn,
|
|
@@ -21,6 +22,7 @@ export const registry = {
|
|
|
21
22
|
'acryl-db-sqlite': db,
|
|
22
23
|
'acryl-node-server': nodeServer,
|
|
23
24
|
'acryl-door': door,
|
|
25
|
+
extensions,
|
|
24
26
|
routes,
|
|
25
27
|
}
|
|
26
28
|
|
|
@@ -71,30 +73,29 @@ export interface AppOptions {
|
|
|
71
73
|
* `migrations/`; the one place that names the SQLite provider is this file (`acrylblends check-deps`), so a different provider is a change here.
|
|
72
74
|
*/
|
|
73
75
|
export async function createApp(chosen: AppInstance, options: AppOptions = {}): Promise<App> {
|
|
74
|
-
const
|
|
76
|
+
const read = readManifest(options.values)
|
|
75
77
|
const listen = options.listen
|
|
78
|
+
// Rows left out: the server (and the door, which needs it) when the app is reached in process; the door when it is switched off; live plugin installs in production.
|
|
79
|
+
const leaveOut = new Set<string>()
|
|
80
|
+
if (listen === false) leaveOut.add('acryl-node-server').add('acryl-door')
|
|
81
|
+
if (!doorEnabled()) leaveOut.add('acryl-door')
|
|
82
|
+
if (process.env.NODE_ENV === 'production') leaveOut.add('extensions')
|
|
83
|
+
const manifest = without(read, ...leaveOut)
|
|
76
84
|
const file = options.database ?? 'data/chat.sqlite'
|
|
77
85
|
const root = new Context()
|
|
78
86
|
const first = root.plugin(instance, chosen)
|
|
79
87
|
await first.await()
|
|
80
88
|
const fibers: Fiber[] = [
|
|
81
89
|
first,
|
|
82
|
-
...(await compose(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
: doorEnabled()
|
|
87
|
-
? manifest
|
|
88
|
-
: without(manifest, 'acryl-door'),
|
|
89
|
-
registry,
|
|
90
|
-
{
|
|
91
|
-
db: {
|
|
92
|
-
path: isAbsolute(file) ? file : resolve(projectRoot, file),
|
|
93
|
-
migrations: join(projectRoot, 'migrations'),
|
|
94
|
-
},
|
|
95
|
-
server: { port: chosen.port.start, scan: chosen.port.scan ? 20 : 0 },
|
|
90
|
+
...(await compose(root, manifest, registry, {
|
|
91
|
+
db: {
|
|
92
|
+
path: isAbsolute(file) ? file : resolve(projectRoot, file),
|
|
93
|
+
migrations: join(projectRoot, 'migrations'),
|
|
96
94
|
},
|
|
97
|
-
|
|
95
|
+
// What is installed while the app runs lives in plugins/, next to the plugins copied from the library (plugins/library.json lists those, so they are not installed twice).
|
|
96
|
+
extensions: { sources: [{ dir: join(projectRoot, 'plugins'), trust: 'install' }] },
|
|
97
|
+
server: { port: chosen.port.start, scan: chosen.port.scan ? 20 : 0 },
|
|
98
|
+
})),
|
|
98
99
|
]
|
|
99
100
|
return {
|
|
100
101
|
root,
|
|
@@ -17,6 +17,9 @@ spec:
|
|
|
17
17
|
name: acryl-router
|
|
18
18
|
- id: routes
|
|
19
19
|
name: routes
|
|
20
|
+
# Plugins installed while the app runs (the door's `plugin add`): development only, src/app.ts leaves it out when NODE_ENV=production.
|
|
21
|
+
- id: extensions
|
|
22
|
+
name: extensions
|
|
20
23
|
- id: server
|
|
21
24
|
name: acryl-node-server
|
|
22
25
|
config:
|
|
@@ -4,6 +4,7 @@ import { Context, type Fiber } from '@deepseek-ai/cordis'
|
|
|
4
4
|
import * as door from '../plugins/acryl-door/src/index.ts'
|
|
5
5
|
import * as nodeServer from '../plugins/acryl-node-server/src/index.ts'
|
|
6
6
|
import * as router from '../plugins/acryl-router/src/index.ts'
|
|
7
|
+
import { extensions } from '../plugins/extensions/index.ts'
|
|
7
8
|
import { type AppInstance, instance } from '../plugins/instance/index.ts'
|
|
8
9
|
import {
|
|
9
10
|
blueprintsIn,
|
|
@@ -19,11 +20,14 @@ export const registry = {
|
|
|
19
20
|
'acryl-router': router,
|
|
20
21
|
'acryl-node-server': nodeServer,
|
|
21
22
|
'acryl-door': door,
|
|
23
|
+
extensions,
|
|
22
24
|
routes,
|
|
23
25
|
}
|
|
24
26
|
|
|
27
|
+
const projectRoot = fileURLToPath(new URL('..', import.meta.url))
|
|
28
|
+
|
|
25
29
|
/** The manifest next to this app's source. */
|
|
26
|
-
export const MANIFEST = join(
|
|
30
|
+
export const MANIFEST = join(projectRoot, 'blend.yaml')
|
|
27
31
|
|
|
28
32
|
/**
|
|
29
33
|
* The app's manifest, resolved. A Blend finds its Blueprint in `blueprints/<id>.yaml`; an app that is itself a Blueprint never looks.
|
|
@@ -32,7 +36,7 @@ export const MANIFEST = join(fileURLToPath(new URL('..', import.meta.url)), 'ble
|
|
|
32
36
|
export function readManifest(values?: Readonly<Record<string, ParameterValue>>) {
|
|
33
37
|
return loadManifest(MANIFEST, {
|
|
34
38
|
known: Object.keys(registry),
|
|
35
|
-
getBlueprint: blueprintsIn(join(
|
|
39
|
+
getBlueprint: blueprintsIn(join(projectRoot, 'blueprints')),
|
|
36
40
|
...(values ? { values } : {}),
|
|
37
41
|
})
|
|
38
42
|
}
|
|
@@ -62,25 +66,24 @@ export async function createApp(
|
|
|
62
66
|
chosen: AppInstance,
|
|
63
67
|
options: { values?: Readonly<Record<string, ParameterValue>>; listen?: boolean } = {},
|
|
64
68
|
): Promise<App> {
|
|
65
|
-
const
|
|
69
|
+
const read = readManifest(options.values)
|
|
66
70
|
const listen = options.listen
|
|
71
|
+
// Rows left out: the server (and the door, which needs it) when the app is reached in process; the door when it is switched off; live plugin installs in production.
|
|
72
|
+
const leaveOut = new Set<string>()
|
|
73
|
+
if (listen === false) leaveOut.add('acryl-node-server').add('acryl-door')
|
|
74
|
+
if (!doorEnabled()) leaveOut.add('acryl-door')
|
|
75
|
+
if (process.env.NODE_ENV === 'production') leaveOut.add('extensions')
|
|
76
|
+
const manifest = without(read, ...leaveOut)
|
|
67
77
|
const root = new Context()
|
|
68
78
|
const first = root.plugin(instance, chosen)
|
|
69
79
|
await first.await()
|
|
70
80
|
const fibers: Fiber[] = [
|
|
71
81
|
first,
|
|
72
|
-
...(await compose(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
? manifest
|
|
78
|
-
: without(manifest, 'acryl-door'),
|
|
79
|
-
registry,
|
|
80
|
-
{
|
|
81
|
-
server: { port: chosen.port.start, scan: chosen.port.scan ? 20 : 0 },
|
|
82
|
-
},
|
|
83
|
-
)),
|
|
82
|
+
...(await compose(root, manifest, registry, {
|
|
83
|
+
// What is installed while the app runs lives in plugins/, next to the plugins copied from the library (plugins/library.json lists those, so they are not installed twice).
|
|
84
|
+
extensions: { sources: [{ dir: join(projectRoot, 'plugins'), trust: 'install' }] },
|
|
85
|
+
server: { port: chosen.port.start, scan: chosen.port.scan ? 20 : 0 },
|
|
86
|
+
})),
|
|
84
87
|
]
|
|
85
88
|
return {
|
|
86
89
|
root,
|
|
@@ -20,6 +20,9 @@ spec:
|
|
|
20
20
|
name: acryl-db-sqlite
|
|
21
21
|
- id: routes
|
|
22
22
|
name: routes
|
|
23
|
+
# Plugins installed while the app runs (the door's `plugin add`): development only, src/app.ts leaves it out when NODE_ENV=production.
|
|
24
|
+
- id: extensions
|
|
25
|
+
name: extensions
|
|
23
26
|
- id: server
|
|
24
27
|
name: acryl-node-server
|
|
25
28
|
config:
|
|
@@ -5,6 +5,7 @@ import * as db from '../plugins/acryl-db-sqlite/src/index.ts'
|
|
|
5
5
|
import * as door from '../plugins/acryl-door/src/index.ts'
|
|
6
6
|
import * as nodeServer from '../plugins/acryl-node-server/src/index.ts'
|
|
7
7
|
import * as router from '../plugins/acryl-router/src/index.ts'
|
|
8
|
+
import { extensions } from '../plugins/extensions/index.ts'
|
|
8
9
|
import { type AppInstance, instance } from '../plugins/instance/index.ts'
|
|
9
10
|
import {
|
|
10
11
|
blueprintsIn,
|
|
@@ -21,6 +22,7 @@ export const registry = {
|
|
|
21
22
|
'acryl-db-sqlite': db,
|
|
22
23
|
'acryl-node-server': nodeServer,
|
|
23
24
|
'acryl-door': door,
|
|
25
|
+
extensions,
|
|
24
26
|
routes,
|
|
25
27
|
}
|
|
26
28
|
|
|
@@ -71,30 +73,29 @@ export interface AppOptions {
|
|
|
71
73
|
* `migrations/`; the one place that names the SQLite provider is this file (`acrylblends check-deps`), so a different provider is a change here.
|
|
72
74
|
*/
|
|
73
75
|
export async function createApp(chosen: AppInstance, options: AppOptions = {}): Promise<App> {
|
|
74
|
-
const
|
|
76
|
+
const read = readManifest(options.values)
|
|
75
77
|
const listen = options.listen
|
|
78
|
+
// Rows left out: the server (and the door, which needs it) when the app is reached in process; the door when it is switched off; live plugin installs in production.
|
|
79
|
+
const leaveOut = new Set<string>()
|
|
80
|
+
if (listen === false) leaveOut.add('acryl-node-server').add('acryl-door')
|
|
81
|
+
if (!doorEnabled()) leaveOut.add('acryl-door')
|
|
82
|
+
if (process.env.NODE_ENV === 'production') leaveOut.add('extensions')
|
|
83
|
+
const manifest = without(read, ...leaveOut)
|
|
76
84
|
const file = options.database ?? 'data/notes.sqlite'
|
|
77
85
|
const root = new Context()
|
|
78
86
|
const first = root.plugin(instance, chosen)
|
|
79
87
|
await first.await()
|
|
80
88
|
const fibers: Fiber[] = [
|
|
81
89
|
first,
|
|
82
|
-
...(await compose(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
: doorEnabled()
|
|
87
|
-
? manifest
|
|
88
|
-
: without(manifest, 'acryl-door'),
|
|
89
|
-
registry,
|
|
90
|
-
{
|
|
91
|
-
db: {
|
|
92
|
-
path: isAbsolute(file) ? file : resolve(projectRoot, file),
|
|
93
|
-
migrations: join(projectRoot, 'migrations'),
|
|
94
|
-
},
|
|
95
|
-
server: { port: chosen.port.start, scan: chosen.port.scan ? 20 : 0 },
|
|
90
|
+
...(await compose(root, manifest, registry, {
|
|
91
|
+
db: {
|
|
92
|
+
path: isAbsolute(file) ? file : resolve(projectRoot, file),
|
|
93
|
+
migrations: join(projectRoot, 'migrations'),
|
|
96
94
|
},
|
|
97
|
-
|
|
95
|
+
// What is installed while the app runs lives in plugins/, next to the plugins copied from the library (plugins/library.json lists those, so they are not installed twice).
|
|
96
|
+
extensions: { sources: [{ dir: join(projectRoot, 'plugins'), trust: 'install' }] },
|
|
97
|
+
server: { port: chosen.port.start, scan: chosen.port.scan ? 20 : 0 },
|
|
98
|
+
})),
|
|
98
99
|
]
|
|
99
100
|
return {
|
|
100
101
|
root,
|