@shipvo/sim 0.1.0 → 0.1.2
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 +8 -3
- package/server.mjs +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shipvo/sim",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"description": "The Shipvo simulator: runs a Shipvo app's web build in a phone-sized headless browser and exposes it to agents (accessibility tree, tap/type/scroll, simulated device, mock backend). Used by @shipvo/mcp and `shipvo sim`.",
|
|
@@ -20,10 +20,15 @@
|
|
|
20
20
|
},
|
|
21
21
|
"keywords": [
|
|
22
22
|
"shipvo",
|
|
23
|
-
"
|
|
23
|
+
"react-native",
|
|
24
24
|
"react-native-web",
|
|
25
|
+
"mobile-simulator",
|
|
26
|
+
"headless",
|
|
25
27
|
"playwright",
|
|
26
|
-
"
|
|
28
|
+
"mcp",
|
|
29
|
+
"ai-agents",
|
|
30
|
+
"mobile-testing",
|
|
31
|
+
"e2e-testing"
|
|
27
32
|
],
|
|
28
33
|
"homepage": "https://github.com/shipvo/shipvo#readme",
|
|
29
34
|
"repository": {
|
package/server.mjs
CHANGED
|
@@ -25,7 +25,7 @@ let CFG = {}; try { CFG = JSON.parse(readFileSync(join(process.cwd(), "shipvo.js
|
|
|
25
25
|
const PORT = Number(arg("port", 4545)), DIR = arg("dir", "/tmp/pn-ui"), DIST = arg("dist", join(process.cwd(), "sim-dist"));
|
|
26
26
|
const DEFAULT_APP = arg("app", CFG.appId || "tide"), APP_NAME = CFG.name || "Tide & Tackle";
|
|
27
27
|
// Published releases: open_app("tide@r13") loads the web artifact that `shipvo publish` stored next to the phone bundle.
|
|
28
|
-
const CONTROL = (process.env.PN_CONTROL || process.env.CONTENT_FROM || CFG.controlPlane || "https://
|
|
28
|
+
const CONTROL = (process.env.PN_CONTROL || process.env.CONTENT_FROM || CFG.controlPlane || "https://api.shipvo.dev").replace(/\/$/, "");
|
|
29
29
|
async function resolveApp(spec) {
|
|
30
30
|
const m = /^([a-z0-9-]+)(?:@(?:r?(\d+)|(latest)))?$/.exec(String(spec || DEFAULT_APP)); if (!m) throw new Error(`bad app spec "${spec}": use "${DEFAULT_APP}", "${DEFAULT_APP}@r13" or "${DEFAULT_APP}@latest"`);
|
|
31
31
|
const [, app, rel] = m;
|
|
@@ -53,7 +53,7 @@ async function newSession(id, opts = {}) {
|
|
|
53
53
|
const page = await ctx.newPage();
|
|
54
54
|
await page.goto(target.url, { waitUntil: "networkidle" });
|
|
55
55
|
await page.waitForTimeout(300);
|
|
56
|
-
sessions.set(id, { ctx, page, app: target.app, release: target.release });
|
|
56
|
+
sessions.set(id, { ctx, page, app: target.app, release: target.release, startedAt: new Date().toISOString() });
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
async function screen(page) {
|
|
@@ -191,6 +191,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
191
191
|
// agent API
|
|
192
192
|
if (req.method !== "POST") return send(404, { error: "not found" });
|
|
193
193
|
let raw = ""; for await (const ch of req) raw += ch; const body = raw ? JSON.parse(raw) : {};
|
|
194
|
+
if (url.pathname === "/sessions") return send(200, { ok: true, sessions: [...sessions.entries()].map(([id, s]) => ({ session: id, app: s.app, release: s.release, started_at: s.startedAt ?? null, url: s.page.url() })) });
|
|
194
195
|
if (url.pathname === "/session") { await newSession(body.session, body); const s = sessions.get(body.session); log(body.session, "start", true, { app: s.app, release: s.release }); return send(200, { ok: true, app: s.app, release: s.release, screen: await screen(s.page) }); }
|
|
195
196
|
if (url.pathname === "/act") {
|
|
196
197
|
try { const r = await act(body.session, body); log(body.session, body.action, true, body.ref ? { ref: body.ref } : {}); return send(200, { ok: true, ...r }); }
|