@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.
- package/README.md +181 -0
- package/bin/veil-studio.js +142 -0
- package/nuxt-app/.output/public/200.html +13 -0
- package/nuxt-app/.output/public/404.html +13 -0
- package/nuxt-app/.output/public/_nuxt/builds/latest.json +1 -0
- package/nuxt-app/.output/public/_nuxt/builds/meta/6b28df26-54af-4fad-a1f0-38808960d9fe.json +1 -0
- package/nuxt-app/.output/public/_nuxt/entry.BrrOeBSX.js +120 -0
- package/nuxt-app/.output/public/_nuxt/entry.CYnp7zY5.css +1 -0
- package/nuxt-app/.output/public/_nuxt/error-404.BbdzCaXe.js +1 -0
- package/nuxt-app/.output/public/_nuxt/error-404.JekaaCis.css +1 -0
- package/nuxt-app/.output/public/_nuxt/error-500.CNP9nqm1.css +1 -0
- package/nuxt-app/.output/public/_nuxt/error-500.DbOlBIIY.js +1 -0
- package/nuxt-app/.output/public/_nuxt/index.BEoXSIOu.css +1 -0
- package/nuxt-app/.output/public/_nuxt/index.CNms2yAq.js +1 -0
- package/nuxt-app/.output/public/_nuxt/materialdesignicons-webfont.B7mPwVP_.ttf +0 -0
- package/nuxt-app/.output/public/_nuxt/materialdesignicons-webfont.CSr8KVlo.eot +0 -0
- package/nuxt-app/.output/public/_nuxt/materialdesignicons-webfont.Dp5v-WZN.woff2 +0 -0
- package/nuxt-app/.output/public/_nuxt/materialdesignicons-webfont.PXm3-2wK.woff +0 -0
- package/nuxt-app/.output/public/_nuxt/vue.-sixQ7xP.BlWffD__.js +1 -0
- package/nuxt-app/.output/public/index.html +13 -0
- package/package.json +37 -0
- package/server/index.js +184 -0
- package/server/routes/files.js +80 -0
- package/server/socket.js +507 -0
- package/server/utils/board-state.js +357 -0
- package/server/utils/config.js +51 -0
- package/server/utils/db.js +484 -0
- package/server/utils/element-instances.js +104 -0
- package/server/utils/element-registry.js +127 -0
- package/server/utils/elements/agent-instance.js +62 -0
- package/server/utils/elements/agent.js +93 -0
- package/server/utils/elements/annotation.js +30 -0
- package/server/utils/elements/approval-gate.js +49 -0
- package/server/utils/elements/assumption.js +32 -0
- package/server/utils/elements/blocker.js +36 -0
- package/server/utils/elements/chat-room.js +47 -0
- package/server/utils/elements/chat-view.js +33 -0
- package/server/utils/elements/code-block.js +39 -0
- package/server/utils/elements/collapsible-group.js +37 -0
- package/server/utils/elements/comparison-table.js +38 -0
- package/server/utils/elements/constraint.js +32 -0
- package/server/utils/elements/decision.js +39 -0
- package/server/utils/elements/diff-patch.js +38 -0
- package/server/utils/elements/divider.js +30 -0
- package/server/utils/elements/document-draft.js +35 -0
- package/server/utils/elements/fact-claim.js +36 -0
- package/server/utils/elements/feedback-request.js +43 -0
- package/server/utils/elements/file-reference.js +31 -0
- package/server/utils/elements/filter.js +48 -0
- package/server/utils/elements/generator.js +51 -0
- package/server/utils/elements/goal.js +36 -0
- package/server/utils/elements/html.js +35 -0
- package/server/utils/elements/idea.js +32 -0
- package/server/utils/elements/image-local.js +21 -0
- package/server/utils/elements/image.js +34 -0
- package/server/utils/elements/json-object.js +47 -0
- package/server/utils/elements/label-tag.js +30 -0
- package/server/utils/elements/markdown.js +37 -0
- package/server/utils/elements/merger.js +36 -0
- package/server/utils/elements/message.js +40 -0
- package/server/utils/elements/milestone.js +44 -0
- package/server/utils/elements/notification.js +34 -0
- package/server/utils/elements/outline.js +35 -0
- package/server/utils/elements/primitive.js +36 -0
- package/server/utils/elements/pro-con-list.js +39 -0
- package/server/utils/elements/processor.js +54 -0
- package/server/utils/elements/project.js +40 -0
- package/server/utils/elements/question.js +42 -0
- package/server/utils/elements/queue.js +85 -0
- package/server/utils/elements/research-note.js +41 -0
- package/server/utils/elements/section.js +35 -0
- package/server/utils/elements/source-collection.js +45 -0
- package/server/utils/elements/splitter.js +42 -0
- package/server/utils/elements/status-update.js +38 -0
- package/server/utils/elements/task.js +72 -0
- package/server/utils/elements/template.js +46 -0
- package/server/utils/elements/test-case.js +42 -0
- package/server/utils/elements/text.js +29 -0
- package/server/utils/elements/todo-list.js +57 -0
- package/server/utils/elements/url-card.js +37 -0
- package/server/utils/elements/web-search-query.js +46 -0
- package/server/utils/elements/web-snapshot.js +37 -0
- package/server/utils/file-utils.js +88 -0
- package/server/utils/session-watcher.js +108 -0
- package/server/utils/socket-io.js +14 -0
- package/server/utils/veil-client.js +185 -0
- package/server/utils/veil-ws.js +207 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'primitive',
|
|
5
|
+
name: 'Primitive',
|
|
6
|
+
description: 'Basic drawing primitive: rectangle, circle, line, text-label, or freehand.',
|
|
7
|
+
icon: 'shapes',
|
|
8
|
+
defaultWidth: 120,
|
|
9
|
+
defaultHeight: 80,
|
|
10
|
+
expansionMode: 'inline',
|
|
11
|
+
tags: ['org'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element } = context
|
|
17
|
+
return {
|
|
18
|
+
getViewData() {
|
|
19
|
+
return {
|
|
20
|
+
subtype: element.data.subtype || 'rectangle',
|
|
21
|
+
color: element.data.color || '#3b82f6',
|
|
22
|
+
fill: element.data.fill || 'transparent',
|
|
23
|
+
label: element.data.label || '',
|
|
24
|
+
points: element.data.points || [],
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
getPorts() { return [] },
|
|
28
|
+
actions: {
|
|
29
|
+
update(data = {}) {
|
|
30
|
+
const { updateElement } = require('../board-state.js')
|
|
31
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'pro-con-list',
|
|
5
|
+
name: 'Pro / Con List',
|
|
6
|
+
description: 'Weigh the pros and cons of a decision.',
|
|
7
|
+
icon: 'scale',
|
|
8
|
+
defaultWidth: 220,
|
|
9
|
+
defaultHeight: 130,
|
|
10
|
+
expansionMode: 'inline',
|
|
11
|
+
tags: ['thinking'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element } = context
|
|
17
|
+
return {
|
|
18
|
+
getViewData() {
|
|
19
|
+
return {
|
|
20
|
+
title: element.data.title || '',
|
|
21
|
+
pros: element.data.pros || [],
|
|
22
|
+
cons: element.data.cons || [],
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
getPorts() {
|
|
26
|
+
return [
|
|
27
|
+
{ key: 'items-in', direction: 'input', dataType: 'any', label: 'Items In' },
|
|
28
|
+
{ key: 'summary-out', direction: 'output', dataType: 'text', label: 'Summary Out' },
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
actions: {
|
|
32
|
+
update(data = {}) {
|
|
33
|
+
const { updateElement } = require('../board-state.js')
|
|
34
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'processor',
|
|
5
|
+
name: 'Processor',
|
|
6
|
+
description: 'Execute a JavaScript script against input data.',
|
|
7
|
+
icon: 'terminal',
|
|
8
|
+
defaultWidth: 220,
|
|
9
|
+
defaultHeight: 110,
|
|
10
|
+
expansionMode: 'popup',
|
|
11
|
+
tags: ['flow', 'dev'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element, log } = context
|
|
17
|
+
return {
|
|
18
|
+
getViewData() {
|
|
19
|
+
return {
|
|
20
|
+
script: element.data.script || '',
|
|
21
|
+
cached: element.data.cached || false,
|
|
22
|
+
result: element.data.result || null,
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
getPorts() {
|
|
26
|
+
return [
|
|
27
|
+
{ key: 'input-in', direction: 'input', dataType: 'any', label: 'Input In' },
|
|
28
|
+
{ key: 'output-out', direction: 'output', dataType: 'any', label: 'Output Out' },
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
actions: {
|
|
32
|
+
run({ inputs } = {}) {
|
|
33
|
+
const script = element.data.script
|
|
34
|
+
if (!script) throw new Error('No script set')
|
|
35
|
+
let result
|
|
36
|
+
try {
|
|
37
|
+
// eslint-disable-next-line no-new-func
|
|
38
|
+
result = new Function('inputs', script)(inputs)
|
|
39
|
+
} catch (err) {
|
|
40
|
+
log(`Script error: ${err.message}`)
|
|
41
|
+
throw err
|
|
42
|
+
}
|
|
43
|
+
const { updateElement } = require('../board-state.js')
|
|
44
|
+
updateElement(element.id, { data: { ...element.data, result } })
|
|
45
|
+
return result
|
|
46
|
+
},
|
|
47
|
+
update(data = {}) {
|
|
48
|
+
const { updateElement } = require('../board-state.js')
|
|
49
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'project',
|
|
5
|
+
name: 'Project',
|
|
6
|
+
description: 'A project with status and milestones.',
|
|
7
|
+
icon: 'folder-kanban',
|
|
8
|
+
defaultWidth: 240,
|
|
9
|
+
defaultHeight: 130,
|
|
10
|
+
expansionMode: 'sidebar',
|
|
11
|
+
tags: ['pm'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element } = context
|
|
17
|
+
return {
|
|
18
|
+
getViewData() {
|
|
19
|
+
return {
|
|
20
|
+
title: element.data.title || '',
|
|
21
|
+
description: element.data.description || '',
|
|
22
|
+
status: element.data.status || 'active',
|
|
23
|
+
milestones: element.data.milestones || [],
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
getPorts() {
|
|
27
|
+
return [
|
|
28
|
+
{ key: 'tasks-in', direction: 'input', dataType: 'any', label: 'Tasks In' },
|
|
29
|
+
{ key: 'status-out', direction: 'output', dataType: 'text', label: 'Status Out' },
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
actions: {
|
|
33
|
+
update(data = {}) {
|
|
34
|
+
const { updateElement } = require('../board-state.js')
|
|
35
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'question',
|
|
5
|
+
name: 'Question',
|
|
6
|
+
description: 'An open question with status tracking.',
|
|
7
|
+
icon: 'help-circle',
|
|
8
|
+
defaultWidth: 200,
|
|
9
|
+
defaultHeight: 80,
|
|
10
|
+
expansionMode: 'inline',
|
|
11
|
+
tags: ['research', 'thinking'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
|
|
14
|
+
createInstance(context) {
|
|
15
|
+
const { element } = context
|
|
16
|
+
return {
|
|
17
|
+
getViewData() {
|
|
18
|
+
return {
|
|
19
|
+
text: element.data.text || '',
|
|
20
|
+
status: element.data.status || 'open',
|
|
21
|
+
answer: element.data.answer || null,
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
getPorts() {
|
|
25
|
+
return [
|
|
26
|
+
{ key: 'question-out', direction: 'output', dataType: 'text', label: 'Question Out' },
|
|
27
|
+
{ key: 'answer-out', direction: 'output', dataType: 'text', label: 'Answer Out' },
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
actions: {
|
|
31
|
+
answer({ text } = {}) {
|
|
32
|
+
const { updateElement } = require('../board-state.js')
|
|
33
|
+
updateElement(element.id, { data: { ...element.data, status: 'answered', answer: text } })
|
|
34
|
+
},
|
|
35
|
+
update(data = {}) {
|
|
36
|
+
const { updateElement } = require('../board-state.js')
|
|
37
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'queue',
|
|
5
|
+
name: 'Queue',
|
|
6
|
+
description: 'A queue of items with manual or timer-based triggering.',
|
|
7
|
+
icon: 'list-ordered',
|
|
8
|
+
defaultWidth: 200,
|
|
9
|
+
defaultHeight: 110,
|
|
10
|
+
expansionMode: 'inline',
|
|
11
|
+
tags: ['flow'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element, emit, log } = context
|
|
17
|
+
let _interval = null
|
|
18
|
+
|
|
19
|
+
function _startTimer() {
|
|
20
|
+
if (_interval) return
|
|
21
|
+
const ms = element.data.intervalMs || 5000
|
|
22
|
+
_interval = setInterval(() => {
|
|
23
|
+
const items = element.data.items || []
|
|
24
|
+
if (items.length === 0) return
|
|
25
|
+
const [next, ...rest] = items
|
|
26
|
+
const { updateElement } = require('../board-state.js')
|
|
27
|
+
updateElement(element.id, { data: { ...element.data, items: rest } })
|
|
28
|
+
emit('element:view', { id: element.id, viewData: { items: rest, lastDequeued: next } })
|
|
29
|
+
}, ms)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function _stopTimer() {
|
|
33
|
+
if (_interval) { clearInterval(_interval); _interval = null }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (element.data.triggerType === 'timer') _startTimer()
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
getViewData() {
|
|
40
|
+
return {
|
|
41
|
+
items: element.data.items || [],
|
|
42
|
+
triggerType: element.data.triggerType || 'manual',
|
|
43
|
+
intervalMs: element.data.intervalMs || 5000,
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
getPorts() {
|
|
47
|
+
return [
|
|
48
|
+
{ key: 'item-in', direction: 'input', dataType: 'any', label: 'Item In' },
|
|
49
|
+
{ key: 'item-out', direction: 'output', dataType: 'any', label: 'Item Out' },
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
actions: {
|
|
53
|
+
enqueue({ item } = {}) {
|
|
54
|
+
const { updateElement } = require('../board-state.js')
|
|
55
|
+
const items = [...(element.data.items || []), item]
|
|
56
|
+
updateElement(element.id, { data: { ...element.data, items } })
|
|
57
|
+
},
|
|
58
|
+
dequeue(_params) {
|
|
59
|
+
const items = element.data.items || []
|
|
60
|
+
if (items.length === 0) return null
|
|
61
|
+
const [next, ...rest] = items
|
|
62
|
+
const { updateElement } = require('../board-state.js')
|
|
63
|
+
updateElement(element.id, { data: { ...element.data, items: rest } })
|
|
64
|
+
return next
|
|
65
|
+
},
|
|
66
|
+
setTimer({ intervalMs, enabled } = {}) {
|
|
67
|
+
const { updateElement } = require('../board-state.js')
|
|
68
|
+
if (enabled) {
|
|
69
|
+
updateElement(element.id, { data: { ...element.data, triggerType: 'timer', intervalMs: intervalMs || 5000 } })
|
|
70
|
+
_stopTimer()
|
|
71
|
+
_startTimer()
|
|
72
|
+
} else {
|
|
73
|
+
updateElement(element.id, { data: { ...element.data, triggerType: 'manual' } })
|
|
74
|
+
_stopTimer()
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
update(data = {}) {
|
|
78
|
+
const { updateElement } = require('../board-state.js')
|
|
79
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
onDestroy() { _stopTimer() },
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'research-note',
|
|
5
|
+
name: 'Research Note',
|
|
6
|
+
description: 'A note linked to research sources.',
|
|
7
|
+
icon: 'notebook',
|
|
8
|
+
defaultWidth: 220,
|
|
9
|
+
defaultHeight: 110,
|
|
10
|
+
expansionMode: 'sidebar',
|
|
11
|
+
tags: ['research'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
|
|
14
|
+
createInstance(context) {
|
|
15
|
+
const { element } = context
|
|
16
|
+
return {
|
|
17
|
+
getViewData() {
|
|
18
|
+
return {
|
|
19
|
+
title: element.data.title || '',
|
|
20
|
+
insight: element.data.insight || '',
|
|
21
|
+
content: element.data.content || '',
|
|
22
|
+
source: element.data.source || '',
|
|
23
|
+
status: element.data.status || 'open',
|
|
24
|
+
sourceIds: element.data.sourceIds || [],
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
getPorts() {
|
|
28
|
+
return [
|
|
29
|
+
{ key: 'sources-in', direction: 'input', dataType: 'json', label: 'Sources In' },
|
|
30
|
+
{ key: 'note-out', direction: 'output', dataType: 'text', label: 'Note Out' },
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
actions: {
|
|
34
|
+
update(data = {}) {
|
|
35
|
+
const { updateElement } = require('../board-state.js')
|
|
36
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'section',
|
|
5
|
+
name: 'Section',
|
|
6
|
+
description: 'A document section with title and content.',
|
|
7
|
+
icon: 'pilcrow',
|
|
8
|
+
defaultWidth: 200,
|
|
9
|
+
defaultHeight: 90,
|
|
10
|
+
expansionMode: 'inline',
|
|
11
|
+
tags: ['docs'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element } = context
|
|
17
|
+
return {
|
|
18
|
+
getViewData() {
|
|
19
|
+
return { title: element.data.title || '', content: element.data.content || '' }
|
|
20
|
+
},
|
|
21
|
+
getPorts() {
|
|
22
|
+
return [
|
|
23
|
+
{ key: 'content-in', direction: 'input', dataType: 'text', label: 'Content In' },
|
|
24
|
+
{ key: 'section-out', direction: 'output', dataType: 'text', label: 'Section Out' },
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
actions: {
|
|
28
|
+
update(data = {}) {
|
|
29
|
+
const { updateElement } = require('../board-state.js')
|
|
30
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'source-collection',
|
|
5
|
+
name: 'Source Collection',
|
|
6
|
+
description: 'A collection of research sources (URLs, files, references).',
|
|
7
|
+
icon: 'library',
|
|
8
|
+
defaultWidth: 200,
|
|
9
|
+
defaultHeight: 110,
|
|
10
|
+
expansionMode: 'popup',
|
|
11
|
+
tags: ['research'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element } = context
|
|
17
|
+
return {
|
|
18
|
+
getViewData() {
|
|
19
|
+
return {
|
|
20
|
+
title: element.data.title || '',
|
|
21
|
+
sources: element.data.sources || [],
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
getPorts() {
|
|
25
|
+
return [{ key: 'collection-out', direction: 'output', dataType: 'json', label: 'Collection Out' }]
|
|
26
|
+
},
|
|
27
|
+
actions: {
|
|
28
|
+
addSource({ url, title, type } = {}) {
|
|
29
|
+
const { updateElement } = require('../board-state.js')
|
|
30
|
+
const sources = [...(element.data.sources || []), { url, title, type, id: Date.now().toString() }]
|
|
31
|
+
updateElement(element.id, { data: { ...element.data, sources } })
|
|
32
|
+
},
|
|
33
|
+
removeSource({ id } = {}) {
|
|
34
|
+
const { updateElement } = require('../board-state.js')
|
|
35
|
+
const sources = (element.data.sources || []).filter(s => s.id !== id)
|
|
36
|
+
updateElement(element.id, { data: { ...element.data, sources } })
|
|
37
|
+
},
|
|
38
|
+
update(data = {}) {
|
|
39
|
+
const { updateElement } = require('../board-state.js')
|
|
40
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'splitter',
|
|
5
|
+
name: 'Splitter',
|
|
6
|
+
description: 'Route input to different outputs based on conditions.',
|
|
7
|
+
icon: 'split',
|
|
8
|
+
defaultWidth: 200,
|
|
9
|
+
defaultHeight: 110,
|
|
10
|
+
expansionMode: 'inline',
|
|
11
|
+
tags: ['flow'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element } = context
|
|
17
|
+
return {
|
|
18
|
+
getViewData() {
|
|
19
|
+
return { rules: element.data.rules || [] }
|
|
20
|
+
},
|
|
21
|
+
getPorts() {
|
|
22
|
+
const rules = element.data.rules || []
|
|
23
|
+
const outPorts = rules.map((r, i) => ({
|
|
24
|
+
key: `out-${i}`,
|
|
25
|
+
direction: 'output',
|
|
26
|
+
dataType: 'any',
|
|
27
|
+
label: r.label || `Out ${i + 1}`,
|
|
28
|
+
}))
|
|
29
|
+
return [
|
|
30
|
+
{ key: 'input-in', direction: 'input', dataType: 'any', label: 'Input In' },
|
|
31
|
+
...outPorts,
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
actions: {
|
|
35
|
+
update(data = {}) {
|
|
36
|
+
const { updateElement } = require('../board-state.js')
|
|
37
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'status-update',
|
|
5
|
+
name: 'Status Update',
|
|
6
|
+
description: 'A timestamped status update for a project.',
|
|
7
|
+
icon: 'megaphone',
|
|
8
|
+
defaultWidth: 220,
|
|
9
|
+
defaultHeight: 90,
|
|
10
|
+
expansionMode: 'inline',
|
|
11
|
+
tags: ['pm'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element } = context
|
|
17
|
+
return {
|
|
18
|
+
getViewData() {
|
|
19
|
+
return {
|
|
20
|
+
content: element.data.content || '',
|
|
21
|
+
timestamp: element.data.timestamp || null,
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
getPorts() {
|
|
25
|
+
return [
|
|
26
|
+
{ key: 'project-in', direction: 'input', dataType: 'any', label: 'Project In' },
|
|
27
|
+
{ key: 'update-out', direction: 'output', dataType: 'text', label: 'Update Out' },
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
actions: {
|
|
31
|
+
update(data = {}) {
|
|
32
|
+
const { updateElement } = require('../board-state.js')
|
|
33
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'task',
|
|
5
|
+
name: 'Task',
|
|
6
|
+
description: 'Run an agent task and track its status.',
|
|
7
|
+
icon: 'play-circle',
|
|
8
|
+
defaultWidth: 220,
|
|
9
|
+
defaultHeight: 120,
|
|
10
|
+
expansionMode: 'popup',
|
|
11
|
+
tags: ['cli', 'task'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
|
|
14
|
+
createInstance(context) {
|
|
15
|
+
const { element, veil, emit, log } = context
|
|
16
|
+
let _taskTimeout = null
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
getViewData() {
|
|
20
|
+
return {
|
|
21
|
+
agentName: element.data.agentName || null,
|
|
22
|
+
taskId: element.data.taskId || null,
|
|
23
|
+
prompt: element.data.prompt || '',
|
|
24
|
+
spawnOutput: element.data.spawnOutput || false,
|
|
25
|
+
result: element.data.result || null,
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
getPorts() {
|
|
30
|
+
return [
|
|
31
|
+
{ key: 'prompt-in', direction: 'input', dataType: 'text', label: 'Prompt In' },
|
|
32
|
+
{ key: 'data-in', direction: 'input', dataType: 'any', label: 'Data In' },
|
|
33
|
+
{ key: 'result', direction: 'output', dataType: 'any', label: 'Result' },
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
actions: {
|
|
38
|
+
async run({ prompt: overridePrompt } = {}) {
|
|
39
|
+
const agentName = element.data.agentName
|
|
40
|
+
if (!agentName) throw new Error('No agent name set')
|
|
41
|
+
const prompt = overridePrompt || element.data.prompt
|
|
42
|
+
if (!prompt) throw new Error('No prompt set')
|
|
43
|
+
|
|
44
|
+
log(`Creating task for agent "${agentName}"`)
|
|
45
|
+
const task = await veil.post('/tasks', { agent: agentName, prompt })
|
|
46
|
+
|
|
47
|
+
const { updateElement, updateElementState } = require('../board-state.js')
|
|
48
|
+
updateElement(element.id, { data: { ...element.data, taskId: task.id }, state: 'running' })
|
|
49
|
+
updateElementState(element.id, 'running')
|
|
50
|
+
|
|
51
|
+
// Schedule fade-out after 10 min if completed
|
|
52
|
+
if (_taskTimeout) clearTimeout(_taskTimeout)
|
|
53
|
+
_taskTimeout = setTimeout(() => {
|
|
54
|
+
updateElementState(element.id, 'completed')
|
|
55
|
+
}, 10 * 60 * 1000)
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
async cancel(_params) {
|
|
59
|
+
const taskId = element.data.taskId
|
|
60
|
+
if (!taskId) throw new Error('No active task')
|
|
61
|
+
await veil.post(`/tasks/${encodeURIComponent(taskId)}/cancel`)
|
|
62
|
+
const { updateElementState } = require('../board-state.js')
|
|
63
|
+
updateElementState(element.id, 'default')
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
onDestroy() {
|
|
68
|
+
if (_taskTimeout) clearTimeout(_taskTimeout)
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'template',
|
|
5
|
+
name: 'Template',
|
|
6
|
+
description: 'A text template with variable substitution.',
|
|
7
|
+
icon: 'file-code',
|
|
8
|
+
defaultWidth: 220,
|
|
9
|
+
defaultHeight: 90,
|
|
10
|
+
expansionMode: 'popup',
|
|
11
|
+
tags: ['docs'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element } = context
|
|
17
|
+
return {
|
|
18
|
+
getViewData() {
|
|
19
|
+
return {
|
|
20
|
+
title: element.data.title || '',
|
|
21
|
+
template: element.data.template || '',
|
|
22
|
+
variables: element.data.variables || [],
|
|
23
|
+
result: element.data.result || null,
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
getPorts() {
|
|
27
|
+
return [
|
|
28
|
+
{ key: 'vars-in', direction: 'input', dataType: 'json', label: 'Variables In' },
|
|
29
|
+
{ key: 'filled-out', direction: 'output', dataType: 'text', label: 'Filled Out' },
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
actions: {
|
|
33
|
+
fill({ vars } = {}) {
|
|
34
|
+
const tmpl = element.data.template || ''
|
|
35
|
+
const result = tmpl.replace(/\{\{(\w+)\}\}/g, (_, key) => vars?.[key] ?? `{{${key}}}`)
|
|
36
|
+
const { updateElement } = require('../board-state.js')
|
|
37
|
+
updateElement(element.id, { data: { ...element.data, result } })
|
|
38
|
+
},
|
|
39
|
+
update(data = {}) {
|
|
40
|
+
const { updateElement } = require('../board-state.js')
|
|
41
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'test-case',
|
|
5
|
+
name: 'Test Case',
|
|
6
|
+
description: 'Track a test case with input, expected, and actual output.',
|
|
7
|
+
icon: 'flask-conical',
|
|
8
|
+
defaultWidth: 240,
|
|
9
|
+
defaultHeight: 120,
|
|
10
|
+
expansionMode: 'popup',
|
|
11
|
+
tags: ['dev'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element } = context
|
|
17
|
+
return {
|
|
18
|
+
getViewData() {
|
|
19
|
+
return {
|
|
20
|
+
title: element.data.title || '',
|
|
21
|
+
input: element.data.input || '',
|
|
22
|
+
expected: element.data.expected || '',
|
|
23
|
+
actual: element.data.actual || null,
|
|
24
|
+
passed: element.data.passed ?? null,
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
getPorts() {
|
|
28
|
+
return [
|
|
29
|
+
{ key: 'input-in', direction: 'input', dataType: 'any', label: 'Input In' },
|
|
30
|
+
{ key: 'expected-in', direction: 'input', dataType: 'any', label: 'Expected In' },
|
|
31
|
+
{ key: 'result-out', direction: 'output', dataType: 'json', label: 'Result Out' },
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
actions: {
|
|
35
|
+
update(data = {}) {
|
|
36
|
+
const { updateElement } = require('../board-state.js')
|
|
37
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
}
|