@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: 'fact-claim',
|
|
5
|
+
name: 'Fact / Claim',
|
|
6
|
+
description: 'A verifiable fact or claim with confidence rating.',
|
|
7
|
+
icon: 'check-circle',
|
|
8
|
+
defaultWidth: 200,
|
|
9
|
+
defaultHeight: 80,
|
|
10
|
+
expansionMode: 'inline',
|
|
11
|
+
tags: ['research', 'thinking'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element } = context
|
|
17
|
+
return {
|
|
18
|
+
getViewData() {
|
|
19
|
+
return {
|
|
20
|
+
claim: element.data.claim || '',
|
|
21
|
+
confidence: element.data.confidence ?? 0.5,
|
|
22
|
+
sourceIds: element.data.sourceIds || [],
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
getPorts() {
|
|
26
|
+
return [{ key: 'claim-out', direction: 'output', dataType: 'text', label: 'Claim Out' }]
|
|
27
|
+
},
|
|
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,43 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'feedback-request',
|
|
5
|
+
name: 'Feedback Request',
|
|
6
|
+
description: 'Request feedback or input from an agent or user.',
|
|
7
|
+
icon: 'message-circle-question',
|
|
8
|
+
defaultWidth: 220,
|
|
9
|
+
defaultHeight: 90,
|
|
10
|
+
expansionMode: 'inline',
|
|
11
|
+
tags: ['comm'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element } = context
|
|
17
|
+
return {
|
|
18
|
+
getViewData() {
|
|
19
|
+
return {
|
|
20
|
+
question: element.data.question || '',
|
|
21
|
+
status: element.data.status || 'waiting',
|
|
22
|
+
response: element.data.response || null,
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
getPorts() {
|
|
26
|
+
return [
|
|
27
|
+
{ key: 'question-in', direction: 'input', dataType: 'text', label: 'Question In' },
|
|
28
|
+
{ key: 'response-out', direction: 'output', dataType: 'text', label: 'Response Out' },
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
actions: {
|
|
32
|
+
respond({ response } = {}) {
|
|
33
|
+
const { updateElement } = require('../board-state.js')
|
|
34
|
+
updateElement(element.id, { data: { ...element.data, status: 'answered', response } })
|
|
35
|
+
},
|
|
36
|
+
update(data = {}) {
|
|
37
|
+
const { updateElement } = require('../board-state.js')
|
|
38
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'file-reference',
|
|
5
|
+
name: 'File Reference',
|
|
6
|
+
description: 'Reference a file in the project directory.',
|
|
7
|
+
icon: 'file',
|
|
8
|
+
defaultWidth: 180,
|
|
9
|
+
defaultHeight: 70,
|
|
10
|
+
expansionMode: 'popup',
|
|
11
|
+
tags: ['data', 'file'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
|
|
14
|
+
createInstance(context) {
|
|
15
|
+
const { element } = context
|
|
16
|
+
return {
|
|
17
|
+
getViewData() {
|
|
18
|
+
return { filePath: element.data.filePath || null }
|
|
19
|
+
},
|
|
20
|
+
getPorts() {
|
|
21
|
+
return [{ key: 'file-out', direction: 'output', dataType: 'file', label: 'File Out' }]
|
|
22
|
+
},
|
|
23
|
+
actions: {
|
|
24
|
+
update({ filePath } = {}) {
|
|
25
|
+
const { updateElement } = require('../board-state.js')
|
|
26
|
+
updateElement(element.id, { data: { ...element.data, filePath } })
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'filter',
|
|
5
|
+
name: 'Filter',
|
|
6
|
+
description: 'Pass or reject input based on a JS expression.',
|
|
7
|
+
icon: 'filter',
|
|
8
|
+
defaultWidth: 200,
|
|
9
|
+
defaultHeight: 80,
|
|
10
|
+
expansionMode: 'inline',
|
|
11
|
+
tags: ['flow'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element, log } = context
|
|
17
|
+
return {
|
|
18
|
+
getViewData() {
|
|
19
|
+
return { expression: element.data.expression || '' }
|
|
20
|
+
},
|
|
21
|
+
getPorts() {
|
|
22
|
+
return [
|
|
23
|
+
{ key: 'input-in', direction: 'input', dataType: 'any', label: 'Input In' },
|
|
24
|
+
{ key: 'out-passed', direction: 'output', dataType: 'any', label: 'Passed' },
|
|
25
|
+
{ key: 'out-rejected', direction: 'output', dataType: 'any', label: 'Rejected' },
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
actions: {
|
|
29
|
+
evaluate({ input } = {}) {
|
|
30
|
+
const expr = element.data.expression
|
|
31
|
+
if (!expr) return { passed: true, rejected: false }
|
|
32
|
+
try {
|
|
33
|
+
// eslint-disable-next-line no-new-func
|
|
34
|
+
const result = new Function('input', `return (${expr})`)(input)
|
|
35
|
+
return { passed: !!result, rejected: !result }
|
|
36
|
+
} catch (err) {
|
|
37
|
+
log(`Filter expression error: ${err.message}`)
|
|
38
|
+
return { passed: false, rejected: true }
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
update(data = {}) {
|
|
42
|
+
const { updateElement } = require('../board-state.js')
|
|
43
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'generator',
|
|
5
|
+
name: 'Generator',
|
|
6
|
+
description: 'Generate content by running an agent task with a prompt template.',
|
|
7
|
+
icon: 'cpu',
|
|
8
|
+
defaultWidth: 220,
|
|
9
|
+
defaultHeight: 130,
|
|
10
|
+
expansionMode: 'popup',
|
|
11
|
+
tags: ['flow'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element, veil, log } = context
|
|
17
|
+
return {
|
|
18
|
+
getViewData() {
|
|
19
|
+
return {
|
|
20
|
+
agentName: element.data.agentName || null,
|
|
21
|
+
promptTemplate: element.data.promptTemplate || '',
|
|
22
|
+
inputType: element.data.inputType || 'text',
|
|
23
|
+
outputType: element.data.outputType || 'text',
|
|
24
|
+
spawnOutput: element.data.spawnOutput || false,
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
getPorts() {
|
|
28
|
+
return [
|
|
29
|
+
{ key: 'input-in', direction: 'input', dataType: 'any', label: 'Input In' },
|
|
30
|
+
{ key: 'output-out', direction: 'output', dataType: 'any', label: 'Output Out' },
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
actions: {
|
|
34
|
+
async run({ inputs } = {}) {
|
|
35
|
+
const agentName = element.data.agentName
|
|
36
|
+
if (!agentName) throw new Error('No agent name set')
|
|
37
|
+
const prompt = (element.data.promptTemplate || '').replace(/\{\{(\w+)\}\}/g, (_, k) => inputs?.[k] ?? `{{${k}}}`)
|
|
38
|
+
log(`Generating with agent "${agentName}"`)
|
|
39
|
+
const task = await veil.post('/tasks', { agent: agentName, prompt })
|
|
40
|
+
const { updateElement, updateElementState } = require('../board-state.js')
|
|
41
|
+
updateElement(element.id, { data: { ...element.data, lastTaskId: task.id } })
|
|
42
|
+
updateElementState(element.id, 'running')
|
|
43
|
+
},
|
|
44
|
+
update(data = {}) {
|
|
45
|
+
const { updateElement } = require('../board-state.js')
|
|
46
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'goal',
|
|
5
|
+
name: 'Goal',
|
|
6
|
+
description: 'A goal with success criteria.',
|
|
7
|
+
icon: 'target',
|
|
8
|
+
defaultWidth: 200,
|
|
9
|
+
defaultHeight: 90,
|
|
10
|
+
expansionMode: 'inline',
|
|
11
|
+
tags: ['thinking', '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
|
+
criteria: element.data.criteria || [],
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
getPorts() {
|
|
26
|
+
return [{ key: 'goal-out', direction: 'output', dataType: 'text', label: 'Goal Out' }]
|
|
27
|
+
},
|
|
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,35 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'html',
|
|
5
|
+
name: 'HTML Preview',
|
|
6
|
+
description: 'Write HTML in edit mode, preview it live via a sandboxed iframe.',
|
|
7
|
+
icon: 'code-tags',
|
|
8
|
+
defaultWidth: 320,
|
|
9
|
+
defaultHeight: 240,
|
|
10
|
+
tags: ['data', 'dev'],
|
|
11
|
+
isBuiltIn: true,
|
|
12
|
+
|
|
13
|
+
createInstance(context) {
|
|
14
|
+
const { element } = context
|
|
15
|
+
return {
|
|
16
|
+
getViewData() {
|
|
17
|
+
return {
|
|
18
|
+
html: element.data.html || '',
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
getPorts() {
|
|
22
|
+
return [
|
|
23
|
+
{ key: 'html-in', direction: 'input', dataType: 'text', label: 'HTML In' },
|
|
24
|
+
{ key: 'html-out', direction: 'output', dataType: 'text', label: 'HTML 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,32 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'idea',
|
|
5
|
+
name: 'Idea',
|
|
6
|
+
description: 'Capture a single idea or insight.',
|
|
7
|
+
icon: 'lightbulb',
|
|
8
|
+
defaultWidth: 170,
|
|
9
|
+
defaultHeight: 80,
|
|
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 { text: element.data.text || '', category: element.data.category || null }
|
|
20
|
+
},
|
|
21
|
+
getPorts() {
|
|
22
|
+
return [{ key: 'idea-out', direction: 'output', dataType: 'text', label: 'Idea Out' }]
|
|
23
|
+
},
|
|
24
|
+
actions: {
|
|
25
|
+
update(data = {}) {
|
|
26
|
+
const { updateElement } = require('../board-state.js')
|
|
27
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'image-local',
|
|
5
|
+
name: 'Image (Local)',
|
|
6
|
+
description: 'Display a local file image by its path on disk.',
|
|
7
|
+
icon: '🖼',
|
|
8
|
+
defaultWidth: 200,
|
|
9
|
+
defaultHeight: 160,
|
|
10
|
+
expansionMode: 'inline',
|
|
11
|
+
tags: ['data', 'media'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
|
|
14
|
+
createInstance(_context) {
|
|
15
|
+
return {
|
|
16
|
+
getViewData() { return {} },
|
|
17
|
+
getPorts() { return [] },
|
|
18
|
+
actions: {},
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'image',
|
|
5
|
+
name: 'Image',
|
|
6
|
+
description: 'Display an image from the project directory.',
|
|
7
|
+
icon: 'image',
|
|
8
|
+
defaultWidth: 220,
|
|
9
|
+
defaultHeight: 160,
|
|
10
|
+
expansionMode: 'popup',
|
|
11
|
+
tags: ['data', 'media'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
|
|
14
|
+
createInstance(context) {
|
|
15
|
+
const { element } = context
|
|
16
|
+
return {
|
|
17
|
+
getViewData() {
|
|
18
|
+
return { filePath: element.data.filePath || null, alt: element.data.alt || '' }
|
|
19
|
+
},
|
|
20
|
+
getPorts() {
|
|
21
|
+
return [{ key: 'image-out', direction: 'output', dataType: 'file', label: 'Image Out' }]
|
|
22
|
+
},
|
|
23
|
+
actions: {
|
|
24
|
+
update({ filePath, alt } = {}) {
|
|
25
|
+
const { updateElement } = require('../board-state.js')
|
|
26
|
+
const data = { ...element.data }
|
|
27
|
+
if (filePath !== undefined) data.filePath = filePath
|
|
28
|
+
if (alt !== undefined) data.alt = alt
|
|
29
|
+
updateElement(element.id, { data })
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'json-object',
|
|
5
|
+
name: 'JSON Object',
|
|
6
|
+
description: 'Store and display a JSON object with dynamic output ports per top-level key.',
|
|
7
|
+
icon: 'braces',
|
|
8
|
+
defaultWidth: 220,
|
|
9
|
+
defaultHeight: 110,
|
|
10
|
+
expansionMode: 'popup',
|
|
11
|
+
tags: ['data'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
|
|
14
|
+
createInstance(context) {
|
|
15
|
+
const { element } = context
|
|
16
|
+
return {
|
|
17
|
+
getViewData() {
|
|
18
|
+
return {
|
|
19
|
+
content: element.data.content || {},
|
|
20
|
+
title: element.data.title || '',
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
getPorts() {
|
|
24
|
+
const content = element.data.content || {}
|
|
25
|
+
const keyPorts = Object.keys(content).map(key => ({
|
|
26
|
+
key: `out-${key}`,
|
|
27
|
+
direction: 'output',
|
|
28
|
+
dataType: 'any',
|
|
29
|
+
label: key,
|
|
30
|
+
}))
|
|
31
|
+
return [
|
|
32
|
+
{ key: 'full-out', direction: 'output', dataType: 'json', label: 'Full Object' },
|
|
33
|
+
...keyPorts,
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
actions: {
|
|
37
|
+
update({ content, title } = {}) {
|
|
38
|
+
const { updateElement } = require('../board-state.js')
|
|
39
|
+
const data = { ...element.data }
|
|
40
|
+
if (content !== undefined) data.content = content
|
|
41
|
+
if (title !== undefined) data.title = title
|
|
42
|
+
updateElement(element.id, { data })
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'label-tag',
|
|
5
|
+
name: 'Label / Tag',
|
|
6
|
+
description: 'A visual label or tag for organizing elements.',
|
|
7
|
+
icon: 'tag',
|
|
8
|
+
defaultWidth: 120,
|
|
9
|
+
defaultHeight: 36,
|
|
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 { text: element.data.text || '', color: element.data.color || '#3b82f6' }
|
|
20
|
+
},
|
|
21
|
+
getPorts() { return [] },
|
|
22
|
+
actions: {
|
|
23
|
+
update(data = {}) {
|
|
24
|
+
const { updateElement } = require('../board-state.js')
|
|
25
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'markdown',
|
|
5
|
+
name: 'Markdown',
|
|
6
|
+
description: 'A markdown note with rendered preview and edit/read toggle.',
|
|
7
|
+
icon: 'file-text',
|
|
8
|
+
defaultWidth: 220,
|
|
9
|
+
defaultHeight: 140,
|
|
10
|
+
expansionMode: 'inline',
|
|
11
|
+
tags: ['data', 'content'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
|
|
14
|
+
createInstance(context) {
|
|
15
|
+
const { element } = context
|
|
16
|
+
return {
|
|
17
|
+
getViewData() {
|
|
18
|
+
return {
|
|
19
|
+
content: element.data.content || '',
|
|
20
|
+
title: element.data.title || '',
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
getPorts() {
|
|
24
|
+
return [{ key: 'text-out', direction: 'output', dataType: 'text', label: 'Text Out' }]
|
|
25
|
+
},
|
|
26
|
+
actions: {
|
|
27
|
+
update({ content, title } = {}) {
|
|
28
|
+
const { updateElement } = require('../board-state.js')
|
|
29
|
+
const data = { ...element.data }
|
|
30
|
+
if (content !== undefined) data.content = content
|
|
31
|
+
if (title !== undefined) data.title = title
|
|
32
|
+
updateElement(element.id, { data })
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'merger',
|
|
5
|
+
name: 'Merger',
|
|
6
|
+
description: 'Combine multiple inputs into a single output.',
|
|
7
|
+
icon: 'merge',
|
|
8
|
+
defaultWidth: 200,
|
|
9
|
+
defaultHeight: 90,
|
|
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 { strategy: element.data.strategy || 'concat' }
|
|
20
|
+
},
|
|
21
|
+
getPorts() {
|
|
22
|
+
return [
|
|
23
|
+
{ key: 'in-a', direction: 'input', dataType: 'any', label: 'Input A' },
|
|
24
|
+
{ key: 'in-b', direction: 'input', dataType: 'any', label: 'Input B' },
|
|
25
|
+
{ key: 'merged-out', direction: 'output', dataType: 'any', label: 'Merged Out' },
|
|
26
|
+
]
|
|
27
|
+
},
|
|
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,40 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'message',
|
|
5
|
+
name: 'Message',
|
|
6
|
+
description: 'A single message with sender and content.',
|
|
7
|
+
icon: 'message-square',
|
|
8
|
+
defaultWidth: 200,
|
|
9
|
+
defaultHeight: 80,
|
|
10
|
+
expansionMode: 'inline',
|
|
11
|
+
tags: ['comm'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
hiddenFromPalette: true,
|
|
14
|
+
|
|
15
|
+
createInstance(context) {
|
|
16
|
+
const { element } = context
|
|
17
|
+
return {
|
|
18
|
+
getViewData() {
|
|
19
|
+
return {
|
|
20
|
+
from: element.data.from || '',
|
|
21
|
+
content: element.data.content || '',
|
|
22
|
+
timestamp: element.data.timestamp || null,
|
|
23
|
+
to: element.data.to || null,
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
getPorts() {
|
|
27
|
+
return [
|
|
28
|
+
{ key: 'msg-in', direction: 'input', dataType: 'text', label: 'Message In' },
|
|
29
|
+
{ key: 'msg-out', direction: 'output', dataType: 'text', label: 'Message 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,44 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'milestone',
|
|
5
|
+
name: 'Milestone',
|
|
6
|
+
description: 'A project milestone with deadline.',
|
|
7
|
+
icon: 'flag',
|
|
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
|
+
title: element.data.title || '',
|
|
21
|
+
deadline: element.data.deadline || null,
|
|
22
|
+
completed: element.data.completed || false,
|
|
23
|
+
taskIds: element.data.taskIds || [],
|
|
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
|
+
complete(_params) {
|
|
38
|
+
const { updateElement } = require('../board-state.js')
|
|
39
|
+
updateElement(element.id, { data: { ...element.data, completed: true } })
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'notification',
|
|
5
|
+
name: 'Notification',
|
|
6
|
+
description: 'A styled notification card with color, icon, title, and content.',
|
|
7
|
+
icon: 'bell',
|
|
8
|
+
defaultWidth: 220,
|
|
9
|
+
defaultHeight: 100,
|
|
10
|
+
expansionMode: 'inline',
|
|
11
|
+
tags: ['data'],
|
|
12
|
+
isBuiltIn: true,
|
|
13
|
+
|
|
14
|
+
createInstance(context) {
|
|
15
|
+
const { element } = context
|
|
16
|
+
return {
|
|
17
|
+
getViewData() {
|
|
18
|
+
return {
|
|
19
|
+
color: element.data.color || '#60a5fa',
|
|
20
|
+
icon: element.data.icon || '',
|
|
21
|
+
title: element.data.title || '',
|
|
22
|
+
content: element.data.content || '',
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
getPorts() { return [] },
|
|
26
|
+
actions: {
|
|
27
|
+
update(data = {}) {
|
|
28
|
+
const { updateElement } = require('../board-state.js')
|
|
29
|
+
updateElement(element.id, { data: { ...element.data, ...data } })
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
type: 'outline',
|
|
5
|
+
name: 'Outline',
|
|
6
|
+
description: 'A hierarchical outline with nested nodes.',
|
|
7
|
+
icon: 'list-tree',
|
|
8
|
+
defaultWidth: 220,
|
|
9
|
+
defaultHeight: 140,
|
|
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 { title: element.data.title || '', nodes: element.data.nodes || [] }
|
|
20
|
+
},
|
|
21
|
+
getPorts() {
|
|
22
|
+
return [
|
|
23
|
+
{ key: 'items-in', direction: 'input', dataType: 'any', label: 'Items In' },
|
|
24
|
+
{ key: 'structure-out', direction: 'output', dataType: 'json', label: 'Structure 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
|
+
}
|