@vellumai/assistant 0.12.2-staging.5 → 0.12.2-staging.7
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/Dockerfile +7 -7
- package/docs/architecture/memory.md +11 -2
- package/docs/desktop-browser-cli.md +4 -2
- package/node_modules/@vellumai/environments/src/shell.test.ts +21 -0
- package/node_modules/@vellumai/environments/src/shell.ts +24 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -2
- package/openapi.yaml +157 -55
- package/package.json +5 -4
- package/scripts/bundled-plugin-packages.ts +154 -0
- package/scripts/generate-bundled-plugin-packages.ts +29 -0
- package/scripts/postinstall.ts +33 -0
- package/scripts/smoke-desktop-browser-cli.ts +1 -0
- package/scripts/test.ts +15 -13
- package/src/__tests__/agent-loop.test.ts +124 -0
- package/src/__tests__/approval-interception-trust-gates.test.ts +40 -0
- package/src/__tests__/channel-approval.test.ts +9 -14
- package/src/__tests__/conversation-agent-loop.test.ts +25 -0
- package/src/__tests__/db-conversation-tool-surface.test.ts +144 -0
- package/src/__tests__/managed-store.test.ts +121 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +0 -1
- package/src/__tests__/run-conversation-turn-persistence.test.ts +138 -1
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +88 -0
- package/src/__tests__/script-proxy-certs.test.ts +1 -1
- package/src/__tests__/subagent-tool-gate-mode.test.ts +169 -0
- package/src/__tests__/terminal-tools.test.ts +8 -0
- package/src/__tests__/unicode.test.ts +36 -0
- package/src/agent/loop.ts +19 -0
- package/src/api/events/desktop-activity-changed.ts +10 -0
- package/src/api/index.ts +6 -0
- package/src/approvals/approval-primitive.ts +5 -2
- package/src/approvals/scoped-approval-grants.ts +6 -2
- package/src/calls/__tests__/voice-control-protocol.test.ts +24 -2
- package/src/calls/__tests__/voice-session-bridge.test.ts +22 -2
- package/src/calls/voice-control-protocol.ts +13 -4
- package/src/calls/voice-session-bridge.ts +27 -6
- package/src/cli/commands/__tests__/plugins.test.ts +66 -0
- package/src/cli/commands/plugins.ts +50 -18
- package/src/cli/lib/__tests__/install-from-github.test.ts +67 -0
- package/src/cli/lib/__tests__/local-plugin-upgrade.test.ts +169 -0
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +57 -0
- package/src/cli/lib/__tests__/plugin-catalog-platform.test.ts +14 -0
- package/src/cli/lib/__tests__/plugin-catalog-resolve.test.ts +27 -1
- package/src/cli/lib/__tests__/plugin-details.test.ts +9 -2
- package/src/cli/lib/__tests__/plugin-marketplace.test.ts +20 -0
- package/src/cli/lib/__tests__/plugins-install-offline.test.ts +43 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +31 -0
- package/src/cli/lib/bundled-plugin-packages.json +4 -0
- package/src/cli/lib/bundled-plugin-packages.ts +87 -0
- package/src/cli/lib/diff-plugin.ts +1 -1
- package/src/cli/lib/inspect-plugin.ts +80 -12
- package/src/cli/lib/install-from-github.ts +133 -76
- package/src/cli/lib/plugin-catalog-cache.ts +22 -3
- package/src/cli/lib/plugin-catalog-local.ts +13 -3
- package/src/cli/lib/plugin-catalog-platform.ts +6 -1
- package/src/cli/lib/plugin-catalog-resolve.ts +20 -0
- package/src/cli/lib/plugin-details.ts +12 -0
- package/src/cli/lib/plugin-marketplace.ts +121 -21
- package/src/cli/lib/plugin-pin-history.ts +5 -2
- package/src/cli/lib/search-plugins.ts +58 -16
- package/src/cli/lib/upgrade-plugin.ts +48 -3
- package/src/config/bundled-skills/skill-management/SKILL.md +1 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +6 -6
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +43 -0
- package/src/daemon/conversation-agent-loop.ts +2 -0
- package/src/daemon/conversation-tool-setup.ts +61 -23
- package/src/daemon/conversation.ts +17 -0
- package/src/daemon/daemon-control.ts +2 -6
- package/src/daemon/orphan-reaper.ts +4 -3
- package/src/daemon/tool-setup-types.ts +6 -0
- package/src/daemon/wake-conversation-ops.ts +38 -15
- package/src/desktop/desktop-automation-lease.test.ts +143 -0
- package/src/desktop/desktop-automation-lease.ts +39 -3
- package/src/live-voice/__tests__/live-voice-vad.test.ts +624 -3
- package/src/live-voice/__tests__/session-controls.test.ts +18 -0
- package/src/live-voice/live-voice-session.ts +575 -53
- package/src/live-voice/session-controls.ts +7 -3
- package/src/messaging/provider-message-metadata.ts +3 -3
- package/src/monitoring/plugin-auto-update.ts +6 -0
- package/src/notifications/__tests__/copy-composer.test.ts +70 -0
- package/src/notifications/copy-composer.ts +11 -3
- package/src/persistence/conversation-plugin-facade.ts +13 -0
- package/src/persistence/conversation-tool-surface.ts +86 -0
- package/src/persistence/migrations/378-create-conversation-tool-surfaces.test.ts +78 -0
- package/src/persistence/migrations/378-create-conversation-tool-surfaces.ts +29 -0
- package/src/persistence/schema/conversation-tool-surfaces.ts +22 -0
- package/src/persistence/schema/index.ts +1 -0
- package/src/persistence/steps.ts +2 -0
- package/src/plugin-api/conversation-turn.ts +31 -7
- package/src/plugin-api/index.ts +9 -1
- package/src/plugin-api/plugin-channel-turn-trust.test.ts +133 -0
- package/src/plugin-api/plugin-channel-turn-trust.ts +71 -0
- package/src/plugins/defaults/memory/AGENTS.md +14 -2
- package/src/plugins/defaults/memory/__tests__/buffer-file.test.ts +320 -0
- package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +43 -0
- package/src/plugins/defaults/memory/__tests__/fixtures/buffer-appender.ts +17 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +46 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +5 -0
- package/src/plugins/defaults/memory/__tests__/memory-run-evidence.test.ts +161 -0
- package/src/plugins/defaults/memory/buffer-file.ts +354 -0
- package/src/plugins/defaults/memory/buffer-format.ts +40 -0
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +1 -2
- package/src/plugins/defaults/memory/context-search/format.ts +2 -1
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +2 -1
- package/src/plugins/defaults/memory/context-search/sources/workspace.ts +2 -1
- package/src/plugins/defaults/memory/graph/capability-seed.ts +1 -2
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +1 -42
- package/src/plugins/defaults/memory/host-utils.ts +0 -10
- package/src/plugins/defaults/memory/injectors.ts +4 -3
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +55 -181
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +1 -1
- package/src/plugins/defaults/memory/memory-run-evidence.ts +213 -0
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +407 -99
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +10 -0
- package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +107 -7
- package/src/plugins/defaults/memory/substrate/consolidation-job.ts +307 -86
- package/src/plugins/defaults/memory/substrate/consolidation-tool-surface.ts +34 -0
- package/src/plugins/defaults/memory/substrate/page-index.ts +2 -1
- package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +89 -49
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +1 -1
- package/src/plugins/defaults/memory/tools.ts +1 -1
- package/src/plugins/defaults/memory/v1/graph/consolidation.ts +2 -2
- package/src/plugins/defaults/memory/v1/graph/extraction.ts +2 -1
- package/src/plugins/defaults/memory/v1/graph/retriever.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +5 -0
- package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +5 -2
- package/src/plugins/defaults/memory/v2/reranker.ts +2 -1
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +81 -1
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +87 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +21 -0
- package/src/plugins/defaults/memory/v3/card.ts +2 -1
- package/src/plugins/defaults/memory/v3/injector.ts +212 -178
- package/src/plugins/defaults/memory/v3/orchestrate.ts +86 -22
- package/src/plugins/defaults/memory/v3/pool-select.ts +10 -7
- package/src/plugins/defaults/memory/v3/sections.ts +2 -1
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +10 -1
- package/src/plugins/defaults/tool-result-truncate/terminal.ts +1 -46
- package/src/runtime/AGENTS.md +1 -1
- package/src/runtime/__tests__/agent-wake.test.ts +86 -1
- package/src/runtime/agent-wake.ts +20 -4
- package/src/runtime/guardian-action-service.ts +2 -17
- package/src/runtime/guardian-reply-router.ts +1 -8
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +102 -0
- package/src/runtime/routes/channel-route-shared.ts +1 -9
- package/src/runtime/routes/desktop-setup-routes.test.ts +2 -2
- package/src/runtime/routes/desktop-setup-routes.ts +7 -3
- package/src/runtime/routes/guardian-approval-interception.ts +24 -0
- package/src/runtime/routes/inbound-message-handler.ts +2 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +1 -1
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +7 -4
- package/src/runtime/routes/plugins-routes.ts +69 -49
- package/src/schedule/run-script.ts +2 -2
- package/src/skills/managed-store.ts +98 -32
- package/src/tools/host-terminal/host-shell.ts +12 -6
- package/src/tools/shared/filesystem/file-ops-service.ts +1 -31
- package/src/tools/shared/shell-output.test.ts +10 -0
- package/src/tools/shared/shell-output.ts +14 -2
- package/src/tools/skills/find-similar-skills.test.ts +3 -0
- package/src/tools/skills/resolve-execute-invocation.ts +24 -0
- package/src/tools/skills/sandbox-runner.ts +13 -2
- package/src/tools/skills/scaffold-managed.ts +18 -14
- package/src/tools/terminal/__tests__/safe-env.test.ts +29 -0
- package/src/tools/terminal/safe-env.ts +30 -1
- package/src/tools/terminal/sanitized-bash.ts +15 -2
- package/src/tools/terminal/shell-launch.test.ts +162 -0
- package/src/tools/terminal/shell.test.ts +29 -0
- package/src/tools/terminal/shell.ts +13 -7
- package/src/util/host-process.test.ts +17 -1
- package/src/util/host-process.ts +24 -0
- package/src/util/unicode.ts +29 -0
package/Dockerfile
CHANGED
|
@@ -130,13 +130,13 @@ RUN bun run scripts/smoke-container-workspace-dependencies.ts
|
|
|
130
130
|
# The repo-root .dockerignore decides which skills (and files) ship.
|
|
131
131
|
COPY skills /app/skills
|
|
132
132
|
|
|
133
|
-
# Materialize the git-ignored offline
|
|
134
|
-
#
|
|
135
|
-
#
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
133
|
+
# Materialize the git-ignored offline marketplace and reviewed local packages.
|
|
134
|
+
# The build installs with --ignore-scripts, so the postinstall sync that creates
|
|
135
|
+
# these static imports in development never runs here.
|
|
136
|
+
COPY plugins /app/plugins
|
|
137
|
+
COPY meta/sync-bundled-copies.ts /app/meta/
|
|
138
|
+
RUN cd /app && bun run meta/sync-bundled-copies.ts --plugins-only && \
|
|
139
|
+
bun run assistant/scripts/generate-bundled-plugin-packages.ts
|
|
140
140
|
|
|
141
141
|
# Install assistant CLI launcher backed by the bundled assistant package
|
|
142
142
|
RUN printf '#!/usr/bin/env sh\nexec bun run /app/assistant/src/index.ts "$@"\n' > /usr/local/bin/assistant && \
|
|
@@ -87,8 +87,17 @@ graph LR
|
|
|
87
87
|
nesting existed still parse, since an unindented body line that is not itself
|
|
88
88
|
entry-shaped is read as a continuation.
|
|
89
89
|
- **Consolidation** (`substrate/consolidation-job.ts`) is a background
|
|
90
|
-
agent conversation that files buffer entries into concept pages
|
|
91
|
-
the aggregate views
|
|
90
|
+
agent conversation that files buffer entries into concept pages and
|
|
91
|
+
rewrites the aggregate views. The agent never writes the buffer: the job
|
|
92
|
+
snapshots `buffer.md`, hands the run its pass's entries verbatim in the
|
|
93
|
+
prompt, and after the run removes exactly those entries itself through
|
|
94
|
+
`buffer-file.ts` (the module that also owns the append path, so the two
|
|
95
|
+
writers of the buffer share one protocol). Removal happens only when the
|
|
96
|
+
run's persisted messages hold a page-writing tool call with a non-error
|
|
97
|
+
result, the same evidence bar the retrospective's cursor advance uses; a
|
|
98
|
+
run that wrote nothing, failed, or timed out leaves the buffer intact for
|
|
99
|
+
the next pass. Entries deferred past the per-run cap and entries appended
|
|
100
|
+
while the run was in flight are therefore never lost. Scheduling
|
|
92
101
|
(`maybeEnqueueGraphMaintenanceJobs` in `jobs-worker.ts`):
|
|
93
102
|
- interval-based (`memory.v2.consolidation_interval_hours`, default 8h),
|
|
94
103
|
skipped below `MIN_BUFFER_LINES_FOR_CONSOLIDATION` (10) **unless** the
|
|
@@ -18,7 +18,7 @@ flowchart LR
|
|
|
18
18
|
|
|
19
19
|
Chrome and its dock launcher share the managed profile and loopback debug port. For Chrome reopened from the dock, the profile singleton lock identifies a candidate PID, validated against the installed executable, profile and loopback debug arguments. Discovery checks `/proc` socket ownership against that browser PID, refuses redirects and validates the returned browser WebSocket endpoint. The connection stays within the container. No CDP endpoint or token is exposed to the renderer.
|
|
20
20
|
|
|
21
|
-
The desktop client bypasses personal-browser discovery, extension reconnect waits and backend fallback. It reuses the existing AX snapshot, DOM element resolution, mouse, keyboard, extraction and credential-fill implementations. Operation-scoped clients borrow the lease's connection; disposing one does not release the lease. `detach`, `close`, cancellation, errors and idle expiry release control. Only `tabs close` closes a Chrome tab.
|
|
21
|
+
The desktop client bypasses personal-browser discovery, extension reconnect waits and backend fallback. It reuses the existing AX snapshot, DOM element resolution, mouse, keyboard, extraction and credential-fill implementations. Operation-scoped clients borrow the lease's connection; disposing one does not release the lease. `detach`, `close`, turn completion, cancellation, errors and idle expiry release control. Turn completion clears the activity indicator immediately and queues browser cleanup before the next automation session; it leaves Chrome and the current page open for the user. Only `tabs close` closes a Chrome tab.
|
|
22
22
|
|
|
23
23
|
`assistant browser --virtual-desktop screenshot --output /tmp/desktop-page.jpg` captures a color page image through CDP `Page.captureScreenshot`. It excludes the browser toolbar and desktop dock. `snapshot` returns semantic page structure. Agents should use these interfaces and let the manager start the desktop, including when older memory notes describe manual Xvnc, `xdotool` or scratch XWD conversion scripts.
|
|
24
24
|
|
|
@@ -26,8 +26,10 @@ Tab IDs are ephemeral numeric aliases for this managed browser's CDP target IDs.
|
|
|
26
26
|
|
|
27
27
|
CDP mouse events use page viewport CSS coordinates. Before dispatching them, the client animates a purple arrow overlay to the same point. The overlay is excluded from accessibility and hit testing. It appears in the existing desktop stream and is removed on release. It does not move the OS pointer, appear in browser toolbar UI or visualize every programmatic DOM operation. Native dialogs and other applications are outside the browser CLI; users can interact with them directly in the expanded desktop. The picture-in-picture preview is view-only. Direct user interaction does not pause automation.
|
|
28
28
|
|
|
29
|
-
The client records key and mouse presses before dispatch. On release it opens a fresh bounded cleanup connection, attaches to the same live targets, releases uncertain held input and removes overlays. A failed cleanup preserves state and the automation slot for retry. Dispatched actions are never automatically retried. Closed targets need no input cleanup. Browser-process loss disposes the client, and later requests discover the replacement process.
|
|
29
|
+
The client records key and mouse presses before dispatch. On release it opens a fresh bounded cleanup connection, attaches to the same live targets, releases uncertain held input and removes overlays. A failed cleanup preserves state and the automation slot for retry. Turn-triggered cancellation retries cleanup automatically until it succeeds or ownership changes. Dispatched actions are never automatically retried. Closed targets need no input cleanup. Browser-process loss disposes the client, and later requests discover the replacement process.
|
|
30
30
|
|
|
31
31
|
`--use-active-tab` and personal browser targeting are rejected with `--virtual-desktop`. Download waiting is unsupported. Browser operations are bounded to two minutes and share the desktop lease's action budget and idle expiry.
|
|
32
32
|
|
|
33
33
|
Validation: focused client tests exercise shared snapshot/click behavior, namespace isolation, stale references, target changes, cancellation and uncertain-input cleanup. Lease tests cover browser ownership, cancellation and cleanup independently of native input. The Linux smoke script exercises real Chrome, the CLI and visible pointer feedback.
|
|
34
|
+
|
|
35
|
+
The desktop header icon pulses in the assistant's avatar accent color while a browser automation lease is active, including between browser commands. It shares the progress indicator's accent and neutral fallback. Reduced-motion clients show a solid accent. Setup status exposes the optional `automationActive` field; `desktop_activity_changed` events refresh it on acquisition and cancellation or release. Installation progress retains its `assistant:self:desktop` sync invalidations. The indicator reads status without starting installation, and reconnects refetch the current lease state.
|
|
@@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test";
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
buildShellInvocation,
|
|
5
|
+
buildShellSpawnFlags,
|
|
5
6
|
pathListDelimiter,
|
|
6
7
|
prependUniquePathEntries,
|
|
7
8
|
} from "./shell.js";
|
|
@@ -38,6 +39,26 @@ describe("buildShellInvocation", () => {
|
|
|
38
39
|
});
|
|
39
40
|
});
|
|
40
41
|
|
|
42
|
+
describe("buildShellSpawnFlags", () => {
|
|
43
|
+
test("creates a POSIX process group and hides Windows consoles", () => {
|
|
44
|
+
expect(buildShellSpawnFlags("linux")).toEqual({
|
|
45
|
+
detached: true,
|
|
46
|
+
windowsHide: true,
|
|
47
|
+
});
|
|
48
|
+
expect(buildShellSpawnFlags("darwin")).toEqual({
|
|
49
|
+
detached: true,
|
|
50
|
+
windowsHide: true,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("does not detach Windows children that use piped stdio", () => {
|
|
55
|
+
expect(buildShellSpawnFlags("win32")).toEqual({
|
|
56
|
+
detached: false,
|
|
57
|
+
windowsHide: true,
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
41
62
|
describe("path list handling", () => {
|
|
42
63
|
test("uses the platform delimiter", () => {
|
|
43
64
|
expect(pathListDelimiter("win32")).toBe(";");
|
|
@@ -5,6 +5,11 @@ export interface ShellInvocation {
|
|
|
5
5
|
args: string[];
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
export interface ShellSpawnFlags {
|
|
9
|
+
detached: boolean;
|
|
10
|
+
windowsHide: true;
|
|
11
|
+
}
|
|
12
|
+
|
|
8
13
|
const WINDOWS_UTF8_PREAMBLE =
|
|
9
14
|
"try { [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 } catch {}; " +
|
|
10
15
|
"$OutputEncoding = [System.Text.Encoding]::UTF8; " +
|
|
@@ -43,6 +48,25 @@ export function buildShellInvocation(
|
|
|
43
48
|
return { command: "bash", args: ["-c", "--", command] };
|
|
44
49
|
}
|
|
45
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Spawn flags for assistant-owned shell children (sandbox bash, local
|
|
53
|
+
* host_bash fallback, sanitized CLI bash, skill runners, scheduled scripts).
|
|
54
|
+
*
|
|
55
|
+
* POSIX uses a new process group so timeout/abort can SIGKILL the tree via
|
|
56
|
+
* `-pid`. Windows process trees are torn down with `taskkill /T`, which does
|
|
57
|
+
* not need a detached process. Combining `DETACHED_PROCESS`,
|
|
58
|
+
* `CREATE_NO_WINDOW`, and piped stdio on Windows can emit `close` with exit
|
|
59
|
+
* 0 and empty pipes without running the encoded command.
|
|
60
|
+
*/
|
|
61
|
+
export function buildShellSpawnFlags(
|
|
62
|
+
hostPlatform: NodeJS.Platform = process.platform,
|
|
63
|
+
): ShellSpawnFlags {
|
|
64
|
+
return {
|
|
65
|
+
detached: hostPlatform !== "win32",
|
|
66
|
+
windowsHide: true,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
46
70
|
export function pathListDelimiter(
|
|
47
71
|
hostPlatform: NodeJS.Platform = process.platform,
|
|
48
72
|
): string {
|
|
@@ -83,8 +83,14 @@ export const SourceMetadataSchema = z
|
|
|
83
83
|
clientTimezone: z.string().optional(),
|
|
84
84
|
/** Channel command intent (e.g. Telegram /start). */
|
|
85
85
|
commandIntent: CommandIntentSchema.optional(),
|
|
86
|
-
/**
|
|
87
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Whether the message addresses the assistant by name, an @-mention on
|
|
88
|
+
* the platforms that have one. Stated by the channel's normalizer only
|
|
89
|
+
* where it proved the answer; absent means "not established". Read to
|
|
90
|
+
* decide whether a reply is expected before any text exists, never to
|
|
91
|
+
* admit or deny: admission is the gate's job, upstream of this.
|
|
92
|
+
*/
|
|
93
|
+
botMentioned: z.boolean().optional(),
|
|
88
94
|
/**
|
|
89
95
|
* Slack-specific: the `edited.ts` float-string from a `message_changed`
|
|
90
96
|
* event. Used by the daemon to reject out-of-order edit deliveries whose
|
package/openapi.yaml
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
openapi: 3.1.0
|
|
4
4
|
info:
|
|
5
5
|
title: Vellum Assistant API
|
|
6
|
-
version: 0.12.
|
|
6
|
+
version: 0.12.1
|
|
7
7
|
description: Auto-generated OpenAPI specification for the Vellum Assistant runtime HTTP server.
|
|
8
8
|
servers:
|
|
9
9
|
- url: http://127.0.0.1:7821
|
|
@@ -5042,7 +5042,7 @@ paths:
|
|
|
5042
5042
|
type: string
|
|
5043
5043
|
required:
|
|
5044
5044
|
- type
|
|
5045
|
-
|
|
5045
|
+
botMentioned:
|
|
5046
5046
|
type: boolean
|
|
5047
5047
|
slackEditedTs:
|
|
5048
5048
|
type: string
|
|
@@ -11941,6 +11941,8 @@ paths:
|
|
|
11941
11941
|
- ready
|
|
11942
11942
|
- failed
|
|
11943
11943
|
- unsupported
|
|
11944
|
+
automationActive:
|
|
11945
|
+
type: boolean
|
|
11944
11946
|
stage:
|
|
11945
11947
|
type: string
|
|
11946
11948
|
enum:
|
|
@@ -11971,6 +11973,8 @@ paths:
|
|
|
11971
11973
|
- ready
|
|
11972
11974
|
- failed
|
|
11973
11975
|
- unsupported
|
|
11976
|
+
automationActive:
|
|
11977
|
+
type: boolean
|
|
11974
11978
|
stage:
|
|
11975
11979
|
type: string
|
|
11976
11980
|
enum:
|
|
@@ -26622,26 +26626,44 @@ paths:
|
|
|
26622
26626
|
description: Resolved version (installed copy first, then repo `package.json`).
|
|
26623
26627
|
source:
|
|
26624
26628
|
anyOf:
|
|
26625
|
-
-
|
|
26626
|
-
|
|
26627
|
-
|
|
26628
|
-
|
|
26629
|
-
|
|
26630
|
-
|
|
26631
|
-
|
|
26632
|
-
|
|
26633
|
-
|
|
26634
|
-
|
|
26635
|
-
|
|
26636
|
-
|
|
26637
|
-
|
|
26638
|
-
|
|
26639
|
-
|
|
26640
|
-
|
|
26641
|
-
|
|
26642
|
-
|
|
26643
|
-
|
|
26644
|
-
|
|
26629
|
+
- oneOf:
|
|
26630
|
+
- type: object
|
|
26631
|
+
properties:
|
|
26632
|
+
kind:
|
|
26633
|
+
type: string
|
|
26634
|
+
const: github
|
|
26635
|
+
repo:
|
|
26636
|
+
type: string
|
|
26637
|
+
description: "`owner/repo` of the external plugin repository."
|
|
26638
|
+
path:
|
|
26639
|
+
description: Directory within the repo, when the plugin is not at the root.
|
|
26640
|
+
type: string
|
|
26641
|
+
ref:
|
|
26642
|
+
type: string
|
|
26643
|
+
description: Pinned git ref the plugin is fetched from.
|
|
26644
|
+
required:
|
|
26645
|
+
- kind
|
|
26646
|
+
- repo
|
|
26647
|
+
- ref
|
|
26648
|
+
additionalProperties: false
|
|
26649
|
+
- type: object
|
|
26650
|
+
properties:
|
|
26651
|
+
kind:
|
|
26652
|
+
type: string
|
|
26653
|
+
const: local
|
|
26654
|
+
path:
|
|
26655
|
+
type: string
|
|
26656
|
+
description: Package key in the assistant bundle.
|
|
26657
|
+
version:
|
|
26658
|
+
type: string
|
|
26659
|
+
description: Bundled package version.
|
|
26660
|
+
required:
|
|
26661
|
+
- kind
|
|
26662
|
+
- path
|
|
26663
|
+
- version
|
|
26664
|
+
additionalProperties: false
|
|
26665
|
+
description: Reviewed source of the marketplace entry.
|
|
26666
|
+
type: object
|
|
26645
26667
|
- type: "null"
|
|
26646
26668
|
description: Pinned origin from the marketplace entry, or null when an installed copy has no catalog entry.
|
|
26647
26669
|
readme:
|
|
@@ -26996,28 +27018,42 @@ paths:
|
|
|
26996
27018
|
description: ISO-8601 install timestamp from the sidecar; null when absent.
|
|
26997
27019
|
source:
|
|
26998
27020
|
anyOf:
|
|
26999
|
-
-
|
|
27000
|
-
|
|
27001
|
-
|
|
27002
|
-
|
|
27003
|
-
|
|
27004
|
-
|
|
27005
|
-
|
|
27006
|
-
|
|
27007
|
-
|
|
27008
|
-
|
|
27009
|
-
|
|
27010
|
-
|
|
27011
|
-
|
|
27012
|
-
|
|
27013
|
-
|
|
27014
|
-
|
|
27015
|
-
|
|
27016
|
-
|
|
27017
|
-
|
|
27018
|
-
|
|
27019
|
-
|
|
27021
|
+
- oneOf:
|
|
27022
|
+
- type: object
|
|
27023
|
+
properties:
|
|
27024
|
+
kind:
|
|
27025
|
+
type: string
|
|
27026
|
+
const: github
|
|
27027
|
+
owner:
|
|
27028
|
+
type: string
|
|
27029
|
+
repo:
|
|
27030
|
+
type: string
|
|
27031
|
+
path:
|
|
27032
|
+
type: string
|
|
27033
|
+
ref:
|
|
27034
|
+
type: string
|
|
27035
|
+
required:
|
|
27036
|
+
- kind
|
|
27037
|
+
- owner
|
|
27038
|
+
- repo
|
|
27039
|
+
- ref
|
|
27040
|
+
additionalProperties: false
|
|
27041
|
+
- type: object
|
|
27042
|
+
properties:
|
|
27043
|
+
kind:
|
|
27044
|
+
type: string
|
|
27045
|
+
const: local
|
|
27046
|
+
path:
|
|
27047
|
+
type: string
|
|
27048
|
+
version:
|
|
27049
|
+
type: string
|
|
27050
|
+
required:
|
|
27051
|
+
- kind
|
|
27052
|
+
- path
|
|
27053
|
+
- version
|
|
27054
|
+
additionalProperties: false
|
|
27020
27055
|
description: Source coordinates recorded in the install-time provenance sidecar.
|
|
27056
|
+
type: object
|
|
27021
27057
|
- type: "null"
|
|
27022
27058
|
description: Source recorded at install time; null when no sidecar exists.
|
|
27023
27059
|
localChanges:
|
|
@@ -27076,6 +27112,9 @@ paths:
|
|
|
27076
27112
|
anyOf:
|
|
27077
27113
|
- type: object
|
|
27078
27114
|
properties:
|
|
27115
|
+
kind:
|
|
27116
|
+
type: string
|
|
27117
|
+
const: local
|
|
27079
27118
|
repo:
|
|
27080
27119
|
type: string
|
|
27081
27120
|
description: "`owner/repo` of the external plugin repository."
|
|
@@ -27111,6 +27150,9 @@ paths:
|
|
|
27111
27150
|
marketplaceRef:
|
|
27112
27151
|
type: string
|
|
27113
27152
|
description: Ref of the canonical repo the marketplace manifest was read from.
|
|
27153
|
+
version:
|
|
27154
|
+
description: Bundled package version.
|
|
27155
|
+
type: string
|
|
27114
27156
|
required:
|
|
27115
27157
|
- repo
|
|
27116
27158
|
- path
|
|
@@ -27547,7 +27589,7 @@ paths:
|
|
|
27547
27589
|
description: Install name. Matches `assistant plugins install <name>`.
|
|
27548
27590
|
path:
|
|
27549
27591
|
type: string
|
|
27550
|
-
description:
|
|
27592
|
+
description: Human-readable catalog origin locator.
|
|
27551
27593
|
description:
|
|
27552
27594
|
description: Short description, when known (external entries only today).
|
|
27553
27595
|
type: string
|
|
@@ -27561,27 +27603,87 @@ paths:
|
|
|
27561
27603
|
- type: string
|
|
27562
27604
|
- type: "null"
|
|
27563
27605
|
description: Marketplace category slug (Skills taxonomy); null when the entry declares none.
|
|
27564
|
-
|
|
27606
|
+
integration:
|
|
27565
27607
|
type: object
|
|
27566
27608
|
properties:
|
|
27567
27609
|
kind:
|
|
27568
27610
|
type: string
|
|
27569
|
-
const:
|
|
27570
|
-
|
|
27611
|
+
const: mcp
|
|
27612
|
+
displayName:
|
|
27613
|
+
type: string
|
|
27614
|
+
documentationUrl:
|
|
27571
27615
|
type: string
|
|
27572
|
-
|
|
27573
|
-
path:
|
|
27574
|
-
description: Directory within the repo, when the plugin is not at the root.
|
|
27616
|
+
verifiedAt:
|
|
27575
27617
|
type: string
|
|
27576
|
-
|
|
27618
|
+
verification:
|
|
27619
|
+
type: string
|
|
27620
|
+
const: documentation-only
|
|
27621
|
+
setup:
|
|
27622
|
+
type: object
|
|
27623
|
+
properties:
|
|
27624
|
+
mode:
|
|
27625
|
+
type: string
|
|
27626
|
+
enum:
|
|
27627
|
+
- oauth
|
|
27628
|
+
- manual
|
|
27629
|
+
instructions:
|
|
27630
|
+
type: string
|
|
27631
|
+
required:
|
|
27632
|
+
- mode
|
|
27633
|
+
- instructions
|
|
27634
|
+
additionalProperties: false
|
|
27635
|
+
logo:
|
|
27636
|
+
type: string
|
|
27637
|
+
oauthProvider:
|
|
27577
27638
|
type: string
|
|
27578
|
-
description: Pinned git ref the plugin is fetched from.
|
|
27579
27639
|
required:
|
|
27580
27640
|
- kind
|
|
27581
|
-
-
|
|
27582
|
-
-
|
|
27641
|
+
- displayName
|
|
27642
|
+
- documentationUrl
|
|
27643
|
+
- verifiedAt
|
|
27644
|
+
- verification
|
|
27645
|
+
- setup
|
|
27646
|
+
- logo
|
|
27583
27647
|
additionalProperties: false
|
|
27584
|
-
|
|
27648
|
+
source:
|
|
27649
|
+
oneOf:
|
|
27650
|
+
- type: object
|
|
27651
|
+
properties:
|
|
27652
|
+
kind:
|
|
27653
|
+
type: string
|
|
27654
|
+
const: github
|
|
27655
|
+
repo:
|
|
27656
|
+
type: string
|
|
27657
|
+
description: "`owner/repo` of the external plugin repository."
|
|
27658
|
+
path:
|
|
27659
|
+
description: Directory within the repo, when the plugin is not at the root.
|
|
27660
|
+
type: string
|
|
27661
|
+
ref:
|
|
27662
|
+
type: string
|
|
27663
|
+
description: Pinned git ref the plugin is fetched from.
|
|
27664
|
+
required:
|
|
27665
|
+
- kind
|
|
27666
|
+
- repo
|
|
27667
|
+
- ref
|
|
27668
|
+
additionalProperties: false
|
|
27669
|
+
- type: object
|
|
27670
|
+
properties:
|
|
27671
|
+
kind:
|
|
27672
|
+
type: string
|
|
27673
|
+
const: local
|
|
27674
|
+
path:
|
|
27675
|
+
type: string
|
|
27676
|
+
description: Package key in the assistant bundle.
|
|
27677
|
+
version:
|
|
27678
|
+
type: string
|
|
27679
|
+
description: Bundled package version.
|
|
27680
|
+
required:
|
|
27681
|
+
- kind
|
|
27682
|
+
- path
|
|
27683
|
+
- version
|
|
27684
|
+
additionalProperties: false
|
|
27685
|
+
description: Reviewed source of the marketplace entry.
|
|
27686
|
+
type: object
|
|
27585
27687
|
required:
|
|
27586
27688
|
- name
|
|
27587
27689
|
- path
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vellumai/assistant",
|
|
3
|
-
"version": "0.12.2-staging.
|
|
3
|
+
"version": "0.12.2-staging.7",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -24,16 +24,17 @@
|
|
|
24
24
|
"lint:unused": "knip --include files,dependencies,unlisted",
|
|
25
25
|
"lint:circular": "bun run scripts/check-circular-deps.ts",
|
|
26
26
|
"lint:unused:production": "knip --production --include exports",
|
|
27
|
-
"
|
|
27
|
+
"sync:bundled-catalog": "cd .. && bun run meta/sync-bundled-copies.ts && bun run assistant/scripts/generate-bundled-plugin-packages.ts",
|
|
28
|
+
"pretypecheck": "bun run sync:bundled-catalog",
|
|
28
29
|
"typecheck": "bunx tsc --noEmit",
|
|
29
|
-
"pretypecheck:fast": "
|
|
30
|
+
"pretypecheck:fast": "bun run sync:bundled-catalog",
|
|
30
31
|
"typecheck:fast": "bunx tsgo --noEmit",
|
|
31
32
|
"test": "bun run scripts/test.ts",
|
|
32
33
|
"test:coverage": "COVERAGE=true bun run scripts/test.ts",
|
|
33
34
|
"test:stable": "EXCLUDE_EXPERIMENTAL=true bun run scripts/test.ts",
|
|
34
35
|
"test:bench": "find src -type f -name '*.benchmark.test.ts' -print0 | xargs -0 -P 1 -I {} bun test {}",
|
|
35
36
|
"test:filesystem-tools": "bash scripts/test-filesystem-tools.sh",
|
|
36
|
-
"postinstall": "
|
|
37
|
+
"postinstall": "bun run scripts/postinstall.ts"
|
|
37
38
|
},
|
|
38
39
|
"dependencies": {
|
|
39
40
|
"@agentclientprotocol/sdk": "0.25.0",
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { lstatSync, readdirSync, readFileSync, realpathSync } from "node:fs";
|
|
2
|
+
import { join, relative, resolve, sep } from "node:path";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
AGENT_PLUGINS_MCP_SCHEMA_URL,
|
|
6
|
+
SpecMcpDocumentSchema,
|
|
7
|
+
SpecMcpServerSchema,
|
|
8
|
+
} from "../src/mcp/spec-schema.js";
|
|
9
|
+
import {
|
|
10
|
+
readPluginManifest,
|
|
11
|
+
STANDARD_PLUGIN_MANIFEST,
|
|
12
|
+
} from "../src/util/plugin-manifest.js";
|
|
13
|
+
|
|
14
|
+
export interface BundledPackageFile {
|
|
15
|
+
path: string;
|
|
16
|
+
contentBase64: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface BundledPackage {
|
|
20
|
+
version: string;
|
|
21
|
+
files: BundledPackageFile[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Validate and embed every local source in the canonical marketplace. */
|
|
25
|
+
export function buildBundledPluginPackages(
|
|
26
|
+
repoRoot: string,
|
|
27
|
+
): Record<string, BundledPackage> {
|
|
28
|
+
const marketplacePath = join(repoRoot, "plugins", "marketplace.json");
|
|
29
|
+
const manifest = JSON.parse(readFileSync(marketplacePath, "utf8")) as {
|
|
30
|
+
plugins?: unknown;
|
|
31
|
+
};
|
|
32
|
+
if (!Array.isArray(manifest.plugins)) {
|
|
33
|
+
throw new Error("plugins/marketplace.json is missing its plugins array");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const pluginsRoot = realpathSync(join(repoRoot, "plugins"));
|
|
37
|
+
const packages: Record<string, BundledPackage> = {};
|
|
38
|
+
for (const rawEntry of manifest.plugins) {
|
|
39
|
+
if (typeof rawEntry !== "object" || rawEntry === null) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const entry = rawEntry as Record<string, unknown>;
|
|
43
|
+
const rawSource = entry.source;
|
|
44
|
+
if (typeof rawSource !== "object" || rawSource === null) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const source = rawSource as Record<string, unknown>;
|
|
48
|
+
if (source.source !== "local") {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (
|
|
52
|
+
typeof entry.name !== "string" ||
|
|
53
|
+
typeof source.path !== "string" ||
|
|
54
|
+
typeof source.version !== "string"
|
|
55
|
+
) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
"local marketplace entries require name, path, and version",
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const pathSegments = source.path.split("/");
|
|
62
|
+
if (
|
|
63
|
+
!source.path.startsWith("plugins/") ||
|
|
64
|
+
source.path.includes("\\") ||
|
|
65
|
+
pathSegments.some(
|
|
66
|
+
(segment) => segment === "" || segment === "." || segment === "..",
|
|
67
|
+
)
|
|
68
|
+
) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`local marketplace package path is not canonical: ${source.path}`,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
let packageRoot = resolve(repoRoot);
|
|
74
|
+
for (const segment of pathSegments) {
|
|
75
|
+
packageRoot = join(packageRoot, segment);
|
|
76
|
+
if (lstatSync(packageRoot).isSymbolicLink()) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
`local marketplace package path may not contain symlinks: ${source.path}`,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const packageRealpath = realpathSync(packageRoot);
|
|
83
|
+
const relativeToPlugins = relative(pluginsRoot, packageRealpath);
|
|
84
|
+
if (
|
|
85
|
+
relativeToPlugins === "" ||
|
|
86
|
+
relativeToPlugins === ".." ||
|
|
87
|
+
relativeToPlugins.startsWith(`..${sep}`)
|
|
88
|
+
) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
`local marketplace package escapes plugins/: ${source.path}`,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const pluginManifest = readPluginManifest(packageRealpath);
|
|
95
|
+
if (
|
|
96
|
+
pluginManifest.source !== STANDARD_PLUGIN_MANIFEST ||
|
|
97
|
+
pluginManifest.name !== entry.name ||
|
|
98
|
+
pluginManifest.version !== source.version
|
|
99
|
+
) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`local marketplace package ${source.path} must match entry name and version`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
const rawMcp = JSON.parse(
|
|
105
|
+
readFileSync(join(packageRealpath, "mcp.json"), "utf8"),
|
|
106
|
+
) as unknown;
|
|
107
|
+
const mcp = SpecMcpDocumentSchema.parse(rawMcp);
|
|
108
|
+
if (mcp.$schema !== AGENT_PLUGINS_MCP_SCHEMA_URL) {
|
|
109
|
+
throw new Error(
|
|
110
|
+
`local marketplace package ${source.path} must use the Agent Plugins MCP schema`,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
if (Object.keys(mcp.mcpServers).length === 0) {
|
|
114
|
+
throw new Error(
|
|
115
|
+
`local marketplace package ${source.path} must declare an MCP server`,
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
for (const server of Object.values(mcp.mcpServers)) {
|
|
119
|
+
SpecMcpServerSchema.parse(server);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const files: BundledPackageFile[] = [];
|
|
123
|
+
const visit = (directory: string): void => {
|
|
124
|
+
for (const child of readdirSync(directory, { withFileTypes: true })) {
|
|
125
|
+
const childPath = join(directory, child.name);
|
|
126
|
+
if (child.isSymbolicLink() || lstatSync(childPath).isSymbolicLink()) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`local marketplace packages may not contain symlinks: ${source.path}/${child.name}`,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
if (child.isDirectory()) {
|
|
132
|
+
visit(childPath);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (!child.isFile()) {
|
|
136
|
+
throw new Error(
|
|
137
|
+
`local marketplace package contains an unsupported entry: ${childPath}`,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
files.push({
|
|
141
|
+
path: relative(packageRealpath, childPath).split(sep).join("/"),
|
|
142
|
+
contentBase64: readFileSync(childPath).toString("base64"),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
visit(packageRealpath);
|
|
147
|
+
files.sort((a, b) => a.path.localeCompare(b.path));
|
|
148
|
+
if (packages[source.path]) {
|
|
149
|
+
throw new Error(`duplicate local marketplace package: ${source.path}`);
|
|
150
|
+
}
|
|
151
|
+
packages[source.path] = { version: source.version, files };
|
|
152
|
+
}
|
|
153
|
+
return packages;
|
|
154
|
+
}
|