@vellumai/assistant 0.6.0 → 0.6.2
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 +4 -0
- package/ARCHITECTURE.md +68 -15
- package/Dockerfile +2 -2
- package/bun.lock +6 -2
- package/docker-entrypoint.sh +42 -1
- package/docs/architecture/integrations.md +1 -1
- package/docs/architecture/memory.md +21 -24
- package/node_modules/@vellumai/ces-contracts/src/handles.ts +7 -9
- package/openapi.yaml +539 -4
- package/package.json +5 -1
- package/src/__tests__/anthropic-provider.test.ts +160 -95
- package/src/__tests__/app-dir-path-guard.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +47 -1
- package/src/__tests__/app-source-watcher.test.ts +159 -0
- package/src/__tests__/assistant-event-hub.test.ts +30 -0
- package/src/__tests__/checker.test.ts +138 -172
- package/src/__tests__/cli-command-risk-guard.test.ts +1 -1
- package/src/__tests__/config-schema.test.ts +5 -0
- package/src/__tests__/context-overflow-approval.test.ts +5 -5
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +4 -6
- package/src/__tests__/conversation-agent-loop.test.ts +4 -51
- package/src/__tests__/conversation-analysis-routes.test.ts +169 -0
- package/src/__tests__/conversation-directories-parse.test.ts +105 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +653 -832
- package/src/__tests__/conversation-runtime-workspace.test.ts +1 -93
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +17 -4
- package/src/__tests__/conversation-wipe.test.ts +2 -6
- package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -12
- package/src/__tests__/conversation-workspace-injection.test.ts +25 -26
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
- package/src/__tests__/copy-composer-tc-templates.test.ts +335 -0
- package/src/__tests__/credential-execution-approval-bridge.test.ts +0 -2
- package/src/__tests__/date-context.test.ts +76 -210
- package/src/__tests__/db-schedule-syntax-migration.test.ts +16 -1
- package/src/__tests__/file-list-tool.test.ts +219 -0
- package/src/__tests__/first-greeting.test.ts +1 -1
- package/src/__tests__/heartbeat-service.test.ts +180 -3
- package/src/__tests__/identity-routes.test.ts +328 -0
- package/src/__tests__/init-feature-flag-overrides.test.ts +167 -0
- package/src/__tests__/injection-block.test.ts +24 -0
- package/src/__tests__/inline-command-runner.test.ts +7 -5
- package/src/__tests__/install-skill-routing.test.ts +7 -6
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +15 -14
- package/src/__tests__/list-messages-tool-merge.test.ts +300 -0
- package/src/__tests__/llm-context-normalization.test.ts +18 -18
- package/src/__tests__/llm-context-route-provider.test.ts +101 -0
- package/src/__tests__/llm-request-log-turn-query.test.ts +162 -0
- package/src/__tests__/log-export-workspace.test.ts +257 -100
- package/src/__tests__/managed-credential-catalog-cli.test.ts +12 -14
- package/src/__tests__/mcp-abort-signal.test.ts +5 -0
- package/src/__tests__/mcp-client-auth.test.ts +5 -0
- package/src/__tests__/memory-recall-log-store.test.ts +132 -0
- package/src/__tests__/migration-export-streaming.test.ts +304 -0
- package/src/__tests__/migration-import-commit-http.test.ts +11 -10
- package/src/__tests__/mock-fetch.ts +87 -0
- package/src/__tests__/navigate-settings-tab.test.ts +14 -1
- package/src/__tests__/notification-broadcaster.test.ts +65 -0
- package/src/__tests__/notification-decision-recipient-context.test.ts +282 -0
- package/src/__tests__/onboarding-template-contract.test.ts +63 -14
- package/src/__tests__/parser.test.ts +32 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +452 -0
- package/src/__tests__/permission-controls-v2-flag.test.ts +55 -0
- package/src/__tests__/permission-mode-sse.test.ts +418 -0
- package/src/__tests__/permission-mode-store.test.ts +277 -0
- package/src/__tests__/permission-mode.test.ts +101 -0
- package/src/__tests__/pkb-autoinject.test.ts +96 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +359 -0
- package/src/__tests__/profiler-routes.test.ts +502 -0
- package/src/__tests__/profiler-run-store.test.ts +441 -0
- package/src/__tests__/proxy-approval-callback.test.ts +4 -75
- package/src/__tests__/registry.test.ts +1 -1
- package/src/__tests__/require-fresh-approval.test.ts +0 -2
- package/src/__tests__/sandbox-diagnostics.test.ts +1 -32
- package/src/__tests__/sandbox-host-parity.test.ts +5 -4
- package/src/__tests__/scheduler-reuse-conversation.test.ts +368 -0
- package/src/__tests__/scrub-corrupted-image-attachments.test.ts +278 -0
- package/src/__tests__/search-skills-unified.test.ts +4 -3
- package/src/__tests__/send-endpoint-busy.test.ts +42 -3
- package/src/__tests__/set-permission-mode.test.ts +274 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +12 -0
- package/src/__tests__/skill-memory.test.ts +2 -783
- package/src/__tests__/strip-memory-injections.test.ts +187 -0
- package/src/__tests__/subagent-detail.test.ts +84 -0
- package/src/__tests__/subagent-disposal.test.ts +308 -0
- package/src/__tests__/subagent-manager-notify.test.ts +19 -10
- package/src/__tests__/subagent-notify-parent.test.ts +390 -0
- package/src/__tests__/subagent-role-registry.test.ts +108 -0
- package/src/__tests__/subagent-tool-filtering.test.ts +71 -0
- package/src/__tests__/subagent-tools.test.ts +464 -4
- package/src/__tests__/system-prompt-ask-mode.test.ts +139 -0
- package/src/__tests__/task-memory-cleanup.test.ts +12 -12
- package/src/__tests__/terminal-sandbox.test.ts +1 -1
- package/src/__tests__/terminal-tools.test.ts +16 -29
- package/src/__tests__/test-preload.ts +18 -0
- package/src/__tests__/tool-domain-event-publisher.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -8
- package/src/__tests__/tool-executor.test.ts +4 -27
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
- package/src/__tests__/top-level-renderer.test.ts +10 -13
- package/src/__tests__/transport-hints-queue.test.ts +77 -0
- package/src/__tests__/trust-store.test.ts +4 -4
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +116 -2
- package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +387 -0
- package/src/__tests__/workspace-migration-030-seed-pkb-autoinject.test.ts +168 -0
- package/src/__tests__/workspace-policy.test.ts +2 -7
- package/src/agent/loop.ts +6 -29
- package/src/approvals/guardian-request-resolvers.ts +24 -0
- package/src/avatar/traits-png-sync.ts +3 -3
- package/src/channels/types.ts +5 -0
- package/src/cli/__tests__/run-assistant-command.ts +56 -0
- package/src/cli/__tests__/unknown-command.test.ts +33 -0
- package/src/cli/commands/__tests__/email-download.test.ts +245 -0
- package/src/cli/commands/__tests__/email-list.test.ts +192 -0
- package/src/cli/commands/__tests__/email-register.test.ts +186 -0
- package/src/cli/commands/__tests__/email-send.test.ts +291 -0
- package/src/cli/commands/__tests__/email-status.test.ts +181 -0
- package/src/cli/commands/__tests__/email-unregister.test.ts +139 -0
- package/src/cli/commands/__tests__/routes.test.ts +562 -0
- package/src/cli/commands/conversations.ts +1 -8
- package/src/cli/commands/default-action.ts +68 -1
- package/src/cli/commands/email.ts +584 -835
- package/src/cli/commands/memory.ts +1 -34
- package/src/cli/commands/notifications.ts +7 -2
- package/src/cli/commands/oauth/__tests__/connect.test.ts +27 -0
- package/src/cli/commands/oauth/connect.ts +25 -5
- package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +1 -1
- package/src/cli/commands/routes.ts +396 -0
- package/src/cli/commands/skills.ts +130 -20
- package/src/cli/program.ts +11 -2
- package/src/cli.ts +1 -120
- package/src/config/assistant-feature-flags.ts +59 -55
- package/src/config/bundled-skills/app-builder/SKILL.md +91 -5
- package/src/config/bundled-skills/gmail/SKILL.md +13 -8
- package/src/config/bundled-skills/gmail/TOOLS.json +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -1
- package/src/config/bundled-skills/messaging/SKILL.md +7 -0
- package/src/config/bundled-skills/schedule/SKILL.md +22 -2
- package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
- package/src/config/bundled-skills/settings/TOOLS.json +1 -1
- package/src/config/bundled-skills/settings/tools/avatar-get.ts +3 -13
- package/src/config/bundled-skills/settings/tools/avatar-remove.ts +2 -4
- package/src/config/bundled-skills/settings/tools/avatar-update.ts +5 -2
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +8 -3
- package/src/config/bundled-skills/slack/SKILL.md +2 -0
- package/src/config/bundled-skills/subagent/SKILL.md +43 -3
- package/src/config/bundled-skills/subagent/TOOLS.json +29 -4
- package/src/config/env-registry.ts +63 -0
- package/src/config/feature-flag-registry.json +17 -1
- package/src/config/schema.ts +8 -0
- package/src/config/schemas/filing.ts +51 -0
- package/src/config/schemas/heartbeat.ts +15 -12
- package/src/config/schemas/memory-lifecycle.ts +12 -0
- package/src/config/schemas/security.ts +14 -0
- package/src/config/schemas/services.ts +8 -0
- package/src/credential-execution/approval-bridge.ts +0 -1
- package/src/credential-execution/managed-catalog.ts +3 -7
- package/src/daemon/app-source-watcher.ts +93 -0
- package/src/daemon/config-watcher.ts +85 -3
- package/src/daemon/context-overflow-approval.ts +0 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +20 -0
- package/src/daemon/conversation-agent-loop.ts +179 -65
- package/src/daemon/conversation-attachments.ts +0 -1
- package/src/daemon/conversation-history.ts +4 -19
- package/src/daemon/conversation-lifecycle.ts +8 -14
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +30 -8
- package/src/daemon/conversation-queue-manager.ts +8 -0
- package/src/daemon/conversation-runtime-assembly.ts +359 -308
- package/src/daemon/conversation-surfaces.ts +65 -0
- package/src/daemon/conversation-tool-setup.ts +44 -17
- package/src/daemon/conversation-workspace.ts +1 -2
- package/src/daemon/conversation.ts +19 -3
- package/src/daemon/date-context.ts +26 -53
- package/src/daemon/first-greeting.ts +1 -1
- package/src/daemon/handlers/conversations.ts +5 -7
- package/src/daemon/handlers/shared.test.ts +143 -0
- package/src/daemon/handlers/shared.ts +70 -5
- package/src/daemon/handlers/skills.ts +11 -18
- package/src/daemon/lifecycle.ts +220 -158
- package/src/daemon/message-types/conversations.ts +29 -6
- package/src/daemon/message-types/messages.ts +9 -2
- package/src/daemon/message-types/notifications.ts +12 -0
- package/src/daemon/message-types/schedules.ts +1 -0
- package/src/daemon/message-types/settings.ts +18 -0
- package/src/daemon/profiler-run-store.ts +557 -0
- package/src/daemon/server.ts +87 -10
- package/src/daemon/shutdown-handlers.ts +5 -0
- package/src/daemon/tool-side-effects.ts +23 -3
- package/src/daemon/transport-hints.ts +33 -0
- package/src/export/transcript-formatter.ts +148 -0
- package/src/filing/filing-service.ts +228 -0
- package/src/heartbeat/heartbeat-service.ts +96 -7
- package/src/index.ts +1 -1
- package/src/mcp/client.ts +6 -0
- package/src/mcp/mcp-oauth-provider.ts +149 -27
- package/src/memory/admin.ts +33 -32
- package/src/memory/app-store.ts +69 -0
- package/src/memory/conversation-bootstrap.ts +1 -1
- package/src/memory/conversation-crud.ts +151 -117
- package/src/memory/conversation-directories.ts +39 -0
- package/src/memory/conversation-group-migration.ts +66 -6
- package/src/memory/conversation-queries.ts +58 -12
- package/src/memory/conversation-title-service.ts +1 -0
- package/src/memory/db-init.ts +182 -376
- package/src/memory/embedding-local.ts +1 -1
- package/src/memory/graph/bootstrap.ts +75 -66
- package/src/memory/graph/capability-seed.ts +167 -17
- package/src/memory/graph/consolidation.ts +38 -4
- package/src/memory/graph/conversation-graph-memory.ts +133 -104
- package/src/memory/graph/extraction-job.ts +9 -4
- package/src/memory/graph/extraction.ts +66 -23
- package/src/memory/graph/graph-memory-state-store.ts +37 -0
- package/src/memory/graph/graph-search.ts +29 -15
- package/src/memory/graph/injection.ts +38 -8
- package/src/memory/graph/inspect.ts +12 -3
- package/src/memory/graph/retriever.ts +365 -262
- package/src/memory/graph/store.test.ts +48 -0
- package/src/memory/graph/store.ts +150 -11
- package/src/memory/graph/tool-handlers.ts +84 -209
- package/src/memory/graph/tools.ts +8 -52
- package/src/memory/graph/types.ts +24 -0
- package/src/memory/group-crud.ts +25 -9
- package/src/memory/job-handlers/cleanup.ts +44 -1
- package/src/memory/jobs-store.ts +70 -60
- package/src/memory/jobs-worker.ts +44 -28
- package/src/memory/llm-request-log-store.ts +96 -12
- package/src/memory/memory-recall-log-store.ts +49 -5
- package/src/memory/migrations/203-drop-memory-items-tables.ts +33 -1
- package/src/memory/migrations/206-memory-graph-node-edits.ts +19 -0
- package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +131 -0
- package/src/memory/migrations/207-conversation-graph-memory-state.ts +20 -0
- package/src/memory/migrations/208-conversations-last-message-at.ts +35 -0
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +85 -0
- package/src/memory/migrations/210-schedule-reuse-conversation.ts +13 -0
- package/src/memory/migrations/211-memory-recall-logs-query-context.ts +21 -0
- package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +19 -0
- package/src/memory/migrations/index.ts +8 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/schema/conversations.ts +14 -0
- package/src/memory/schema/infrastructure.ts +8 -1
- package/src/memory/schema/memory-core.ts +0 -51
- package/src/memory/schema/memory-graph.ts +15 -0
- package/src/memory/task-memory-cleanup.ts +30 -11
- package/src/messaging/provider.ts +1 -1
- package/src/notifications/broadcaster.ts +6 -0
- package/src/notifications/conversation-pairing.ts +12 -4
- package/src/notifications/copy-composer.ts +86 -0
- package/src/notifications/decision-engine.ts +35 -0
- package/src/notifications/emit-signal.ts +14 -0
- package/src/notifications/signal.ts +11 -0
- package/src/oauth/platform-connection.test.ts +2 -2
- package/src/oauth/seed-providers.ts +1 -0
- package/src/permissions/checker.ts +15 -4
- package/src/permissions/defaults.ts +7 -8
- package/src/permissions/permission-mode-store.ts +180 -0
- package/src/permissions/permission-mode.ts +31 -0
- package/src/permissions/prompter.ts +0 -2
- package/src/permissions/workspace-policy.ts +9 -0
- package/src/platform/client.ts +1 -1
- package/src/prompts/system-prompt.ts +59 -7
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +100 -0
- package/src/prompts/templates/BOOTSTRAP.md +76 -162
- package/src/prompts/templates/HEARTBEAT.md +3 -1
- package/src/prompts/templates/SOUL.md +30 -9
- package/src/prompts/templates/UPDATES.md +8 -0
- package/src/providers/anthropic/client.ts +107 -219
- package/src/runtime/assistant-event-hub.ts +22 -0
- package/src/runtime/auth/route-policy.ts +23 -0
- package/src/runtime/auth/token-service.ts +8 -0
- package/src/runtime/http-server.ts +32 -2
- package/src/runtime/http-types.ts +12 -1
- package/src/runtime/migrations/vbundle-builder.ts +389 -3
- package/src/runtime/migrations/vbundle-importer.ts +8 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +378 -0
- package/src/runtime/routes/app-management-routes.ts +1 -11
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +26 -0
- package/src/runtime/routes/archive-utils.ts +29 -0
- package/src/runtime/routes/avatar-routes.ts +2 -9
- package/src/runtime/routes/btw-routes.ts +14 -1
- package/src/runtime/routes/conversation-analysis-routes.ts +185 -0
- package/src/runtime/routes/conversation-management-routes.ts +1 -14
- package/src/runtime/routes/conversation-query-routes.ts +49 -3
- package/src/runtime/routes/conversation-routes.ts +270 -44
- package/src/runtime/routes/group-routes.ts +22 -8
- package/src/runtime/routes/heartbeat-routes.ts +4 -10
- package/src/runtime/routes/identity-routes.ts +53 -18
- package/src/runtime/routes/llm-context-normalization.ts +14 -10
- package/src/runtime/routes/log-export/AGENTS.md +104 -0
- package/src/runtime/routes/log-export/__tests__/workspace-allowlist-error-contract.test.ts +103 -0
- package/src/runtime/routes/log-export/__tests__/workspace-allowlist.test.ts +716 -0
- package/src/runtime/routes/log-export/workspace-allowlist.ts +458 -0
- package/src/runtime/routes/log-export-routes.ts +41 -278
- package/src/runtime/routes/memory-item-routes.test.ts +168 -233
- package/src/runtime/routes/migration-routes.ts +18 -7
- package/src/runtime/routes/profiler-routes.ts +350 -0
- package/src/runtime/routes/schedule-routes.ts +27 -12
- package/src/runtime/routes/settings-routes.ts +95 -8
- package/src/runtime/routes/subagents-routes.ts +28 -7
- package/src/runtime/routes/user-route-dispatcher.ts +223 -0
- package/src/runtime/routes/user-routes.ts +41 -0
- package/src/runtime/routes/workspace-routes.ts +0 -1
- package/src/schedule/schedule-store.ts +30 -0
- package/src/schedule/scheduler.ts +45 -18
- package/src/skills/catalog-install.ts +10 -2
- package/src/skills/inline-command-runner.ts +12 -14
- package/src/skills/managed-store.ts +2 -2
- package/src/skills/skill-memory.ts +1 -293
- package/src/subagent/index.ts +13 -3
- package/src/subagent/manager.ts +308 -29
- package/src/subagent/types.ts +68 -0
- package/src/tasks/task-runner.ts +4 -4
- package/src/tools/apps/executors.ts +29 -4
- package/src/tools/filesystem/list.ts +93 -0
- package/src/tools/permission-checker.ts +78 -18
- package/src/tools/registry.ts +4 -0
- package/src/tools/schedule/create.ts +3 -0
- package/src/tools/schedule/list.ts +1 -0
- package/src/tools/schedule/update.ts +6 -0
- package/src/tools/secret-detection-handler.ts +0 -1
- package/src/tools/shared/filesystem/errors.ts +5 -0
- package/src/tools/shared/filesystem/file-ops-service.ts +90 -2
- package/src/tools/shared/filesystem/types.ts +17 -0
- package/src/tools/shared/shell-output.ts +31 -2
- package/src/tools/skills/sandbox-runner.ts +3 -6
- package/src/tools/subagent/abort.ts +12 -2
- package/src/tools/subagent/message.ts +9 -2
- package/src/tools/subagent/notify-parent.ts +79 -0
- package/src/tools/subagent/read.ts +29 -8
- package/src/tools/subagent/resolve.ts +21 -0
- package/src/tools/subagent/spawn.ts +2 -0
- package/src/tools/subagent/status.ts +11 -1
- package/src/tools/system/avatar-generator.ts +3 -3
- package/src/tools/system/register.ts +23 -0
- package/src/tools/system/set-permission-mode.ts +103 -0
- package/src/tools/terminal/parser.ts +30 -5
- package/src/tools/terminal/safe-env.ts +16 -1
- package/src/tools/terminal/sandbox-diagnostics.ts +4 -4
- package/src/tools/terminal/sandbox.ts +4 -1
- package/src/tools/terminal/shell.ts +3 -5
- package/src/tools/tool-manifest.ts +6 -0
- package/src/tools/types.ts +2 -3
- package/src/util/logger.ts +1 -1
- package/src/util/platform.ts +50 -17
- package/src/watcher/provider-types.ts +1 -1
- package/src/workspace/migrations/023-move-config-files-to-workspace.ts +2 -2
- package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +2 -2
- package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +270 -0
- package/src/workspace/migrations/029-seed-pkb.ts +85 -0
- package/src/workspace/migrations/030-seed-pkb-autoinject.ts +73 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/workspace/top-level-renderer.ts +5 -9
- package/src/__tests__/cli-memory.test.ts +0 -377
- package/src/__tests__/clipboard.test.ts +0 -88
- package/src/cli/cli-memory.ts +0 -179
- package/src/util/clipboard.ts +0 -34
|
@@ -3,7 +3,6 @@ import { describe, expect, test } from "bun:test";
|
|
|
3
3
|
import {
|
|
4
4
|
applyRuntimeInjections,
|
|
5
5
|
injectWorkspaceTopLevelContext,
|
|
6
|
-
stripWorkspaceTopLevelContext,
|
|
7
6
|
} from "../daemon/conversation-runtime-assembly.js";
|
|
8
7
|
import type { Message } from "../providers/types.js";
|
|
9
8
|
|
|
@@ -15,16 +14,12 @@ function userMsg(text: string): Message {
|
|
|
15
14
|
return { role: "user", content: [{ type: "text", text }] };
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
function assistantMsg(text: string): Message {
|
|
19
|
-
return { role: "assistant", content: [{ type: "text", text }] };
|
|
20
|
-
}
|
|
21
|
-
|
|
22
17
|
// ---------------------------------------------------------------------------
|
|
23
18
|
// Tests
|
|
24
19
|
// ---------------------------------------------------------------------------
|
|
25
20
|
|
|
26
21
|
const sampleContext =
|
|
27
|
-
"<
|
|
22
|
+
"<workspace>\nRoot: /sandbox\nDirectories: src, lib, tests\n</workspace>";
|
|
28
23
|
|
|
29
24
|
describe("Workspace top-level context — injection", () => {
|
|
30
25
|
test("prepends workspace block to user message content", () => {
|
|
@@ -62,93 +57,6 @@ describe("Workspace top-level context — injection", () => {
|
|
|
62
57
|
});
|
|
63
58
|
});
|
|
64
59
|
|
|
65
|
-
describe("Workspace top-level context — stripping", () => {
|
|
66
|
-
test("strips injected workspace block from user messages", () => {
|
|
67
|
-
const messages: Message[] = [
|
|
68
|
-
{
|
|
69
|
-
role: "user",
|
|
70
|
-
content: [
|
|
71
|
-
{ type: "text", text: sampleContext },
|
|
72
|
-
{ type: "text", text: "Hello" },
|
|
73
|
-
],
|
|
74
|
-
},
|
|
75
|
-
assistantMsg("Hi there"),
|
|
76
|
-
];
|
|
77
|
-
|
|
78
|
-
const stripped = stripWorkspaceTopLevelContext(messages);
|
|
79
|
-
|
|
80
|
-
expect(stripped).toHaveLength(2);
|
|
81
|
-
expect(stripped[0].content).toHaveLength(1);
|
|
82
|
-
expect((stripped[0].content[0] as { text: string }).text).toBe("Hello");
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test("does not strip non-workspace text blocks", () => {
|
|
86
|
-
const messages: Message[] = [
|
|
87
|
-
userMsg("Regular message"),
|
|
88
|
-
assistantMsg("Response"),
|
|
89
|
-
];
|
|
90
|
-
|
|
91
|
-
const stripped = stripWorkspaceTopLevelContext(messages);
|
|
92
|
-
expect(stripped).toEqual(messages);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
test("removes user message entirely when only workspace block remains", () => {
|
|
96
|
-
const messages: Message[] = [
|
|
97
|
-
{ role: "user", content: [{ type: "text", text: sampleContext }] },
|
|
98
|
-
assistantMsg("Response"),
|
|
99
|
-
];
|
|
100
|
-
|
|
101
|
-
const stripped = stripWorkspaceTopLevelContext(messages);
|
|
102
|
-
expect(stripped).toHaveLength(1);
|
|
103
|
-
expect(stripped[0].role).toBe("assistant");
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
test("does not strip from assistant messages", () => {
|
|
107
|
-
const messages: Message[] = [assistantMsg(sampleContext)];
|
|
108
|
-
|
|
109
|
-
const stripped = stripWorkspaceTopLevelContext(messages);
|
|
110
|
-
expect(stripped).toHaveLength(1);
|
|
111
|
-
expect((stripped[0].content[0] as { text: string }).text).toBe(
|
|
112
|
-
sampleContext,
|
|
113
|
-
);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
test("preserves tool_result blocks during stripping", () => {
|
|
117
|
-
const messages: Message[] = [
|
|
118
|
-
{
|
|
119
|
-
role: "user",
|
|
120
|
-
content: [
|
|
121
|
-
{ type: "text", text: sampleContext },
|
|
122
|
-
{
|
|
123
|
-
type: "tool_result",
|
|
124
|
-
tool_use_id: "tu_1",
|
|
125
|
-
content: "result",
|
|
126
|
-
is_error: false,
|
|
127
|
-
},
|
|
128
|
-
],
|
|
129
|
-
},
|
|
130
|
-
];
|
|
131
|
-
|
|
132
|
-
const stripped = stripWorkspaceTopLevelContext(messages);
|
|
133
|
-
expect(stripped).toHaveLength(1);
|
|
134
|
-
expect(stripped[0].content).toHaveLength(1);
|
|
135
|
-
expect(stripped[0].content[0].type).toBe("tool_result");
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
test("no empty-message artifacts after stripping", () => {
|
|
139
|
-
const messages: Message[] = [
|
|
140
|
-
userMsg("Before"),
|
|
141
|
-
{ role: "user", content: [{ type: "text", text: sampleContext }] },
|
|
142
|
-
assistantMsg("After"),
|
|
143
|
-
];
|
|
144
|
-
|
|
145
|
-
const stripped = stripWorkspaceTopLevelContext(messages);
|
|
146
|
-
expect(stripped).toHaveLength(2);
|
|
147
|
-
expect(stripped[0].role).toBe("user");
|
|
148
|
-
expect(stripped[1].role).toBe("assistant");
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
|
|
152
60
|
describe("applyRuntimeInjections — workspace top-level context", () => {
|
|
153
61
|
test("injects workspace context when provided", () => {
|
|
154
62
|
const messages: Message[] = [userMsg("Hello")];
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
* Regression tests for app surface refresh and eventing side effects in
|
|
3
3
|
* createToolExecutor (conversation-tool-setup.ts).
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* Tests verify that app_refresh, app_create, and app_delete hooks fire
|
|
6
|
+
* correctly, and that removed hooks (app_update, app_file_edit,
|
|
7
|
+
* app_file_write) no longer trigger side effects.
|
|
8
|
+
*
|
|
9
|
+
* File-change detection for file_write/file_edit is handled by
|
|
10
|
+
* AppSourceWatcher (see app-source-watcher.test.ts).
|
|
9
11
|
*/
|
|
10
12
|
|
|
11
13
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
@@ -42,6 +44,16 @@ mock.module("../tools/browser/browser-screencast.js", () => ({
|
|
|
42
44
|
registerConversationSender: mock(() => {}),
|
|
43
45
|
}));
|
|
44
46
|
|
|
47
|
+
// Mock app-store functions used by handleAppChange in tool-side-effects
|
|
48
|
+
mock.module("../memory/app-store.js", () => ({
|
|
49
|
+
getApp: mock(() => null),
|
|
50
|
+
getAppDirPath: mock(() => "/tmp/test-apps/dummy"),
|
|
51
|
+
isMultifileApp: mock(() => false),
|
|
52
|
+
getAppsDir: mock(() => "/tmp/test-apps"),
|
|
53
|
+
resolveAppIdByDirName: mock(() => null),
|
|
54
|
+
resolveAppIdFromPath: mock(() => null),
|
|
55
|
+
}));
|
|
56
|
+
|
|
45
57
|
// ---------------------------------------------------------------------------
|
|
46
58
|
// Import createToolExecutor after mocks are in place
|
|
47
59
|
// ---------------------------------------------------------------------------
|
|
@@ -423,4 +435,5 @@ describe("session-tool-setup app refresh side effects", () => {
|
|
|
423
435
|
expect(updatePublishedSpy).toHaveBeenCalledTimes(1);
|
|
424
436
|
});
|
|
425
437
|
});
|
|
438
|
+
|
|
426
439
|
});
|
|
@@ -94,7 +94,7 @@ describe("wipeConversation", () => {
|
|
|
94
94
|
|
|
95
95
|
test("cancels pending memory jobs", async () => {
|
|
96
96
|
const conv = createConversation("test");
|
|
97
|
-
|
|
97
|
+
await addMessage(conv.id, "user", "hello", undefined, {
|
|
98
98
|
skipIndexing: true,
|
|
99
99
|
});
|
|
100
100
|
|
|
@@ -102,7 +102,7 @@ describe("wipeConversation", () => {
|
|
|
102
102
|
const db = getDb();
|
|
103
103
|
db.run(`DELETE FROM memory_jobs`);
|
|
104
104
|
|
|
105
|
-
enqueueMemoryJob("
|
|
105
|
+
enqueueMemoryJob("graph_extract", { conversationId: conv.id });
|
|
106
106
|
enqueueMemoryJob("build_conversation_summary", {
|
|
107
107
|
conversationId: conv.id,
|
|
108
108
|
});
|
|
@@ -121,8 +121,6 @@ describe("wipeConversation", () => {
|
|
|
121
121
|
.all() as Array<{ status: string; last_error: string | null }>;
|
|
122
122
|
|
|
123
123
|
for (const job of jobs) {
|
|
124
|
-
// Skip embed_item jobs enqueued by wipeConversation's unsupersede logic
|
|
125
|
-
if (job.status === "pending") continue;
|
|
126
124
|
expect(job.status).toBe("failed");
|
|
127
125
|
expect(job.last_error).toContain("conversation_wiped");
|
|
128
126
|
}
|
|
@@ -137,8 +135,6 @@ describe("wipeConversation", () => {
|
|
|
137
135
|
|
|
138
136
|
expect(getConversation(conv.id)).toBeNull();
|
|
139
137
|
expect(result.segmentIds).toEqual([]);
|
|
140
|
-
expect(result.orphanedItemIds).toEqual([]);
|
|
141
|
-
expect(result.unsupersededItemIds).toEqual([]);
|
|
142
138
|
expect(result.deletedSummaryIds).toEqual([]);
|
|
143
139
|
expect(result.cancelledJobCount).toBe(0);
|
|
144
140
|
});
|
|
@@ -91,7 +91,7 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
91
91
|
updateConversationUsage: () => {},
|
|
92
92
|
updateConversationTitle: () => {},
|
|
93
93
|
updateConversationContextWindow: () => {},
|
|
94
|
-
deleteMessageById: () => ({ segmentIds: [],
|
|
94
|
+
deleteMessageById: () => ({ segmentIds: [], deletedSummaryIds: [] }),
|
|
95
95
|
deleteLastExchange: () => 0,
|
|
96
96
|
}));
|
|
97
97
|
|
|
@@ -227,16 +227,13 @@ describe("Conversation workspace cache state", () => {
|
|
|
227
227
|
expect(conversation.isWorkspaceTopLevelDirty()).toBe(false);
|
|
228
228
|
expect(conversation.getWorkspaceTopLevelContext()).not.toBeNull();
|
|
229
229
|
expect(conversation.getWorkspaceTopLevelContext()!).toContain(
|
|
230
|
-
"<
|
|
230
|
+
"<workspace>",
|
|
231
231
|
);
|
|
232
232
|
expect(conversation.getWorkspaceTopLevelContext()!).toContain(
|
|
233
|
-
"</
|
|
233
|
+
"</workspace>",
|
|
234
234
|
);
|
|
235
235
|
expect(conversation.getWorkspaceTopLevelContext()!).toContain(
|
|
236
|
-
`Current conversation
|
|
237
|
-
);
|
|
238
|
-
expect(conversation.getWorkspaceTopLevelContext()!).toContain(
|
|
239
|
-
`Attachment files: ${conversationAttachmentsPath}`,
|
|
236
|
+
`Current conversation attachments: ${conversationAttachmentsPath}`,
|
|
240
237
|
);
|
|
241
238
|
});
|
|
242
239
|
|
|
@@ -267,7 +264,7 @@ describe("Conversation workspace cache state", () => {
|
|
|
267
264
|
|
|
268
265
|
expect(conversation.getWorkspaceTopLevelContext()).not.toBeNull();
|
|
269
266
|
expect(conversation.getWorkspaceTopLevelContext()!).toContain(
|
|
270
|
-
"<
|
|
267
|
+
"<workspace>",
|
|
271
268
|
);
|
|
272
269
|
expect(conversation.isWorkspaceTopLevelDirty()).toBe(false);
|
|
273
270
|
});
|
|
@@ -286,10 +283,7 @@ describe("Conversation workspace cache state", () => {
|
|
|
286
283
|
tempConversation.refreshWorkspaceTopLevelContextIfNeeded();
|
|
287
284
|
|
|
288
285
|
expect(tempConversation.getWorkspaceTopLevelContext()!).toContain(
|
|
289
|
-
`Current conversation
|
|
290
|
-
);
|
|
291
|
-
expect(tempConversation.getWorkspaceTopLevelContext()!).toContain(
|
|
292
|
-
`Attachment files: conversations/${legacyDirName}/attachments/`,
|
|
286
|
+
`Current conversation attachments: conversations/${legacyDirName}/attachments/`,
|
|
293
287
|
);
|
|
294
288
|
} finally {
|
|
295
289
|
rmSync(workspaceRoot, { recursive: true, force: true });
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
2
|
|
|
3
3
|
import type { AgentEvent } from "../agent/loop.js";
|
|
4
|
-
import { getConversationDirName } from "../memory/conversation-disk-view.js";
|
|
5
4
|
import type { Message, ProviderResponse } from "../providers/types.js";
|
|
6
5
|
|
|
7
6
|
// ---------------------------------------------------------------------------
|
|
@@ -124,7 +123,7 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
124
123
|
updateConversationUsage: () => {},
|
|
125
124
|
updateConversationTitle: () => {},
|
|
126
125
|
updateConversationContextWindow: () => {},
|
|
127
|
-
deleteMessageById: () => ({ segmentIds: [],
|
|
126
|
+
deleteMessageById: () => ({ segmentIds: [], deletedSummaryIds: [] }),
|
|
128
127
|
deleteLastExchange: () => 0,
|
|
129
128
|
}));
|
|
130
129
|
|
|
@@ -274,13 +273,6 @@ function messageText(message: Message): string {
|
|
|
274
273
|
.join("\n");
|
|
275
274
|
}
|
|
276
275
|
|
|
277
|
-
const conversationDirName = getConversationDirName(
|
|
278
|
-
"conv-1",
|
|
279
|
-
Date.parse("2026-03-19T12:00:00.000Z"),
|
|
280
|
-
);
|
|
281
|
-
const conversationPath = `conversations/${conversationDirName}/`;
|
|
282
|
-
const conversationAttachmentsPath = `${conversationPath}attachments/`;
|
|
283
|
-
|
|
284
276
|
// ---------------------------------------------------------------------------
|
|
285
277
|
// Tests
|
|
286
278
|
// ---------------------------------------------------------------------------
|
|
@@ -302,8 +294,8 @@ describe("Conversation workspace injection", () => {
|
|
|
302
294
|
const runtimeUser = runCalls[0][runCalls[0].length - 1];
|
|
303
295
|
expect(runtimeUser.role).toBe("user");
|
|
304
296
|
const text = messageText(runtimeUser);
|
|
305
|
-
expect(text).toContain("<
|
|
306
|
-
expect(text).toContain("</
|
|
297
|
+
expect(text).toContain("<workspace>");
|
|
298
|
+
expect(text).toContain("</workspace>");
|
|
307
299
|
});
|
|
308
300
|
|
|
309
301
|
test("workspace context includes root path and directories", async () => {
|
|
@@ -316,8 +308,8 @@ describe("Conversation workspace injection", () => {
|
|
|
316
308
|
const runtimeUser = runCalls[0][runCalls[0].length - 1];
|
|
317
309
|
const text = messageText(runtimeUser);
|
|
318
310
|
expect(text).toContain("Root: /tmp");
|
|
319
|
-
expect(text).toContain(
|
|
320
|
-
expect(text).toContain(
|
|
311
|
+
expect(text).toContain("Directories: src, tests, docs");
|
|
312
|
+
expect(text).toContain("Files: README.md, package.json");
|
|
321
313
|
});
|
|
322
314
|
|
|
323
315
|
test("workspace context is prepended before user text", async () => {
|
|
@@ -331,33 +323,40 @@ describe("Conversation workspace injection", () => {
|
|
|
331
323
|
const firstBlock = runtimeUser.content[0];
|
|
332
324
|
expect(firstBlock.type).toBe("text");
|
|
333
325
|
const firstText = (firstBlock as { type: "text"; text: string }).text;
|
|
334
|
-
expect(firstText).toContain("<
|
|
326
|
+
expect(firstText).toContain("<workspace>");
|
|
335
327
|
});
|
|
336
328
|
|
|
337
|
-
test("workspace context
|
|
329
|
+
test("workspace context persists in history (not stripped between turns)", async () => {
|
|
338
330
|
const conversation = makeConversation();
|
|
339
331
|
await conversation.loadFromDb();
|
|
340
332
|
|
|
341
333
|
await conversation.processMessage("Hello", [], () => {});
|
|
342
334
|
|
|
335
|
+
// Workspace blocks use <workspace> tag which is intentionally NOT stripped.
|
|
343
336
|
const persistedMessages = conversation.getMessages();
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
337
|
+
const userMsg = persistedMessages.find((m) => m.role === "user");
|
|
338
|
+
expect(userMsg).toBeDefined();
|
|
339
|
+
const text = messageText(userMsg!);
|
|
340
|
+
expect(text).toContain("<workspace>");
|
|
348
341
|
});
|
|
349
342
|
|
|
350
|
-
test("
|
|
343
|
+
test("second message does NOT include workspace block", async () => {
|
|
351
344
|
const conversation = makeConversation();
|
|
352
345
|
await conversation.loadFromDb();
|
|
353
346
|
|
|
347
|
+
// First message — workspace is injected
|
|
354
348
|
await conversation.processMessage("Hello", [], () => {});
|
|
355
|
-
|
|
356
|
-
const
|
|
357
|
-
const
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
349
|
+
expect(runCalls).toHaveLength(1);
|
|
350
|
+
const firstCallUser = runCalls[0][runCalls[0].length - 1];
|
|
351
|
+
const firstText = messageText(firstCallUser);
|
|
352
|
+
expect(firstText).toContain("<workspace>");
|
|
353
|
+
|
|
354
|
+
// Second message — workspace is NOT injected (not first message, no compaction)
|
|
355
|
+
await conversation.processMessage("Follow up", [], () => {});
|
|
356
|
+
expect(runCalls).toHaveLength(2);
|
|
357
|
+
const secondCallUser = runCalls[1][runCalls[1].length - 1];
|
|
358
|
+
const secondText = messageText(secondCallUser);
|
|
359
|
+
expect(secondText).not.toContain("<workspace>");
|
|
361
360
|
});
|
|
362
361
|
});
|
|
363
362
|
|
|
@@ -120,7 +120,7 @@ mock.module("../memory/conversation-crud.js", () => ({
|
|
|
120
120
|
updateConversationUsage: () => {},
|
|
121
121
|
updateConversationTitle: () => {},
|
|
122
122
|
updateConversationContextWindow: () => {},
|
|
123
|
-
deleteMessageById: () => ({ segmentIds: [],
|
|
123
|
+
deleteMessageById: () => ({ segmentIds: [], deletedSummaryIds: [] }),
|
|
124
124
|
deleteLastExchange: () => 0,
|
|
125
125
|
}));
|
|
126
126
|
|