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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "acrylblends",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "The Acryl web framework (import { Acryl } from \"acrylblends\") and the acrylblends command that scaffolds Cordis apps.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -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 (when the app has the `extensions` plugin; `acrylblends init --template agent` does). `tool call` reaches only the tools on the door's allowlist (empty by default). On Windows the command is `.acryl\bin\acryl.cmd`.
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 manifest = readManifest(options.values)
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
- root,
84
- listen === false
85
- ? without(manifest, 'acryl-node-server', 'acryl-door')
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,
@@ -6,6 +6,7 @@
6
6
  "acryl-db-sqlite",
7
7
  "manifest",
8
8
  "save",
9
+ "extensions",
9
10
  "acryl-door"
10
11
  ]
11
12
  }
@@ -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(fileURLToPath(new URL('..', import.meta.url)), 'blend.yaml')
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(fileURLToPath(new URL('..', import.meta.url)), 'blueprints')),
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 manifest = readManifest(options.values)
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
- root,
74
- listen === false
75
- ? without(manifest, 'acryl-node-server', 'acryl-door')
76
- : doorEnabled()
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,
@@ -1,3 +1,11 @@
1
1
  {
2
- "plugins": ["instance", "acryl-router", "acryl-node-server", "manifest", "save", "acryl-door"]
2
+ "plugins": [
3
+ "instance",
4
+ "acryl-router",
5
+ "acryl-node-server",
6
+ "manifest",
7
+ "save",
8
+ "extensions",
9
+ "acryl-door"
10
+ ]
3
11
  }
@@ -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 manifest = readManifest(options.values)
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
- root,
84
- listen === false
85
- ? without(manifest, 'acryl-node-server', 'acryl-door')
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,
@@ -6,6 +6,7 @@
6
6
  "acryl-db-sqlite",
7
7
  "manifest",
8
8
  "save",
9
+ "extensions",
9
10
  "acryl-door"
10
11
  ]
11
12
  }