@vellumai/assistant 0.5.9 → 0.5.11
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/AGENTS.md +9 -1
- package/ARCHITECTURE.md +48 -48
- package/Dockerfile +2 -0
- package/README.md +1 -1
- package/docs/architecture/integrations.md +6 -13
- package/docs/architecture/memory.md +7 -12
- package/docs/architecture/security.md +5 -5
- package/docs/credential-execution-service.md +9 -9
- package/docs/skills.md +1 -1
- package/node_modules/@vellumai/credential-storage/src/index.ts +2 -2
- package/node_modules/@vellumai/credential-storage/src/static-credentials.ts +1 -1
- package/openapi.yaml +7130 -0
- package/package.json +2 -1
- package/scripts/generate-openapi.ts +562 -0
- package/src/__tests__/acp-session.test.ts +239 -44
- package/src/__tests__/assistant-feature-flag-guard.test.ts +8 -8
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +5 -86
- package/src/__tests__/assistant-feature-flags-integration.test.ts +7 -14
- package/src/__tests__/browser-skill-endstate.test.ts +1 -1
- package/src/__tests__/btw-routes.test.ts +8 -0
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +10 -10
- package/src/__tests__/channel-approvals.test.ts +7 -7
- package/src/__tests__/channel-readiness-service.test.ts +41 -0
- package/src/__tests__/config-schema.test.ts +10 -2
- package/src/__tests__/context-memory-e2e.test.ts +2 -6
- package/src/__tests__/conversation-skill-tools.test.ts +1 -3
- package/src/__tests__/conversation-title-service.test.ts +2 -15
- package/src/__tests__/credential-execution-feature-gates.test.ts +4 -8
- package/src/__tests__/credential-execution-managed-contract.test.ts +8 -8
- package/src/__tests__/credential-security-e2e.test.ts +4 -4
- package/src/__tests__/credential-security-invariants.test.ts +3 -3
- package/src/__tests__/credentials-cli.test.ts +3 -3
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -1
- package/src/__tests__/gateway-only-guard.test.ts +3 -0
- package/src/__tests__/heartbeat-service.test.ts +35 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -1
- package/src/__tests__/inline-skill-load-permissions.test.ts +3 -3
- package/src/__tests__/llm-request-log-turn-query.test.ts +64 -0
- package/src/__tests__/log-export-workspace.test.ts +1 -1
- package/src/__tests__/mcp-client-auth.test.ts +1 -1
- package/src/__tests__/memory-lifecycle-e2e.test.ts +2 -2
- package/src/__tests__/memory-recall-log-store.test.ts +182 -0
- package/src/__tests__/memory-recall-quality.test.ts +6 -8
- package/src/__tests__/memory-regressions.test.ts +53 -42
- package/src/__tests__/memory-retrieval.benchmark.test.ts +5 -9
- package/src/__tests__/messaging-skill-split.test.ts +2 -17
- package/src/__tests__/oauth-cli.test.ts +98 -551
- package/src/__tests__/platform-callback-registration.test.ts +119 -0
- package/src/__tests__/secret-ingress-channel.test.ts +261 -0
- package/src/__tests__/secret-ingress-cli.test.ts +201 -0
- package/src/__tests__/secret-ingress-http.test.ts +312 -0
- package/src/__tests__/secret-ingress.test.ts +283 -0
- package/src/__tests__/secret-onetime-send.test.ts +4 -4
- package/src/__tests__/skill-feature-flags-integration.test.ts +4 -4
- package/src/__tests__/skill-feature-flags.test.ts +11 -19
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -1
- package/src/__tests__/skill-load-inline-command.test.ts +3 -3
- package/src/__tests__/skill-load-inline-includes.test.ts +2 -2
- package/src/__tests__/skill-memory.test.ts +2 -4
- package/src/__tests__/skill-projection-feature-flag.test.ts +2 -4
- package/src/__tests__/skill-projection.benchmark.test.ts +1 -3
- package/src/__tests__/skills.test.ts +16 -2
- package/src/__tests__/slack-channel-config.test.ts +1 -1
- package/src/__tests__/slack-skill.test.ts +5 -69
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -1
- package/src/__tests__/workspace-migration-015-migrate-credentials-to-keychain.test.ts +5 -238
- package/src/__tests__/workspace-migration-016-migrate-credentials-from-keychain.test.ts +5 -206
- package/src/__tests__/workspace-migration-018-rekey-compound-credential-keys.test.ts +181 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +15 -7
- package/src/acp/client-handler.ts +113 -31
- package/src/acp/session-manager.ts +29 -27
- package/src/approvals/guardian-request-resolvers.ts +1 -1
- package/src/cli/AGENTS.md +73 -0
- package/src/cli/commands/autonomy.ts +3 -5
- package/src/cli/commands/credential-execution.ts +1 -2
- package/src/cli/commands/credentials.ts +4 -4
- package/src/cli/commands/memory.ts +2 -3
- package/src/cli/commands/oauth/__tests__/connect.test.ts +785 -0
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +760 -0
- package/src/cli/commands/oauth/__tests__/mode.test.ts +672 -0
- package/src/cli/commands/oauth/__tests__/ping.test.ts +690 -0
- package/src/cli/commands/oauth/__tests__/status.test.ts +579 -0
- package/src/cli/commands/oauth/__tests__/token.test.ts +467 -0
- package/src/cli/commands/oauth/apps.ts +29 -11
- package/src/cli/commands/oauth/connect.ts +373 -0
- package/src/cli/commands/oauth/connections.ts +14 -493
- package/src/cli/commands/oauth/disconnect.ts +333 -0
- package/src/cli/commands/oauth/index.ts +62 -10
- package/src/cli/commands/oauth/mode.ts +263 -0
- package/src/cli/commands/oauth/ping.ts +222 -0
- package/src/cli/commands/oauth/providers.ts +30 -3
- package/src/cli/commands/oauth/request.ts +576 -0
- package/src/cli/commands/oauth/shared.ts +132 -0
- package/src/cli/commands/oauth/status.ts +202 -0
- package/src/cli/commands/oauth/token.ts +159 -0
- package/src/cli/commands/platform.ts +20 -14
- package/src/cli.ts +82 -17
- package/src/config/assistant-feature-flags.ts +74 -11
- package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +13 -36
- package/src/config/bundled-skills/messaging/TOOLS.json +9 -9
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +1 -1
- package/src/config/bundled-skills/notifications/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/SKILL.md +2 -2
- package/src/config/bundled-skills/settings/SKILL.md +5 -3
- package/src/config/bundled-skills/settings/TOOLS.json +17 -0
- package/src/config/bundled-skills/settings/tools/avatar-get.ts +50 -0
- package/src/config/bundled-skills/settings/tools/avatar-remove.ts +7 -0
- package/src/config/bundled-skills/settings/tools/avatar-update.ts +6 -1
- package/src/config/bundled-skills/settings/tools/identity-avatar.ts +55 -0
- package/src/config/bundled-skills/skills-catalog/SKILL.md +3 -3
- package/src/config/bundled-skills/slack/SKILL.md +58 -44
- package/src/config/bundled-tool-registry.ts +2 -19
- package/src/config/env.ts +5 -1
- package/src/config/feature-flag-registry.json +57 -41
- package/src/config/loader.ts +4 -0
- package/src/config/schemas/platform.ts +0 -8
- package/src/config/schemas/security.ts +9 -1
- package/src/config/schemas/services.ts +1 -1
- package/src/config/skill-state.ts +1 -3
- package/src/config/skills.ts +2 -4
- package/src/credential-execution/feature-gates.ts +9 -16
- package/src/credential-execution/process-manager.ts +12 -0
- package/src/daemon/config-watcher.ts +4 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +10 -0
- package/src/daemon/conversation-agent-loop.ts +49 -2
- package/src/daemon/conversation-memory.ts +0 -1
- package/src/daemon/handlers/config-slack-channel.ts +43 -1
- package/src/daemon/handlers/conversations.ts +41 -33
- package/src/daemon/lifecycle.ts +28 -5
- package/src/daemon/message-types/acp.ts +0 -15
- package/src/daemon/message-types/memory.ts +0 -1
- package/src/daemon/message-types/messages.ts +9 -1
- package/src/daemon/message-types/schedules.ts +9 -0
- package/src/daemon/server.ts +19 -7
- package/src/email/feature-gate.ts +3 -3
- package/src/heartbeat/heartbeat-service.ts +48 -0
- package/src/inbound/platform-callback-registration.ts +61 -7
- package/src/mcp/mcp-oauth-provider.ts +3 -3
- package/src/memory/app-store.ts +3 -3
- package/src/memory/conversation-crud.ts +124 -0
- package/src/memory/conversation-title-service.ts +7 -17
- package/src/memory/db-init.ts +8 -0
- package/src/memory/embedding-local.ts +47 -2
- package/src/memory/indexer.ts +13 -10
- package/src/memory/items-extractor.ts +12 -4
- package/src/memory/job-utils.ts +5 -0
- package/src/memory/jobs-store.ts +10 -2
- package/src/memory/journal-memory.ts +6 -2
- package/src/memory/llm-request-log-store.ts +88 -21
- package/src/memory/memory-recall-log-store.ts +128 -0
- package/src/memory/migrations/194-memory-recall-logs.ts +50 -0
- package/src/memory/migrations/195-oauth-providers-ping-config.ts +23 -0
- package/src/memory/migrations/index.ts +2 -0
- package/src/memory/migrations/validate-migration-state.ts +14 -1
- package/src/memory/retriever.test.ts +4 -5
- package/src/memory/schema/infrastructure.ts +31 -0
- package/src/memory/schema/oauth.ts +3 -0
- package/src/messaging/providers/telegram-bot/adapter.ts +1 -1
- package/src/oauth/connect-orchestrator.ts +54 -0
- package/src/oauth/manual-token-connection.ts +5 -5
- package/src/oauth/oauth-store.ts +26 -5
- package/src/oauth/seed-providers.ts +10 -1
- package/src/permissions/checker.ts +2 -2
- package/src/permissions/trust-client.ts +2 -2
- package/src/platform/client.ts +2 -2
- package/src/prompts/journal-context.ts +6 -1
- package/src/providers/anthropic/client.ts +143 -1
- package/src/runtime/auth/__tests__/middleware.test.ts +19 -0
- package/src/runtime/auth/route-policy.ts +0 -1
- package/src/runtime/btw-sidechain.ts +7 -1
- package/src/runtime/channel-approvals.ts +2 -2
- package/src/runtime/channel-readiness-service.ts +30 -7
- package/src/runtime/http-router.ts +31 -0
- package/src/runtime/http-server.ts +21 -4
- package/src/runtime/http-types.ts +2 -0
- package/src/runtime/pending-interactions.ts +21 -3
- package/src/runtime/routes/acp-routes.ts +46 -28
- package/src/runtime/routes/app-management-routes.ts +123 -0
- package/src/runtime/routes/app-routes.ts +31 -0
- package/src/runtime/routes/approval-routes.ts +108 -3
- package/src/runtime/routes/attachment-routes.ts +45 -0
- package/src/runtime/routes/avatar-routes.ts +16 -0
- package/src/runtime/routes/brain-graph-routes.ts +18 -0
- package/src/runtime/routes/btw-routes.ts +20 -0
- package/src/runtime/routes/call-routes.ts +81 -0
- package/src/runtime/routes/channel-readiness-routes.ts +48 -7
- package/src/runtime/routes/channel-routes.ts +18 -0
- package/src/runtime/routes/channel-verification-routes.ts +49 -1
- package/src/runtime/routes/contact-routes.ts +77 -0
- package/src/runtime/routes/conversation-attention-routes.ts +37 -0
- package/src/runtime/routes/conversation-management-routes.ts +94 -0
- package/src/runtime/routes/conversation-query-routes.ts +78 -0
- package/src/runtime/routes/conversation-routes.ts +115 -38
- package/src/runtime/routes/conversation-starter-routes.ts +29 -0
- package/src/runtime/routes/debug-routes.ts +23 -0
- package/src/runtime/routes/diagnostics-routes.ts +30 -0
- package/src/runtime/routes/documents-routes.ts +42 -0
- package/src/runtime/routes/events-routes.ts +10 -0
- package/src/runtime/routes/global-search-routes.ts +35 -0
- package/src/runtime/routes/guardian-action-routes.ts +47 -2
- package/src/runtime/routes/guardian-approval-prompt.ts +77 -2
- package/src/runtime/routes/heartbeat-routes.ts +278 -0
- package/src/runtime/routes/host-bash-routes.ts +16 -1
- package/src/runtime/routes/host-cu-routes.ts +23 -1
- package/src/runtime/routes/host-file-routes.ts +18 -1
- package/src/runtime/routes/identity-routes.ts +35 -0
- package/src/runtime/routes/inbound-message-handler.ts +46 -25
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +30 -2
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +1 -2
- package/src/runtime/routes/integrations/twilio.ts +32 -22
- package/src/runtime/routes/invite-routes.ts +83 -0
- package/src/runtime/routes/log-export-routes.ts +14 -0
- package/src/runtime/routes/memory-item-routes.ts +99 -1
- package/src/runtime/routes/migration-rollback-routes.ts +25 -0
- package/src/runtime/routes/migration-routes.ts +40 -0
- package/src/runtime/routes/notification-routes.ts +20 -0
- package/src/runtime/routes/oauth-apps.ts +11 -3
- package/src/runtime/routes/pairing-routes.ts +15 -0
- package/src/runtime/routes/recording-routes.ts +72 -0
- package/src/runtime/routes/schedule-routes.ts +77 -5
- package/src/runtime/routes/secret-routes.ts +63 -1
- package/src/runtime/routes/settings-routes.ts +91 -1
- package/src/runtime/routes/skills-routes.ts +98 -16
- package/src/runtime/routes/subagents-routes.ts +38 -3
- package/src/runtime/routes/surface-action-routes.ts +66 -24
- package/src/runtime/routes/surface-content-routes.ts +20 -0
- package/src/runtime/routes/telemetry-routes.ts +12 -0
- package/src/runtime/routes/trace-event-routes.ts +25 -0
- package/src/runtime/routes/trust-rules-routes.ts +46 -0
- package/src/runtime/routes/tts-routes.ts +15 -4
- package/src/runtime/routes/upgrade-broadcast-routes.ts +38 -0
- package/src/runtime/routes/usage-routes.ts +59 -0
- package/src/runtime/routes/watch-routes.ts +28 -0
- package/src/runtime/routes/work-items-routes.ts +59 -0
- package/src/runtime/routes/workspace-commit-routes.ts +12 -0
- package/src/runtime/routes/workspace-routes.ts +102 -0
- package/src/schedule/scheduler.ts +7 -1
- package/src/security/AGENTS.md +7 -0
- package/src/security/credential-backend.ts +1 -1
- package/src/security/encrypted-store.ts +3 -3
- package/src/security/oauth2.ts +55 -0
- package/src/security/secret-ingress.ts +174 -0
- package/src/security/secret-patterns.ts +133 -0
- package/src/security/secret-scanner.ts +28 -117
- package/src/signals/confirm.ts +12 -8
- package/src/signals/user-message.ts +18 -3
- package/src/skills/skill-memory.ts +1 -2
- package/src/tasks/task-runner.ts +7 -1
- package/src/tools/credentials/broker.ts +1 -1
- package/src/tools/credentials/metadata-store.ts +1 -1
- package/src/tools/credentials/vault.ts +2 -3
- package/src/tools/memory/definitions.ts +1 -1
- package/src/tools/memory/handlers.test.ts +2 -4
- package/src/tools/skills/load.ts +1 -1
- package/src/tools/terminal/safe-env.ts +7 -0
- package/src/tools/tool-manifest.ts +1 -1
- package/src/util/log-redact.ts +9 -34
- package/src/workspace/migrations/015-migrate-credentials-to-keychain.ts +13 -148
- package/src/workspace/migrations/016-migrate-credentials-from-keychain.ts +7 -145
- package/src/workspace/migrations/AGENTS.md +11 -0
- package/src/workspace/migrations/runner.ts +16 -6
- package/src/workspace/migrations/types.ts +7 -0
- package/docs/architecture/keychain-broker.md +0 -69
- package/src/__tests__/keychain-broker-client.test.ts +0 -800
- package/src/cli/commands/oauth/platform.ts +0 -525
- package/src/config/bundled-skills/slack/TOOLS.json +0 -272
- package/src/config/bundled-skills/slack/tools/shared.ts +0 -34
- package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +0 -27
- package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +0 -38
- package/src/config/bundled-skills/slack/tools/slack-channel-permissions.ts +0 -146
- package/src/config/bundled-skills/slack/tools/slack-configure-channels.ts +0 -105
- package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +0 -26
- package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +0 -27
- package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +0 -25
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +0 -372
- package/src/security/keychain-broker-client.ts +0 -446
|
@@ -4,12 +4,16 @@
|
|
|
4
4
|
* POST /v1/surface-actions — dispatch a surface action to an active conversation.
|
|
5
5
|
* Requires the conversation to already exist (does not create new conversations).
|
|
6
6
|
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
|
|
9
|
+
import { isHttpAuthDisabled } from "../../config/env.js";
|
|
7
10
|
import { getLogger } from "../../util/logger.js";
|
|
8
11
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
|
|
9
12
|
import type { AuthContext } from "../auth/types.js";
|
|
10
13
|
import { healGuardianBindingDrift } from "../guardian-vellum-migration.js";
|
|
11
14
|
import { httpError } from "../http-errors.js";
|
|
12
15
|
import type { RouteDefinition } from "../http-router.js";
|
|
16
|
+
import { resolveLocalTrustContext } from "../local-actor-identity.js";
|
|
13
17
|
import {
|
|
14
18
|
resolveTrustContext,
|
|
15
19
|
withSourceChannel,
|
|
@@ -55,32 +59,39 @@ function applyTrustContext(
|
|
|
55
59
|
const sourceChannel = "vellum";
|
|
56
60
|
|
|
57
61
|
if (authContext.actorPrincipalId) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
62
|
+
// Dev bypass (HTTP auth disabled): the synthetic "dev-bypass" principal
|
|
63
|
+
// won't match any guardian binding. Resolve from the local guardian
|
|
64
|
+
// binding instead, which produces the correct guardian trust context.
|
|
65
|
+
if (isHttpAuthDisabled() && authContext.actorPrincipalId === "dev-bypass") {
|
|
66
|
+
conversation.setTrustContext(resolveLocalTrustContext(sourceChannel));
|
|
67
|
+
} else {
|
|
68
|
+
const assistantId = DAEMON_INTERNAL_ASSISTANT_ID;
|
|
69
|
+
let trustCtx = resolveTrustContext({
|
|
70
|
+
assistantId,
|
|
71
|
+
sourceChannel,
|
|
72
|
+
conversationExternalId: "local",
|
|
73
|
+
actorExternalId: authContext.actorPrincipalId,
|
|
74
|
+
});
|
|
75
|
+
if (trustCtx.trustClass === "unknown") {
|
|
76
|
+
const healed = healGuardianBindingDrift(authContext.actorPrincipalId);
|
|
77
|
+
if (healed) {
|
|
78
|
+
trustCtx = resolveTrustContext({
|
|
79
|
+
assistantId,
|
|
80
|
+
sourceChannel,
|
|
81
|
+
conversationExternalId: "local",
|
|
82
|
+
actorExternalId: authContext.actorPrincipalId,
|
|
83
|
+
});
|
|
84
|
+
log.info(
|
|
85
|
+
{
|
|
86
|
+
actorPrincipalId: authContext.actorPrincipalId,
|
|
87
|
+
trustClass: trustCtx.trustClass,
|
|
88
|
+
},
|
|
89
|
+
"Trust re-resolved after guardian binding drift heal (surface action)",
|
|
90
|
+
);
|
|
91
|
+
}
|
|
81
92
|
}
|
|
93
|
+
conversation.setTrustContext(withSourceChannel(sourceChannel, trustCtx));
|
|
82
94
|
}
|
|
83
|
-
conversation.setTrustContext(withSourceChannel(sourceChannel, trustCtx));
|
|
84
95
|
} else {
|
|
85
96
|
// Service principals or tokens without an actor ID get guardian context.
|
|
86
97
|
conversation.setTrustContext({ trustClass: "guardian", sourceChannel });
|
|
@@ -209,6 +220,26 @@ export function surfaceActionRouteDefinitions(deps: {
|
|
|
209
220
|
{
|
|
210
221
|
endpoint: "surface-actions",
|
|
211
222
|
method: "POST",
|
|
223
|
+
summary: "Trigger a surface action",
|
|
224
|
+
description:
|
|
225
|
+
"Execute an interactive action on a surface (e.g. button click, form submit).",
|
|
226
|
+
tags: ["surfaces"],
|
|
227
|
+
requestBody: z.object({
|
|
228
|
+
conversationId: z
|
|
229
|
+
.string()
|
|
230
|
+
.describe("Conversation that owns the surface")
|
|
231
|
+
.optional(),
|
|
232
|
+
surfaceId: z.string().describe("Surface to act on"),
|
|
233
|
+
actionId: z.string().describe("Action identifier"),
|
|
234
|
+
data: z
|
|
235
|
+
.object({})
|
|
236
|
+
.passthrough()
|
|
237
|
+
.describe("Action-specific payload")
|
|
238
|
+
.optional(),
|
|
239
|
+
}),
|
|
240
|
+
responseBody: z.object({
|
|
241
|
+
ok: z.boolean(),
|
|
242
|
+
}),
|
|
212
243
|
handler: async ({ req, authContext }) => {
|
|
213
244
|
if (!deps.findConversation) {
|
|
214
245
|
return httpError(
|
|
@@ -228,6 +259,17 @@ export function surfaceActionRouteDefinitions(deps: {
|
|
|
228
259
|
{
|
|
229
260
|
endpoint: "surfaces/:id/undo",
|
|
230
261
|
method: "POST",
|
|
262
|
+
summary: "Undo last surface action",
|
|
263
|
+
description: "Revert the most recent action on a surface.",
|
|
264
|
+
tags: ["surfaces"],
|
|
265
|
+
requestBody: z.object({
|
|
266
|
+
conversationId: z
|
|
267
|
+
.string()
|
|
268
|
+
.describe("Conversation that owns the surface"),
|
|
269
|
+
}),
|
|
270
|
+
responseBody: z.object({
|
|
271
|
+
ok: z.boolean(),
|
|
272
|
+
}),
|
|
231
273
|
handler: async ({ req, params }) => {
|
|
232
274
|
if (!deps.findConversation) {
|
|
233
275
|
return httpError(
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* conversation's in-memory surface state. Used by clients to re-hydrate surfaces
|
|
6
6
|
* whose data was stripped during memory compaction.
|
|
7
7
|
*/
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
8
10
|
import type {
|
|
9
11
|
SurfaceData,
|
|
10
12
|
SurfaceType,
|
|
@@ -45,6 +47,24 @@ export function surfaceContentRouteDefinitions(deps: {
|
|
|
45
47
|
{
|
|
46
48
|
endpoint: "surfaces/:surfaceId",
|
|
47
49
|
method: "GET",
|
|
50
|
+
summary: "Get surface content",
|
|
51
|
+
description:
|
|
52
|
+
"Return the full surface payload from the conversation's in-memory surface state.",
|
|
53
|
+
tags: ["surfaces"],
|
|
54
|
+
queryParams: [
|
|
55
|
+
{
|
|
56
|
+
name: "conversationId",
|
|
57
|
+
schema: { type: "string" },
|
|
58
|
+
required: true,
|
|
59
|
+
description: "Conversation that owns the surface",
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
responseBody: z.object({
|
|
63
|
+
surfaceId: z.string(),
|
|
64
|
+
surfaceType: z.string(),
|
|
65
|
+
title: z.string(),
|
|
66
|
+
data: z.object({}).passthrough().describe("Surface data payload"),
|
|
67
|
+
}),
|
|
48
68
|
handler: ({ url, params }) => {
|
|
49
69
|
if (!deps.findConversation) {
|
|
50
70
|
return httpError(
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* POST /v1/telemetry/lifecycle — record a lifecycle event (app_open, hatch).
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
|
|
7
9
|
import { recordLifecycleEvent } from "../../memory/lifecycle-events-store.js";
|
|
8
10
|
import { getLogger } from "../../util/logger.js";
|
|
9
11
|
import { httpError } from "../http-errors.js";
|
|
@@ -47,6 +49,16 @@ export function telemetryRouteDefinitions(): RouteDefinition[] {
|
|
|
47
49
|
{
|
|
48
50
|
endpoint: "telemetry/lifecycle",
|
|
49
51
|
method: "POST",
|
|
52
|
+
summary: "Record lifecycle event",
|
|
53
|
+
description: "Record a telemetry lifecycle event (app_open, hatch).",
|
|
54
|
+
tags: ["telemetry"],
|
|
55
|
+
requestBody: z.object({
|
|
56
|
+
event_name: z.string().describe("Event name: app_open or hatch"),
|
|
57
|
+
}),
|
|
58
|
+
responseBody: z.object({
|
|
59
|
+
id: z.string().describe("Event ID"),
|
|
60
|
+
event_name: z.string(),
|
|
61
|
+
}),
|
|
50
62
|
handler: async ({ req }) => handleRecordLifecycleEvent(req),
|
|
51
63
|
},
|
|
52
64
|
];
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* GET /v1/trace-events — Returns persisted trace events for a conversation.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
|
|
7
9
|
import { getTraceEvents } from "../../memory/trace-event-store.js";
|
|
8
10
|
import { httpError } from "../http-errors.js";
|
|
9
11
|
import type { RouteDefinition } from "../http-router.js";
|
|
@@ -17,6 +19,29 @@ export function traceEventRouteDefinitions(): RouteDefinition[] {
|
|
|
17
19
|
{
|
|
18
20
|
endpoint: "trace-events",
|
|
19
21
|
method: "GET",
|
|
22
|
+
summary: "List trace events",
|
|
23
|
+
description: "Return persisted trace events for a conversation.",
|
|
24
|
+
tags: ["trace"],
|
|
25
|
+
queryParams: [
|
|
26
|
+
{
|
|
27
|
+
name: "conversationId",
|
|
28
|
+
schema: { type: "string" },
|
|
29
|
+
description: "Conversation ID (required)",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: "limit",
|
|
33
|
+
schema: { type: "integer" },
|
|
34
|
+
description: "Max events to return",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "afterSequence",
|
|
38
|
+
schema: { type: "integer" },
|
|
39
|
+
description: "Return events after this sequence number",
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
responseBody: z.object({
|
|
43
|
+
events: z.array(z.unknown()).describe("Trace event objects"),
|
|
44
|
+
}),
|
|
20
45
|
handler: ({ url }) => {
|
|
21
46
|
const conversationId = url.searchParams.get("conversationId");
|
|
22
47
|
if (!conversationId) {
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* the approval-flow trust-rule endpoint in approval-routes.ts.
|
|
6
6
|
* All endpoints are bearer-token authenticated (standard runtime auth).
|
|
7
7
|
*/
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
8
10
|
import {
|
|
9
11
|
addRule,
|
|
10
12
|
getAllRules,
|
|
@@ -176,21 +178,65 @@ export function trustRulesRouteDefinitions(): RouteDefinition[] {
|
|
|
176
178
|
{
|
|
177
179
|
endpoint: "trust-rules/manage",
|
|
178
180
|
method: "GET",
|
|
181
|
+
summary: "List all trust rules",
|
|
182
|
+
description: "Return all persistent trust rules.",
|
|
183
|
+
tags: ["trust-rules"],
|
|
184
|
+
responseBody: z.object({
|
|
185
|
+
type: z.string(),
|
|
186
|
+
rules: z.array(z.unknown()).describe("Trust rule objects"),
|
|
187
|
+
}),
|
|
179
188
|
handler: () => handleListTrustRules(),
|
|
180
189
|
},
|
|
181
190
|
{
|
|
182
191
|
endpoint: "trust-rules/manage",
|
|
183
192
|
method: "POST",
|
|
193
|
+
summary: "Add a trust rule",
|
|
194
|
+
description:
|
|
195
|
+
"Create a new persistent trust rule (standalone, not approval-flow).",
|
|
196
|
+
tags: ["trust-rules"],
|
|
197
|
+
requestBody: z.object({
|
|
198
|
+
toolName: z.string().describe("Tool name"),
|
|
199
|
+
pattern: z.string().describe("Allowlist pattern"),
|
|
200
|
+
scope: z.string().describe("Scope"),
|
|
201
|
+
decision: z.string().describe("allow, deny, or ask"),
|
|
202
|
+
allowHighRisk: z
|
|
203
|
+
.boolean()
|
|
204
|
+
.describe("Allow high-risk invocations")
|
|
205
|
+
.optional(),
|
|
206
|
+
executionTarget: z.string().describe("Execution target").optional(),
|
|
207
|
+
}),
|
|
208
|
+
responseBody: z.object({
|
|
209
|
+
ok: z.boolean(),
|
|
210
|
+
}),
|
|
184
211
|
handler: async ({ req }) => handleAddTrustRuleManage(req),
|
|
185
212
|
},
|
|
186
213
|
{
|
|
187
214
|
endpoint: "trust-rules/manage/:id",
|
|
188
215
|
method: "DELETE",
|
|
216
|
+
summary: "Remove a trust rule",
|
|
217
|
+
description: "Delete a trust rule by ID.",
|
|
218
|
+
tags: ["trust-rules"],
|
|
219
|
+
responseBody: z.object({
|
|
220
|
+
ok: z.boolean(),
|
|
221
|
+
}),
|
|
189
222
|
handler: ({ params }) => handleRemoveTrustRuleManage(params.id),
|
|
190
223
|
},
|
|
191
224
|
{
|
|
192
225
|
endpoint: "trust-rules/manage/:id",
|
|
193
226
|
method: "PATCH",
|
|
227
|
+
summary: "Update a trust rule",
|
|
228
|
+
description: "Partially update fields on an existing trust rule.",
|
|
229
|
+
tags: ["trust-rules"],
|
|
230
|
+
requestBody: z.object({
|
|
231
|
+
tool: z.string().describe("Tool name"),
|
|
232
|
+
pattern: z.string().describe("Allowlist pattern"),
|
|
233
|
+
scope: z.string().describe("Scope"),
|
|
234
|
+
decision: z.string().describe("allow, deny, or ask"),
|
|
235
|
+
priority: z.number().describe("Rule priority"),
|
|
236
|
+
}),
|
|
237
|
+
responseBody: z.object({
|
|
238
|
+
ok: z.boolean(),
|
|
239
|
+
}),
|
|
194
240
|
handler: async ({ req, params }) =>
|
|
195
241
|
handleUpdateTrustRuleManage(req, params.id),
|
|
196
242
|
},
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* POST /v1/messages/:id/tts?conversationId=... — synthesize message text to audio
|
|
5
5
|
*
|
|
6
|
-
* Gated behind the `
|
|
6
|
+
* Gated behind the `message-tts` assistant feature flag.
|
|
7
7
|
* Uses Fish Audio for synthesis when configured.
|
|
8
8
|
*/
|
|
9
9
|
|
|
@@ -18,7 +18,7 @@ import type { RouteDefinition } from "../http-router.js";
|
|
|
18
18
|
|
|
19
19
|
const log = getLogger("tts-routes");
|
|
20
20
|
|
|
21
|
-
const MESSAGE_TTS_FLAG = "
|
|
21
|
+
const MESSAGE_TTS_FLAG = "message-tts" as const;
|
|
22
22
|
|
|
23
23
|
// ---------------------------------------------------------------------------
|
|
24
24
|
// Route definitions
|
|
@@ -30,6 +30,17 @@ export function ttsRouteDefinitions(): RouteDefinition[] {
|
|
|
30
30
|
endpoint: "messages/:id/tts",
|
|
31
31
|
method: "POST",
|
|
32
32
|
policyKey: "messages/tts",
|
|
33
|
+
summary: "Synthesize message to speech",
|
|
34
|
+
description:
|
|
35
|
+
"Synthesize a message's text content to audio using Fish Audio TTS.",
|
|
36
|
+
tags: ["messages"],
|
|
37
|
+
queryParams: [
|
|
38
|
+
{
|
|
39
|
+
name: "conversationId",
|
|
40
|
+
schema: { type: "string" },
|
|
41
|
+
description: "Conversation that contains the message",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
33
44
|
handler: async ({ url, params }) => {
|
|
34
45
|
const config = getConfig();
|
|
35
46
|
|
|
@@ -50,8 +61,8 @@ export function ttsRouteDefinitions(): RouteDefinition[] {
|
|
|
50
61
|
return httpError("BAD_REQUEST", "Message has no text content", 400);
|
|
51
62
|
}
|
|
52
63
|
|
|
53
|
-
const sanitizedText = sanitizeForTts(result.text);
|
|
54
|
-
if (!sanitizedText
|
|
64
|
+
const sanitizedText = sanitizeForTts(result.text).trim();
|
|
65
|
+
if (!sanitizedText) {
|
|
55
66
|
return httpError(
|
|
56
67
|
"BAD_REQUEST",
|
|
57
68
|
"Message has no speakable text content",
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* minted service token.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
|
|
12
14
|
import type {
|
|
13
15
|
ServiceGroupUpdateComplete,
|
|
14
16
|
ServiceGroupUpdateProgress,
|
|
@@ -25,6 +27,42 @@ export function upgradeBroadcastRouteDefinitions(): RouteDefinition[] {
|
|
|
25
27
|
{
|
|
26
28
|
endpoint: "admin/upgrade-broadcast",
|
|
27
29
|
method: "POST",
|
|
30
|
+
summary: "Broadcast upgrade lifecycle event",
|
|
31
|
+
description:
|
|
32
|
+
"Publish a service group update lifecycle event (starting, progress, or complete) to all connected SSE clients.",
|
|
33
|
+
tags: ["admin"],
|
|
34
|
+
requestBody: z.object({
|
|
35
|
+
type: z
|
|
36
|
+
.string()
|
|
37
|
+
.describe('Event type: "starting", "progress", or "complete"'),
|
|
38
|
+
targetVersion: z
|
|
39
|
+
.string()
|
|
40
|
+
.describe("Target version (required for starting)")
|
|
41
|
+
.optional(),
|
|
42
|
+
expectedDowntimeSeconds: z
|
|
43
|
+
.number()
|
|
44
|
+
.describe("Expected downtime in seconds (starting, default 60)")
|
|
45
|
+
.optional(),
|
|
46
|
+
statusMessage: z
|
|
47
|
+
.string()
|
|
48
|
+
.describe("Status message (required for progress)")
|
|
49
|
+
.optional(),
|
|
50
|
+
installedVersion: z
|
|
51
|
+
.string()
|
|
52
|
+
.describe("Installed version (required for complete)")
|
|
53
|
+
.optional(),
|
|
54
|
+
success: z
|
|
55
|
+
.boolean()
|
|
56
|
+
.describe("Whether upgrade succeeded (required for complete)")
|
|
57
|
+
.optional(),
|
|
58
|
+
rolledBackToVersion: z
|
|
59
|
+
.string()
|
|
60
|
+
.describe("Version rolled back to, if any (complete)")
|
|
61
|
+
.optional(),
|
|
62
|
+
}),
|
|
63
|
+
responseBody: z.object({
|
|
64
|
+
ok: z.boolean(),
|
|
65
|
+
}),
|
|
28
66
|
handler: async ({ req }) => {
|
|
29
67
|
let body: unknown;
|
|
30
68
|
try {
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* GET /v1/usage/breakdown?from=&to=&groupBy= — grouped breakdown (actor, provider, model)
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
|
|
9
11
|
import {
|
|
10
12
|
getUsageDayBuckets,
|
|
11
13
|
getUsageGroupBreakdown,
|
|
@@ -63,6 +65,21 @@ export function usageRouteDefinitions(): RouteDefinition[] {
|
|
|
63
65
|
{
|
|
64
66
|
endpoint: "usage/totals",
|
|
65
67
|
method: "GET",
|
|
68
|
+
summary: "Get usage totals",
|
|
69
|
+
description: "Return aggregate usage totals for a time range.",
|
|
70
|
+
tags: ["usage"],
|
|
71
|
+
queryParams: [
|
|
72
|
+
{
|
|
73
|
+
name: "from",
|
|
74
|
+
schema: { type: "integer" },
|
|
75
|
+
description: "Start epoch millis (required)",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: "to",
|
|
79
|
+
schema: { type: "integer" },
|
|
80
|
+
description: "End epoch millis (required)",
|
|
81
|
+
},
|
|
82
|
+
],
|
|
66
83
|
handler: ({ url }) => {
|
|
67
84
|
const range = parseTimeRange(url);
|
|
68
85
|
if (range instanceof Response) return range;
|
|
@@ -73,6 +90,24 @@ export function usageRouteDefinitions(): RouteDefinition[] {
|
|
|
73
90
|
{
|
|
74
91
|
endpoint: "usage/daily",
|
|
75
92
|
method: "GET",
|
|
93
|
+
summary: "Get daily usage",
|
|
94
|
+
description: "Return per-day usage buckets for a time range.",
|
|
95
|
+
tags: ["usage"],
|
|
96
|
+
queryParams: [
|
|
97
|
+
{
|
|
98
|
+
name: "from",
|
|
99
|
+
schema: { type: "integer" },
|
|
100
|
+
description: "Start epoch millis (required)",
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: "to",
|
|
104
|
+
schema: { type: "integer" },
|
|
105
|
+
description: "End epoch millis (required)",
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
responseBody: z.object({
|
|
109
|
+
buckets: z.array(z.unknown()).describe("Daily usage bucket objects"),
|
|
110
|
+
}),
|
|
76
111
|
handler: ({ url }) => {
|
|
77
112
|
const range = parseTimeRange(url);
|
|
78
113
|
if (range instanceof Response) return range;
|
|
@@ -83,6 +118,30 @@ export function usageRouteDefinitions(): RouteDefinition[] {
|
|
|
83
118
|
{
|
|
84
119
|
endpoint: "usage/breakdown",
|
|
85
120
|
method: "GET",
|
|
121
|
+
summary: "Get usage breakdown",
|
|
122
|
+
description:
|
|
123
|
+
"Return grouped usage breakdown (by actor, provider, or model).",
|
|
124
|
+
tags: ["usage"],
|
|
125
|
+
queryParams: [
|
|
126
|
+
{
|
|
127
|
+
name: "from",
|
|
128
|
+
schema: { type: "integer" },
|
|
129
|
+
description: "Start epoch millis (required)",
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: "to",
|
|
133
|
+
schema: { type: "integer" },
|
|
134
|
+
description: "End epoch millis (required)",
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: "groupBy",
|
|
138
|
+
schema: { type: "string" },
|
|
139
|
+
description: "Group by: actor, provider, or model (required)",
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
responseBody: z.object({
|
|
143
|
+
breakdown: z.array(z.unknown()).describe("Grouped usage entries"),
|
|
144
|
+
}),
|
|
86
145
|
handler: ({ url }) => {
|
|
87
146
|
const range = parseTimeRange(url);
|
|
88
147
|
if (range instanceof Response) return range;
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* zero dependency on CU session state.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
8
10
|
import { getLogger } from "../../util/logger.js";
|
|
9
11
|
import { httpError } from "../http-errors.js";
|
|
10
12
|
import type { RouteDefinition } from "../http-router.js";
|
|
@@ -122,7 +124,33 @@ export function watchRouteDefinitions(deps: {
|
|
|
122
124
|
endpoint: "computer-use/watch",
|
|
123
125
|
method: "POST",
|
|
124
126
|
policyKey: "computer-use/watch",
|
|
127
|
+
summary: "Submit watch observation",
|
|
128
|
+
description: "Send a screen observation from ambient watch mode.",
|
|
129
|
+
tags: ["computer-use"],
|
|
125
130
|
handler: async ({ req }) => handleWatchObservationRoute(req, getDeps()),
|
|
131
|
+
requestBody: z.object({
|
|
132
|
+
watchId: z.string().describe("Watch session ID"),
|
|
133
|
+
conversationId: z.string().describe("Conversation to associate with"),
|
|
134
|
+
ocrText: z.string().describe("OCR text from screen capture"),
|
|
135
|
+
appName: z.string().describe("Active application name").optional(),
|
|
136
|
+
windowTitle: z.string().describe("Active window title").optional(),
|
|
137
|
+
bundleIdentifier: z
|
|
138
|
+
.string()
|
|
139
|
+
.describe("Application bundle identifier")
|
|
140
|
+
.optional(),
|
|
141
|
+
timestamp: z.number().describe("Capture timestamp (epoch ms)"),
|
|
142
|
+
captureIndex: z
|
|
143
|
+
.number()
|
|
144
|
+
.int()
|
|
145
|
+
.describe("Index of this capture in the batch"),
|
|
146
|
+
totalExpected: z
|
|
147
|
+
.number()
|
|
148
|
+
.int()
|
|
149
|
+
.describe("Total captures expected in the batch"),
|
|
150
|
+
}),
|
|
151
|
+
responseBody: z.object({
|
|
152
|
+
ok: z.boolean(),
|
|
153
|
+
}),
|
|
126
154
|
},
|
|
127
155
|
];
|
|
128
156
|
}
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* sharing business logic with the handlers in
|
|
6
6
|
* `daemon/handlers/work-items.ts`.
|
|
7
7
|
*/
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
8
10
|
import type { Conversation } from "../../daemon/conversation.js";
|
|
9
11
|
import type { ServerMessage } from "../../daemon/message-protocol.js";
|
|
10
12
|
import { getMessages } from "../../memory/conversation-crud.js";
|
|
@@ -417,6 +419,12 @@ export function workItemRouteDefinitions(
|
|
|
417
419
|
endpoint: "work-items",
|
|
418
420
|
method: "GET",
|
|
419
421
|
policyKey: "work-items",
|
|
422
|
+
summary: "List work items",
|
|
423
|
+
description: "Return work items, optionally filtered by status.",
|
|
424
|
+
tags: ["work-items"],
|
|
425
|
+
responseBody: z.object({
|
|
426
|
+
items: z.array(z.unknown()),
|
|
427
|
+
}),
|
|
420
428
|
handler: ({ url }) => {
|
|
421
429
|
const status = url.searchParams.get("status") ?? undefined;
|
|
422
430
|
const items = listWorkItems(
|
|
@@ -431,6 +439,9 @@ export function workItemRouteDefinitions(
|
|
|
431
439
|
endpoint: "work-items/:id",
|
|
432
440
|
method: "GET",
|
|
433
441
|
policyKey: "work-items",
|
|
442
|
+
summary: "Get a work item",
|
|
443
|
+
description: "Return a single work item by ID.",
|
|
444
|
+
tags: ["work-items"],
|
|
434
445
|
handler: ({ params }) => {
|
|
435
446
|
const item = getWorkItem(params.id) ?? null;
|
|
436
447
|
if (!item) {
|
|
@@ -445,6 +456,17 @@ export function workItemRouteDefinitions(
|
|
|
445
456
|
endpoint: "work-items/:id",
|
|
446
457
|
method: "PATCH",
|
|
447
458
|
policyKey: "work-items",
|
|
459
|
+
summary: "Update a work item",
|
|
460
|
+
description:
|
|
461
|
+
"Partially update a work item's title, notes, status, or priority.",
|
|
462
|
+
tags: ["work-items"],
|
|
463
|
+
requestBody: z.object({
|
|
464
|
+
title: z.string(),
|
|
465
|
+
notes: z.string(),
|
|
466
|
+
status: z.string(),
|
|
467
|
+
priorityTier: z.number().int(),
|
|
468
|
+
sortIndex: z.number().int(),
|
|
469
|
+
}),
|
|
448
470
|
handler: async ({ req, params }) => {
|
|
449
471
|
const body = (await req.json()) as {
|
|
450
472
|
title?: string;
|
|
@@ -490,6 +512,9 @@ export function workItemRouteDefinitions(
|
|
|
490
512
|
endpoint: "work-items/:id/complete",
|
|
491
513
|
method: "POST",
|
|
492
514
|
policyKey: "work-items/complete",
|
|
515
|
+
summary: "Complete a work item",
|
|
516
|
+
description: "Transition a work item from awaiting_review to done.",
|
|
517
|
+
tags: ["work-items"],
|
|
493
518
|
handler: ({ params }) => {
|
|
494
519
|
const existing = getWorkItem(params.id);
|
|
495
520
|
if (!existing) {
|
|
@@ -521,6 +546,9 @@ export function workItemRouteDefinitions(
|
|
|
521
546
|
endpoint: "work-items/:id",
|
|
522
547
|
method: "DELETE",
|
|
523
548
|
policyKey: "work-items",
|
|
549
|
+
summary: "Delete a work item",
|
|
550
|
+
description: "Permanently remove a work item.",
|
|
551
|
+
tags: ["work-items"],
|
|
524
552
|
handler: ({ params }) => {
|
|
525
553
|
const existing = getWorkItem(params.id);
|
|
526
554
|
if (!existing) {
|
|
@@ -537,6 +565,9 @@ export function workItemRouteDefinitions(
|
|
|
537
565
|
endpoint: "work-items/:id/cancel",
|
|
538
566
|
method: "POST",
|
|
539
567
|
policyKey: "work-items/cancel",
|
|
568
|
+
summary: "Cancel a running work item",
|
|
569
|
+
description: "Abort a running work item and set its status to cancelled.",
|
|
570
|
+
tags: ["work-items"],
|
|
540
571
|
handler: ({ params }) => {
|
|
541
572
|
const workItem = getWorkItem(params.id);
|
|
542
573
|
if (!workItem) {
|
|
@@ -577,6 +608,14 @@ export function workItemRouteDefinitions(
|
|
|
577
608
|
endpoint: "work-items/:id/approve-permissions",
|
|
578
609
|
method: "POST",
|
|
579
610
|
policyKey: "work-items/approve-permissions",
|
|
611
|
+
summary: "Approve tool permissions",
|
|
612
|
+
description: "Pre-approve a set of tools for a work item before it runs.",
|
|
613
|
+
tags: ["work-items"],
|
|
614
|
+
requestBody: z.object({
|
|
615
|
+
approvedTools: z
|
|
616
|
+
.array(z.unknown())
|
|
617
|
+
.describe("Array of tool names to approve"),
|
|
618
|
+
}),
|
|
580
619
|
handler: async ({ req, params }) => {
|
|
581
620
|
const body = (await req.json()) as { approvedTools?: string[] };
|
|
582
621
|
if (!Array.isArray(body.approvedTools)) {
|
|
@@ -602,6 +641,14 @@ export function workItemRouteDefinitions(
|
|
|
602
641
|
endpoint: "work-items/:id/preflight",
|
|
603
642
|
method: "POST",
|
|
604
643
|
policyKey: "work-items/preflight",
|
|
644
|
+
summary: "Preflight check",
|
|
645
|
+
description: "Check tool permissions needed before running a work item.",
|
|
646
|
+
tags: ["work-items"],
|
|
647
|
+
responseBody: z.object({
|
|
648
|
+
id: z.string(),
|
|
649
|
+
success: z.boolean(),
|
|
650
|
+
permissions: z.object({}).passthrough(),
|
|
651
|
+
}),
|
|
605
652
|
handler: async ({ params }) => {
|
|
606
653
|
const result = await preflightWorkItem(params.id);
|
|
607
654
|
if (!result.success) {
|
|
@@ -620,6 +667,10 @@ export function workItemRouteDefinitions(
|
|
|
620
667
|
endpoint: "work-items/:id/run",
|
|
621
668
|
method: "POST",
|
|
622
669
|
policyKey: "work-items/run",
|
|
670
|
+
summary: "Run a work item",
|
|
671
|
+
description:
|
|
672
|
+
"Execute the task associated with a work item. Returns immediately; execution happens in the background.",
|
|
673
|
+
tags: ["work-items"],
|
|
623
674
|
handler: async ({ params }) => {
|
|
624
675
|
const workItem = getWorkItem(params.id);
|
|
625
676
|
if (!workItem) {
|
|
@@ -782,6 +833,14 @@ export function workItemRouteDefinitions(
|
|
|
782
833
|
endpoint: "work-items/:id/output",
|
|
783
834
|
method: "GET",
|
|
784
835
|
policyKey: "work-items/output",
|
|
836
|
+
summary: "Get work item output",
|
|
837
|
+
description: "Return the final output of a completed work item run.",
|
|
838
|
+
tags: ["work-items"],
|
|
839
|
+
responseBody: z.object({
|
|
840
|
+
id: z.string(),
|
|
841
|
+
success: z.boolean(),
|
|
842
|
+
output: z.object({}).passthrough(),
|
|
843
|
+
}),
|
|
785
844
|
handler: ({ params }) => {
|
|
786
845
|
try {
|
|
787
846
|
const result = getWorkItemOutput(params.id);
|