@vgai/sdk 0.5.20 → 0.5.21
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/package.json +2 -2
- package/src/editor/transport.ts +42 -4
- package/src/play/transport.ts +23 -5
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@vgai/sdk",
|
|
3
3
|
"author": "Volter AI, Inc.",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
|
-
"version": "0.5.
|
|
5
|
+
"version": "0.5.21",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
33
|
-
"@vgai/engine": "0.5.
|
|
33
|
+
"@vgai/engine": "0.5.21",
|
|
34
34
|
"playwright": "^1.58.2",
|
|
35
35
|
"zod": "^4.3.6"
|
|
36
36
|
}
|
package/src/editor/transport.ts
CHANGED
|
@@ -179,6 +179,15 @@ export interface EditorSessionInfo {
|
|
|
179
179
|
pid: number | null;
|
|
180
180
|
/** Exact explicitly targeted editor origin/base URL, including protocol and host. */
|
|
181
181
|
url?: string;
|
|
182
|
+
/**
|
|
183
|
+
* Why this server cannot DESCRIBE the `project` it is serving — its
|
|
184
|
+
* manifest's own parse/validation failure, naming the failing key. `null`
|
|
185
|
+
* when the project reads fine, and `undefined` from a probe that did not ask
|
|
186
|
+
* (or a server too old to say). See {@link servedProjectPath}: a session in
|
|
187
|
+
* this state is still THIS project's session, and callers must report the
|
|
188
|
+
* reason rather than treat it as no session at all.
|
|
189
|
+
*/
|
|
190
|
+
manifestError?: string | null;
|
|
182
191
|
}
|
|
183
192
|
|
|
184
193
|
export interface EditorCommandResult {
|
|
@@ -414,6 +423,28 @@ function readRegisteredSessions(): RegistrySessionEntry[] {
|
|
|
414
423
|
}
|
|
415
424
|
}
|
|
416
425
|
|
|
426
|
+
/**
|
|
427
|
+
* WHICH PROJECT a `/__editor/project` body says its server is serving.
|
|
428
|
+
*
|
|
429
|
+
* `serving` is that server's own statement of "I AM serving this project, I
|
|
430
|
+
* just cannot describe it" (its manifest is unparseable or fails strict
|
|
431
|
+
* validation) — added to the route precisely because a bare `{ project: null }`
|
|
432
|
+
* is indistinguishable from "no project open". Reading only `project.path`
|
|
433
|
+
* collapses the two, and the cost is that every project-matched command loses
|
|
434
|
+
* a live session the moment a save breaks its manifest, reporting it as
|
|
435
|
+
* belonging to no project rather than as this project's degraded session.
|
|
436
|
+
*/
|
|
437
|
+
function servedProjectPath(body: unknown): { path: string | null; manifestError: string | null } {
|
|
438
|
+
const b = body as {
|
|
439
|
+
project?: { path?: string } | null;
|
|
440
|
+
serving?: { path?: string; error?: string } | null;
|
|
441
|
+
};
|
|
442
|
+
return {
|
|
443
|
+
path: b.project?.path ?? b.serving?.path ?? null,
|
|
444
|
+
manifestError: b.project ? null : (b.serving?.error ?? null),
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
|
|
417
448
|
async function fetchJson(url: string, timeoutMs: number): Promise<unknown | undefined> {
|
|
418
449
|
try {
|
|
419
450
|
const res = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });
|
|
@@ -463,9 +494,15 @@ export class HttpEditorTransport implements EditorTransport {
|
|
|
463
494
|
const base = editorUrl.replace(/\/+$/, '');
|
|
464
495
|
const body = await fetchJson(`${base}/__editor/project`, timeoutMs);
|
|
465
496
|
if (body === undefined) return undefined;
|
|
466
|
-
const
|
|
497
|
+
const served = servedProjectPath(body);
|
|
467
498
|
const port = url.port ? Number(url.port) : url.protocol === 'https:' ? 443 : 80;
|
|
468
|
-
return {
|
|
499
|
+
return {
|
|
500
|
+
port,
|
|
501
|
+
project: served.path,
|
|
502
|
+
pid: null,
|
|
503
|
+
url: base,
|
|
504
|
+
manifestError: served.manifestError,
|
|
505
|
+
};
|
|
469
506
|
}
|
|
470
507
|
|
|
471
508
|
async listSessions(timeoutMs: number): Promise<EditorSessionInfo[]> {
|
|
@@ -478,11 +515,12 @@ export class HttpEditorTransport implements EditorTransport {
|
|
|
478
515
|
perProbeTimeout,
|
|
479
516
|
);
|
|
480
517
|
if (body === undefined) return undefined;
|
|
481
|
-
const
|
|
518
|
+
const served = servedProjectPath(body);
|
|
482
519
|
const info: EditorSessionInfo = {
|
|
483
520
|
port: s.port,
|
|
484
|
-
project,
|
|
521
|
+
project: served.path,
|
|
485
522
|
pid: s.pid,
|
|
523
|
+
manifestError: served.manifestError,
|
|
486
524
|
};
|
|
487
525
|
return info;
|
|
488
526
|
}),
|
package/src/play/transport.ts
CHANGED
|
@@ -426,15 +426,33 @@ function readRegisteredSessions(): RegistrySessionEntry[] {
|
|
|
426
426
|
try {
|
|
427
427
|
const raw: unknown = JSON.parse(readFileSync(registryFile, 'utf8'));
|
|
428
428
|
return Array.isArray(raw)
|
|
429
|
-
? raw
|
|
430
|
-
.filter(isRegistrySessionEntry)
|
|
431
|
-
.filter((s) => pidAlive(s.pid))
|
|
429
|
+
? raw.filter(isRegistrySessionEntry).filter((s) => pidAlive(s.pid))
|
|
432
430
|
: [];
|
|
433
431
|
} catch {
|
|
434
432
|
return [];
|
|
435
433
|
}
|
|
436
434
|
}
|
|
437
435
|
|
|
436
|
+
/**
|
|
437
|
+
* WHICH PROJECT a `/__editor/project` body says its server is serving — the
|
|
438
|
+
* play lane's copy of `editor/transport.ts`'s `servedProjectPath` (deliberate
|
|
439
|
+
* light duplicate of the read half, same as `readRegisteredSessions` above).
|
|
440
|
+
*
|
|
441
|
+
* `serving` is that server's own statement of "I AM serving this project, I
|
|
442
|
+
* just cannot describe it" (its manifest is unparseable or fails strict
|
|
443
|
+
* validation) — added to the route precisely because a bare `{ project: null }`
|
|
444
|
+
* is indistinguishable from "no project open". Reading only `project.path`
|
|
445
|
+
* collapses the two, and the cost is that every project-matched command loses
|
|
446
|
+
* a live session the moment a save breaks its manifest.
|
|
447
|
+
*/
|
|
448
|
+
function servedProjectPath(body: unknown): string | null {
|
|
449
|
+
const b = body as {
|
|
450
|
+
project?: { path?: string } | null;
|
|
451
|
+
serving?: { path?: string } | null;
|
|
452
|
+
};
|
|
453
|
+
return b.project?.path ?? b.serving?.path ?? null;
|
|
454
|
+
}
|
|
455
|
+
|
|
438
456
|
async function fetchJson(url: string, timeoutMs: number): Promise<unknown | undefined> {
|
|
439
457
|
try {
|
|
440
458
|
const res = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });
|
|
@@ -548,7 +566,7 @@ export class HttpPlayTransport implements PlayTransport {
|
|
|
548
566
|
const base = editorUrl.replace(/\/+$/, '');
|
|
549
567
|
const body = await fetchJson(`${base}/__editor/project`, timeoutMs);
|
|
550
568
|
if (body === undefined) return undefined;
|
|
551
|
-
const project = (body
|
|
569
|
+
const project = servedProjectPath(body);
|
|
552
570
|
const port = url.port ? Number(url.port) : url.protocol === 'https:' ? 443 : 80;
|
|
553
571
|
return { port, project, pid: null, url: base };
|
|
554
572
|
}
|
|
@@ -563,7 +581,7 @@ export class HttpPlayTransport implements PlayTransport {
|
|
|
563
581
|
perProbeTimeout,
|
|
564
582
|
);
|
|
565
583
|
if (body === undefined) return undefined;
|
|
566
|
-
const project = (body
|
|
584
|
+
const project = servedProjectPath(body);
|
|
567
585
|
const info: PlaySessionInfo = {
|
|
568
586
|
port: s.port,
|
|
569
587
|
project,
|