Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# test inputs, kept byte for byte
test/fixtures
2 changes: 2 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// the plugin's config, for the tests kept outside the shipped plugin
export { default } from './plugins/spatial-artifacts/eslint.config.js';
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
},
"scripts": {
"dev": "bun scripts/dev.ts",
"lint": "bun run --cwd plugins/spatial-artifacts lint",
"lint-fix": "bun run --cwd plugins/spatial-artifacts lint-fix",
"test": "bun run --cwd plugins/spatial-artifacts test",
"typecheck": "tsc -p plugins/spatial-artifacts/tsconfig.src.json && tsc -p plugins/spatial-artifacts/tsconfig.dev.json"
"lint": "bun run --cwd plugins/spatial-artifacts lint && prettier --check test && eslint test",
"lint-fix": "bun run --cwd plugins/spatial-artifacts lint-fix && prettier --write test && eslint --fix test",
"test": "node --test test/*.test.ts",
"typecheck": "tsc -p plugins/spatial-artifacts/tsconfig.src.json && tsc -p plugins/spatial-artifacts/tsconfig.dev.json && tsc -p test"
},
"devDependencies": {
"@eslint/js": "10.0.1",
Expand Down
1 change: 0 additions & 1 deletion plugins/spatial-artifacts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ commands/spatial.md /spatial
server/ MCP server (mcp.ts, tools/) and the daemon (daemon.ts, store, db, preview, ...)
web/ viewer shell, gallery and the in-page runtime (window.claude, comment mode)
skills/ spatial-design, spatial-diagramming, spatial-capabilities, spatial-3d-design
test/ node --test suites
~/.spatial-artifacts/ all state: artifacts, comments, db, assets, grants, server.json, server.log
```

Expand Down
3 changes: 1 addition & 2 deletions plugins/spatial-artifacts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
"scripts": {
"daemon": "node server/daemon.ts",
"lint": "prettier --check . && eslint . && tsc --project ./tsconfig.json && tsc --project ./tsconfig.dev.json && tsc --project ./tsconfig.src.json",
"lint-fix": "prettier --write . && eslint --fix .",
"test": "node --test test/*.test.ts"
"lint-fix": "prettier --write . && eslint --fix ."
},
"engines": {
"node": ">=22.18"
Expand Down
2 changes: 1 addition & 1 deletion plugins/spatial-artifacts/server/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ const next = (cur: Doc | undefined, w: Write, path: string): { path: string; nex
return { path, next: { data: { ...cur.data, [w.field]: s }, version, updatedAt: at } };
}
default:
return fail('invalid_argument', `unknown op ${w.op}`);
return fail('invalid_argument', `unknown write operation "${w.op}"`);
}
};

Expand Down
2 changes: 1 addition & 1 deletion plugins/spatial-artifacts/tsconfig.src.json
Original file line number Diff line number Diff line change
Expand Up @@ -140,5 +140,5 @@
/* Watch Options */
// assumeChangesOnlyAffectDirectDependencies
},
"include": ["server", "scripts", "test"]
"include": ["server", "scripts"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { after, before, describe, test } from 'node:test';

const HOME = mkdtempSync(join(tmpdir(), 'da-caps-'));
process.env['SPATIAL_ARTIFACTS_DIR'] = HOME;
const { startDaemon } = await import('../server/daemon.ts');
const { wrapHtml } = await import('../server/wrap.ts');
const { configured } = await import('../server/mcphost.ts');
const { startDaemon } = await import('../plugins/spatial-artifacts/server/daemon.ts');
const { wrapHtml } = await import('../plugins/spatial-artifacts/server/wrap.ts');
const { configured } = await import('../plugins/spatial-artifacts/server/mcphost.ts');

type Res = { status: number; body: any; headers: Record<string, unknown>; raw: Buffer };
const http = (
Expand Down
36 changes: 22 additions & 14 deletions plugins/spatial-artifacts/test/core.test.ts → test/core.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import { after, before, describe, test } from 'node:test';

const HOME = mkdtempSync(join(tmpdir(), 'da-test-'));
process.env['SPATIAL_ARTIFACTS_DIR'] = HOME;
const { startDaemon } = await import('../server/daemon.ts');
const { findTitle, unwrap, wrapHtml } = await import('../server/wrap.ts');
const { claudeStatus } = await import('../server/store.ts');
const { CLAUDE_WORK_MS } = await import('../server/constants.ts');
const { startDaemon } = await import('../plugins/spatial-artifacts/server/daemon.ts');
const { findTitle, unwrap, wrapHtml } = await import('../plugins/spatial-artifacts/server/wrap.ts');
const { claudeStatus } = await import('../plugins/spatial-artifacts/server/store.ts');
const { CLAUDE_WORK_MS } = await import('../plugins/spatial-artifacts/server/constants.ts');

type Res = { status: number; body: any; headers: Record<string, unknown> };
const http = (
Expand Down Expand Up @@ -605,7 +605,7 @@ describe('daemon', () => {
});

test('comment monitors run an existing script when an existing skill loads', () => {
const root = join(import.meta.dirname, '..');
const root = join(import.meta.dirname, '..', 'plugins', 'spatial-artifacts');
const monitors = JSON.parse(readFileSync(join(root, 'monitors', 'monitors.json'), 'utf8'));
const skills = ['spatial-design', 'spatial-3d-design'];
assert.deepEqual(
Expand Down Expand Up @@ -638,7 +638,7 @@ test('claude status: waiting once the work window passes, none once resolved', (

// claude code sets only CLAUDE_PLUGIN_ROOT, and codex sets it too; a bare $PLUGIN_ROOT breaks the hook in claude code
test('comment hook runs an existing script from the plugin root both CLIs set', () => {
const root = join(import.meta.dirname, '..');
const root = join(import.meta.dirname, '..', 'plugins', 'spatial-artifacts');
const [h] = JSON.parse(readFileSync(join(root, 'hooks', 'hooks.json'), 'utf8')).hooks.UserPromptSubmit[0].hooks;
const script = h.command.match(/"\$\{CLAUDE_PLUGIN_ROOT\}\/(\S+?)"/)[1];
assert.ok(existsSync(join(root, script)));
Expand All @@ -652,10 +652,14 @@ describe('mcp over stdio', () => {
SPATIAL_ARTIFACTS_PORT: String(port),
SPATIAL_ARTIFACTS_AUTO_OPEN: '0',
};
const proc = spawn(process.execPath, [join(import.meta.dirname, '..', 'server', 'mcp.ts')], {
env,
stdio: ['pipe', 'pipe', 'inherit'],
});
const proc = spawn(
process.execPath,
[join(import.meta.dirname, '..', 'plugins', 'spatial-artifacts', 'server', 'mcp.ts')],
{
env,
stdio: ['pipe', 'pipe', 'inherit'],
},
);
let buf = '';
let n = 0;
const waiting = new Map<number, (m: any) => void>();
Expand Down Expand Up @@ -702,10 +706,14 @@ describe('mcp over stdio', () => {
test('a later session republishing a file updates the artifact it went to, unless it changed since', async () => {
// a second mcp server process: what a resumed or restarted claude session starts
const later = async () => {
const p = spawn(process.execPath, [join(import.meta.dirname, '..', 'server', 'mcp.ts')], {
env,
stdio: ['pipe', 'pipe', 'inherit'],
});
const p = spawn(
process.execPath,
[join(import.meta.dirname, '..', 'plugins', 'spatial-artifacts', 'server', 'mcp.ts')],
{
env,
stdio: ['pipe', 'pipe', 'inherit'],
},
);
let b = '';
let k = 0;
const w = new Map<number, (m: any) => void>();
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const { chromium } = await import('playwright').catch(() =>
);
const HOME = mkdtempSync(join(tmpdir(), 'da-e2e-'));
process.env.SPATIAL_ARTIFACTS_DIR = HOME;
const P = join(import.meta.dirname, '..', '..');
const P = join(import.meta.dirname, '..', '..', 'plugins', 'spatial-artifacts');
const project = mkdtempSync(join(tmpdir(), 'da-proj-'));
mkdirSync(join(project, 'src'));
writeFileSync(join(project, 'src', 'a.txt'), 'hello files');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,22 @@ import { pathToFileURL } from 'node:url';

const HOME = mkdtempSync(join(tmpdir(), 'spatial-artifacts-preview-'));
process.env['SPATIAL_ARTIFACTS_DIR'] = HOME;
const { preview } = await import('../server/preview.ts');
const { preview } = await import('../plugins/spatial-artifacts/server/preview.ts');

const FIX = join(import.meta.dirname, 'fixtures');
const { assemble } = await import(
pathToFileURL(join(import.meta.dirname, '..', 'skills', 'spatial-3d-design', 'scripts', 'new-scene.mjs')).href
pathToFileURL(
join(
import.meta.dirname,
'..',
'plugins',
'spatial-artifacts',
'skills',
'spatial-3d-design',
'scripts',
'new-scene.mjs',
),
).href
);

after(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { join } from 'node:path';
import { describe, test } from 'node:test';
import { pathToFileURL } from 'node:url';

const SKILL = join(import.meta.dirname, '..', 'skills', 'spatial-3d-design');
const SKILL = join(import.meta.dirname, '..', 'plugins', 'spatial-artifacts', 'skills', 'spatial-3d-design');
const core = await import(pathToFileURL(join(SKILL, 'template', 'scene-core.mjs')).href);

const doc = (entities: unknown[], extra: Record<string, unknown> = {}) =>
Expand Down
4 changes: 4 additions & 0 deletions test/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "../plugins/spatial-artifacts/tsconfig.src.json",
"include": ["."]
}
Loading