@tempo-ai/mcp 0.0.102 → 0.0.103
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/bin.js +1 -1
- package/dist/{call-TNF2AXMX.js → call-XYOJSSYR.js} +2 -2
- package/dist/{chunk-6P4PI7CS.js → chunk-C3J4LFJI.js} +4 -4
- package/dist/index.js +1 -1
- package/dist/{serve-NGUFKD5I.js → serve-P7M4UFJS.js} +147 -68
- package/dist/serve-P7M4UFJS.js.map +1 -0
- package/package.json +1 -1
- package/dist/serve-NGUFKD5I.js.map +0 -1
- /package/dist/{call-TNF2AXMX.js.map → call-XYOJSSYR.js.map} +0 -0
- /package/dist/{chunk-6P4PI7CS.js.map → chunk-C3J4LFJI.js.map} +0 -0
package/dist/bin.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
9
9
|
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
10
10
|
async function connectAggregate(options) {
|
|
11
|
-
const { createTempoAggregate } = await import("./serve-
|
|
11
|
+
const { createTempoAggregate } = await import("./serve-P7M4UFJS.js");
|
|
12
12
|
const handle = await createTempoAggregate(options);
|
|
13
13
|
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
14
14
|
const client = new Client({ name: "tempo-mcp-cli", version: "0" });
|
|
@@ -127,4 +127,4 @@ export {
|
|
|
127
127
|
runCall,
|
|
128
128
|
runTools
|
|
129
129
|
};
|
|
130
|
-
//# sourceMappingURL=call-
|
|
130
|
+
//# sourceMappingURL=call-XYOJSSYR.js.map
|
|
@@ -157,7 +157,7 @@ async function run(argv) {
|
|
|
157
157
|
process.stderr.write(USAGE);
|
|
158
158
|
return 1;
|
|
159
159
|
}
|
|
160
|
-
const { runServe } = await import("./serve-
|
|
160
|
+
const { runServe } = await import("./serve-P7M4UFJS.js");
|
|
161
161
|
return await runServe(options);
|
|
162
162
|
}
|
|
163
163
|
switch (subcommand) {
|
|
@@ -172,11 +172,11 @@ async function run(argv) {
|
|
|
172
172
|
return await runToken(rest);
|
|
173
173
|
}
|
|
174
174
|
case "tools": {
|
|
175
|
-
const { runTools } = await import("./call-
|
|
175
|
+
const { runTools } = await import("./call-XYOJSSYR.js");
|
|
176
176
|
return await runTools(rest);
|
|
177
177
|
}
|
|
178
178
|
case "call": {
|
|
179
|
-
const { runCall } = await import("./call-
|
|
179
|
+
const { runCall } = await import("./call-XYOJSSYR.js");
|
|
180
180
|
return await runCall(rest);
|
|
181
181
|
}
|
|
182
182
|
default:
|
|
@@ -195,4 +195,4 @@ async function run(argv) {
|
|
|
195
195
|
export {
|
|
196
196
|
run
|
|
197
197
|
};
|
|
198
|
-
//# sourceMappingURL=chunk-
|
|
198
|
+
//# sourceMappingURL=chunk-C3J4LFJI.js.map
|
package/dist/index.js
CHANGED
|
@@ -15520,11 +15520,11 @@ scaffolded project.
|
|
|
15520
15520
|
| \`scripts.start\` | string | Canvas-host launcher (runs from the tempo root). Prefer a foreground process. Tempo substitutes every literal \`\${PORT}\`, exports the same port as \`TEMPO_PORT\`, and sets \`TEMPO=true\`. |
|
|
15521
15521
|
| \`scripts.stop\` | string? | Matching teardown for a daemonized/external host. Tempo substitutes \`\${PORT}\` and runs this before signalling the launcher group. Required when \`scripts.start\` exits successfully while the host continues in the background. |
|
|
15522
15522
|
| \`urls.tempoHost\` | URL string? | Public \`/tempo-host\` URL to probe when stdout cannot describe the reachable boundary (containers, tunnels, remotes). May contain \`\${PORT}\`; e.g. \`http://127.0.0.1:\${PORT}/tempo-host\`. |
|
|
15523
|
-
| \`apps\` | array? | \`[{ "appDir"?, "
|
|
15523
|
+
| \`apps\` | array? | \`[{ "appDir"?, "start"?, "url"? }]\` \u2014 one entry per client app; only \`apps[0]\` is active today. \`start\` launches the user's REAL app for route storyboards and may be any foreground command; \`url\` optionally supplies the independent HTTP(S) readiness target and route base. \`\${APP_PORT}\` is an optional allocated-port helper and legacy \`\${PORT}\` remains supported. Legacy \`apps[].appStart\`, \`scripts.appStart\`, and top-level \`appDir\` still read and auto-migrate. |
|
|
15524
15524
|
|
|
15525
15525
|
**Every command in this file runs through the platform shell \u2014 \`cmd.exe\` on
|
|
15526
15526
|
Windows, not PowerShell.** That applies to \`scripts.install\` and
|
|
15527
|
-
\`scripts.start\` exactly as it does to \`
|
|
15527
|
+
\`scripts.start\` exactly as it does to app \`start\`. Write plain, cross-platform
|
|
15528
15528
|
invocations; \`&&\` and \`cd\` are fine (cmd supports both). Never use PowerShell
|
|
15529
15529
|
syntax \u2014 \`if (Test-Path \u2026) { \u2026 } else { \u2026 }\`, \`Test-Path\`, \`$env:FOO\` \u2014 because
|
|
15530
15530
|
cmd.exe cannot parse it and aborts with "X was unexpected at this time" BEFORE
|
|
@@ -15565,8 +15565,10 @@ For Svelte 5, setup is complete only when all applicable items below hold:
|
|
|
15565
15565
|
\`tempo/vite.config.ts\`\u2014includes \`tempoVitePlugin()\` and its active Svelte
|
|
15566
15566
|
preprocessing chain starts with \`tempoSveltePreprocess(...)\`. Preserve all
|
|
15567
15567
|
existing preprocessors after Tempo's preprocessor.
|
|
15568
|
-
4. Route storyboards additionally have an \`apps[0].
|
|
15569
|
-
the
|
|
15568
|
+
4. Route storyboards additionally have an \`apps[0].start\` command and should
|
|
15569
|
+
set \`apps[0].url\` when the HTTP(S) liveness target is known. The command
|
|
15570
|
+
may use the optional \`\${APP_PORT}\` helper (legacy \`\${PORT}\` also
|
|
15571
|
+
works). Configure both with \`set_app_dev_command\`.
|
|
15570
15572
|
|
|
15571
15573
|
The official Svelte Vite plugin compiles \`.svelte\` modules; Tempo's Vite
|
|
15572
15574
|
plugin injects the projection runtime; and Tempo's Svelte preprocessor records
|
|
@@ -15918,7 +15920,7 @@ export default function AuthComponentsCanvas() {
|
|
|
15918
15920
|
|
|
15919
15921
|
Canvases created before the React format use object exports instead of JSX \u2014 \`export const Login: TempoStoryboard = { render: () => <LoginForm />, layout: {\u2026} }\` with a \`TempoCanvasConfig\` default export. Tempo migrates these to the React format automatically when they are opened in the Design tab. If you encounter one, run \`canvas_migrate_to_latest\` on it BEFORE making any edit \u2014 never hand-write legacy declarations, and never mix the two formats in one file.
|
|
15920
15922
|
|
|
15921
|
-
### Route Storyboards & the app dev
|
|
15923
|
+
### Route Storyboards & the app dev config (\`apps[0].start\` / \`url\`)
|
|
15922
15924
|
|
|
15923
15925
|
Route storyboards (\`<RouteStoryboard>\`) load **the user's real app** in the iframe, NOT the canvas sidecar. They need a second supervised process \u2014 the user's actual app dev server \u2014 which Tempo manages from the app dev command in \`tempo.config.json\`, stored canonically on the \`apps[]\` list (one entry per client app; only \`apps[0]\` is active today):
|
|
15924
15926
|
|
|
@@ -15931,13 +15933,14 @@ Route storyboards (\`<RouteStoryboard>\`) load **the user's real app** in the if
|
|
|
15931
15933
|
"apps": [
|
|
15932
15934
|
{
|
|
15933
15935
|
"appDir": "client", // app package dir, relative to repo root (omit for autodetect)
|
|
15934
|
-
"
|
|
15936
|
+
"start": "npm exec vite --port=\${APP_PORT}", // arbitrary foreground command
|
|
15937
|
+
"url": "http://127.0.0.1:\${APP_PORT}" // optional HTTP(S) liveness target
|
|
15935
15938
|
}
|
|
15936
15939
|
]
|
|
15937
15940
|
}
|
|
15938
15941
|
\`\`\`
|
|
15939
15942
|
|
|
15940
|
-
(Files written by older Tempo versions may still carry
|
|
15943
|
+
(Files written by older Tempo versions may still carry \`apps[].appStart\`, \`scripts.appStart\`, or top-level \`appDir\`. They read normally and migrate to canonical \`apps[].start\` on the next config write.)
|
|
15941
15944
|
|
|
15942
15945
|
**The app's own bundler config MUST include the Tempo annotation plugin.** Route storyboards are served by the user's app dev server (NOT the \`tempo/\` sidecar), so the canvas can only select/edit their elements if THAT server injects the \`data-tempo-*\` annotations \u2014 i.e. the **app's own** framework config carries the Tempo plugin, active under \`TEMPO=true\`. Without it the app still renders in the iframe, but every click collapses to one unmappable root and the user reports *"route storyboard elements are not clickable."* This is separate from the \`tempo/\` sidecar's plugin (\xA74.2) \u2014 both configs need it, for different servers. Add the plugin to the app package (and add \`tempo-sdk\` to the app's deps) per framework:
|
|
15943
15946
|
|
|
@@ -15990,13 +15993,13 @@ Route storyboards (\`<RouteStoryboard>\`) load **the user's real app** in the if
|
|
|
15990
15993
|
};
|
|
15991
15994
|
\`\`\`
|
|
15992
15995
|
|
|
15993
|
-
The plugin no-ops unless \`TEMPO=true\` (which the supervisor sets when it runs \`
|
|
15996
|
+
The plugin no-ops unless \`TEMPO=true\` (which the supervisor sets when it runs app \`start\`), so it is safe to keep in the config permanently.
|
|
15994
15997
|
|
|
15995
15998
|
Mechanics:
|
|
15996
15999
|
|
|
15997
|
-
- The supervisor allocates a free TCP port per workspace
|
|
15998
|
-
-
|
|
15999
|
-
-
|
|
16000
|
+
- The supervisor always allocates a free local TCP port per workspace and persists it at \`<workspaceRoot>/.tempo/app-devserver.json\` (gitignored, per-worktree).
|
|
16001
|
+
- A \`url\` containing \`\${APP_PORT}\` (or legacy \`\${PORT}\`) uses that allocated helper value. A literal URL is an opaque HTTP(S) readiness target and route base: its hostname and port never control local allocation, so it may point through a container, tunnel, or remote machine.
|
|
16002
|
+
- Every literal \`\${APP_PORT}\` or legacy \`\${PORT}\` in app \`start\` and \`url\` is substituted before spawn/probe. The renderer resolves route storyboard paths against the resulting URL.
|
|
16000
16003
|
- Lifecycle: warm with a 5-minute idle stop \u2014 the supervisor stays alive while a canvas with route storyboards is open and stops 5 minutes after the last canvas closes.
|
|
16001
16004
|
- While starting, an overlay reads "Starting your app dev server\u2026" on every route storyboard.
|
|
16002
16005
|
|
|
@@ -16006,16 +16009,29 @@ Mechanics:
|
|
|
16006
16009
|
|
|
16007
16010
|
| Framework | Command shape |
|
|
16008
16011
|
|-----------|---------------|
|
|
16009
|
-
| Vite | \`<pm> exec vite --port=\${
|
|
16010
|
-
| Next.js | \`<pm> exec next dev -p \${
|
|
16011
|
-
| Expo (web) | \`npx expo start --web --port \${
|
|
16012
|
-
| CRA / Remix / generic | \`PORT=\${
|
|
16012
|
+
| Vite | \`<pm> exec vite --port=\${APP_PORT} --strictPort\` (e.g. \`pnpm exec vite \u2026\`, \`npx vite \u2026\`) |
|
|
16013
|
+
| Next.js | \`<pm> exec next dev -p \${APP_PORT}\` |
|
|
16014
|
+
| Expo (web) | \`npx expo start --web --port \${APP_PORT}\` |
|
|
16015
|
+
| CRA / Remix / generic | \`PORT=\${APP_PORT} npm run dev\` |
|
|
16013
16016
|
|
|
16014
|
-
**
|
|
16017
|
+
**When using the allocated helper port, invoke the bundler binary directly \u2014 do NOT route the port flag through \`<pm> run dev -- --port=\${APP_PORT}\`.** When the \`dev\` script is a bare \`vite\` (the common case) and the project uses **pnpm**, that form can forward the literal \`--\` separator through to Vite, which treats it as a positional arg and ignores \`--port\`. The direct-exec form (\`pnpm exec vite \u2026\` / \`npx vite \u2026\`) is correct under every package manager. (\`--strictPort\` makes a mismatch fail loudly.)
|
|
16015
16018
|
|
|
16016
|
-
The command
|
|
16019
|
+
The command is otherwise arbitrary. The allocated helper token is optional, and a configured \`url\` is always the liveness target Tempo probes.
|
|
16017
16020
|
|
|
16018
|
-
**
|
|
16021
|
+
**Independent readiness URL.** Use a literal \`url\` whenever the URL Tempo can reach differs from the locally allocated port, including a container, tunnel, or remote machine:
|
|
16022
|
+
|
|
16023
|
+
\`\`\`json
|
|
16024
|
+
{
|
|
16025
|
+
"apps": [{
|
|
16026
|
+
"start": "npm run dev:remote",
|
|
16027
|
+
"url": "https://preview.example.com"
|
|
16028
|
+
}]
|
|
16029
|
+
}
|
|
16030
|
+
\`\`\`
|
|
16031
|
+
|
|
16032
|
+
The supervisor probes \`url\` directly rather than waiting for stdout URL discovery and uses it as the public route base after it responds. The local helper port remains independently allocated and available to \`start\` through \`APP_PORT\`, \`PORT\`, and \`TEMPO_APP_PORT\`, even when the literal URL spells a completely different host or explicit port.
|
|
16033
|
+
|
|
16034
|
+
**Keep the command plain and cross-platform \u2014 one invocation, no shell conditionals.** Tempo spawns it through the platform shell (**cmd.exe on Windows**, not PowerShell) and substitutes \`\${APP_PORT}\` (or legacy \`\${PORT}\`) before spawning. A leading \`NAME=value\` prefix \u2014 for example \`PORT=\${APP_PORT} npm run dev\` \u2014 is also safe on every OS: the supervisor lifts it into the spawn environment instead of handing it to the shell, and it always sets \`APP_PORT\`, \`PORT\`, and \`TEMPO_APP_PORT\` in the environment regardless. Never use PowerShell syntax \u2014 \`if (Test-Path \u2026) { \u2026 } else { \u2026 }\`, \`Test-Path\`, \`$env:FOO\`, \`Get-\`/\`Set-\` cmdlets \u2014 cmd.exe can't parse it and aborts before running anything. If the app lives in a subdirectory, set \`appDir\` instead of changing directories inside the command.
|
|
16019
16035
|
|
|
16020
16036
|
**Driving the lifecycle directly.** Three sibling tools mirror the canvas-sidecar trio: \`check_app_dev_server\` / \`start_app_dev_server\` / \`stop_app_dev_server\` (vs \`check_canvas_devserver\` / \`start_canvas_devserver\` / \`stop_canvas_devserver\`). \`check_app_dev_server\` returns \`{configured, running, phase, port, url, error}\` \u2014 call it first when a route storyboard isn't loading, to disambiguate: \`configured: false\` \u2192 \`set_app_dev_command\`; \`configured: true, running: false\` \u2192 read \`error\`, then \`start_app_dev_server\`; \`running: true\` \u2192 the route itself is the problem, not the supervisor. After editing the app dev command, \`stop_app_dev_server\` then \`start_app_dev_server\` to pick up the new command.
|
|
16021
16037
|
|
|
@@ -16023,9 +16039,9 @@ The command MUST contain the literal \`\${PORT}\` token. Without it the supervis
|
|
|
16023
16039
|
|
|
16024
16040
|
**Home canvas.** A project's home canvas (single \`route: "/"\` storyboard) backs the header Run (play) button and the turn-summary "Run app" card \u2014 both open it next to the app's dev-server output. When setting a project up for canvases or route storyboards, ensure one exists: \`canvas_project_init\` seeds it alongside the template canvas; if a \`route: "/"\` canvas already exists, mark it with \`canvas_set_home\` instead of duplicating; otherwise create one with \`canvas_create({ canvas_name: "Home", home: true, storyboards: [{ export_name: "Home", route: "/" }] })\`.
|
|
16025
16041
|
|
|
16026
|
-
Use the \`set_app_dev_command\` MCP tool to write this \u2014 don't hand-edit \`tempo.config.json\` for it. The tool validates the
|
|
16042
|
+
Use the \`set_app_dev_command\` MCP tool to write this \u2014 don't hand-edit \`tempo.config.json\` for it. The tool validates the fields and clears any cached supervisor so the next route storyboard load picks up the new config. \`create-canvas\` issues a soft-gate warning in its result when route storyboards are requested but app start is missing \u2014 confirm the command with the user, then call \`set_app_dev_command\`. When you set it, you should also check the app's bundler plugin + \`tempo-sdk\` dep are in place (above), unless you already did.
|
|
16027
16043
|
|
|
16028
|
-
Once set, \`
|
|
16044
|
+
Once set, app \`start\` also appears automatically in the workspace header's Run (play) button under **Org run scripts** as a read-only "App dev server" entry (the default unless the user picks another) \u2014 never add a run script duplicating it, and when the route-storyboard supervisor is already up, point the user at its URL instead of suggesting they also hit play. Other Run-button commands (build, test, \u2026) are DB-backed (org-shared + per-user, per project) \u2014 add them with \`configure_run_script\` (\`tempo-scripts-tools\` MCP), not in this file. The home canvas + app dev config stay in the repo, so once the app runs, suggest committing them so teammates get the app Run entry too.
|
|
16029
16045
|
|
|
16030
16046
|
### Import Resolution
|
|
16031
16047
|
|
|
@@ -23705,7 +23721,7 @@ function matchClass(line) {
|
|
|
23705
23721
|
if (isShellParseAbortOutput(line)) {
|
|
23706
23722
|
return {
|
|
23707
23723
|
class: "shell-dialect-mismatch",
|
|
23708
|
-
hint: "The dev command failed to PARSE in the shell (Tempo runs commands through cmd.exe on Windows) \u2014 nothing actually ran. This almost always means the command was written in PowerShell syntax, which cmd.exe cannot parse: `if (...) { ... } else { ... }`, `Test-Path`, `$env:FOO`. Rewrite it as a single, plain, cross-platform invocation with no shell conditionals \u2014 e.g. `npm exec
|
|
23724
|
+
hint: "The dev command failed to PARSE in the shell (Tempo runs commands through cmd.exe on Windows) \u2014 nothing actually ran. This almost always means the command was written in PowerShell syntax, which cmd.exe cannot parse: `if (...) { ... } else { ... }`, `Test-Path`, `$env:FOO`. Rewrite it as a single, plain, cross-platform invocation with no shell conditionals \u2014 e.g. `npm exec next dev -p ${APP_PORT}` or simply `npm run dev` when it does not need Tempo's optional allocated helper port (legacy `${PORT}` also works). Chaining with `&&` is fine; cmd supports it. If the app lives in a subdirectory, set `appDir` in tempo.config.json instead of `cd`/`pushd`-ing inside the command."
|
|
23709
23725
|
};
|
|
23710
23726
|
}
|
|
23711
23727
|
if (isDevServerLockConflictOutput(line)) {
|
|
@@ -24453,6 +24469,7 @@ var AppDevServer = class _AppDevServer {
|
|
|
24453
24469
|
this.hasParentDeathWatchdog = false;
|
|
24454
24470
|
this.options = {
|
|
24455
24471
|
command: options.command,
|
|
24472
|
+
url: options.url,
|
|
24456
24473
|
cwd: path12.resolve(options.cwd),
|
|
24457
24474
|
workspaceRoot: path12.resolve(options.workspaceRoot),
|
|
24458
24475
|
urlScrapeTimeoutMs: resolveUrlScrapeTimeout(options.urlScrapeTimeoutMs),
|
|
@@ -24713,7 +24730,7 @@ var AppDevServer = class _AppDevServer {
|
|
|
24713
24730
|
this.recentOutput = [];
|
|
24714
24731
|
const dialectIssue = findPowerShellSyntax(this.options.command);
|
|
24715
24732
|
if (dialectIssue) {
|
|
24716
|
-
const error = `The app dev command was rejected before spawn: it contains PowerShell-only syntax (${dialectIssue}), which the shell Tempo runs commands with (cmd.exe on Windows) cannot parse \u2014 nothing was started. Rewrite "
|
|
24733
|
+
const error = `The app dev command was rejected before spawn: it contains PowerShell-only syntax (${dialectIssue}), which the shell Tempo runs commands with (cmd.exe on Windows) cannot parse \u2014 nothing was started. Rewrite "apps[0].start" in tempo.config.json as a single plain cross-platform command \u2014 use \${APP_PORT} only if it needs Tempo's allocated helper port \u2014 and if the app lives in a subdirectory set "appDir" instead of cd/pushd-ing inside the command (chaining with \`&&\` is fine; cmd supports it).`;
|
|
24717
24734
|
devLog("app-devserver:shell-dialect-rejected", {
|
|
24718
24735
|
command: this.options.command,
|
|
24719
24736
|
construct: dialectIssue
|
|
@@ -24745,6 +24762,7 @@ var AppDevServer = class _AppDevServer {
|
|
|
24745
24762
|
const command = lifted.command;
|
|
24746
24763
|
const env = {
|
|
24747
24764
|
...process.env,
|
|
24765
|
+
APP_PORT: String(port),
|
|
24748
24766
|
PORT: String(port),
|
|
24749
24767
|
TEMPO_APP_PORT: String(port),
|
|
24750
24768
|
// Activate the Tempo annotation plugin (tempoVitePlugin /
|
|
@@ -24767,6 +24785,7 @@ var AppDevServer = class _AppDevServer {
|
|
|
24767
24785
|
Object.assign(env, lifted.env);
|
|
24768
24786
|
devLog("app-devserver:spawn", {
|
|
24769
24787
|
command,
|
|
24788
|
+
configuredUrl: this.options.url ?? null,
|
|
24770
24789
|
liftedEnvKeys: Object.keys(lifted.env),
|
|
24771
24790
|
cwd: this.options.cwd,
|
|
24772
24791
|
port
|
|
@@ -25028,14 +25047,21 @@ Hint: ${hint.hint}` : ""}`;
|
|
|
25028
25047
|
});
|
|
25029
25048
|
}
|
|
25030
25049
|
async waitForReady(port, signal) {
|
|
25031
|
-
const
|
|
25032
|
-
|
|
25033
|
-
|
|
25034
|
-
|
|
25035
|
-
|
|
25036
|
-
|
|
25037
|
-
|
|
25038
|
-
|
|
25050
|
+
const configuredUrl = this.options.url ? substituteAppPort(this.options.url, port) : null;
|
|
25051
|
+
if (!configuredUrl) {
|
|
25052
|
+
const scrapeDeadline = Date.now() + this.options.urlScrapeTimeoutMs;
|
|
25053
|
+
while (!this.detectedBaseUrl && Date.now() < scrapeDeadline) {
|
|
25054
|
+
throwIfAppLaunchAborted(signal);
|
|
25055
|
+
if (!this.child) return null;
|
|
25056
|
+
await sleepForAppLaunch(120, signal);
|
|
25057
|
+
}
|
|
25058
|
+
}
|
|
25059
|
+
const baseUrl = configuredUrl ?? this.detectedBaseUrl ?? `http://${PUBLIC_HOSTNAME}:${port}`;
|
|
25060
|
+
const publicUrl = rewriteToPublicHost(
|
|
25061
|
+
baseUrl,
|
|
25062
|
+
port,
|
|
25063
|
+
configuredUrl === null
|
|
25064
|
+
);
|
|
25039
25065
|
const start = Date.now();
|
|
25040
25066
|
let lastProgressAt = start;
|
|
25041
25067
|
while (true) {
|
|
@@ -25403,17 +25429,17 @@ function extractServerUrl(text) {
|
|
|
25403
25429
|
}
|
|
25404
25430
|
return null;
|
|
25405
25431
|
}
|
|
25406
|
-
function rewriteToPublicHost(url, fallbackPort) {
|
|
25432
|
+
function rewriteToPublicHost(url, fallbackPort, applyFallbackPort = true) {
|
|
25407
25433
|
try {
|
|
25408
25434
|
const parsed = new URL(url);
|
|
25409
25435
|
if (parsed.hostname === "0.0.0.0" || parsed.hostname === "::") {
|
|
25410
25436
|
parsed.hostname = PUBLIC_HOSTNAME;
|
|
25411
25437
|
}
|
|
25412
|
-
if (!parsed.port) {
|
|
25438
|
+
if (applyFallbackPort && !parsed.port) {
|
|
25413
25439
|
parsed.port = String(fallbackPort);
|
|
25414
25440
|
}
|
|
25415
25441
|
const normalizedPath = parsed.pathname.replace(/\/+$/, "");
|
|
25416
|
-
return `${parsed.origin}${normalizedPath}`;
|
|
25442
|
+
return `${parsed.origin}${normalizedPath}${parsed.search}`;
|
|
25417
25443
|
} catch {
|
|
25418
25444
|
return `http://${PUBLIC_HOSTNAME}:${fallbackPort}`;
|
|
25419
25445
|
}
|
|
@@ -25504,7 +25530,7 @@ function waitForWatchdogChildPid(watchdog, timeoutMs = 2e3) {
|
|
|
25504
25530
|
});
|
|
25505
25531
|
}
|
|
25506
25532
|
function substituteAppPort(command, port) {
|
|
25507
|
-
return command.replace(/\$\{PORT\}/g, String(port));
|
|
25533
|
+
return command.replace(/\$\{(?:APP_PORT|PORT)\}/g, String(port));
|
|
25508
25534
|
}
|
|
25509
25535
|
async function findFreePort(range) {
|
|
25510
25536
|
const maxAttempts = 50;
|
|
@@ -32291,9 +32317,25 @@ function validateAppStart(value, label = "scripts.appStart") {
|
|
|
32291
32317
|
);
|
|
32292
32318
|
}
|
|
32293
32319
|
const trimmed2 = value.trim();
|
|
32294
|
-
|
|
32320
|
+
return trimmed2;
|
|
32321
|
+
}
|
|
32322
|
+
function validateAppUrl(value, label) {
|
|
32323
|
+
if (value === void 0 || value === null) return void 0;
|
|
32324
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
32325
|
+
throw new Error(
|
|
32326
|
+
`tempo.config.json field "${label}" must be a non-empty string when set`
|
|
32327
|
+
);
|
|
32328
|
+
}
|
|
32329
|
+
const trimmed2 = value.trim();
|
|
32330
|
+
let parsed;
|
|
32331
|
+
try {
|
|
32332
|
+
parsed = new URL(trimmed2.replace(/\$\{(?:APP_PORT|PORT)\}/g, "5173"));
|
|
32333
|
+
} catch {
|
|
32334
|
+
throw new Error(`tempo.config.json field "${label}" must be a valid URL`);
|
|
32335
|
+
}
|
|
32336
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
32295
32337
|
throw new Error(
|
|
32296
|
-
`tempo.config.json field "${label}" must
|
|
32338
|
+
`tempo.config.json field "${label}" must use the "http:" or "https:" protocol`
|
|
32297
32339
|
);
|
|
32298
32340
|
}
|
|
32299
32341
|
return trimmed2;
|
|
@@ -32385,9 +32427,7 @@ function validateApps(value) {
|
|
|
32385
32427
|
const seenAppDirs = /* @__PURE__ */ new Set();
|
|
32386
32428
|
return value.map((entry, i) => {
|
|
32387
32429
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
32388
|
-
throw new Error(
|
|
32389
|
-
`tempo.config.json field "apps[${i}]" must be an object`
|
|
32390
|
-
);
|
|
32430
|
+
throw new Error(`tempo.config.json field "apps[${i}]" must be an object`);
|
|
32391
32431
|
}
|
|
32392
32432
|
const raw = entry;
|
|
32393
32433
|
const appDir = validateAppDir(raw.appDir, `apps[${i}].appDir`);
|
|
@@ -32404,19 +32444,36 @@ function validateApps(value) {
|
|
|
32404
32444
|
}
|
|
32405
32445
|
seenAppDirs.add(appDir);
|
|
32406
32446
|
}
|
|
32407
|
-
const
|
|
32447
|
+
const url = validateAppUrl(raw.url, `apps[${i}].url`);
|
|
32448
|
+
const start = validateAppStart(raw.start, `apps[${i}].start`);
|
|
32449
|
+
const legacyAppStart = validateAppStart(
|
|
32450
|
+
raw.appStart,
|
|
32451
|
+
`apps[${i}].appStart`
|
|
32452
|
+
);
|
|
32453
|
+
if (start !== void 0 && legacyAppStart !== void 0 && start !== legacyAppStart) {
|
|
32454
|
+
throw new Error(
|
|
32455
|
+
`tempo.config.json fields "apps[${i}].start" and legacy "apps[${i}].appStart" disagree \u2014 make them match or drop "appStart"`
|
|
32456
|
+
);
|
|
32457
|
+
}
|
|
32458
|
+
const effectiveStart = start ?? legacyAppStart;
|
|
32459
|
+
if (url !== void 0 && effectiveStart === void 0) {
|
|
32460
|
+
throw new Error(
|
|
32461
|
+
`tempo.config.json field "apps[${i}].url" requires "apps[${i}].start"`
|
|
32462
|
+
);
|
|
32463
|
+
}
|
|
32408
32464
|
const uiFramework = validateUiFramework(
|
|
32409
32465
|
raw.uiFramework,
|
|
32410
32466
|
`apps[${i}].uiFramework`
|
|
32411
32467
|
);
|
|
32412
|
-
if (appDir === void 0 &&
|
|
32468
|
+
if (appDir === void 0 && effectiveStart === void 0 && url === void 0 && uiFramework === void 0) {
|
|
32413
32469
|
throw new Error(
|
|
32414
|
-
`tempo.config.json field "apps[${i}]" must set "appDir", "
|
|
32470
|
+
`tempo.config.json field "apps[${i}]" must set "appDir", "start", "url", and/or "uiFramework" \u2014 an empty entry encodes nothing`
|
|
32415
32471
|
);
|
|
32416
32472
|
}
|
|
32417
32473
|
return {
|
|
32418
32474
|
...appDir !== void 0 ? { appDir } : {},
|
|
32419
|
-
...
|
|
32475
|
+
...effectiveStart !== void 0 ? { start: effectiveStart } : {},
|
|
32476
|
+
...url !== void 0 ? { url } : {},
|
|
32420
32477
|
...uiFramework !== void 0 ? { uiFramework } : {}
|
|
32421
32478
|
};
|
|
32422
32479
|
});
|
|
@@ -32470,11 +32527,10 @@ function validateTempoConfigFile(value) {
|
|
|
32470
32527
|
const setupScript = validateSetupScript(raw.setupScript);
|
|
32471
32528
|
const runScripts = validateRunScripts(raw.runScripts);
|
|
32472
32529
|
const appStart = validateAppStart(
|
|
32473
|
-
scripts.appStart
|
|
32474
|
-
|
|
32475
|
-
const stop = validateScriptsStop(
|
|
32476
|
-
scripts.stop
|
|
32530
|
+
scripts.appStart,
|
|
32531
|
+
"scripts.appStart"
|
|
32477
32532
|
);
|
|
32533
|
+
const stop = validateScriptsStop(scripts.stop);
|
|
32478
32534
|
if (apps) {
|
|
32479
32535
|
const activeApp = apps[0];
|
|
32480
32536
|
if (appDir !== void 0 && appDir !== activeApp.appDir) {
|
|
@@ -32482,9 +32538,9 @@ function validateTempoConfigFile(value) {
|
|
|
32482
32538
|
`tempo.config.json fields "appDir" ("${appDir}") and "apps[0].appDir" ("${activeApp.appDir}") disagree \u2014 apps[0] is the active app; make them match or drop the legacy "appDir"`
|
|
32483
32539
|
);
|
|
32484
32540
|
}
|
|
32485
|
-
if (appStart !== void 0 && appStart !== activeApp.
|
|
32541
|
+
if (appStart !== void 0 && appStart !== activeApp.start) {
|
|
32486
32542
|
throw new Error(
|
|
32487
|
-
'tempo.config.json fields "scripts.appStart" and "apps[0].
|
|
32543
|
+
'tempo.config.json fields "scripts.appStart" and "apps[0].start" disagree \u2014 apps[0] is the active app; make them match or drop the legacy "scripts.appStart"'
|
|
32488
32544
|
);
|
|
32489
32545
|
}
|
|
32490
32546
|
}
|
|
@@ -32495,12 +32551,12 @@ function validateTempoConfigFile(value) {
|
|
|
32495
32551
|
normalizedApps = [
|
|
32496
32552
|
{
|
|
32497
32553
|
...appDir !== void 0 ? { appDir } : {},
|
|
32498
|
-
...appStart !== void 0 ? { appStart } : {}
|
|
32554
|
+
...appStart !== void 0 ? { start: appStart } : {}
|
|
32499
32555
|
}
|
|
32500
32556
|
];
|
|
32501
32557
|
}
|
|
32502
32558
|
const activeAppDir = normalizedApps ? normalizedApps[0].appDir : void 0;
|
|
32503
|
-
const activeAppStart = normalizedApps ? normalizedApps[0].
|
|
32559
|
+
const activeAppStart = normalizedApps ? normalizedApps[0].start : void 0;
|
|
32504
32560
|
return {
|
|
32505
32561
|
...paths ? { paths } : {},
|
|
32506
32562
|
...urls ? { urls } : {},
|
|
@@ -32790,14 +32846,19 @@ async function resolveTempoConfig(projectRoot) {
|
|
|
32790
32846
|
if (config.apps && config.apps.length > 0) {
|
|
32791
32847
|
apps = config.apps.map((app) => ({
|
|
32792
32848
|
appDir: app.appDir,
|
|
32793
|
-
|
|
32849
|
+
start: app.start ?? null,
|
|
32850
|
+
url: app.url ?? null,
|
|
32851
|
+
appStart: app.start ?? null,
|
|
32794
32852
|
...app.uiFramework ? { uiFramework: app.uiFramework } : {}
|
|
32795
32853
|
}));
|
|
32796
32854
|
} else {
|
|
32855
|
+
const legacyStart = config.scripts.appStart ?? null;
|
|
32797
32856
|
apps = [
|
|
32798
32857
|
{
|
|
32799
32858
|
...config.appDir !== void 0 ? { appDir: config.appDir } : {},
|
|
32800
|
-
|
|
32859
|
+
start: legacyStart,
|
|
32860
|
+
url: null,
|
|
32861
|
+
appStart: legacyStart
|
|
32801
32862
|
}
|
|
32802
32863
|
];
|
|
32803
32864
|
}
|
|
@@ -32814,6 +32875,7 @@ async function resolveTempoConfig(projectRoot) {
|
|
|
32814
32875
|
viteConfigPath: path23.join(tempoRoot, "vite.config.ts"),
|
|
32815
32876
|
tsconfigPath: path23.join(tempoRoot, "tsconfig.json"),
|
|
32816
32877
|
tempoHostUrl: config.urls?.tempoHost ?? null,
|
|
32878
|
+
appUrl: activeApp.url,
|
|
32817
32879
|
scripts: {
|
|
32818
32880
|
install: config.scripts.install,
|
|
32819
32881
|
start: config.scripts.start,
|
|
@@ -44094,11 +44156,11 @@ function registerTools(server, context) {
|
|
|
44094
44156
|
...output,
|
|
44095
44157
|
warnings: [
|
|
44096
44158
|
...output.warnings ?? [],
|
|
44097
|
-
"This canvas contains a route storyboard (`<RouteStoryboard>`) but no app dev command (`apps[0].
|
|
44159
|
+
"This canvas contains a route storyboard (`<RouteStoryboard>`) but no app dev command (`apps[0].start`) is configured in tempo.config.json. Route iframes will fail to load until you configure the user's real app dev server. Read the project root's package.json `scripts.dev`, then call `set_app_dev_command` with that foreground command and, when known, its HTTP(S) readiness URL. `${APP_PORT}` is an optional allocated-port helper; legacy `${PORT}` remains supported."
|
|
44098
44160
|
],
|
|
44099
44161
|
app_dev_server: {
|
|
44100
44162
|
configured: false,
|
|
44101
|
-
next_step: "Call set_app_dev_command with
|
|
44163
|
+
next_step: "Call set_app_dev_command with start and, when needed, url."
|
|
44102
44164
|
}
|
|
44103
44165
|
},
|
|
44104
44166
|
null,
|
|
@@ -44298,7 +44360,7 @@ function registerTools(server, context) {
|
|
|
44298
44360
|
start: scaffoldedConfig.scripts.start
|
|
44299
44361
|
}
|
|
44300
44362
|
} : void 0;
|
|
44301
|
-
const reviewNotes = "UI source framework is explicit: omission means React. If this is a Svelte 5 app, set apps[0].uiFramework to \"svelte\" in tempo.config.json and rerun canvas_project_init before creating storyboards. That rerun fills the generated sidecar's missing svelte and @sveltejs/vite-plugin-svelte dependencies using starter defaults; it preserves existing sidecar package specs. For a Svelte route storyboard, setup is NOT complete until apps[0].
|
|
44363
|
+
const reviewNotes = "UI source framework is explicit: omission means React. If this is a Svelte 5 app, set apps[0].uiFramework to \"svelte\" in tempo.config.json and rerun canvas_project_init before creating storyboards. That rerun fills the generated sidecar's missing svelte and @sveltejs/vite-plugin-svelte dependencies using starter defaults; it preserves existing sidecar package specs. For a Svelte route storyboard, setup is NOT complete until apps[0].start is configured, the app's own package depends on tempo-sdk, and a standalone Svelte/Vite app directly dev-depends on @sveltejs/vite-plugin-svelte. Use set_app_dev_command for start and its HTTP(S) readiness URL when known; `${APP_PORT}` is an optional allocated-port helper and legacy `${PORT}` remains supported. Add only missing app packages, choose versions compatible with its existing Svelte/Vite toolchain, and never replace configured versions with Tempo's starter defaults. The app's own Vite/Svelte config must use tempoVitePlugin() plus tempoSveltePreprocess(...) as the first Svelte preprocessor; the generated tempo/ sidecar config does not affect the separately running app. Preserve any existing Svelte preprocessors after Tempo's. Double-check initial_tempo_config's scripts.install against this repo before moving on. A plain package-manager install (bare `npm install`/`pnpm install`/\u2026 or Tempo's chained `cd .. && \u2026 && cd tempo && \u2026` form) means Tempo's DEFAULT behavior: it installs the project root and tempo/ itself with the detected package manager \u2014 correct for most single-package repos. Write a CUSTOM command instead when the default won't produce importable app code: the app lives in a workspace/monorepo subdirectory (install must run at the workspace root or with the right filter), the app needs postinstall codegen (e.g. `prisma generate`), a private registry needs .npmrc/env, or the repo has a non-standard install. A custom value runs verbatim from tempo/ (cmd.exe-compatible syntax only, cover BOTH roots' dependencies) and Tempo NEVER rewrites it. After editing, run start_canvas_devserver({ force_install: true }).";
|
|
44302
44364
|
return textResult2(
|
|
44303
44365
|
JSON.stringify(
|
|
44304
44366
|
{
|
|
@@ -44412,27 +44474,44 @@ function registerTools(server, context) {
|
|
|
44412
44474
|
);
|
|
44413
44475
|
server.tool(
|
|
44414
44476
|
"set_app_dev_command",
|
|
44415
|
-
"Configure the app dev
|
|
44477
|
+
"Configure the user's REAL app dev server in tempo.config.json, stored canonically as `apps[0].start` plus optional `apps[0].url`. Legacy `apps[0].appStart` and `scripts.appStart` still read and migrate to `start` on write. Required for route storyboards. `start` may be any foreground command. `url`, when set, is only the HTTP(S) readiness target and route base: it is probed as written, never controls local allocation, and may point through a container, tunnel, or remote machine. Tempo exposes its independently allocated helper port through `${APP_PORT}` and still accepts legacy `${PORT}` in app start/URL fields. Invoke commands directly, keep them cross-platform, and use appDir for subdirectory apps. At least one of command/url must be provided; null clears that field. Idempotent.",
|
|
44416
44478
|
{
|
|
44417
44479
|
command: z23.string().nullish().describe(
|
|
44418
|
-
"The
|
|
44480
|
+
"The canonical apps[0].start foreground command. It may be arbitrary; use `${APP_PORT}` when the command should consume Tempo's allocated helper port. Legacy `${PORT}` remains supported. Omit to leave unchanged; pass null/empty to clear the app server configuration."
|
|
44481
|
+
),
|
|
44482
|
+
url: z23.string().nullish().describe(
|
|
44483
|
+
"Optional canonical apps[0].url. This is the HTTP(S) readiness target and route base only. It may contain `${APP_PORT}` (or legacy `${PORT}`) or be any literal reachable HTTP(S) URL, including a container, tunnel, or remote host; it never controls local port allocation. Omit to leave unchanged; pass null/empty to clear only this field."
|
|
44419
44484
|
),
|
|
44420
44485
|
...appDevServerTargetArgs
|
|
44421
44486
|
},
|
|
44422
|
-
async ({ command, repo_root, app_dir }) => {
|
|
44487
|
+
async ({ command, url, repo_root, app_dir }) => {
|
|
44423
44488
|
if (!context.appDevServer)
|
|
44424
44489
|
return unsupportedEnvironmentResult("appDevServer");
|
|
44425
|
-
|
|
44490
|
+
if (command === void 0 && url === void 0) {
|
|
44491
|
+
return errorResult9("Provide command and/or url to update.");
|
|
44492
|
+
}
|
|
44493
|
+
const startValue = command === void 0 ? void 0 : typeof command === "string" && command.trim().length > 0 ? command.trim() : null;
|
|
44494
|
+
const urlValue = url === void 0 ? void 0 : typeof url === "string" && url.trim().length > 0 ? url.trim() : null;
|
|
44426
44495
|
try {
|
|
44427
|
-
await context.appDevServer.
|
|
44428
|
-
|
|
44496
|
+
await context.appDevServer.setConfig(
|
|
44497
|
+
{
|
|
44498
|
+
...startValue !== void 0 ? { start: startValue } : {},
|
|
44499
|
+
...urlValue !== void 0 ? { url: urlValue } : {}
|
|
44500
|
+
},
|
|
44429
44501
|
toAppDevServerTarget({ repo_root, app_dir })
|
|
44430
44502
|
);
|
|
44431
44503
|
return textResult2(
|
|
44432
44504
|
JSON.stringify(
|
|
44433
44505
|
{
|
|
44434
|
-
|
|
44435
|
-
|
|
44506
|
+
// Preserve the original result field for callers that inspect
|
|
44507
|
+
// tool output instead of only the tool arguments.
|
|
44508
|
+
...startValue !== void 0 ? { app_dev_command: startValue } : {},
|
|
44509
|
+
...urlValue !== void 0 ? { app_dev_url: urlValue } : {},
|
|
44510
|
+
app_dev_config_update: {
|
|
44511
|
+
...startValue !== void 0 ? { start: startValue } : {},
|
|
44512
|
+
...urlValue !== void 0 ? { url: urlValue } : {}
|
|
44513
|
+
},
|
|
44514
|
+
note: startValue === null ? "Cleared." : "Saved. The supervisor allocates the optional local `${APP_PORT}` helper independently (legacy `${PORT}` remains supported); a configured URL is probed exactly as the readiness target and route base. Before declaring setup complete, verify the app depends on tempo-sdk and its own bundler config carries Tempo instrumentation. For standalone Svelte/Vite, add @sveltejs/vite-plugin-svelte only if missing, preserve compatible configured versions, and use tempoVitePlugin() plus tempoSveltePreprocess(...) first in the app's preprocess chain; tempo/ only configures the sidecar."
|
|
44436
44515
|
},
|
|
44437
44516
|
null,
|
|
44438
44517
|
2
|
|
@@ -44447,7 +44526,7 @@ function registerTools(server, context) {
|
|
|
44447
44526
|
);
|
|
44448
44527
|
server.tool(
|
|
44449
44528
|
"check_app_dev_server",
|
|
44450
|
-
"Check the per-workspace app dev server
|
|
44529
|
+
"Check the per-workspace app dev server configured by canonical `apps[0].start`/`url` (legacy appStart spellings also read). Returns `{configured, running, phase, port, url, error}`. Use this when a route storyboard isn't rendering. `configured: false` means start is unset; `phase: 'error'` carries the supervisor failure.",
|
|
44451
44530
|
{ ...appDevServerTargetArgs },
|
|
44452
44531
|
async ({ repo_root, app_dir }) => {
|
|
44453
44532
|
if (!context.appDevServer)
|
|
@@ -44466,7 +44545,7 @@ function registerTools(server, context) {
|
|
|
44466
44545
|
);
|
|
44467
44546
|
server.tool(
|
|
44468
44547
|
"start_app_dev_server",
|
|
44469
|
-
"Start the per-workspace app dev server if it isn't already running. Spawns
|
|
44548
|
+
"Start the per-workspace app dev server if it isn't already running. Spawns canonical `apps[0].start`, substitutes `${APP_PORT}` (or legacy `${PORT}`) in start/url, persists the independently selected local helper port under `<workspaceRoot>/.tempo/app-devserver.json`, and HTTP-gates readiness against the configured URL or detected local URL. A literal URL is probed as written and does not affect local allocation. No-op if already running. When start is unset, returns `{configured: false}`; call `set_app_dev_command` first.",
|
|
44470
44549
|
{ ...appDevServerTargetArgs },
|
|
44471
44550
|
async ({ repo_root, app_dir }) => {
|
|
44472
44551
|
if (!context.appDevServer)
|
|
@@ -45143,7 +45222,7 @@ function isExternallyExposed(toolName, opts) {
|
|
|
45143
45222
|
}
|
|
45144
45223
|
|
|
45145
45224
|
// src/version.ts
|
|
45146
|
-
var CLI_VERSION = "0.0.
|
|
45225
|
+
var CLI_VERSION = "0.0.103";
|
|
45147
45226
|
|
|
45148
45227
|
// src/canvas-hooks.ts
|
|
45149
45228
|
var import_pngjs3 = __toESM(require_png(), 1);
|
|
@@ -47117,4 +47196,4 @@ export {
|
|
|
47117
47196
|
runServe,
|
|
47118
47197
|
scopeParamsFor
|
|
47119
47198
|
};
|
|
47120
|
-
//# sourceMappingURL=serve-
|
|
47199
|
+
//# sourceMappingURL=serve-P7M4UFJS.js.map
|