@openagentpack/playground 0.0.2 → 0.2.0-beta-ddef91c-20260720

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.
@@ -3,7 +3,7 @@
3
3
  // src/server.ts
4
4
  import "@hono/zod-openapi";
5
5
  import { readFileSync } from "fs";
6
- import { dirname as dirname2, join } from "path";
6
+ import { dirname as dirname3, join as join2 } from "path";
7
7
  import { fileURLToPath } from "url";
8
8
  import { serve } from "@hono/node-server";
9
9
  import { serveStatic } from "@hono/node-server/serve-static";
@@ -1052,109 +1052,6 @@ function localizedDescription(template) {
1052
1052
  return names.zh ?? names.en ?? Object.values(names)[0] ?? template.id;
1053
1053
  }
1054
1054
 
1055
- // ../playbooks/src/session-runtime.ts
1056
- function playbookIdentityMismatchMessage(playbookId) {
1057
- return `\u73A9\u6CD5\u300C${playbookId}\u300D\u5B58\u5728\u540C\u5E94\u7528\u540C\u540D Agent\uFF0C\u4F46 metadata.${PLAYBOOK_APP_METADATA_KEY}/${PLAYBOOK_METADATA_KEY} \u672A\u5BF9\u4E0A\uFF0C\u7591\u4F3C\u8EAB\u4EFD\u672A\u76D6\u7AE0\uFF1B\u8BF7\u68C0\u67E5\u914D\u7F6E\u800C\u975E\u91CD\u590D\u521B\u5EFA\u3002`;
1058
- }
1059
- var PlaybookAgentIdentityMismatchError = class extends Error {
1060
- constructor(playbookId) {
1061
- super(playbookIdentityMismatchMessage(playbookId));
1062
- this.name = "PlaybookAgentIdentityMismatchError";
1063
- }
1064
- };
1065
- function pickPlaybookAgent(agents, input) {
1066
- const matched = agents.filter(
1067
- (agent2) => (input.includeArchived || !isArchived(agent2)) && agent2.metadata?.[PLAYBOOK_APP_METADATA_KEY] === input.appId && agent2.metadata?.[PLAYBOOK_METADATA_KEY] === input.playbookId
1068
- );
1069
- if (matched.length <= 1) {
1070
- return {
1071
- agent: matched[0],
1072
- duplicates: [],
1073
- identityMismatch: matched.length === 0 && hasSameNameCurrentAppAgent(agents, input)
1074
- };
1075
- }
1076
- const sorted = [...matched].sort((a, b) => epochOf(updatedAtOf(b)) - epochOf(updatedAtOf(a)));
1077
- const [agent, ...duplicates] = sorted;
1078
- return { agent, duplicates, identityMismatch: false };
1079
- }
1080
- function createPlaybookSessionRuntime(adapters) {
1081
- async function findAgent(playbookId) {
1082
- const [agents, expectedAgentName] = await Promise.all([
1083
- adapters.agents.listPlaybookAgents({ playbookId, includeArchived: false }),
1084
- adapters.identity.expectedAgentName?.(playbookId)
1085
- ]);
1086
- return pickPlaybookAgent(agents, {
1087
- playbookId,
1088
- appId: adapters.identity.appId,
1089
- expectedAgentName
1090
- });
1091
- }
1092
- return {
1093
- async list(input) {
1094
- return adapters.sessions.list(input);
1095
- },
1096
- async getDetail(input) {
1097
- return adapters.sessions.getDetail(input);
1098
- },
1099
- async start(input) {
1100
- const pick = await findAgent(input.playbookId);
1101
- if (pick.identityMismatch) throw new PlaybookAgentIdentityMismatchError(input.playbookId);
1102
- if (pick.agent && pick.duplicates.length) {
1103
- adapters.onDuplicateAgent?.({ playbookId: input.playbookId, winner: pick.agent, duplicates: pick.duplicates });
1104
- }
1105
- const agent = await adapters.agents.ensurePlaybookAgent({
1106
- playbookId: input.playbookId,
1107
- model: input.model,
1108
- matched: pick.agent
1109
- });
1110
- const started = await adapters.sessions.start({ ...input, remoteAgentId: agent.id });
1111
- if (started.events) {
1112
- adapters.events?.attachLiveStream(started.sessionId, started.events, started.completedEvents);
1113
- } else if (started.completedEvents?.length) {
1114
- adapters.events?.seedCompleted(started.sessionId, started.completedEvents);
1115
- }
1116
- return adapters.sessions.getDetail({
1117
- sessionId: started.sessionId,
1118
- playbookId: input.playbookId,
1119
- remoteAgentId: agent.id
1120
- });
1121
- },
1122
- async send(input) {
1123
- const sent = await adapters.sessions.send(input);
1124
- if (sent.events) {
1125
- adapters.events?.attachLiveStream(sent.sessionId, sent.events, sent.completedEvents);
1126
- } else if (sent.completedEvents?.length) {
1127
- adapters.events?.seedCompleted(sent.sessionId, sent.completedEvents);
1128
- }
1129
- return adapters.sessions.getDetail({
1130
- sessionId: sent.sessionId,
1131
- playbookId: input.playbookId
1132
- });
1133
- },
1134
- async delete(input) {
1135
- await adapters.sessions.delete(input);
1136
- }
1137
- };
1138
- }
1139
- function hasSameNameCurrentAppAgent(agents, input) {
1140
- if (!input.expectedAgentName) return false;
1141
- return agents.some(
1142
- (agent) => !isArchived(agent) && agent.metadata?.[PLAYBOOK_APP_METADATA_KEY] === input.appId && agent.name === input.expectedAgentName
1143
- );
1144
- }
1145
- function isArchived(agent) {
1146
- return agent.archivedAt != null || agent.archived_at != null;
1147
- }
1148
- function updatedAtOf(agent) {
1149
- return agent.updatedAt ?? agent.updated_at;
1150
- }
1151
- function epochOf(value) {
1152
- if (value == null) return 0;
1153
- if (typeof value === "number") return value;
1154
- const parsed = Date.parse(value);
1155
- return Number.isNaN(parsed) ? 0 : parsed;
1156
- }
1157
-
1158
1055
  // ../playbooks/src/index.ts
1159
1056
  var PLAYBOOK_SOURCES = {
1160
1057
  bailian: bailian_default,
@@ -1314,7 +1211,7 @@ function compileAgentRuntime(playbookId, baseConfig, modelOverride) {
1314
1211
  const config = cloneConfig(baseConfig);
1315
1212
  const resolved = resolveSeedPlaybook(effectiveId, provider);
1316
1213
  const runtimeAgentId = resolved.agent.name;
1317
- const built = buildAgentDecl(void 0, toAgentBuildInput(resolved, provider, modelOverride));
1214
+ const built = buildAgentDecl(void 0, toAgentBuildInput(resolved, provider, baseConfig, modelOverride));
1318
1215
  config.agents = {
1319
1216
  ...config.agents ?? {},
1320
1217
  [runtimeAgentId]: built.agent
@@ -1373,12 +1270,32 @@ function validateAgent(playbookId, _config) {
1373
1270
  function computeAgentConfigHash(config, agentId) {
1374
1271
  return createHash("sha256").update(stableStringify({ agentId, config })).digest("hex").slice(0, 16);
1375
1272
  }
1376
- function toAgentBuildInput(resolved, provider, modelOverride) {
1273
+ function toAgentBuildInput(resolved, provider, baseConfig, modelOverride) {
1377
1274
  const model = resolvePlaybookModel(resolved, provider, modelOverride);
1275
+ const envKeys = Object.keys(baseConfig.environments ?? {});
1276
+ if (envKeys.length !== 1) {
1277
+ throw new Error(
1278
+ `Expected exactly 1 environment in runtime config, got ${envKeys.length}. The agent compile path assumes a single base environment per provider.`
1279
+ );
1280
+ }
1281
+ const environmentName = envKeys[0];
1282
+ const vaultProfile = getVaultProfile(provider);
1283
+ let vaultName;
1284
+ if (vaultProfile) {
1285
+ const vaultKeys = Object.keys(baseConfig.vaults ?? {});
1286
+ if (vaultKeys.length !== 1) {
1287
+ throw new Error(
1288
+ `Expected exactly 1 vault in runtime config for provider '${provider}', got ${vaultKeys.length}. The agent compile path assumes a single base vault per provider.`
1289
+ );
1290
+ }
1291
+ vaultName = vaultKeys[0];
1292
+ }
1378
1293
  return {
1379
1294
  description: resolved.agent.description,
1380
1295
  model,
1381
1296
  instructions: resolved.agent.system,
1297
+ environment: environmentName,
1298
+ vault: vaultName,
1382
1299
  provider,
1383
1300
  builtinTools: resolved.agent.builtinTools,
1384
1301
  skills: resolved.agent.skills.map(
@@ -1458,13 +1375,15 @@ async function buildRuntimeConfig() {
1458
1375
  // Secret value is injected from env here — never stored in playbooks.
1459
1376
  secret_value: requireEnv(cred.secret_name),
1460
1377
  ...cred.networking ? { networking: cred.networking } : {}
1461
- }))
1378
+ })),
1379
+ metadata: { "agents.vault": "true" }
1462
1380
  }
1463
1381
  } : {};
1464
1382
  const environments = {
1465
1383
  [environment.name]: {
1466
1384
  ...environment.description ? { description: environment.description } : {},
1467
- config: environment.config
1385
+ config: environment.config,
1386
+ metadata: { "agents.base": "true" }
1468
1387
  }
1469
1388
  };
1470
1389
  const rawConfig = {
@@ -1489,12 +1408,47 @@ function requireEnv(name) {
1489
1408
  }
1490
1409
 
1491
1410
  // ../../apps/server/src/lib/state-scope.ts
1492
- import { resolve } from "path";
1411
+ import { copyFileSync, existsSync, mkdirSync, renameSync } from "fs";
1412
+ import { homedir } from "os";
1413
+ import { dirname, join, resolve } from "path";
1493
1414
  import { LocalFileStateBackend } from "@openagentpack/sdk";
1494
- var DEFAULT_STATE_PATH = "examples/bailian/bailian-cli/agents.state.json";
1415
+ var DEFAULT_STATE_PATH = join(homedir(), ".agents", "playground.state.json");
1416
+ var LEGACY_STATE_PATH = "examples/bailian/bailian-cli/agents.state.json";
1417
+ var migrationChecked = false;
1418
+ function ensureMigrated(newPath, cwd) {
1419
+ if (migrationChecked) return;
1420
+ if (existsSync(newPath)) {
1421
+ migrationChecked = true;
1422
+ return;
1423
+ }
1424
+ const legacyPath = resolve(cwd, LEGACY_STATE_PATH);
1425
+ if (!existsSync(legacyPath)) {
1426
+ migrationChecked = true;
1427
+ return;
1428
+ }
1429
+ try {
1430
+ mkdirSync(dirname(newPath), { recursive: true });
1431
+ copyFileSync(legacyPath, newPath);
1432
+ try {
1433
+ renameSync(legacyPath, `${legacyPath}.migrated`);
1434
+ } catch {
1435
+ }
1436
+ migrationChecked = true;
1437
+ console.warn(
1438
+ `[state] Migrated playground state from legacy path:
1439
+ ${legacyPath}
1440
+ \u2192 ${newPath}
1441
+ The legacy file has been renamed to ${legacyPath}.migrated.`
1442
+ );
1443
+ } catch (error) {
1444
+ console.warn(`[state] Failed to migrate legacy state file: ${error instanceof Error ? error.message : error}`);
1445
+ }
1446
+ }
1495
1447
  function resolveStatePath(env = process.env, cwd = process.cwd()) {
1496
1448
  const configured = env.AGENTS_STATE_PATH?.trim();
1497
- return configured ? resolve(cwd, configured) : resolve(cwd, DEFAULT_STATE_PATH);
1449
+ if (configured) return resolve(cwd, configured);
1450
+ ensureMigrated(DEFAULT_STATE_PATH, cwd);
1451
+ return DEFAULT_STATE_PATH;
1498
1452
  }
1499
1453
  function deriveWebUiStateScope() {
1500
1454
  return { projectId: RUNTIME_PROJECT_NAME };
@@ -1633,6 +1587,109 @@ async function importMatchedCloudAgent(input, provider, matched) {
1633
1587
  });
1634
1588
  }
1635
1589
 
1590
+ // ../../apps/server/src/services/sessions/playbook-session-adapter/runtime.ts
1591
+ function playbookIdentityMismatchMessage(playbookId) {
1592
+ return `\u73A9\u6CD5\u300C${playbookId}\u300D\u5B58\u5728\u540C\u5E94\u7528\u540C\u540D Agent\uFF0C\u4F46 metadata.${PLAYBOOK_APP_METADATA_KEY}/${PLAYBOOK_METADATA_KEY} \u672A\u5BF9\u4E0A\uFF0C\u7591\u4F3C\u8EAB\u4EFD\u672A\u76D6\u7AE0\uFF1B\u8BF7\u68C0\u67E5\u914D\u7F6E\u800C\u975E\u91CD\u590D\u521B\u5EFA\u3002`;
1593
+ }
1594
+ var PlaybookAgentIdentityMismatchError = class extends Error {
1595
+ constructor(playbookId) {
1596
+ super(playbookIdentityMismatchMessage(playbookId));
1597
+ this.name = "PlaybookAgentIdentityMismatchError";
1598
+ }
1599
+ };
1600
+ function pickPlaybookAgent(agents, input) {
1601
+ const matched = agents.filter(
1602
+ (agent2) => (input.includeArchived || !isArchived(agent2)) && agent2.metadata?.[PLAYBOOK_APP_METADATA_KEY] === input.appId && agent2.metadata?.[PLAYBOOK_METADATA_KEY] === input.playbookId
1603
+ );
1604
+ if (matched.length <= 1) {
1605
+ return {
1606
+ agent: matched[0],
1607
+ duplicates: [],
1608
+ identityMismatch: matched.length === 0 && hasSameNameCurrentAppAgent(agents, input)
1609
+ };
1610
+ }
1611
+ const sorted = [...matched].sort((a, b) => epochOf(updatedAtOf(b)) - epochOf(updatedAtOf(a)));
1612
+ const [agent, ...duplicates] = sorted;
1613
+ return { agent, duplicates, identityMismatch: false };
1614
+ }
1615
+ function createPlaybookSessionRuntime(deps) {
1616
+ async function findAgent(playbookId) {
1617
+ const [agents, expectedAgentName] = await Promise.all([
1618
+ deps.agents.listPlaybookAgents({ playbookId, includeArchived: false }),
1619
+ deps.identity.expectedAgentName?.(playbookId)
1620
+ ]);
1621
+ return pickPlaybookAgent(agents, {
1622
+ playbookId,
1623
+ appId: deps.identity.appId,
1624
+ expectedAgentName
1625
+ });
1626
+ }
1627
+ return {
1628
+ async list(input) {
1629
+ return deps.sessions.list(input);
1630
+ },
1631
+ async getDetail(input) {
1632
+ return deps.sessions.getDetail(input);
1633
+ },
1634
+ async start(input) {
1635
+ const pick = await findAgent(input.playbookId);
1636
+ if (pick.identityMismatch) throw new PlaybookAgentIdentityMismatchError(input.playbookId);
1637
+ if (pick.agent && pick.duplicates.length) {
1638
+ deps.onDuplicateAgent?.({ playbookId: input.playbookId, winner: pick.agent, duplicates: pick.duplicates });
1639
+ }
1640
+ const agent = await deps.agents.ensurePlaybookAgent({
1641
+ playbookId: input.playbookId,
1642
+ model: input.model,
1643
+ matched: pick.agent
1644
+ });
1645
+ const started = await deps.sessions.start({ ...input, remoteAgentId: agent.id });
1646
+ if (started.events) {
1647
+ deps.events?.attachLiveStream(started.sessionId, started.events, started.completedEvents);
1648
+ } else if (started.completedEvents?.length) {
1649
+ deps.events?.seedCompleted(started.sessionId, started.completedEvents);
1650
+ }
1651
+ return deps.sessions.getDetail({
1652
+ sessionId: started.sessionId,
1653
+ playbookId: input.playbookId,
1654
+ remoteAgentId: agent.id
1655
+ });
1656
+ },
1657
+ async send(input) {
1658
+ const sent = await deps.sessions.send(input);
1659
+ if (sent.events) {
1660
+ deps.events?.attachLiveStream(sent.sessionId, sent.events, sent.completedEvents);
1661
+ } else if (sent.completedEvents?.length) {
1662
+ deps.events?.seedCompleted(sent.sessionId, sent.completedEvents);
1663
+ }
1664
+ return deps.sessions.getDetail({
1665
+ sessionId: sent.sessionId,
1666
+ playbookId: input.playbookId
1667
+ });
1668
+ },
1669
+ async delete(input) {
1670
+ await deps.sessions.delete(input);
1671
+ }
1672
+ };
1673
+ }
1674
+ function hasSameNameCurrentAppAgent(agents, input) {
1675
+ if (!input.expectedAgentName) return false;
1676
+ return agents.some(
1677
+ (agent) => !isArchived(agent) && agent.metadata?.[PLAYBOOK_APP_METADATA_KEY] === input.appId && agent.name === input.expectedAgentName
1678
+ );
1679
+ }
1680
+ function isArchived(agent) {
1681
+ return agent.archivedAt != null || agent.archived_at != null;
1682
+ }
1683
+ function updatedAtOf(agent) {
1684
+ return agent.updatedAt ?? agent.updated_at;
1685
+ }
1686
+ function epochOf(value) {
1687
+ if (value == null) return 0;
1688
+ if (typeof value === "number") return value;
1689
+ const parsed = Date.parse(value);
1690
+ return Number.isNaN(parsed) ? 0 : parsed;
1691
+ }
1692
+
1636
1693
  // ../../apps/server/src/services/sessions/playbook-session-adapter/sessions.ts
1637
1694
  import {
1638
1695
  deleteSession,
@@ -1838,7 +1895,7 @@ function seedCompletedEvents(sessionId, events) {
1838
1895
  }
1839
1896
 
1840
1897
  // ../../apps/server/src/services/sessions/playbook-session-adapter/index.ts
1841
- function createModeAPlaybookSessionRuntime() {
1898
+ function createServerPlaybookSessionRuntime() {
1842
1899
  return createPlaybookSessionRuntime({
1843
1900
  identity: {
1844
1901
  appId: getPlaybookAppId(),
@@ -1898,7 +1955,7 @@ function createModeAPlaybookSessionRuntime() {
1898
1955
  onDuplicateAgent({ playbookId, winner, duplicates }) {
1899
1956
  const all = [winner, ...duplicates];
1900
1957
  console.warn(
1901
- `\u73A9\u6CD5\u300C${playbookId}\u300D\u5339\u914D\u5230 ${all.length} \u4E2A active playbook Agent(${all.map((agent) => agent.id).join(", ")});\u53D6\u6700\u8FD1\u66F4\u65B0\u7684 ${winner.id}\u3002`
1958
+ `\u73A9\u6CD5\u300C${playbookId}\u300D\u5339\u914D\u5230 ${all.length} \u4E2A active playbook Agent(${all.map((agent) => agent.id).join(", ")})\uFF1B\u53D6\u6700\u8FD1\u66F4\u65B0\u7684 ${winner.id}\u3002`
1902
1959
  );
1903
1960
  }
1904
1961
  });
@@ -1918,7 +1975,7 @@ async function updatePlaybookAgentModel(slug, model) {
1918
1975
  throw new UserError2(run.error ?? `Failed to update agent '${input.agentId}' model (status: ${run.status}).`);
1919
1976
  }
1920
1977
  }
1921
- var playbookSessionRuntime = createModeAPlaybookSessionRuntime();
1978
+ var playbookSessionRuntime = createServerPlaybookSessionRuntime();
1922
1979
  async function listSessionsForAgent(input) {
1923
1980
  const requestedAgentId = input.agentId?.trim() || void 0;
1924
1981
  const limit = input.limit ?? 50;
@@ -2089,7 +2146,7 @@ import { areRuntimeCredentialsReady, resolveActiveProvider as resolveActiveProvi
2089
2146
 
2090
2147
  // ../../apps/server/src/lib/agents-config.ts
2091
2148
  import { mkdir, readFile, writeFile } from "fs/promises";
2092
- import { dirname } from "path";
2149
+ import { dirname as dirname2 } from "path";
2093
2150
  import {
2094
2151
  AGENTS_CONFIG_PROVIDERS,
2095
2152
  AGENTS_PROVIDER_FIELDS,
@@ -2168,17 +2225,20 @@ async function readProviderConfig() {
2168
2225
  }
2169
2226
  const provider = diskConfig.AGENTS_PROVIDER ?? resolveActiveProvider();
2170
2227
  const merged = { AGENTS_PROVIDER: provider };
2171
- for (const field of AGENTS_PROVIDER_FIELDS[provider]) {
2172
- const diskValue = diskConfig[field.key]?.trim();
2173
- const envValue = process.env[field.key]?.trim();
2174
- merged[field.key] = diskValue || envValue;
2228
+ for (const candidateProvider of AGENTS_CONFIG_PROVIDERS) {
2229
+ for (const field of AGENTS_PROVIDER_FIELDS[candidateProvider]) {
2230
+ const diskValue = diskConfig[field.key]?.trim();
2231
+ const envValue = process.env[field.key]?.trim();
2232
+ const value = diskValue || envValue;
2233
+ if (value) merged[field.key] = value;
2234
+ }
2175
2235
  }
2176
2236
  return merged;
2177
2237
  }
2178
2238
  async function writeProviderConfig(input) {
2179
2239
  const config = validateProviderConfig(input);
2180
2240
  const path = providerConfigPath();
2181
- await mkdir(dirname(path), { recursive: true });
2241
+ await mkdir(dirname2(path), { recursive: true });
2182
2242
  const payload = { AGENTS_PROVIDER: config.AGENTS_PROVIDER };
2183
2243
  for (const field of AGENTS_PROVIDER_FIELDS[config.AGENTS_PROVIDER]) {
2184
2244
  payload[field.key] = config[field.key];
@@ -2192,7 +2252,7 @@ async function writeProviderConfig(input) {
2192
2252
  // ../../apps/server/src/schemas/config.ts
2193
2253
  import { z as z3 } from "@hono/zod-openapi";
2194
2254
  var AgentsConfigSchema = z3.object({
2195
- AGENTS_PROVIDER: z3.enum(AGENTS_CONFIG_PROVIDERS2).optional()
2255
+ AGENTS_PROVIDER: z3.enum(AGENTS_CONFIG_PROVIDERS2)
2196
2256
  }).catchall(z3.string()).openapi("AgentsConfig");
2197
2257
  var AgentsConfigSnapshotSchema = z3.object({
2198
2258
  AGENTS_PROVIDER: z3.enum(AGENTS_CONFIG_PROVIDERS2).optional()
@@ -2357,7 +2417,45 @@ environmentsRoute.openapi(deleteEnvironmentRoute, async (c) => {
2357
2417
  });
2358
2418
 
2359
2419
  // ../../apps/server/src/routes/files.ts
2360
- import { OpenAPIHono as OpenAPIHono4 } from "@hono/zod-openapi";
2420
+ import { createRoute as createRoute4, OpenAPIHono as OpenAPIHono4 } from "@hono/zod-openapi";
2421
+
2422
+ // ../../apps/server/src/schemas/files.ts
2423
+ import { z as z5 } from "@hono/zod-openapi";
2424
+ var ProviderFileInfoSchema = z5.object({
2425
+ id: z5.string(),
2426
+ filename: z5.string(),
2427
+ mime_type: z5.string(),
2428
+ size_bytes: z5.number(),
2429
+ created_at: z5.string(),
2430
+ downloadable: z5.boolean().optional(),
2431
+ status: z5.string().optional(),
2432
+ purpose: z5.string().optional(),
2433
+ available: z5.boolean().optional()
2434
+ }).openapi("ProviderFileInfo");
2435
+ var UploadFileFormSchema = z5.object({
2436
+ file: z5.instanceof(File).openapi({ type: "string", format: "binary" })
2437
+ });
2438
+ var FilesResponseSchema = z5.object({
2439
+ files: z5.array(ProviderFileInfoSchema)
2440
+ });
2441
+ var FileStatusesBodySchema = z5.object({
2442
+ fileIds: z5.array(z5.string())
2443
+ });
2444
+ var FileStatusInfoSchema = z5.object({
2445
+ id: z5.string(),
2446
+ status: z5.string().optional(),
2447
+ available: z5.boolean().optional()
2448
+ });
2449
+ var FileStatusesResponseSchema = z5.object({
2450
+ files: z5.array(FileStatusInfoSchema)
2451
+ });
2452
+ var FileParamsSchema = z5.object({
2453
+ id: z5.string().min(1)
2454
+ });
2455
+ var FileDownloadResponseSchema = z5.object({
2456
+ url: z5.string(),
2457
+ expires_at: z5.string().optional()
2458
+ });
2361
2459
 
2362
2460
  // ../../apps/server/src/services/files/upload.ts
2363
2461
  import {
@@ -2411,21 +2509,38 @@ async function getUserFileStatuses(fileIds) {
2411
2509
  // ../../apps/server/src/routes/files.ts
2412
2510
  var filesRoute = new OpenAPIHono4();
2413
2511
  var MAX_UPLOAD_BYTES = 100 * 1024 * 1024;
2414
- filesRoute.post("/files", async (c) => {
2415
- let body;
2416
- try {
2417
- body = await c.req.parseBody();
2418
- } catch (error) {
2419
- return jsonError(error, 400);
2420
- }
2421
- const file = body.file;
2422
- if (!(file instanceof File) || file.size === 0) {
2423
- return c.json({ error: { message: "file is required" } }, 400);
2424
- }
2425
- if (file.size > MAX_UPLOAD_BYTES) {
2426
- return c.json({ error: { message: "file too large" } }, 413);
2512
+ var uploadFileRoute = createRoute4({
2513
+ method: "post",
2514
+ path: "/files",
2515
+ operationId: "uploadFile",
2516
+ request: {
2517
+ body: {
2518
+ required: true,
2519
+ content: { "multipart/form-data": { schema: UploadFileFormSchema } }
2520
+ }
2521
+ },
2522
+ responses: {
2523
+ 201: {
2524
+ description: "Upload a workspace file",
2525
+ content: { "application/json": { schema: ProviderFileInfoSchema } }
2526
+ },
2527
+ 413: {
2528
+ description: "File exceeds the upload size limit",
2529
+ content: { "application/json": { schema: ErrorResponseSchema } }
2530
+ },
2531
+ ...errorResponses
2427
2532
  }
2428
- try {
2533
+ });
2534
+ filesRoute.openapi(
2535
+ uploadFileRoute,
2536
+ async (c) => {
2537
+ const { file } = c.req.valid("form");
2538
+ if (file.size === 0) {
2539
+ return c.json({ error: { message: "file is required" } }, 400);
2540
+ }
2541
+ if (file.size > MAX_UPLOAD_BYTES) {
2542
+ return c.json({ error: { message: "file too large" } }, 413);
2543
+ }
2429
2544
  const content = new Uint8Array(await file.arrayBuffer());
2430
2545
  const info = await uploadUserFile({
2431
2546
  content,
@@ -2433,80 +2548,109 @@ filesRoute.post("/files", async (c) => {
2433
2548
  mimeType: file.type || void 0
2434
2549
  });
2435
2550
  return c.json(info, 201);
2436
- } catch (error) {
2437
- return jsonError(error);
2551
+ },
2552
+ (result, c) => {
2553
+ if (!result.success) return c.json({ error: { message: "file is required" } }, 400);
2438
2554
  }
2439
- });
2440
- filesRoute.get("/files", async (c) => {
2441
- try {
2442
- const files = await listUserFiles();
2443
- return c.json({ files });
2444
- } catch (error) {
2445
- return jsonError(error);
2555
+ );
2556
+ var listFilesRoute = createRoute4({
2557
+ method: "get",
2558
+ path: "/files",
2559
+ operationId: "listFiles",
2560
+ responses: {
2561
+ 200: {
2562
+ description: "List workspace files",
2563
+ content: { "application/json": { schema: FilesResponseSchema } }
2564
+ },
2565
+ ...errorResponses
2446
2566
  }
2447
2567
  });
2448
- filesRoute.post("/files/status", async (c) => {
2449
- let body;
2450
- try {
2451
- body = await c.req.json();
2452
- } catch (error) {
2453
- return jsonError(error, 400);
2454
- }
2455
- const fileIds = body.fileIds;
2456
- if (!Array.isArray(fileIds) || fileIds.some((id) => typeof id !== "string")) {
2457
- return c.json({ error: { message: "fileIds (string[]) is required" } }, 400);
2458
- }
2459
- try {
2460
- const files = await getUserFileStatuses(fileIds);
2461
- return c.json({ files });
2462
- } catch (error) {
2463
- return jsonError(error);
2568
+ filesRoute.openapi(listFilesRoute, async (c) => {
2569
+ const files = await listUserFiles();
2570
+ return c.json({ files }, 200);
2571
+ });
2572
+ var getFileStatusesRoute = createRoute4({
2573
+ method: "post",
2574
+ path: "/files/status",
2575
+ operationId: "getFileStatuses",
2576
+ request: {
2577
+ body: {
2578
+ required: true,
2579
+ content: { "application/json": { schema: FileStatusesBodySchema } }
2580
+ }
2581
+ },
2582
+ responses: {
2583
+ 200: {
2584
+ description: "Get file scan statuses",
2585
+ content: { "application/json": { schema: FileStatusesResponseSchema } }
2586
+ },
2587
+ ...errorResponses
2464
2588
  }
2465
2589
  });
2466
- filesRoute.get("/files/:id/download", async (c) => {
2467
- const id = c.req.param("id");
2468
- if (!id) {
2469
- return c.json({ error: { message: "file id is required" } }, 400);
2590
+ filesRoute.openapi(
2591
+ getFileStatusesRoute,
2592
+ async (c) => {
2593
+ const { fileIds } = c.req.valid("json");
2594
+ const files = await getUserFileStatuses(fileIds);
2595
+ return c.json({ files }, 200);
2596
+ },
2597
+ (result, c) => {
2598
+ if (!result.success) return c.json({ error: { message: "fileIds (string[]) is required" } }, 400);
2470
2599
  }
2471
- try {
2472
- const result = await getUserFileDownloadUrl(id);
2473
- return c.json(result);
2474
- } catch (error) {
2475
- return jsonError(error);
2600
+ );
2601
+ var downloadFileRoute = createRoute4({
2602
+ method: "get",
2603
+ path: "/files/{id}/download",
2604
+ operationId: "downloadFile",
2605
+ request: { params: FileParamsSchema },
2606
+ responses: {
2607
+ 200: {
2608
+ description: "Resolve a short-lived file download URL",
2609
+ content: { "application/json": { schema: FileDownloadResponseSchema } }
2610
+ },
2611
+ ...errorResponses
2476
2612
  }
2477
2613
  });
2478
- filesRoute.delete("/files/:id", async (c) => {
2479
- const id = c.req.param("id");
2480
- if (!id) {
2481
- return c.json({ error: { message: "file id is required" } }, 400);
2482
- }
2483
- try {
2484
- await deleteUserFile(id);
2485
- return c.body(null, 204);
2486
- } catch (error) {
2487
- return jsonError(error);
2614
+ filesRoute.openapi(downloadFileRoute, async (c) => {
2615
+ const { id } = c.req.valid("param");
2616
+ const result = await getUserFileDownloadUrl(id);
2617
+ return c.json(result, 200);
2618
+ });
2619
+ var deleteFileRoute = createRoute4({
2620
+ method: "delete",
2621
+ path: "/files/{id}",
2622
+ operationId: "deleteFile",
2623
+ request: { params: FileParamsSchema },
2624
+ responses: {
2625
+ 204: { description: "File deleted" },
2626
+ ...errorResponses
2488
2627
  }
2489
2628
  });
2629
+ filesRoute.openapi(deleteFileRoute, async (c) => {
2630
+ const { id } = c.req.valid("param");
2631
+ await deleteUserFile(id);
2632
+ return c.body(null, 204);
2633
+ });
2490
2634
 
2491
2635
  // ../../apps/server/src/routes/models.ts
2492
- import { createRoute as createRoute4, OpenAPIHono as OpenAPIHono5 } from "@hono/zod-openapi";
2636
+ import { createRoute as createRoute5, OpenAPIHono as OpenAPIHono5 } from "@hono/zod-openapi";
2493
2637
  import { listProviderModelsForContext } from "@openagentpack/sdk";
2494
2638
 
2495
2639
  // ../../apps/server/src/schemas/models.ts
2496
- import { z as z5 } from "@hono/zod-openapi";
2497
- var ModelOptionSchema = z5.object({
2498
- id: z5.string(),
2499
- display_name: z5.string(),
2500
- is_enabled: z5.boolean().optional(),
2501
- is_new: z5.boolean().optional()
2640
+ import { z as z6 } from "@hono/zod-openapi";
2641
+ var ModelOptionSchema = z6.object({
2642
+ id: z6.string(),
2643
+ display_name: z6.string(),
2644
+ is_enabled: z6.boolean().optional(),
2645
+ is_new: z6.boolean().optional()
2502
2646
  });
2503
- var ModelsResponseSchema = z5.object({
2504
- models: z5.array(ModelOptionSchema)
2647
+ var ModelsResponseSchema = z6.object({
2648
+ models: z6.array(ModelOptionSchema)
2505
2649
  });
2506
2650
 
2507
2651
  // ../../apps/server/src/routes/models.ts
2508
2652
  var modelsRoute = new OpenAPIHono5();
2509
- var listModelsRoute = createRoute4({
2653
+ var listModelsRoute = createRoute5({
2510
2654
  method: "get",
2511
2655
  path: "/models",
2512
2656
  responses: {
@@ -2534,73 +2678,72 @@ modelsRoute.openapi(listModelsRoute, async (c) => {
2534
2678
  });
2535
2679
 
2536
2680
  // ../../apps/server/src/routes/sessions/index.ts
2537
- import { createRoute as createRoute9, OpenAPIHono as OpenAPIHono10 } from "@hono/zod-openapi";
2681
+ import { createRoute as createRoute10, OpenAPIHono as OpenAPIHono10 } from "@hono/zod-openapi";
2538
2682
 
2539
2683
  // ../../apps/server/src/schemas/sessions.ts
2540
- import { z as z6 } from "@hono/zod-openapi";
2684
+ import { z as z7 } from "@hono/zod-openapi";
2541
2685
  import { SessionEventSchema, SessionSchema } from "@openagentpack/sdk";
2542
- var SessionListResponseSchema = z6.object({
2543
- data: z6.array(SessionSchema),
2544
- next_page_token: z6.string().nullish()
2686
+ var SessionListResponseSchema = z7.object({
2687
+ data: z7.array(SessionSchema),
2688
+ next_page_token: z7.string().nullish()
2545
2689
  }).openapi("SessionListResponse");
2546
- var SessionDetailResponseSchema = z6.object({
2690
+ var SessionDetailResponseSchema = z7.object({
2547
2691
  session: SessionSchema,
2548
- events: z6.array(SessionEventSchema),
2549
- events_next_page_token: z6.string().nullish()
2692
+ events: z7.array(SessionEventSchema),
2693
+ events_next_page_token: z7.string().nullish()
2550
2694
  }).openapi("SessionDetailResponse");
2551
- var SessionEventsPageResponseSchema = z6.object({
2552
- events: z6.array(SessionEventSchema),
2553
- events_next_page_token: z6.string().nullish()
2695
+ var SessionEventsPageResponseSchema = z7.object({
2696
+ events: z7.array(SessionEventSchema),
2697
+ events_next_page_token: z7.string().nullish()
2554
2698
  }).openapi("SessionEventsPageResponse");
2555
- var SessionDeleteResponseSchema = z6.object({
2556
- session_id: z6.string(),
2557
- deleted: z6.boolean()
2699
+ var SessionDeleteResponseSchema = z7.object({
2700
+ session_id: z7.string(),
2701
+ deleted: z7.boolean()
2558
2702
  }).openapi("SessionDeleteResponse");
2559
- var SessionsQuerySchema = z6.object({
2703
+ var SessionsQuerySchema = z7.object({
2560
2704
  // Non-numeric values resolve to `undefined` so the handler clamps to a
2561
2705
  // default instead of the request being rejected with a 400.
2562
- limit: z6.preprocess((value) => {
2706
+ limit: z7.preprocess((value) => {
2563
2707
  const parsed = Number(value);
2564
2708
  return Number.isFinite(parsed) ? parsed : void 0;
2565
- }, z6.number().int().optional()),
2566
- agentId: z6.string().optional(),
2709
+ }, z7.number().int().optional()),
2710
+ agentId: z7.string().optional(),
2567
2711
  // Opaque cursor for the next page (provider's next_page / next_page_token, passed through verbatim).
2568
- pageToken: z6.string().optional()
2712
+ pageToken: z7.string().optional()
2569
2713
  });
2570
- var SessionDetailQuerySchema = z6.object({
2571
- agentId: z6.string().optional()
2714
+ var SessionDetailQuerySchema = z7.object({
2715
+ agentId: z7.string().optional()
2572
2716
  });
2573
- var SessionEventsQuerySchema = z6.object({
2574
- agentId: z6.string().optional(),
2575
- pageToken: z6.string().optional(),
2576
- limit: z6.preprocess((value) => {
2717
+ var SessionEventsQuerySchema = z7.object({
2718
+ agentId: z7.string().optional(),
2719
+ pageToken: z7.string().optional(),
2720
+ limit: z7.preprocess((value) => {
2577
2721
  const parsed = Number(value);
2578
2722
  return Number.isFinite(parsed) ? parsed : void 0;
2579
- }, z6.number().int().optional())
2723
+ }, z7.number().int().optional())
2580
2724
  });
2581
- var SessionParamsSchema = z6.object({
2582
- sessionId: z6.string()
2725
+ var SessionParamsSchema = z7.object({
2726
+ sessionId: z7.string()
2583
2727
  });
2584
- var CreateSessionBodySchema = z6.object({
2585
- agentId: z6.string(),
2586
- prompt: z6.string().min(1),
2587
- // Required: a session must be pinned to a cloud environment (sandbox). Both transports
2588
- // enforce this so Mode A (REST/OpenAPI) and Mode B (console) reject env-less creates.
2589
- environmentId: z6.string().min(1),
2728
+ var CreateSessionBodySchema = z7.object({
2729
+ agentId: z7.string(),
2730
+ prompt: z7.string().min(1),
2731
+ // Required: a session must be pinned to a cloud environment (sandbox).
2732
+ environmentId: z7.string().min(1),
2590
2733
  // Optional: cloud vault ids to bind a user-supplied credential so the sandbox receives it.
2591
2734
  // Top-level binding shape matches the console createSession.
2592
- vaultIds: z6.array(z6.string()).optional(),
2593
- title: z6.string().optional(),
2735
+ vaultIds: z7.array(z7.string()).optional(),
2736
+ title: z7.string().optional(),
2594
2737
  // Uploaded files to mount as session resources so the task can read the user's files.
2595
2738
  // Each file needs a mount_path (provider rejects a file resource without one).
2596
- files: z6.array(z6.object({ fileId: z6.string(), mountPath: z6.string() })).optional(),
2739
+ files: z7.array(z7.object({ fileId: z7.string(), mountPath: z7.string() })).optional(),
2597
2740
  // Model the agent should run for this session. If present, createSession applies it
2598
2741
  // to the agent config immediately before starting the run.
2599
- model: z6.string().optional()
2742
+ model: z7.string().optional()
2600
2743
  });
2601
- var SendMessageBodySchema = z6.object({
2602
- agentId: z6.string().optional(),
2603
- message: z6.string().min(1)
2744
+ var SendMessageBodySchema = z7.object({
2745
+ agentId: z7.string().optional(),
2746
+ message: z7.string().min(1)
2604
2747
  });
2605
2748
 
2606
2749
  // ../../apps/server/src/services/sessions/event-sanitizer.ts
@@ -2611,9 +2754,9 @@ function shouldIncludeDebugRaw(request) {
2611
2754
  }
2612
2755
 
2613
2756
  // ../../apps/server/src/routes/sessions/detail.ts
2614
- import { createRoute as createRoute5, OpenAPIHono as OpenAPIHono6 } from "@hono/zod-openapi";
2757
+ import { createRoute as createRoute6, OpenAPIHono as OpenAPIHono6 } from "@hono/zod-openapi";
2615
2758
  var sessionsDetailRoute = new OpenAPIHono6();
2616
- var getSessionRoute = createRoute5({
2759
+ var getSessionRoute = createRoute6({
2617
2760
  method: "get",
2618
2761
  path: "/sessions/{sessionId}",
2619
2762
  request: {
@@ -2642,7 +2785,7 @@ sessionsDetailRoute.openapi(getSessionRoute, async (c) => {
2642
2785
  200
2643
2786
  );
2644
2787
  });
2645
- var deleteSessionRoute = createRoute5({
2788
+ var deleteSessionRoute = createRoute6({
2646
2789
  method: "delete",
2647
2790
  path: "/sessions/{sessionId}",
2648
2791
  request: {
@@ -2665,9 +2808,9 @@ sessionsDetailRoute.openapi(deleteSessionRoute, async (c) => {
2665
2808
  });
2666
2809
 
2667
2810
  // ../../apps/server/src/routes/sessions/events.ts
2668
- import { createRoute as createRoute6, OpenAPIHono as OpenAPIHono7 } from "@hono/zod-openapi";
2811
+ import { createRoute as createRoute7, OpenAPIHono as OpenAPIHono7 } from "@hono/zod-openapi";
2669
2812
  var sessionsEventsRoute = new OpenAPIHono7();
2670
- var listSessionEventsRoute = createRoute6({
2813
+ var listSessionEventsRoute = createRoute7({
2671
2814
  method: "get",
2672
2815
  path: "/sessions/{sessionId}/events",
2673
2816
  request: {
@@ -2704,9 +2847,9 @@ sessionsEventsRoute.openapi(listSessionEventsRoute, async (c) => {
2704
2847
  });
2705
2848
 
2706
2849
  // ../../apps/server/src/routes/sessions/messages.ts
2707
- import { createRoute as createRoute7, OpenAPIHono as OpenAPIHono8 } from "@hono/zod-openapi";
2850
+ import { createRoute as createRoute8, OpenAPIHono as OpenAPIHono8 } from "@hono/zod-openapi";
2708
2851
  var sessionsMessagesRoute = new OpenAPIHono8();
2709
- var sendMessageRoute = createRoute7({
2852
+ var sendMessageRoute = createRoute8({
2710
2853
  method: "post",
2711
2854
  path: "/sessions/{sessionId}/messages",
2712
2855
  request: {
@@ -2735,15 +2878,15 @@ sessionsMessagesRoute.openapi(sendMessageRoute, async (c) => {
2735
2878
  });
2736
2879
 
2737
2880
  // ../../apps/server/src/routes/sessions/stream.ts
2738
- import { createRoute as createRoute8, OpenAPIHono as OpenAPIHono9, z as z7 } from "@hono/zod-openapi";
2881
+ import { createRoute as createRoute9, OpenAPIHono as OpenAPIHono9, z as z8 } from "@hono/zod-openapi";
2739
2882
  var sessionsStreamRoute = new OpenAPIHono9();
2740
- var SessionStreamQuerySchema = z7.object({
2741
- after: z7.preprocess((value) => {
2883
+ var SessionStreamQuerySchema = z8.object({
2884
+ after: z8.preprocess((value) => {
2742
2885
  const parsed = Number(value);
2743
2886
  return Number.isFinite(parsed) ? parsed : void 0;
2744
- }, z7.number().int().optional())
2887
+ }, z8.number().int().optional())
2745
2888
  });
2746
- var streamSessionRoute = createRoute8({
2889
+ var streamSessionRoute = createRoute9({
2747
2890
  method: "get",
2748
2891
  path: "/sessions/{sessionId}/stream",
2749
2892
  request: {
@@ -2755,7 +2898,7 @@ var streamSessionRoute = createRoute8({
2755
2898
  description: "Stream session events as Server-Sent Events",
2756
2899
  content: {
2757
2900
  "text/event-stream": {
2758
- schema: z7.string().openapi({
2901
+ schema: z8.string().openapi({
2759
2902
  description: 'SSE frames with event types "event", "done", and "ping".'
2760
2903
  })
2761
2904
  }
@@ -2866,7 +3009,7 @@ data: ${data}
2866
3009
 
2867
3010
  // ../../apps/server/src/routes/sessions/index.ts
2868
3011
  var sessionsRoute = new OpenAPIHono10();
2869
- var listSessionsRoute = createRoute9({
3012
+ var listSessionsRoute = createRoute10({
2870
3013
  method: "get",
2871
3014
  path: "/sessions",
2872
3015
  request: {
@@ -2892,7 +3035,7 @@ sessionsRoute.openapi(listSessionsRoute, async (c) => {
2892
3035
  });
2893
3036
  return c.json({ data: sessions, next_page_token: nextPageToken ?? null }, 200);
2894
3037
  });
2895
- var createSessionRoute = createRoute9({
3038
+ var createSessionRoute = createRoute10({
2896
3039
  method: "post",
2897
3040
  path: "/sessions",
2898
3041
  request: {
@@ -2934,7 +3077,52 @@ sessionsRoute.route("/", sessionsMessagesRoute);
2934
3077
  sessionsRoute.route("/", sessionsStreamRoute);
2935
3078
 
2936
3079
  // ../../apps/server/src/routes/skills.ts
2937
- import { OpenAPIHono as OpenAPIHono11 } from "@hono/zod-openapi";
3080
+ import { createRoute as createRoute11, OpenAPIHono as OpenAPIHono11 } from "@hono/zod-openapi";
3081
+
3082
+ // ../../apps/server/src/schemas/skills.ts
3083
+ import { z as z9 } from "@hono/zod-openapi";
3084
+ var ProviderSkillInfoSchema = z9.object({
3085
+ id: z9.string(),
3086
+ name: z9.string(),
3087
+ description: z9.string().optional(),
3088
+ source: z9.enum(["custom", "official"]),
3089
+ status: z9.enum(["checking", "active", "rejected", "deleted"]),
3090
+ latest_version: z9.string().optional(),
3091
+ created_at: z9.string().optional(),
3092
+ updated_at: z9.string().optional()
3093
+ }).openapi("ProviderSkillInfo");
3094
+ var UploadSkillFileFormSchema = z9.object({
3095
+ file: z9.instanceof(File).openapi({ type: "string", format: "binary" })
3096
+ });
3097
+ var CreateSkillBodySchema = z9.object({
3098
+ fileId: z9.string().min(1)
3099
+ });
3100
+ var WarmSkillBodySchema = z9.object({
3101
+ name: z9.string().min(1),
3102
+ url: z9.string().min(1)
3103
+ });
3104
+ var WarmSkillResponseSchema = z9.object({
3105
+ ok: z9.literal(true)
3106
+ });
3107
+ var SkillsQuerySchema = z9.object({
3108
+ source: z9.enum(["custom", "official"]).optional()
3109
+ });
3110
+ var SkillsResponseSchema = z9.object({
3111
+ skills: z9.array(ProviderSkillInfoSchema)
3112
+ });
3113
+ var SkillStatusesBodySchema = z9.object({
3114
+ skillIds: z9.array(z9.string())
3115
+ });
3116
+ var SkillStatusInfoSchema = z9.object({
3117
+ id: z9.string(),
3118
+ status: z9.enum(["checking", "active", "rejected", "deleted"]).optional()
3119
+ });
3120
+ var SkillStatusesResponseSchema = z9.object({
3121
+ skills: z9.array(SkillStatusInfoSchema)
3122
+ });
3123
+ var SkillParamsSchema = z9.object({
3124
+ id: z9.string().min(1)
3125
+ });
2938
3126
 
2939
3127
  // ../../apps/server/src/services/skills/manage.ts
2940
3128
  import {
@@ -3036,145 +3224,208 @@ async function warmSkillByUrl(name, url) {
3036
3224
  // ../../apps/server/src/routes/skills.ts
3037
3225
  var skillsRoute = new OpenAPIHono11();
3038
3226
  var MAX_UPLOAD_BYTES2 = 100 * 1024 * 1024;
3039
- skillsRoute.post("/skills/upload-file", async (c) => {
3040
- let body;
3041
- try {
3042
- body = await c.req.parseBody();
3043
- } catch (error) {
3044
- return jsonError(error, 400);
3045
- }
3046
- const file = body.file;
3047
- if (!(file instanceof File) || file.size === 0) {
3048
- return c.json({ error: { message: "file is required" } }, 400);
3049
- }
3050
- if (!file.name.toLowerCase().endsWith(".zip")) {
3051
- return c.json({ error: { message: "skill file must be a .zip" } }, 400);
3052
- }
3053
- if (file.size > MAX_UPLOAD_BYTES2) {
3054
- return c.json({ error: { message: "file too large" } }, 413);
3227
+ var uploadSkillFileRoute = createRoute11({
3228
+ method: "post",
3229
+ path: "/skills/upload-file",
3230
+ operationId: "uploadSkillFile",
3231
+ request: {
3232
+ body: {
3233
+ required: true,
3234
+ content: { "multipart/form-data": { schema: UploadSkillFileFormSchema } }
3235
+ }
3236
+ },
3237
+ responses: {
3238
+ 201: {
3239
+ description: "Upload a skill archive as a file pending audit",
3240
+ content: { "application/json": { schema: ProviderFileInfoSchema } }
3241
+ },
3242
+ 413: {
3243
+ description: "Skill archive exceeds the upload size limit",
3244
+ content: { "application/json": { schema: ErrorResponseSchema } }
3245
+ },
3246
+ ...errorResponses
3055
3247
  }
3056
- try {
3248
+ });
3249
+ skillsRoute.openapi(
3250
+ uploadSkillFileRoute,
3251
+ async (c) => {
3252
+ const { file } = c.req.valid("form");
3253
+ if (file.size === 0) return c.json({ error: { message: "file is required" } }, 400);
3254
+ if (!file.name.toLowerCase().endsWith(".zip")) {
3255
+ return c.json({ error: { message: "skill file must be a .zip" } }, 400);
3256
+ }
3257
+ if (file.size > MAX_UPLOAD_BYTES2) return c.json({ error: { message: "file too large" } }, 413);
3057
3258
  const content = new Uint8Array(await file.arrayBuffer());
3058
3259
  const info = await uploadUserSkillFile({ content, filename: file.name });
3059
3260
  return c.json(info, 201);
3060
- } catch (error) {
3061
- return jsonError(error);
3062
- }
3063
- });
3064
- skillsRoute.post("/skills", async (c) => {
3065
- let body;
3066
- try {
3067
- body = await c.req.json();
3068
- } catch (error) {
3069
- return jsonError(error, 400);
3261
+ },
3262
+ (result, c) => {
3263
+ if (!result.success) return c.json({ error: { message: "file is required" } }, 400);
3070
3264
  }
3071
- const fileId = body.fileId;
3072
- if (typeof fileId !== "string" || fileId.length === 0) {
3073
- return c.json({ error: { message: "fileId is required" } }, 400);
3265
+ );
3266
+ var createSkillRoute = createRoute11({
3267
+ method: "post",
3268
+ path: "/skills",
3269
+ operationId: "createSkill",
3270
+ request: {
3271
+ body: {
3272
+ required: true,
3273
+ content: { "application/json": { schema: CreateSkillBodySchema } }
3274
+ }
3275
+ },
3276
+ responses: {
3277
+ 201: {
3278
+ description: "Create a skill from an audited file",
3279
+ content: { "application/json": { schema: ProviderSkillInfoSchema } }
3280
+ },
3281
+ ...errorResponses
3074
3282
  }
3075
- try {
3283
+ });
3284
+ skillsRoute.openapi(
3285
+ createSkillRoute,
3286
+ async (c) => {
3287
+ const { fileId } = c.req.valid("json");
3076
3288
  const info = await createUserSkillFromFile(fileId);
3077
3289
  return c.json(info, 201);
3078
- } catch (error) {
3079
- return jsonError(error);
3080
- }
3081
- });
3082
- skillsRoute.post("/skills/warm", async (c) => {
3083
- let body;
3084
- try {
3085
- body = await c.req.json();
3086
- } catch (error) {
3087
- return jsonError(error, 400);
3290
+ },
3291
+ (result, c) => {
3292
+ if (!result.success) return c.json({ error: { message: "fileId is required" } }, 400);
3088
3293
  }
3089
- const { name, url } = body;
3090
- if (typeof name !== "string" || !name || typeof url !== "string" || !url) {
3091
- return c.json({ error: { message: "name and url are required" } }, 400);
3294
+ );
3295
+ var warmSkillRoute = createRoute11({
3296
+ method: "post",
3297
+ path: "/skills/warm",
3298
+ operationId: "warmSkill",
3299
+ request: {
3300
+ body: {
3301
+ required: true,
3302
+ content: { "application/json": { schema: WarmSkillBodySchema } }
3303
+ }
3304
+ },
3305
+ responses: {
3306
+ 200: {
3307
+ description: "Warm a custom skill until it is active",
3308
+ content: { "application/json": { schema: WarmSkillResponseSchema } }
3309
+ },
3310
+ ...errorResponses
3092
3311
  }
3093
- try {
3312
+ });
3313
+ skillsRoute.openapi(
3314
+ warmSkillRoute,
3315
+ async (c) => {
3316
+ const { name, url } = c.req.valid("json");
3094
3317
  await warmSkillByUrl(name, url);
3095
3318
  return c.json({ ok: true }, 200);
3096
- } catch (error) {
3097
- return jsonError(error);
3098
- }
3099
- });
3100
- skillsRoute.get("/skills", async (c) => {
3101
- const source = c.req.query("source");
3102
- if (source !== void 0 && source !== "custom" && source !== "official") {
3103
- return c.json({ error: { message: "source must be 'custom' or 'official'" } }, 400);
3319
+ },
3320
+ (result, c) => {
3321
+ if (!result.success) return c.json({ error: { message: "name and url are required" } }, 400);
3104
3322
  }
3105
- try {
3106
- const skills = await listUserSkills(source);
3107
- return c.json({ skills });
3108
- } catch (error) {
3109
- return jsonError(error);
3323
+ );
3324
+ var listSkillsRoute = createRoute11({
3325
+ method: "get",
3326
+ path: "/skills",
3327
+ operationId: "listSkills",
3328
+ request: { query: SkillsQuerySchema },
3329
+ responses: {
3330
+ 200: {
3331
+ description: "List custom or official skills",
3332
+ content: { "application/json": { schema: SkillsResponseSchema } }
3333
+ },
3334
+ ...errorResponses
3110
3335
  }
3111
3336
  });
3112
- skillsRoute.post("/skills/status", async (c) => {
3113
- let body;
3114
- try {
3115
- body = await c.req.json();
3116
- } catch (error) {
3117
- return jsonError(error, 400);
3118
- }
3119
- const skillIds = body.skillIds;
3120
- if (!Array.isArray(skillIds) || skillIds.some((id) => typeof id !== "string")) {
3121
- return c.json({ error: { message: "skillIds (string[]) is required" } }, 400);
3337
+ skillsRoute.openapi(
3338
+ listSkillsRoute,
3339
+ async (c) => {
3340
+ const { source } = c.req.valid("query");
3341
+ const skills = await listUserSkills(source);
3342
+ return c.json({ skills }, 200);
3343
+ },
3344
+ (result, c) => {
3345
+ if (!result.success) {
3346
+ return c.json({ error: { message: "source must be 'custom' or 'official'" } }, 400);
3347
+ }
3122
3348
  }
3123
- try {
3124
- const skills = await getUserSkillStatuses(skillIds);
3125
- return c.json({ skills });
3126
- } catch (error) {
3127
- return jsonError(error);
3349
+ );
3350
+ var getSkillStatusesRoute = createRoute11({
3351
+ method: "post",
3352
+ path: "/skills/status",
3353
+ operationId: "getSkillStatuses",
3354
+ request: {
3355
+ body: {
3356
+ required: true,
3357
+ content: { "application/json": { schema: SkillStatusesBodySchema } }
3358
+ }
3359
+ },
3360
+ responses: {
3361
+ 200: {
3362
+ description: "Get skill scan statuses",
3363
+ content: { "application/json": { schema: SkillStatusesResponseSchema } }
3364
+ },
3365
+ ...errorResponses
3128
3366
  }
3129
3367
  });
3130
- skillsRoute.delete("/skills/:id", async (c) => {
3131
- const id = c.req.param("id");
3132
- if (!id) {
3133
- return c.json({ error: { message: "skill id is required" } }, 400);
3368
+ skillsRoute.openapi(
3369
+ getSkillStatusesRoute,
3370
+ async (c) => {
3371
+ const { skillIds } = c.req.valid("json");
3372
+ const skills = await getUserSkillStatuses(skillIds);
3373
+ return c.json({ skills }, 200);
3374
+ },
3375
+ (result, c) => {
3376
+ if (!result.success) return c.json({ error: { message: "skillIds (string[]) is required" } }, 400);
3134
3377
  }
3135
- try {
3136
- await deleteUserSkill(id);
3137
- return c.body(null, 204);
3138
- } catch (error) {
3139
- return jsonError(error);
3378
+ );
3379
+ var deleteSkillRoute = createRoute11({
3380
+ method: "delete",
3381
+ path: "/skills/{id}",
3382
+ operationId: "deleteSkill",
3383
+ request: { params: SkillParamsSchema },
3384
+ responses: {
3385
+ 204: { description: "Skill deleted" },
3386
+ ...errorResponses
3140
3387
  }
3141
3388
  });
3389
+ skillsRoute.openapi(deleteSkillRoute, async (c) => {
3390
+ const { id } = c.req.valid("param");
3391
+ await deleteUserSkill(id);
3392
+ return c.body(null, 204);
3393
+ });
3142
3394
 
3143
3395
  // ../../apps/server/src/routes/vaults.ts
3144
- import { createRoute as createRoute10, OpenAPIHono as OpenAPIHono12 } from "@hono/zod-openapi";
3396
+ import { createRoute as createRoute12, OpenAPIHono as OpenAPIHono12 } from "@hono/zod-openapi";
3145
3397
  import { createCloudVault, deleteCloudVault, listCloudVaults } from "@openagentpack/sdk";
3146
3398
 
3147
3399
  // ../../apps/server/src/schemas/vaults.ts
3148
- import { z as z8 } from "@hono/zod-openapi";
3400
+ import { z as z10 } from "@hono/zod-openapi";
3149
3401
  import { CloudVaultSchema } from "@openagentpack/sdk";
3150
3402
  import { CloudVaultSchema as CloudVaultSchema2 } from "@openagentpack/sdk";
3151
- var CloudVaultsResponseSchema = z8.object({
3152
- vaults: z8.array(CloudVaultSchema)
3403
+ var CloudVaultsResponseSchema = z10.object({
3404
+ vaults: z10.array(CloudVaultSchema)
3153
3405
  });
3154
- var CreateVaultBodySchema = z8.object({
3155
- name: z8.string().min(1),
3156
- metadata: z8.record(z8.string(), z8.string()).optional(),
3157
- // The DASHSCOPE_API_KEY stored as the vault's credential secret value. Optional: Mode B
3158
- // supplies the user's key; Mode A (local) omits it and the server injects it from its own
3159
- // DASHSCOPE_API_KEY env. (Mode B never reaches this REST route — it goes via console RPC.)
3160
- key: z8.string().min(1).optional()
3406
+ var CreateVaultBodySchema = z10.object({
3407
+ name: z10.string().min(1),
3408
+ metadata: z10.record(z10.string(), z10.string()).optional(),
3409
+ // The DASHSCOPE_API_KEY stored as the vault's credential secret value. Optional:
3410
+ // when omitted the server injects it from its own DASHSCOPE_API_KEY env.
3411
+ key: z10.string().min(1).optional()
3161
3412
  });
3162
- var CreateVaultResponseSchema = z8.object({
3163
- id: z8.string().nullable(),
3164
- type: z8.string(),
3165
- version: z8.number().optional()
3413
+ var CreateVaultResponseSchema = z10.object({
3414
+ id: z10.string().nullable(),
3415
+ type: z10.string(),
3416
+ version: z10.number().optional()
3166
3417
  });
3167
- var DeleteVaultResponseSchema = z8.object({
3168
- id: z8.string(),
3169
- type: z8.string()
3418
+ var DeleteVaultResponseSchema = z10.object({
3419
+ id: z10.string(),
3420
+ type: z10.string()
3170
3421
  });
3171
- var VaultParamsSchema = z8.object({
3172
- vaultId: z8.string().min(1)
3422
+ var VaultParamsSchema = z10.object({
3423
+ vaultId: z10.string().min(1)
3173
3424
  });
3174
3425
 
3175
3426
  // ../../apps/server/src/routes/vaults.ts
3176
3427
  var vaultsRoute = new OpenAPIHono12();
3177
- var listVaultsRoute = createRoute10({
3428
+ var listVaultsRoute = createRoute12({
3178
3429
  method: "get",
3179
3430
  path: "/vaults",
3180
3431
  responses: {
@@ -3189,7 +3440,7 @@ vaultsRoute.openapi(listVaultsRoute, async (c) => {
3189
3440
  const vaults = await withAgentRuntime(DEFAULT_AGENT_ID, (ctx) => listCloudVaults(ctx));
3190
3441
  return c.json({ vaults }, 200);
3191
3442
  });
3192
- var createVaultRoute = createRoute10({
3443
+ var createVaultRoute = createRoute12({
3193
3444
  method: "post",
3194
3445
  path: "/vaults",
3195
3446
  request: {
@@ -3217,8 +3468,8 @@ vaultsRoute.openapi(createVaultRoute, async (c) => {
3217
3468
  const vault = await withAgentRuntime(
3218
3469
  DEFAULT_AGENT_ID,
3219
3470
  (ctx) => createCloudVault(ctx, name, {
3220
- // display_name carries the base-vault identity (Agents/secrets) a vault has no
3221
- // separate `name` field, so findBaseVault nets it by display_name + the stamp.
3471
+ // display_name is used as the vault's human-readable label on the provider.
3472
+ // findBaseVault identifies the managed vault by its metadata stamp (agents.vault).
3222
3473
  display_name: name,
3223
3474
  metadata,
3224
3475
  credentials: structure.credentials.map((cred) => ({
@@ -3232,7 +3483,7 @@ vaultsRoute.openapi(createVaultRoute, async (c) => {
3232
3483
  );
3233
3484
  return c.json(vault, 200);
3234
3485
  });
3235
- var deleteVaultRoute = createRoute10({
3486
+ var deleteVaultRoute = createRoute12({
3236
3487
  method: "delete",
3237
3488
  path: "/vaults/{vaultId}",
3238
3489
  request: {
@@ -3318,8 +3569,8 @@ async function resolveListenPort(preferred, maxAttempts = MAX_PORT_ATTEMPTS) {
3318
3569
 
3319
3570
  // src/server.ts
3320
3571
  var DEFAULT_PLAYGROUND_PORT = 4848;
3321
- var webRoot = join(dirname2(fileURLToPath(import.meta.url)), "../../web");
3322
- var indexHtml = injectPlaygroundRuntimeMarker(readFileSync(join(webRoot, "index.html"), "utf8"));
3572
+ var webRoot = join2(dirname3(fileURLToPath(import.meta.url)), "../../web");
3573
+ var indexHtml = injectPlaygroundRuntimeMarker(readFileSync(join2(webRoot, "index.html"), "utf8"));
3323
3574
  function injectPlaygroundRuntimeMarker(html) {
3324
3575
  if (html.includes('name="agents-runtime"')) return html;
3325
3576
  return html.replace("<head>", '<head>\n <meta name="agents-runtime" content="playground" />');