@impractical-ai/motion 0.1.13 → 0.1.14
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/{api-4YQKINQI.js → api-VLQHOCLI.js} +6 -2
- package/dist/{chunk-PTYSKJ2Y.js → chunk-7SNCVSTA.js} +4 -4
- package/dist/{chunk-ZCTJTQB7.js → chunk-L5ERED5A.js} +79 -10
- package/dist/{chunk-GAHKKLF3.js → chunk-O3BUN66P.js} +45 -14
- package/dist/{commands-NWJK7ANI.js → commands-3PIMUGYP.js} +12 -5
- package/dist/index.js +5 -5
- package/dist/{stdio-PLWZDKDA.js → stdio-M2YRHGFJ.js} +773 -237
- package/package.json +3 -3
|
@@ -3,29 +3,33 @@ import {
|
|
|
3
3
|
ApiContractError,
|
|
4
4
|
ApiError,
|
|
5
5
|
ApiTransportError,
|
|
6
|
+
WORKSPACE_HEADER,
|
|
6
7
|
admitMcpCall,
|
|
7
8
|
delay,
|
|
8
9
|
invoke,
|
|
9
10
|
invokeAt,
|
|
10
11
|
jobStatus,
|
|
11
12
|
studioLink,
|
|
13
|
+
studioQuery,
|
|
12
14
|
validateApiResponse,
|
|
13
15
|
waitForJobs,
|
|
14
16
|
withAdmissionReceipt,
|
|
15
17
|
withMeteredCall
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import "./chunk-
|
|
18
|
+
} from "./chunk-O3BUN66P.js";
|
|
19
|
+
import "./chunk-7SNCVSTA.js";
|
|
18
20
|
import "./chunk-77HVPD4G.js";
|
|
19
21
|
export {
|
|
20
22
|
ApiContractError,
|
|
21
23
|
ApiError,
|
|
22
24
|
ApiTransportError,
|
|
25
|
+
WORKSPACE_HEADER,
|
|
23
26
|
admitMcpCall,
|
|
24
27
|
delay,
|
|
25
28
|
invoke,
|
|
26
29
|
invokeAt,
|
|
27
30
|
jobStatus,
|
|
28
31
|
studioLink,
|
|
32
|
+
studioQuery,
|
|
29
33
|
validateApiResponse,
|
|
30
34
|
waitForJobs,
|
|
31
35
|
withAdmissionReceipt,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// package.json
|
|
4
4
|
var package_default = {
|
|
5
5
|
name: "@impractical-ai/motion",
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.14",
|
|
7
7
|
private: false,
|
|
8
8
|
description: "Create and refine Impractical Motion videos from coding agents and the terminal.",
|
|
9
9
|
homepage: "https://github.com/Openpod/impractical-motion#readme",
|
|
@@ -30,7 +30,7 @@ var package_default = {
|
|
|
30
30
|
scripts: {
|
|
31
31
|
build: 'node ../scripts/verify-locked-cli-install.mjs && node ../scripts/build-engine-dts.mjs --cli-only && rm -rf dist && ./node_modules/esbuild/bin/esbuild src/index.ts --define:__BUILD_COMMIT__=\\"$(git rev-parse --short HEAD 2>/dev/null || echo dev)\\" --bundle --platform=node --format=esm --target=node22 --splitting --outdir=dist --external:playwright-core --banner:js="#!/usr/bin/env node" && chmod +x dist/index.js',
|
|
32
32
|
typecheck: "tsc --noEmit",
|
|
33
|
-
test: "npm run typecheck && npm run build && esbuild tests/onboarding.test.ts tests/mcp-tools.test.ts tests/mcp-frames.test.ts tests/mcp-browser-pool.test.ts tests/mcp-motion.test.ts tests/mcp-craft.test.ts tests/mcp-depthkit.test.ts tests/mcp-motion-score.test.ts tests/mcp-install-font.test.ts tests/mcp-metric-catalog.test.ts tests/mcp-text-census.test.ts tests/mcp-phased-flow.test.ts tests/mcp-preflight.test.ts tests/engine-dts.test.ts tests/mcp-connect.test.ts tests/mcp-longpoll.test.ts tests/mcp-agent-timeout.test.ts tests/api-hardening.test.ts --bundle --platform=node --format=esm --packages=external --outdir=dist --out-extension:.js=.mjs && node --test dist/onboarding.test.mjs dist/mcp-tools.test.mjs dist/mcp-frames.test.mjs dist/mcp-browser-pool.test.mjs dist/mcp-motion.test.mjs dist/mcp-craft.test.mjs dist/mcp-depthkit.test.mjs dist/mcp-motion-score.test.mjs dist/mcp-install-font.test.mjs dist/mcp-metric-catalog.test.mjs dist/mcp-text-census.test.mjs dist/mcp-phased-flow.test.mjs dist/mcp-preflight.test.mjs dist/engine-dts.test.mjs dist/mcp-connect.test.mjs dist/mcp-longpoll.test.mjs dist/mcp-agent-timeout.test.mjs dist/api-hardening.test.mjs",
|
|
33
|
+
test: "npm run typecheck && npm run build && esbuild tests/onboarding.test.ts tests/mcp-tools.test.ts tests/mcp-frames.test.ts tests/mcp-browser-pool.test.ts tests/mcp-motion.test.ts tests/mcp-craft.test.ts tests/mcp-depthkit.test.ts tests/mcp-motion-score.test.ts tests/mcp-install-font.test.ts tests/mcp-metric-catalog.test.ts tests/mcp-text-census.test.ts tests/mcp-phased-flow.test.ts tests/mcp-preflight.test.ts tests/engine-dts.test.ts tests/mcp-connect.test.ts tests/mcp-workspaces.test.ts tests/mcp-longpoll.test.ts tests/mcp-agent-timeout.test.ts tests/api-hardening.test.ts --bundle --platform=node --format=esm --packages=external --outdir=dist --out-extension:.js=.mjs && node --test dist/onboarding.test.mjs dist/mcp-tools.test.mjs dist/mcp-frames.test.mjs dist/mcp-browser-pool.test.mjs dist/mcp-motion.test.mjs dist/mcp-craft.test.mjs dist/mcp-depthkit.test.mjs dist/mcp-motion-score.test.mjs dist/mcp-install-font.test.mjs dist/mcp-metric-catalog.test.mjs dist/mcp-text-census.test.mjs dist/mcp-phased-flow.test.mjs dist/mcp-preflight.test.mjs dist/engine-dts.test.mjs dist/mcp-connect.test.mjs dist/mcp-workspaces.test.mjs dist/mcp-longpoll.test.mjs dist/mcp-agent-timeout.test.mjs dist/api-hardening.test.mjs",
|
|
34
34
|
prepack: "npm run build",
|
|
35
35
|
"test:rig": "npm run typecheck && esbuild tests/engine-dts.test.ts tests/mcp-agent-timeout.test.ts tests/mcp-browser-pool.test.ts tests/mcp-component-assertions.test.ts tests/mcp-components.test.ts tests/mcp-connect.test.ts tests/mcp-craft.test.ts tests/mcp-depthkit.test.ts tests/mcp-exposed-ground.test.ts tests/mcp-frames.test.ts tests/mcp-install-font.test.ts tests/mcp-legibility.test.ts tests/mcp-longpoll.test.ts tests/mcp-metric-catalog.test.ts tests/mcp-motion-score.test.ts tests/mcp-motion-slop.test.ts tests/mcp-motion.test.ts tests/mcp-phased-flow.test.ts tests/mcp-preflight.test.ts tests/mcp-ref-inject.test.ts tests/mcp-shot-list.test.ts tests/mcp-text-census.test.ts tests/mcp-tools.test.ts tests/review-modules.test.ts tests/rig-transplant.test.ts --bundle --platform=node --format=esm --packages=external --outdir=.rig-tests --out-extension:.js=.mjs && node --test .rig-tests/engine-dts.test.mjs .rig-tests/mcp-agent-timeout.test.mjs .rig-tests/mcp-browser-pool.test.mjs .rig-tests/mcp-component-assertions.test.mjs .rig-tests/mcp-components.test.mjs .rig-tests/mcp-connect.test.mjs .rig-tests/mcp-craft.test.mjs .rig-tests/mcp-depthkit.test.mjs .rig-tests/mcp-exposed-ground.test.mjs .rig-tests/mcp-frames.test.mjs .rig-tests/mcp-install-font.test.mjs .rig-tests/mcp-legibility.test.mjs .rig-tests/mcp-longpoll.test.mjs .rig-tests/mcp-metric-catalog.test.mjs .rig-tests/mcp-motion-score.test.mjs .rig-tests/mcp-motion-slop.test.mjs .rig-tests/mcp-motion.test.mjs .rig-tests/mcp-phased-flow.test.mjs .rig-tests/mcp-preflight.test.mjs .rig-tests/mcp-ref-inject.test.mjs .rig-tests/mcp-shot-list.test.mjs .rig-tests/mcp-text-census.test.mjs .rig-tests/mcp-tools.test.mjs .rig-tests/review-modules.test.mjs .rig-tests/rig-transplant.test.mjs"
|
|
36
36
|
},
|
|
@@ -43,7 +43,7 @@ var package_default = {
|
|
|
43
43
|
typescript: "^5.6.3"
|
|
44
44
|
},
|
|
45
45
|
dependencies: {
|
|
46
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
46
|
+
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
47
47
|
"playwright-core": "^1.55.1",
|
|
48
48
|
zod: "^4.4.3"
|
|
49
49
|
}
|
|
@@ -57,7 +57,7 @@ var PRODUCTION_APP_URL = "https://motion.impractical.ai";
|
|
|
57
57
|
var PRODUCTION_SUPABASE_URL = "https://uaxjweednprtbhbceify.supabase.co";
|
|
58
58
|
var PACKAGE_NAME = "@impractical-ai/motion";
|
|
59
59
|
var PACKAGE_VERSION = package_default.version;
|
|
60
|
-
var BUILD_COMMIT = "
|
|
60
|
+
var BUILD_COMMIT = "e734492" ? "e734492" : "dev";
|
|
61
61
|
var BUILD_ID = `${PACKAGE_VERSION}+${BUILD_COMMIT}`;
|
|
62
62
|
var PACKAGE_COMMAND = `npx --yes ${PACKAGE_NAME}`;
|
|
63
63
|
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
ApiContractError,
|
|
3
4
|
ApiError,
|
|
4
5
|
delay,
|
|
5
6
|
invokeAt,
|
|
6
7
|
loadConfig,
|
|
7
8
|
recoverCorruptConfig,
|
|
8
9
|
saveConfig
|
|
9
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-O3BUN66P.js";
|
|
10
11
|
import {
|
|
11
12
|
PACKAGE_COMMAND,
|
|
12
13
|
PACKAGE_NAME,
|
|
13
14
|
PACKAGE_VERSION,
|
|
14
15
|
PRODUCTION_APP_URL,
|
|
15
16
|
PRODUCTION_SUPABASE_URL
|
|
16
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-7SNCVSTA.js";
|
|
17
18
|
|
|
18
19
|
// src/onboarding.ts
|
|
19
20
|
import {
|
|
@@ -31,6 +32,48 @@ import { dirname, join } from "node:path";
|
|
|
31
32
|
import { fileURLToPath } from "node:url";
|
|
32
33
|
import { spawnSync } from "node:child_process";
|
|
33
34
|
import { createRequire } from "node:module";
|
|
35
|
+
|
|
36
|
+
// src/workspaces.ts
|
|
37
|
+
var UNSUPPORTED = {
|
|
38
|
+
supported: false,
|
|
39
|
+
keyScope: null,
|
|
40
|
+
lastOpenWorkspaceId: null,
|
|
41
|
+
workspaces: []
|
|
42
|
+
};
|
|
43
|
+
async function fetchWorkspaces(request) {
|
|
44
|
+
let result;
|
|
45
|
+
try {
|
|
46
|
+
result = await request("workspace-bootstrap", { action: "list_workspaces" });
|
|
47
|
+
} catch (error) {
|
|
48
|
+
if (error instanceof ApiContractError) return UNSUPPORTED;
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
if (!Array.isArray(result?.workspaces)) return UNSUPPORTED;
|
|
52
|
+
const keyScope = result.keyScope === "user" ? "user" : result.keyScope === "org" ? "org" : null;
|
|
53
|
+
const workspaces = result.workspaces.filter((row) => typeof row?.id === "string").map((row) => ({
|
|
54
|
+
id: String(row.id),
|
|
55
|
+
name: typeof row.name === "string" ? row.name : null,
|
|
56
|
+
slug: typeof row.slug === "string" ? row.slug : null,
|
|
57
|
+
role: typeof row.role === "string" ? row.role : "",
|
|
58
|
+
plan: typeof row.plan === "string" ? row.plan : null,
|
|
59
|
+
usage: row.usage && typeof row.usage === "object" ? row.usage : null
|
|
60
|
+
}));
|
|
61
|
+
return {
|
|
62
|
+
supported: true,
|
|
63
|
+
keyScope,
|
|
64
|
+
lastOpenWorkspaceId: typeof result.lastOpenWorkspaceId === "string" ? result.lastOpenWorkspaceId : null,
|
|
65
|
+
workspaces
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function workspaceLabel(workspace) {
|
|
69
|
+
return workspace.name ? `${workspace.name} (${workspace.id})` : workspace.id;
|
|
70
|
+
}
|
|
71
|
+
var DEVICE_START_BODY = { action: "start", scope: "user" };
|
|
72
|
+
function grantScope(grant) {
|
|
73
|
+
return grant.scope === "user" ? "user" : "org";
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/onboarding.ts
|
|
34
77
|
var CLAUDE_MARKETPLACE = "Openpod/impractical-agent-plugins";
|
|
35
78
|
var CLAUDE_PLUGIN = "impractical-motion@impractical";
|
|
36
79
|
var CLAUDE_MARKETPLACE_NAME = "impractical";
|
|
@@ -656,7 +699,7 @@ async function waitForApproval(supabaseUrl, authorization, log, setupFlag) {
|
|
|
656
699
|
action: "poll",
|
|
657
700
|
deviceCode: authorization.deviceCode
|
|
658
701
|
});
|
|
659
|
-
if (result.status === "authorized") return result
|
|
702
|
+
if (result.status === "authorized") return result;
|
|
660
703
|
if (!announced) {
|
|
661
704
|
log("Waiting for browser approval\u2026");
|
|
662
705
|
announced = true;
|
|
@@ -681,9 +724,25 @@ async function setup(options) {
|
|
|
681
724
|
const existing = loadConfig();
|
|
682
725
|
let apiKey = existing.supabaseUrl === supabaseUrl ? existing.apiKey : void 0;
|
|
683
726
|
let verified;
|
|
727
|
+
let workspacesLine;
|
|
728
|
+
const listWorkspaces = async (key) => {
|
|
729
|
+
const listing = await fetchWorkspaces((name, body) => invokeAt(supabaseUrl, name, body, key));
|
|
730
|
+
workspacesLine = `Workspaces: ${listing.workspaces.map(workspaceLabel).join(", ") || "none yet"} (one key for all of them)`;
|
|
731
|
+
};
|
|
732
|
+
const verify = async (key, scope) => {
|
|
733
|
+
if (scope === "user") return listWorkspaces(key);
|
|
734
|
+
try {
|
|
735
|
+
verified = await invokeAt(supabaseUrl, "workspace-bootstrap", {}, key);
|
|
736
|
+
} catch (error) {
|
|
737
|
+
if (scope === "unknown" && error instanceof ApiError && error.status === 409 && error.details?.error === "workspace_selection_required") {
|
|
738
|
+
return listWorkspaces(key);
|
|
739
|
+
}
|
|
740
|
+
throw error;
|
|
741
|
+
}
|
|
742
|
+
};
|
|
684
743
|
if (apiKey) {
|
|
685
744
|
try {
|
|
686
|
-
|
|
745
|
+
await verify(apiKey, "unknown");
|
|
687
746
|
options.log("Existing connection verified; browser authorization is not needed.");
|
|
688
747
|
} catch (error) {
|
|
689
748
|
if (!(error instanceof ApiError) || error.status !== 401) throw error;
|
|
@@ -692,9 +751,11 @@ async function setup(options) {
|
|
|
692
751
|
}
|
|
693
752
|
if (!apiKey) {
|
|
694
753
|
if (options.installAgentMcp) verifyAgentConfigs();
|
|
695
|
-
const authorization = await invokeAt(
|
|
696
|
-
|
|
697
|
-
|
|
754
|
+
const authorization = await invokeAt(
|
|
755
|
+
supabaseUrl,
|
|
756
|
+
"cli-device-auth",
|
|
757
|
+
DEVICE_START_BODY
|
|
758
|
+
);
|
|
698
759
|
options.log("");
|
|
699
760
|
options.log("Connect Impractical Motion");
|
|
700
761
|
options.log(`Code: ${authorization.userCode}`);
|
|
@@ -704,15 +765,17 @@ async function setup(options) {
|
|
|
704
765
|
const opened = openBrowser(authorization.verificationUri);
|
|
705
766
|
options.log(opened ? "Opened your browser." : "Could not open a browser automatically; use the link above.");
|
|
706
767
|
}
|
|
768
|
+
let grant;
|
|
707
769
|
try {
|
|
708
|
-
|
|
770
|
+
grant = await waitForApproval(supabaseUrl, authorization, options.log, setupFlag);
|
|
709
771
|
} catch (error) {
|
|
710
772
|
if (error instanceof ApiError && error.status === 410) {
|
|
711
773
|
throw new Error(`Authorization expired. Run \`${PACKAGE_COMMAND} setup ${setupFlag}\` again.`);
|
|
712
774
|
}
|
|
713
775
|
throw error;
|
|
714
776
|
}
|
|
715
|
-
|
|
777
|
+
apiKey = grant.apiKey;
|
|
778
|
+
await verify(apiKey, grantScope(grant));
|
|
716
779
|
saveConfig({ apiKey, supabaseUrl, appUrl });
|
|
717
780
|
}
|
|
718
781
|
const claudePlugin = options.installClaudePlugin ? installClaudePlugin(options.log) : void 0;
|
|
@@ -735,7 +798,9 @@ async function setup(options) {
|
|
|
735
798
|
options.log(`Refreshed legacy /impractical for ${skill.harness}; previous copy preserved at ${skill.backupPath}.`);
|
|
736
799
|
}
|
|
737
800
|
if (claudePlugin) options.log(pluginResultLine(claudePlugin));
|
|
738
|
-
options.log(
|
|
801
|
+
options.log(
|
|
802
|
+
workspacesLine ?? `Workspace: ${verified.orgId}${verified.plan ? ` \xB7 ${verified.plan}` : ""}`
|
|
803
|
+
);
|
|
739
804
|
options.log("");
|
|
740
805
|
if (options.installClaudePlugin) {
|
|
741
806
|
options.log("Run /reload-plugins, then type continue.");
|
|
@@ -752,6 +817,10 @@ async function setup(options) {
|
|
|
752
817
|
}
|
|
753
818
|
|
|
754
819
|
export {
|
|
820
|
+
fetchWorkspaces,
|
|
821
|
+
workspaceLabel,
|
|
822
|
+
DEVICE_START_BODY,
|
|
823
|
+
grantScope,
|
|
755
824
|
openBrowser,
|
|
756
825
|
setup
|
|
757
826
|
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
PRODUCTION_APP_URL,
|
|
4
4
|
PRODUCTION_SUPABASE_URL
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-7SNCVSTA.js";
|
|
6
6
|
|
|
7
7
|
// src/config.ts
|
|
8
8
|
import {
|
|
@@ -63,7 +63,9 @@ Run: npx --yes @impractical-ai/motion setup --agent`
|
|
|
63
63
|
}
|
|
64
64
|
function loadConfig() {
|
|
65
65
|
const stored = readStoredConfig();
|
|
66
|
+
const workspace = process.env.IMPRACTICAL_WORKSPACE?.trim() || void 0;
|
|
66
67
|
return {
|
|
68
|
+
...workspace ? { workspace } : {},
|
|
67
69
|
apiKey: process.env.IMPRACTICAL_API_KEY ?? stored.apiKey,
|
|
68
70
|
supabaseUrl: process.env.IMPRACTICAL_SUPABASE_URL ?? stored.supabaseUrl ?? PRODUCTION_SUPABASE_URL,
|
|
69
71
|
appUrl: process.env.IMPRACTICAL_APP_URL ?? stored.appUrl ?? PRODUCTION_APP_URL
|
|
@@ -144,7 +146,15 @@ function validateApiResponse(name, body, data) {
|
|
|
144
146
|
if (name === "video-shares" && input.action === "clone" && (typeof data.projectId !== "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(data.projectId) || typeof data.alreadyForked !== "boolean")) {
|
|
145
147
|
throw new ApiContractError(name, "a projectId and alreadyForked flag");
|
|
146
148
|
}
|
|
147
|
-
if (name === "workspace-bootstrap") {
|
|
149
|
+
if (name === "workspace-bootstrap" && input.action === "project_workspace") {
|
|
150
|
+
if (!("workspace" in data) || "orgId" in data) {
|
|
151
|
+
throw new ApiContractError(name, "a workspace field");
|
|
152
|
+
}
|
|
153
|
+
} else if (name === "workspace-bootstrap" && input.action === "list_workspaces") {
|
|
154
|
+
if (!Array.isArray(data.workspaces)) {
|
|
155
|
+
throw new ApiContractError(name, "an object with a workspaces array");
|
|
156
|
+
}
|
|
157
|
+
} else if (name === "workspace-bootstrap") {
|
|
148
158
|
const billing = data.billing;
|
|
149
159
|
if (typeof data.orgId !== "string" || typeof data.plan !== "string" || typeof data.hasAccess !== "boolean" || !isRecord(billing) || typeof billing.status !== "string") {
|
|
150
160
|
throw new ApiContractError(
|
|
@@ -188,12 +198,13 @@ function validateApiResponse(name, body, data) {
|
|
|
188
198
|
}
|
|
189
199
|
return data;
|
|
190
200
|
}
|
|
201
|
+
var WORKSPACE_HEADER = "x-impractical-workspace";
|
|
191
202
|
async function invoke(name, body = {}) {
|
|
192
|
-
const { apiKey, supabaseUrl } = requireConfig();
|
|
193
|
-
const
|
|
194
|
-
return invokeAt(supabaseUrl, name, body, apiKey, receipt);
|
|
203
|
+
const { apiKey, supabaseUrl, workspace } = requireConfig();
|
|
204
|
+
const call = admissionContext.getStore();
|
|
205
|
+
return invokeAt(supabaseUrl, name, body, apiKey, call?.receipt, call ? call.workspace : workspace);
|
|
195
206
|
}
|
|
196
|
-
async function invokeAt(supabaseUrl, name, body = {}, apiKey, admissionReceipt) {
|
|
207
|
+
async function invokeAt(supabaseUrl, name, body = {}, apiKey, admissionReceipt, workspace) {
|
|
197
208
|
const requestUrl = `${supabaseUrl.replace(/\/$/, "")}/functions/v1/${name}`;
|
|
198
209
|
let response;
|
|
199
210
|
try {
|
|
@@ -202,6 +213,7 @@ async function invokeAt(supabaseUrl, name, body = {}, apiKey, admissionReceipt)
|
|
|
202
213
|
headers: {
|
|
203
214
|
...apiKey ? { authorization: `Bearer ${apiKey}` } : {},
|
|
204
215
|
...admissionReceipt ? { "x-impractical-admission": admissionReceipt } : {},
|
|
216
|
+
...apiKey && workspace ? { [WORKSPACE_HEADER]: workspace } : {},
|
|
205
217
|
"content-type": "application/json"
|
|
206
218
|
},
|
|
207
219
|
body: JSON.stringify(body)
|
|
@@ -231,16 +243,33 @@ async function invokeAt(supabaseUrl, name, body = {}, apiKey, admissionReceipt)
|
|
|
231
243
|
}
|
|
232
244
|
return validateApiResponse(name, body, data);
|
|
233
245
|
}
|
|
234
|
-
async function admitMcpCall(toolName, callId = randomUUID()) {
|
|
246
|
+
async function admitMcpCall(toolName, target, callId = randomUUID()) {
|
|
235
247
|
const { apiKey, supabaseUrl } = requireConfig();
|
|
236
|
-
return invokeAt(
|
|
248
|
+
return invokeAt(
|
|
249
|
+
supabaseUrl,
|
|
250
|
+
"mcp-admission",
|
|
251
|
+
{ callId, toolName, ...target && Object.keys(target).length ? { target } : {} },
|
|
252
|
+
apiKey
|
|
253
|
+
);
|
|
237
254
|
}
|
|
238
|
-
function withAdmissionReceipt(receipt, task) {
|
|
239
|
-
return admissionContext.run(receipt, task);
|
|
255
|
+
function withAdmissionReceipt(receipt, task, workspace) {
|
|
256
|
+
return admissionContext.run({ receipt, workspace }, task);
|
|
240
257
|
}
|
|
241
258
|
async function withMeteredCall(toolName, task) {
|
|
242
|
-
const
|
|
243
|
-
|
|
259
|
+
const { workspace } = requireConfig();
|
|
260
|
+
const admission = await admitMcpCall(toolName, workspace ? { workspace } : void 0);
|
|
261
|
+
return withAdmissionReceipt(
|
|
262
|
+
admission.receipt,
|
|
263
|
+
task,
|
|
264
|
+
admission.keyScope === "user" ? admission.workspace?.id : void 0
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
function studioQuery(slug, workspace) {
|
|
268
|
+
const params = [
|
|
269
|
+
...slug ? [`scene=${slug}`] : [],
|
|
270
|
+
...workspace ? [`workspace=${encodeURIComponent(workspace)}`] : []
|
|
271
|
+
];
|
|
272
|
+
return params.length ? `?${params.join("&")}` : "";
|
|
244
273
|
}
|
|
245
274
|
var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
246
275
|
async function jobStatus(jobIds) {
|
|
@@ -264,9 +293,9 @@ async function waitForJobs(jobIds, onTick, deadlineMs = 72e5) {
|
|
|
264
293
|
}
|
|
265
294
|
return latest;
|
|
266
295
|
}
|
|
267
|
-
function studioLink(appUrl, projectId, slug) {
|
|
296
|
+
function studioLink(appUrl, projectId, slug, workspace) {
|
|
268
297
|
const base = (appUrl ?? "http://localhost:5173").replace(/\/$/, "");
|
|
269
|
-
return `${base}/projects/${projectId}/studio${slug
|
|
298
|
+
return `${base}/projects/${projectId}/studio${studioQuery(slug, workspace)}`;
|
|
270
299
|
}
|
|
271
300
|
|
|
272
301
|
export {
|
|
@@ -278,11 +307,13 @@ export {
|
|
|
278
307
|
ApiContractError,
|
|
279
308
|
ApiTransportError,
|
|
280
309
|
validateApiResponse,
|
|
310
|
+
WORKSPACE_HEADER,
|
|
281
311
|
invoke,
|
|
282
312
|
invokeAt,
|
|
283
313
|
admitMcpCall,
|
|
284
314
|
withAdmissionReceipt,
|
|
285
315
|
withMeteredCall,
|
|
316
|
+
studioQuery,
|
|
286
317
|
delay,
|
|
287
318
|
jobStatus,
|
|
288
319
|
waitForJobs,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
setup
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-L5ERED5A.js";
|
|
5
5
|
import {
|
|
6
6
|
invoke,
|
|
7
7
|
invokeAt,
|
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
saveConfig,
|
|
12
12
|
studioLink,
|
|
13
13
|
waitForJobs
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-O3BUN66P.js";
|
|
15
|
+
import "./chunk-7SNCVSTA.js";
|
|
16
16
|
import "./chunk-77HVPD4G.js";
|
|
17
17
|
|
|
18
18
|
// src/commands.ts
|
|
@@ -1247,7 +1247,11 @@ async function shareVideo(rest, flags) {
|
|
|
1247
1247
|
method: body ? "POST" : "GET",
|
|
1248
1248
|
redirect: "error",
|
|
1249
1249
|
signal: AbortSignal.timeout(45e3),
|
|
1250
|
-
headers: {
|
|
1250
|
+
headers: {
|
|
1251
|
+
authorization: `Bearer ${config.apiKey}`,
|
|
1252
|
+
...config.workspace ? { "x-impractical-workspace": config.workspace } : {},
|
|
1253
|
+
"content-type": "application/json"
|
|
1254
|
+
},
|
|
1251
1255
|
body: body ? JSON.stringify(body) : void 0
|
|
1252
1256
|
}
|
|
1253
1257
|
);
|
|
@@ -1380,7 +1384,10 @@ async function login(flags) {
|
|
|
1380
1384
|
config.supabaseUrl,
|
|
1381
1385
|
"workspace-bootstrap",
|
|
1382
1386
|
{},
|
|
1383
|
-
config.apiKey
|
|
1387
|
+
config.apiKey,
|
|
1388
|
+
void 0,
|
|
1389
|
+
// IMPRACTICAL_WORKSPACE, for a multi-workspace key; unset sends nothing.
|
|
1390
|
+
config.workspace
|
|
1384
1391
|
);
|
|
1385
1392
|
if (Object.keys(patch).length) saveConfig(patch);
|
|
1386
1393
|
out(`org: ${snapshot.orgId}`);
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
PACKAGE_VERSION
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7SNCVSTA.js";
|
|
5
5
|
import "./chunk-77HVPD4G.js";
|
|
6
6
|
|
|
7
7
|
// src/cli-args.ts
|
|
@@ -160,11 +160,11 @@ async function runCli(args, deps) {
|
|
|
160
160
|
// src/index.ts
|
|
161
161
|
runCli(process.argv.slice(2), {
|
|
162
162
|
writeLine: (line) => console.log(line),
|
|
163
|
-
loadCommands: () => import("./commands-
|
|
164
|
-
loadApi: () => import("./api-
|
|
165
|
-
loadMcp: () => import("./stdio-
|
|
163
|
+
loadCommands: () => import("./commands-3PIMUGYP.js"),
|
|
164
|
+
loadApi: () => import("./api-VLQHOCLI.js"),
|
|
165
|
+
loadMcp: () => import("./stdio-M2YRHGFJ.js")
|
|
166
166
|
}).catch(async (error) => {
|
|
167
|
-
const { ApiError } = await import("./api-
|
|
167
|
+
const { ApiError } = await import("./api-VLQHOCLI.js");
|
|
168
168
|
if (error instanceof ApiError) {
|
|
169
169
|
console.error(`Error (${error.status} from ${error.fn}): ${error.message}`);
|
|
170
170
|
if (error.status === 429) console.error("Weekly MCP allowance reached. Upgrade or wait for Monday UTC.");
|