deepspace 0.28.0 → 0.28.1
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/CHANGELOG.md +6 -0
- package/README.md +8 -0
- package/dist/{chunk-652TIGI4.js → chunk-PVEUIQN4.js} +2 -2
- package/dist/{chunk-652TIGI4.js.map → chunk-PVEUIQN4.js.map} +1 -1
- package/dist/cli.js +467 -35
- package/dist/cli.js.map +1 -1
- package/dist/documentation-client-core.js +1 -1
- package/dist/documentation-default-renderer.cjs +1 -1
- package/dist/documentation-react.js +1 -1
- package/dist/documentation-runtime.js +1 -1
- package/dist/documentation-server-core.js +1 -1
- package/dist/documentation.js +1 -1
- package/dist/documentation.js.map +1 -1
- package/dist/server.d.ts +21 -1
- package/dist/server.js +46 -11
- package/dist/server.js.map +1 -1
- package/dist/worker.d.ts +99 -1
- package/dist/worker.js +305 -33
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli/cli.ts
|
|
4
4
|
import {
|
|
5
|
-
defineCommand as
|
|
5
|
+
defineCommand as defineCommand15,
|
|
6
6
|
runMain,
|
|
7
7
|
runCommand,
|
|
8
8
|
renderUsage
|
|
@@ -660,6 +660,9 @@ var INVALID_URLS = {
|
|
|
660
660
|
platform: "http://127.0.0.1:9",
|
|
661
661
|
deploy: "http://127.0.0.1:9"
|
|
662
662
|
};
|
|
663
|
+
function appDomainForEnv(env) {
|
|
664
|
+
return env === "production" ? "app.space" : env === "staging" ? "spacestest.com" : null;
|
|
665
|
+
}
|
|
663
666
|
var PLATFORM_URLS = DEEPSPACE_ENV === "production" ? PROD_URLS : DEEPSPACE_ENV === "staging" ? STAGING_URLS : INVALID_URLS;
|
|
664
667
|
var PLANE_AUTH_URLS = {
|
|
665
668
|
production: PROD_URLS.auth,
|
|
@@ -689,10 +692,11 @@ function decodeJwtPayload(token) {
|
|
|
689
692
|
return JSON.parse(Buffer.from(payloadSegment, "base64url").toString("utf8"));
|
|
690
693
|
}
|
|
691
694
|
|
|
692
|
-
// src/
|
|
695
|
+
// src/shared/auth-session.ts
|
|
693
696
|
var SESSION_COOKIE = "__Secure-better-auth.session_token";
|
|
694
|
-
|
|
695
|
-
|
|
697
|
+
|
|
698
|
+
// src/cli/session.ts
|
|
699
|
+
async function exchangeSessionToken(authUrl, sessionToken, path, action, body) {
|
|
696
700
|
let res;
|
|
697
701
|
try {
|
|
698
702
|
res = await fetchWithTransientRetry(
|
|
@@ -701,8 +705,10 @@ async function exchangeSession(authUrl, sessionToken) {
|
|
|
701
705
|
method: "POST",
|
|
702
706
|
headers: {
|
|
703
707
|
Cookie: `${SESSION_COOKIE}=${encodeURIComponent(sessionToken)}`,
|
|
704
|
-
Origin: authUrl
|
|
705
|
-
|
|
708
|
+
Origin: authUrl,
|
|
709
|
+
...body === void 0 ? {} : { "Content-Type": "application/json" }
|
|
710
|
+
},
|
|
711
|
+
body
|
|
706
712
|
}),
|
|
707
713
|
{ timeoutMs: 15e3 }
|
|
708
714
|
);
|
|
@@ -717,7 +723,7 @@ async function exchangeSession(authUrl, sessionToken) {
|
|
|
717
723
|
if (res.status === 401) return null;
|
|
718
724
|
if (!res.ok) {
|
|
719
725
|
throw new ApiError(
|
|
720
|
-
`The auth service could not
|
|
726
|
+
`The auth service could not ${action} (HTTP ${res.status}). Retry without logging in again.`,
|
|
721
727
|
res.status,
|
|
722
728
|
res.status === 429 ? "rate_limited" : "auth_service_unavailable",
|
|
723
729
|
path
|
|
@@ -744,6 +750,18 @@ async function exchangeSession(authUrl, sessionToken) {
|
|
|
744
750
|
}
|
|
745
751
|
return data.token;
|
|
746
752
|
}
|
|
753
|
+
function exchangeSession(authUrl, sessionToken) {
|
|
754
|
+
return exchangeSessionToken(authUrl, sessionToken, "/api/auth/token", "refresh the CLI token");
|
|
755
|
+
}
|
|
756
|
+
function exchangeAgentSession(authUrl, sessionToken, target2) {
|
|
757
|
+
return exchangeSessionToken(
|
|
758
|
+
authUrl,
|
|
759
|
+
sessionToken,
|
|
760
|
+
"/api/auth/agent-token",
|
|
761
|
+
"mint the app-specific agent token",
|
|
762
|
+
JSON.stringify({ target: target2 })
|
|
763
|
+
);
|
|
764
|
+
}
|
|
747
765
|
|
|
748
766
|
// src/cli/lib/secure-file.ts
|
|
749
767
|
import { chmodSync, writeFileSync } from "fs";
|
|
@@ -814,6 +832,14 @@ function isTokenValid(jwt, minimumValidityMs) {
|
|
|
814
832
|
async function refreshTokenFromSession() {
|
|
815
833
|
return await exchangeStoredSession();
|
|
816
834
|
}
|
|
835
|
+
async function mintAgentToken(target2) {
|
|
836
|
+
if (!existsSync(SESSION_PATH)) throw notAuthenticated("Not logged in");
|
|
837
|
+
const sessionToken = readFileSync2(SESSION_PATH, "utf-8").trim();
|
|
838
|
+
const token = await exchangeAgentSession(AUTH_URL, sessionToken, target2);
|
|
839
|
+
if (!token)
|
|
840
|
+
throw notAuthenticated("The stored session is no longer valid (expired or unreadable)");
|
|
841
|
+
return token;
|
|
842
|
+
}
|
|
817
843
|
async function exchangeStoredSession() {
|
|
818
844
|
if (!existsSync(SESSION_PATH)) return null;
|
|
819
845
|
const sessionToken = readFileSync2(SESSION_PATH, "utf-8").trim();
|
|
@@ -4436,7 +4462,6 @@ function saveTestAccountStore(store) {
|
|
|
4436
4462
|
}
|
|
4437
4463
|
|
|
4438
4464
|
// src/cli/lib/test-account-service.ts
|
|
4439
|
-
var SESSION_COOKIE2 = "__Secure-better-auth.session_token";
|
|
4440
4465
|
var TestAccountServiceError = class extends Error {
|
|
4441
4466
|
constructor(message, code) {
|
|
4442
4467
|
super(message);
|
|
@@ -4449,7 +4474,7 @@ function serviceError(data, fallback) {
|
|
|
4449
4474
|
var AUTH_URL4 = process.env.DEEPSPACE_AUTH_URL ?? PLATFORM_URLS.auth;
|
|
4450
4475
|
function sessionCookie() {
|
|
4451
4476
|
const token = readFileSync12(SESSION_PATH, "utf-8").trim();
|
|
4452
|
-
return `${
|
|
4477
|
+
return `${SESSION_COOKIE}=${encodeURIComponent(token)}`;
|
|
4453
4478
|
}
|
|
4454
4479
|
async function fetchRemoteTestAccounts() {
|
|
4455
4480
|
const response = await fetch(`${AUTH_URL4}/api/auth/test-accounts`, {
|
|
@@ -10975,6 +11000,412 @@ var integrations_default = defineCommand9({
|
|
|
10975
11000
|
}
|
|
10976
11001
|
});
|
|
10977
11002
|
|
|
11003
|
+
// src/cli/commands/agent.ts
|
|
11004
|
+
import { createReadStream } from "fs";
|
|
11005
|
+
import { defineCommand as defineCommand10 } from "citty";
|
|
11006
|
+
|
|
11007
|
+
// src/server/agent-target.ts
|
|
11008
|
+
var PRODUCTION_OFFICIAL_AGENT_ORIGINS = ["https://admin.deep.space"];
|
|
11009
|
+
var PRODUCTION_APP_DOMAIN = "app.space";
|
|
11010
|
+
function normalizeAgentTargetOrigin(value, policy) {
|
|
11011
|
+
if (typeof value !== "string" || !value) return null;
|
|
11012
|
+
let url;
|
|
11013
|
+
try {
|
|
11014
|
+
url = new URL(value);
|
|
11015
|
+
} catch {
|
|
11016
|
+
return null;
|
|
11017
|
+
}
|
|
11018
|
+
if (url.username || url.password || url.search || url.hash || url.pathname !== "/") return null;
|
|
11019
|
+
const hostname = url.hostname.toLowerCase();
|
|
11020
|
+
const loopback = ["localhost", "127.0.0.1", "[::1]"].includes(hostname);
|
|
11021
|
+
if (loopback) {
|
|
11022
|
+
return policy.allowLoopback && ["http:", "https:"].includes(url.protocol) ? url.origin : null;
|
|
11023
|
+
}
|
|
11024
|
+
if (url.protocol !== "https:" || url.port) return null;
|
|
11025
|
+
if (policy.appDomain.toLowerCase() === PRODUCTION_APP_DOMAIN && PRODUCTION_OFFICIAL_AGENT_ORIGINS.includes(url.origin)) {
|
|
11026
|
+
return url.origin;
|
|
11027
|
+
}
|
|
11028
|
+
const suffix = `.${policy.appDomain.toLowerCase()}`;
|
|
11029
|
+
if (!hostname.endsWith(suffix)) return null;
|
|
11030
|
+
const label = hostname.slice(0, -suffix.length);
|
|
11031
|
+
return !label.includes(".") && validateAppName(label).valid ? url.origin : null;
|
|
11032
|
+
}
|
|
11033
|
+
|
|
11034
|
+
// src/shared/bounded-body.ts
|
|
11035
|
+
var BodyTooLargeError = class extends Error {
|
|
11036
|
+
constructor(maxBytes) {
|
|
11037
|
+
super(`Body exceeds ${maxBytes} bytes`);
|
|
11038
|
+
this.maxBytes = maxBytes;
|
|
11039
|
+
this.name = "BodyTooLargeError";
|
|
11040
|
+
}
|
|
11041
|
+
};
|
|
11042
|
+
async function readBoundedBodyText(source, maxBytes) {
|
|
11043
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes <= 0) {
|
|
11044
|
+
throw new TypeError("maxBytes must be a positive safe integer");
|
|
11045
|
+
}
|
|
11046
|
+
const declared = source.headers.get("content-length");
|
|
11047
|
+
if (declared && /^\d+$/.test(declared.trim()) && Number(declared) > maxBytes) {
|
|
11048
|
+
await source.body?.cancel().catch(() => void 0);
|
|
11049
|
+
throw new BodyTooLargeError(maxBytes);
|
|
11050
|
+
}
|
|
11051
|
+
if (!source.body) return "";
|
|
11052
|
+
const reader = source.body.getReader();
|
|
11053
|
+
const decoder = new TextDecoder();
|
|
11054
|
+
let bytes = 0;
|
|
11055
|
+
let text2 = "";
|
|
11056
|
+
try {
|
|
11057
|
+
while (true) {
|
|
11058
|
+
const chunk = await reader.read();
|
|
11059
|
+
if (chunk.done) break;
|
|
11060
|
+
bytes += chunk.value.byteLength;
|
|
11061
|
+
if (bytes > maxBytes) {
|
|
11062
|
+
await reader.cancel().catch(() => void 0);
|
|
11063
|
+
throw new BodyTooLargeError(maxBytes);
|
|
11064
|
+
}
|
|
11065
|
+
text2 += decoder.decode(chunk.value, { stream: true });
|
|
11066
|
+
}
|
|
11067
|
+
return text2 + decoder.decode();
|
|
11068
|
+
} finally {
|
|
11069
|
+
reader.releaseLock();
|
|
11070
|
+
}
|
|
11071
|
+
}
|
|
11072
|
+
|
|
11073
|
+
// src/shared/agent-tool-protocol.ts
|
|
11074
|
+
var AGENT_TOOL_REQUEST_BODY_CAP = 64 * 1024;
|
|
11075
|
+
var AGENT_TOOL_RESPONSE_BODY_CAP = 1024 * 1024;
|
|
11076
|
+
|
|
11077
|
+
// src/cli/commands/agent.ts
|
|
11078
|
+
var DEFAULT_TIMEOUT_MS2 = 12e4;
|
|
11079
|
+
var MAX_TIMEOUT_MS = 6e5;
|
|
11080
|
+
var MAX_INPUT_BYTES = AGENT_TOOL_REQUEST_BODY_CAP;
|
|
11081
|
+
var MAX_RESPONSE_BYTES = AGENT_TOOL_RESPONSE_BODY_CAP;
|
|
11082
|
+
function badApp(message) {
|
|
11083
|
+
throw new Refusal(message, "invalid_agent_app");
|
|
11084
|
+
}
|
|
11085
|
+
function isCanonicalAppLabel(value) {
|
|
11086
|
+
return value.length >= APP_NAME_RULES.minLength && value.length <= APP_NAME_RULES.maxLength && APP_NAME_RULES.pattern.test(value);
|
|
11087
|
+
}
|
|
11088
|
+
function resolveAgentTarget(app2, plane = DEEPSPACE_ENV) {
|
|
11089
|
+
if (typeof app2 !== "string" || !app2)
|
|
11090
|
+
badApp("App must be a canonical app name or canonical app URL.");
|
|
11091
|
+
const appDomain = appDomainForEnv(plane);
|
|
11092
|
+
if (!appDomain) badApp("The selected DeepSpace environment is invalid.");
|
|
11093
|
+
if (app2.toLowerCase() === "localhost") {
|
|
11094
|
+
badApp("Pass an explicit loopback URL for local development (e.g. 'http://localhost:8787').");
|
|
11095
|
+
}
|
|
11096
|
+
if (isCanonicalAppLabel(app2)) {
|
|
11097
|
+
return { url: `https://${app2}.${appDomain}` };
|
|
11098
|
+
}
|
|
11099
|
+
const url = normalizeAgentTargetOrigin(app2, {
|
|
11100
|
+
appDomain,
|
|
11101
|
+
allowLoopback: true
|
|
11102
|
+
});
|
|
11103
|
+
if (!url) {
|
|
11104
|
+
badApp(
|
|
11105
|
+
"App URL must be an exact canonical app origin (or a root loopback URL for local development)."
|
|
11106
|
+
);
|
|
11107
|
+
}
|
|
11108
|
+
return { url };
|
|
11109
|
+
}
|
|
11110
|
+
function parseAgentTimeout(raw) {
|
|
11111
|
+
if (raw == null) return DEFAULT_TIMEOUT_MS2;
|
|
11112
|
+
const value = typeof raw === "number" ? raw : Number(raw);
|
|
11113
|
+
if (!Number.isInteger(value) || value <= 0 || value > MAX_TIMEOUT_MS) {
|
|
11114
|
+
throw new Refusal(
|
|
11115
|
+
`Invalid --timeout '${String(raw)}'. Must be a positive integer up to ${MAX_TIMEOUT_MS} milliseconds.`,
|
|
11116
|
+
"invalid_timeout"
|
|
11117
|
+
);
|
|
11118
|
+
}
|
|
11119
|
+
return value;
|
|
11120
|
+
}
|
|
11121
|
+
function assertInputSize(value) {
|
|
11122
|
+
if (Buffer.byteLength(value) > MAX_INPUT_BYTES) {
|
|
11123
|
+
throw new Refusal(`Input exceeds the ${MAX_INPUT_BYTES}-byte limit.`, "input_too_large");
|
|
11124
|
+
}
|
|
11125
|
+
}
|
|
11126
|
+
function serializeAgentInput(input) {
|
|
11127
|
+
const body = JSON.stringify({ input });
|
|
11128
|
+
if (Buffer.byteLength(body) > AGENT_TOOL_REQUEST_BODY_CAP) {
|
|
11129
|
+
throw new Refusal(
|
|
11130
|
+
`Tool request exceeds the ${AGENT_TOOL_REQUEST_BODY_CAP}-byte limit.`,
|
|
11131
|
+
"input_too_large"
|
|
11132
|
+
);
|
|
11133
|
+
}
|
|
11134
|
+
return body;
|
|
11135
|
+
}
|
|
11136
|
+
async function readBoundedLocalInput(source) {
|
|
11137
|
+
const chunks = [];
|
|
11138
|
+
let size = 0;
|
|
11139
|
+
for await (const chunk of source) {
|
|
11140
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
11141
|
+
size += buffer.length;
|
|
11142
|
+
if (size > MAX_INPUT_BYTES) {
|
|
11143
|
+
throw new Refusal(`Input exceeds the ${MAX_INPUT_BYTES}-byte limit.`, "input_too_large");
|
|
11144
|
+
}
|
|
11145
|
+
chunks.push(buffer);
|
|
11146
|
+
}
|
|
11147
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
11148
|
+
}
|
|
11149
|
+
async function resolveAgentInput(opts) {
|
|
11150
|
+
if (opts.input != null && opts.inputFile != null) {
|
|
11151
|
+
throw new Refusal("Pass either --input or --input-file, not both.", "conflicting_input_args");
|
|
11152
|
+
}
|
|
11153
|
+
let raw = "{}";
|
|
11154
|
+
if (opts.input != null) {
|
|
11155
|
+
raw = opts.input;
|
|
11156
|
+
assertInputSize(raw);
|
|
11157
|
+
} else if (opts.inputFile != null) {
|
|
11158
|
+
if (opts.inputFile === "-") {
|
|
11159
|
+
raw = await readBoundedLocalInput(process.stdin);
|
|
11160
|
+
} else {
|
|
11161
|
+
try {
|
|
11162
|
+
raw = await readBoundedLocalInput(createReadStream(opts.inputFile));
|
|
11163
|
+
} catch (error) {
|
|
11164
|
+
if (error instanceof Refusal) throw error;
|
|
11165
|
+
throw new Refusal(`Could not read input file '${opts.inputFile}'.`, "input_file_unreadable");
|
|
11166
|
+
}
|
|
11167
|
+
}
|
|
11168
|
+
}
|
|
11169
|
+
try {
|
|
11170
|
+
return JSON.parse(raw);
|
|
11171
|
+
} catch {
|
|
11172
|
+
throw new Refusal("Input is not valid JSON.", "invalid_input_json");
|
|
11173
|
+
}
|
|
11174
|
+
}
|
|
11175
|
+
function isRecord(value) {
|
|
11176
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11177
|
+
}
|
|
11178
|
+
function validApp(value) {
|
|
11179
|
+
return isRecord(value) && typeof value.id === "string" && typeof value.name === "string";
|
|
11180
|
+
}
|
|
11181
|
+
function validTool(value) {
|
|
11182
|
+
return isRecord(value) && typeof value.name === "string" && typeof value.description === "string" && Object.prototype.hasOwnProperty.call(value, "inputSchema");
|
|
11183
|
+
}
|
|
11184
|
+
function parseToolsResponse(value) {
|
|
11185
|
+
if (!isRecord(value) || value.ok !== true || !validApp(value.app) || !Array.isArray(value.tools)) {
|
|
11186
|
+
throw new Refusal("The app returned an unexpected tools response.", "invalid_agent_response");
|
|
11187
|
+
}
|
|
11188
|
+
if (!value.tools.every(validTool)) {
|
|
11189
|
+
throw new Refusal("The app returned an invalid tool definition.", "invalid_agent_response");
|
|
11190
|
+
}
|
|
11191
|
+
return { ok: true, app: value.app, tools: value.tools };
|
|
11192
|
+
}
|
|
11193
|
+
function parseInvokeResponse(value) {
|
|
11194
|
+
if (!isRecord(value) || value.ok !== true || !Object.prototype.hasOwnProperty.call(value, "result")) {
|
|
11195
|
+
throw new Refusal("The app returned an unexpected tool response.", "invalid_agent_response");
|
|
11196
|
+
}
|
|
11197
|
+
return { ok: true, result: value.result };
|
|
11198
|
+
}
|
|
11199
|
+
function safeServerCode(value) {
|
|
11200
|
+
return typeof value === "string" && /^[a-z][a-z0-9_]{0,63}$/.test(value) ? value : void 0;
|
|
11201
|
+
}
|
|
11202
|
+
function redact(value, tokens) {
|
|
11203
|
+
return tokens.reduce(
|
|
11204
|
+
(text2, token) => token ? text2.split(token).join("[redacted]") : text2,
|
|
11205
|
+
value
|
|
11206
|
+
);
|
|
11207
|
+
}
|
|
11208
|
+
function redactValue(value, tokens) {
|
|
11209
|
+
if (typeof value === "string") return redact(value, tokens);
|
|
11210
|
+
if (Array.isArray(value)) return value.map((item) => redactValue(item, tokens));
|
|
11211
|
+
if (isRecord(value)) {
|
|
11212
|
+
return Object.fromEntries(
|
|
11213
|
+
Object.entries(value).map(([key, item]) => [redact(key, tokens), redactValue(item, tokens)])
|
|
11214
|
+
);
|
|
11215
|
+
}
|
|
11216
|
+
return value;
|
|
11217
|
+
}
|
|
11218
|
+
async function readResponseText(response) {
|
|
11219
|
+
try {
|
|
11220
|
+
return await readBoundedBodyText(response, MAX_RESPONSE_BYTES);
|
|
11221
|
+
} catch (error) {
|
|
11222
|
+
if (error instanceof BodyTooLargeError) {
|
|
11223
|
+
throw new Refusal(
|
|
11224
|
+
`App response exceeds the ${MAX_RESPONSE_BYTES}-byte limit.`,
|
|
11225
|
+
"response_too_large"
|
|
11226
|
+
);
|
|
11227
|
+
}
|
|
11228
|
+
throw error;
|
|
11229
|
+
}
|
|
11230
|
+
}
|
|
11231
|
+
async function requestJson(url, init, token, timeout) {
|
|
11232
|
+
const controller = new AbortController();
|
|
11233
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
11234
|
+
try {
|
|
11235
|
+
let response;
|
|
11236
|
+
try {
|
|
11237
|
+
response = await fetch(url, {
|
|
11238
|
+
...init,
|
|
11239
|
+
headers: { ...init.headers, authorization: `Bearer ${token}` },
|
|
11240
|
+
redirect: "manual",
|
|
11241
|
+
signal: controller.signal
|
|
11242
|
+
});
|
|
11243
|
+
} catch (error) {
|
|
11244
|
+
if (controller.signal.aborted || error instanceof Error && error.name === "AbortError") {
|
|
11245
|
+
throw new Refusal(`Request timed out after ${timeout}ms.`, "agent_timeout");
|
|
11246
|
+
}
|
|
11247
|
+
throw new Refusal("Could not reach the app agent endpoint.", "agent_network_error");
|
|
11248
|
+
}
|
|
11249
|
+
if (response.status >= 300 && response.status < 400) {
|
|
11250
|
+
await response.body?.cancel().catch(() => void 0);
|
|
11251
|
+
throw new Refusal(
|
|
11252
|
+
"App agent endpoint redirected; refusing to forward credentials.",
|
|
11253
|
+
"agent_redirect_refused"
|
|
11254
|
+
);
|
|
11255
|
+
}
|
|
11256
|
+
let text2;
|
|
11257
|
+
try {
|
|
11258
|
+
text2 = await readResponseText(response);
|
|
11259
|
+
} catch (error) {
|
|
11260
|
+
if (error instanceof Refusal) throw error;
|
|
11261
|
+
if (controller.signal.aborted || error instanceof Error && error.name === "AbortError") {
|
|
11262
|
+
throw new Refusal(`Request timed out after ${timeout}ms.`, "agent_timeout");
|
|
11263
|
+
}
|
|
11264
|
+
throw new Refusal("Could not read the app agent response.", "agent_network_error");
|
|
11265
|
+
}
|
|
11266
|
+
let body = null;
|
|
11267
|
+
if (text2) {
|
|
11268
|
+
try {
|
|
11269
|
+
body = JSON.parse(text2);
|
|
11270
|
+
} catch {
|
|
11271
|
+
if (response.ok)
|
|
11272
|
+
throw new Refusal("The app returned a non-JSON response.", "invalid_agent_response");
|
|
11273
|
+
}
|
|
11274
|
+
}
|
|
11275
|
+
return { status: response.status, body, text: text2 };
|
|
11276
|
+
} finally {
|
|
11277
|
+
clearTimeout(timer);
|
|
11278
|
+
}
|
|
11279
|
+
}
|
|
11280
|
+
function httpRefusal(response, tokens) {
|
|
11281
|
+
const server = isRecord(response.body) ? response.body : void 0;
|
|
11282
|
+
const code = safeServerCode(server?.code);
|
|
11283
|
+
const message = typeof server?.error === "string" ? redact(server.error, tokens).slice(0, 500) : "";
|
|
11284
|
+
if (response.status === 403) {
|
|
11285
|
+
return new Refusal(
|
|
11286
|
+
message || "You are not allowed to use this app agent.",
|
|
11287
|
+
code ?? "agent_forbidden"
|
|
11288
|
+
);
|
|
11289
|
+
}
|
|
11290
|
+
if (response.status === 404 && !server) {
|
|
11291
|
+
return new Refusal(
|
|
11292
|
+
"This app does not expose the requested agent endpoint.",
|
|
11293
|
+
"agent_endpoint_not_found"
|
|
11294
|
+
);
|
|
11295
|
+
}
|
|
11296
|
+
return new Refusal(
|
|
11297
|
+
message || `App agent request failed (${response.status}).`,
|
|
11298
|
+
code ?? (response.status === 404 ? "agent_endpoint_not_found" : "agent_request_failed")
|
|
11299
|
+
);
|
|
11300
|
+
}
|
|
11301
|
+
async function callAgent(target2, path, init, timeout) {
|
|
11302
|
+
let token = await mintAgentToken(target2.url);
|
|
11303
|
+
const tokens = [token];
|
|
11304
|
+
let retried = false;
|
|
11305
|
+
for (; ; ) {
|
|
11306
|
+
const response = await requestJson(`${target2.url}${path}`, init, token, timeout);
|
|
11307
|
+
if (response.status !== 401) {
|
|
11308
|
+
if (response.status < 200 || response.status >= 300) throw httpRefusal(response, tokens);
|
|
11309
|
+
return redactValue(response.body, tokens);
|
|
11310
|
+
}
|
|
11311
|
+
if (!retried) {
|
|
11312
|
+
retried = true;
|
|
11313
|
+
token = await mintAgentToken(target2.url);
|
|
11314
|
+
tokens.push(token);
|
|
11315
|
+
continue;
|
|
11316
|
+
}
|
|
11317
|
+
throw new Refusal(
|
|
11318
|
+
"Authentication was rejected. Run `deepspace auth login` and try again.",
|
|
11319
|
+
"not_authenticated",
|
|
11320
|
+
{ action: cliAction("deepspace", "auth", "login") }
|
|
11321
|
+
);
|
|
11322
|
+
}
|
|
11323
|
+
}
|
|
11324
|
+
async function runAgentTools(args) {
|
|
11325
|
+
const target2 = resolveAgentTarget(args.app);
|
|
11326
|
+
const body = parseToolsResponse(
|
|
11327
|
+
await callAgent(target2, "/_deepspace/agent/tools", { method: "GET" }, DEFAULT_TIMEOUT_MS2)
|
|
11328
|
+
);
|
|
11329
|
+
if (!args.json) {
|
|
11330
|
+
console.log(`App: ${body.app.name} (${body.app.id}, ${target2.url})`);
|
|
11331
|
+
if (body.tools.length === 0) console.log("Tools: none");
|
|
11332
|
+
else {
|
|
11333
|
+
console.log("Tools:");
|
|
11334
|
+
for (const tool of body.tools) {
|
|
11335
|
+
console.log(`- ${tool.name}: ${tool.description}`);
|
|
11336
|
+
console.log(` Input: ${JSON.stringify(tool.inputSchema)}`);
|
|
11337
|
+
if (tool.outputSchema !== void 0) {
|
|
11338
|
+
console.log(` Output: ${JSON.stringify(tool.outputSchema)}`);
|
|
11339
|
+
}
|
|
11340
|
+
}
|
|
11341
|
+
}
|
|
11342
|
+
}
|
|
11343
|
+
return { data: { app: body.app, url: target2.url, tools: body.tools } };
|
|
11344
|
+
}
|
|
11345
|
+
async function runAgentInvoke(args) {
|
|
11346
|
+
const target2 = resolveAgentTarget(args.app);
|
|
11347
|
+
const input = await resolveAgentInput({ input: args.input, inputFile: args.inputFile });
|
|
11348
|
+
const tool = args.tool;
|
|
11349
|
+
if (typeof tool !== "string" || !tool)
|
|
11350
|
+
throw new Refusal("Tool name is required.", "invalid_agent_tool");
|
|
11351
|
+
const requestBody = serializeAgentInput(input);
|
|
11352
|
+
const body = parseInvokeResponse(
|
|
11353
|
+
await callAgent(
|
|
11354
|
+
target2,
|
|
11355
|
+
`/_deepspace/agent/tools/${encodeURIComponent(tool)}`,
|
|
11356
|
+
{
|
|
11357
|
+
method: "POST",
|
|
11358
|
+
headers: { "content-type": "application/json" },
|
|
11359
|
+
body: requestBody
|
|
11360
|
+
},
|
|
11361
|
+
parseAgentTimeout(args.timeout)
|
|
11362
|
+
)
|
|
11363
|
+
);
|
|
11364
|
+
if (!args.json) {
|
|
11365
|
+
console.log(`App: ${args.app} (${target2.url})`);
|
|
11366
|
+
console.log(`Tool: ${tool}`);
|
|
11367
|
+
console.log("Result:");
|
|
11368
|
+
console.log(JSON.stringify(body.result, null, 2));
|
|
11369
|
+
}
|
|
11370
|
+
return { data: { app: args.app, url: target2.url, tool, result: body.result } };
|
|
11371
|
+
}
|
|
11372
|
+
var tools = defineDeepspaceCommand({
|
|
11373
|
+
meta: { name: "tools", description: "List the agent tools exposed by an app" },
|
|
11374
|
+
args: {
|
|
11375
|
+
app: { type: "positional", description: "Canonical app name or URL", required: true }
|
|
11376
|
+
},
|
|
11377
|
+
async run({ args }) {
|
|
11378
|
+
return runAgentTools({ app: args.app, json: args.json });
|
|
11379
|
+
}
|
|
11380
|
+
});
|
|
11381
|
+
var invoke2 = defineDeepspaceCommand({
|
|
11382
|
+
meta: { name: "invoke", description: "Invoke an agent tool exposed by an app" },
|
|
11383
|
+
args: {
|
|
11384
|
+
app: { type: "positional", description: "Canonical app name or URL", required: true },
|
|
11385
|
+
tool: { type: "positional", description: "Tool name", required: true },
|
|
11386
|
+
input: { type: "string", description: "Inline JSON tool input" },
|
|
11387
|
+
"input-file": { type: "string", description: "JSON input file (use - for stdin)" },
|
|
11388
|
+
timeout: {
|
|
11389
|
+
type: "string",
|
|
11390
|
+
description: `Request timeout in milliseconds (default: ${DEFAULT_TIMEOUT_MS2})`
|
|
11391
|
+
}
|
|
11392
|
+
},
|
|
11393
|
+
async run({ args }) {
|
|
11394
|
+
return runAgentInvoke({
|
|
11395
|
+
app: args.app,
|
|
11396
|
+
tool: args.tool,
|
|
11397
|
+
input: args.input,
|
|
11398
|
+
inputFile: args["input-file"],
|
|
11399
|
+
timeout: args.timeout,
|
|
11400
|
+
json: args.json
|
|
11401
|
+
});
|
|
11402
|
+
}
|
|
11403
|
+
});
|
|
11404
|
+
var agent_default = defineCommand10({
|
|
11405
|
+
meta: { name: "agent", description: "List and invoke an app\u2019s stateless local agent tools" },
|
|
11406
|
+
subCommands: { tools, invoke: invoke2 }
|
|
11407
|
+
});
|
|
11408
|
+
|
|
10978
11409
|
// src/cli/commands/feedback.ts
|
|
10979
11410
|
import * as p16 from "@clack/prompts";
|
|
10980
11411
|
import { existsSync as existsSync25, readFileSync as readFileSync21 } from "fs";
|
|
@@ -11201,7 +11632,7 @@ Context: deepspace ${payload.cliVersion} \xB7 ${payload.nodeVersion} \xB7 ${payl
|
|
|
11201
11632
|
});
|
|
11202
11633
|
|
|
11203
11634
|
// src/cli/commands/secrets.ts
|
|
11204
|
-
import { defineCommand as
|
|
11635
|
+
import { defineCommand as defineCommand11 } from "citty";
|
|
11205
11636
|
import { readFileSync as readFileSync22 } from "fs";
|
|
11206
11637
|
|
|
11207
11638
|
// src/cli/lib/citty-args.ts
|
|
@@ -11284,7 +11715,7 @@ function warnIfDebugRoutesEnabled(secrets) {
|
|
|
11284
11715
|
var APPLY_HINT = "Run `deepspace deploy` to apply \u2014 secrets take effect at deploy time.";
|
|
11285
11716
|
var APPLIES_AT_DEPLOY = { appliesAtDeploy: true, devRestartRequired: true };
|
|
11286
11717
|
var LOCAL_DEV_HINT = "Running `deepspace dev start`? Restart it to load the change locally.";
|
|
11287
|
-
var list6 =
|
|
11718
|
+
var list6 = defineCommand11({
|
|
11288
11719
|
meta: { name: "list", description: "List masked secrets in a config" },
|
|
11289
11720
|
args: {
|
|
11290
11721
|
...COMMON_ARGS,
|
|
@@ -11310,7 +11741,7 @@ var list6 = defineCommand10({
|
|
|
11310
11741
|
}
|
|
11311
11742
|
}
|
|
11312
11743
|
});
|
|
11313
|
-
var set =
|
|
11744
|
+
var set = defineCommand11({
|
|
11314
11745
|
meta: { name: "set", description: "Set secrets from KEY=value pairs, or KEY --stdin" },
|
|
11315
11746
|
args: {
|
|
11316
11747
|
...COMMON_ARGS,
|
|
@@ -11394,7 +11825,7 @@ var set = defineCommand10({
|
|
|
11394
11825
|
);
|
|
11395
11826
|
}
|
|
11396
11827
|
});
|
|
11397
|
-
var get2 =
|
|
11828
|
+
var get2 = defineCommand11({
|
|
11398
11829
|
meta: { name: "get", description: "Get a secret; pass --plain to print the value" },
|
|
11399
11830
|
args: {
|
|
11400
11831
|
...COMMON_ARGS,
|
|
@@ -11432,7 +11863,7 @@ var get2 = defineCommand10({
|
|
|
11432
11863
|
);
|
|
11433
11864
|
}
|
|
11434
11865
|
});
|
|
11435
|
-
var del2 =
|
|
11866
|
+
var del2 = defineCommand11({
|
|
11436
11867
|
meta: { name: "delete", description: "Delete one or more secrets" },
|
|
11437
11868
|
args: {
|
|
11438
11869
|
...COMMON_ARGS,
|
|
@@ -11468,7 +11899,7 @@ var del2 = defineCommand10({
|
|
|
11468
11899
|
);
|
|
11469
11900
|
}
|
|
11470
11901
|
});
|
|
11471
|
-
var upload =
|
|
11902
|
+
var upload = defineCommand11({
|
|
11472
11903
|
meta: { name: "upload", description: "Upload secrets from a dotenv or JSON file" },
|
|
11473
11904
|
args: {
|
|
11474
11905
|
...COMMON_ARGS,
|
|
@@ -11527,7 +11958,7 @@ async function readUploadSource(file) {
|
|
|
11527
11958
|
);
|
|
11528
11959
|
}
|
|
11529
11960
|
}
|
|
11530
|
-
var download =
|
|
11961
|
+
var download = defineCommand11({
|
|
11531
11962
|
meta: { name: "download", description: "Download a config\u2019s secrets (dotenv/json/shell)" },
|
|
11532
11963
|
args: {
|
|
11533
11964
|
...COMMON_ARGS,
|
|
@@ -11567,7 +11998,7 @@ var download = defineCommand10({
|
|
|
11567
11998
|
process.stdout.write(formatSecretsDownload(secrets, format));
|
|
11568
11999
|
}
|
|
11569
12000
|
});
|
|
11570
|
-
var pull =
|
|
12001
|
+
var pull = defineCommand11({
|
|
11571
12002
|
meta: { name: "pull", description: "Refresh the .dev.vars cache from the app store" },
|
|
11572
12003
|
args: { ...COMMON_ARGS },
|
|
11573
12004
|
async run({ args }) {
|
|
@@ -11608,7 +12039,7 @@ var pull = defineCommand10({
|
|
|
11608
12039
|
);
|
|
11609
12040
|
}
|
|
11610
12041
|
});
|
|
11611
|
-
var configsList =
|
|
12042
|
+
var configsList = defineCommand11({
|
|
11612
12043
|
meta: { name: "list", description: "List the app\u2019s configs" },
|
|
11613
12044
|
args: { ...COMMON_ARGS },
|
|
11614
12045
|
async run({ args }) {
|
|
@@ -11625,7 +12056,7 @@ var configsList = defineCommand10({
|
|
|
11625
12056
|
});
|
|
11626
12057
|
}
|
|
11627
12058
|
});
|
|
11628
|
-
var configsCreate =
|
|
12059
|
+
var configsCreate = defineCommand11({
|
|
11629
12060
|
meta: { name: "create", description: "Create a config (optionally copying another)" },
|
|
11630
12061
|
args: {
|
|
11631
12062
|
...COMMON_ARGS,
|
|
@@ -11659,7 +12090,7 @@ var configsCreate = defineCommand10({
|
|
|
11659
12090
|
);
|
|
11660
12091
|
}
|
|
11661
12092
|
});
|
|
11662
|
-
var configsDelete =
|
|
12093
|
+
var configsDelete = defineCommand11({
|
|
11663
12094
|
meta: { name: "delete", description: "Delete a config and all of its secrets" },
|
|
11664
12095
|
args: {
|
|
11665
12096
|
...COMMON_ARGS,
|
|
@@ -11704,11 +12135,11 @@ var configsDelete = defineCommand10({
|
|
|
11704
12135
|
);
|
|
11705
12136
|
}
|
|
11706
12137
|
});
|
|
11707
|
-
var configs =
|
|
12138
|
+
var configs = defineCommand11({
|
|
11708
12139
|
meta: { name: "configs", description: "Manage the app\u2019s secrets configs" },
|
|
11709
12140
|
subCommands: { list: configsList, create: configsCreate, delete: configsDelete }
|
|
11710
12141
|
});
|
|
11711
|
-
var secrets_default =
|
|
12142
|
+
var secrets_default = defineCommand11({
|
|
11712
12143
|
meta: { name: "secrets", description: "Manage the app\u2019s secrets store" },
|
|
11713
12144
|
subCommands: {
|
|
11714
12145
|
list: list6,
|
|
@@ -11869,7 +12300,7 @@ var init_default = defineDeepspaceCommand({
|
|
|
11869
12300
|
});
|
|
11870
12301
|
|
|
11871
12302
|
// src/cli/commands/status.ts
|
|
11872
|
-
import { defineCommand as
|
|
12303
|
+
import { defineCommand as defineCommand12 } from "citty";
|
|
11873
12304
|
import * as p17 from "@clack/prompts";
|
|
11874
12305
|
import { existsSync as existsSync26, readFileSync as readFileSync23 } from "fs";
|
|
11875
12306
|
function timeAgo(iso) {
|
|
@@ -11913,7 +12344,7 @@ function resolveStatusApp(appDir, wranglerEnv) {
|
|
|
11913
12344
|
return { appName, appId: null, appIdError: err.message };
|
|
11914
12345
|
}
|
|
11915
12346
|
}
|
|
11916
|
-
var status_default =
|
|
12347
|
+
var status_default = defineCommand12({
|
|
11917
12348
|
meta: {
|
|
11918
12349
|
name: "status",
|
|
11919
12350
|
description: "One screenful of current state \u2014 always names the platform plane (env, services) \u2014 plus session, app, workspace, and live release"
|
|
@@ -13156,7 +13587,7 @@ Re-run with --allow-do-deletion to accept the data loss.`,
|
|
|
13156
13587
|
});
|
|
13157
13588
|
|
|
13158
13589
|
// src/cli/commands/workspace.ts
|
|
13159
|
-
import { defineCommand as
|
|
13590
|
+
import { defineCommand as defineCommand13 } from "citty";
|
|
13160
13591
|
|
|
13161
13592
|
// src/cli/commands/workspace/new.ts
|
|
13162
13593
|
import * as p25 from "@clack/prompts";
|
|
@@ -15048,7 +15479,7 @@ var dropWorkspaceCommand = defineDeepspaceCommand({
|
|
|
15048
15479
|
});
|
|
15049
15480
|
|
|
15050
15481
|
// src/cli/commands/workspace.ts
|
|
15051
|
-
var workspace_default =
|
|
15482
|
+
var workspace_default = defineCommand13({
|
|
15052
15483
|
meta: {
|
|
15053
15484
|
name: "workspace",
|
|
15054
15485
|
description: "Durable parallel-agent workspaces (new/attach/sync/list/status/land/drop)"
|
|
@@ -15227,7 +15658,7 @@ var activity_default = defineDeepspaceCommand({
|
|
|
15227
15658
|
});
|
|
15228
15659
|
|
|
15229
15660
|
// src/cli/commands/git-credential.ts
|
|
15230
|
-
import { defineCommand as
|
|
15661
|
+
import { defineCommand as defineCommand14 } from "citty";
|
|
15231
15662
|
function parseFields(input) {
|
|
15232
15663
|
const fields = /* @__PURE__ */ new Map();
|
|
15233
15664
|
for (const line of input.split("\n")) {
|
|
@@ -15269,7 +15700,7 @@ function declineHint(op, input, token, deployUrl) {
|
|
|
15269
15700
|
}
|
|
15270
15701
|
return "";
|
|
15271
15702
|
}
|
|
15272
|
-
var git_credential_default =
|
|
15703
|
+
var git_credential_default = defineCommand14({
|
|
15273
15704
|
meta: {
|
|
15274
15705
|
name: "git-credential",
|
|
15275
15706
|
description: "Git credential helper (installed automatically; not for direct use)"
|
|
@@ -15378,7 +15809,7 @@ import { join as join28, resolve as resolve22 } from "path";
|
|
|
15378
15809
|
// package.json
|
|
15379
15810
|
var package_default = {
|
|
15380
15811
|
name: "deepspace",
|
|
15381
|
-
version: "0.28.
|
|
15812
|
+
version: "0.28.1",
|
|
15382
15813
|
engines: {
|
|
15383
15814
|
node: ">=22.15.0 <23 || >=24 <25 || >=26 <27"
|
|
15384
15815
|
},
|
|
@@ -15700,7 +16131,7 @@ var pkg = JSON.parse(readFileSync27(join29(__dirname, "..", "package.json"), "ut
|
|
|
15700
16131
|
if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync31("/etc/ssl/certs/ca-certificates.crt")) {
|
|
15701
16132
|
process.env.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
|
|
15702
16133
|
}
|
|
15703
|
-
var create2 =
|
|
16134
|
+
var create2 = defineCommand15({
|
|
15704
16135
|
meta: {
|
|
15705
16136
|
name: "create",
|
|
15706
16137
|
description: "Create a new DeepSpace app (runs create-deepspace; all flags are forwarded)"
|
|
@@ -15749,11 +16180,11 @@ var create2 = defineCommand14({
|
|
|
15749
16180
|
}
|
|
15750
16181
|
});
|
|
15751
16182
|
var rename = (cmd, name) => ({ ...cmd, meta: { ...cmd.meta ?? {}, name } });
|
|
15752
|
-
var auth =
|
|
16183
|
+
var auth = defineCommand15({
|
|
15753
16184
|
meta: { name: "auth", description: "Session: login, logout, whoami" },
|
|
15754
16185
|
subCommands: { login: login_default, logout: logout_default, whoami: whoami_default }
|
|
15755
16186
|
});
|
|
15756
|
-
var app =
|
|
16187
|
+
var app = defineCommand15({
|
|
15757
16188
|
meta: {
|
|
15758
16189
|
name: "app",
|
|
15759
16190
|
description: "The app itself: create, init, list, files, source, update, undeploy, transfer, collaborators, domain, usage"
|
|
@@ -15772,11 +16203,11 @@ var app = defineCommand14({
|
|
|
15772
16203
|
update: update_default
|
|
15773
16204
|
}
|
|
15774
16205
|
});
|
|
15775
|
-
var devGroup =
|
|
16206
|
+
var devGroup = defineCommand15({
|
|
15776
16207
|
meta: { name: "dev", description: "Local development" },
|
|
15777
16208
|
subCommands: { start: rename(dev_default, "start"), kill: kill_default }
|
|
15778
16209
|
});
|
|
15779
|
-
var testGroup =
|
|
16210
|
+
var testGroup = defineCommand15({
|
|
15780
16211
|
meta: { name: "test", description: "App tests and test tooling" },
|
|
15781
16212
|
subCommands: {
|
|
15782
16213
|
run: rename(test_default, "run"),
|
|
@@ -15784,7 +16215,7 @@ var testGroup = defineCommand14({
|
|
|
15784
16215
|
accounts: rename(test_accounts_default, "accounts")
|
|
15785
16216
|
}
|
|
15786
16217
|
});
|
|
15787
|
-
var main =
|
|
16218
|
+
var main = defineCommand15({
|
|
15788
16219
|
meta: {
|
|
15789
16220
|
name: "deepspace",
|
|
15790
16221
|
version: pkg.version,
|
|
@@ -15810,6 +16241,7 @@ var main = defineCommand14({
|
|
|
15810
16241
|
add: add_default,
|
|
15811
16242
|
secrets: secrets_default,
|
|
15812
16243
|
integrations: integrations_default,
|
|
16244
|
+
agent: agent_default,
|
|
15813
16245
|
auth,
|
|
15814
16246
|
app,
|
|
15815
16247
|
feedback: feedback_default,
|