dsh-system-prompt-insertion 0.0.1 → 0.2.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/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +174 -2
- package/cordis.patch.yml +18 -0
- package/lib/client.js +1414 -0
- package/lib/index.d.ts +324 -0
- package/lib/index.js +902 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +95 -4
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import Schema from "@deepseek-ai/schemastery";
|
|
2
|
+
import { Context } from "@deepseek-ai/cordis";
|
|
3
|
+
/**
|
|
4
|
+
* The data model this plugin persists.
|
|
5
|
+
*
|
|
6
|
+
* ## One source of truth
|
|
7
|
+
*
|
|
8
|
+
* Everything the model sees comes from one JSON file
|
|
9
|
+
* (`$DSH_HOME/system-prompt-insertion.json`). The profile row's `config` only carries
|
|
10
|
+
* deployment-level switches (master switch, file override, soft size cap) — never
|
|
11
|
+
* prompt text — so there is exactly one place a section can be edited, and the
|
|
12
|
+
* Web editor and a hand-edited file cannot disagree.
|
|
13
|
+
*
|
|
14
|
+
* @module dsh-system-prompt-insertion/types
|
|
15
|
+
*/
|
|
16
|
+
/** Where a section lands inside the assembled system prompt. */
|
|
17
|
+
export declare const POSITIONS: readonly ['head', 'body', 'tail'];
|
|
18
|
+
/** A placement band, resolved to a concrete `order` at registration time. */
|
|
19
|
+
type Position = (typeof POSITIONS)[number];
|
|
20
|
+
/** One user-owned prompt section. */
|
|
21
|
+
interface SectionSpec {
|
|
22
|
+
/** Stable identifier; also part of the registered section name. */
|
|
23
|
+
id: string;
|
|
24
|
+
/** Short label shown by the editor and in diagnostics. */
|
|
25
|
+
title: string;
|
|
26
|
+
/** The text contributed to the system prompt. */
|
|
27
|
+
text: string;
|
|
28
|
+
/** Placement band; ignored when {@link order} is set. */
|
|
29
|
+
position: Position;
|
|
30
|
+
/** Explicit `order` override, or `null` to follow {@link position}. */
|
|
31
|
+
order: number | null;
|
|
32
|
+
/** Whether this section is contributed at all. */
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
/** Whether `{{variable}}` references resolve (false keeps the text literal). */
|
|
35
|
+
interpolate: boolean;
|
|
36
|
+
}
|
|
37
|
+
/** The whole persisted state. */
|
|
38
|
+
interface LayerState {
|
|
39
|
+
/** Store format version; bumped only with a migration. */
|
|
40
|
+
version: 1;
|
|
41
|
+
/** Plugin-wide kill switch, editable from the UI. */
|
|
42
|
+
enabled: boolean;
|
|
43
|
+
/** Sections in editor order; the array order breaks ties inside one band. */
|
|
44
|
+
sections: SectionSpec[];
|
|
45
|
+
}
|
|
46
|
+
/** A section id: lowercase alphanumerics and dashes, long enough to be unique. */
|
|
47
|
+
export declare const SECTION_ID: RegExp;
|
|
48
|
+
/** Section-name prefix; also how the preview tells our sections apart. */
|
|
49
|
+
export declare const SECTION_PREFIX: string;
|
|
50
|
+
/** Upper bound on a stored section text, in UTF-8 bytes. */
|
|
51
|
+
export declare const MAX_TEXT_BYTES: number;
|
|
52
|
+
/** Upper bound on stored sections; the editor warns instead of silently dropping. */
|
|
53
|
+
export declare const MAX_SECTIONS: number;
|
|
54
|
+
/** The empty state a fresh install starts from. */
|
|
55
|
+
export declare function emptyState(): LayerState;
|
|
56
|
+
/** Thrown when a state document cannot be accepted. */
|
|
57
|
+
export declare class StateValidationError extends Error {
|
|
58
|
+
readonly path: string;
|
|
59
|
+
constructor(path: string, message: string);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Validate and normalize one stored state document.
|
|
63
|
+
*
|
|
64
|
+
* Unknown keys inside a section are rejected rather than dropped: a section whose
|
|
65
|
+
* field was renamed by a future version must fail loudly instead of silently
|
|
66
|
+
* losing configuration.
|
|
67
|
+
*
|
|
68
|
+
* @param input - the parsed JSON value.
|
|
69
|
+
* @returns a fresh, fully normalized state.
|
|
70
|
+
* @throws StateValidationError when the document is not acceptable.
|
|
71
|
+
*/
|
|
72
|
+
export declare function normalizeState(input: unknown): LayerState;
|
|
73
|
+
/** The logging surface this module needs (a subset of `ctx.logger`). */
|
|
74
|
+
interface StoreLogger {
|
|
75
|
+
info(message: string): void;
|
|
76
|
+
warn(message: string): void;
|
|
77
|
+
error(message: string): void;
|
|
78
|
+
}
|
|
79
|
+
/** Where the current state came from, for the UI's status line. */
|
|
80
|
+
type StoreSource = 'memory' | 'file' | 'missing' | 'unreadable';
|
|
81
|
+
/** Constructor options. */
|
|
82
|
+
interface PromptStoreOptions {
|
|
83
|
+
/** Absolute path of the JSON document. */
|
|
84
|
+
path: string;
|
|
85
|
+
/** Logger used for load/save diagnostics. */
|
|
86
|
+
logger: StoreLogger;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Render a path for the UI without leaking a machine-specific home directory.
|
|
90
|
+
*
|
|
91
|
+
* @param path - absolute path.
|
|
92
|
+
* @returns `~/.dsh/...` for paths under the default home, `$DSH_HOME/...` for a
|
|
93
|
+
* configured one, and the path unchanged otherwise.
|
|
94
|
+
*/
|
|
95
|
+
export declare function displayPath(path: string): string;
|
|
96
|
+
/** The section store. */
|
|
97
|
+
export declare class PromptStore {
|
|
98
|
+
private readonly path;
|
|
99
|
+
private readonly logger;
|
|
100
|
+
private state;
|
|
101
|
+
private stamp;
|
|
102
|
+
private source;
|
|
103
|
+
private error;
|
|
104
|
+
private loaded;
|
|
105
|
+
constructor(options: PromptStoreOptions);
|
|
106
|
+
/** Absolute path of the JSON document. */
|
|
107
|
+
file(): string;
|
|
108
|
+
/** Display form of {@link file} for user-facing text. */
|
|
109
|
+
displayPath(): string;
|
|
110
|
+
/** Where the current state came from. */
|
|
111
|
+
origin(): StoreSource;
|
|
112
|
+
/** The last load or parse error, if the file could not be read. */
|
|
113
|
+
lastError(): string | undefined;
|
|
114
|
+
/**
|
|
115
|
+
* The current state, re-reading the file when it changed on disk.
|
|
116
|
+
*
|
|
117
|
+
* @returns a frozen view; callers must not mutate it.
|
|
118
|
+
*/
|
|
119
|
+
current(): LayerState;
|
|
120
|
+
/**
|
|
121
|
+
* Validate, persist, and publish a new state.
|
|
122
|
+
*
|
|
123
|
+
* @param input - the candidate state (already parsed JSON).
|
|
124
|
+
* @returns the normalized state that was stored.
|
|
125
|
+
* @throws StateValidationError when the candidate is not acceptable.
|
|
126
|
+
*/
|
|
127
|
+
save(input: unknown): LayerState;
|
|
128
|
+
/** Re-read the file. A failed read keeps the previous state live. */
|
|
129
|
+
private reload;
|
|
130
|
+
}
|
|
131
|
+
/** First order inside the `head` band — right after the persona prefix. */
|
|
132
|
+
export declare const HEAD_BASE = 10;
|
|
133
|
+
/** First order inside the `body` band — after every tool guidance section. */
|
|
134
|
+
export declare const BODY_BASE = 5100;
|
|
135
|
+
/** Distance kept above the host's own last section. */
|
|
136
|
+
export declare const TAIL_GAP = 300;
|
|
137
|
+
/** Spacing between two sections of the same band. */
|
|
138
|
+
export declare const SECTION_STEP = 10;
|
|
139
|
+
/** Fallback for the host's last built-in section order (`DEPLOYMENT_PERSONA_SUFFIX`). */
|
|
140
|
+
export declare const FALLBACK_TAIL_BASE = 10200;
|
|
141
|
+
/** The band bases resolved once per load. */
|
|
142
|
+
interface OrderBases {
|
|
143
|
+
/** Order of the host's `deployment:persona-suffix` section. */
|
|
144
|
+
tailBase: number;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Resolve the concrete order of one section.
|
|
148
|
+
*
|
|
149
|
+
* @param section - the stored section.
|
|
150
|
+
* @param ordinal - its index among ALL sections of the same band, in editor
|
|
151
|
+
* order. Disabled and empty entries keep their slot, so switching one off does
|
|
152
|
+
* not renumber its neighbours.
|
|
153
|
+
* @param bases - the band bases for this load.
|
|
154
|
+
* @returns the order to register.
|
|
155
|
+
*/
|
|
156
|
+
export declare function resolveSectionOrder(section: SectionSpec, ordinal: number, bases: OrderBases): number;
|
|
157
|
+
/**
|
|
158
|
+
* Plan the registrations for one state: which sections are contributed, under
|
|
159
|
+
* which name and at which order.
|
|
160
|
+
*
|
|
161
|
+
* @param state - the stored state.
|
|
162
|
+
* @param bases - the band bases for this load.
|
|
163
|
+
* @param prefix - registered-name prefix (`user:system-prompt-insertion:` by default).
|
|
164
|
+
* @returns one plan per ENABLED, non-empty section, in editor order.
|
|
165
|
+
*/
|
|
166
|
+
export declare function planRegistrations(state: LayerState, bases: OrderBases, prefix: string): Array<{
|
|
167
|
+
section: SectionSpec;
|
|
168
|
+
name: string;
|
|
169
|
+
order: number;
|
|
170
|
+
}>;
|
|
171
|
+
/** Read the host's own last built-in section order at runtime. */
|
|
172
|
+
export declare function resolveOrderBases(ctx: Context): OrderBases;
|
|
173
|
+
/** Diagnostics surface (a subset of `ctx.logger`). */
|
|
174
|
+
type RegistrarLogger = StoreLogger;
|
|
175
|
+
/** Owns the registered sections of one plugin instance. */
|
|
176
|
+
export declare class SectionRegistrar {
|
|
177
|
+
private readonly ctx;
|
|
178
|
+
private readonly store;
|
|
179
|
+
private readonly logger;
|
|
180
|
+
private readonly prefix;
|
|
181
|
+
private disposers;
|
|
182
|
+
private names;
|
|
183
|
+
private orderByName;
|
|
184
|
+
private bases;
|
|
185
|
+
constructor(ctx: Context, store: PromptStore, logger: RegistrarLogger, prefix?: string);
|
|
186
|
+
/** The band bases currently in use (also reported to the preview). */
|
|
187
|
+
orderBases(): OrderBases;
|
|
188
|
+
/** Names of the sections currently registered, for diagnostics and the preview. */
|
|
189
|
+
registeredNames(): string[];
|
|
190
|
+
/** The concrete order each registered section was placed at. */
|
|
191
|
+
registeredOrders(): ReadonlyMap<string, number>;
|
|
192
|
+
/**
|
|
193
|
+
* Rebuild the registration plan from the store.
|
|
194
|
+
*
|
|
195
|
+
* Registration is idempotent per plan: the previous plan is disposed first, so a
|
|
196
|
+
* removed section cannot linger. A section whose registration throws (a name
|
|
197
|
+
* collision with another plugin) is reported and skipped instead of taking the
|
|
198
|
+
* whole plugin down.
|
|
199
|
+
*
|
|
200
|
+
* @returns the state that was planned from.
|
|
201
|
+
*/
|
|
202
|
+
sync(): LayerState;
|
|
203
|
+
/** Dispose every registration this instance owns. */
|
|
204
|
+
dispose(): void;
|
|
205
|
+
}
|
|
206
|
+
/** One warning the editor shows above the preview. */
|
|
207
|
+
interface PreviewWarning {
|
|
208
|
+
/** Stable machine code the client localizes. */
|
|
209
|
+
code: 'hidden' | 'duplicate' | 'unknown-variable' | 'oversize' | 'empty' | 'store-error' | 'render-error' | 'preview-partial';
|
|
210
|
+
/** The section the warning is about, when it is about one. */
|
|
211
|
+
sectionId?: string;
|
|
212
|
+
/** Values the client interpolates into its own localized copy. */
|
|
213
|
+
params?: Record<string, string | number>;
|
|
214
|
+
/** English fallback for a client that does not know this code. */
|
|
215
|
+
message: string;
|
|
216
|
+
}
|
|
217
|
+
/** One section of the assembled prompt. */
|
|
218
|
+
interface PreviewSection {
|
|
219
|
+
/** Registry name. */
|
|
220
|
+
name: string;
|
|
221
|
+
/** Zero-based position in the rendered prompt. */
|
|
222
|
+
index: number;
|
|
223
|
+
/** The order this plugin registered the section at, when it is ours. */
|
|
224
|
+
order?: number;
|
|
225
|
+
/** UTF-8 size of the resolved text. */
|
|
226
|
+
bytes: number;
|
|
227
|
+
/** Whether this section came from this plugin. */
|
|
228
|
+
ours: boolean;
|
|
229
|
+
/** The resolved (probably interpolated) text. */
|
|
230
|
+
text: string;
|
|
231
|
+
}
|
|
232
|
+
/** Everything the preview panel renders. */
|
|
233
|
+
interface PreviewResult {
|
|
234
|
+
/** The rendered system prompt, or `''` when rendering failed. */
|
|
235
|
+
rendered: string;
|
|
236
|
+
/** UTF-8 size of {@link rendered}. */
|
|
237
|
+
bytes: number;
|
|
238
|
+
/** The assembly's sections in canonical order. */
|
|
239
|
+
sections: PreviewSection[];
|
|
240
|
+
/** Variables the loop registered for this assembly. */
|
|
241
|
+
variables: string[];
|
|
242
|
+
/** Warnings derived from the state and the assembly. */
|
|
243
|
+
warnings: PreviewWarning[];
|
|
244
|
+
/** Whether an effective complete-prompt section owns the assembly. */
|
|
245
|
+
complete: boolean;
|
|
246
|
+
/** Why rendering failed, when it did. */
|
|
247
|
+
renderError?: string;
|
|
248
|
+
}
|
|
249
|
+
/** The subset of host services the preview needs. */
|
|
250
|
+
interface PreviewHost {
|
|
251
|
+
ctx: Context;
|
|
252
|
+
store: PromptStore;
|
|
253
|
+
registrar: SectionRegistrar;
|
|
254
|
+
maxSectionBytes: number;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Build the preview for the current state.
|
|
258
|
+
*
|
|
259
|
+
* @param host - the store, registrar, host context and soft size cap.
|
|
260
|
+
* @returns the assembled prompt, its sections, and every warning.
|
|
261
|
+
*/
|
|
262
|
+
export declare function buildPreview(host: PreviewHost): Promise<PreviewResult>;
|
|
263
|
+
/** URL prefix of every route this plugin owns. */
|
|
264
|
+
export declare const ROUTE_PREFIX = "/dsh-system-prompt-insertion";
|
|
265
|
+
/** Largest accepted request body (the state document is small; 512 KiB is slack). */
|
|
266
|
+
export declare const MAX_BODY_BYTES: number;
|
|
267
|
+
/** Services the routes need. */
|
|
268
|
+
interface RouteDeps {
|
|
269
|
+
/** The state document. */
|
|
270
|
+
store: PromptStore;
|
|
271
|
+
/** Rebuilds the registration plan after a save. */
|
|
272
|
+
registrar: SectionRegistrar;
|
|
273
|
+
/** Produces the assembled prompt for the preview. */
|
|
274
|
+
preview(): Promise<PreviewResult>;
|
|
275
|
+
/** Logger for rejected requests. */
|
|
276
|
+
logger: StoreLogger;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Register the three routes on `ctx.webServer` when that service is present.
|
|
280
|
+
*
|
|
281
|
+
* The plugin stays fully functional without it (the host half needs only the
|
|
282
|
+
* prompt registry); a headless profile simply has no editor.
|
|
283
|
+
*
|
|
284
|
+
* @param ctx - the plugin context.
|
|
285
|
+
* @param deps - store, registrar, preview builder and logger.
|
|
286
|
+
*/
|
|
287
|
+
export declare function registerRoutes(ctx: Context, deps: RouteDeps): void;
|
|
288
|
+
/** Cordis plugin name. */
|
|
289
|
+
export declare const name = "system-prompt-insertion";
|
|
290
|
+
/** The prompt registry must exist before a section can be registered. */
|
|
291
|
+
export declare const inject: string[];
|
|
292
|
+
/** The profile row's configuration. */
|
|
293
|
+
export interface Config {
|
|
294
|
+
/** Master switch: `false` registers nothing and serves no routes. */
|
|
295
|
+
enabled: boolean;
|
|
296
|
+
/** State file override; empty uses `$DSH_HOME/system-prompt-insertion.json`. */
|
|
297
|
+
storeFile: string;
|
|
298
|
+
/** Soft per-section size cap reported by the editor. */
|
|
299
|
+
maxSectionBytes: number;
|
|
300
|
+
}
|
|
301
|
+
/** Schema for {@link Config}. */
|
|
302
|
+
export declare const Config: Schema<Config>;
|
|
303
|
+
/** Options resolved from {@link Config}. */
|
|
304
|
+
export interface ResolvedOptions {
|
|
305
|
+
/** Absolute path of the state document. */
|
|
306
|
+
storeFile: string;
|
|
307
|
+
/** Soft per-section size cap. */
|
|
308
|
+
maxSectionBytes: number;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Resolve the row configuration into absolute options.
|
|
312
|
+
*
|
|
313
|
+
* @param config - the row configuration.
|
|
314
|
+
* @returns the paths and limits the plugin runs with.
|
|
315
|
+
*/
|
|
316
|
+
export declare function resolveOptions(config: Config): ResolvedOptions;
|
|
317
|
+
/**
|
|
318
|
+
* Mount the user-owned system-prompt text and its editor.
|
|
319
|
+
*
|
|
320
|
+
* @param ctx - the profile row's context.
|
|
321
|
+
* @param config - the validated row configuration.
|
|
322
|
+
*/
|
|
323
|
+
export declare function apply(ctx: Context, config: Config): void;
|
|
324
|
+
export type { LayerState, OrderBases, Position, SectionSpec };
|