@plosson/agentio 0.8.4 → 0.8.5
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 +1 -1
- package/src/commands/teleport.test.ts +37 -0
- package/src/commands/teleport.ts +29 -7
- package/src/server/favicon.ts +17 -0
- package/src/server/http.ts +11 -0
- package/src/server/setup-page.ts +2 -0
package/package.json
CHANGED
|
@@ -41,6 +41,12 @@ interface FakeRunnerOptions {
|
|
|
41
41
|
deployedApp?: SiteioApp | null;
|
|
42
42
|
/** Stdout returned by logsApp. Default: empty string. */
|
|
43
43
|
logsStdout?: string;
|
|
44
|
+
/**
|
|
45
|
+
* If set, the first call to `deploy` throws an Error with this message;
|
|
46
|
+
* subsequent calls succeed. Used to simulate siteio rejecting `-f` on
|
|
47
|
+
* an app that was originally created with `-g` (git mode).
|
|
48
|
+
*/
|
|
49
|
+
failDeployFirstWith?: string;
|
|
44
50
|
failOn?:
|
|
45
51
|
| 'isInstalled'
|
|
46
52
|
| 'isLoggedIn'
|
|
@@ -88,6 +94,14 @@ function makeFakeRunner(opts: FakeRunnerOptions = {}): {
|
|
|
88
94
|
async deploy(args) {
|
|
89
95
|
calls.push({ method: 'deploy', args });
|
|
90
96
|
if (shouldFail('deploy')) throw new Error('deploy failed');
|
|
97
|
+
if (opts.failDeployFirstWith != null) {
|
|
98
|
+
const deployCallCount = calls.filter(
|
|
99
|
+
(c) => c.method === 'deploy'
|
|
100
|
+
).length;
|
|
101
|
+
if (deployCallCount === 1) {
|
|
102
|
+
throw new Error(opts.failDeployFirstWith);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
91
105
|
},
|
|
92
106
|
async restartApp(name) {
|
|
93
107
|
calls.push({ method: 'restartApp', args: { name } });
|
|
@@ -447,6 +461,29 @@ describe('runTeleport — preflight failures', () => {
|
|
|
447
461
|
// already have their bearer.
|
|
448
462
|
expect(logs).not.toContain('To add to Claude Code:');
|
|
449
463
|
});
|
|
464
|
+
|
|
465
|
+
test('rebuild: deploy retries without -f if existing app was created in git mode', async () => {
|
|
466
|
+
const deps = makeDeps({
|
|
467
|
+
existingApp: { name: 'mcp', url: 'https://mcp.existing.com' },
|
|
468
|
+
failDeployFirstWith:
|
|
469
|
+
'siteio apps deploy mcp -f /tmp/Dockerfile failed (deploy mcp): exit 1\nx Cannot override Dockerfile: app was not created with -f',
|
|
470
|
+
});
|
|
471
|
+
const result = await runTeleport({ name: 'mcp' }, deps);
|
|
472
|
+
|
|
473
|
+
const deployCalls = deps.calls.filter((c) => c.method === 'deploy');
|
|
474
|
+
expect(deployCalls).toHaveLength(2);
|
|
475
|
+
// First attempt passed -f (inline Dockerfile)…
|
|
476
|
+
expect(
|
|
477
|
+
(deployCalls[0]!.args as { dockerfilePath?: string }).dockerfilePath
|
|
478
|
+
).toMatch(/Dockerfile$/);
|
|
479
|
+
// …second attempt omits -f so siteio uses its stored git settings.
|
|
480
|
+
expect(
|
|
481
|
+
(deployCalls[1]!.args as { dockerfilePath?: string }).dockerfilePath
|
|
482
|
+
).toBeUndefined();
|
|
483
|
+
|
|
484
|
+
expect(result.serverApiKey).toBe('');
|
|
485
|
+
expect(deps.logLines.join('\n')).toMatch(/not created with -f/i);
|
|
486
|
+
});
|
|
450
487
|
});
|
|
451
488
|
|
|
452
489
|
/* ------------------------------------------------------------------ */
|
package/src/commands/teleport.ts
CHANGED
|
@@ -753,13 +753,35 @@ export async function runTeleport(
|
|
|
753
753
|
? 'Rebuilding (this may take a minute — Docker is rebuilding your image)…'
|
|
754
754
|
: 'Deploying (this may take a minute — Docker is building your image)…'
|
|
755
755
|
);
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
756
|
+
try {
|
|
757
|
+
await deps.runner.deploy({
|
|
758
|
+
name: name,
|
|
759
|
+
// In git mode, there's no -f to re-pass on deploy — siteio uses
|
|
760
|
+
// the stored git settings from create.
|
|
761
|
+
...(tempPath ? { dockerfilePath: tempPath } : {}),
|
|
762
|
+
noCache: opts.noCache,
|
|
763
|
+
});
|
|
764
|
+
} catch (err) {
|
|
765
|
+
// The existing app may have been created in git mode (no -f). siteio
|
|
766
|
+
// refuses `deploy -f` in that case with a specific error — retry
|
|
767
|
+
// without -f so it falls back to the stored git settings.
|
|
768
|
+
if (
|
|
769
|
+
isRebuild &&
|
|
770
|
+
tempPath &&
|
|
771
|
+
err instanceof Error &&
|
|
772
|
+
/not created with -f/i.test(err.message)
|
|
773
|
+
) {
|
|
774
|
+
deps.log(
|
|
775
|
+
'Existing app was not created with -f — retrying deploy without inline Dockerfile (siteio will rebuild from its stored git settings).'
|
|
776
|
+
);
|
|
777
|
+
await deps.runner.deploy({
|
|
778
|
+
name: name,
|
|
779
|
+
noCache: opts.noCache,
|
|
780
|
+
});
|
|
781
|
+
} else {
|
|
782
|
+
throw err;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
763
785
|
|
|
764
786
|
// Try to surface the deployed URL. Non-fatal if siteio doesn't
|
|
765
787
|
// give us one back.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedded favicon served at `/favicon.ico` and `/favicon.png`. Keeps MCP
|
|
3
|
+
* clients (e.g. Claude's connector UI) from falling back to the generic
|
|
4
|
+
* globe icon. Bytes are inlined so every build target — dev, `bun build
|
|
5
|
+
* --target node`, and `bun build --compile` — ships it without filesystem
|
|
6
|
+
* lookups.
|
|
7
|
+
*
|
|
8
|
+
* Source: `site/logo.png` (120x120 PNG).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const FAVICON_BASE64 =
|
|
12
|
+
'iVBORw0KGgoAAAANSUhEUgAAAHgAAAB4EAIAAADmln3GAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAGYktHRP///////wlY99wAAAAHdElNRQfqAQMQAyhWYExTAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDI2LTAxLTAzVDE2OjAzOjM5KzAwOjAwTY3PQAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyNi0wMS0wM1QxNjowMzozOSswMDowMDzQd/wAAAAodEVYdGRhdGU6dGltZXN0YW1wADIwMjYtMDEtMDNUMTY6MDM6MzkrMDA6MDBrxVYjAAAMjklEQVR42u3dd1QU1x4H8Dtll04EREBFEBSVIiWCFAUBsccSTYyFGKOIPp9HeXmWYIklqKioiSHRaKIGsSTHEiNRH6iRpgRDsUSKiGIE9IkNZZfdnZn3x7z3Ts5LZnbdyt73+/zlcX87d+71e2an3DsScXFpaS9eIACwQJp6BwDQJwg0wAoEGmAFAg2wAoEGWIFAA6xAoAFWINAAKxBogBUINMAKBBpgBQINsAKBBliBQAOsQKABViDQACsQaIAVCDTACgQaYAUCDbACgQZYgUADrECgAVYg0AArEGiAFQg0wAoEGmAFAg2wAoEGWIFAA6xAoAFWINAAKxBogBUINMAKBBpgBQINsAKBBliBQAOsQKABViDQACsQaIAVCDTACgQaYAUCDbACgQZYgUADrECgAVYg0AArEGiAFQg0wAoEGmAFAg2w8i9H6natiosOZAAAAABJRU5ErkJggg==';
|
|
13
|
+
|
|
14
|
+
export const FAVICON_BYTES = Uint8Array.from(
|
|
15
|
+
Buffer.from(FAVICON_BASE64, 'base64')
|
|
16
|
+
);
|
|
17
|
+
export const FAVICON_CONTENT_TYPE = 'image/png';
|
package/src/server/http.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { handleMcpRequest } from './mcp-http';
|
|
|
2
2
|
import type { OAuthStore } from './oauth-store';
|
|
3
3
|
import { requireBearer, routeOAuth } from './oauth';
|
|
4
4
|
import { routeSetup } from './setup-page';
|
|
5
|
+
import { FAVICON_BYTES, FAVICON_CONTENT_TYPE } from './favicon';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Context passed to every fetch handler invocation. Built once at boot in
|
|
@@ -36,6 +37,16 @@ export async function handleRequest(
|
|
|
36
37
|
return jsonResponse({ ok: true });
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
if (url.pathname === '/favicon.ico' || url.pathname === '/favicon.png') {
|
|
41
|
+
return new Response(FAVICON_BYTES, {
|
|
42
|
+
status: 200,
|
|
43
|
+
headers: {
|
|
44
|
+
'content-type': FAVICON_CONTENT_TYPE,
|
|
45
|
+
'cache-control': 'public, max-age=86400',
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
39
50
|
// Root setup page — operator-facing UI (API-key gated) for picking
|
|
40
51
|
// profiles and generating the MCP URL.
|
|
41
52
|
const setupResponse = await routeSetup(req, ctx);
|
package/src/server/setup-page.ts
CHANGED
|
@@ -188,6 +188,7 @@ function loginFormHtml(errorMessage?: string): string {
|
|
|
188
188
|
<html lang="en">
|
|
189
189
|
<head>
|
|
190
190
|
<meta charset="utf-8">
|
|
191
|
+
<link rel="icon" type="image/png" href="/favicon.png">
|
|
191
192
|
<title>agentio MCP setup</title>
|
|
192
193
|
<style>${BASE_CSS}</style>
|
|
193
194
|
</head>
|
|
@@ -307,6 +308,7 @@ ${sectionsHtml}
|
|
|
307
308
|
<html lang="en">
|
|
308
309
|
<head>
|
|
309
310
|
<meta charset="utf-8">
|
|
311
|
+
<link rel="icon" type="image/png" href="/favicon.png">
|
|
310
312
|
<title>agentio MCP setup</title>
|
|
311
313
|
<style>${BASE_CSS}${PROFILES_CSS}</style>
|
|
312
314
|
</head>
|