@wrongstack/core 0.299.0 → 0.300.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/coordination/director.d.ts +8 -0
- package/dist/coordination/fleet-manager.d.ts +48 -3
- package/dist/coordination/ifleet-manager.d.ts +2 -0
- package/dist/coordination/index.js +120 -20
- package/dist/coordination/multi-agent-coordinator.d.ts +1 -0
- package/dist/core/fallback-model.d.ts +48 -0
- package/dist/core/index.d.ts +3 -2
- package/dist/core/index.js +226 -26
- package/dist/core/instruction-template.d.ts +80 -0
- package/dist/core/system-prompt-blocks.d.ts +10 -1
- package/dist/core/system-prompt-builder.d.ts +35 -1
- package/dist/defaults/index.js +238 -99
- package/dist/execution/autonomy-brain.d.ts +7 -0
- package/dist/execution/council-brain.d.ts +11 -0
- package/dist/execution/council-orchestrator.d.ts +23 -4
- package/dist/execution/council-prompts.d.ts +12 -1
- package/dist/execution/index.js +355 -138
- package/dist/fleet-notifier.d.ts +9 -2
- package/dist/hooks/index.js +8 -4
- package/dist/hq/index.js +18 -4
- package/dist/hq/protocol/fleet.d.ts +20 -0
- package/dist/hq/protocol.js +10 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1512 -707
- package/dist/kernel/events/brain-events.d.ts +9 -0
- package/dist/kernel/events/provider-events.d.ts +42 -1
- package/dist/models/index.js +1 -1
- package/dist/plugin/api.d.ts +6 -0
- package/dist/plugin/config.d.ts +55 -0
- package/dist/plugin/index.d.ts +1 -1
- package/dist/plugin/index.js +134 -21
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.js +157 -42
- package/dist/security/permission-helpers.d.ts +23 -6
- package/dist/security/permission-policy.d.ts +16 -0
- package/dist/security/totp.d.ts +14 -0
- package/dist/storage/director-state.d.ts +7 -0
- package/dist/storage/index.js +33 -8
- package/dist/tools/fallback-system-config-view-tool.d.ts +1 -1
- package/dist/tools/index.js +388 -102
- package/dist/types/council.d.ts +11 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/multi-agent.d.ts +10 -0
- package/dist/types/one-shot-llm.d.ts +9 -0
- package/dist/types/plugin.d.ts +28 -0
- package/dist/worktree/index.js +4 -4
- package/instructions/system-lite.md +81 -3
- package/instructions/system-pro.md +275 -90
- package/instructions/system.md +228 -81
- package/package.json +3 -3
|
@@ -264,6 +264,15 @@ export interface BrainEventMap {
|
|
|
264
264
|
completed: number;
|
|
265
265
|
/** Optional fleet-wide cost total (USD) — set by the host bridge when known. */
|
|
266
266
|
totalCostUsd?: number | undefined;
|
|
267
|
+
/** Concurrent-subagent ceiling (issue #323). */
|
|
268
|
+
maxConcurrent?: number | undefined;
|
|
269
|
+
/** Lifetime spawn budget snapshot (issue #323). */
|
|
270
|
+
maxSpawns?: number | undefined;
|
|
271
|
+
usedSpawns?: number | undefined;
|
|
272
|
+
remainingSpawns?: number | undefined;
|
|
273
|
+
effectiveSource?: string | undefined;
|
|
274
|
+
checkpointMaxSpawns?: number | undefined;
|
|
275
|
+
ceilingMismatch?: boolean | undefined;
|
|
267
276
|
subagentStatuses: {
|
|
268
277
|
subagentId: string;
|
|
269
278
|
taskId: string;
|
|
@@ -160,6 +160,8 @@ export interface ProviderEventMap {
|
|
|
160
160
|
};
|
|
161
161
|
status: number;
|
|
162
162
|
providerSwitched: boolean;
|
|
163
|
+
/** Gate correlation id — set when a fallback gate mediated the switch. */
|
|
164
|
+
requestId?: string | undefined;
|
|
163
165
|
contextWindowWarning?: {
|
|
164
166
|
fromMaxContext: number;
|
|
165
167
|
toMaxContext: number;
|
|
@@ -167,7 +169,33 @@ export interface ProviderEventMap {
|
|
|
167
169
|
} | undefined;
|
|
168
170
|
};
|
|
169
171
|
/**
|
|
170
|
-
* Fired
|
|
172
|
+
* Fired by the fallback gate function (supplied to the fallback-model
|
|
173
|
+
* extension via `FallbackModelDeps.fallbackGate`) when the chain is about
|
|
174
|
+
* to engage, BEFORE attempting any fallback entry. Carries the full
|
|
175
|
+
* candidate list so the UI can show a modal with a countdown and manual
|
|
176
|
+
* pick. The gate waits for a `provider.fallback_choice` event bus emission
|
|
177
|
+
* (or the countdown timer) before proceeding with the chosen model or
|
|
178
|
+
* auto-switching to the next candidate.
|
|
179
|
+
*/
|
|
180
|
+
'provider.fallback_pending': {
|
|
181
|
+
sessionId?: string | undefined;
|
|
182
|
+
from: {
|
|
183
|
+
providerId: string;
|
|
184
|
+
model: string;
|
|
185
|
+
};
|
|
186
|
+
status: number;
|
|
187
|
+
candidates: Array<{
|
|
188
|
+
providerId: string;
|
|
189
|
+
model: string;
|
|
190
|
+
}>;
|
|
191
|
+
/** Seconds the UI should count down before auto-switching to the next model. */
|
|
192
|
+
autoSwitchSeconds: number;
|
|
193
|
+
/** Unique request id — the UI echoes this back in the choice message. */
|
|
194
|
+
requestId: string;
|
|
195
|
+
timestamp: number;
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Fired when a (providerId, model) pair transitions between
|
|
171
199
|
* healthy/degraded/blocked states. The tracker emits this so the
|
|
172
200
|
* CLI/TUI/WebUI can render a live status indicator.
|
|
173
201
|
*/
|
|
@@ -180,6 +208,19 @@ export interface ProviderEventMap {
|
|
|
180
208
|
timestamp: number;
|
|
181
209
|
stateExpiresAt?: number | undefined;
|
|
182
210
|
};
|
|
211
|
+
/**
|
|
212
|
+
* Fired by the UI when the user manually picks a model from the
|
|
213
|
+
* fallback modal. The fallback gate listens for this event (matched
|
|
214
|
+
* by `requestId`) to resolve with the chosen model instead of waiting
|
|
215
|
+
* for the countdown.
|
|
216
|
+
*/
|
|
217
|
+
'provider.fallback_choice': {
|
|
218
|
+
requestId: string;
|
|
219
|
+
providerId?: string | undefined;
|
|
220
|
+
model?: string | undefined;
|
|
221
|
+
/** When true, auto-switch to the next candidate (countdown expired or Esc). */
|
|
222
|
+
autoSwitch?: boolean | undefined;
|
|
223
|
+
};
|
|
183
224
|
/**
|
|
184
225
|
* Fired when the agent's actively selected (primary, not fallback)
|
|
185
226
|
* provider/model is blocked and will be skipped. The CLI/TUI should
|
package/dist/models/index.js
CHANGED
|
@@ -584,7 +584,7 @@ var DefaultModelsRegistry = class {
|
|
|
584
584
|
async load(opts = {}) {
|
|
585
585
|
if (this.payload && !opts.force) return this.payload;
|
|
586
586
|
if (this.seed) {
|
|
587
|
-
this.payload = this.seed;
|
|
587
|
+
this.payload = this.withExtraOverlay(this.seed);
|
|
588
588
|
this.fetchedAt = /* @__PURE__ */ new Date();
|
|
589
589
|
return this.payload;
|
|
590
590
|
}
|
package/dist/plugin/api.d.ts
CHANGED
|
@@ -7,9 +7,11 @@ import type { ProviderRegistry } from '../registry/provider-registry.js';
|
|
|
7
7
|
import type { SlashCommandRegistry } from '../registry/slash-command-registry.js';
|
|
8
8
|
import type { ToolRegistry } from '../registry/tool-registry.js';
|
|
9
9
|
import type { Config } from '../types/config.js';
|
|
10
|
+
import type { CouncilQuestion, CouncilResult } from '../types/council.js';
|
|
10
11
|
import type { HookEvent, HookMatcher, InProcessHook } from '../types/hooks.js';
|
|
11
12
|
import type { Logger } from '../types/logger.js';
|
|
12
13
|
import type { ModelsRegistry } from '../types/models-registry.js';
|
|
14
|
+
import type { OneShotLLMInput, OneShotLLMResult } from '../types/one-shot-llm.js';
|
|
13
15
|
import type { MCPRegistryView, MetricsSinkView, Notifier, PluginAPI, PluginCapabilities, PluginDependency, PluginLLM, PluginPipelines, ProviderRegistryView, SessionWriterView, SlashCommandRegistryView, ToolRegistryView } from '../types/plugin.js';
|
|
14
16
|
import type { Provider } from '../types/provider.js';
|
|
15
17
|
import type { SystemPromptContributor } from '../types/system-prompt-contributor.js';
|
|
@@ -91,6 +93,10 @@ export interface PluginAPIInit {
|
|
|
91
93
|
getProvider?: (() => Provider) | undefined;
|
|
92
94
|
getModel?: (() => string) | undefined;
|
|
93
95
|
createProvider?: ((name: string, model?: string) => Provider) | undefined;
|
|
96
|
+
/** Preferred production path: shared One Shot runtime with fallbacks. */
|
|
97
|
+
oneShot?: ((input: OneShotLLMInput) => Promise<OneShotLLMResult>) | undefined;
|
|
98
|
+
/** Optional shared multi-model Council runtime. */
|
|
99
|
+
council?: ((question: CouncilQuestion) => Promise<CouncilResult>) | undefined;
|
|
94
100
|
} | undefined;
|
|
95
101
|
config: Config;
|
|
96
102
|
/**
|
package/dist/plugin/config.d.ts
CHANGED
|
@@ -28,6 +28,61 @@ export interface PluginConfigChange {
|
|
|
28
28
|
* beat aliases, making migrations deterministic regardless of object order.
|
|
29
29
|
*/
|
|
30
30
|
export declare function resolvePluginConfig(input: ResolvePluginConfigInput): ResolvedPluginConfig;
|
|
31
|
+
/**
|
|
32
|
+
* Default `config.plugins` name matcher: the canonical name, a declared
|
|
33
|
+
* alias, or the `@wrongstack/plugins/<name>` subpath spelling of either.
|
|
34
|
+
*
|
|
35
|
+
* Surfaces that know more pass their own `matches` — the loader has an alias
|
|
36
|
+
* table (`lsp` → `@wrongstack/plug-lsp`), the CLI folds `telegram` and
|
|
37
|
+
* `@wrongstack/telegram` into one row. This is the floor, not the ceiling.
|
|
38
|
+
*/
|
|
39
|
+
export declare function pluginEntryMatchesName(configuredName: string, name: string, aliases?: readonly string[]): boolean;
|
|
40
|
+
export type PluginEnablementSource = 'feature-flag' | 'plugin-entry' | 'extension' | 'default';
|
|
41
|
+
export interface ResolvedPluginEnablement {
|
|
42
|
+
enabled: boolean;
|
|
43
|
+
source: PluginEnablementSource;
|
|
44
|
+
}
|
|
45
|
+
export interface ResolvePluginEnablementInput {
|
|
46
|
+
name: string;
|
|
47
|
+
aliases?: readonly string[] | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* `'active'` — runs unless something turns it off.
|
|
50
|
+
* `'inactive'` — runs only when something explicitly turns it on.
|
|
51
|
+
* Omitted behaves like `'inactive'`.
|
|
52
|
+
*/
|
|
53
|
+
defaultState?: 'active' | 'inactive' | undefined;
|
|
54
|
+
config?: (Partial<Pick<Config, 'plugins' | 'extensions'>> & {
|
|
55
|
+
features?: Partial<Config['features']> | undefined;
|
|
56
|
+
}) | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Overrides how a `config.plugins` entry name is matched against this
|
|
59
|
+
* plugin. Surfaces normalize specs differently (the loader maps
|
|
60
|
+
* `@wrongstack/plugins/foo` → `foo`, the CLI treats `telegram` and
|
|
61
|
+
* `@wrongstack/telegram` as one row), so matching is per-surface —
|
|
62
|
+
* only the PRECEDENCE below is shared. Defaults to name/alias equality.
|
|
63
|
+
*/
|
|
64
|
+
matches?: ((configuredName: string) => boolean) | undefined;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Resolve whether a plugin boots, under ONE precedence shared by every
|
|
68
|
+
* surface that reports or acts on plugin state:
|
|
69
|
+
*
|
|
70
|
+
* 1. `features.plugins === false` — kills every plugin.
|
|
71
|
+
* 2. a matching `config.plugins` entry — `{ enabled: false }` is off,
|
|
72
|
+
* anything else is on. This is what `wstack plugin enable|disable`
|
|
73
|
+
* writes, so it stays the highest per-plugin authority.
|
|
74
|
+
* 3. `config.extensions[name].enabled`, when it is a boolean — the
|
|
75
|
+
* plugin's own master switch.
|
|
76
|
+
* 4. the catalog `defaultState`.
|
|
77
|
+
*
|
|
78
|
+
* Rule 3 used to be read only by the loader, and only in its `=== true`
|
|
79
|
+
* direction: a plugin switched on via `extensions` ran while every
|
|
80
|
+
* reporting surface — which looked at `config.plugins` alone — called it
|
|
81
|
+
* disabled, and `extensions[name].enabled = false` turned nothing off.
|
|
82
|
+
* Both directions now resolve here, so "what runs" and "what the report
|
|
83
|
+
* says" cannot drift apart again.
|
|
84
|
+
*/
|
|
85
|
+
export declare function resolvePluginEnablement(input: ResolvePluginEnablementInput): ResolvedPluginEnablement;
|
|
31
86
|
export declare function resolvePluginManifestConfig(plugin: Pick<Plugin, 'name' | 'configAliases' | 'defaultConfig'>, config?: ResolvePluginConfigInput['config'], explicitOptions?: Readonly<Record<string, unknown>>): ResolvedPluginConfig;
|
|
32
87
|
/** Unknown fields are immutable by default so a new option cannot silently hot-reload. */
|
|
33
88
|
export declare function diffPluginConfig(previous: Readonly<Record<string, unknown>>, next: Readonly<Record<string, unknown>>, fields: Readonly<Record<string, PluginConfigFieldMetadata>>): PluginConfigChange[];
|
package/dist/plugin/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { DefaultPluginAPI, definePlugin, type PluginAPIInit } from './api.js';
|
|
2
|
-
export { diffPluginConfig, type PluginConfigChange, type PluginConfigSource, type ResolvePluginConfigInput, type ResolvedPluginConfig, redactPluginConfig, resolvePluginConfig, resolvePluginManifestConfig, validatePluginConfigMetadata, } from './config.js';
|
|
2
|
+
export { diffPluginConfig, type PluginConfigChange, type PluginConfigSource, type PluginEnablementSource, pluginEntryMatchesName, type ResolvePluginConfigInput, type ResolvePluginEnablementInput, type ResolvedPluginConfig, type ResolvedPluginEnablement, redactPluginConfig, resolvePluginConfig, resolvePluginEnablement, resolvePluginManifestConfig, validatePluginConfigMetadata, } from './config.js';
|
|
3
3
|
export { KERNEL_API_VERSION, loadPlugins, type LoadPluginsOptions, type PluginHostHandle, type PluginLoadFailure, unloadPlugins, } from './loader.js';
|
|
4
4
|
export type { PluginAPI } from '../types/plugin.js';
|
|
5
5
|
export { buildReviewerModelPool, createAutoReviewPlugin, parseReviewSeverity, type ReviewerModelAssignment, selectRoundRobinReviewerAssignment, } from '../plugins/auto-review-plugin.js';
|
package/dist/plugin/index.js
CHANGED
|
@@ -1275,6 +1275,36 @@ function resolvePluginConfig(input) {
|
|
|
1275
1275
|
merge(input.explicitOptions, "explicit-options");
|
|
1276
1276
|
return { options, configured, sources };
|
|
1277
1277
|
}
|
|
1278
|
+
function pluginEntryMatchesName(configuredName, name, aliases = []) {
|
|
1279
|
+
for (const candidate of [name, ...aliases]) {
|
|
1280
|
+
if (configuredName === candidate) return true;
|
|
1281
|
+
if (configuredName === `@wrongstack/plugins/${candidate}`) return true;
|
|
1282
|
+
}
|
|
1283
|
+
return false;
|
|
1284
|
+
}
|
|
1285
|
+
function resolvePluginEnablement(input) {
|
|
1286
|
+
if (input.config?.features?.plugins === false) {
|
|
1287
|
+
return { enabled: false, source: "feature-flag" };
|
|
1288
|
+
}
|
|
1289
|
+
const names = [.../* @__PURE__ */ new Set([input.name, ...input.aliases ?? []])];
|
|
1290
|
+
const matches2 = input.matches ?? ((configuredName) => pluginEntryMatchesName(configuredName, input.name, input.aliases ?? []));
|
|
1291
|
+
const plugins = input.config?.plugins;
|
|
1292
|
+
if (Array.isArray(plugins)) {
|
|
1293
|
+
for (const candidate of plugins) {
|
|
1294
|
+
if (typeof candidate === "string") {
|
|
1295
|
+
if (matches2(candidate)) return { enabled: true, source: "plugin-entry" };
|
|
1296
|
+
continue;
|
|
1297
|
+
}
|
|
1298
|
+
if (!isPluginEntry(candidate) || !matches2(candidate.name)) continue;
|
|
1299
|
+
return { enabled: candidate.enabled !== false, source: "plugin-entry" };
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
for (const name of names) {
|
|
1303
|
+
const enabled = input.config?.extensions?.[name]?.["enabled"];
|
|
1304
|
+
if (typeof enabled === "boolean") return { enabled, source: "extension" };
|
|
1305
|
+
}
|
|
1306
|
+
return { enabled: input.defaultState === "active", source: "default" };
|
|
1307
|
+
}
|
|
1278
1308
|
function resolvePluginManifestConfig(plugin, config, explicitOptions) {
|
|
1279
1309
|
return resolvePluginConfig({
|
|
1280
1310
|
name: plugin.name,
|
|
@@ -1740,11 +1770,12 @@ function wrapApiForCapabilityCheck(plugin, api, log, enforce = false) {
|
|
|
1740
1770
|
});
|
|
1741
1771
|
const wrappedLlm = caps.llm !== false || !api.llm ? api.llm : new Proxy(api.llm, {
|
|
1742
1772
|
get(target, prop, receiver) {
|
|
1743
|
-
if (prop === "complete") {
|
|
1773
|
+
if (prop === "complete" || prop === "council") {
|
|
1744
1774
|
return (prompt, options) => {
|
|
1745
|
-
violate("llm",
|
|
1746
|
-
const
|
|
1747
|
-
|
|
1775
|
+
violate("llm", `${String(prop)}(${prompt.length} chars)`);
|
|
1776
|
+
const method = target[prop];
|
|
1777
|
+
if (!method) return void 0;
|
|
1778
|
+
return options === void 0 ? method.call(target, prompt) : method.call(target, prompt, options);
|
|
1748
1779
|
};
|
|
1749
1780
|
}
|
|
1750
1781
|
return Reflect.get(target, prop, receiver);
|
|
@@ -1973,6 +2004,8 @@ function makePluginLLM(owner, hostLLM, providerRegistry, config, getLiveConfig,
|
|
|
1973
2004
|
const currentModel = () => hostLLM.getModel?.() ?? hostLLM.model;
|
|
1974
2005
|
const DEFAULT_MAX_TOKENS = 2048;
|
|
1975
2006
|
const HARD_MAX_TOKENS = 32768;
|
|
2007
|
+
const DEFAULT_TIMEOUT_MS = 3e4;
|
|
2008
|
+
const HARD_TIMEOUT_MS = 12e4;
|
|
1976
2009
|
const pluginDefaults = () => {
|
|
1977
2010
|
const extensions = currentConfig().extensions;
|
|
1978
2011
|
const raw = extensions?.[owner]?.["llm"];
|
|
@@ -1982,7 +2015,11 @@ function makePluginLLM(owner, hostLLM, providerRegistry, config, getLiveConfig,
|
|
|
1982
2015
|
...typeof r["provider"] === "string" && r["provider"] ? { provider: r["provider"] } : {},
|
|
1983
2016
|
...typeof r["model"] === "string" && r["model"] ? { model: r["model"] } : {},
|
|
1984
2017
|
...typeof r["maxTokens"] === "number" ? { maxTokens: r["maxTokens"] } : {},
|
|
1985
|
-
...typeof r["temperature"] === "number" ? { temperature: r["temperature"] } : {}
|
|
2018
|
+
...typeof r["temperature"] === "number" ? { temperature: r["temperature"] } : {},
|
|
2019
|
+
...typeof r["role"] === "string" && r["role"] ? { role: r["role"] } : {},
|
|
2020
|
+
...Array.isArray(r["fallbackModels"]) && r["fallbackModels"].every((v) => typeof v === "string") ? { fallbackModels: [...r["fallbackModels"]] } : {},
|
|
2021
|
+
...typeof r["timeoutMs"] === "number" ? { timeoutMs: r["timeoutMs"] } : {},
|
|
2022
|
+
...typeof r["councilProfile"] === "string" && r["councilProfile"] ? { councilProfile: r["councilProfile"] } : {}
|
|
1986
2023
|
};
|
|
1987
2024
|
};
|
|
1988
2025
|
const resolveProvider = (name, model) => {
|
|
@@ -2019,7 +2056,7 @@ function makePluginLLM(owner, hostLLM, providerRegistry, config, getLiveConfig,
|
|
|
2019
2056
|
providerCache.set(cacheKey, created);
|
|
2020
2057
|
return { provider: created, providerName };
|
|
2021
2058
|
};
|
|
2022
|
-
|
|
2059
|
+
const pluginLlm = {
|
|
2023
2060
|
defaults() {
|
|
2024
2061
|
const d = pluginDefaults();
|
|
2025
2062
|
return {
|
|
@@ -2030,12 +2067,49 @@ function makePluginLLM(owner, hostLLM, providerRegistry, config, getLiveConfig,
|
|
|
2030
2067
|
async complete(prompt, opts) {
|
|
2031
2068
|
const defaults = pluginDefaults();
|
|
2032
2069
|
const model = opts?.model ?? defaults.model ?? currentModel();
|
|
2033
|
-
const
|
|
2070
|
+
const providerName = opts?.provider ?? defaults.provider ?? currentProvider().id;
|
|
2034
2071
|
const maxTokens = Math.min(
|
|
2035
2072
|
HARD_MAX_TOKENS,
|
|
2036
2073
|
opts?.maxTokens ?? defaults.maxTokens ?? DEFAULT_MAX_TOKENS
|
|
2037
2074
|
);
|
|
2038
2075
|
const temperature = opts?.temperature ?? defaults.temperature;
|
|
2076
|
+
const timeoutMs = Math.min(
|
|
2077
|
+
HARD_TIMEOUT_MS,
|
|
2078
|
+
Math.max(1, opts?.timeoutMs ?? defaults.timeoutMs ?? DEFAULT_TIMEOUT_MS)
|
|
2079
|
+
);
|
|
2080
|
+
if (hostLLM.oneShot) {
|
|
2081
|
+
metrics.counter("llm.calls", 1, { provider: providerName, model, engine: "one-shot" });
|
|
2082
|
+
const result = await hostLLM.oneShot({
|
|
2083
|
+
userPrompt: prompt,
|
|
2084
|
+
providerId: providerName,
|
|
2085
|
+
model,
|
|
2086
|
+
maxTokens,
|
|
2087
|
+
timeoutMs,
|
|
2088
|
+
...temperature !== void 0 ? { temperature } : {},
|
|
2089
|
+
...opts?.system ? { system: opts.system } : {},
|
|
2090
|
+
...opts?.responseFormat === "json" ? { responseFormat: { type: "json_object" } } : {},
|
|
2091
|
+
...opts?.signal ? { signal: opts.signal } : {},
|
|
2092
|
+
...opts?.role ?? defaults.role ? { role: opts?.role ?? defaults.role } : {},
|
|
2093
|
+
...opts?.fallbackModels ?? defaults.fallbackModels ? { fallbackModels: [...opts?.fallbackModels ?? defaults.fallbackModels ?? []] } : {}
|
|
2094
|
+
});
|
|
2095
|
+
if (result.error) {
|
|
2096
|
+
metrics.counter("llm.errors", 1, { provider: result.provider, model: result.model });
|
|
2097
|
+
throw new Error(result.error);
|
|
2098
|
+
}
|
|
2099
|
+
metrics.counter("llm.tokens_in", result.tokens.input);
|
|
2100
|
+
metrics.counter("llm.tokens_out", result.tokens.output);
|
|
2101
|
+
return {
|
|
2102
|
+
text: result.text,
|
|
2103
|
+
model: result.model,
|
|
2104
|
+
provider: result.provider,
|
|
2105
|
+
usage: { input: result.tokens.input, output: result.tokens.output },
|
|
2106
|
+
stopReason: result.stopReason ?? "end_turn",
|
|
2107
|
+
fromFallback: result.fromFallback,
|
|
2108
|
+
attempts: result.attempts,
|
|
2109
|
+
durationMs: result.durationMs
|
|
2110
|
+
};
|
|
2111
|
+
}
|
|
2112
|
+
const { provider } = resolveProvider(providerName, model);
|
|
2039
2113
|
const request = {
|
|
2040
2114
|
model,
|
|
2041
2115
|
messages: [{ role: "user", content: [{ type: "text", text: prompt }] }],
|
|
@@ -2044,7 +2118,8 @@ function makePluginLLM(owner, hostLLM, providerRegistry, config, getLiveConfig,
|
|
|
2044
2118
|
...opts?.system ? { system: [{ type: "text", text: opts.system }] } : {},
|
|
2045
2119
|
...opts?.responseFormat === "json" ? { responseFormat: { type: "json_object" } } : {}
|
|
2046
2120
|
};
|
|
2047
|
-
const
|
|
2121
|
+
const timeoutSignal = AbortSignal.timeout(timeoutMs);
|
|
2122
|
+
const signal = opts?.signal ? AbortSignal.any([opts.signal, timeoutSignal]) : timeoutSignal;
|
|
2048
2123
|
metrics.counter("llm.calls", 1, { provider: providerName, model });
|
|
2049
2124
|
try {
|
|
2050
2125
|
const response = await provider.complete(request, { signal });
|
|
@@ -2069,6 +2144,33 @@ function makePluginLLM(owner, hostLLM, providerRegistry, config, getLiveConfig,
|
|
|
2069
2144
|
}
|
|
2070
2145
|
}
|
|
2071
2146
|
};
|
|
2147
|
+
const council = hostLLM.council;
|
|
2148
|
+
if (council) {
|
|
2149
|
+
pluginLlm.council = async (question, opts) => {
|
|
2150
|
+
const trimmed = question.trim();
|
|
2151
|
+
if (!trimmed) throw new Error("Plugin Council question must not be empty.");
|
|
2152
|
+
if (trimmed.length > 2e4) {
|
|
2153
|
+
throw new Error("Plugin Council question must not exceed 20000 characters.");
|
|
2154
|
+
}
|
|
2155
|
+
if ((opts?.context?.length ?? 0) > 8e4) {
|
|
2156
|
+
throw new Error("Plugin Council context must not exceed 80000 characters.");
|
|
2157
|
+
}
|
|
2158
|
+
const defaults = pluginDefaults();
|
|
2159
|
+
metrics.counter("llm.council.calls", 1, { plugin: owner });
|
|
2160
|
+
const result = await council({
|
|
2161
|
+
question: trimmed,
|
|
2162
|
+
...opts?.context ? { context: opts.context } : {},
|
|
2163
|
+
...opts?.options ? { options: opts.options } : {},
|
|
2164
|
+
...opts?.profile ?? defaults.councilProfile ? { profile: opts?.profile ?? defaults.councilProfile } : {},
|
|
2165
|
+
...opts?.signal ? { signal: opts.signal } : {}
|
|
2166
|
+
});
|
|
2167
|
+
metrics.counter("llm.tokens_in", result.usage.inputTokens);
|
|
2168
|
+
metrics.counter("llm.tokens_out", result.usage.outputTokens);
|
|
2169
|
+
if (result.status === "failed") metrics.counter("llm.errors", 1, { provider: "council" });
|
|
2170
|
+
return result;
|
|
2171
|
+
};
|
|
2172
|
+
}
|
|
2173
|
+
return pluginLlm;
|
|
2072
2174
|
}
|
|
2073
2175
|
function scopedMetrics(sink, pluginName) {
|
|
2074
2176
|
const prefix = `plugin.${pluginName}.`;
|
|
@@ -8958,7 +9060,7 @@ function createPromptsPlugin(opts) {
|
|
|
8958
9060
|
version: "1.0.0",
|
|
8959
9061
|
description: "Prompt library with 100+ builtin prompts, search, and AI authoring",
|
|
8960
9062
|
apiVersion: "^0.1",
|
|
8961
|
-
capabilities: { slashCommands: true },
|
|
9063
|
+
capabilities: { slashCommands: true, llm: true },
|
|
8962
9064
|
defaultConfig: {},
|
|
8963
9065
|
setup(api) {
|
|
8964
9066
|
const rawConfig = api.config;
|
|
@@ -8969,7 +9071,7 @@ function createPromptsPlugin(opts) {
|
|
|
8969
9071
|
bundledDir: rawConfig["bundledPromptsDir"]
|
|
8970
9072
|
}) : null);
|
|
8971
9073
|
usage = opts?.usage ?? (paths ? new PromptUsageStore(paths.promptUsage) : null);
|
|
8972
|
-
api.slashCommands.register(buildPromptsCommand(() => store, () => loader));
|
|
9074
|
+
api.slashCommands.register(buildPromptsCommand(() => store, () => loader, () => api.llm));
|
|
8973
9075
|
api.slashCommands.register(buildPromptSearchCommand(() => loader, () => usage));
|
|
8974
9076
|
api.slashCommands.register(buildPromptGenCommand(() => loader));
|
|
8975
9077
|
api.log.info("[prompts] loaded \u2014 /prompts, /prompt, /prompt-gen available");
|
|
@@ -8985,7 +9087,7 @@ function createPromptsPlugin(opts) {
|
|
|
8985
9087
|
}
|
|
8986
9088
|
};
|
|
8987
9089
|
}
|
|
8988
|
-
function buildPromptsCommand(getStore, getLoader) {
|
|
9090
|
+
function buildPromptsCommand(getStore, getLoader, getLlm) {
|
|
8989
9091
|
return {
|
|
8990
9092
|
name: "prompts",
|
|
8991
9093
|
description: "Manage your prompt library: /prompts [list|view|add|edit|delete|favorite|extend]",
|
|
@@ -9080,16 +9182,25 @@ ${lines.join("\n")}
|
|
|
9080
9182
|
const matches2 = await store.find(parsed.title);
|
|
9081
9183
|
if (matches2.length === 0) return { message: `No prompt matching "${parsed.title}".` };
|
|
9082
9184
|
const exact = matches2.find((m) => m.title.toLowerCase() === parsed.title?.toLowerCase()) ?? expectDefined(matches2[0]);
|
|
9083
|
-
const
|
|
9084
|
-
if (!
|
|
9085
|
-
|
|
9086
|
-
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
|
|
9090
|
-
|
|
9091
|
-
|
|
9092
|
-
|
|
9185
|
+
const llm = getLlm();
|
|
9186
|
+
if (!llm) return { message: "LLM not available. Configure a provider first." };
|
|
9187
|
+
let enhanced;
|
|
9188
|
+
try {
|
|
9189
|
+
enhanced = await llm.complete(
|
|
9190
|
+
renderInstructionTemplate(readBundledInstructionText("llm/prompt-extend.md"), {
|
|
9191
|
+
existingPrompt: exact.content,
|
|
9192
|
+
additionalInstructions: parsed.content
|
|
9193
|
+
}),
|
|
9194
|
+
{
|
|
9195
|
+
system: "You improve reusable prompts while preserving their intent and variables.",
|
|
9196
|
+
role: "prompt-refiner",
|
|
9197
|
+
maxTokens: 2048
|
|
9198
|
+
}
|
|
9199
|
+
);
|
|
9200
|
+
} catch {
|
|
9201
|
+
return { message: "LLM enhancement failed. The saved prompt was not changed." };
|
|
9202
|
+
}
|
|
9203
|
+
exact.content = enhanced.text.trim();
|
|
9093
9204
|
exact.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
9094
9205
|
await store.save(exact);
|
|
9095
9206
|
getLoader()?.invalidateCache();
|
|
@@ -11973,10 +12084,12 @@ export {
|
|
|
11973
12084
|
parseChimeraReviewReport,
|
|
11974
12085
|
parseReviewSeverity,
|
|
11975
12086
|
persistReviewReport,
|
|
12087
|
+
pluginEntryMatchesName,
|
|
11976
12088
|
recordCompletedReview,
|
|
11977
12089
|
recordStartedReview,
|
|
11978
12090
|
redactPluginConfig,
|
|
11979
12091
|
resolvePluginConfig,
|
|
12092
|
+
resolvePluginEnablement,
|
|
11980
12093
|
resolvePluginManifestConfig,
|
|
11981
12094
|
selectRoundRobinReviewerAssignment,
|
|
11982
12095
|
unloadPlugins,
|
package/dist/security/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export { AutoApprovePermissionPolicy, alwaysAllowUnavailableReason, DefaultPermi
|
|
|
10
10
|
export { TRUST_POLICY_JSON_SCHEMA, TRUST_POLICY_LIMITS, TRUST_POLICY_SCHEMA_VERSION, type TrustPolicyDiagnostic, type TrustPolicyDiagnosticCode, type TrustPolicyValidationResult, validateTrustPolicy, } from './permission-policy-schema.js';
|
|
11
11
|
export { ReadOnlyPermissionPolicy } from './readonly-permission-policy.js';
|
|
12
12
|
export { DefaultSecretScrubber } from './secret-scrubber.js';
|
|
13
|
-
export { base32Decode, base32Encode, buildOtpAuthUri, generateRecoveryCodes, generateTotpSecret, generateTotp, hashRecoveryCode, verifyRecoveryCode, verifyTotp, } from './totp.js';
|
|
13
|
+
export { base32Decode, base32Encode, buildOtpAuthUri, generateRecoveryCodes, generateTotpSecret, generateTotp, hashRecoveryCode, verifyRecoveryCode, verifyTotp, verifyTotpCounter, } from './totp.js';
|
|
14
14
|
export { DefaultSecretVault, migratePlaintextSecrets, rewriteConfigEncrypted, rotateConfigKeys, type SecretVaultOptions, } from './secret-vault.js';
|
|
15
15
|
export type { CompatibilityTrustBoundaryOptions, TrustActor, TrustActorKind, TrustAllowDecision, TrustAttribute, TrustAuthContext, TrustAuthMethod, TrustBoundary, TrustBoundaryAuditEntry, TrustBoundaryDecision, TrustBoundaryRequest, TrustConfirmDecision, TrustDecodeIssue, TrustDecodeResult, TrustDenyDecision, TrustRisk, TrustScope, TrustScopedTokenDecision, TrustSubject, TrustSurface, } from './trust-boundary.js';
|
|
16
16
|
export { createCompatibilityTrustBoundary, decodeTrustBoundaryDecision, decodeTrustBoundaryRequest, isTrustDecisionAllowed, TRUST_BOUNDARY_VERSION, } from './trust-boundary.js';
|