flowviant 0.106.0 → 0.107.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.
|
@@ -27,10 +27,8 @@
|
|
|
27
27
|
* The kinds. Per kind:
|
|
28
28
|
* - `posture`: the turn profile the card runs under (turnProfile.mjs);
|
|
29
29
|
* - `artifact`: null for code (it delivers commits), else what proves a
|
|
30
|
-
* delivery — `match` over the artifact file name,
|
|
31
|
-
*
|
|
32
|
-
* viewer alone is a page, not a model), and the `missing` sentence a turn
|
|
33
|
-
* settles `nothing` with when the proof was not written;
|
|
30
|
+
* delivery — `match` over the artifact file name, and the `missing`
|
|
31
|
+
* sentence a turn settles `nothing` with when the proof was not written;
|
|
34
32
|
* - `offRuntime(rt)`: the sentence when the chosen CLI cannot run the posture.
|
|
35
33
|
*/
|
|
36
34
|
/** Every non-code kind runs on Claude: the one CLI that declares their postures. */
|
|
@@ -51,18 +49,19 @@ export const AGENT_TASK_KINDS = Object.freeze({
|
|
|
51
49
|
offRuntime: () => CLAUDE_ONLY,
|
|
52
50
|
}),
|
|
53
51
|
/**
|
|
54
|
-
* THE 3D-MODEL KIND (0.105.0
|
|
55
|
-
* model
|
|
56
|
-
*
|
|
57
|
-
*
|
|
52
|
+
* THE 3D-MODEL KIND (0.105.0; one page since 0.107.0): a three.js page that
|
|
53
|
+
* builds the model in code, which the person exports to one .glb in Review.
|
|
54
|
+
* Under the design fence (read the repo, write only `.flowviant/artifacts/**`):
|
|
55
|
+
* a model is a picture of an asset, and committing it is a separate code
|
|
56
|
+
* card a person raises at Accept. Proven by its page alone — the model is
|
|
57
|
+
* IN the page; 0.105.0's second proof (a .gltf/.glb/.obj beside it) went
|
|
58
|
+
* with the files it asked for.
|
|
58
59
|
*/
|
|
59
60
|
model: Object.freeze({
|
|
60
61
|
posture: 'design',
|
|
61
62
|
artifact: Object.freeze({
|
|
62
63
|
match: /\.html?$/i,
|
|
63
|
-
|
|
64
|
-
missing:
|
|
65
|
-
'the turn ended without writing a model bundle (an HTML viewer and a .gltf, .glb or .obj file) under .flowviant/artifacts/',
|
|
64
|
+
missing: 'the turn ended without writing a 3D model page under .flowviant/artifacts/',
|
|
66
65
|
}),
|
|
67
66
|
offRuntime: () => CLAUDE_ONLY,
|
|
68
67
|
}),
|
|
@@ -91,8 +91,8 @@ export const AGENT_TASK_TYPES = Object.freeze({
|
|
|
91
91
|
label: '3D model',
|
|
92
92
|
kind: 'model',
|
|
93
93
|
contract:
|
|
94
|
-
'model the object the card describes
|
|
95
|
-
'3D assets the repository already has.',
|
|
94
|
+
'model the object the card describes in the one three.js page, at the scale and in the units of the ' +
|
|
95
|
+
'target the card names, else of any 3D assets the repository already has.',
|
|
96
96
|
}),
|
|
97
97
|
vector: Object.freeze({
|
|
98
98
|
label: 'Icons & vector',
|
|
@@ -56,62 +56,84 @@ or, if you are stopping to ask:
|
|
|
56
56
|
past tense, plain sentences, no card ids.`;
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
|
-
* THE 3D-MODEL CARD
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
59
|
+
* THE 3D-MODEL CARD (rewritten 0.107.0, the owner, 2026-09-27: "yeah just
|
|
60
|
+
* glb"). The product is ONE .glb a person downloads and imports; the card
|
|
61
|
+
* hands back ONE three.js page that builds the model in code and shows it —
|
|
62
|
+
* how Claude makes a model a person can look at anywhere else — and Flowviant
|
|
63
|
+
* exports that page's model group to a .glb with three.js's own GLTFExporter
|
|
64
|
+
* when the person presses Download .glb in Review (apps/web
|
|
65
|
+
* `workbench/glbExport.ts`, the other half of the handshake below).
|
|
65
66
|
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* it
|
|
78
|
-
*
|
|
79
|
-
*
|
|
67
|
+
* WHY NOT A MODEL FILE ON DISK. This kind runs under the `design` posture:
|
|
68
|
+
* Read, `ls`, and `Edit(.flowviant/artifacts/**)` — text only, no shell. A
|
|
69
|
+
* .glb is binary; a .gltf's buffer is base64 floats nobody writes by hand.
|
|
70
|
+
* The 0.105.0 contract asked for OBJ + .mtl + SVG textures instead, and a
|
|
71
|
+
* katana came back as seven files, textures no game engine imports and a
|
|
72
|
+
* generator script (2026-09-27). Built in code, drawn textures are canvases,
|
|
73
|
+
* and the exporter embeds them in the .glb as PNGs.
|
|
74
|
+
*
|
|
75
|
+
* THE HANDSHAKE IS SPELLED WORD FOR WORD because the web keys on it: the page
|
|
76
|
+
* announces `glb-ready` once its model stands, and answers `export-glb` with
|
|
77
|
+
* the binary. The page runs in a scripts-only sandbox with an opaque origin,
|
|
78
|
+
* so it posts to `parent` with `'*'`; the app accepts only its own frame's
|
|
79
|
+
* messages. A page with no handshake (every 0.105.0 bundle) is still viewed;
|
|
80
|
+
* it is just never offered a Download .glb.
|
|
80
81
|
*/
|
|
81
82
|
export const SYSTEM_AGENT_MODEL = `You are the human's own Claude, working one 3D MODEL card in a git worktree of
|
|
82
83
|
their repository. Nobody is watching this run. You have the repo and nothing
|
|
83
84
|
else — no project tools, no board, no chat.
|
|
84
85
|
|
|
85
86
|
A 3D MODEL CARD HANDS BACK A MODEL YOU CAN LOOK AT, NOT A CHANGE. Nothing you
|
|
86
|
-
do here edits the product: the person turns the model around,
|
|
87
|
+
do here edits the product: the person turns the model around, downloads it as
|
|
88
|
+
one .glb, and decides.
|
|
87
89
|
|
|
88
90
|
WHAT TO DO:
|
|
89
91
|
|
|
90
|
-
1. Read the repository first
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
92
|
+
1. Read the card and the repository first. If the card names where the model
|
|
93
|
+
will be used — a game engine, a platform, a printer — meet that target's
|
|
94
|
+
import rules: its scale and units, its up axis, its triangle and texture
|
|
95
|
+
limits. Otherwise match the scale and units of any 3D assets the repository
|
|
96
|
+
already has. Say in your summary what you assumed.
|
|
97
|
+
|
|
98
|
+
2. Write ONE file, .flowviant/artifacts/<kebab-name>/index.html — a short
|
|
99
|
+
kebab-case name for what it is (for example
|
|
100
|
+
.flowviant/artifacts/reading-chair/index.html). Nothing else goes in that
|
|
101
|
+
folder: no model files, no textures, no scripts, no notes. The page BUILDS
|
|
102
|
+
THE MODEL IN CODE and shows it:
|
|
103
|
+
- three.js as ES modules from cdn.jsdelivr.net/npm, through an import map
|
|
104
|
+
for "three" and "three/addons/"; orbit controls, lights and a neutral
|
|
105
|
+
ground. Nothing else loads from the network, and nothing can be sent.
|
|
106
|
+
- the model is ONE THREE.Group named for what it is, built from three.js
|
|
107
|
+
geometry (lathe, extrude, tube, box and the rest, one mesh per part),
|
|
108
|
+
with MeshStandardMaterial only. Colour, roughness and metalness are
|
|
109
|
+
material values, or textures you DRAW ON A CANVAS in the page
|
|
110
|
+
(THREE.CanvasTexture, 1024px or less) — never an image file.
|
|
111
|
+
- the ground, a grid, the lights, a figure for scale and every other
|
|
112
|
+
helper stay OUTSIDE that group: they are the viewer's, not the model.
|
|
113
|
+
- no download or save button of your own: the page cannot download
|
|
114
|
+
anything. Flowviant's Download .glb is the way out.
|
|
115
|
+
- once the group is built, hand it to Flowviant exactly like this, with
|
|
116
|
+
MODEL the group:
|
|
117
|
+
|
|
118
|
+
import { GLTFExporter } from 'three/addons/exporters/GLTFExporter.js';
|
|
119
|
+
addEventListener('message', (e) => {
|
|
120
|
+
if (e.source !== parent || e.data?.flowviant !== 'export-glb') return;
|
|
121
|
+
new GLTFExporter().parse(
|
|
122
|
+
MODEL,
|
|
123
|
+
(glb) => parent.postMessage({ flowviant: 'glb', glb }, '*', [glb]),
|
|
124
|
+
(err) => parent.postMessage({ flowviant: 'glb-error', message: String(err) }, '*'),
|
|
125
|
+
{ binary: true }
|
|
126
|
+
);
|
|
127
|
+
});
|
|
128
|
+
parent.postMessage({ flowviant: 'glb-ready' }, '*');
|
|
129
|
+
|
|
130
|
+
Keep the page under 2 MB.
|
|
109
131
|
|
|
110
132
|
${ARTIFACT_CONTRACT_TAIL({
|
|
111
133
|
ask: `If you cannot model it without a DECISION only a person can make — which of
|
|
112
134
|
two directions, what size or style, which asset it stands beside — STOP AND
|
|
113
135
|
ASK. Do not guess. A question costs one reply; a guessed model costs a review.`,
|
|
114
|
-
summary: 'one or two sentences on what the model shows,
|
|
136
|
+
summary: 'one or two sentences on what the model shows, the folder it is in, and the scale and target you assumed',
|
|
115
137
|
})}`;
|
|
116
138
|
|
|
117
139
|
/**
|
package/bin/lib/prompts.mjs
CHANGED
|
@@ -545,8 +545,8 @@ MECHANICS OF THIS CHAT:
|
|
|
545
545
|
- "code": a change to the code — commits they review and merge. The default.
|
|
546
546
|
- "design": a UI mockup — one HTML page to look at; no code changed.
|
|
547
547
|
"Mockup", "design page X", "show me what the settings page could look like".
|
|
548
|
-
- "model": a 3D model —
|
|
549
|
-
|
|
548
|
+
- "model": a 3D model — one page to turn it around in, downloaded as a
|
|
549
|
+
.glb; no code changed. "3D model", "mesh", "a chair model", "glTF", "OBJ".
|
|
550
550
|
- "deck": a presentation — one HTML slide deck; no code changed. "Slides",
|
|
551
551
|
"a deck", "a presentation", "a pitch".
|
|
552
552
|
- "research": a write-up — read the repo and the web; no code changed.
|
|
@@ -1048,7 +1048,7 @@ export const AGENT_CONTRACTS = Object.freeze({
|
|
|
1048
1048
|
});
|
|
1049
1049
|
export const AGENT_HANDS_BACK = Object.freeze({
|
|
1050
1050
|
design: 'a DESIGN card: it hands back a mockup',
|
|
1051
|
-
model: 'a 3D MODEL card: it hands back a
|
|
1051
|
+
model: 'a 3D MODEL card: it hands back a model to view and download as a .glb',
|
|
1052
1052
|
deck: 'a PRESENTATION card: it hands back an HTML slide deck',
|
|
1053
1053
|
research: 'a RESEARCH card: it hands back a write-up',
|
|
1054
1054
|
});
|
|
@@ -78,8 +78,8 @@ export function agentTurnSettlement({ turnId, job, kind, out, lastAnswer, usage,
|
|
|
78
78
|
*
|
|
79
79
|
* Its product is under `.flowviant/artifacts/`, and the kind's table
|
|
80
80
|
* (agentTaskKinds.mjs) says which file proves it: a `.html` mockup for
|
|
81
|
-
* design, a `.html` deck, a `.md` write-up for research, and
|
|
82
|
-
*
|
|
81
|
+
* design, a `.html` deck, a `.md` write-up for research, and a `.html`
|
|
82
|
+
* page for a 3D model (the model is built in it, 0.107.0). A turn that
|
|
83
83
|
* says "delivered" without having written one would land the agent in Review
|
|
84
84
|
* with nothing to look at and a summary describing a page that does not
|
|
85
85
|
* exist — so it settles `nothing` with the measured sentence, and the
|
|
@@ -108,19 +108,10 @@ export function agentTurnSettlement({ turnId, job, kind, out, lastAnswer, usage,
|
|
|
108
108
|
*/
|
|
109
109
|
if (res.outcome === 'delivered' && kind.artifact) {
|
|
110
110
|
const want = kind.artifact.match;
|
|
111
|
-
|
|
112
|
-
// page, not a model — a `.gltf`/`.glb`/`.obj` must stand beside it. A
|
|
113
|
-
// task turn delivers when it wrote EITHER half this turn and BOTH stand
|
|
114
|
-
// (a re-modelled mesh — a rewritten .gltf/.glb/.obj — need not rewrite
|
|
115
|
-
// its viewer; a texture or .mtl alone is neither half). The halves are
|
|
116
|
-
// not paired by folder (pinned in the test). With no companion this is
|
|
117
|
-
// exactly the one-file rule design, deck and research have.
|
|
118
|
-
const also = kind.artifact.companion;
|
|
119
|
-
const need = (l) => l.some((e) => want.test(e.name)) && (!also || l.some((e) => also.test(e.name)));
|
|
111
|
+
const has = (l) => l.some((e) => want.test(e.name));
|
|
120
112
|
const standing = scanArtifacts(wt);
|
|
121
|
-
const
|
|
122
|
-
const
|
|
123
|
-
const present = wrote || ((job.kind !== 'task' || job.redo === true) && need(standing));
|
|
113
|
+
const wrote = has(changedArtifacts(artifactsBefore, standing));
|
|
114
|
+
const present = wrote || ((job.kind !== 'task' || job.redo === true) && has(standing));
|
|
124
115
|
if (!present) {
|
|
125
116
|
return report({
|
|
126
117
|
turnId,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flowviant",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.107.0",
|
|
4
4
|
"description": "Run your own coding CLIs as build agents for Flowviant — Claude Code, Codex or Antigravity, on your own credentials. Holds your sessions, keeps a worktree per tab, and ships branches on your word.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|