@volter/world 3.0.165 → 3.0.166
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/dist/examples/customer-onboarding/README.md +1 -1
- package/dist/examples/customer-onboarding/package.json +1 -1
- package/dist/examples/integration-branches/README.md +4 -4
- package/dist/examples/integration-branches/package.json +1 -1
- package/dist/examples/workplace-agent/README.md +1 -1
- package/dist/examples/workplace-agent/package.json +1 -1
- package/dist/src/mcp.js +14 -6
- package/examples/customer-onboarding/README.md +1 -1
- package/examples/customer-onboarding/package.json +1 -1
- package/examples/integration-branches/README.md +4 -4
- package/examples/integration-branches/package.json +1 -1
- package/examples/workplace-agent/README.md +1 -1
- package/examples/workplace-agent/package.json +1 -1
- package/package.json +1 -1
- package/src/mcp.ts +15 -6
|
@@ -13,7 +13,7 @@ You need Node 22.6+, npm and registry access during installation. The browser pa
|
|
|
13
13
|
Copy this starter into a new folder:
|
|
14
14
|
|
|
15
15
|
```console
|
|
16
|
-
$ npx @volter/world@3.0.
|
|
16
|
+
$ npx @volter/world@3.0.166 example customer-onboarding --dir onboarding
|
|
17
17
|
$ cd onboarding
|
|
18
18
|
$ npm install
|
|
19
19
|
```
|
|
@@ -13,7 +13,7 @@ Give two workers the same Stripe baseline, let them change different existing cu
|
|
|
13
13
|
Use an empty parent folder. Create the baseline starter there:
|
|
14
14
|
|
|
15
15
|
```console
|
|
16
|
-
$ npx @volter/world@3.0.
|
|
16
|
+
$ npx @volter/world@3.0.166 example integration-branches --dir baseline
|
|
17
17
|
$ cd baseline
|
|
18
18
|
$ npm install
|
|
19
19
|
$ ./node_modules/.bin/volter world init --name baseline --twins stripe
|
|
@@ -38,9 +38,9 @@ The stopped baseline retains its history and can supply local path remotes. Defa
|
|
|
38
38
|
Create three more copies in the same parent folder:
|
|
39
39
|
|
|
40
40
|
```console
|
|
41
|
-
$ npx @volter/world@3.0.
|
|
42
|
-
$ npx @volter/world@3.0.
|
|
43
|
-
$ npx @volter/world@3.0.
|
|
41
|
+
$ npx @volter/world@3.0.166 example integration-branches --dir integration
|
|
42
|
+
$ npx @volter/world@3.0.166 example integration-branches --dir worker-a
|
|
43
|
+
$ npx @volter/world@3.0.166 example integration-branches --dir worker-b
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
In `integration`, then `worker-a`, then `worker-b`, install dependencies and initialize with the folder's name. Before a first boot or app write, link and pull the baseline:
|
|
@@ -19,7 +19,7 @@ A catalog page may select a newer default. Keep this example's manifest and inst
|
|
|
19
19
|
together; its recorded workflow does not establish behavior for a different release.
|
|
20
20
|
|
|
21
21
|
```console
|
|
22
|
-
$ npx @volter/world@3.0.
|
|
22
|
+
$ npx @volter/world@3.0.166 example workplace-agent --dir workplace
|
|
23
23
|
$ cd workplace
|
|
24
24
|
$ npm install
|
|
25
25
|
$ ./node_modules/.bin/volter world init --name workplace --twins github,linear,slack
|
package/dist/src/mcp.js
CHANGED
|
@@ -29,9 +29,9 @@ function volter(args, dir, timeoutSeconds = 600) {
|
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
31
|
/** A command that keeps running (the World's view, a sign-in waiting for approval): started once, answered as soon as
|
|
32
|
-
* its
|
|
32
|
+
* its announcement says what the agent needs, left running for as long as this server runs. */
|
|
33
33
|
const background = new Map();
|
|
34
|
-
function startBackground(key, args, dir, ready, seconds = 60) {
|
|
34
|
+
function startBackground(key, args, dir, ready, seconds = 60, incompleteCode = 0) {
|
|
35
35
|
background.get(key)?.kill();
|
|
36
36
|
background.delete(key);
|
|
37
37
|
return new Promise((done) => {
|
|
@@ -44,15 +44,23 @@ function startBackground(key, args, dir, ready, seconds = 60) {
|
|
|
44
44
|
clearTimeout(timer);
|
|
45
45
|
done({ code, output });
|
|
46
46
|
} };
|
|
47
|
-
const take = (d) => { output += d.toString(); if (ready.test(output))
|
|
47
|
+
const take = (d) => { output += d.toString(); if (typeof ready === 'function' ? ready(output) : ready.test(output))
|
|
48
48
|
answer(0); };
|
|
49
49
|
child.stdout.on('data', take);
|
|
50
50
|
child.stderr.on('data', take);
|
|
51
51
|
child.on('error', (e) => { output += e.message; answer(1); });
|
|
52
|
-
child.on('close', (code) => { background.delete(key); answer(code ?? 1); });
|
|
53
|
-
const timer = setTimeout(() => answer(
|
|
52
|
+
child.on('close', (code) => { background.delete(key); answer(code === 0 ? incompleteCode : code ?? 1); });
|
|
53
|
+
const timer = setTimeout(() => answer(incompleteCode), seconds * 1000);
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
|
+
/** cli.ts finishes the access announcement after the runtime's initial viewing/console lines. */
|
|
57
|
+
function viewAnnouncementComplete(output) {
|
|
58
|
+
if (/(?:^|\n)apps[ \t]+/.test(output)) {
|
|
59
|
+
// The local-origin announcement ends with its browser guidance, after any missing-console notice.
|
|
60
|
+
return /(?:^|\n)\(the World opens at its own \*\.localhost origin;[^\r\n]*\)\r?\n/.test(output);
|
|
61
|
+
}
|
|
62
|
+
return /(?:^|\n)(?:read-only view[ \t]+\S+|\(no console installed:[^\r\n]*\))\r?\n/.test(output);
|
|
63
|
+
}
|
|
56
64
|
/** Everything this server left running, ended: a World under a dashboard is brought down through its own command first
|
|
57
65
|
* (its state kept, its teardown recorded), then the command itself. */
|
|
58
66
|
function stopAll() {
|
|
@@ -126,7 +134,7 @@ export async function serveMcp(version) {
|
|
|
126
134
|
catch (e) {
|
|
127
135
|
return fail(e);
|
|
128
136
|
}
|
|
129
|
-
const r = await startBackground(`view:${root}`, ['world', 'view', '--no-open'], root,
|
|
137
|
+
const r = await startBackground(`view:${root}`, ['world', 'view', '--no-open'], root, viewAnnouncementComplete, 60, 1);
|
|
130
138
|
return text(`${before}${r.output}`, r.code !== 0);
|
|
131
139
|
});
|
|
132
140
|
server.registerTool('world_log', {
|
|
@@ -13,7 +13,7 @@ You need Node 22.6+, npm and registry access during installation. The browser pa
|
|
|
13
13
|
Copy this starter into a new folder:
|
|
14
14
|
|
|
15
15
|
```console
|
|
16
|
-
$ npx @volter/world@3.0.
|
|
16
|
+
$ npx @volter/world@3.0.166 example customer-onboarding --dir onboarding
|
|
17
17
|
$ cd onboarding
|
|
18
18
|
$ npm install
|
|
19
19
|
```
|
|
@@ -13,7 +13,7 @@ Give two workers the same Stripe baseline, let them change different existing cu
|
|
|
13
13
|
Use an empty parent folder. Create the baseline starter there:
|
|
14
14
|
|
|
15
15
|
```console
|
|
16
|
-
$ npx @volter/world@3.0.
|
|
16
|
+
$ npx @volter/world@3.0.166 example integration-branches --dir baseline
|
|
17
17
|
$ cd baseline
|
|
18
18
|
$ npm install
|
|
19
19
|
$ ./node_modules/.bin/volter world init --name baseline --twins stripe
|
|
@@ -38,9 +38,9 @@ The stopped baseline retains its history and can supply local path remotes. Defa
|
|
|
38
38
|
Create three more copies in the same parent folder:
|
|
39
39
|
|
|
40
40
|
```console
|
|
41
|
-
$ npx @volter/world@3.0.
|
|
42
|
-
$ npx @volter/world@3.0.
|
|
43
|
-
$ npx @volter/world@3.0.
|
|
41
|
+
$ npx @volter/world@3.0.166 example integration-branches --dir integration
|
|
42
|
+
$ npx @volter/world@3.0.166 example integration-branches --dir worker-a
|
|
43
|
+
$ npx @volter/world@3.0.166 example integration-branches --dir worker-b
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
In `integration`, then `worker-a`, then `worker-b`, install dependencies and initialize with the folder's name. Before a first boot or app write, link and pull the baseline:
|
|
@@ -19,7 +19,7 @@ A catalog page may select a newer default. Keep this example's manifest and inst
|
|
|
19
19
|
together; its recorded workflow does not establish behavior for a different release.
|
|
20
20
|
|
|
21
21
|
```console
|
|
22
|
-
$ npx @volter/world@3.0.
|
|
22
|
+
$ npx @volter/world@3.0.166 example workplace-agent --dir workplace
|
|
23
23
|
$ cd workplace
|
|
24
24
|
$ npm install
|
|
25
25
|
$ ./node_modules/.bin/volter world init --name workplace --twins github,linear,slack
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/world",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.166",
|
|
4
4
|
"description": "Run your app against a world of twins. `World` and `Repo` — one method per verb: init, up, run, log, diff, reset, branch, checkout, clone, fetch, changeset, push — and the `volter` command, one client of them.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"volter",
|
package/src/mcp.ts
CHANGED
|
@@ -31,22 +31,31 @@ function volter(args: string[], dir: string, timeoutSeconds = 600): Promise<Ran>
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/** A command that keeps running (the World's view, a sign-in waiting for approval): started once, answered as soon as
|
|
34
|
-
* its
|
|
34
|
+
* its announcement says what the agent needs, left running for as long as this server runs. */
|
|
35
35
|
const background = new Map<string, ChildProcess>();
|
|
36
|
-
function startBackground(key: string, args: string[], dir: string, ready: RegExp, seconds = 60): Promise<Ran> {
|
|
36
|
+
function startBackground(key: string, args: string[], dir: string, ready: RegExp | ((output: string) => boolean), seconds = 60, incompleteCode = 0): Promise<Ran> {
|
|
37
37
|
background.get(key)?.kill(); background.delete(key);
|
|
38
38
|
return new Promise((done) => {
|
|
39
39
|
const child = spawn(process.execPath, [CLI, ...args], { cwd: dir, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'], env: process.env });
|
|
40
40
|
background.set(key, child);
|
|
41
41
|
let output = ''; let answered = false;
|
|
42
42
|
const answer = (code: number): void => { if (!answered) { answered = true; clearTimeout(timer); done({ code, output }); } };
|
|
43
|
-
const take = (d: Buffer): void => { output += d.toString(); if (ready.test(output)) answer(0); };
|
|
43
|
+
const take = (d: Buffer): void => { output += d.toString(); if (typeof ready === 'function' ? ready(output) : ready.test(output)) answer(0); };
|
|
44
44
|
child.stdout!.on('data', take); child.stderr!.on('data', take);
|
|
45
45
|
child.on('error', (e) => { output += e.message; answer(1); });
|
|
46
|
-
child.on('close', (code) => { background.delete(key); answer(code ?? 1); });
|
|
47
|
-
const timer = setTimeout(() => answer(
|
|
46
|
+
child.on('close', (code) => { background.delete(key); answer(code === 0 ? incompleteCode : code ?? 1); });
|
|
47
|
+
const timer = setTimeout(() => answer(incompleteCode), seconds * 1000);
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
|
+
|
|
51
|
+
/** cli.ts finishes the access announcement after the runtime's initial viewing/console lines. */
|
|
52
|
+
function viewAnnouncementComplete(output: string): boolean {
|
|
53
|
+
if (/(?:^|\n)apps[ \t]+/.test(output)) {
|
|
54
|
+
// The local-origin announcement ends with its browser guidance, after any missing-console notice.
|
|
55
|
+
return /(?:^|\n)\(the World opens at its own \*\.localhost origin;[^\r\n]*\)\r?\n/.test(output);
|
|
56
|
+
}
|
|
57
|
+
return /(?:^|\n)(?:read-only view[ \t]+\S+|\(no console installed:[^\r\n]*\))\r?\n/.test(output);
|
|
58
|
+
}
|
|
50
59
|
/** Everything this server left running, ended: a World under a dashboard is brought down through its own command first
|
|
51
60
|
* (its state kept, its teardown recorded), then the command itself. */
|
|
52
61
|
function stopAll(): void {
|
|
@@ -111,7 +120,7 @@ export async function serveMcp(version: string): Promise<void> {
|
|
|
111
120
|
const root = here(dir);
|
|
112
121
|
let before = '';
|
|
113
122
|
try { const s = World.open({ root }).status(); if (s.running && !s.served) { const down = await volter(['world', 'down'], root); if (down.code !== 0) return ran(down); before = `${down.output.trim()} (state kept; the dashboard runs it now)\n`; } } catch (e) { return fail(e); }
|
|
114
|
-
const r = await startBackground(`view:${root}`, ['world', 'view', '--no-open'], root,
|
|
123
|
+
const r = await startBackground(`view:${root}`, ['world', 'view', '--no-open'], root, viewAnnouncementComplete, 60, 1);
|
|
115
124
|
return text(`${before}${r.output}`, r.code !== 0);
|
|
116
125
|
});
|
|
117
126
|
|