acryl-development-canvas 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/LICENSE +21 -0
- package/README.md +58 -0
- package/cordis.patch.yml +3 -0
- package/docs/PLAN.md +40 -0
- package/lib/canvas-pty-contract.d.ts +17 -0
- package/lib/canvas-pty-route.d.ts +19 -0
- package/lib/canvas-pty.d.ts +82 -0
- package/lib/client.js +8071 -0
- package/lib/client.js.map +1 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.js +473 -0
- package/lib/index.js.map +1 -0
- package/lib/types/canvas-pty-contract.d.ts +17 -0
- package/lib/types/client/development-canvas/DevelopmentCanvas.d.ts +15 -0
- package/lib/types/client/development-canvas/agent-commands.d.ts +14 -0
- package/lib/types/client/development-canvas/pty-api.d.ts +13 -0
- package/lib/types/client/development-canvas/session-client.d.ts +22 -0
- package/lib/types/client/development-canvas/session-navigation.d.ts +12 -0
- package/lib/types/client/development-canvas/state.d.ts +65 -0
- package/lib/types/client/index.d.ts +23 -0
- package/lib/types/client/styles.d.ts +2 -0
- package/package.json +120 -0
- package/provenance.json +9 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ACRYL.dev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# ACRYL Development Canvas
|
|
2
|
+
|
|
3
|
+
`acryl-development-canvas` is a standalone Host and Client Cordis plugin for
|
|
4
|
+
the ACRYL Development Canvas. It adds a workspace canvas to compatible Desktop
|
|
5
|
+
profiles, with terminal-backed tiles, file tiles, browser tiles, and a Client
|
|
6
|
+
contribution to the `desktop.main` slot.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
dsh plugin --profile desktop add acryl-development-canvas
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The package declares both a DSH bundle patch and an `acryl-package` manifest,
|
|
15
|
+
so it is discoverable through the ACRYL package catalog as well as normal DSH
|
|
16
|
+
plugin installation.
|
|
17
|
+
|
|
18
|
+
## What it owns
|
|
19
|
+
|
|
20
|
+
- The Host owns loopback PTY routes and every PTY process it starts.
|
|
21
|
+
- The Client owns its Desktop slot contribution, xterm clients, injected
|
|
22
|
+
styles, and browser-side cleanup.
|
|
23
|
+
- Removing the Loader row unregisters routes, closes PTYs, removes the Canvas
|
|
24
|
+
contribution, and restores the default conversation surface.
|
|
25
|
+
|
|
26
|
+
## Engineering principles
|
|
27
|
+
|
|
28
|
+
- **Dependency inversion and separated interfaces.** The Host consumes the
|
|
29
|
+
normal `webServer` capability; the Client consumes `slots`. Neither imports a
|
|
30
|
+
concrete Desktop bootstrap or creates another plugin runtime.
|
|
31
|
+
- **One owner for live resources.** Routes, PTYs, subscriptions, styles, and
|
|
32
|
+
slot registrations are acquired inside their owning Cordis effects and
|
|
33
|
+
disposed with their Fibers.
|
|
34
|
+
- **Reversible composition.** The stable Loader row controls the capability.
|
|
35
|
+
Disable, unload, or replacement removes only Canvas contributions.
|
|
36
|
+
- **Orthogonality and information hiding.** Host process control and Client
|
|
37
|
+
presentation remain separate; PTY transport does not become canonical agent
|
|
38
|
+
history or a global application service.
|
|
39
|
+
- **Fail fast and contain failure.** A non-loopback Host is rejected before
|
|
40
|
+
routes mount, and partial route activation rolls back registrations.
|
|
41
|
+
- **YAGNI.** The package uses the existing DSH/Cordis Host, Client, slot, and
|
|
42
|
+
Loader seams instead of creating another PTY registry, event bus, or
|
|
43
|
+
lifecycle system.
|
|
44
|
+
- **Refactor-safe behavior.** Tests exercise activation, route rollback,
|
|
45
|
+
PTY disposal, Client cleanup, slot replacement, and repeated lifecycle use.
|
|
46
|
+
|
|
47
|
+
## Package compatibility
|
|
48
|
+
|
|
49
|
+
The Host requires a loopback DSH `webServer`. The Client is intended for a
|
|
50
|
+
profile that declares the `desktop.main` slot. When that slot is absent, the
|
|
51
|
+
Client leaves the profile untouched.
|
|
52
|
+
|
|
53
|
+
## Provenance
|
|
54
|
+
|
|
55
|
+
This package is a copy-only extraction from the ACRYL workspace. The source
|
|
56
|
+
package remains in the main repository. See [`provenance.json`](./provenance.json)
|
|
57
|
+
for the source boundary and [`docs/PLAN.md`](./docs/PLAN.md) for the Cordis
|
|
58
|
+
lifecycle design.
|
package/cordis.patch.yml
ADDED
package/docs/PLAN.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Development Canvas public package
|
|
2
|
+
|
|
3
|
+
Date: 2026-09-09. Copy-only extraction of the existing ACRYL Development Canvas
|
|
4
|
+
Host and Client Cordis plugin. The source package remains in the ACRYL monorepo.
|
|
5
|
+
|
|
6
|
+
## Capability and plugin boundary
|
|
7
|
+
|
|
8
|
+
The Canvas is independently configurable, mountable, and removable. The Host
|
|
9
|
+
owns loopback PTY routes and live PTY processes. The Client owns its desktop
|
|
10
|
+
slot contribution, browser-side PTY client, xterm resources, and styles.
|
|
11
|
+
|
|
12
|
+
## Provides and consumes
|
|
13
|
+
|
|
14
|
+
The Host hard-injects `webServer` and provides its owned routes. The Client
|
|
15
|
+
hard-injects `slots`, contributes to `desktop.main` only while that declaration
|
|
16
|
+
exists, and exposes no parallel service registry.
|
|
17
|
+
|
|
18
|
+
## Effects and disposal
|
|
19
|
+
|
|
20
|
+
One Host effect owns the route registrations and `CanvasPtyRegistry`; teardown
|
|
21
|
+
removes routes in reverse order and awaits all PTY termination. The Client
|
|
22
|
+
declaration effect owns the slot registration, styles, and client handles.
|
|
23
|
+
|
|
24
|
+
## Configuration and composition
|
|
25
|
+
|
|
26
|
+
The published `dsh.bundle.patch` inserts the stable
|
|
27
|
+
`desktop-development-canvas` Loader row. The row is ordinary Cordis desired
|
|
28
|
+
composition and supports disable/reload through the host Loader.
|
|
29
|
+
|
|
30
|
+
## Events and durability
|
|
31
|
+
|
|
32
|
+
PTY bytes and Canvas view state are presentation/transport concerns, not a
|
|
33
|
+
canonical agent history. Durable agent/room facts remain owned by their runtime
|
|
34
|
+
services. This package does not create a second event or persistence system.
|
|
35
|
+
|
|
36
|
+
## Verification and release
|
|
37
|
+
|
|
38
|
+
The copied suite covers Host activation, route rollback/removal, PTY lifecycle,
|
|
39
|
+
Client slot replacement, and client cleanup. Tags run build, typecheck, test,
|
|
40
|
+
npm provenance publish, and GitHub release creation.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Allowlisted Development Canvas PTY commands and loopback routes. */
|
|
2
|
+
export declare const CANVAS_PTY_COMMAND_IDS: readonly ["shell", "claude", "codex", "opencode", "gemini", "pi", "grok", "aider", "goose", "amp", "kimi", "cursor", "hermes", "qwen"];
|
|
3
|
+
export type CanvasPtyCommandId = (typeof CANVAS_PTY_COMMAND_IDS)[number];
|
|
4
|
+
export declare const CANVAS_PTY_PATH = "/api/development-canvas/pty";
|
|
5
|
+
export declare const CANVAS_PTY_INPUT_PATH = "/api/development-canvas/pty/input";
|
|
6
|
+
export declare const CANVAS_PTY_RESIZE_PATH = "/api/development-canvas/pty/resize";
|
|
7
|
+
export declare const CANVAS_PTY_CLOSE_PATH = "/api/development-canvas/pty/close";
|
|
8
|
+
/** @param value - unknown command id from JSON. */
|
|
9
|
+
export declare function isCanvasPtyCommandId(value: unknown): value is CanvasPtyCommandId;
|
|
10
|
+
export type CanvasPtyStatus = 'starting' | 'running' | 'exited' | 'error';
|
|
11
|
+
export interface CanvasPtyView {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly status: CanvasPtyStatus;
|
|
14
|
+
readonly output: string;
|
|
15
|
+
readonly exitCode: number | null;
|
|
16
|
+
readonly error: string | null;
|
|
17
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Same-origin JSON handlers for Development Canvas PTY sessions. */
|
|
2
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
3
|
+
import type { CanvasPtyRegistry } from './canvas-pty.ts';
|
|
4
|
+
/**
|
|
5
|
+
* POST start and GET snapshot for the Canvas PTY route.
|
|
6
|
+
*/
|
|
7
|
+
export declare function handleCanvasPtyRequest(req: IncomingMessage, res: ServerResponse, expectedOrigin: string, registry: CanvasPtyRegistry, reportError: (operation: string, cause: unknown) => void): Promise<void>;
|
|
8
|
+
/** POST stdin to a live session. */
|
|
9
|
+
export declare function handleCanvasPtyInputRequest(req: IncomingMessage, res: ServerResponse, expectedOrigin: string, registry: CanvasPtyRegistry, reportError: (operation: string, cause: unknown) => void): Promise<void>;
|
|
10
|
+
/** POST terminal dimensions to a live session. */
|
|
11
|
+
export declare function handleCanvasPtyResizeRequest(req: IncomingMessage, res: ServerResponse, expectedOrigin: string, registry: CanvasPtyRegistry, reportError: (operation: string, cause: unknown) => void): Promise<void>;
|
|
12
|
+
/** POST idempotent close. */
|
|
13
|
+
export declare function handleCanvasPtyCloseRequest(req: IncomingMessage, res: ServerResponse, expectedOrigin: string, registry: CanvasPtyRegistry, reportError: (operation: string, cause: unknown) => void): Promise<void>;
|
|
14
|
+
export declare const canvasPtyRoutePaths: {
|
|
15
|
+
readonly pty: "/api/development-canvas/pty";
|
|
16
|
+
readonly input: "/api/development-canvas/pty/input";
|
|
17
|
+
readonly resize: "/api/development-canvas/pty/resize";
|
|
18
|
+
readonly close: "/api/development-canvas/pty/close";
|
|
19
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/** Host-owned Development Canvas PTY sessions. UI observes; this module owns lifetime. */
|
|
2
|
+
import type { CanvasPtyCommandId, CanvasPtyView } from './canvas-pty-contract.ts';
|
|
3
|
+
/**
|
|
4
|
+
* A Finder-launched macOS app gets a minimal PATH (`/usr/bin:/bin:…`), so a
|
|
5
|
+
* bare agent name such as `claude` fails to spawn even when it is installed.
|
|
6
|
+
* Resolve bare commands to an absolute executable by merging `env.PATH` with
|
|
7
|
+
* the user's login-shell PATH (cached per registry).
|
|
8
|
+
*/
|
|
9
|
+
export declare function canvasPtySpawnDirs(env: NodeJS.ProcessEnv, platform: NodeJS.Platform): string[];
|
|
10
|
+
/**
|
|
11
|
+
* Return an absolute executable path for `command`, or `undefined` when none of
|
|
12
|
+
* `dirs` contains an executable `command`. Absolute/relative paths pass through.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveCanvasPtyCommand(command: string, dirs: readonly string[], platform: NodeJS.Platform): string | undefined;
|
|
15
|
+
export interface CanvasPtyProcess {
|
|
16
|
+
onData(listener: (data: string) => void): {
|
|
17
|
+
dispose(): void;
|
|
18
|
+
};
|
|
19
|
+
onExit(listener: (event: {
|
|
20
|
+
exitCode: number;
|
|
21
|
+
signal?: number;
|
|
22
|
+
}) => void): {
|
|
23
|
+
dispose(): void;
|
|
24
|
+
};
|
|
25
|
+
write(data: string): void;
|
|
26
|
+
resize(cols: number, rows: number): void;
|
|
27
|
+
kill(signal?: string): void;
|
|
28
|
+
}
|
|
29
|
+
/** PTY spawn injected so unit tests never launch a real process. */
|
|
30
|
+
export type CanvasPtySpawn = (command: string, args: readonly string[], options: {
|
|
31
|
+
readonly cwd: string;
|
|
32
|
+
readonly env: NodeJS.ProcessEnv;
|
|
33
|
+
readonly name: string;
|
|
34
|
+
readonly cols: number;
|
|
35
|
+
readonly rows: number;
|
|
36
|
+
}) => CanvasPtyProcess;
|
|
37
|
+
export interface CanvasPtySpawnPlan {
|
|
38
|
+
readonly command: string;
|
|
39
|
+
readonly args: readonly string[];
|
|
40
|
+
}
|
|
41
|
+
export interface CanvasPtyRegistryOptions {
|
|
42
|
+
readonly spawn?: CanvasPtySpawn;
|
|
43
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
44
|
+
readonly cwd?: string;
|
|
45
|
+
readonly platform?: NodeJS.Platform;
|
|
46
|
+
readonly createId?: () => string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolve argv for one allowlisted canvas command.
|
|
50
|
+
* @param commandId - catalog id from the tab.
|
|
51
|
+
* @param platform - Host process.platform.
|
|
52
|
+
* @param env - environment used to pick SHELL / ComSpec.
|
|
53
|
+
*/
|
|
54
|
+
export declare function planCanvasPtyCommand(commandId: CanvasPtyCommandId, platform: NodeJS.Platform, env: NodeJS.ProcessEnv): CanvasPtySpawnPlan;
|
|
55
|
+
/** Table of live native PTY sessions for one Development Canvas Host fiber. */
|
|
56
|
+
export declare class CanvasPtyRegistry {
|
|
57
|
+
private readonly sessions;
|
|
58
|
+
private readonly spawnImpl;
|
|
59
|
+
private readonly env;
|
|
60
|
+
private readonly cwd;
|
|
61
|
+
private readonly platform;
|
|
62
|
+
private readonly createId;
|
|
63
|
+
private readonly spawnDirs;
|
|
64
|
+
constructor(options?: CanvasPtyRegistryOptions);
|
|
65
|
+
/**
|
|
66
|
+
* Start one allowlisted command inside a real terminal.
|
|
67
|
+
* @param commandId - catalog id from the Terminal/agent tab.
|
|
68
|
+
*/
|
|
69
|
+
start(commandId: string): CanvasPtyView;
|
|
70
|
+
/** Write exact terminal input bytes. */
|
|
71
|
+
write(id: string, data: string): void;
|
|
72
|
+
/** Resize one live terminal. */
|
|
73
|
+
resize(id: string, cols: number, rows: number): void;
|
|
74
|
+
/** Snapshot one session for the renderer. */
|
|
75
|
+
read(id: string): CanvasPtyView;
|
|
76
|
+
/** Stop one session. Idempotent. */
|
|
77
|
+
close(id: string): Promise<void>;
|
|
78
|
+
/** Stop every session owned by this fiber. */
|
|
79
|
+
disposeAll(): Promise<void>;
|
|
80
|
+
private require;
|
|
81
|
+
private view;
|
|
82
|
+
}
|