@desplega.ai/agent-swarm 1.129.0 → 1.131.0
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/README.md +2 -2
- package/dist/{actions-kfv2dawe.js → actions-w53mbns9.js} +11 -11
- package/dist/{anthropic-messages-3xgme8my.js → anthropic-messages-rjmd2e7n.js} +5 -5
- package/dist/{app-q8vjk6e8.js → app-m9gwqsqv.js} +8 -8
- package/dist/{artifact-hg4t1nx7.js → artifact-jysj3wrg.js} +2 -2
- package/dist/{assistant-g037r345.js → assistant-bp65m6f3.js} +13 -13
- package/dist/{azure-openai-responses-xa4sh9f6.js → azure-openai-responses-c0yjmbfd.js} +8 -5
- package/dist/{boot-reembed-18pzsrxa.js → boot-reembed-62p0at2k.js} +6 -6
- package/dist/{boot-reembed-wpks2cj8.js → boot-reembed-xmfp6wdh.js} +7 -7
- package/dist/{boot-scrub-logs-n7szd57r.js → boot-scrub-logs-rr8q2dms.js} +5 -5
- package/dist/{claude-adapter-qz4r0ajt.js → claude-adapter-2y47mrkd.js} +9 -9
- package/dist/{cli-mhjnbgb6.js → cli-0rcyq6d9.js} +450 -186
- package/dist/{cli-ttkmehy0.js → cli-2q72qz2s.js} +274 -25
- package/dist/{cli-gztgc3hz.js → cli-2wadx7p2.js} +2 -2
- package/dist/cli-3fj60etf.js +153 -0
- package/dist/{cli-7ecgm5v0.js → cli-3kf51j15.js} +1 -1
- package/dist/{cli-vgexpfsr.js → cli-57khth04.js} +6 -3
- package/dist/{cli-2mbe7vk0.js → cli-5dsbcjjw.js} +1 -1
- package/dist/{cli-etr62zy6.js → cli-5kx36evn.js} +2 -2
- package/dist/{cli-v2tr6amf.js → cli-5n6e5yfn.js} +30 -8
- package/dist/{cli-hx02s9zq.js → cli-5v4rw6yd.js} +2 -2
- package/dist/{cli-v37yr6mf.js → cli-5ze9rv97.js} +4 -4
- package/dist/{cli-ch7t5v7n.js → cli-6map995v.js} +9 -4
- package/dist/{cli-h0457a67.js → cli-70xqj0z3.js} +3 -3
- package/dist/{cli-kk4f9r17.js → cli-72q8m8gk.js} +8 -6
- package/dist/{cli-7padk69a.js → cli-78xwvkhj.js} +2 -2
- package/dist/{cli-dxtxacy7.js → cli-9dr5qzc0.js} +45 -8
- package/dist/{cli-17zxdgsq.js → cli-a40rnf71.js} +6 -6
- package/dist/{cli-t53vnnxz.js → cli-a4jzdpa3.js} +2514 -1055
- package/dist/{cli-w10fkrf1.js → cli-akdvwc9v.js} +354 -115
- package/dist/{cli-1qkk5er0.js → cli-bmze986d.js} +1 -1
- package/dist/{cli-ga12dc1d.js → cli-bqw0mt1n.js} +3 -3
- package/dist/{cli-0sf92efp.js → cli-cdeg08wx.js} +1 -1
- package/dist/{cli-a8ynhkyj.js → cli-cvgjwnh1.js} +17 -15
- package/dist/{cli-9fxg3v5m.js → cli-d2tfkcga.js} +4 -4
- package/dist/{cli-nhcd7x43.js → cli-d3x3x1c9.js} +2 -2
- package/dist/{cli-6nh2qxvh.js → cli-darcwax3.js} +1 -1
- package/dist/{cli-yjbgmysx.js → cli-e7ckcg4v.js} +12 -12
- package/dist/{cli-4n2gcjpd.js → cli-efxfnq6q.js} +4 -3
- package/dist/{cli-z9xqqhfk.js → cli-er3a4bb0.js} +1 -1
- package/dist/{cli-xg2eezyv.js → cli-f1am9szv.js} +1 -1
- package/dist/{cli-xy4cwsm9.js → cli-fywms69x.js} +1 -1
- package/dist/{cli-33jj76y8.js → cli-g6b8x1h8.js} +1 -1
- package/dist/{cli-epsvdckx.js → cli-gm9cbhbq.js} +20 -10
- package/dist/{cli-rkndnn90.js → cli-k9qkf1hw.js} +6 -4
- package/dist/{cli-zejvt395.js → cli-kh3ba2zf.js} +1 -1
- package/dist/{cli-gb25p1h2.js → cli-nm5gtp1x.js} +2 -2
- package/dist/{cli-akxnpx17.js → cli-pm6xbh84.js} +1829 -1629
- package/dist/{cli-2k0ztbfp.js → cli-psh3c4va.js} +1 -1
- package/dist/{cli-39vgrsep.js → cli-qv61hp37.js} +2 -2
- package/dist/{cli-hv2fndhm.js → cli-r6kqqbj0.js} +6 -4
- package/dist/{cli-1y1cm570.js → cli-rzbpmxdr.js} +1 -1
- package/dist/{cli-mmrk00vp.js → cli-t1xze5qh.js} +1 -1
- package/dist/{cli-g252a9ky.js → cli-t55yw3a1.js} +2 -2
- package/dist/{cli-7bz8dzqa.js → cli-t76vw5db.js} +1184 -1522
- package/dist/{cli-4n4mdv21.js → cli-xpxde7rm.js} +7 -3
- package/dist/{cli-fpaa5k2q.js → cli-yw8vghx2.js} +54 -18
- package/dist/cli-zsspvvm2.js +490 -0
- package/dist/cli.js +27 -25
- package/dist/{codex-adapter-7v6t7ff6.js → codex-adapter-d24q75wk.js} +7 -7
- package/dist/{codex-hook-amndawyb.js → codex-hook-hq54t9ft.js} +2 -2
- package/dist/{codex-session-runner-e7j4khe2.js → codex-session-runner-g50vcsex.js} +7 -7
- package/dist/{commands-ex0k5tbf.js → commands-c3nrc5hg.js} +5 -5
- package/dist/{db-df7jatfc.js → db-nt7fg3tw.js} +5 -5
- package/dist/{google-generative-ai-y42hnw9p.js → google-generative-ai-hysrd8qx.js} +7 -5
- package/dist/{google-vertex-4sg66gb6.js → google-vertex-p5arrga0.js} +7 -5
- package/dist/{handlers-1j2cfqt2.js → handlers-fkr6swat.js} +13 -13
- package/dist/{hook-nx9a0mj3.js → hook-77wpvnjc.js} +7 -7
- package/dist/{hook-w6yaf6sy.js → hook-g019yehy.js} +8 -8
- package/dist/{http-4tz5h8wg.js → http-jewj0syk.js} +2993 -716
- package/dist/{index-0bpkzb09.js → index-070v4eyb.js} +3 -3
- package/dist/{index-0s67qv7h.js → index-6gm5he8h.js} +11 -11
- package/dist/{index-35gtv6gj.js → index-7n2xpbd4.js} +310 -40
- package/dist/{index-ker3gccb.js → index-9znhar3x.js} +4 -4
- package/dist/{index-5n2c8yay.js → index-hase6zbe.js} +2 -2
- package/dist/{index-kcf3tm9h.js → index-hfvggd0z.js} +12 -12
- package/dist/{index-7c0jqna0.js → index-hp1kdbjj.js} +13 -13
- package/dist/{keepalive-3j4a9168.js → keepalive-j0fjvqfd.js} +7 -7
- package/dist/{lead-6kpevymb.js → lead-1n8x30xe.js} +33 -33
- package/dist/{maintenance-m1k82ean.js → maintenance-gvev11sa.js} +7 -7
- package/dist/{mistral-conversations-bjkdfb6z.js → mistral-conversations-81fwav0j.js} +6 -6
- package/dist/{oauth-refresh-sweep-881k8e4q.js → oauth-refresh-sweep-s9ecsvh0.js} +6 -6
- package/dist/{onboard-c0ykffjn.js → onboard-pvm5b38w.js} +2 -2
- package/dist/{openai-codex-responses-xetseqvt.js → openai-codex-responses-5g27pd6f.js} +43 -23
- package/dist/{openai-completions-5r2g5axa.js → openai-completions-3vkmfz2a.js} +55 -11
- package/dist/{openai-responses-ce67hd23.js → openai-responses-dg4t7j7a.js} +8 -5
- package/dist/{openrouter-images-pzfp22jb.js → openrouter-images-g3gm8931.js} +1 -1
- package/dist/{otel-impl-sqagjerv.js → otel-impl-p6jvgd9c.js} +6 -4
- package/dist/{otel-3mp81ppd.js → otel-nqa12wf3.js} +2 -2
- package/dist/{pi-mono-adapter-k584k16g.js → pi-mono-adapter-t091s27g.js} +17117 -7517
- package/dist/{pricing-refresh-y82whbf9.js → pricing-refresh-k49rcyed.js} +7 -7
- package/dist/{rbac-roles-nvkqmzyd.js → rbac-roles-30pspvy7.js} +7 -7
- package/dist/{rbac-roles-4ht8gegc.js → rbac-roles-cr80g96t.js} +6 -6
- package/dist/{render-v2-wvqdgvvp.js → render-v2-xm457ng1.js} +8 -8
- package/dist/{seed-pricing-fy3rxhde.js → seed-pricing-yhpv35fr.js} +6 -6
- package/dist/{setup-ak5cnc6f.js → setup-nytnmwwr.js} +2 -2
- package/dist/{worker-d8769q8a.js → worker-msytr2cw.js} +33 -33
- package/openapi.json +34039 -11036
- package/package.json +8 -6
- package/src/apps/definition.ts +368 -26
- package/src/apps/row-store.ts +66 -10
- package/src/apps/schema-migrate.ts +95 -1
- package/src/apps/store.ts +13 -4
- package/src/apps/sync-run-as.ts +18 -0
- package/src/apps/sync.ts +934 -0
- package/src/apps/version.ts +16 -2
- package/src/assets/key.ts +8 -1
- package/src/be/asset-key-audit.ts +3 -1
- package/src/be/db-queries/mcp-oauth.ts +297 -24
- package/src/be/db.ts +42 -1
- package/src/be/migrations/129_asset_keys_apps_scripts.sql +161 -0
- package/src/be/scripts/db.ts +5 -2
- package/src/be/scripts/typecheck.ts +1 -0
- package/src/be/seed-scripts/catalog/app-sync-run.ts +32 -0
- package/src/be/seed-scripts/catalog/github-issues-pull.ts +102 -0
- package/src/be/seed-scripts/index.ts +18 -0
- package/src/be/seed-skills/index.ts +7 -0
- package/src/http/active-sessions.ts +26 -18
- package/src/http/agents.ts +94 -27
- package/src/http/api-keys.ts +91 -17
- package/src/http/approval-requests.ts +87 -10
- package/src/http/apps.ts +361 -53
- package/src/http/assets.ts +165 -31
- package/src/http/budgets.ts +7 -5
- package/src/http/codex-oauth-keep-warm.ts +21 -3
- package/src/http/config.ts +46 -16
- package/src/http/context.ts +33 -6
- package/src/http/ecosystem.ts +20 -6
- package/src/http/events.ts +24 -9
- package/src/http/favorites.ts +20 -6
- package/src/http/fs.ts +60 -17
- package/src/http/heartbeat.ts +18 -4
- package/src/http/inbox-state.ts +12 -6
- package/src/http/integrations.ts +25 -5
- package/src/http/kv.ts +36 -15
- package/src/http/mcp-bridge.ts +5 -1
- package/src/http/mcp-oauth.ts +332 -17
- package/src/http/mcp-servers.ts +56 -18
- package/src/http/memory.ts +282 -29
- package/src/http/metrics.ts +80 -17
- package/src/http/oauth-callback.ts +10 -4
- package/src/http/oauth-generic.ts +5 -1
- package/src/http/oauth-locks.ts +6 -3
- package/src/http/openapi.ts +57 -9
- package/src/http/page-proxy.ts +25 -5
- package/src/http/pages-public.ts +37 -20
- package/src/http/pages.ts +93 -28
- package/src/http/poll.ts +89 -5
- package/src/http/pricing.ts +9 -6
- package/src/http/prompt-templates.ts +85 -21
- package/src/http/route-def.ts +67 -4
- package/src/http/schedules.ts +63 -14
- package/src/http/script-connection-proxy.ts +30 -4
- package/src/http/script-connections.ts +393 -43
- package/src/http/script-runs.ts +73 -19
- package/src/http/scripts.ts +257 -39
- package/src/http/session-data.ts +87 -14
- package/src/http/sessions.ts +80 -5
- package/src/http/skills.ts +115 -35
- package/src/http/stats.ts +94 -13
- package/src/http/task-templates.ts +6 -4
- package/src/http/tasks.ts +230 -61
- package/src/http/trackers/jira.ts +90 -30
- package/src/http/trackers/linear.ts +46 -12
- package/src/http/users.ts +162 -25
- package/src/http/utils.ts +12 -2
- package/src/http/webhooks.ts +30 -16
- package/src/http/workflow-events.ts +18 -5
- package/src/http/workflows.ts +128 -39
- package/src/http/x.ts +37 -6
- package/src/oauth/ensure-mcp-token.ts +16 -1
- package/src/oauth/mcp-wrapper.ts +281 -26
- package/src/providers/pi-mono-adapter.ts +1 -1
- package/src/scripts-runtime/credential-broker/README.md +1 -1
- package/src/scripts-runtime/credential-broker/fetch-patch.ts +12 -2
- package/src/scripts-runtime/sdk-allowlist.ts +1 -0
- package/src/scripts-runtime/stdlib/fetch.ts +6 -0
- package/src/scripts-runtime/types/stdlib.d.ts +1 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +1 -0
- package/src/server.ts +2 -0
- package/src/tests/apps-rbac.test.ts +110 -0
- package/src/tests/apps-spike2.test.ts +4 -1
- package/src/tests/apps-sync-engine.test.ts +2540 -0
- package/src/tests/apps-sync.test.ts +1627 -0
- package/src/tests/asset-key-api.test.ts +48 -2
- package/src/tests/asset-key-invariants.test.ts +92 -0
- package/src/tests/asset-key-migration.test.ts +174 -8
- package/src/tests/asset-key-normalization.test.ts +2 -0
- package/src/tests/credential-broker.test.ts +27 -2
- package/src/tests/mcp-oauth-dcr-reuse.test.ts +743 -0
- package/src/tests/mcp-oauth-ensure-token.test.ts +45 -0
- package/src/tests/mcp-oauth-manual-client.test.ts +135 -2
- package/src/tests/mcp-oauth-queries.test.ts +153 -0
- package/src/tests/mcp-oauth-wrapper.test.ts +432 -0
- package/src/tests/memory-http-recall-gating.test.ts +2 -0
- package/src/tests/openapi-response-contract.test.ts +138 -0
- package/src/tests/rbac-admission-e2e.test.ts +68 -0
- package/src/tests/script-connections.test.ts +3 -0
- package/src/tests/scripts-runtime-fetch.test.ts +121 -0
- package/src/tests/scripts-runtime-secret-egress.test.ts +4 -2
- package/src/tests/seed-scripts.test.ts +2 -2
- package/src/tests/swarm-tool-result-gate.test.ts +32 -0
- package/src/tests/task-working-dir.test.ts +8 -4
- package/src/tests/whoami-route.test.ts +127 -0
- package/src/tests/workflow-engine-v2.test.ts +80 -7
- package/src/tests/workflow-swarm-script.test.ts +104 -0
- package/src/tools/app-get.ts +10 -2
- package/src/tools/app-rollback.ts +1 -0
- package/src/tools/app-sync.ts +112 -0
- package/src/tools/script-common.ts +20 -0
- package/src/tools/tool-config.ts +2 -1
- package/src/tools/utils.ts +11 -0
- package/src/tools/workflows/create-workflow.ts +4 -1
- package/src/types.ts +1394 -1206
- package/src/utils/template.ts +8 -1
- package/src/utils/zod-openapi.ts +11 -0
- package/src/workflows/engine.ts +27 -4
- package/src/workflows/executors/swarm-script.ts +28 -0
- package/src/workflows/retry-poller.ts +19 -2
- package/templates/skills/apps/content.md +94 -5
- package/templates/skills/asset-namespaces/content.md +2 -2
- package/templates/skills/scheduled-task-resilience/SKILL.md +102 -0
- package/templates/skills/scheduled-task-resilience/config.json +14 -0
- package/templates/skills/scheduled-task-resilience/content.md +97 -0
- package/dist/cli-7wmybrt5.js +0 -115
- package/dist/cli-d91pvmq1.js +0 -14
package/src/http/session-data.ts
CHANGED
|
@@ -16,10 +16,68 @@ import {
|
|
|
16
16
|
import { recordSessionCost } from "../otel";
|
|
17
17
|
import { incrementServerSessionsProcessed } from "../server-runtime-counters";
|
|
18
18
|
import type { SessionCost } from "../types";
|
|
19
|
-
import { SessionCostModelBreakdownSchema } from "../types";
|
|
19
|
+
import { SessionCostModelBreakdownSchema, SessionCostSchema, SessionLogSchema } from "../types";
|
|
20
20
|
import { route } from "./route-def";
|
|
21
21
|
import { recomputeSessionCost } from "./session-cost-recompute";
|
|
22
|
-
import {
|
|
22
|
+
import { jsonError } from "./utils";
|
|
23
|
+
|
|
24
|
+
// ─── Response Schemas ────────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
/** Mirrors `SessionCostSummaryTotals` in src/be/db.ts. */
|
|
27
|
+
const SessionCostSummaryTotalsSchema = z.object({
|
|
28
|
+
totalCostUsd: z.number(),
|
|
29
|
+
totalInputTokens: z.number().int(),
|
|
30
|
+
totalOutputTokens: z.number().int(),
|
|
31
|
+
totalCacheReadTokens: z.number().int(),
|
|
32
|
+
totalCacheWriteTokens: z.number().int(),
|
|
33
|
+
totalDurationMs: z.number().int(),
|
|
34
|
+
totalSessions: z.number().int(),
|
|
35
|
+
avgCostPerSession: z.number(),
|
|
36
|
+
attributedCostUsd: z.number(),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
/** Mirrors `SessionCostDailyRow` in src/be/db.ts. */
|
|
40
|
+
const SessionCostDailyRowSchema = z.object({
|
|
41
|
+
date: z.string(),
|
|
42
|
+
costUsd: z.number(),
|
|
43
|
+
inputTokens: z.number().int(),
|
|
44
|
+
outputTokens: z.number().int(),
|
|
45
|
+
sessions: z.number().int(),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
/** Mirrors `SessionCostByAgentRow` in src/be/db.ts. */
|
|
49
|
+
const SessionCostByAgentRowSchema = z.object({
|
|
50
|
+
agentId: z.string(),
|
|
51
|
+
costUsd: z.number(),
|
|
52
|
+
inputTokens: z.number().int(),
|
|
53
|
+
outputTokens: z.number().int(),
|
|
54
|
+
sessions: z.number().int(),
|
|
55
|
+
durationMs: z.number().int(),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
/** Mirrors `SessionCostByUserRow` in src/be/db.ts. */
|
|
59
|
+
const SessionCostByUserRowSchema = z.object({
|
|
60
|
+
userId: z.string().nullable(),
|
|
61
|
+
costUsd: z.number(),
|
|
62
|
+
inputTokens: z.number().int(),
|
|
63
|
+
outputTokens: z.number().int(),
|
|
64
|
+
tasks: z.number().int(),
|
|
65
|
+
durationMs: z.number().int(),
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
/** Mirrors the return type of `getSessionCostSummary` in src/be/db.ts. */
|
|
69
|
+
const SessionCostSummarySchema = z.object({
|
|
70
|
+
totals: SessionCostSummaryTotalsSchema,
|
|
71
|
+
daily: z.array(SessionCostDailyRowSchema),
|
|
72
|
+
byAgent: z.array(SessionCostByAgentRowSchema),
|
|
73
|
+
byUser: z.array(SessionCostByUserRowSchema),
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
/** Mirrors `DashboardCostSummary` in src/be/db.ts. */
|
|
77
|
+
const DashboardCostSummarySchema = z.object({
|
|
78
|
+
costToday: z.number(),
|
|
79
|
+
costMtd: z.number(),
|
|
80
|
+
});
|
|
23
81
|
|
|
24
82
|
// ─── Route Definitions ───────────────────────────────────────────────────────
|
|
25
83
|
|
|
@@ -37,7 +95,10 @@ const createSessionLogsRoute = route({
|
|
|
37
95
|
cli: z.string().optional(),
|
|
38
96
|
}),
|
|
39
97
|
responses: {
|
|
40
|
-
201: {
|
|
98
|
+
201: {
|
|
99
|
+
description: "Logs stored",
|
|
100
|
+
schema: z.object({ success: z.literal(true), count: z.number().int().nonnegative() }),
|
|
101
|
+
},
|
|
41
102
|
400: { description: "Validation error" },
|
|
42
103
|
},
|
|
43
104
|
});
|
|
@@ -57,7 +118,10 @@ const getSessionLogsByTask = route({
|
|
|
57
118
|
limit: z.coerce.number().int().min(1).max(1000).optional(),
|
|
58
119
|
}),
|
|
59
120
|
responses: {
|
|
60
|
-
200: {
|
|
121
|
+
200: {
|
|
122
|
+
description: "Session logs",
|
|
123
|
+
schema: z.object({ logs: z.array(SessionLogSchema) }),
|
|
124
|
+
},
|
|
61
125
|
404: { description: "Task not found" },
|
|
62
126
|
},
|
|
63
127
|
});
|
|
@@ -111,7 +175,10 @@ const createSessionCostRoute = route({
|
|
|
111
175
|
createdAt: z.number().int().nonnegative().optional(),
|
|
112
176
|
}),
|
|
113
177
|
responses: {
|
|
114
|
-
201: {
|
|
178
|
+
201: {
|
|
179
|
+
description: "Cost record stored",
|
|
180
|
+
schema: z.object({ success: z.literal(true), cost: SessionCostSchema }),
|
|
181
|
+
},
|
|
115
182
|
400: { description: "Validation error" },
|
|
116
183
|
},
|
|
117
184
|
});
|
|
@@ -131,7 +198,7 @@ const getSessionCostSummaryRoute = route({
|
|
|
131
198
|
userId: z.string().optional(),
|
|
132
199
|
}),
|
|
133
200
|
responses: {
|
|
134
|
-
200: { description: "Cost summary" },
|
|
201
|
+
200: { description: "Cost summary", schema: SessionCostSummarySchema },
|
|
135
202
|
400: { description: "Invalid groupBy" },
|
|
136
203
|
},
|
|
137
204
|
});
|
|
@@ -143,7 +210,7 @@ const getDashboardCosts = route({
|
|
|
143
210
|
summary: "Cost today and month-to-date for dashboard",
|
|
144
211
|
tags: ["Session Data"],
|
|
145
212
|
responses: {
|
|
146
|
-
200: { description: "Dashboard cost data" },
|
|
213
|
+
200: { description: "Dashboard cost data", schema: DashboardCostSummarySchema },
|
|
147
214
|
},
|
|
148
215
|
});
|
|
149
216
|
|
|
@@ -161,7 +228,10 @@ const listSessionCosts = route({
|
|
|
161
228
|
limit: z.coerce.number().int().min(1).optional(),
|
|
162
229
|
}),
|
|
163
230
|
responses: {
|
|
164
|
-
200: {
|
|
231
|
+
200: {
|
|
232
|
+
description: "Session costs",
|
|
233
|
+
schema: z.object({ costs: z.array(SessionCostSchema) }),
|
|
234
|
+
},
|
|
165
235
|
},
|
|
166
236
|
});
|
|
167
237
|
|
|
@@ -186,7 +256,10 @@ export async function handleSessionData(
|
|
|
186
256
|
cli: parsed.body.cli || "claude",
|
|
187
257
|
lines: parsed.body.lines,
|
|
188
258
|
});
|
|
189
|
-
|
|
259
|
+
createSessionLogsRoute.respond(res, 201, {
|
|
260
|
+
success: true,
|
|
261
|
+
count: parsed.body.lines.length,
|
|
262
|
+
});
|
|
190
263
|
} catch (error) {
|
|
191
264
|
console.error("[HTTP] Failed to create session logs:", error);
|
|
192
265
|
jsonError(res, "Failed to store session logs", 500);
|
|
@@ -203,7 +276,7 @@ export async function handleSessionData(
|
|
|
203
276
|
return true;
|
|
204
277
|
}
|
|
205
278
|
const logs = getSessionLogsByTaskId(parsed.params.taskId, parsed.query?.limit);
|
|
206
|
-
|
|
279
|
+
getSessionLogsByTask.respond(res, 200, { logs });
|
|
207
280
|
return true;
|
|
208
281
|
}
|
|
209
282
|
|
|
@@ -302,7 +375,7 @@ export async function handleSessionData(
|
|
|
302
375
|
},
|
|
303
376
|
});
|
|
304
377
|
incrementServerSessionsProcessed();
|
|
305
|
-
|
|
378
|
+
createSessionCostRoute.respond(res, 201, { success: true, cost });
|
|
306
379
|
} catch (error) {
|
|
307
380
|
console.error("[HTTP] Failed to create session cost:", error);
|
|
308
381
|
jsonError(res, "Failed to store session cost", 500);
|
|
@@ -320,13 +393,13 @@ export async function handleSessionData(
|
|
|
320
393
|
userId: parsed.query.userId || undefined,
|
|
321
394
|
groupBy: parsed.query.groupBy || "both",
|
|
322
395
|
});
|
|
323
|
-
|
|
396
|
+
getSessionCostSummaryRoute.respond(res, 200, summary);
|
|
324
397
|
return true;
|
|
325
398
|
}
|
|
326
399
|
|
|
327
400
|
if (getDashboardCosts.match(req.method, pathSegments)) {
|
|
328
401
|
const dashboardCosts = getDashboardCostSummary();
|
|
329
|
-
|
|
402
|
+
getDashboardCosts.respond(res, 200, dashboardCosts);
|
|
330
403
|
return true;
|
|
331
404
|
}
|
|
332
405
|
|
|
@@ -352,7 +425,7 @@ export async function handleSessionData(
|
|
|
352
425
|
costs = getAllSessionCosts(limit);
|
|
353
426
|
}
|
|
354
427
|
|
|
355
|
-
|
|
428
|
+
listSessionCosts.respond(res, 200, { costs });
|
|
356
429
|
return true;
|
|
357
430
|
}
|
|
358
431
|
|
package/src/http/sessions.ts
CHANGED
|
@@ -2,8 +2,69 @@ import type { IncomingMessage, ServerResponse } from "node:http";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { countSessions, getRootTaskChain, getTaskById, listRecentSessions } from "../be/db";
|
|
4
4
|
import { getTaskSteeringFields } from "../be/steering";
|
|
5
|
+
import { AgentTaskSchema, AgentTaskStatusSchema, SteerModeSchema } from "../types";
|
|
5
6
|
import { route } from "./route-def";
|
|
6
|
-
import {
|
|
7
|
+
import { jsonError } from "./utils";
|
|
8
|
+
|
|
9
|
+
// ─── Response Schemas ────────────────────────────────────────────────────────
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* `/api/sessions` list item's `root` when slim (default) — mirrors the
|
|
13
|
+
* `AgentTaskSummary` TS type in ../types: the `task` text truncated to a
|
|
14
|
+
* bounded preview and completion/integration/context blobs dropped. Kept in
|
|
15
|
+
* lock-step with that type's `Pick<...>` field list (mirrors the sibling
|
|
16
|
+
* definition in src/http/tasks.ts — not imported from there since it isn't
|
|
17
|
+
* exported).
|
|
18
|
+
*/
|
|
19
|
+
const AgentTaskSummarySchema = AgentTaskSchema.pick({
|
|
20
|
+
id: true,
|
|
21
|
+
key: true,
|
|
22
|
+
agentId: true,
|
|
23
|
+
creatorAgentId: true,
|
|
24
|
+
task: true,
|
|
25
|
+
title: true,
|
|
26
|
+
status: true,
|
|
27
|
+
source: true,
|
|
28
|
+
taskType: true,
|
|
29
|
+
tags: true,
|
|
30
|
+
priority: true,
|
|
31
|
+
dependsOn: true,
|
|
32
|
+
offeredTo: true,
|
|
33
|
+
acceptedAt: true,
|
|
34
|
+
parentTaskId: true,
|
|
35
|
+
scheduleId: true,
|
|
36
|
+
model: true,
|
|
37
|
+
modelTier: true,
|
|
38
|
+
effort: true,
|
|
39
|
+
provider: true,
|
|
40
|
+
requestedByUserId: true,
|
|
41
|
+
progress: true,
|
|
42
|
+
createdAt: true,
|
|
43
|
+
lastUpdatedAt: true,
|
|
44
|
+
finishedAt: true,
|
|
45
|
+
peakContextPercent: true,
|
|
46
|
+
totalCostUsd: true,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A `/api/sessions` list item. `root` is a full `AgentTask` when
|
|
51
|
+
* `?fields=full`, an `AgentTaskSummary` otherwise (default).
|
|
52
|
+
*/
|
|
53
|
+
const SessionListItemSchema = z.object({
|
|
54
|
+
root: z.union([AgentTaskSchema, AgentTaskSummarySchema]),
|
|
55
|
+
chainTaskCount: z.number().int(),
|
|
56
|
+
lastActivityAt: z.string(),
|
|
57
|
+
latestStatus: AgentTaskStatusSchema,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* A full `AgentTask` decorated with `getTaskSteeringFields` — the shape of
|
|
62
|
+
* `root` and each `chain` entry on `GET /api/sessions/{rootTaskId}`.
|
|
63
|
+
*/
|
|
64
|
+
const TaskWithSteeringSchema = AgentTaskSchema.extend({
|
|
65
|
+
isLeadTask: z.boolean(),
|
|
66
|
+
supportedSteerModes: z.array(SteerModeSchema),
|
|
67
|
+
});
|
|
7
68
|
|
|
8
69
|
// ─── Route Definitions ───────────────────────────────────────────────────────
|
|
9
70
|
|
|
@@ -32,7 +93,15 @@ const listSessions = route({
|
|
|
32
93
|
fields: z.enum(["full", "slim"]).optional(),
|
|
33
94
|
}),
|
|
34
95
|
responses: {
|
|
35
|
-
200: {
|
|
96
|
+
200: {
|
|
97
|
+
description: "Recent sessions ordered by chain-wide last activity",
|
|
98
|
+
schema: z.object({
|
|
99
|
+
sessions: z.array(SessionListItemSchema),
|
|
100
|
+
total: z.number().int(),
|
|
101
|
+
limit: z.number().int(),
|
|
102
|
+
offset: z.number().int(),
|
|
103
|
+
}),
|
|
104
|
+
},
|
|
36
105
|
401: { description: "Unauthorized" },
|
|
37
106
|
},
|
|
38
107
|
auth: { apiKey: true },
|
|
@@ -46,7 +115,13 @@ const getSession = route({
|
|
|
46
115
|
tags: ["Sessions"],
|
|
47
116
|
params: z.object({ rootTaskId: z.string() }),
|
|
48
117
|
responses: {
|
|
49
|
-
200: {
|
|
118
|
+
200: {
|
|
119
|
+
description: "Root task + chain (ordered by createdAt)",
|
|
120
|
+
schema: z.object({
|
|
121
|
+
root: TaskWithSteeringSchema,
|
|
122
|
+
chain: z.array(TaskWithSteeringSchema),
|
|
123
|
+
}),
|
|
124
|
+
},
|
|
50
125
|
401: { description: "Unauthorized" },
|
|
51
126
|
404: { description: "Root task not found" },
|
|
52
127
|
},
|
|
@@ -89,7 +164,7 @@ export async function handleSessions(
|
|
|
89
164
|
q: parsed.query.q,
|
|
90
165
|
requestedByUserId: parsed.query.requestedByUserId,
|
|
91
166
|
});
|
|
92
|
-
|
|
167
|
+
listSessions.respond(res, 200, {
|
|
93
168
|
sessions,
|
|
94
169
|
total,
|
|
95
170
|
limit: parsed.query.limit ?? 25,
|
|
@@ -107,7 +182,7 @@ export async function handleSessions(
|
|
|
107
182
|
return true;
|
|
108
183
|
}
|
|
109
184
|
const chain = getRootTaskChain(parsed.params.rootTaskId);
|
|
110
|
-
|
|
185
|
+
getSession.respond(res, 200, {
|
|
111
186
|
root: { ...root, ...getTaskSteeringFields(root) },
|
|
112
187
|
chain: chain.map((task) => ({ ...task, ...getTaskSteeringFields(task) })),
|
|
113
188
|
});
|
package/src/http/skills.ts
CHANGED
|
@@ -18,8 +18,14 @@ import {
|
|
|
18
18
|
} from "../be/db";
|
|
19
19
|
import { parseSkillContent } from "../be/skill-parser";
|
|
20
20
|
import { computeAgentSkillsSignature, syncSkillsToFilesystem } from "../be/skill-sync";
|
|
21
|
+
import {
|
|
22
|
+
AgentSkillSchema,
|
|
23
|
+
SkillFileSchema,
|
|
24
|
+
SkillSchema,
|
|
25
|
+
SkillWithInstallInfoSchema,
|
|
26
|
+
} from "../types";
|
|
21
27
|
import { route } from "./route-def";
|
|
22
|
-
import {
|
|
28
|
+
import { jsonError } from "./utils";
|
|
23
29
|
|
|
24
30
|
const SYSTEM_DEFAULT_SKILL_LOCKED_MESSAGE =
|
|
25
31
|
"This skill is system-managed and cannot be edited from the UI; it is re-seeded on each start. Fork it under a new name to customize.";
|
|
@@ -35,6 +41,72 @@ const skillFileWithPathSchema = skillFileBodySchema.extend({
|
|
|
35
41
|
path: z.string().min(1),
|
|
36
42
|
});
|
|
37
43
|
|
|
44
|
+
// ─── Response Schemas ────────────────────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
/** Bundled-file manifest entry — `SkillFile` minus the heavy `content` field. */
|
|
47
|
+
const skillFileManifestEntrySchema = SkillFileSchema.omit({ content: true });
|
|
48
|
+
|
|
49
|
+
const skillsListResponseSchema = z.object({
|
|
50
|
+
skills: z.array(SkillSchema),
|
|
51
|
+
total: z.number(),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const skillFileManifestResponseSchema = z.object({
|
|
55
|
+
files: z.array(skillFileManifestEntrySchema),
|
|
56
|
+
total: z.number(),
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const bulkUpsertSkillFilesResponseSchema = z.object({
|
|
60
|
+
files: z.array(SkillFileSchema),
|
|
61
|
+
total: z.number(),
|
|
62
|
+
skill: SkillSchema.nullable(),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const skillFileResponseSchema = z.object({ file: SkillFileSchema });
|
|
66
|
+
|
|
67
|
+
const skillFileWithSkillResponseSchema = z.object({
|
|
68
|
+
file: SkillFileSchema,
|
|
69
|
+
skill: SkillSchema.nullable(),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const deleteSkillFileResponseSchema = z.object({
|
|
73
|
+
success: z.literal(true),
|
|
74
|
+
skill: SkillSchema.nullable(),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const skillWrapperResponseSchema = z.object({ skill: SkillSchema });
|
|
78
|
+
|
|
79
|
+
const deleteSuccessResponseSchema = z.object({ success: z.literal(true) });
|
|
80
|
+
|
|
81
|
+
const installSkillResponseSchema = z.object({ agentSkill: AgentSkillSchema });
|
|
82
|
+
|
|
83
|
+
const uninstallSkillResponseSchema = z.object({ success: z.boolean() });
|
|
84
|
+
|
|
85
|
+
const syncRemoteResponseSchema = z.object({
|
|
86
|
+
updated: z.number(),
|
|
87
|
+
checked: z.number(),
|
|
88
|
+
errors: z.array(z.string()),
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const syncFilesystemResponseSchema = z.object({
|
|
92
|
+
synced: z.number(),
|
|
93
|
+
removed: z.number(),
|
|
94
|
+
errors: z.array(z.string()),
|
|
95
|
+
message: z.string(),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const agentSkillsListResponseSchema = z.object({
|
|
99
|
+
skills: z.array(SkillWithInstallInfoSchema),
|
|
100
|
+
total: z.number(),
|
|
101
|
+
signature: z.string(),
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const agentSkillsSignatureResponseSchema = z.object({
|
|
105
|
+
hash: z.string(),
|
|
106
|
+
count: z.number(),
|
|
107
|
+
generatedAt: z.string(),
|
|
108
|
+
});
|
|
109
|
+
|
|
38
110
|
function decodeSkillFilePath(pathSegments: string[]): string {
|
|
39
111
|
return pathSegments
|
|
40
112
|
.slice(4)
|
|
@@ -63,7 +135,7 @@ const listSkillsRoute = route({
|
|
|
63
135
|
fields: z.enum(["full", "slim"]).optional(),
|
|
64
136
|
}),
|
|
65
137
|
responses: {
|
|
66
|
-
200: { description: "Skill list" },
|
|
138
|
+
200: { description: "Skill list", schema: skillsListResponseSchema },
|
|
67
139
|
},
|
|
68
140
|
});
|
|
69
141
|
|
|
@@ -76,7 +148,7 @@ const getSkillRoute = route({
|
|
|
76
148
|
auth: { apiKey: true },
|
|
77
149
|
params: z.object({ id: z.string() }),
|
|
78
150
|
responses: {
|
|
79
|
-
200: { description: "Skill details" },
|
|
151
|
+
200: { description: "Skill details", schema: SkillSchema },
|
|
80
152
|
404: { description: "Skill not found" },
|
|
81
153
|
},
|
|
82
154
|
});
|
|
@@ -91,7 +163,7 @@ const listSkillFilesRoute = route({
|
|
|
91
163
|
auth: { apiKey: true },
|
|
92
164
|
params: z.object({ id: z.string() }),
|
|
93
165
|
responses: {
|
|
94
|
-
200: { description: "Skill file manifest" },
|
|
166
|
+
200: { description: "Skill file manifest", schema: skillFileManifestResponseSchema },
|
|
95
167
|
404: { description: "Skill not found" },
|
|
96
168
|
},
|
|
97
169
|
});
|
|
@@ -109,7 +181,7 @@ const bulkUpsertSkillFilesRoute = route({
|
|
|
109
181
|
files: z.array(skillFileWithPathSchema).max(100),
|
|
110
182
|
}),
|
|
111
183
|
responses: {
|
|
112
|
-
200: { description: "Skill files upserted" },
|
|
184
|
+
200: { description: "Skill files upserted", schema: bulkUpsertSkillFilesResponseSchema },
|
|
113
185
|
400: { description: "Validation error" },
|
|
114
186
|
404: { description: "Skill not found" },
|
|
115
187
|
},
|
|
@@ -125,7 +197,7 @@ const getSkillFileRoute = route({
|
|
|
125
197
|
auth: { apiKey: true },
|
|
126
198
|
params: z.object({ id: z.string(), path: z.string() }),
|
|
127
199
|
responses: {
|
|
128
|
-
200: { description: "Skill file" },
|
|
200
|
+
200: { description: "Skill file", schema: skillFileResponseSchema },
|
|
129
201
|
404: { description: "Skill or file not found" },
|
|
130
202
|
},
|
|
131
203
|
});
|
|
@@ -142,7 +214,7 @@ const upsertSkillFileRoute = route({
|
|
|
142
214
|
params: z.object({ id: z.string(), path: z.string() }),
|
|
143
215
|
body: skillFileBodySchema,
|
|
144
216
|
responses: {
|
|
145
|
-
200: { description: "Skill file upserted" },
|
|
217
|
+
200: { description: "Skill file upserted", schema: skillFileWithSkillResponseSchema },
|
|
146
218
|
400: { description: "Validation error" },
|
|
147
219
|
404: { description: "Skill not found" },
|
|
148
220
|
},
|
|
@@ -159,7 +231,7 @@ const deleteSkillFileRoute = route({
|
|
|
159
231
|
rbac: { permission: "skill.update.any" },
|
|
160
232
|
params: z.object({ id: z.string(), path: z.string() }),
|
|
161
233
|
responses: {
|
|
162
|
-
200: { description: "Skill file deleted" },
|
|
234
|
+
200: { description: "Skill file deleted", schema: deleteSkillFileResponseSchema },
|
|
163
235
|
404: { description: "Skill or file not found" },
|
|
164
236
|
},
|
|
165
237
|
});
|
|
@@ -180,7 +252,7 @@ const createSkillRoute = route({
|
|
|
180
252
|
systemDefault: z.boolean().optional(),
|
|
181
253
|
}),
|
|
182
254
|
responses: {
|
|
183
|
-
201: { description: "Skill created" },
|
|
255
|
+
201: { description: "Skill created", schema: skillWrapperResponseSchema },
|
|
184
256
|
400: { description: "Validation error" },
|
|
185
257
|
},
|
|
186
258
|
});
|
|
@@ -196,7 +268,7 @@ const updateSkillRoute = route({
|
|
|
196
268
|
params: z.object({ id: z.string() }),
|
|
197
269
|
body: z.record(z.string(), z.unknown()),
|
|
198
270
|
responses: {
|
|
199
|
-
200: { description: "Skill updated" },
|
|
271
|
+
200: { description: "Skill updated", schema: skillWrapperResponseSchema },
|
|
200
272
|
403: { description: "System-managed skills cannot be edited" },
|
|
201
273
|
404: { description: "Skill not found" },
|
|
202
274
|
},
|
|
@@ -212,7 +284,7 @@ const deleteSkillRoute = route({
|
|
|
212
284
|
rbac: { permission: "skill.delete.any" },
|
|
213
285
|
params: z.object({ id: z.string() }),
|
|
214
286
|
responses: {
|
|
215
|
-
200: { description: "Skill deleted" },
|
|
287
|
+
200: { description: "Skill deleted", schema: deleteSuccessResponseSchema },
|
|
216
288
|
403: { description: "System-managed skills cannot be deleted" },
|
|
217
289
|
404: { description: "Skill not found" },
|
|
218
290
|
},
|
|
@@ -231,7 +303,7 @@ const installSkillRoute = route({
|
|
|
231
303
|
agentId: z.string(),
|
|
232
304
|
}),
|
|
233
305
|
responses: {
|
|
234
|
-
200: { description: "Skill installed" },
|
|
306
|
+
200: { description: "Skill installed", schema: installSkillResponseSchema },
|
|
235
307
|
404: { description: "Skill not found" },
|
|
236
308
|
},
|
|
237
309
|
});
|
|
@@ -246,7 +318,7 @@ const uninstallSkillRoute = route({
|
|
|
246
318
|
rbac: { permission: "skill.uninstall.any" },
|
|
247
319
|
params: z.object({ id: z.string(), agentId: z.string() }),
|
|
248
320
|
responses: {
|
|
249
|
-
200: { description: "Skill uninstalled" },
|
|
321
|
+
200: { description: "Skill uninstalled", schema: uninstallSkillResponseSchema },
|
|
250
322
|
},
|
|
251
323
|
});
|
|
252
324
|
|
|
@@ -265,7 +337,7 @@ const installRemoteRoute = route({
|
|
|
265
337
|
isComplex: z.boolean().optional(),
|
|
266
338
|
}),
|
|
267
339
|
responses: {
|
|
268
|
-
201: { description: "Remote skill installed" },
|
|
340
|
+
201: { description: "Remote skill installed", schema: skillWrapperResponseSchema },
|
|
269
341
|
400: { description: "Fetch failed" },
|
|
270
342
|
},
|
|
271
343
|
});
|
|
@@ -283,7 +355,7 @@ const syncRemoteRoute = route({
|
|
|
283
355
|
force: z.boolean().optional(),
|
|
284
356
|
}),
|
|
285
357
|
responses: {
|
|
286
|
-
200: { description: "Sync results" },
|
|
358
|
+
200: { description: "Sync results", schema: syncRemoteResponseSchema },
|
|
287
359
|
},
|
|
288
360
|
});
|
|
289
361
|
|
|
@@ -296,7 +368,7 @@ const syncFilesystemRoute = route({
|
|
|
296
368
|
auth: { apiKey: true, agentId: true },
|
|
297
369
|
rbac: { ungated: "self-scoped: syncs the caller's own agent FS" },
|
|
298
370
|
responses: {
|
|
299
|
-
200: { description: "Filesystem sync results" },
|
|
371
|
+
200: { description: "Filesystem sync results", schema: syncFilesystemResponseSchema },
|
|
300
372
|
},
|
|
301
373
|
});
|
|
302
374
|
|
|
@@ -309,7 +381,7 @@ const getAgentSkillsRoute = route({
|
|
|
309
381
|
auth: { apiKey: true },
|
|
310
382
|
params: z.object({ id: z.string() }),
|
|
311
383
|
responses: {
|
|
312
|
-
200: { description: "Agent skills list" },
|
|
384
|
+
200: { description: "Agent skills list", schema: agentSkillsListResponseSchema },
|
|
313
385
|
},
|
|
314
386
|
});
|
|
315
387
|
|
|
@@ -324,7 +396,7 @@ const getAgentSkillsSignatureRoute = route({
|
|
|
324
396
|
auth: { apiKey: true },
|
|
325
397
|
params: z.object({ id: z.string() }),
|
|
326
398
|
responses: {
|
|
327
|
-
200: { description: "Skills signature" },
|
|
399
|
+
200: { description: "Skills signature", schema: agentSkillsSignatureResponseSchema },
|
|
328
400
|
},
|
|
329
401
|
});
|
|
330
402
|
|
|
@@ -342,7 +414,11 @@ export async function handleSkills(
|
|
|
342
414
|
const parsed = await getAgentSkillsSignatureRoute.parse(req, res, pathSegments, queryParams);
|
|
343
415
|
if (!parsed) return true;
|
|
344
416
|
const sig = computeAgentSkillsSignature(parsed.params.id);
|
|
345
|
-
|
|
417
|
+
getAgentSkillsSignatureRoute.respond(res, 200, {
|
|
418
|
+
hash: sig.hash,
|
|
419
|
+
count: sig.count,
|
|
420
|
+
generatedAt: new Date().toISOString(),
|
|
421
|
+
});
|
|
346
422
|
return true;
|
|
347
423
|
}
|
|
348
424
|
|
|
@@ -352,7 +428,7 @@ export async function handleSkills(
|
|
|
352
428
|
if (!parsed) return true;
|
|
353
429
|
const skills = getAgentSkills(parsed.params.id);
|
|
354
430
|
const signature = computeAgentSkillsSignature(parsed.params.id).hash;
|
|
355
|
-
|
|
431
|
+
getAgentSkillsRoute.respond(res, 200, { skills, total: skills.length, signature });
|
|
356
432
|
return true;
|
|
357
433
|
}
|
|
358
434
|
|
|
@@ -400,7 +476,7 @@ export async function handleSkills(
|
|
|
400
476
|
isComplex: parsed.body.isComplex ?? false,
|
|
401
477
|
});
|
|
402
478
|
|
|
403
|
-
|
|
479
|
+
installRemoteRoute.respond(res, 201, { skill });
|
|
404
480
|
} catch (err) {
|
|
405
481
|
jsonError(res, err instanceof Error ? err.message : "Unknown error", 400);
|
|
406
482
|
}
|
|
@@ -462,7 +538,7 @@ export async function handleSkills(
|
|
|
462
538
|
}
|
|
463
539
|
}
|
|
464
540
|
|
|
465
|
-
|
|
541
|
+
syncRemoteRoute.respond(res, 200, { updated, checked: remoteSkills.length, errors });
|
|
466
542
|
return true;
|
|
467
543
|
}
|
|
468
544
|
|
|
@@ -476,7 +552,7 @@ export async function handleSkills(
|
|
|
476
552
|
}
|
|
477
553
|
|
|
478
554
|
const result = syncSkillsToFilesystem(agentId);
|
|
479
|
-
|
|
555
|
+
syncFilesystemRoute.respond(res, 200, {
|
|
480
556
|
synced: result.synced,
|
|
481
557
|
removed: result.removed,
|
|
482
558
|
errors: result.errors,
|
|
@@ -498,7 +574,7 @@ export async function handleSkills(
|
|
|
498
574
|
|
|
499
575
|
try {
|
|
500
576
|
const agentSkill = installSkill(parsed.body.agentId, parsed.params.id);
|
|
501
|
-
|
|
577
|
+
installSkillRoute.respond(res, 200, { agentSkill });
|
|
502
578
|
} catch (err) {
|
|
503
579
|
jsonError(res, err instanceof Error ? err.message : "Install failed", 400);
|
|
504
580
|
}
|
|
@@ -511,7 +587,7 @@ export async function handleSkills(
|
|
|
511
587
|
if (!parsed) return true;
|
|
512
588
|
|
|
513
589
|
const removed = uninstallSkill(parsed.params.agentId, parsed.params.id);
|
|
514
|
-
|
|
590
|
+
uninstallSkillRoute.respond(res, 200, { success: removed });
|
|
515
591
|
return true;
|
|
516
592
|
}
|
|
517
593
|
|
|
@@ -533,7 +609,7 @@ export async function handleSkills(
|
|
|
533
609
|
includeContent,
|
|
534
610
|
});
|
|
535
611
|
|
|
536
|
-
|
|
612
|
+
listSkillsRoute.respond(res, 200, { skills, total: skills.length });
|
|
537
613
|
return true;
|
|
538
614
|
}
|
|
539
615
|
|
|
@@ -549,7 +625,7 @@ export async function handleSkills(
|
|
|
549
625
|
}
|
|
550
626
|
|
|
551
627
|
const files = listSkillFileManifest(parsed.params.id);
|
|
552
|
-
|
|
628
|
+
listSkillFilesRoute.respond(res, 200, { files, total: files.length });
|
|
553
629
|
return true;
|
|
554
630
|
}
|
|
555
631
|
|
|
@@ -571,7 +647,11 @@ export async function handleSkills(
|
|
|
571
647
|
try {
|
|
572
648
|
const files = upsertSkillFiles(parsed.params.id, parsed.body.files);
|
|
573
649
|
const updatedSkill = getSkillById(parsed.params.id);
|
|
574
|
-
|
|
650
|
+
bulkUpsertSkillFilesRoute.respond(res, 200, {
|
|
651
|
+
files,
|
|
652
|
+
total: files.length,
|
|
653
|
+
skill: updatedSkill,
|
|
654
|
+
});
|
|
575
655
|
} catch (err) {
|
|
576
656
|
jsonError(res, err instanceof Error ? err.message : "Failed to upsert files", 400);
|
|
577
657
|
}
|
|
@@ -595,7 +675,7 @@ export async function handleSkills(
|
|
|
595
675
|
jsonError(res, "Skill file not found", 404);
|
|
596
676
|
return true;
|
|
597
677
|
}
|
|
598
|
-
|
|
678
|
+
getSkillFileRoute.respond(res, 200, { file });
|
|
599
679
|
} catch (err) {
|
|
600
680
|
jsonError(res, err instanceof Error ? err.message : "Invalid file path", 400);
|
|
601
681
|
}
|
|
@@ -623,7 +703,7 @@ export async function handleSkills(
|
|
|
623
703
|
...parsed.body,
|
|
624
704
|
});
|
|
625
705
|
const updatedSkill = getSkillById(parsed.params.id);
|
|
626
|
-
|
|
706
|
+
upsertSkillFileRoute.respond(res, 200, { file, skill: updatedSkill });
|
|
627
707
|
} catch (err) {
|
|
628
708
|
jsonError(res, err instanceof Error ? err.message : "Failed to upsert file", 400);
|
|
629
709
|
}
|
|
@@ -652,7 +732,7 @@ export async function handleSkills(
|
|
|
652
732
|
return true;
|
|
653
733
|
}
|
|
654
734
|
const updatedSkill = getSkillById(parsed.params.id);
|
|
655
|
-
|
|
735
|
+
deleteSkillFileRoute.respond(res, 200, { success: true, skill: updatedSkill });
|
|
656
736
|
} catch (err) {
|
|
657
737
|
jsonError(res, err instanceof Error ? err.message : "Invalid file path", 400);
|
|
658
738
|
}
|
|
@@ -669,7 +749,7 @@ export async function handleSkills(
|
|
|
669
749
|
jsonError(res, "Skill not found", 404);
|
|
670
750
|
return true;
|
|
671
751
|
}
|
|
672
|
-
|
|
752
|
+
getSkillRoute.respond(res, 200, skill);
|
|
673
753
|
return true;
|
|
674
754
|
}
|
|
675
755
|
|
|
@@ -696,7 +776,7 @@ export async function handleSkills(
|
|
|
696
776
|
userInvocable: pm.userInvocable,
|
|
697
777
|
systemDefault: parsed.body.systemDefault,
|
|
698
778
|
});
|
|
699
|
-
|
|
779
|
+
createSkillRoute.respond(res, 201, { skill });
|
|
700
780
|
} catch (err) {
|
|
701
781
|
jsonError(res, err instanceof Error ? err.message : "Create failed", 400);
|
|
702
782
|
}
|
|
@@ -768,7 +848,7 @@ export async function handleSkills(
|
|
|
768
848
|
jsonError(res, "Skill not found", 404);
|
|
769
849
|
return true;
|
|
770
850
|
}
|
|
771
|
-
|
|
851
|
+
updateSkillRoute.respond(res, 200, { skill });
|
|
772
852
|
return true;
|
|
773
853
|
}
|
|
774
854
|
|
|
@@ -792,7 +872,7 @@ export async function handleSkills(
|
|
|
792
872
|
jsonError(res, "Skill not found", 404);
|
|
793
873
|
return true;
|
|
794
874
|
}
|
|
795
|
-
|
|
875
|
+
deleteSkillRoute.respond(res, 200, { success: true });
|
|
796
876
|
return true;
|
|
797
877
|
}
|
|
798
878
|
|