@vellumai/assistant 0.8.11 → 0.8.12-staging.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/ARCHITECTURE.md +15 -17
- package/README.md +0 -6
- package/bun.lock +6 -122
- package/node_modules/@vellumai/gateway-client/bun.lock +1 -0
- package/node_modules/@vellumai/gateway-client/package.json +3 -1
- package/node_modules/@vellumai/gateway-client/src/__tests__/gateway-client.test.ts +1 -1
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +87 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +3 -5
- package/openapi.yaml +633 -4
- package/package.json +1 -3
- package/src/__tests__/adaptive-thinking-repair.test.ts +185 -0
- package/src/__tests__/agent-loop-compaction-events.test.ts +7 -6
- package/src/__tests__/anthropic-provider.test.ts +129 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +4 -1
- package/src/__tests__/btw-routes.test.ts +7 -34
- package/src/__tests__/checker.test.ts +6 -12
- package/src/__tests__/config-loader-backfill.test.ts +4 -2
- package/src/__tests__/config-loader-quarantine-notice.test.ts +167 -0
- package/src/__tests__/config-watcher.test.ts +2 -2
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-error.test.ts +2 -6
- package/src/__tests__/conversation-history-web-search.test.ts +8 -0
- package/src/__tests__/conversation-title-service.test.ts +2 -1
- package/src/__tests__/credential-security-invariants.test.ts +1 -1
- package/src/__tests__/disk-pressure-tools.test.ts +1 -1
- package/src/__tests__/exploration-drift-hook.test.ts +692 -0
- package/src/__tests__/filing-service.test.ts +8 -3
- package/src/__tests__/guardian-action-store.test.ts +0 -167
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +1 -1
- package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -1
- package/src/__tests__/heartbeat-service.test.ts +5 -2
- package/src/__tests__/identity-intro-cache.test.ts +12 -5
- package/src/__tests__/identity-routes.test.ts +16 -57
- package/src/__tests__/injector-chain.test.ts +8 -3
- package/src/__tests__/injector-config-quarantine-notice.test.ts +115 -0
- package/src/__tests__/llm-catalog-parity.test.ts +16 -0
- package/src/__tests__/llm-usage-store.test.ts +11 -0
- package/src/__tests__/log-export-workspace.test.ts +468 -3
- package/src/__tests__/memory-v2-static-injector.test.ts +22 -0
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/oauth-cli.test.ts +19 -8
- package/src/__tests__/openai-provider.test.ts +34 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +0 -1
- package/src/__tests__/recurrence-engine.test.ts +45 -0
- package/src/__tests__/schedule-routes.test.ts +34 -0
- package/src/__tests__/scheduler-disk-pressure.test.ts +1 -1
- package/src/__tests__/script-proxy-conversation-manager.test.ts +10 -5
- package/src/__tests__/secret-fixtures.ts +20 -0
- package/src/__tests__/skill-tool-factory.test.ts +49 -0
- package/src/__tests__/subagent-role-registry.test.ts +24 -1
- package/src/__tests__/subagent-tools.test.ts +1 -0
- package/src/__tests__/system-prompt.test.ts +109 -11
- package/src/__tests__/tool-approval-handler.test.ts +85 -0
- package/src/__tests__/tool-audit-listener.test.ts +86 -0
- package/src/__tests__/tool-error-hook.test.ts +1 -0
- package/src/__tests__/tool-result-spool.test.ts +337 -0
- package/src/__tests__/tool-result-truncate-hook.test.ts +1 -0
- package/src/__tests__/validate-input.test.ts +95 -1
- package/src/__tests__/workspace-migration-098-remove-stale-updates-bulletin-file.test.ts +65 -0
- package/src/__tests__/workspace-migration-099-disable-cache-one-shot-callsites.test.ts +139 -0
- package/src/__tests__/workspace-migration-100-upgrade-quality-profile-to-fable-5.test.ts +174 -0
- package/src/__tests__/workspace-migration-101-upgrade-balanced-economy-to-minimax-m3.test.ts +162 -0
- package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +45 -95
- package/src/acp/__tests__/agent-process.test.ts +315 -2
- package/src/acp/__tests__/prepare-agent-env.test.ts +79 -5
- package/src/acp/agent-process.ts +163 -34
- package/src/acp/prepare-agent-env.ts +55 -15
- package/src/agent/loop.ts +81 -24
- package/src/api/events/usage-progress.ts +28 -0
- package/src/api/index.ts +6 -0
- package/src/background-wake/wake-intent-hooks.test.ts +2 -0
- package/src/bundler/app-bundler.ts +25 -42
- package/src/bundler/app-compiler.ts +8 -0
- package/src/calls/call-controller.ts +1 -1
- package/src/cli/commands/plugins.ts +248 -15
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +318 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +16 -9
- package/src/cli/lib/__tests__/plugin-artifact.test.ts +183 -0
- package/src/cli/lib/__tests__/plugin-details.test.ts +158 -0
- package/src/cli/lib/__tests__/plugin-fingerprint.test.ts +245 -0
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +307 -0
- package/src/cli/lib/inspect-plugin.ts +252 -0
- package/src/cli/lib/install-from-github.ts +214 -21
- package/src/cli/lib/list-installed-plugins.ts +17 -6
- package/src/cli/lib/plugin-artifact.ts +103 -0
- package/src/cli/lib/plugin-details.ts +18 -1
- package/src/cli/lib/plugin-fingerprint.ts +197 -0
- package/src/cli/lib/upgrade-plugin.ts +225 -0
- package/src/config/bundled-skills/subagent/SKILL.md +2 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +8 -2
- package/src/config/call-site-defaults.ts +13 -2
- package/src/config/feature-flag-registry.json +8 -16
- package/src/config/loader.ts +52 -59
- package/src/config/schema.ts +0 -2
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
- package/src/config/schemas/__tests__/memory-v3.test.ts +10 -0
- package/src/config/schemas/llm.ts +10 -0
- package/src/config/schemas/memory-v2.ts +13 -0
- package/src/config/schemas/memory-v3.ts +92 -0
- package/src/config/seed-inference-profiles.ts +4 -8
- package/src/context/post-turn-tool-result-truncation.ts +32 -18
- package/src/context/tool-result-spool.ts +104 -0
- package/src/credential-execution/feature-gates.ts +0 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +41 -16
- package/src/daemon/conversation-error.ts +6 -15
- package/src/daemon/conversation.ts +9 -0
- package/src/daemon/disk-pressure-policy.ts +0 -1
- package/src/daemon/lifecycle.ts +1 -20
- package/src/daemon/message-types/conversations.ts +2 -15
- package/src/daemon/trust-context.ts +1 -1
- package/src/events/tool-audit-listener.ts +40 -9
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -1
- package/src/home/__tests__/home-content-refresh.test.ts +114 -0
- package/src/home/__tests__/suggested-prompts.test.ts +86 -5
- package/src/home/home-content-refresh.ts +43 -31
- package/src/home/home-greeting-cache.ts +8 -1
- package/src/home/home-greeting.ts +13 -9
- package/src/home/suggested-prompts.ts +77 -24
- package/src/ipc/routes/trust-rules.test.ts +66 -72
- package/src/media/image-credentials.ts +2 -2
- package/src/memory/__tests__/compaction-log-store-clickhouse.test.ts +432 -0
- package/src/memory/{compaction-log-writer-clickhouse.ts → compaction-log-store-clickhouse.ts} +264 -55
- package/src/memory/conversation-attention-store.ts +1 -0
- package/src/memory/conversation-bootstrap.ts +18 -9
- package/src/memory/conversation-crud.ts +12 -2
- package/src/memory/conversation-title-service.ts +53 -9
- package/src/memory/delivery-channels.ts +0 -69
- package/src/memory/graph/extraction-job.ts +0 -15
- package/src/memory/guardian-action-store.ts +1 -376
- package/src/memory/llm-usage-store.ts +5 -1
- package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +2 -2
- package/src/memory/v2/__tests__/consolidation-job.test.ts +183 -2
- package/src/memory/v2/__tests__/injection.test.ts +70 -0
- package/src/memory/v2/__tests__/static-context.test.ts +12 -0
- package/src/memory/v2/consolidation-job.ts +93 -9
- package/src/memory/v2/injection.ts +53 -0
- package/src/memory/v2/prompts/consolidation.ts +1 -0
- package/src/memory/v2/static-context.ts +13 -1
- package/src/memory/v2/sweep-job.ts +1 -1
- package/src/memory/v2/types.ts +5 -0
- package/src/plugin-api/types.ts +7 -0
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +300 -0
- package/src/plugins/defaults/exploration-drift/package.json +15 -0
- package/src/plugins/defaults/index.ts +25 -0
- package/src/plugins/defaults/memory-retrieval/injectors.ts +132 -4
- package/src/plugins/defaults/memory-v3-shadow/__tests__/card.test.ts +92 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +2 -1
- package/src/plugins/defaults/memory-v3-shadow/__tests__/fresh-set.test.ts +52 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/live-integration.test.ts +2 -1
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +136 -5
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +17 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +6 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +5 -1
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +68 -4
- package/src/plugins/defaults/memory-v3-shadow/card.ts +49 -5
- package/src/plugins/defaults/memory-v3-shadow/fresh-set.ts +59 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +4 -2
- package/src/plugins/defaults/memory-v3-shadow/learned-edges.test.ts +169 -0
- package/src/plugins/defaults/memory-v3-shadow/learned-edges.ts +178 -0
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +115 -26
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +13 -9
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +144 -22
- package/src/plugins/defaults/memory-v3-shadow/types.ts +24 -6
- package/src/plugins/defaults/title-generate/hooks/stop.ts +13 -0
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +16 -0
- package/src/prompts/cache-boundary.ts +17 -0
- package/src/prompts/sections.ts +50 -17
- package/src/prompts/system-prompt.ts +12 -4
- package/src/prompts/templates/system-sections.ts +22 -0
- package/src/providers/__tests__/unparseable-tool-args.test.ts +53 -0
- package/src/providers/anthropic/client.ts +74 -28
- package/src/providers/gemini/client.ts +5 -1
- package/src/providers/minimax/client.ts +9 -0
- package/src/providers/model-catalog.ts +28 -0
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/chat-completions-provider.ts +4 -2
- package/src/providers/openai/responses-provider.ts +7 -2
- package/src/providers/retry.ts +8 -0
- package/src/providers/types.ts +11 -0
- package/src/providers/unparseable-tool-args.ts +56 -0
- package/src/runtime/AGENTS.md +6 -0
- package/src/runtime/__tests__/agent-wake.test.ts +2 -2
- package/src/runtime/agent-wake.ts +5 -5
- package/src/runtime/background-job-runner.ts +2 -2
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +150 -3
- package/src/runtime/migrations/vbundle-import-analyzer.ts +29 -6
- package/src/runtime/migrations/vbundle-import-policy.ts +23 -0
- package/src/runtime/migrations/vbundle-importer.ts +9 -4
- package/src/runtime/migrations/vbundle-streaming-importer.ts +8 -3
- package/src/runtime/pre-first-message-gate.ts +1 -1
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +241 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +132 -0
- package/src/runtime/routes/__tests__/gateway-log-routes.test.ts +97 -185
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +17 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +348 -0
- package/src/runtime/routes/__tests__/task-routes.test.ts +3 -3
- package/src/runtime/routes/btw-routes.ts +0 -14
- package/src/runtime/routes/conversation-compaction-routes.ts +86 -19
- package/src/runtime/routes/conversation-list-routes.ts +77 -5
- package/src/runtime/routes/conversation-management-routes.ts +54 -0
- package/src/runtime/routes/conversation-query-routes.ts +79 -4
- package/src/runtime/routes/gateway-log-routes.ts +14 -64
- package/src/runtime/routes/home-feed-routes.ts +10 -0
- package/src/runtime/routes/identity-intro-cache.ts +1 -1
- package/src/runtime/routes/identity-routes.ts +76 -20
- package/src/runtime/routes/inbound-message-handler.ts +0 -36
- package/src/runtime/routes/log-export-routes.ts +143 -96
- package/src/runtime/routes/plugins-routes.ts +380 -0
- package/src/runtime/routes/redact-staged-export.ts +259 -0
- package/src/runtime/routes/schedule-routes.ts +19 -2
- package/src/runtime/routes/trust-rules-routes.ts +14 -67
- package/src/schedule/recurrence-engine.ts +34 -0
- package/src/schedule/scheduler.ts +1 -0
- package/src/security/redact-json.ts +61 -0
- package/src/skills/validate-input.ts +41 -1
- package/src/subagent/types.ts +26 -1
- package/src/telemetry/types.ts +15 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +6 -1
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/apps/executors.ts +1 -1
- package/src/tools/skills/skill-tool-factory.ts +19 -8
- package/src/tools/tool-approval-handler.ts +31 -0
- package/src/usage/types.ts +8 -1
- package/src/util/platform.ts +16 -0
- package/src/watcher/engine.ts +1 -0
- package/src/workspace/adaptive-thinking-repair.ts +113 -0
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +70 -67
- package/src/workspace/migrations/098-remove-stale-updates-bulletin-file.ts +31 -0
- package/src/workspace/migrations/099-disable-cache-one-shot-callsites.ts +81 -0
- package/src/workspace/migrations/100-upgrade-quality-profile-to-fable-5.ts +86 -0
- package/src/workspace/migrations/101-upgrade-balanced-economy-to-minimax-m3.ts +70 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +0 -202
- package/src/__tests__/conversation-starters-cadence.test.ts +0 -161
- package/src/__tests__/guardian-action-followup-executor.test.ts +0 -322
- package/src/__tests__/guardian-action-followup-store.test.ts +0 -373
- package/src/__tests__/guardian-action-late-reply.test.ts +0 -1083
- package/src/__tests__/update-bulletin-job.test.ts +0 -292
- package/src/config/schemas/updates.ts +0 -14
- package/src/memory/__tests__/compaction-log-writer-clickhouse.test.ts +0 -227
- package/src/memory/conversation-starters-cadence.ts +0 -78
- package/src/prompts/update-bulletin-job.ts +0 -180
- package/src/runtime/guardian-action-followup-executor.ts +0 -306
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
type FetchLike,
|
|
34
34
|
sanitizePluginName,
|
|
35
35
|
} from "./install-from-github.js";
|
|
36
|
+
import { parsePluginArtifact, type PluginArtifact } from "./plugin-artifact.js";
|
|
36
37
|
import {
|
|
37
38
|
fetchMarketplaceEntries,
|
|
38
39
|
type MarketplaceEntry,
|
|
@@ -56,6 +57,7 @@ interface PluginManifestFields {
|
|
|
56
57
|
readonly description: string | null;
|
|
57
58
|
readonly homepage: string | null;
|
|
58
59
|
readonly license: string | null;
|
|
60
|
+
readonly artifact: PluginArtifact | null;
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
/** Options that control which plugin to resolve and at what ref. */
|
|
@@ -97,6 +99,13 @@ export interface PluginDetails {
|
|
|
97
99
|
readonly readme: string | null;
|
|
98
100
|
/** Git ref the catalog metadata / README were resolved at. */
|
|
99
101
|
readonly ref: string;
|
|
102
|
+
/**
|
|
103
|
+
* Prebuilt client artifact (download URL + sha256) declared in the
|
|
104
|
+
* plugin's `package.json` `vellum.artifact`, resolved from the installed
|
|
105
|
+
* copy first then the repo; `null` when the plugin ships none or its
|
|
106
|
+
* descriptor is incomplete (e.g. a placeholder `sha256`).
|
|
107
|
+
*/
|
|
108
|
+
readonly artifact: PluginArtifact | null;
|
|
100
109
|
}
|
|
101
110
|
|
|
102
111
|
/** No installed copy and no catalog/source entry claims the name. */
|
|
@@ -175,6 +184,7 @@ export async function getPluginDetails(
|
|
|
175
184
|
source,
|
|
176
185
|
readme,
|
|
177
186
|
ref,
|
|
187
|
+
artifact: local.manifest.artifact ?? remote.manifest.artifact,
|
|
178
188
|
};
|
|
179
189
|
}
|
|
180
190
|
|
|
@@ -342,7 +352,13 @@ function githubFetch(
|
|
|
342
352
|
}
|
|
343
353
|
|
|
344
354
|
function emptyManifest(): PluginManifestFields {
|
|
345
|
-
return {
|
|
355
|
+
return {
|
|
356
|
+
version: null,
|
|
357
|
+
description: null,
|
|
358
|
+
homepage: null,
|
|
359
|
+
license: null,
|
|
360
|
+
artifact: null,
|
|
361
|
+
};
|
|
346
362
|
}
|
|
347
363
|
|
|
348
364
|
function safeParseManifest(raw: string): PluginManifestFields {
|
|
@@ -365,6 +381,7 @@ function parseManifest(raw: string): PluginManifestFields {
|
|
|
365
381
|
description: typeof meta.description === "string" ? meta.description : null,
|
|
366
382
|
homepage: typeof meta.homepage === "string" ? meta.homepage : null,
|
|
367
383
|
license: normalizeLicense(meta.license),
|
|
384
|
+
artifact: parsePluginArtifact(parsed),
|
|
368
385
|
};
|
|
369
386
|
}
|
|
370
387
|
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content fingerprint of an installed plugin tree, used to detect local
|
|
3
|
+
* modifications after install.
|
|
4
|
+
*
|
|
5
|
+
* A plugin install is a flattened snapshot of a commit — the `.git` metadata is
|
|
6
|
+
* stripped during materialization (see {@link ./install-from-github}), so there
|
|
7
|
+
* is no working tree to ask `git status`. To tell whether a user has edited an
|
|
8
|
+
* installed copy, install records a per-file digest of the materialized tree in
|
|
9
|
+
* the provenance sidecar; later a recompute over the on-disk copy is compared
|
|
10
|
+
* against that baseline.
|
|
11
|
+
*
|
|
12
|
+
* The fingerprint is a one-way digest map — it answers "did this change?" and
|
|
13
|
+
* "which files?", but cannot reconstruct the original bytes. Producing an
|
|
14
|
+
* actual diff or a 3-way merge instead re-derives the baseline from the
|
|
15
|
+
* recorded immutable commit SHA (a separate concern from this module).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { createHash } from "node:crypto";
|
|
19
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
20
|
+
import { join } from "node:path";
|
|
21
|
+
|
|
22
|
+
/** Digest algorithm recorded alongside the file map, for forward compatibility. */
|
|
23
|
+
export type FingerprintAlgorithm = "sha256";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Per-file content digest of a plugin tree. Keys are POSIX-style
|
|
27
|
+
* (forward-slash) paths relative to the plugin root so the baseline is stable
|
|
28
|
+
* across platforms; values are lowercase hex digests of each file's bytes.
|
|
29
|
+
*/
|
|
30
|
+
export interface Fingerprint {
|
|
31
|
+
readonly algorithm: FingerprintAlgorithm;
|
|
32
|
+
readonly files: Readonly<Record<string, string>>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Difference between a recorded fingerprint and the current on-disk tree.
|
|
37
|
+
* Paths are POSIX-relative, matching {@link Fingerprint.files}. A rename
|
|
38
|
+
* surfaces as one `removed` plus one `added` entry.
|
|
39
|
+
*/
|
|
40
|
+
export interface FingerprintComparison {
|
|
41
|
+
/** Present in both, but the content digest differs. */
|
|
42
|
+
readonly modified: readonly string[];
|
|
43
|
+
/** Present on disk, absent from the recorded baseline. */
|
|
44
|
+
readonly added: readonly string[];
|
|
45
|
+
/** Recorded in the baseline, absent on disk. */
|
|
46
|
+
readonly removed: readonly string[];
|
|
47
|
+
/** True when the on-disk tree exactly matches the recorded baseline. */
|
|
48
|
+
readonly clean: boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function hashFile(absPath: string): string {
|
|
52
|
+
return createHash("sha256").update(readFileSync(absPath)).digest("hex");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Walk `root` and return a content digest for every regular file, keyed by its
|
|
57
|
+
* POSIX-relative path. Symlinks are skipped (the loader does not follow them,
|
|
58
|
+
* and install never materializes them); top-level entries named in `exclude`
|
|
59
|
+
* are skipped so the provenance sidecar never fingerprints itself.
|
|
60
|
+
*/
|
|
61
|
+
export function computeFingerprint(
|
|
62
|
+
root: string,
|
|
63
|
+
exclude: readonly string[] = [],
|
|
64
|
+
): Fingerprint {
|
|
65
|
+
const excluded = new Set(exclude);
|
|
66
|
+
const files: Record<string, string> = {};
|
|
67
|
+
|
|
68
|
+
const walk = (relDir: string): void => {
|
|
69
|
+
const absDir = relDir ? join(root, relDir) : root;
|
|
70
|
+
for (const entry of readdirSync(absDir, { withFileTypes: true })) {
|
|
71
|
+
if (relDir === "" && excluded.has(entry.name)) continue;
|
|
72
|
+
// Only regular files contribute to the digest; symlinks are never part of
|
|
73
|
+
// a materialized install and a directory is descended into, not hashed.
|
|
74
|
+
if (entry.isSymbolicLink()) continue;
|
|
75
|
+
const rel = relDir ? `${relDir}/${entry.name}` : entry.name;
|
|
76
|
+
if (entry.isDirectory()) {
|
|
77
|
+
walk(rel);
|
|
78
|
+
} else if (entry.isFile()) {
|
|
79
|
+
files[rel] = hashFile(join(root, rel));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
walk("");
|
|
85
|
+
return { algorithm: "sha256", files };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Compare the current contents of `root` against a recorded fingerprint,
|
|
90
|
+
* applying the same `exclude` used to compute the baseline so the sidecar is
|
|
91
|
+
* not counted as an addition.
|
|
92
|
+
*/
|
|
93
|
+
export function compareFingerprint(
|
|
94
|
+
root: string,
|
|
95
|
+
baseline: Fingerprint,
|
|
96
|
+
exclude: readonly string[] = [],
|
|
97
|
+
): FingerprintComparison {
|
|
98
|
+
const current = computeFingerprint(root, exclude).files;
|
|
99
|
+
const modified: string[] = [];
|
|
100
|
+
const added: string[] = [];
|
|
101
|
+
const removed: string[] = [];
|
|
102
|
+
|
|
103
|
+
for (const [path, digest] of Object.entries(current)) {
|
|
104
|
+
const recorded = baseline.files[path];
|
|
105
|
+
if (recorded === undefined) added.push(path);
|
|
106
|
+
else if (recorded !== digest) modified.push(path);
|
|
107
|
+
}
|
|
108
|
+
for (const path of Object.keys(baseline.files)) {
|
|
109
|
+
if (current[path] === undefined) removed.push(path);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
modified.sort();
|
|
113
|
+
added.sort();
|
|
114
|
+
removed.sort();
|
|
115
|
+
return {
|
|
116
|
+
modified,
|
|
117
|
+
added,
|
|
118
|
+
removed,
|
|
119
|
+
clean: modified.length === 0 && added.length === 0 && removed.length === 0,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Parse a fingerprint from already-decoded JSON. Lenient by design — any shape
|
|
125
|
+
* problem yields `null` so an older or hand-edited sidecar simply reports "no
|
|
126
|
+
* recorded baseline" rather than throwing.
|
|
127
|
+
*/
|
|
128
|
+
export function parseFingerprint(value: unknown): Fingerprint | null {
|
|
129
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
const obj = value as Record<string, unknown>;
|
|
133
|
+
if (obj.algorithm !== "sha256") return null;
|
|
134
|
+
const rawFiles = obj.files;
|
|
135
|
+
if (
|
|
136
|
+
typeof rawFiles !== "object" ||
|
|
137
|
+
rawFiles === null ||
|
|
138
|
+
Array.isArray(rawFiles)
|
|
139
|
+
) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
const files: Record<string, string> = {};
|
|
143
|
+
for (const [path, digest] of Object.entries(rawFiles)) {
|
|
144
|
+
if (typeof digest !== "string") return null;
|
|
145
|
+
files[path] = digest;
|
|
146
|
+
}
|
|
147
|
+
return { algorithm: "sha256", files };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Aggregate SHA-256 digest over a tree's contents, returned as `v2:<hex>`.
|
|
152
|
+
*
|
|
153
|
+
* This is the same scheme skills record in their `install-meta.json`
|
|
154
|
+
* `contentHash` (see `src/skills/install-meta.ts`): files are visited in
|
|
155
|
+
* POSIX-relative path order and each contributes a length-prefixed path
|
|
156
|
+
* segment followed by its length-prefixed bytes, so neither path/content
|
|
157
|
+
* boundaries nor reordering can collide. The `v2:` prefix marks the hashing
|
|
158
|
+
* scheme so it can evolve without ambiguity. Unlike {@link Fingerprint}, this
|
|
159
|
+
* is a single whole-tree digest — useful as a compact integrity signal
|
|
160
|
+
* alongside the per-file map. Symlinks are skipped and top-level entries named
|
|
161
|
+
* in `exclude` (e.g. the sidecar itself) are omitted, matching
|
|
162
|
+
* {@link computeFingerprint}.
|
|
163
|
+
*/
|
|
164
|
+
export function computeContentHash(
|
|
165
|
+
root: string,
|
|
166
|
+
exclude: readonly string[] = [],
|
|
167
|
+
): string {
|
|
168
|
+
const excluded = new Set(exclude);
|
|
169
|
+
const entries: Array<{ rel: string; abs: string }> = [];
|
|
170
|
+
|
|
171
|
+
const walk = (relDir: string): void => {
|
|
172
|
+
const absDir = relDir ? join(root, relDir) : root;
|
|
173
|
+
for (const entry of readdirSync(absDir, { withFileTypes: true })) {
|
|
174
|
+
if (relDir === "" && excluded.has(entry.name)) continue;
|
|
175
|
+
if (entry.isSymbolicLink()) continue;
|
|
176
|
+
const rel = relDir ? `${relDir}/${entry.name}` : entry.name;
|
|
177
|
+
if (entry.isDirectory()) {
|
|
178
|
+
walk(rel);
|
|
179
|
+
} else if (entry.isFile()) {
|
|
180
|
+
entries.push({ rel, abs: join(root, rel) });
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
walk("");
|
|
185
|
+
entries.sort((a, b) => a.rel.localeCompare(b.rel));
|
|
186
|
+
|
|
187
|
+
const hash = createHash("sha256");
|
|
188
|
+
for (const { rel, abs } of entries) {
|
|
189
|
+
const pathBuf = Buffer.from(rel, "utf-8");
|
|
190
|
+
const content = readFileSync(abs);
|
|
191
|
+
hash.update(`${pathBuf.length}:`);
|
|
192
|
+
hash.update(pathBuf);
|
|
193
|
+
hash.update(`${content.length}:`);
|
|
194
|
+
hash.update(content);
|
|
195
|
+
}
|
|
196
|
+
return `v2:${hash.digest("hex")}`;
|
|
197
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upgrade a single installed plugin to the marketplace's current pin.
|
|
3
|
+
*
|
|
4
|
+
* The marketplace pins every plugin to a full, immutable commit SHA (see
|
|
5
|
+
* {@link ./plugin-marketplace}); an upgrade re-materializes the install at
|
|
6
|
+
* whatever SHA the catalog currently advertises. Drift is detected with the
|
|
7
|
+
* same exact commit-SHA comparison {@link ./inspect-plugin} uses, so an
|
|
8
|
+
* upgrade is a no-op when the installed copy already matches the pin.
|
|
9
|
+
*
|
|
10
|
+
* This is deliberately a distinct operation from install: `install` is
|
|
11
|
+
* first-time materialization (and errors on an existing install unless
|
|
12
|
+
* `--force` is passed), whereas `upgrade` moves an existing install forward.
|
|
13
|
+
* Mechanically the move is a forced re-install at the current pin, which the
|
|
14
|
+
* underlying {@link ./install-from-github.installPlugin} performs atomically —
|
|
15
|
+
* the previously installed copy is preserved until the fetch succeeds.
|
|
16
|
+
*
|
|
17
|
+
* Conflict resolution for locally-modified plugins is intentionally out of
|
|
18
|
+
* scope here: this overwrites the install with the pinned tree. A future
|
|
19
|
+
* iteration will detect local edits (installed SHA = merge base) and resolve
|
|
20
|
+
* them before the swap.
|
|
21
|
+
*
|
|
22
|
+
* Designed for direct programmatic use with injected dependencies, mirroring
|
|
23
|
+
* the sibling plugin libraries. The CLI command `assistant plugins upgrade
|
|
24
|
+
* <name>` is a thin wrapper that supplies production deps and formats the
|
|
25
|
+
* result.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { join } from "node:path";
|
|
29
|
+
|
|
30
|
+
import { getWorkspacePluginsDir } from "../../util/platform.js";
|
|
31
|
+
import {
|
|
32
|
+
inspectPlugin,
|
|
33
|
+
type PluginInspection,
|
|
34
|
+
PluginInspectNotFoundError,
|
|
35
|
+
} from "./inspect-plugin.js";
|
|
36
|
+
import {
|
|
37
|
+
type FetchLike,
|
|
38
|
+
type GitRunner,
|
|
39
|
+
installPlugin,
|
|
40
|
+
PluginSourceUnavailableError,
|
|
41
|
+
type PostinstallRunner,
|
|
42
|
+
sanitizePluginName,
|
|
43
|
+
} from "./install-from-github.js";
|
|
44
|
+
import { PluginNotInstalledError } from "./uninstall-plugin.js";
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Outcome of an upgrade attempt.
|
|
48
|
+
*
|
|
49
|
+
* - `upgraded` — the install was moved to the current marketplace pin.
|
|
50
|
+
* - `already-up-to-date` — the installed commit already equals the pin; no-op.
|
|
51
|
+
* - `would-upgrade` — a `--dry-run` that found drift but made no changes.
|
|
52
|
+
*/
|
|
53
|
+
export type PluginUpgradeOutcome =
|
|
54
|
+
| "upgraded"
|
|
55
|
+
| "already-up-to-date"
|
|
56
|
+
| "would-upgrade";
|
|
57
|
+
|
|
58
|
+
/** Options that control which plugin to upgrade and how. */
|
|
59
|
+
export interface UpgradePluginOptions {
|
|
60
|
+
/** Install name (kebab-case directory name). */
|
|
61
|
+
readonly name: string;
|
|
62
|
+
/** Report what would change without modifying the install. */
|
|
63
|
+
readonly dryRun?: boolean;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Dependencies injected by the caller. */
|
|
67
|
+
export interface UpgradePluginDeps {
|
|
68
|
+
/** HTTP client. Production callers pass `globalThis.fetch.bind(globalThis)`. */
|
|
69
|
+
readonly fetch: FetchLike;
|
|
70
|
+
/** Override the workspace plugins directory. Falls back to the live workspace. */
|
|
71
|
+
readonly workspacePluginsDir?: string;
|
|
72
|
+
/** Override the git runner used to clone the source. Forwarded to {@link installPlugin}. */
|
|
73
|
+
readonly runGit?: GitRunner;
|
|
74
|
+
/** Override the postinstall adapter runner. Forwarded to {@link installPlugin}. */
|
|
75
|
+
readonly runPostinstall?: PostinstallRunner;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Result of an upgrade attempt. */
|
|
79
|
+
export interface PluginUpgradeResult {
|
|
80
|
+
readonly name: string;
|
|
81
|
+
readonly outcome: PluginUpgradeOutcome;
|
|
82
|
+
/** Installed commit before the upgrade; `null` when no provenance was recorded. */
|
|
83
|
+
readonly fromCommit: string | null;
|
|
84
|
+
/** Marketplace-pinned commit the install was (or would be) moved to. */
|
|
85
|
+
readonly toCommit: string;
|
|
86
|
+
/** Absolute path to the installed plugin directory. */
|
|
87
|
+
readonly target: string;
|
|
88
|
+
/** Files materialized by the upgrade; `null` for a no-op or dry run. */
|
|
89
|
+
readonly fileCount: number | null;
|
|
90
|
+
/** Whether this was a dry run (no changes made). */
|
|
91
|
+
readonly dryRun: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Whether the installed copy lacked resolvable provenance before the
|
|
94
|
+
* upgrade. Such installs are re-pinned to the current SHA, which also
|
|
95
|
+
* records provenance going forward.
|
|
96
|
+
*/
|
|
97
|
+
readonly provenanceWasUnknown: boolean;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** An installed plugin has no marketplace pin to upgrade to. */
|
|
101
|
+
export class PluginNotUpgradableError extends Error {
|
|
102
|
+
constructor(
|
|
103
|
+
readonly pluginName: string,
|
|
104
|
+
reason: string,
|
|
105
|
+
) {
|
|
106
|
+
super(`Plugin "${pluginName}" cannot be upgraded: ${reason}.`);
|
|
107
|
+
this.name = "PluginNotUpgradableError";
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function pluginTarget(name: string, deps: UpgradePluginDeps): string {
|
|
112
|
+
const dir = deps.workspacePluginsDir ?? getWorkspacePluginsDir();
|
|
113
|
+
return join(dir, name);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Move an installed plugin to the marketplace's current pin.
|
|
118
|
+
*
|
|
119
|
+
* Throws {@link PluginNotInstalledError} when no copy is installed,
|
|
120
|
+
* {@link PluginNotUpgradableError} when the install has no marketplace entry to
|
|
121
|
+
* advance to, {@link PluginSourceUnavailableError} when the marketplace catalog
|
|
122
|
+
* is temporarily unreachable (a retryable outage, distinct from the permanent
|
|
123
|
+
* no-entry case), and propagates {@link installPlugin}'s errors (e.g. source
|
|
124
|
+
* unavailable, postinstall failure) when the re-install itself fails.
|
|
125
|
+
*/
|
|
126
|
+
export async function upgradePlugin(
|
|
127
|
+
opts: UpgradePluginOptions,
|
|
128
|
+
deps: UpgradePluginDeps,
|
|
129
|
+
): Promise<PluginUpgradeResult> {
|
|
130
|
+
const name = sanitizePluginName(opts.name);
|
|
131
|
+
const dryRun = opts.dryRun ?? false;
|
|
132
|
+
|
|
133
|
+
let inspection: PluginInspection;
|
|
134
|
+
try {
|
|
135
|
+
inspection = await inspectPlugin(
|
|
136
|
+
{ name },
|
|
137
|
+
{ fetch: deps.fetch, workspacePluginsDir: deps.workspacePluginsDir },
|
|
138
|
+
);
|
|
139
|
+
} catch (err) {
|
|
140
|
+
if (err instanceof PluginInspectNotFoundError) {
|
|
141
|
+
throw new PluginNotInstalledError(name, pluginTarget(name, deps));
|
|
142
|
+
}
|
|
143
|
+
throw err;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
switch (inspection.status) {
|
|
147
|
+
case "not-installed":
|
|
148
|
+
throw new PluginNotInstalledError(name, pluginTarget(name, deps));
|
|
149
|
+
case "not-in-marketplace":
|
|
150
|
+
throw new PluginNotUpgradableError(
|
|
151
|
+
name,
|
|
152
|
+
"it has no marketplace entry to upgrade from",
|
|
153
|
+
);
|
|
154
|
+
case "remote-unavailable":
|
|
155
|
+
// A transient catalog outage is not a permanent "cannot upgrade" state:
|
|
156
|
+
// the same request can succeed once the marketplace source recovers, so
|
|
157
|
+
// surface it as a retryable source-unavailable error rather than a
|
|
158
|
+
// conflict.
|
|
159
|
+
throw new PluginSourceUnavailableError(
|
|
160
|
+
`Plugin "${name}" cannot be upgraded: the marketplace could not be reached (${inspection.remoteError ?? "unknown error"}).`,
|
|
161
|
+
503,
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// The remaining statuses (up-to-date, update-available, unknown-provenance)
|
|
166
|
+
// all imply an installed copy and a resolvable marketplace pin.
|
|
167
|
+
const { local, remote } = inspection;
|
|
168
|
+
if (!local || !remote) {
|
|
169
|
+
throw new PluginNotUpgradableError(
|
|
170
|
+
name,
|
|
171
|
+
"its install or marketplace metadata could not be resolved",
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const fromCommit = local.commit;
|
|
176
|
+
const toCommit = remote.commit;
|
|
177
|
+
const provenanceWasUnknown = inspection.status === "unknown-provenance";
|
|
178
|
+
|
|
179
|
+
if (inspection.status === "up-to-date") {
|
|
180
|
+
return {
|
|
181
|
+
name,
|
|
182
|
+
outcome: "already-up-to-date",
|
|
183
|
+
fromCommit,
|
|
184
|
+
toCommit,
|
|
185
|
+
target: local.target,
|
|
186
|
+
fileCount: null,
|
|
187
|
+
dryRun,
|
|
188
|
+
provenanceWasUnknown: false,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (dryRun) {
|
|
193
|
+
return {
|
|
194
|
+
name,
|
|
195
|
+
outcome: "would-upgrade",
|
|
196
|
+
fromCommit,
|
|
197
|
+
toCommit,
|
|
198
|
+
target: local.target,
|
|
199
|
+
fileCount: null,
|
|
200
|
+
dryRun: true,
|
|
201
|
+
provenanceWasUnknown,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const result = await installPlugin(
|
|
206
|
+
{ name, force: true },
|
|
207
|
+
{
|
|
208
|
+
fetch: deps.fetch,
|
|
209
|
+
workspacePluginsDir: deps.workspacePluginsDir,
|
|
210
|
+
runGit: deps.runGit,
|
|
211
|
+
runPostinstall: deps.runPostinstall,
|
|
212
|
+
},
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
name,
|
|
217
|
+
outcome: "upgraded",
|
|
218
|
+
fromCommit,
|
|
219
|
+
toCommit: result.commit ?? toCommit,
|
|
220
|
+
target: result.target,
|
|
221
|
+
fileCount: result.fileCount,
|
|
222
|
+
dryRun: false,
|
|
223
|
+
provenanceWasUnknown,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
@@ -39,6 +39,7 @@ Each subagent is spawned with a role that determines its tool access. Choose the
|
|
|
39
39
|
| `researcher` | `web_search`, `web_fetch`, `file_read`, `file_list`, `recall`, `notify_parent` | Information gathering, web research, codebase exploration, reading documentation |
|
|
40
40
|
| `coder` | `bash`, `file_read`, `file_write`, `file_edit`, `web_search`, `recall`, `notify_parent` | Code changes, file editing, running commands, build/test tasks |
|
|
41
41
|
| `planner` | `file_read`, `file_list`, `web_search`, `web_fetch`, `recall`, `notify_parent` | Analysis, planning, synthesizing information, reviewing approaches |
|
|
42
|
+
| `investigator` | `bash`, `file_read`, `file_list`, `web_search`, `web_fetch`, `recall`, `notify_parent` | Root-cause analysis: debugging, log forensics, tracing behavior across many files. Shell access is for read-only investigation (grep/find/reading logs); returns a compact root-cause report |
|
|
42
43
|
|
|
43
44
|
All specialized roles (`researcher`, `coder`, `planner`) include `notify_parent` for mid-run communication with the parent.
|
|
44
45
|
|
|
@@ -97,5 +98,6 @@ Rule of thumb: "Does this task need to know what we've been talking about?" If y
|
|
|
97
98
|
- Use `subagent_message` to send follow-up instructions to a running subagent.
|
|
98
99
|
- Use `subagent_abort` to cancel a subagent that is no longer needed.
|
|
99
100
|
- Default to spawning subagents for any task that involves web research, multi-file exploration, or independent coding work. Serial execution should be the exception, not the rule.
|
|
101
|
+
- Delegate root-cause investigations ("why is X happening?", debugging, log forensics) to an `investigator` instead of grepping inline. A long investigation done inline floods your own context with file slices and grep output, crowding out the conversation; the investigator does the digging in its own context and returns a compact root-cause report.
|
|
100
102
|
- When a user request has both an information-gathering component and an action component, spawn a researcher immediately rather than doing the research inline yourself.
|
|
101
103
|
- Prefer spawning 2-3 focused subagents over one large general-purpose subagent. Smaller scopes finish faster and fail more gracefully.
|
|
@@ -31,8 +31,14 @@
|
|
|
31
31
|
},
|
|
32
32
|
"role": {
|
|
33
33
|
"type": "string",
|
|
34
|
-
"enum": [
|
|
35
|
-
|
|
34
|
+
"enum": [
|
|
35
|
+
"general",
|
|
36
|
+
"researcher",
|
|
37
|
+
"coder",
|
|
38
|
+
"planner",
|
|
39
|
+
"investigator"
|
|
40
|
+
],
|
|
41
|
+
"description": "Agent specialization that controls tool access. 'researcher': read-only (web, files, memory). 'coder': file and bash access. 'planner': read-only analysis. 'investigator': root-cause analysis — debugging, log forensics, tracing behavior across many files; has bash for read-only investigation (grep/find/log inspection) and returns a compact root-cause report. 'general': full access (default). Ignored when fork: true (forks always use general)."
|
|
36
42
|
}
|
|
37
43
|
},
|
|
38
44
|
"required": ["label", "objective"]
|
|
@@ -7,6 +7,13 @@ type CallSiteDefaultConfig = {
|
|
|
7
7
|
temperature?: number | null;
|
|
8
8
|
thinking?: { enabled?: boolean; streamThinking?: boolean };
|
|
9
9
|
contextWindow?: { maxInputTokens?: number };
|
|
10
|
+
/**
|
|
11
|
+
* Opt the call site out of prompt caching. Set for one-shot call sites
|
|
12
|
+
* whose prompts never repeat — or repeat slower than the cache TTL — so
|
|
13
|
+
* each call would pay the cache-write premium without a future read.
|
|
14
|
+
* Telemetry confirms ~0–5% cache hit rates on these sites.
|
|
15
|
+
*/
|
|
16
|
+
disableCache?: boolean;
|
|
10
17
|
};
|
|
11
18
|
|
|
12
19
|
export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
|
|
@@ -17,7 +24,7 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
|
|
|
17
24
|
patternScan: { profile: "balanced" },
|
|
18
25
|
narrativeRefinement: { profile: "balanced" },
|
|
19
26
|
callAgent: { profile: "balanced" },
|
|
20
|
-
memoryConsolidation: { profile: "balanced" },
|
|
27
|
+
memoryConsolidation: { profile: "balanced", disableCache: true },
|
|
21
28
|
identityIntro: { profile: "balanced" },
|
|
22
29
|
emptyStateGreeting: { profile: "balanced" },
|
|
23
30
|
|
|
@@ -32,6 +39,7 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
|
|
|
32
39
|
effort: "low",
|
|
33
40
|
thinking: { enabled: false, streamThinking: false },
|
|
34
41
|
temperature: 0,
|
|
42
|
+
disableCache: true,
|
|
35
43
|
},
|
|
36
44
|
conversationStarters: {
|
|
37
45
|
profile: "balanced",
|
|
@@ -47,7 +55,7 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
|
|
|
47
55
|
memoryV2Sweep: { profile: "cost-optimized" },
|
|
48
56
|
memoryV2Consolidation: { profile: "balanced" },
|
|
49
57
|
conversationSummarization: { profile: "cost-optimized" },
|
|
50
|
-
conversationTitle: { profile: "cost-optimized" },
|
|
58
|
+
conversationTitle: { profile: "cost-optimized", disableCache: true },
|
|
51
59
|
approvalCopy: { profile: "cost-optimized" },
|
|
52
60
|
approvalConversation: { profile: "cost-optimized" },
|
|
53
61
|
trustRuleSuggestion: { profile: "cost-optimized" },
|
|
@@ -70,6 +78,7 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
|
|
|
70
78
|
profile: "cost-optimized",
|
|
71
79
|
effort: "low",
|
|
72
80
|
thinking: { enabled: false },
|
|
81
|
+
disableCache: true,
|
|
73
82
|
},
|
|
74
83
|
guardianQuestionCopy: {
|
|
75
84
|
profile: "cost-optimized",
|
|
@@ -107,11 +116,13 @@ export const CALL_SITE_DEFAULTS: Record<LLMCallSite, CallSiteDefaultConfig> = {
|
|
|
107
116
|
effort: "low",
|
|
108
117
|
thinking: { enabled: false },
|
|
109
118
|
temperature: 0.7,
|
|
119
|
+
disableCache: true,
|
|
110
120
|
},
|
|
111
121
|
homeSuggestedPrompts: {
|
|
112
122
|
profile: "cost-optimized",
|
|
113
123
|
maxTokens: 512,
|
|
114
124
|
effort: "low",
|
|
115
125
|
thinking: { enabled: false },
|
|
126
|
+
disableCache: true,
|
|
116
127
|
},
|
|
117
128
|
};
|
|
@@ -75,14 +75,6 @@
|
|
|
75
75
|
"description": "Control Developer nav visibility in macOS settings",
|
|
76
76
|
"defaultEnabled": false
|
|
77
77
|
},
|
|
78
|
-
{
|
|
79
|
-
"id": "system-schedule-toggles",
|
|
80
|
-
"scope": "assistant",
|
|
81
|
-
"key": "system-schedule-toggles",
|
|
82
|
-
"label": "System Schedule Toggles",
|
|
83
|
-
"description": "Show the Heartbeat pause toggle on the schedules settings page. The toggle only pauses automatic runs; manual Run now remains available.",
|
|
84
|
-
"defaultEnabled": false
|
|
85
|
-
},
|
|
86
78
|
{
|
|
87
79
|
"id": "developer-menu-items",
|
|
88
80
|
"scope": "client",
|
|
@@ -363,6 +355,14 @@
|
|
|
363
355
|
"description": "Enable self-hosted assistant configuration.",
|
|
364
356
|
"defaultEnabled": false
|
|
365
357
|
},
|
|
358
|
+
{
|
|
359
|
+
"id": "web-remote-ingress",
|
|
360
|
+
"scope": "assistant",
|
|
361
|
+
"key": "web-remote-ingress",
|
|
362
|
+
"label": "Web Remote Ingress",
|
|
363
|
+
"description": "Serve the web client over a public tunnel and enable browser pairing for self-hosted assistants.",
|
|
364
|
+
"defaultEnabled": false
|
|
365
|
+
},
|
|
366
366
|
{
|
|
367
367
|
"id": "settings-sleep-policy",
|
|
368
368
|
"scope": "assistant",
|
|
@@ -403,14 +403,6 @@
|
|
|
403
403
|
"description": "When on, memory-v3 topic-tree retrieval becomes the live injected memory source (suppressing v2 injection). Off by default; only enable after shadow telemetry validates the design.",
|
|
404
404
|
"defaultEnabled": false
|
|
405
405
|
},
|
|
406
|
-
{
|
|
407
|
-
"id": "empty-state-dynamic-greetings",
|
|
408
|
-
"scope": "assistant",
|
|
409
|
-
"key": "empty-state-dynamic-greetings",
|
|
410
|
-
"label": "Dynamic Empty-State Greetings",
|
|
411
|
-
"description": "Enable the empty new-chat screen to refresh cached greeting options via the empty-state greeting LLM call site. When off, the assistant serves workspace-authored greetings or static fallbacks only.",
|
|
412
|
-
"defaultEnabled": false
|
|
413
|
-
},
|
|
414
406
|
{
|
|
415
407
|
"id": "self-intro-greeting",
|
|
416
408
|
"scope": "both",
|