dsh-agent-plugins-market 0.7.0 → 0.7.1
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/README.md +2 -2
- package/README.zh.md +2 -2
- package/client/client.js +28048 -1033
- package/client/client.js.map +1 -1
- package/lib/application/catalog-context.js +8 -1
- package/lib/application/catalog.js +13 -0
- package/lib/application/details.js +13 -2
- package/lib/application/mcp-service.js +17 -0
- package/lib/application/panel-resources.js +16 -4
- package/lib/application/project-agent-roles.js +7 -1
- package/lib/catalog/archive.js +1 -1
- package/lib/catalog/paths.js +8 -0
- package/lib/catalog/plugin-variables.js +38 -0
- package/lib/catalog/project-hooks.js +14 -1
- package/lib/catalog/skills-parse.js +47 -0
- package/lib/catalog/source-catalog.js +8 -3
- package/lib/catalog/suite-components.js +2 -2
- package/lib/contracts/market.js +1 -0
- package/lib/contracts/settings.js +63 -0
- package/lib/index.js +26 -11
- package/lib/model/layouts.js +10 -1
- package/lib/routes.js +12 -0
- package/lib/runtime/agent-role-router.js +28 -6
- package/lib/runtime/commands-mounts.js +50 -9
- package/lib/runtime/deadline.js +32 -6
- package/lib/runtime/dynamic-context.js +140 -0
- package/lib/runtime/feedback-tool.js +7 -3
- package/lib/runtime/host-locale.js +39 -3
- package/lib/runtime/lsp-mounts.js +23 -2
- package/lib/runtime/mcp-backend.js +14 -15
- package/lib/runtime/mcp-client/config.js +8 -0
- package/lib/runtime/mcp-client/connection.js +6 -6
- package/lib/runtime/mcp-client/host-seams.js +8 -88
- package/lib/runtime/mcp-config.js +7 -4
- package/lib/runtime/project-runtime.js +23 -9
- package/lib/runtime/reconcile-scheduler.js +6 -8
- package/lib/runtime/reconciler.js +2 -1
- package/lib/runtime/regions.js +0 -19
- package/lib/runtime/settings-namespace.js +21 -13
- package/lib/runtime/skills-provider.js +33 -11
- package/lib/runtime/source-auto-update.js +10 -14
- package/lib/runtime/timer-seat.js +80 -0
- package/lib/runtime/tool-registry-observer.js +20 -20
- package/lib/runtime/user-commands.js +5 -1
- package/lib/runtime/user-panels.js +110 -41
- package/lib/runtime/user-store.js +114 -58
- package/lib/types/application/catalog-context.d.ts +6 -0
- package/lib/types/application/catalog.d.ts +9 -0
- package/lib/types/application/mcp-service.d.ts +6 -0
- package/lib/types/application/ports.d.ts +1 -1
- package/lib/types/application/queries.d.ts +2 -0
- package/lib/types/catalog/paths.d.ts +6 -0
- package/lib/types/catalog/plugin-variables.d.ts +16 -0
- package/lib/types/catalog/skills-parse.d.ts +13 -0
- package/lib/types/catalog/source-catalog.d.ts +7 -2
- package/lib/types/contracts/market.d.ts +10 -0
- package/lib/types/contracts/settings.d.ts +59 -0
- package/lib/types/model/layouts.d.ts +10 -0
- package/lib/types/runtime/agent-role-router.d.ts +6 -2
- package/lib/types/runtime/commands-mounts.d.ts +15 -7
- package/lib/types/runtime/deadline.d.ts +10 -11
- package/lib/types/runtime/dynamic-context.d.ts +81 -0
- package/lib/types/runtime/host-locale.d.ts +19 -1
- package/lib/types/runtime/lsp-mounts.d.ts +7 -0
- package/lib/types/runtime/mcp-backend.d.ts +8 -15
- package/lib/types/runtime/mcp-client/config.d.ts +8 -0
- package/lib/types/runtime/mcp-client/host-seams.d.ts +20 -64
- package/lib/types/runtime/project-runtime.d.ts +10 -3
- package/lib/types/runtime/reconcile-scheduler.d.ts +1 -1
- package/lib/types/runtime/regions.d.ts +1 -4
- package/lib/types/runtime/settings-namespace.d.ts +10 -10
- package/lib/types/runtime/skills-provider.d.ts +11 -2
- package/lib/types/runtime/source-auto-update.d.ts +3 -4
- package/lib/types/runtime/timer-seat.d.ts +51 -0
- package/lib/types/runtime/tool-registry-observer.d.ts +12 -6
- package/lib/types/runtime/user-panels.d.ts +65 -12
- package/lib/types/runtime/user-store.d.ts +65 -16
- package/package.json +21 -4
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Suite } from '../model/types.js';
|
|
2
|
+
/** The absolute paths one expansion can supply; an absent entry leaves its variable verbatim. */
|
|
3
|
+
export interface PluginPathContext {
|
|
4
|
+
/** Suite checkout root: `${PLUGIN_ROOT}` and its dialect aliases. */
|
|
5
|
+
root?: string;
|
|
6
|
+
/** Per-suite data directory: `${PLUGIN_DATA}` and its aliases. */
|
|
7
|
+
data?: string;
|
|
8
|
+
/** Directory holding the skill file: `${CLAUDE_SKILL_DIR}`. */
|
|
9
|
+
skillDir?: string;
|
|
10
|
+
/** Calling session's project directory: `${CLAUDE_PROJECT_DIR}` and its aliases. */
|
|
11
|
+
projectDir?: string;
|
|
12
|
+
}
|
|
13
|
+
/** The suite root `${PLUGIN_ROOT}` and its dialect aliases resolve to. */
|
|
14
|
+
export declare function pluginRootOf(suite: Pick<Suite, 'manifest' | 'root'>): string | undefined;
|
|
15
|
+
/** Replace every path variable the context can resolve; other text stays exactly as written. */
|
|
16
|
+
export declare function expandPluginPaths(text: string, context: PluginPathContext): string;
|
|
@@ -11,5 +11,18 @@ export interface ParsedSkillFrontmatter {
|
|
|
11
11
|
* skill must be dropped from discovery.
|
|
12
12
|
*/
|
|
13
13
|
export declare function parseSkillFrontmatter(text: string, expectedName: string | undefined): ParsedSkillFrontmatter | string;
|
|
14
|
+
/**
|
|
15
|
+
* Rejection for a user skill document the harness's own `dsh-skill-filesystem`
|
|
16
|
+
* reader would drop from `~/.agents/skills`, or `undefined` when that reader
|
|
17
|
+
* accepts it.
|
|
18
|
+
*
|
|
19
|
+
* The two readers share the directory, so the panel publishes only documents
|
|
20
|
+
* both accept: a listed entry never becomes a skill that loads in a
|
|
21
|
+
* market-equipped session alone. The checks mirror the shipped reader rather
|
|
22
|
+
* than the lenient suite scan — strict YAML, no display-name normalization,
|
|
23
|
+
* and a `name` the reader compares only against its kebab grammar.
|
|
24
|
+
* @returns the drop reason, phrased as the reader's own diagnostic.
|
|
25
|
+
*/
|
|
26
|
+
export declare function skillEntryRejection(text: string): string | undefined;
|
|
14
27
|
/** Strip the frontmatter block, returning the instruction body. */
|
|
15
28
|
export declare function stripFrontmatter(text: string): string;
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import type { DiscoveredSuite, SourceRef, SuiteDimension } from '../model/types.js';
|
|
2
2
|
/** Discover suites from the selected configured or project checkouts. */
|
|
3
3
|
export declare function discoverSourceList(sources: SourceRef[], dimension: SuiteDimension, dimensionRoot: string): Promise<DiscoveredSuite[]>;
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Discover suites plus per-source scan diagnostics for one dimension.
|
|
6
|
+
* @param scanProjectLayouts - whether the project's own native Agent directories
|
|
7
|
+
* join the scan. Required on purpose: the switch has one owner (the host
|
|
8
|
+
* settings document), so a default here would be a second copy of it.
|
|
9
|
+
*/
|
|
10
|
+
export declare function discoverSourceListWithNotes(sources: SourceRef[], dimension: SuiteDimension, dimensionRoot: string, scanProjectLayouts: boolean): Promise<{
|
|
6
11
|
suites: DiscoveredSuite[];
|
|
7
12
|
scanNotes: Record<string, string[]>;
|
|
8
13
|
}>;
|
|
@@ -28,6 +28,7 @@ export declare const MARKET_ROUTES: {
|
|
|
28
28
|
readonly setSurface: "/api/agent-plugins/set-surface";
|
|
29
29
|
readonly mcpOverrides: "/api/agent-plugins/mcp-overrides";
|
|
30
30
|
readonly setMcpOverride: "/api/agent-plugins/set-mcp-override";
|
|
31
|
+
readonly setMcpServerEnabled: "/api/agent-plugins/set-mcp-server-enabled";
|
|
31
32
|
readonly mcpRetry: "/api/agent-plugins/mcp-retry";
|
|
32
33
|
readonly mcpReauthorize: "/api/agent-plugins/mcp-reauthorize";
|
|
33
34
|
readonly mcpBackend: "/api/agent-plugins/mcp-backend";
|
|
@@ -243,6 +244,8 @@ export interface SuiteDetail {
|
|
|
243
244
|
description: string | null;
|
|
244
245
|
author: string | null;
|
|
245
246
|
keywords: string[];
|
|
247
|
+
/** Last modification of the suite checkout, as an ISO timestamp; null when it cannot be read. */
|
|
248
|
+
updatedAt: string | null;
|
|
246
249
|
layout: string;
|
|
247
250
|
dimension: string;
|
|
248
251
|
root: string;
|
|
@@ -273,6 +276,7 @@ export interface SkillContent {
|
|
|
273
276
|
}
|
|
274
277
|
/** A user panel entry (skills / commands / agent personas) over HTTP. */
|
|
275
278
|
export interface UserPanelEntryWire {
|
|
279
|
+
/** Entry name: the name its document declares, else the file's base name. */
|
|
276
280
|
name: string;
|
|
277
281
|
description: string;
|
|
278
282
|
disabled: boolean;
|
|
@@ -284,7 +288,13 @@ export interface UserPanelEntryWire {
|
|
|
284
288
|
suiteName?: string;
|
|
285
289
|
metadata: Record<string, unknown>;
|
|
286
290
|
path: string;
|
|
291
|
+
/** The entry file's last modification, as an ISO timestamp. */
|
|
292
|
+
updatedAt?: string | null;
|
|
287
293
|
content: string;
|
|
294
|
+
/** Suite checkout root of a plugin-provided file; runtime consumers resolve `${PLUGIN_ROOT}` against it. */
|
|
295
|
+
suiteRoot?: string;
|
|
296
|
+
/** The suite's `${PLUGIN_DATA}` directory, for the same runtime resolution. */
|
|
297
|
+
suiteData?: string;
|
|
288
298
|
}
|
|
289
299
|
/** The user panel surface the market exposes. */
|
|
290
300
|
export type UserPanelKind = 'skills' | 'commands' | 'agents';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-safe settings contract of the market's host settings namespace: the
|
|
3
|
+
* namespace key, the fields with their defaults, and the one reader that turns
|
|
4
|
+
* a stored section into resolved values.
|
|
5
|
+
*
|
|
6
|
+
* The defaults live here and nowhere else. The namespace schema declares them
|
|
7
|
+
* to the host, the node half reads them back through {@link resolveMarketSettings},
|
|
8
|
+
* and the browser half — which cannot import `src/runtime` — reads the same
|
|
9
|
+
* resolved values off the settings snapshot it is handed. Changing a default is
|
|
10
|
+
* therefore a one-line edit in this module.
|
|
11
|
+
*
|
|
12
|
+
* @module contracts/settings
|
|
13
|
+
*/
|
|
14
|
+
/** Settings namespace this plugin registers; the key the plugin-config tab pairs our card by. */
|
|
15
|
+
export declare const MARKET_SETTINGS_NAMESPACE = "dsh-agent-plugins-market";
|
|
16
|
+
/** The persisted download-region setting: `auto` follows the interface language. */
|
|
17
|
+
export type DownloadRegionSetting = 'auto' | 'global' | 'china';
|
|
18
|
+
/** Every market setting with the value it resolves to when the document says nothing. */
|
|
19
|
+
export interface MarketSettings {
|
|
20
|
+
/** ON = the built-in MCP bridge with OAuth and SSE; OFF = host client compat mode. */
|
|
21
|
+
mcpEnhanced: boolean;
|
|
22
|
+
/** ON = native project Agent layouts (`.claude/`, `.agents/`) take part in discovery. */
|
|
23
|
+
scanProjectLayouts: boolean;
|
|
24
|
+
/** Download region for GitHub acquisition. */
|
|
25
|
+
downloadRegion: DownloadRegionSetting;
|
|
26
|
+
/** ON = the `report_market_issue` model tool is registered. */
|
|
27
|
+
feedbackEnabled: boolean;
|
|
28
|
+
/** ON = every configured source refreshes in the background. */
|
|
29
|
+
autoUpdateSources: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The default of every market setting — the single place one is written.
|
|
33
|
+
*
|
|
34
|
+
* These are user-visible behavior: a flip here is a behavior change that ships
|
|
35
|
+
* with its documentation, not a private implementation detail.
|
|
36
|
+
*/
|
|
37
|
+
export declare const MARKET_SETTINGS_DEFAULTS: MarketSettings;
|
|
38
|
+
/** Every field name the market's settings section carries. */
|
|
39
|
+
export type MarketSettingKey = keyof MarketSettings;
|
|
40
|
+
/**
|
|
41
|
+
* Narrow an untrusted stored region to a setting; anything else reads as the
|
|
42
|
+
* declared default.
|
|
43
|
+
* @param value - the stored `downloadRegion` value.
|
|
44
|
+
* @param fallback - the value an unrecognized input reads as.
|
|
45
|
+
*/
|
|
46
|
+
export declare function narrowDownloadRegion(value: unknown, fallback?: DownloadRegionSetting): DownloadRegionSetting;
|
|
47
|
+
/**
|
|
48
|
+
* Resolve a stored settings section the way the host resolves it: each field
|
|
49
|
+
* takes its stored value when it is one this field accepts, and its declared
|
|
50
|
+
* default otherwise.
|
|
51
|
+
*
|
|
52
|
+
* The host hands the resolved section back on its own, but not every caller has
|
|
53
|
+
* one — the plugin's own halves read a section they may not have received yet,
|
|
54
|
+
* and a test hands in a bare literal. Funnelling all of them through this
|
|
55
|
+
* function is what keeps a second reading of "what does missing mean" from
|
|
56
|
+
* growing somewhere else.
|
|
57
|
+
* @param section - the stored (or absent) namespace section, untrusted.
|
|
58
|
+
*/
|
|
59
|
+
export declare function resolveMarketSettings(section: unknown): MarketSettings;
|
|
@@ -42,6 +42,10 @@ export declare const MANIFEST_ALIASES: Partial<Record<ManifestKind, readonly str
|
|
|
42
42
|
/** Equivalent plugin-owned path variables; these never resolve as credentials. */
|
|
43
43
|
export declare const PLUGIN_ROOT_VARIABLES: ReadonlySet<string>;
|
|
44
44
|
export declare const PLUGIN_DATA_VARIABLES: ReadonlySet<string>;
|
|
45
|
+
/** Equivalent session project-directory variables; only a calling session supplies the directory. */
|
|
46
|
+
export declare const PROJECT_DIR_VARIABLES: ReadonlySet<string>;
|
|
47
|
+
/** Claude Code names the directory holding the skill's own file; no dialect alias exists. */
|
|
48
|
+
export declare const SKILL_DIR_VARIABLE = "CLAUDE_SKILL_DIR";
|
|
45
49
|
/** Explicit project document formats and portable surfaces; execution stays in the runtime adapters. */
|
|
46
50
|
export type ProjectMcpFormat = 'mcpServers' | 'zcode' | 'codex';
|
|
47
51
|
export type ProjectHookFormat = 'claude' | 'zcode';
|
|
@@ -50,6 +54,11 @@ export interface ProjectLayout {
|
|
|
50
54
|
label: string;
|
|
51
55
|
subdirs: readonly string[];
|
|
52
56
|
mcpFiles?: readonly string[];
|
|
57
|
+
/**
|
|
58
|
+
* Project-root-relative hook documents, read in order. A `settings.json`
|
|
59
|
+
* layer carries a `hooks` key; a standalone `hooks.json` may instead be the
|
|
60
|
+
* bare event table, the same file shape a suite ships under `hooks/`.
|
|
61
|
+
*/
|
|
53
62
|
hookFiles?: readonly string[];
|
|
54
63
|
mcpFormat?: ProjectMcpFormat;
|
|
55
64
|
hookFormat?: ProjectHookFormat;
|
|
@@ -64,6 +73,7 @@ export declare const PROJECT_LAYOUTS: readonly [{
|
|
|
64
73
|
readonly dirName: ".agents";
|
|
65
74
|
readonly label: "agents";
|
|
66
75
|
readonly subdirs: readonly ["skills", "agents", "commands"];
|
|
76
|
+
readonly hookFiles: readonly [".agents/hooks/hooks.json", ".agents/hooks.json"];
|
|
67
77
|
}, {
|
|
68
78
|
readonly dirName: ".codex";
|
|
69
79
|
readonly label: "Codex";
|
|
@@ -10,6 +10,10 @@ export interface AgentRoleEntry {
|
|
|
10
10
|
disabled: boolean;
|
|
11
11
|
title?: string;
|
|
12
12
|
rawText?: string;
|
|
13
|
+
/** Suite checkout root the card's `${PLUGIN_ROOT}` variables resolve to; absent for project-native files. */
|
|
14
|
+
suiteRoot?: string;
|
|
15
|
+
/** The suite's `${PLUGIN_DATA}` directory; absent for project-native files. */
|
|
16
|
+
suiteData?: string;
|
|
13
17
|
}
|
|
14
18
|
/**
|
|
15
19
|
* The executable part of one card. `tools` / `disallowedTools` stay in the file
|
|
@@ -83,9 +87,9 @@ export declare function parseAgentRole(text: string): AgentRolePolicy;
|
|
|
83
87
|
*/
|
|
84
88
|
export declare function resolveAgentOptions(policy: AgentRolePolicy, parent: unknown, llm: AgentRoleHost['llm'], signal: AbortSignal, subject: string, diagnose: (message: string) => void): Promise<AgentRoleOptions | undefined>;
|
|
85
89
|
/** Stable summaries; invalid declarations are excluded and transient read failures abort publication. */
|
|
86
|
-
export declare function agentRoleCatalog(entries: AgentRoleEntry[], signal: AbortSignal, diagnose?: (message: string) => void): Promise<SubagentCatalogEntry[]>;
|
|
90
|
+
export declare function agentRoleCatalog(entries: AgentRoleEntry[], signal: AbortSignal, diagnose?: (message: string) => void, projectDir?: string): Promise<SubagentCatalogEntry[]>;
|
|
87
91
|
/** Read the same declaration for catalog summaries and execution, including inline resources. */
|
|
88
|
-
export declare function readAgentRole(entry: AgentRoleEntry): Promise<AgentRolePolicy>;
|
|
92
|
+
export declare function readAgentRole(entry: AgentRoleEntry, projectDir?: string): Promise<AgentRolePolicy>;
|
|
89
93
|
/**
|
|
90
94
|
* Start one role child and return its durable id without waiting for the result.
|
|
91
95
|
* Resume state, steering, and the settlement notice belong to the host's
|
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
* register as dsh slash commands.
|
|
4
4
|
*
|
|
5
5
|
* A CC command is a prompt template the model executes (its body carries
|
|
6
|
-
* `$ARGUMENTS
|
|
7
|
-
* harness's follow-up mechanism: the template
|
|
8
|
-
* becomes one durable user-role follow-up
|
|
9
|
-
* Registrations reconcile on every
|
|
10
|
-
* broken command file
|
|
11
|
-
* command
|
|
6
|
+
* `$ARGUMENTS`, path variables and `` !`cmd` `` dynamic-context placeholders),
|
|
7
|
+
* so the handler maps it onto the harness's follow-up mechanism: the template
|
|
8
|
+
* with those placeholders resolved becomes one durable user-role follow-up
|
|
9
|
+
* message on the receiving agent. Registrations reconcile on every
|
|
10
|
+
* enable/disable/install/uninstall; a broken command file, a failed injected
|
|
11
|
+
* command, or an unavailable `ctx.commands` is contained per command and
|
|
12
|
+
* reported as a diagnostic.
|
|
12
13
|
*/
|
|
13
14
|
import type { Context } from '@deepseek-ai/cordis';
|
|
14
15
|
import type { Suite, SuiteMarkdownResource } from '../model/types.js';
|
|
@@ -23,13 +24,20 @@ interface CommandSpec {
|
|
|
23
24
|
description: string;
|
|
24
25
|
body: string;
|
|
25
26
|
hint?: string;
|
|
27
|
+
/** Set when the command file belongs to a suite with a plugin root; absent for project-native files. */
|
|
28
|
+
suiteRoot?: string;
|
|
29
|
+
/** The suite's `${PLUGIN_DATA}` directory; absent for project-native files. */
|
|
30
|
+
suiteData?: string;
|
|
26
31
|
}
|
|
27
32
|
export declare class CommandMountRegistry {
|
|
28
33
|
private readonly ctx;
|
|
29
34
|
private readonly t;
|
|
35
|
+
private readonly dataRoot?;
|
|
30
36
|
private readonly fingerprints;
|
|
31
37
|
private readonly live;
|
|
32
|
-
constructor(ctx: Context, t?: HostTranslate);
|
|
38
|
+
constructor(ctx: Context, t?: HostTranslate, dataRoot?: string | undefined);
|
|
39
|
+
/** The live shell seam, when the profile has one; dynamic context stays literal without it. */
|
|
40
|
+
private shell;
|
|
33
41
|
/** Register/unregister suite commands to match the enabled suites exactly. */
|
|
34
42
|
reconcile(enabledSuites: Suite[]): Promise<CommandMountDiagnostic[]>;
|
|
35
43
|
/** Dispose every registered command; used at plugin teardown. */
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Every wait here is a race against a timer: the caller stops waiting and the
|
|
5
|
-
* underlying work keeps running. That is the only safe shape for a mount and
|
|
6
|
-
* for the change pipeline that drives it — a spawned server process or a
|
|
7
|
-
* browser authorization the user is completing must not be abandoned just
|
|
8
|
-
* because nobody is waiting for it any more.
|
|
9
|
-
*
|
|
10
|
-
* @module runtime/deadline
|
|
11
|
-
*/
|
|
1
|
+
/** Identifies this plugin's bounded waits inside a timeout reason. */
|
|
2
|
+
export declare const MARKET_DEADLINE_CODE = "MARKET_DEADLINE";
|
|
12
3
|
/**
|
|
13
4
|
* Resolve `true` once `work` settles, or `false` when `deadlineMs` elapses.
|
|
14
5
|
*
|
|
15
6
|
* A rejection counts as settled: this helper only reports timing, so callers
|
|
16
7
|
* that need the failure attach their own handler to `work`.
|
|
8
|
+
*
|
|
9
|
+
* A non-positive wait means "do not wait": the answer is simply whether the
|
|
10
|
+
* work had already settled. That is deliberately not the host primitive's own
|
|
11
|
+
* reading of a non-positive timeout, which is "arm no timer at all" — the floor
|
|
12
|
+
* below keeps the two from collapsing into opposite behaviors.
|
|
13
|
+
* @param work - the work to wait for; it is never cancelled, only stopped being awaited.
|
|
14
|
+
* @param deadlineMs - how long to wait, in milliseconds.
|
|
15
|
+
* @returns whether the work settled before the deadline.
|
|
17
16
|
*/
|
|
18
17
|
export declare function settlesWithin(work: Promise<unknown>, deadlineMs: number): Promise<boolean>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code dynamic context injection: `` !`command` `` in a command body or
|
|
3
|
+
* skill body runs the command and the placeholder becomes its output.
|
|
4
|
+
*
|
|
5
|
+
* One pass over the original text recognizes both spellings — the inline
|
|
6
|
+
* `` !`cmd` `` (only at a line start or after whitespace, matching the authoring
|
|
7
|
+
* rule) and the multi-line ```` ```! ```` fence — and every command runs
|
|
8
|
+
* sequentially in the calling session's directory. Outputs are inserted as
|
|
9
|
+
* plain text and never re-read, so a command cannot emit another placeholder.
|
|
10
|
+
*
|
|
11
|
+
* Failure is contained per invocation rather than per placeholder: the caller
|
|
12
|
+
* aborts the whole invocation with the command's own output, so a model never
|
|
13
|
+
* reads half-injected text. Exit code 1 counts as a result for the commands
|
|
14
|
+
* whose benign outcome it is (`grep`, `rg`, `find`, `diff`, `test`, …).
|
|
15
|
+
*
|
|
16
|
+
* The shell service is reached structurally: {@link shellSeamOf} resolves it
|
|
17
|
+
* from any context, and a profile without one keeps the author's literal text.
|
|
18
|
+
*/
|
|
19
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
20
|
+
/** How long one injected command may run; the executor caps a larger request. */
|
|
21
|
+
export declare const DYNAMIC_CONTEXT_TIMEOUT_MS = 120000;
|
|
22
|
+
/** The requested forward cap for one injected command's stdout, in bytes. */
|
|
23
|
+
export declare const DYNAMIC_CONTEXT_MAX_OUTPUT_BYTES: number;
|
|
24
|
+
/** The slice of the host shell service this module uses. */
|
|
25
|
+
export interface ShellSeam {
|
|
26
|
+
resolve(request: {
|
|
27
|
+
command: string;
|
|
28
|
+
workdir?: string;
|
|
29
|
+
timeoutMs?: number;
|
|
30
|
+
stdoutMaxBytes?: number;
|
|
31
|
+
signal?: AbortSignal;
|
|
32
|
+
}): unknown;
|
|
33
|
+
run(spec: unknown): Promise<ShellOutcome>;
|
|
34
|
+
}
|
|
35
|
+
/** The fields of one shell run this module reads. */
|
|
36
|
+
export interface ShellOutcome {
|
|
37
|
+
exitCode: number | null;
|
|
38
|
+
timedOut: boolean;
|
|
39
|
+
aborted: boolean;
|
|
40
|
+
stdout: {
|
|
41
|
+
text: string;
|
|
42
|
+
truncated: boolean;
|
|
43
|
+
spillPath?: string;
|
|
44
|
+
};
|
|
45
|
+
stderr: {
|
|
46
|
+
text: string;
|
|
47
|
+
truncated: boolean;
|
|
48
|
+
spillPath?: string;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Resolve the host shell service from any context, whether or not the reading
|
|
53
|
+
* fiber injects `shell`.
|
|
54
|
+
*
|
|
55
|
+
* Cordis resolves `ctx.shell` by walking the reading fiber's ancestors, so a
|
|
56
|
+
* scope that does not inject the service throws `cannot get property "shell"
|
|
57
|
+
* without inject` even when a sibling fiber provides it. `ctx.get` reads the
|
|
58
|
+
* global service store instead and answers `undefined` in a profile that has
|
|
59
|
+
* no shell, which is what keeps the seam optional.
|
|
60
|
+
*
|
|
61
|
+
* @param ctx - the context the dynamic-context pass runs under.
|
|
62
|
+
* @returns the shell seam, or `undefined` when the profile provides none.
|
|
63
|
+
*/
|
|
64
|
+
export declare function shellSeamOf(ctx: Context): ShellSeam | undefined;
|
|
65
|
+
export interface DynamicContextOptions {
|
|
66
|
+
shell: ShellSeam;
|
|
67
|
+
/** Session directory every injected command runs in. */
|
|
68
|
+
workdir?: string;
|
|
69
|
+
signal?: AbortSignal;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Run every placeholder's command and return the text the model receives.
|
|
73
|
+
*
|
|
74
|
+
* @param text - author text whose `${...}` variables and arguments are already resolved.
|
|
75
|
+
* @param options - the resolved shell seam, session directory and cancellation signal.
|
|
76
|
+
* @returns the text with each placeholder replaced by its command's output.
|
|
77
|
+
* @throws when a command fails, times out or is aborted, carrying the command and its output.
|
|
78
|
+
*/
|
|
79
|
+
export declare function injectDynamicContext(text: string, options: DynamicContextOptions): Promise<string>;
|
|
80
|
+
/** Whether this command's exit status is a result rather than a failure. */
|
|
81
|
+
export declare function benignExit(exitCode: number | null, command: string): boolean;
|
|
@@ -6,8 +6,26 @@ interface ResolvedLocale {
|
|
|
6
6
|
}
|
|
7
7
|
/** Resolve the active host language from settings; unknown values default to zh. */
|
|
8
8
|
export declare function bindHostLocale(preference: string | undefined): HostTranslate;
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Wire the host settings service as the primary locale source, replacing the
|
|
11
|
+
* `settings.yaml` fallback.
|
|
12
|
+
* @param read - reads `locale.preference` from the settings service.
|
|
13
|
+
*/
|
|
14
|
+
export declare function setHostLocaleSource(read: () => string | undefined): void;
|
|
15
|
+
/**
|
|
16
|
+
* The persisted locale preference: the host settings document when the service
|
|
17
|
+
* is composed, else `$DSH_HOME/settings.yaml` (best effort).
|
|
18
|
+
*/
|
|
10
19
|
export declare function readLocalePreference(): Promise<string | undefined>;
|
|
11
20
|
/** Bind a host translator against the persisted locale preference. */
|
|
12
21
|
export declare function loadHostLocale(): Promise<ResolvedLocale>;
|
|
22
|
+
/**
|
|
23
|
+
* Read `locale.preference` from the host settings service.
|
|
24
|
+
*
|
|
25
|
+
* The locale namespace is registered by the host's own client-locale plugin, so
|
|
26
|
+
* this reads `undefined` until that plugin mounts — which is why the caller
|
|
27
|
+
* re-binds when the service arrives rather than capturing the value once.
|
|
28
|
+
* @param settingsCtx - a context carrying the `settings` service.
|
|
29
|
+
*/
|
|
30
|
+
export declare function readHostLocalePreference(settingsCtx: unknown): string | undefined;
|
|
13
31
|
export {};
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
*/
|
|
30
30
|
import type { Context } from '@deepseek-ai/cordis';
|
|
31
31
|
import { type LegacyLspSeam } from './profile-seam.js';
|
|
32
|
+
import { type PluginPathContext } from '../catalog/plugin-variables.js';
|
|
32
33
|
import { type Suite } from '../model/types.js';
|
|
33
34
|
export interface LspMountDiagnostic {
|
|
34
35
|
suiteId: string;
|
|
@@ -54,6 +55,8 @@ export declare function toLspServerConfig(spec: {
|
|
|
54
55
|
initializationOptions?: unknown;
|
|
55
56
|
configuration?: unknown;
|
|
56
57
|
}): LspStdioServerConfig;
|
|
58
|
+
/** Resolve author-written paths in one declaration before the host spawns the server. */
|
|
59
|
+
export declare function expandLspServerConfig(config: LspStdioServerConfig, context: PluginPathContext): LspStdioServerConfig;
|
|
57
60
|
/** Minimal structural shape of a dynamically imported host plugin module. */
|
|
58
61
|
interface HostModule {
|
|
59
62
|
default?: unknown;
|
|
@@ -87,6 +90,8 @@ export declare class LspMountRegistry {
|
|
|
87
90
|
private capabilityFailure;
|
|
88
91
|
/** Latest diagnostic per suite id; cleared when its suite mounts or leaves the wanted set. */
|
|
89
92
|
private readonly lastDiagnostics;
|
|
93
|
+
/** Plugin storage root holding each suite's `${PLUGIN_DATA}` directory; unset leaves the variable verbatim. */
|
|
94
|
+
private pluginDataRoot?;
|
|
90
95
|
/** Direct (user-configured) server provider; defaults to none. */
|
|
91
96
|
private directProvider;
|
|
92
97
|
private disabledProvider;
|
|
@@ -119,6 +124,8 @@ export declare class LspMountRegistry {
|
|
|
119
124
|
private seamConflictReason;
|
|
120
125
|
/** Dispose the capability seam this registry mounted, once no wanted server needs it. */
|
|
121
126
|
private releaseCapability;
|
|
127
|
+
/** Install the plugin storage root per-suite data directories resolve against. */
|
|
128
|
+
setPluginDataRoot(root: string): void;
|
|
122
129
|
/** Install the direct (user-configured) server provider used at reconcile time. */
|
|
123
130
|
setDirectProvider(provider: () => Promise<Record<string, import('../model/types.js').LspServerSpec>>): void;
|
|
124
131
|
setDisabledProvider(provider: () => Promise<Set<string>>): void;
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* and legacy SSE) or through the host's `@deepseek-ai/dsh-mcp-client`
|
|
5
5
|
* (compatibility mode: no OAuth, no SSE, but the host-native implementation).
|
|
6
6
|
*
|
|
7
|
-
* The choice is
|
|
8
|
-
*
|
|
7
|
+
* The choice is the `mcpEnhanced` field of the market's host settings
|
|
8
|
+
* namespace (see `contracts/settings.ts`) registered by the plugin's node half:
|
|
9
9
|
* the registration is what makes the host 插件配置 tab serve our card, the
|
|
10
10
|
* client card binds it for state, and the node half watches it to remount
|
|
11
11
|
* servers when the switch flips. `readMcpBackend` remains only as the
|
|
@@ -16,30 +16,23 @@
|
|
|
16
16
|
import z from '@deepseek-ai/schemastery';
|
|
17
17
|
/** The MCP mount backend the market uses for suite servers. */
|
|
18
18
|
export type McpBackend = 'builtin' | 'host';
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Schema of the market settings namespace: the switches this plugin's config
|
|
21
|
+
* card serves, with the defaults declared to the host. The values themselves
|
|
22
|
+
* belong to {@link MARKET_SETTINGS_DEFAULTS}; this schema states them, it does
|
|
23
|
+
* not own them.
|
|
24
|
+
*/
|
|
22
25
|
export declare const MarketSettingsSchema: z<Schemastery.ObjectS<{
|
|
23
|
-
/** ON (default) = the built-in bridge with OAuth and SSE; OFF = host client compat mode. */
|
|
24
26
|
mcpEnhanced: z<boolean, boolean>;
|
|
25
|
-
/** Read native Agent layouts under the project root; OFF (default) scans configured sources only. */
|
|
26
27
|
scanProjectLayouts: z<boolean, boolean>;
|
|
27
|
-
/** Download region for GitHub acquisition; `auto` follows the interface language. */
|
|
28
28
|
downloadRegion: z<"auto" | "global" | "china", "auto" | "global" | "china">;
|
|
29
|
-
/** ON (default) = the `report_market_issue` model tool is registered; OFF = unregistered. */
|
|
30
29
|
feedbackEnabled: z<boolean, boolean>;
|
|
31
|
-
/** ON = refresh every configured source in the background; OFF (default) = never. */
|
|
32
30
|
autoUpdateSources: z<boolean, boolean>;
|
|
33
31
|
}>, Schemastery.ObjectT<{
|
|
34
|
-
/** ON (default) = the built-in bridge with OAuth and SSE; OFF = host client compat mode. */
|
|
35
32
|
mcpEnhanced: z<boolean, boolean>;
|
|
36
|
-
/** Read native Agent layouts under the project root; OFF (default) scans configured sources only. */
|
|
37
33
|
scanProjectLayouts: z<boolean, boolean>;
|
|
38
|
-
/** Download region for GitHub acquisition; `auto` follows the interface language. */
|
|
39
34
|
downloadRegion: z<"auto" | "global" | "china", "auto" | "global" | "china">;
|
|
40
|
-
/** ON (default) = the `report_market_issue` model tool is registered; OFF = unregistered. */
|
|
41
35
|
feedbackEnabled: z<boolean, boolean>;
|
|
42
|
-
/** ON = refresh every configured source in the background; OFF (default) = never. */
|
|
43
36
|
autoUpdateSources: z<boolean, boolean>;
|
|
44
37
|
}>>;
|
|
45
38
|
/** Path of the legacy persisted settings file under the plugin data root. */
|
|
@@ -12,6 +12,14 @@ import type { ReconnectConfig } from './connection.js';
|
|
|
12
12
|
import type { McpServerPolicy } from '../../model/types.js';
|
|
13
13
|
/** Default timeout for individual MCP tool calls (ms). */
|
|
14
14
|
export declare const DEFAULT_TOOL_CALL_TIMEOUT_MS = 60000;
|
|
15
|
+
/**
|
|
16
|
+
* How long one connection attempt may spend initializing (ms). A server that
|
|
17
|
+
* never answers would otherwise hold its process, transport and browser leg
|
|
18
|
+
* until the SDK's own 60-second request default expired; a working server
|
|
19
|
+
* handshakes well under a second, and a genuinely slow one can declare its own
|
|
20
|
+
* `startupTimeoutMs`.
|
|
21
|
+
*/
|
|
22
|
+
export declare const DEFAULT_STARTUP_TIMEOUT_MS = 10000;
|
|
15
23
|
/** Valid `serverName`, kept below the public tool-name budget. */
|
|
16
24
|
export declare const SERVER_NAME_PATTERN: RegExp;
|
|
17
25
|
/**
|
|
@@ -1,55 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The host seams the self-built MCP client consumes, re-exported from the
|
|
3
|
+
* packages that own them.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* These are small pure functions and constants, but each one encodes a rule
|
|
6
|
+
* this plugin must obey rather than a choice it gets to make: which credential
|
|
7
|
+
* keys the host accepts, how long a timer may be, which environment names never
|
|
8
|
+
* reach a child process, and which image failures a caller can correct. Reading
|
|
9
|
+
* them from the host keeps one owner per rule, so a host change reaches this
|
|
10
|
+
* plugin instead of leaving a copy behind.
|
|
10
11
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
12
|
+
* The OAuth provider and attachment admission reach their services through the
|
|
13
|
+
* optional `credentials` / `attachments` seams at runtime, so the service types
|
|
14
|
+
* here stay structural — only the rules are imported.
|
|
13
15
|
*
|
|
14
16
|
* @module runtime/mcp-client/host-seams
|
|
15
17
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
export
|
|
21
|
-
/** `DSH_*` environment namespace owned by the harness. */
|
|
22
|
-
export declare const DSH_ENV_PREFIX: "DSH_";
|
|
23
|
-
/**
|
|
24
|
-
* Credential-shaped environment names are NOT forwarded to MCP server child
|
|
25
|
-
* processes (the harness's own `DEEPSEEK_API_KEY`/secrets must not leak into a
|
|
26
|
-
* spawned server implicitly). Deliberately supplied env entries survive
|
|
27
|
-
* because the config's explicit env merges after the scrub.
|
|
28
|
-
*/
|
|
29
|
-
export declare const SENSITIVE_ENV_PATTERN: RegExp;
|
|
30
|
-
/**
|
|
31
|
-
* The ambient parent environment minus credential-shaped names and minus all
|
|
32
|
-
* `DSH_*` names — the canonical base every harness child starts from. `PATH`,
|
|
33
|
-
* `HOME`, locale, and proxy variables survive, so child CLIs run normally;
|
|
34
|
-
* harness identity never leaks implicitly. Both scrubs match case-insensitively:
|
|
35
|
-
* Windows environment names are case-insensitive, so a parent `dsh_*` entry
|
|
36
|
-
* would otherwise survive and read back as `$env:DSH_*` in the child.
|
|
37
|
-
* @returns a fresh environment object safe to hand to a child spawn.
|
|
38
|
-
*/
|
|
39
|
-
export declare function scrubbedParentEnv(): Record<string, string>;
|
|
40
|
-
/** A credential record key: `<scope>/<id>` with both segments in the grammar below. */
|
|
41
|
-
declare const credentialKeyBrand: unique symbol;
|
|
42
|
-
export type CredentialKey = string & {
|
|
43
|
-
readonly [credentialKeyBrand]: true;
|
|
44
|
-
};
|
|
45
|
-
/**
|
|
46
|
-
* Brand a scope and an id as a {@link CredentialKey}.
|
|
47
|
-
* @param scope - the owning plugin's registered name (here: the `mcp-auth` record scope).
|
|
48
|
-
* @param id - the plugin's own addressing unit (here: the folded serverName).
|
|
49
|
-
* @returns the branded key.
|
|
50
|
-
* @throws TypeError when either segment is not a lowercase hyphenated identifier.
|
|
51
|
-
*/
|
|
52
|
-
export declare function credentialKey(scope: string, id: string): CredentialKey;
|
|
18
|
+
import type { CredentialKey } from '@deepseek-ai/dsh-credentials';
|
|
19
|
+
import type { SaveImageAttachment } from '@deepseek-ai/dsh-attachment';
|
|
20
|
+
export { MAX_TIMER_DELAY_MS } from '@deepseek-ai/dsh-timeout';
|
|
21
|
+
export { scrubbedParentEnv } from '@deepseek-ai/dsh-subprocess';
|
|
22
|
+
export { credentialKey, type CredentialKey } from '@deepseek-ai/dsh-credentials';
|
|
53
23
|
/**
|
|
54
24
|
* Structural mirror of the host `CredentialProvider` record surface the OAuth
|
|
55
25
|
* provider needs. Typed structurally because the store arrives via the
|
|
@@ -64,26 +34,12 @@ export interface CredentialRecordStore {
|
|
|
64
34
|
readRecord(key: CredentialKey): Promise<unknown>;
|
|
65
35
|
modifyRecord(key: CredentialKey, mutate: (current: unknown) => Promise<unknown>): Promise<unknown>;
|
|
66
36
|
}
|
|
37
|
+
export { isImageAdmissionError, type ImageMediaType, type SaveImageAttachment } from '@deepseek-ai/dsh-attachment';
|
|
67
38
|
/**
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*/
|
|
72
|
-
export declare function isImageAdmissionError(error: unknown): boolean;
|
|
73
|
-
/** Raster formats supported by the durable attachment vocabulary. */
|
|
74
|
-
export type ImageMediaType = 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif';
|
|
75
|
-
/** One decoded image handed to the host attachment store. */
|
|
76
|
-
export interface SaveImageAttachment {
|
|
77
|
-
data: Buffer;
|
|
78
|
-
mediaType: ImageMediaType;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Structural mirror of the host `AttachmentStore.saveImages` surface. The
|
|
82
|
-
* returned refs are opaque host values that ride inside `ContentBlock`
|
|
83
|
-
* image blocks; typed `unknown` here and narrowed by the model content
|
|
84
|
-
* contract at the projection site.
|
|
39
|
+
* Structural mirror of the host attachment store surface this plugin writes
|
|
40
|
+
* through. The service is resolved off the tool host at call time, so its
|
|
41
|
+
* concrete class is deliberately not imported.
|
|
85
42
|
*/
|
|
86
43
|
export interface AttachmentStoreLike {
|
|
87
44
|
saveImages(images: readonly SaveImageAttachment[]): Promise<readonly unknown[]>;
|
|
88
45
|
}
|
|
89
|
-
export {};
|
|
@@ -4,7 +4,7 @@ import type { Catalog } from '../application/catalog.js';
|
|
|
4
4
|
import type { HostTranslate } from './host-locale.js';
|
|
5
5
|
import type { Suite } from '../model/types.js';
|
|
6
6
|
/** Mount under existing and newly created agents; the caller owns refresh and teardown. */
|
|
7
|
-
export declare function mountProjectCommands(ctx: Context, catalog: Catalog, t: HostTranslate): {
|
|
7
|
+
export declare function mountProjectCommands(ctx: Context, catalog: Catalog, t: HostTranslate, dataRoot?: string): {
|
|
8
8
|
refresh(): Promise<void>;
|
|
9
9
|
dispose(): Promise<void>;
|
|
10
10
|
};
|
|
@@ -19,11 +19,18 @@ export declare function mountProjectHooks(ctx: Context, catalog: Catalog): {
|
|
|
19
19
|
dispose(): Promise<void>;
|
|
20
20
|
};
|
|
21
21
|
/** Kimi's startup skill and system-prompt declarations use the existing scoped prompt service. */
|
|
22
|
-
export declare function mountSuiteInstructions(ctx: Context, catalog: Catalog): {
|
|
22
|
+
export declare function mountSuiteInstructions(ctx: Context, catalog: Catalog, dataRoot?: string): {
|
|
23
23
|
refresh(): Promise<void>;
|
|
24
24
|
dispose(): Promise<void>;
|
|
25
25
|
};
|
|
26
|
-
|
|
26
|
+
/** Runtime paths one instruction pass can resolve; a variable without one stays verbatim. */
|
|
27
|
+
export interface SuiteInstructionPaths {
|
|
28
|
+
/** Plugin storage root holding each suite's `${PLUGIN_DATA}` directory. */
|
|
29
|
+
dataRoot?: string;
|
|
30
|
+
/** Directory of the session the instructions are injected into. */
|
|
31
|
+
projectDir?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare function suiteInstructions(suites: readonly Suite[], paths?: SuiteInstructionPaths): Promise<{
|
|
27
34
|
text: string;
|
|
28
35
|
errors: Array<{
|
|
29
36
|
suiteId: string;
|
|
@@ -28,7 +28,7 @@ export declare class ReconcileScheduler {
|
|
|
28
28
|
private requested;
|
|
29
29
|
private pass;
|
|
30
30
|
private readonly pendingCredentialRefs;
|
|
31
|
-
private credentialFlush;
|
|
31
|
+
private readonly credentialFlush;
|
|
32
32
|
private readonly releaseCredentialUpdates;
|
|
33
33
|
constructor(ctx: Context, runtime: RuntimeReconciler, host: ReconcileHost);
|
|
34
34
|
/** Reconcile now, joining the pass in flight and remembering one follow-up for it. */
|