@newsails/veil-studio 1.0.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.
Files changed (87) hide show
  1. package/README.md +181 -0
  2. package/bin/veil-studio.js +142 -0
  3. package/nuxt-app/.output/public/200.html +13 -0
  4. package/nuxt-app/.output/public/404.html +13 -0
  5. package/nuxt-app/.output/public/_nuxt/builds/latest.json +1 -0
  6. package/nuxt-app/.output/public/_nuxt/builds/meta/6b28df26-54af-4fad-a1f0-38808960d9fe.json +1 -0
  7. package/nuxt-app/.output/public/_nuxt/entry.BrrOeBSX.js +120 -0
  8. package/nuxt-app/.output/public/_nuxt/entry.CYnp7zY5.css +1 -0
  9. package/nuxt-app/.output/public/_nuxt/error-404.BbdzCaXe.js +1 -0
  10. package/nuxt-app/.output/public/_nuxt/error-404.JekaaCis.css +1 -0
  11. package/nuxt-app/.output/public/_nuxt/error-500.CNP9nqm1.css +1 -0
  12. package/nuxt-app/.output/public/_nuxt/error-500.DbOlBIIY.js +1 -0
  13. package/nuxt-app/.output/public/_nuxt/index.BEoXSIOu.css +1 -0
  14. package/nuxt-app/.output/public/_nuxt/index.CNms2yAq.js +1 -0
  15. package/nuxt-app/.output/public/_nuxt/materialdesignicons-webfont.B7mPwVP_.ttf +0 -0
  16. package/nuxt-app/.output/public/_nuxt/materialdesignicons-webfont.CSr8KVlo.eot +0 -0
  17. package/nuxt-app/.output/public/_nuxt/materialdesignicons-webfont.Dp5v-WZN.woff2 +0 -0
  18. package/nuxt-app/.output/public/_nuxt/materialdesignicons-webfont.PXm3-2wK.woff +0 -0
  19. package/nuxt-app/.output/public/_nuxt/vue.-sixQ7xP.BlWffD__.js +1 -0
  20. package/nuxt-app/.output/public/index.html +13 -0
  21. package/package.json +37 -0
  22. package/server/index.js +184 -0
  23. package/server/routes/files.js +80 -0
  24. package/server/socket.js +507 -0
  25. package/server/utils/board-state.js +357 -0
  26. package/server/utils/config.js +51 -0
  27. package/server/utils/db.js +484 -0
  28. package/server/utils/element-instances.js +104 -0
  29. package/server/utils/element-registry.js +127 -0
  30. package/server/utils/elements/agent-instance.js +62 -0
  31. package/server/utils/elements/agent.js +93 -0
  32. package/server/utils/elements/annotation.js +30 -0
  33. package/server/utils/elements/approval-gate.js +49 -0
  34. package/server/utils/elements/assumption.js +32 -0
  35. package/server/utils/elements/blocker.js +36 -0
  36. package/server/utils/elements/chat-room.js +47 -0
  37. package/server/utils/elements/chat-view.js +33 -0
  38. package/server/utils/elements/code-block.js +39 -0
  39. package/server/utils/elements/collapsible-group.js +37 -0
  40. package/server/utils/elements/comparison-table.js +38 -0
  41. package/server/utils/elements/constraint.js +32 -0
  42. package/server/utils/elements/decision.js +39 -0
  43. package/server/utils/elements/diff-patch.js +38 -0
  44. package/server/utils/elements/divider.js +30 -0
  45. package/server/utils/elements/document-draft.js +35 -0
  46. package/server/utils/elements/fact-claim.js +36 -0
  47. package/server/utils/elements/feedback-request.js +43 -0
  48. package/server/utils/elements/file-reference.js +31 -0
  49. package/server/utils/elements/filter.js +48 -0
  50. package/server/utils/elements/generator.js +51 -0
  51. package/server/utils/elements/goal.js +36 -0
  52. package/server/utils/elements/html.js +35 -0
  53. package/server/utils/elements/idea.js +32 -0
  54. package/server/utils/elements/image-local.js +21 -0
  55. package/server/utils/elements/image.js +34 -0
  56. package/server/utils/elements/json-object.js +47 -0
  57. package/server/utils/elements/label-tag.js +30 -0
  58. package/server/utils/elements/markdown.js +37 -0
  59. package/server/utils/elements/merger.js +36 -0
  60. package/server/utils/elements/message.js +40 -0
  61. package/server/utils/elements/milestone.js +44 -0
  62. package/server/utils/elements/notification.js +34 -0
  63. package/server/utils/elements/outline.js +35 -0
  64. package/server/utils/elements/primitive.js +36 -0
  65. package/server/utils/elements/pro-con-list.js +39 -0
  66. package/server/utils/elements/processor.js +54 -0
  67. package/server/utils/elements/project.js +40 -0
  68. package/server/utils/elements/question.js +42 -0
  69. package/server/utils/elements/queue.js +85 -0
  70. package/server/utils/elements/research-note.js +41 -0
  71. package/server/utils/elements/section.js +35 -0
  72. package/server/utils/elements/source-collection.js +45 -0
  73. package/server/utils/elements/splitter.js +42 -0
  74. package/server/utils/elements/status-update.js +38 -0
  75. package/server/utils/elements/task.js +72 -0
  76. package/server/utils/elements/template.js +46 -0
  77. package/server/utils/elements/test-case.js +42 -0
  78. package/server/utils/elements/text.js +29 -0
  79. package/server/utils/elements/todo-list.js +57 -0
  80. package/server/utils/elements/url-card.js +37 -0
  81. package/server/utils/elements/web-search-query.js +46 -0
  82. package/server/utils/elements/web-snapshot.js +37 -0
  83. package/server/utils/file-utils.js +88 -0
  84. package/server/utils/session-watcher.js +108 -0
  85. package/server/utils/socket-io.js +14 -0
  86. package/server/utils/veil-client.js +185 -0
  87. package/server/utils/veil-ws.js +207 -0
package/README.md ADDED
@@ -0,0 +1,181 @@
1
+ # Veil Studio
2
+
3
+ Visual workflow IDE for VeilCLI — an LLM agent runner.
4
+ Drag agents, sessions, tasks, memories, and data blocks onto an infinite canvas, wire them together, and watch everything run in real time.
5
+
6
+ ---
7
+
8
+ ## Features
9
+
10
+ - **Infinite canvas** — place any element type, wire ports, organize with zones and saved views
11
+ - **Real-time sync** — all board mutations broadcast to every connected client instantly
12
+ - **Live chat** — stream token-by-token responses from any agent session, directly in the canvas
13
+ - **External session monitoring** — sessions started by other apps or agent tools appear in Studio in real time, with live streaming, tool indicators, and user messages
14
+ - **File explorer** — browse, edit, and add project files to the board as elements
15
+ - **Custom elements** — drop a folder into `.veil-studio/elements/` to add any element type without rebuilding
16
+ - **No build step** — Express server is plain CommonJS; starts instantly
17
+
18
+ ---
19
+
20
+ ## Quick Start
21
+
22
+ ```bash
23
+ # Install globally
24
+ npm install -g @newsails/veil-studio
25
+
26
+ # Run (from any directory — that directory becomes the workspace)
27
+ veil-studio
28
+ ```
29
+
30
+ Open **http://localhost:4444**
31
+
32
+ > **Node ≥18 required** for running. Node 20 is only needed if building the frontend from source.
33
+
34
+ ### CLI Options
35
+
36
+ ```
37
+ veil-studio [options]
38
+
39
+ --port, -p <number> Studio port (default: 4444)
40
+ --api, -a <url> VeilCLI API base URL (default: http://localhost:5050)
41
+ --api-port, -ap <number> VeilCLI port on localhost (shortcut for --api)
42
+ --project, -d <path> Workspace directory (default: cwd)
43
+ --secret, -s <token> VeilCLI API secret token
44
+ --dev, -D Force dev mode
45
+ --help, -h Show help
46
+ ```
47
+
48
+ Positional shorthand: `veil-studio <port> [api] [project] [secret]`
49
+
50
+ ### Run from source
51
+
52
+ ```bash
53
+ npm install
54
+ node bin/veil-studio.js
55
+ # or
56
+ npm start
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Architecture
62
+
63
+ ```
64
+ Browser (Nuxt 3 SPA — TypeScript, Pinia, TailwindCSS)
65
+ │ Socket.IO ← board mutations, chat, VeilCLI proxy
66
+ │ REST /api/files/* ← file system only
67
+
68
+ Express server (port 4444) — Plain CommonJS, no build step
69
+ ├── Socket.IO handlers server/socket.js
70
+ ├── REST routes server/routes/files.js
71
+ ├── SQLite (sync) .veil-studio/studio.db
72
+ ├── In-memory Maps board state (elements, links, zones, views)
73
+ └── WebSocket client ──► VeilCLI /ws (port 5050)
74
+ real-time events for all sessions & tasks
75
+ ```
76
+
77
+ **Key rules:**
78
+ - Browser **never** talks to VeilCLI directly — all calls proxied via Studio Socket.IO
79
+ - Board state is **server-authoritative** — clients never optimistically mutate
80
+ - Socket.IO for everything board/agent/chat; REST only for `/api/files/*`
81
+
82
+ ---
83
+
84
+ ## Environment Variables
85
+
86
+ | Variable | Default | Purpose |
87
+ |---|---|---|
88
+ | `STUDIO_PORT` | `4444` | Studio server port |
89
+ | `VEIL_API` | `http://localhost:5050` | VeilCLI base URL (auto-read from `.veil/settings.json`) |
90
+ | `VEIL_SECRET` | _(empty)_ | `X-Veil-Secret` auth header (auto-read from `.veil/settings.json`) |
91
+ | `PROJECT_DIR` | `process.cwd()` | Working directory (files, custom elements, DB) |
92
+
93
+ ---
94
+
95
+ ## Project Structure
96
+
97
+ ```
98
+ VeilCLI_Studio/
99
+ ├── server/ Backend — plain CommonJS
100
+ │ ├── index.js Entry: startup sequence, dev proxy, listen
101
+ │ ├── socket.js All Socket.IO event handlers
102
+ │ ├── routes/files.js REST /api/files/*
103
+ │ └── utils/
104
+ │ ├── config.js All env/config resolution
105
+ │ ├── db.js SQLite singleton + schema
106
+ │ ├── board-state.js In-memory Maps + DB sync + broadcasts
107
+ │ ├── element-registry.js 55 built-in + custom type registry
108
+ │ ├── element-instances.js Running element instance Map
109
+ │ ├── veil-client.js VeilCLI REST + SSE streaming wrapper
110
+ │ ├── veil-ws.js Persistent WS to VeilCLI /ws
111
+ │ ├── session-watcher.js Message-count baseline tracker
112
+ │ ├── socket-io.js getIO()/setIO() singleton
113
+ │ ├── file-utils.js Path-safe file operations
114
+ │ └── elements/ 55 built-in element definitions
115
+
116
+ ├── nuxt-app/ Frontend — Nuxt 3, TypeScript, SPA
117
+ │ ├── stores/ board.ts · ui.ts · chat.ts
118
+ │ ├── composables/ useSocket · useBoard · useCamera · useChat
119
+ │ │ useVeil · useElementRegistry · useFileExplorer
120
+ │ ├── components/ canvas/ · elements/ · sidebar/ · chat/
121
+ │ └── .output/ Production build (served by Express in prod)
122
+
123
+ └── docs/ Full reference documentation
124
+ ```
125
+
126
+ ---
127
+
128
+ ## Built-in Element Types (55)
129
+
130
+ | Category | Types |
131
+ |---|---|
132
+ | CLI | `agent` `agent-instance` `chat-view` `task` `skill` `memory` `todo-list` `custom-tool` |
133
+ | Data | `text` `rich-text` `code-block` `json-object` `file-reference` `image` `image-local` `url-card` `web-snapshot` |
134
+ | Research | `source-collection` `research-note` `comparison-table` `fact-claim` `question` `web-search-query` |
135
+ | Docs | `document-draft` `outline` `section` `template` |
136
+ | Dev | `diff-patch` `error-log` `test-case` |
137
+ | Thinking | `idea` `pro-con-list` `decision` `assumption` `constraint` `goal` `blocker` |
138
+ | PM | `project` `milestone` `status-update` |
139
+ | Comm | `chat-room` `message` `feedback-request` `approval-gate` |
140
+ | Flow | `generator` `processor` `splitter` `merger` `filter` `queue` |
141
+ | Org | `collapsible-group` `annotation` `label-tag` `divider` `primitive` |
142
+
143
+ ---
144
+
145
+ ## Custom Elements
146
+
147
+ Drop a folder in `.veil-studio/elements/<type>/` containing:
148
+
149
+ ```
150
+ element.json — metadata (type, name, icon, defaultWidth/Height, …)
151
+ index.js — server-side factory: createInstance(context) → { getViewData, getPorts, actions }
152
+ vue-component.js — frontend Vue component (receives viewData, elementId props; emits action)
153
+ ```
154
+
155
+ Click **Reload Custom Elements** in the palette sidebar — no server restart needed. Custom types with the same name as a built-in **override** the built-in completely.
156
+
157
+ ---
158
+
159
+ ## Documentation
160
+
161
+ | Document | Contents |
162
+ |---|---|
163
+ | [`docs/README.md`](docs/README.md) | Architecture deep-dive, data flow, key decisions |
164
+ | [`docs/Server.md`](docs/Server.md) | All server modules, DB schema, element system reference |
165
+ | [`docs/SocketIO.md`](docs/SocketIO.md) | Every Socket.IO event — payloads, handlers, end-to-end flows |
166
+ | [`docs/UI.md`](docs/UI.md) | Stores, composables, canvas components, chat components |
167
+
168
+ ---
169
+
170
+ ## Production Build
171
+
172
+ When installed via `npm`, the pre-built frontend is included in the package (`nuxt-app/.output/public/`). The server auto-detects it and serves it statically.
173
+
174
+ To rebuild the frontend from source (requires Node 20):
175
+
176
+ ```bash
177
+ npm run build
178
+ # runs scripts/build-ui.js → cd nuxt-app && nuxt build
179
+ ```
180
+
181
+ The server auto-detects whether `nuxt-app/.output/public/` exists — if yes, production mode; if no, dev mode (spawns Nuxt dev automatically).
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env node
2
+ 'use strict'
3
+
4
+ const path = require('path')
5
+
6
+ // ─── CLI help ────────────────────────────────────────────────────────────────
7
+
8
+ const argv = process.argv.slice(2)
9
+
10
+ if (argv.includes('--version') || argv.includes('-v')) {
11
+ const { version } = require('../package.json')
12
+ console.log(version)
13
+ process.exit(0)
14
+ }
15
+
16
+ if (argv.includes('--check-for-update') || argv.includes('-cu')) {
17
+ const https = require('https')
18
+ const { name, version } = require('../package.json')
19
+ const url = `https://registry.npmjs.org/${name}/latest`
20
+ https.get(url, { headers: { 'User-Agent': 'veil-studio-cli' } }, (res) => {
21
+ let data = ''
22
+ res.on('data', chunk => { data += chunk })
23
+ res.on('end', () => {
24
+ if (res.statusCode === 404) {
25
+ console.error(`Package "${name}" not found on npm registry. Has it been published yet?`)
26
+ process.exit(1)
27
+ }
28
+ if (res.statusCode !== 200) {
29
+ console.error(`Registry returned HTTP ${res.statusCode}.`)
30
+ process.exit(1)
31
+ }
32
+ try {
33
+ const latest = JSON.parse(data).version
34
+ if (!latest) { console.error('Unexpected registry response (no version field).'); process.exit(1) }
35
+ if (latest === version) {
36
+ console.log(`No updates available (current: v${version})`)
37
+ } else {
38
+ console.log(`New update exists: v${latest} (current: v${version})`)
39
+ }
40
+ process.exit(0)
41
+ } catch { console.error('Failed to parse registry response.'); process.exit(1) }
42
+ })
43
+ }).on('error', (err) => {
44
+ console.error(`Update check failed: ${err.message}`)
45
+ process.exit(1)
46
+ })
47
+ return // prevent server startup while check is pending
48
+ }
49
+
50
+ if (argv.includes('--help') || argv.includes('-h')) {
51
+ console.log([
52
+ '',
53
+ ' veil-studio — AI agent orchestration workspace with drag-and-drop canvas, real-time chat, and visual workflow builder for creating reusable agent workflows.',
54
+ '',
55
+ ' Usage (named flags):',
56
+ ' veil-studio [--port 4444] [--api <url>] [--project <path>] [--secret <token>]',
57
+ '',
58
+ ' Usage (positional args):',
59
+ ' veil-studio <port> [api] [project] [secret]',
60
+ ' veil-studio 4444',
61
+ ' veil-studio 4444 http://localhost:5050 /my/workspace',
62
+ '',
63
+ ' Options:',
64
+ ' --port | -p <number> Studio port (default: 4444)',
65
+ ' --api | -a <url> Veil CLI API base URL (default: http://localhost:5050)',
66
+ ' --api-port | -ap <number> Veil API port on localhost (shortcut for --api)',
67
+ ' --project | -d <path> Workspace directory (default: cwd)',
68
+ ' --secret | -s <token> Veil API secret token',
69
+ ' --dev | -D Force dev mode (nuxt dev even if build exists)',
70
+ ' --check-for-update | -cu Check npm registry for a newer version',
71
+ ' --version | -v Print version and exit',
72
+ ' --help | -h Show this help',
73
+ '',
74
+ ' Priority (highest → lowest):',
75
+ ' named flags → positional args → env vars → hardcoded defaults',
76
+ '',
77
+ ' Environment variables:',
78
+ ' STUDIO_PORT VEIL_API PROJECT_DIR VEIL_SECRET',
79
+ '',
80
+ ].join('\n'))
81
+ process.exit(0)
82
+ }
83
+
84
+ // ─── Step 1: start from env vars / hardcoded defaults ────────────────────────
85
+
86
+ let port = process.env.STUDIO_PORT || '4444'
87
+ let api = process.env.VEIL_API || 'http://localhost:5050'
88
+ let projectDir = process.env.PROJECT_DIR || process.cwd()
89
+ let secret = process.env.VEIL_SECRET || ''
90
+ let devMode = process.env.STUDIO_DEV === '1'
91
+ let apiExplicit = !!process.env.VEIL_API // track if api was set by env
92
+
93
+ // ─── Step 2: apply positional args (override env/defaults) ───────────────────
94
+
95
+ const positional = []
96
+ for (let i = 0; i < argv.length; i++) {
97
+ if (!argv[i].startsWith('-')) positional.push(argv[i])
98
+ }
99
+ if (positional[0]) port = positional[0]
100
+ if (positional[1]) api = positional[1]
101
+ if (positional[2]) projectDir = positional[2]
102
+ if (positional[3]) secret = positional[3]
103
+
104
+ // ─── Step 3: apply named flags (highest priority) ────────────────────────────
105
+
106
+ let apiPort = ''
107
+ for (let i = 0; i < argv.length; i++) {
108
+ const a = argv[i]
109
+ const v = argv[i + 1]
110
+ if ((a === '--port' || a === '-p') && v && !v.startsWith('-')) { port = v; i++ }
111
+ if ((a === '--api' || a === '-a') && v && !v.startsWith('-')) { api = v; apiExplicit = true; i++ }
112
+ if ((a === '--api-port' || a === '-ap') && v && !v.startsWith('-')) { apiPort = v; i++ }
113
+ if ((a === '--project' || a === '-d') && v && !v.startsWith('-')) { projectDir = v; i++ }
114
+ if ((a === '--secret' || a === '-s') && v && !v.startsWith('-')) { secret = v; i++ }
115
+ if (a === '--dev' || a === '-D') devMode = true
116
+ }
117
+
118
+ // --api-port: build localhost URL only when --api was not explicitly provided
119
+ if (apiPort && !apiExplicit) {
120
+ api = `http://localhost:${apiPort}`
121
+ }
122
+
123
+ // ─── Set env before requiring server ────────────────────────────────────────
124
+
125
+ process.env.STUDIO_PORT = port
126
+ process.env.VEIL_API = api
127
+ process.env.PROJECT_DIR = path.resolve(projectDir)
128
+ if (secret) process.env.VEIL_SECRET = secret
129
+ if (devMode) process.env.STUDIO_DEV = '1'
130
+
131
+ // ─── Banner ──────────────────────────────────────────────────────────────────
132
+
133
+ console.log('')
134
+ console.log(' Veil Studio')
135
+ console.log(` Studio : http://localhost:${port}`)
136
+ console.log(` VeilAPI : ${api}`)
137
+ console.log(` Project : ${process.env.PROJECT_DIR}`)
138
+ console.log('')
139
+
140
+ // ─── Boot server ─────────────────────────────────────────────────────────────
141
+
142
+ require('../server/index.js')
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html><html><head><meta charset="utf-8">
2
+ <meta name="viewport" content="width=device-width, initial-scale=1">
3
+ <title>Veil Studio</title>
4
+ <link rel="stylesheet" href="/_nuxt/entry.CYnp7zY5.css">
5
+ <link rel="modulepreload" as="script" crossorigin href="/_nuxt/entry.BrrOeBSX.js">
6
+ <link rel="prefetch" as="style" crossorigin href="/_nuxt/error-404.JekaaCis.css">
7
+ <link rel="prefetch" as="script" crossorigin href="/_nuxt/error-404.BbdzCaXe.js">
8
+ <link rel="prefetch" as="script" crossorigin href="/_nuxt/vue.-sixQ7xP.BlWffD__.js">
9
+ <link rel="prefetch" as="style" crossorigin href="/_nuxt/error-500.CNP9nqm1.css">
10
+ <link rel="prefetch" as="script" crossorigin href="/_nuxt/error-500.DbOlBIIY.js">
11
+ <script type="module" src="/_nuxt/entry.BrrOeBSX.js" crossorigin></script>
12
+ <script id="unhead:payload" type="application/json">{"title":"Veil Studio"}</script></head><body><div id="__nuxt"></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"_errors":1,"serverRendered":2,"data":3,"state":4,"once":5},{},false,{},{},["Set"]]</script>
13
+ <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html><html><head><meta charset="utf-8">
2
+ <meta name="viewport" content="width=device-width, initial-scale=1">
3
+ <title>Veil Studio</title>
4
+ <link rel="stylesheet" href="/_nuxt/entry.CYnp7zY5.css">
5
+ <link rel="modulepreload" as="script" crossorigin href="/_nuxt/entry.BrrOeBSX.js">
6
+ <link rel="prefetch" as="style" crossorigin href="/_nuxt/error-404.JekaaCis.css">
7
+ <link rel="prefetch" as="script" crossorigin href="/_nuxt/error-404.BbdzCaXe.js">
8
+ <link rel="prefetch" as="script" crossorigin href="/_nuxt/vue.-sixQ7xP.BlWffD__.js">
9
+ <link rel="prefetch" as="style" crossorigin href="/_nuxt/error-500.CNP9nqm1.css">
10
+ <link rel="prefetch" as="script" crossorigin href="/_nuxt/error-500.DbOlBIIY.js">
11
+ <script type="module" src="/_nuxt/entry.BrrOeBSX.js" crossorigin></script>
12
+ <script id="unhead:payload" type="application/json">{"title":"Veil Studio"}</script></head><body><div id="__nuxt"></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"_errors":1,"serverRendered":2,"data":3,"state":4,"once":5},{},false,{},{},["Set"]]</script>
13
+ <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
@@ -0,0 +1 @@
1
+ {"id":"6b28df26-54af-4fad-a1f0-38808960d9fe","timestamp":1773909250273}
@@ -0,0 +1 @@
1
+ {"id":"6b28df26-54af-4fad-a1f0-38808960d9fe","timestamp":1773909250273,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}