dsh-plugin-subagent-director 0.1.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.
Files changed (80) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/LICENSE +21 -0
  3. package/README.md +135 -0
  4. package/lib/bridge-contract.d.ts +41 -0
  5. package/lib/bridge-contract.d.ts.map +1 -0
  6. package/lib/bridge-contract.js +7 -0
  7. package/lib/bridge-contract.js.map +1 -0
  8. package/lib/bridge-entry.d.ts +29 -0
  9. package/lib/bridge-entry.d.ts.map +1 -0
  10. package/lib/bridge-entry.js +10 -0
  11. package/lib/bridge-entry.js.map +1 -0
  12. package/lib/client/RoleCard.d.ts +23 -0
  13. package/lib/client/RoleCard.d.ts.map +1 -0
  14. package/lib/client/RoleCard.js +72 -0
  15. package/lib/client/RoleCard.js.map +1 -0
  16. package/lib/client/SubagentModelDock.d.ts +29 -0
  17. package/lib/client/SubagentModelDock.d.ts.map +1 -0
  18. package/lib/client/SubagentModelDock.js +32 -0
  19. package/lib/client/SubagentModelDock.js.map +1 -0
  20. package/lib/client/SubagentOptionsSection.d.ts +23 -0
  21. package/lib/client/SubagentOptionsSection.d.ts.map +1 -0
  22. package/lib/client/SubagentOptionsSection.js +164 -0
  23. package/lib/client/SubagentOptionsSection.js.map +1 -0
  24. package/lib/client/index.d.ts +44 -0
  25. package/lib/client/index.d.ts.map +1 -0
  26. package/lib/client/index.js +1541 -0
  27. package/lib/client/index.js.map +1 -0
  28. package/lib/client/locales.d.ts +13 -0
  29. package/lib/client/locales.d.ts.map +1 -0
  30. package/lib/client/locales.js +107 -0
  31. package/lib/client/locales.js.map +1 -0
  32. package/lib/client/store-logic.d.ts +105 -0
  33. package/lib/client/store-logic.d.ts.map +1 -0
  34. package/lib/client/store-logic.js +143 -0
  35. package/lib/client/store-logic.js.map +1 -0
  36. package/lib/client/store.d.ts +104 -0
  37. package/lib/client/store.d.ts.map +1 -0
  38. package/lib/client/store.js +223 -0
  39. package/lib/client/store.js.map +1 -0
  40. package/lib/client/subagent-model.d.ts +47 -0
  41. package/lib/client/subagent-model.d.ts.map +1 -0
  42. package/lib/client/subagent-model.js +81 -0
  43. package/lib/client/subagent-model.js.map +1 -0
  44. package/lib/client/ui.d.ts +26 -0
  45. package/lib/client/ui.d.ts.map +1 -0
  46. package/lib/client/ui.js +102 -0
  47. package/lib/client/ui.js.map +1 -0
  48. package/lib/config.d.ts +63 -0
  49. package/lib/config.d.ts.map +1 -0
  50. package/lib/config.js +26 -0
  51. package/lib/config.js.map +1 -0
  52. package/lib/delegation-tool.d.ts +169 -0
  53. package/lib/delegation-tool.d.ts.map +1 -0
  54. package/lib/delegation-tool.js +404 -0
  55. package/lib/delegation-tool.js.map +1 -0
  56. package/lib/envelope.d.ts +97 -0
  57. package/lib/envelope.d.ts.map +1 -0
  58. package/lib/envelope.js +136 -0
  59. package/lib/envelope.js.map +1 -0
  60. package/lib/guidance.d.ts +37 -0
  61. package/lib/guidance.d.ts.map +1 -0
  62. package/lib/guidance.js +46 -0
  63. package/lib/guidance.js.map +1 -0
  64. package/lib/index.d.ts +29 -0
  65. package/lib/index.d.ts.map +1 -0
  66. package/lib/index.js +63 -0
  67. package/lib/index.js.map +1 -0
  68. package/lib/remote.d.ts +102 -0
  69. package/lib/remote.d.ts.map +1 -0
  70. package/lib/remote.js +254 -0
  71. package/lib/remote.js.map +1 -0
  72. package/lib/route-resolver.d.ts +118 -0
  73. package/lib/route-resolver.d.ts.map +1 -0
  74. package/lib/route-resolver.js +71 -0
  75. package/lib/route-resolver.js.map +1 -0
  76. package/lib/settings.d.ts +157 -0
  77. package/lib/settings.d.ts.map +1 -0
  78. package/lib/settings.js +118 -0
  79. package/lib/settings.js.map +1 -0
  80. package/package.json +110 -0
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Wire envelope parsing/validation/response helpers for the self-published
3
+ * "/subagent-director" settings bridge (src/remote.ts). Pure, zero-dependency
4
+ * (no cordis): every function here is unit-testable in a plain node
5
+ * environment and reused verbatim by the host route handler.
6
+ *
7
+ * The wire contract mirrors the generic Connection RPC channel that the client
8
+ * already speaks (dsh-client-connection/lib/client.js:10094-10113): the browser
9
+ * POSTs a "client-request" envelope and expects a "server-response" envelope
10
+ * echoing the same rpcId with an RpcResult in the result slot. We implement the
11
+ * host side directly on a webServer prefix route (kind:"prefix",
12
+ * path:"/subagent-director") instead of via connection.rpc, so a tree-external
13
+ * plugin needs no apiproxy changes.
14
+ *
15
+ * Referenced semantics: dsh-client-connection/lib/index.js:275-300
16
+ * (rpcFetchHandler) and 322-328 (fullResponse).
17
+ */
18
+ import type { RpcResult } from '@deepseek-ai/dsh-host-apiproxy/api';
19
+ /** The rpcId the host uses for envelopes that fail top-level validation. */
20
+ export declare const INVALID_REQUEST_RPC_ID = "invalid-request";
21
+ /** Wire "client-request" envelope a browser rpc.call sends to the channel. */
22
+ export interface ClientRequestEnvelope {
23
+ type: 'client-request';
24
+ rpcId: string;
25
+ method: string;
26
+ payload: unknown;
27
+ }
28
+ /** Wire "server-response" envelope the host answers with. */
29
+ export interface ServerResponseEnvelope<T = unknown> {
30
+ type: 'server-response';
31
+ rpcId: string;
32
+ result: RpcResult<T>;
33
+ }
34
+ /** Outcome of parsing/validating a "client-request" envelope body. */
35
+ export type EnvelopeParseResult = {
36
+ ok: true;
37
+ envelope: ClientRequestEnvelope;
38
+ } | {
39
+ ok: false;
40
+ issues: string[];
41
+ };
42
+ /**
43
+ * Parse and validate a decoded JSON body as a "client-request" envelope.
44
+ * Accepts only an object whose `type` is exactly "client-request", with string
45
+ * `rpcId` and `method`. Returns a structured outcome so the caller can build
46
+ * an "invalid client-request message" bad-request response.
47
+ */
48
+ export declare function parseClientRequestEnvelope(body: unknown): EnvelopeParseResult;
49
+ /**
50
+ * Build the "server-response" envelope for the requested rpcId carrying an
51
+ * RpcResult, mirroring dsh-client-connection/lib/index.js:322-328 (fullResponse).
52
+ */
53
+ export declare function buildServerResponse<T>(rpcId: string, result: RpcResult<T>): ServerResponseEnvelope<T>;
54
+ /**
55
+ * Build the bad-request "server-response" for a malformed client-request
56
+ * envelope. The host cannot trust the caller's rpcId on a malformed message,
57
+ * so it uses the fixed INVALID_REQUEST_RPC_ID (mirroring
58
+ * invalidEnvelopeResponse in dsh-client-connection/lib/index.js:302-309).
59
+ */
60
+ export declare function buildBadRequestResponse(issues: readonly string[]): ServerResponseEnvelope;
61
+ /**
62
+ * Build the bad-request "server-response" for a message whose `method` does not
63
+ * match the path-derived endpoint (mirroring
64
+ * dsh-client-connection/lib/index.js:289-293).
65
+ */
66
+ export declare function buildMethodMismatchResponse(rpcId: string, method: unknown, endpoint: string): ServerResponseEnvelope;
67
+ /**
68
+ * Whether a WHATWG URL hostname names the local loopback authority.
69
+ * Accepts "localhost", the IPv6 loopback literal "[::1]" (brackets retained, as
70
+ * WHATWG URL hostname does), or any IPv4 address in the 127/8 range. Rejects
71
+ * everything else. Mirrors the client-connection predicate
72
+ * (dsh-client-connection/lib/client.js:10135-10139).
73
+ */
74
+ export declare function isLoopbackHostname(hostname: string): boolean;
75
+ /**
76
+ * Classify a raw "Host" request header as loopback. Strips a port suffix and
77
+ * bracket-normalizes the authority before delegating to
78
+ * {@link isLoopbackHostname}. With no port present the header is treated as a
79
+ * bare hostname.
80
+ */
81
+ export declare function isLoopbackHost(rawHost: string): boolean;
82
+ /**
83
+ * Derive the endpoint segment from a pathname under the channel prefix.
84
+ * Returns undefined when the path is not "<channel>/<single-valid-segment>",
85
+ * mirroring the endpointFromPath semantics in
86
+ * dsh-client-connection/lib/index.js:310-315 but without a global pattern
87
+ * import. A valid endpoint is one non-empty segment with no "/", "." or ".."
88
+ * traversal segments.
89
+ */
90
+ export declare function endpointFromPath(channel: string, pathname: string): string | undefined;
91
+ /**
92
+ * The absolute path our bridge owns on the Host web server. Kept here (rather
93
+ * than only in bridge-contract) so the pure helpers and route handler share one
94
+ * literal.
95
+ */
96
+ export declare const SUBAGENT_DIRECTOR_ROUTE_PATH = "/subagent-director";
97
+ //# sourceMappingURL=envelope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAEV,SAAS,EACV,MAAM,oCAAoC,CAAC;AAE5C,4EAA4E;AAC5E,eAAO,MAAM,sBAAsB,oBAAoB,CAAC;AAExD,8EAA8E;AAC9E,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,6DAA6D;AAC7D,MAAM,WAAW,sBAAsB,CAAC,CAAC,GAAG,OAAO;IACjD,IAAI,EAAE,iBAAiB,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;CACtB;AAED,sEAAsE;AACtE,MAAM,MAAM,mBAAmB,GAC3B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,qBAAqB,CAAA;CAAE,GAC7C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEpC;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,OAAO,GAAG,mBAAmB,CAyB7E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAErG;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,sBAAsB,CAOzF;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,MAAM,GACf,sBAAsB,CAOxB;AAID;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQ5D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAcvD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQtF;AAED;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,uBAAuB,CAAC"}
@@ -0,0 +1,136 @@
1
+ /** The rpcId the host uses for envelopes that fail top-level validation. */
2
+ export const INVALID_REQUEST_RPC_ID = 'invalid-request';
3
+ /**
4
+ * Parse and validate a decoded JSON body as a "client-request" envelope.
5
+ * Accepts only an object whose `type` is exactly "client-request", with string
6
+ * `rpcId` and `method`. Returns a structured outcome so the caller can build
7
+ * an "invalid client-request message" bad-request response.
8
+ */
9
+ export function parseClientRequestEnvelope(body) {
10
+ if (body === null || typeof body !== 'object' || Array.isArray(body)) {
11
+ return { ok: false, issues: ['body must be a JSON object'] };
12
+ }
13
+ const record = body;
14
+ const issues = [];
15
+ if (record.type !== 'client-request') {
16
+ issues.push('type must equal "client-request"');
17
+ }
18
+ if (typeof record.rpcId !== 'string') {
19
+ issues.push('rpcId must be a string');
20
+ }
21
+ if (typeof record.method !== 'string') {
22
+ issues.push('method must be a string');
23
+ }
24
+ if (issues.length > 0)
25
+ return { ok: false, issues };
26
+ return {
27
+ ok: true,
28
+ envelope: {
29
+ type: 'client-request',
30
+ rpcId: record.rpcId,
31
+ method: record.method,
32
+ payload: record.payload,
33
+ },
34
+ };
35
+ }
36
+ /**
37
+ * Build the "server-response" envelope for the requested rpcId carrying an
38
+ * RpcResult, mirroring dsh-client-connection/lib/index.js:322-328 (fullResponse).
39
+ */
40
+ export function buildServerResponse(rpcId, result) {
41
+ return { type: 'server-response', rpcId, result };
42
+ }
43
+ /**
44
+ * Build the bad-request "server-response" for a malformed client-request
45
+ * envelope. The host cannot trust the caller's rpcId on a malformed message,
46
+ * so it uses the fixed INVALID_REQUEST_RPC_ID (mirroring
47
+ * invalidEnvelopeResponse in dsh-client-connection/lib/index.js:302-309).
48
+ */
49
+ export function buildBadRequestResponse(issues) {
50
+ const error = {
51
+ code: 'bad-request',
52
+ message: 'invalid client-request message',
53
+ details: { issues: [] },
54
+ };
55
+ return buildServerResponse(INVALID_REQUEST_RPC_ID, { ok: false, error });
56
+ }
57
+ /**
58
+ * Build the bad-request "server-response" for a message whose `method` does not
59
+ * match the path-derived endpoint (mirroring
60
+ * dsh-client-connection/lib/index.js:289-293).
61
+ */
62
+ export function buildMethodMismatchResponse(rpcId, method, endpoint) {
63
+ const error = {
64
+ code: 'bad-request',
65
+ message: 'method ' + JSON.stringify(method) + ' does not match endpoint ' + JSON.stringify(endpoint),
66
+ details: { issues: [] },
67
+ };
68
+ return buildServerResponse(rpcId, { ok: false, error });
69
+ }
70
+ const IPV4_OCTET = /^\d{1,3}$/;
71
+ /**
72
+ * Whether a WHATWG URL hostname names the local loopback authority.
73
+ * Accepts "localhost", the IPv6 loopback literal "[::1]" (brackets retained, as
74
+ * WHATWG URL hostname does), or any IPv4 address in the 127/8 range. Rejects
75
+ * everything else. Mirrors the client-connection predicate
76
+ * (dsh-client-connection/lib/client.js:10135-10139).
77
+ */
78
+ export function isLoopbackHostname(hostname) {
79
+ if (hostname === 'localhost' || hostname === '[::1]')
80
+ return true;
81
+ const parts = hostname.split('.');
82
+ return (parts.length === 4 &&
83
+ parts[0] === '127' &&
84
+ parts.every((part) => IPV4_OCTET.test(part) && Number(part) <= 255));
85
+ }
86
+ /**
87
+ * Classify a raw "Host" request header as loopback. Strips a port suffix and
88
+ * bracket-normalizes the authority before delegating to
89
+ * {@link isLoopbackHostname}. With no port present the header is treated as a
90
+ * bare hostname.
91
+ */
92
+ export function isLoopbackHost(rawHost) {
93
+ let host = rawHost.trim();
94
+ if (host.length === 0)
95
+ return false;
96
+ // IPv6 bracket literal may carry a trailing port: [::1]:3090
97
+ if (host.startsWith('[')) {
98
+ const close = host.indexOf(']');
99
+ if (close === -1)
100
+ return false;
101
+ host = host.slice(0, close + 1);
102
+ }
103
+ else {
104
+ // Split off the first colon that separates host:port (plain hostnames/IPv4).
105
+ const colon = host.indexOf(':');
106
+ if (colon !== -1)
107
+ host = host.slice(0, colon);
108
+ }
109
+ return isLoopbackHostname(host);
110
+ }
111
+ /**
112
+ * Derive the endpoint segment from a pathname under the channel prefix.
113
+ * Returns undefined when the path is not "<channel>/<single-valid-segment>",
114
+ * mirroring the endpointFromPath semantics in
115
+ * dsh-client-connection/lib/index.js:310-315 but without a global pattern
116
+ * import. A valid endpoint is one non-empty segment with no "/", "." or ".."
117
+ * traversal segments.
118
+ */
119
+ export function endpointFromPath(channel, pathname) {
120
+ if (!pathname.startsWith(channel + '/'))
121
+ return undefined;
122
+ const endpoint = pathname.slice(channel.length + 1);
123
+ if (endpoint.length === 0)
124
+ return undefined;
125
+ if (endpoint.split('/').some((segment) => segment.length === 0 || segment === '.' || segment === '..')) {
126
+ return undefined;
127
+ }
128
+ return endpoint;
129
+ }
130
+ /**
131
+ * The absolute path our bridge owns on the Host web server. Kept here (rather
132
+ * than only in bridge-contract) so the pure helpers and route handler share one
133
+ * literal.
134
+ */
135
+ export const SUBAGENT_DIRECTOR_ROUTE_PATH = '/subagent-director';
136
+ //# sourceMappingURL=envelope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.js","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Main-agent role guidance section (design section 8).
3
+ *
4
+ * Registers a system-prompt section listing the configured Subagent Director
5
+ * role templates so the main agent knows which roles exist, what each does,
6
+ * and how to delegate to one. The section order (117) sits just after
7
+ * dsh-tool-subagent's tool paragraph (116.5) to stay locally associated.
8
+ *
9
+ * Dependency handling: ctx.systemPrompt is optional. When the service is not
10
+ * mounted we skip registration entirely (zero intrusion). When it is mounted
11
+ * but there are no roles, the section text provider renders empty and
12
+ * renderPrompt drops it — the observable AC-6.1 behaviour (no roles, no
13
+ * section) while staying robust to roles appearing at runtime.
14
+ */
15
+ import type { Context } from '@deepseek-ai/cordis';
16
+ import type { SubagentDirectorSettings } from './settings.js';
17
+ /** Prompt order: just after dsh-tool-subagent's 116.5 tool section. */
18
+ export declare const GUIDANCE_SECTION_ORDER = 117;
19
+ /** Stable, unique section name (configuration changes only affect new assemblies). */
20
+ export declare const GUIDANCE_SECTION_NAME = "subagent-director:roles";
21
+ /**
22
+ * Pure projection of the role settings onto the guidance prose the main agent
23
+ * reads. Returns '' when there are no roles so the assembled section is dropped.
24
+ * @param settings - current resolved settings snapshot.
25
+ * @param toolName - the configured model-facing delegation tool name.
26
+ */
27
+ export declare function renderRolesGuidance(settings: SubagentDirectorSettings, toolName: string): string;
28
+ /**
29
+ * Register the role guidance section, or no-op when the systemPrompt service
30
+ * is absent. Evalutes roles from the live settings snapshot at each assembly.
31
+ * @param ctx - plugin context.
32
+ * @param getSettings - returns the current settings snapshot.
33
+ * @param toolName - the configured model-facing tool name.
34
+ * @returns the exact section disposer, or undefined when skipped.
35
+ */
36
+ export declare function applyGuidance(ctx: Context, getSettings: () => SubagentDirectorSettings, toolName: string): (() => void) | undefined;
37
+ //# sourceMappingURL=guidance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guidance.d.ts","sourceRoot":"","sources":["../src/guidance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAE9D,uEAAuE;AACvE,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C,sFAAsF;AACtF,eAAO,MAAM,qBAAqB,4BAA4B,CAAC;AAE/D;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,wBAAwB,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiBhG;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,OAAO,EACZ,WAAW,EAAE,MAAM,wBAAwB,EAC3C,QAAQ,EAAE,MAAM,GACf,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAQ1B"}
@@ -0,0 +1,46 @@
1
+ /** Prompt order: just after dsh-tool-subagent's 116.5 tool section. */
2
+ export const GUIDANCE_SECTION_ORDER = 117;
3
+ /** Stable, unique section name (configuration changes only affect new assemblies). */
4
+ export const GUIDANCE_SECTION_NAME = 'subagent-director:roles';
5
+ /**
6
+ * Pure projection of the role settings onto the guidance prose the main agent
7
+ * reads. Returns '' when there are no roles so the assembled section is dropped.
8
+ * @param settings - current resolved settings snapshot.
9
+ * @param toolName - the configured model-facing delegation tool name.
10
+ */
11
+ export function renderRolesGuidance(settings, toolName) {
12
+ const roles = settings.roles ?? {};
13
+ const entries = Object.entries(roles).filter(([, role]) => role !== undefined);
14
+ if (entries.length === 0)
15
+ return '';
16
+ const lines = [
17
+ 'Subagent Director roles — delegate one of these role-bound subagents when the task matches its description. Each role may bind a model; when it does, the subagent runs on that model route.',
18
+ ];
19
+ for (const [id, role] of entries) {
20
+ const bound = role.provider !== undefined && role.provider !== '' ?
21
+ role.model !== undefined && role.model !== '' ? ` (model: ${role.provider}/${role.model})` : ` (provider: ${role.provider})` :
22
+ '';
23
+ lines.push(`- ${role.displayName || id}${bound}: ${role.description}`);
24
+ lines.push(` Delegate with: ${toolName}({ role: "${id}", prompt: "..." })`);
25
+ }
26
+ return lines.join('\n');
27
+ }
28
+ /**
29
+ * Register the role guidance section, or no-op when the systemPrompt service
30
+ * is absent. Evalutes roles from the live settings snapshot at each assembly.
31
+ * @param ctx - plugin context.
32
+ * @param getSettings - returns the current settings snapshot.
33
+ * @param toolName - the configured model-facing tool name.
34
+ * @returns the exact section disposer, or undefined when skipped.
35
+ */
36
+ export function applyGuidance(ctx, getSettings, toolName) {
37
+ const systemPrompt = ctx.get('systemPrompt');
38
+ if (systemPrompt === undefined)
39
+ return undefined;
40
+ return systemPrompt.section({
41
+ name: GUIDANCE_SECTION_NAME,
42
+ order: GUIDANCE_SECTION_ORDER,
43
+ text: () => renderRolesGuidance(getSettings(), toolName),
44
+ });
45
+ }
46
+ //# sourceMappingURL=guidance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guidance.js","sourceRoot":"","sources":["../src/guidance.ts"],"names":[],"mappings":"AAiBA,uEAAuE;AACvE,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAE1C,sFAAsF;AACtF,MAAM,CAAC,MAAM,qBAAqB,GAAG,yBAAyB,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAkC,EAAE,QAAgB;IACtF,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC;IACnC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IAC/E,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEpC,MAAM,KAAK,GAAa;QACtB,8LAA8L;KAC/L,CAAC;IACF,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC;QACjC,MAAM,KAAK,GACT,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC;YACnD,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;YAC9H,EAAE,CAAC;QACP,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,WAAW,IAAI,EAAE,GAAG,KAAK,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QACvE,KAAK,CAAC,IAAI,CAAC,sBAAsB,QAAQ,aAAa,EAAE,qBAAqB,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAC3B,GAAY,EACZ,WAA2C,EAC3C,QAAgB;IAEhB,MAAM,YAAY,GAAG,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC7C,IAAI,YAAY,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACjD,OAAO,YAAY,CAAC,OAAO,CAAC;QAC1B,IAAI,EAAE,qBAAqB;QAC3B,KAAK,EAAE,sBAAsB;QAC7B,IAAI,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,WAAW,EAAE,EAAE,QAAQ,CAAC;KACzD,CAAC,CAAC;AACL,CAAC"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Subagent Director — host plugin composition entry (design section 3).
3
+ *
4
+ * Wires the settings section, the role-guidance section, and the subagent_role
5
+ * delegation tool. Reads user settings live; a deployment without a settings
6
+ * provider degrades to an empty resolved section (zero intrusion).
7
+ *
8
+ * Dependency posture: tools/subagents/llm/settings are required through inject
9
+ * (both web and headless bundles mount the settings service); systemPrompt
10
+ * remains optional and is acquired lazily so its absence does not block the
11
+ * rest. The webServer-dependent HTTP bridge lives in the separate
12
+ * \`subagent-director-bridge\` entry (src/bridge-entry.ts).
13
+ *
14
+ * Background modes: 'one-shot' defaults calls to foreground and runs background
15
+ * calls as a plain Task; 'continuable' defaults them to background via
16
+ * ctx.subagents.startContinuable() and requires the transport provider's
17
+ * prepareContinuable capability, which is validated at mount time (mirrors
18
+ * dsh-tool-subagent).
19
+ */
20
+ import type { Context } from '@deepseek-ai/cordis';
21
+ export { Config } from './config.js';
22
+ export type { DirectorConfig } from './config.js';
23
+ export { assertDelegationCapabilities, buildSubagentRequest, createDelegationParameters, createDelegationOutputSchema, createDelegationTool, DELEGATION_TOOL_PREFIX, resolveDelegationMode, renderDelegationResult, type DelegationToolArgs, type DelegationResult, type DelegationRoute, type DelegationModeDecision, type SubagentRequestParts, } from './delegation-tool.js';
24
+ export { applyGuidance, renderRolesGuidance, GUIDANCE_SECTION_ORDER, GUIDANCE_SECTION_NAME } from './guidance.js';
25
+ export { SUBAGENT_DIRECTOR_SETTINGS_NAMESPACE, SettingsSchema, validateDirectorSettings, installDirectorSettings, type RoleTemplate, type SubagentDirectorSettings, } from './settings.js';
26
+ export declare const name = "subagent-director";
27
+ export declare const inject: string[];
28
+ export declare function apply(ctx: Context, config: import('./config.js').DirectorConfig): void;
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAQnD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EACL,4BAA4B,EAC5B,oBAAoB,EACpB,0BAA0B,EAC1B,4BAA4B,EAC5B,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAClH,OAAO,EACL,oCAAoC,EACpC,cAAc,EACd,wBAAwB,EACxB,uBAAuB,EACvB,KAAK,YAAY,EACjB,KAAK,wBAAwB,GAC9B,MAAM,eAAe,CAAC;AAEvB,eAAO,MAAM,IAAI,sBAAsB,CAAC;AAExC,eAAO,MAAM,MAAM,UAA4C,CAAC;AAEhE,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,aAAa,EAAE,cAAc,QAuD/E"}
package/lib/index.js ADDED
@@ -0,0 +1,63 @@
1
+ import { assertSubagentMaxDepth } from '@deepseek-ai/dsh-subagent';
2
+ import { createDelegationTool } from './delegation-tool.js';
3
+ import { applyGuidance } from './guidance.js';
4
+ import { installDirectorSettings } from './settings.js';
5
+ export { Config } from './config.js';
6
+ export { assertDelegationCapabilities, buildSubagentRequest, createDelegationParameters, createDelegationOutputSchema, createDelegationTool, DELEGATION_TOOL_PREFIX, resolveDelegationMode, renderDelegationResult, } from './delegation-tool.js';
7
+ export { applyGuidance, renderRolesGuidance, GUIDANCE_SECTION_ORDER, GUIDANCE_SECTION_NAME } from './guidance.js';
8
+ export { SUBAGENT_DIRECTOR_SETTINGS_NAMESPACE, SettingsSchema, validateDirectorSettings, installDirectorSettings, } from './settings.js';
9
+ export const name = 'subagent-director';
10
+ export const inject = ['tools', 'subagents', 'llm', 'settings'];
11
+ export function apply(ctx, config) {
12
+ const backgroundMode = config.backgroundMode ?? 'one-shot';
13
+ const toolName = config.toolName ?? 'subagent_role';
14
+ const providerName = config.subagentProvider ?? 'spawn';
15
+ // NOTE: the /subagent-director settings bridge route is installed by the
16
+ // separate `subagent-director-bridge` plugin entry (src/bridge-entry.ts),
17
+ // which injects webServer — tree-external plugins cannot see that service
18
+ // through ctx.get(). The main entry must not touch webServer, or headless
19
+ // profiles would lose the delegation tool.
20
+ // ---- settings snapshot -------------------------------------------------
21
+ let settings = {};
22
+ installDirectorSettings(ctx, {}, {
23
+ setSource: (current) => {
24
+ settings = current();
25
+ },
26
+ onChange: () => {
27
+ // snapshot already updated by setSource; nothing further to do in M1.
28
+ },
29
+ });
30
+ const getSettings = () => settings;
31
+ // ---- role guidance ----------------------------------------------------
32
+ applyGuidance(ctx, getSettings, toolName);
33
+ // ---- delegation tool registration ------------------------------------
34
+ if (typeof config.maxDepth === 'number')
35
+ assertSubagentMaxDepth(config.maxDepth);
36
+ let disposeTool;
37
+ const mount = (provider) => {
38
+ if (typeof config.maxDepth === 'number' && !provider.capabilities.depthLimit) {
39
+ throw new Error('subagent-director: provider "' + provider.name + '" cannot enforce maxDepth (no depthLimit capability) — set maxDepth: \'provider-managed\'');
40
+ }
41
+ if (backgroundMode === 'continuable' && provider.prepareContinuable === undefined) {
42
+ throw new Error('subagent-director: provider "' + provider.name + '" does not support backgroundMode: continuable — switch the subagent provider or use backgroundMode: "one-shot"');
43
+ }
44
+ ctx.logger.info('[' + name + '] registering ' + toolName + ' on subagent transport ' + '"' + providerName + '"' + ' with backgroundMode ' + '"' + backgroundMode + '"');
45
+ disposeTool = ctx.tools.register(createDelegationTool({ ctx, config, provider, getSettings }));
46
+ };
47
+ ctx.on('subagent/provider-added', (provider) => {
48
+ if (provider.name === providerName && disposeTool === undefined)
49
+ mount(provider);
50
+ });
51
+ ctx.on('subagent/provider-removed', (name2) => {
52
+ if (name2 !== providerName || disposeTool === undefined)
53
+ return;
54
+ disposeTool();
55
+ disposeTool = undefined;
56
+ });
57
+ const present = ctx.subagents.getProvider(providerName);
58
+ if (present !== undefined)
59
+ mount(present);
60
+ else
61
+ ctx.logger.info('[' + name + '] subagent provider ' + '"' + providerName + '" not registered yet; the "' + toolName + '" tool will register when it appears');
62
+ }
63
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Subagent Director — self-published setting bridge on the Host web server
3
+ * (design fix: "namespace not exposed").
4
+ *
5
+ * The Web settings client read/writes the plugin's `subagent-director`
6
+ * namespace via a dedicated "/subagent-director" webServer prefix route instead
7
+ * of the Host apiproxy's settings.describe/mutate, which the API proxy gates
8
+ * behind its hard-coded exposedNamespaces() allowlist
9
+ * (dsh-host-apiproxy). A tree-external plugin cannot add its own namespace to
10
+ * that list, so those calls answer `settings-not-exposed`. To bypass the
11
+ * allowlist without touching apiproxy, this module self-publishes a prefix
12
+ * route (kind:"prefix", path:"/subagent-director") via `ctx.webServer.register`
13
+ * (dsh-host-webserver/lib/index.js:53-60) and reads/writes `ctx.settings`
14
+ * itself.
15
+ *
16
+ * The wire contract mirrors the settings domain slice apiproxy exposes for
17
+ * one namespace: `settingsView` returns `{ writable, view }` where `view` is a
18
+ * `SettingsNamespaceView` (redacted), and `settingsMutate` applies path ops
19
+ * with an optimistic `expectedRevision` and returns the new redacted view, or
20
+ * an error with the same `settings-conflict` / `settings-rejected` semantics so
21
+ * the existing client conflict-reload logic works unchanged. The client already
22
+ * speaks this contract unchanged (dsh-client-connection/lib/client.js:10094-10113
23
+ * and src/client/store.ts), so no client change is required.
24
+ *
25
+ * Pure mapping / wire-envelope helpers live at the top (no cordis) so they are
26
+ * unit-testable in a plain node environment. The route handler is a node:http
27
+ * (req, res) handler, mirroring the Connection channel semantics in
28
+ * dsh-client-connection/lib/index.js:275-300 and 322-328, plus a lightweight
29
+ * loopback Host fence.
30
+ */
31
+ import type { IncomingMessage, ServerResponse } from 'node:http';
32
+ import type { Context } from '@deepseek-ai/cordis';
33
+ import { SettingsConflictError, type SettingsDescriptor, type SettingsProvider } from '@deepseek-ai/dsh-settings';
34
+ import type { RpcResult, RpcError, SettingsNamespaceView, SettingsPathOpView } from '@deepseek-ai/dsh-host-apiproxy/api';
35
+ import { SettingsSchema } from './settings.js';
36
+ import { SUBAGENT_DIRECTOR_RPC_VIEW, SUBAGENT_DIRECTOR_RPC_MUTATE, type DirectorMutateRequest, type DirectorViewSuccess } from './bridge-contract.js';
37
+ import { SUBAGENT_DIRECTOR_ROUTE_PATH } from './envelope.js';
38
+ /** Wire route path the bridge owns on the Host web server. */
39
+ export { SUBAGENT_DIRECTOR_ROUTE_PATH as SUBAGENT_DIRECTOR_RPC_CHANNEL };
40
+ /** Endpoint that returns the namespace's redacted wire view. */
41
+ export { SUBAGENT_DIRECTOR_RPC_VIEW };
42
+ /** Endpoint that applies one path-op mutation. */
43
+ export { SUBAGENT_DIRECTOR_RPC_MUTATE };
44
+ /** Request payload for the settingsMutate bridge endpoint. */
45
+ export type { DirectorMutateRequest, DirectorViewSuccess };
46
+ /**
47
+ * Map one redacted settings descriptor to its wire view — mirrors apiproxy's
48
+ * `namespaceView` (dsh-host-apiproxy/lib/index.js:2385-2399) exactly, so the
49
+ * client store sees the same `SettingsNamespaceView` shape it already renders.
50
+ */
51
+ export declare function toDirectorNamespaceView(descriptor: SettingsDescriptor): SettingsNamespaceView;
52
+ /**
53
+ * Find the Subagent Director namespace in a redacted describe result and map
54
+ * it to its wire view; `undefined` when the namespace is not registered.
55
+ */
56
+ export declare function pickDirectorNamespaceView(descriptors: readonly SettingsDescriptor[]): SettingsNamespaceView | undefined;
57
+ /**
58
+ * Read the current redacted namespace view straight from the settings seam.
59
+ * Exported for reuse by tests and by the bridge handler.
60
+ */
61
+ export declare function readDirectorNamespaceView(settings: SettingsProvider): DirectorViewSuccess;
62
+ /** Build the `settings-rejected` RPC error for one seam failure. */
63
+ export declare function directorRejected(ns: string, error: unknown): RpcError;
64
+ /** Build the `settings-conflict` RPC error, mirroring apiproxy's mapping. */
65
+ export declare function directorConflict(conflict: SettingsConflictError): RpcError;
66
+ /**
67
+ * Build the ok payload for the settingsView endpoint.
68
+ * Mirrors the apiproxy `settings.describe` value minus `hasDocument` (the
69
+ * bridge does not own the document affordance; the client ignores it).
70
+ */
71
+ export declare function directorViewOk(settings: SettingsProvider): RpcResult<DirectorViewSuccess>;
72
+ /**
73
+ * Execute one path-op mutation against the settings seam and map the outcome
74
+ * to an RpcResult carrying the new redacted view (or a `settings-conflict` /
75
+ * `settings-rejected` error). Pure over the injected primitives for testing.
76
+ */
77
+ export declare function directorMutate(mutate: SettingsProvider['mutate'], describe: SettingsProvider['describe'], ns: string, ops: readonly SettingsPathOpView[], expectedRevision: number | undefined): Promise<RpcResult<SettingsNamespaceView>>;
78
+ /** Re-export the wire-envelope helpers so tests import them from one place. */
79
+ export { parseClientRequestEnvelope, isLoopbackHost, isLoopbackHostname, endpointFromPath, buildServerResponse, buildMethodMismatchResponse, buildBadRequestResponse, INVALID_REQUEST_RPC_ID, } from './envelope.js';
80
+ /**
81
+ * The node:http handler for the "/subagent-director" prefix route. Owns the
82
+ * full response lifecycle. Wire contract mirrors the generic Connection RPC
83
+ * channel (dsh-client-connection/lib/index.js:275-328):
84
+ * - non-POST → 404 "not found"
85
+ * - wrong content-type → 415
86
+ * - unparseable JSON body → 400 "body is not JSON"
87
+ * - malformed client-request envelope → 200 bad-request (fixed rpcId)
88
+ * - method vs endpoint mismatch → 200 bad-request
89
+ * - non-loopback Host header → 403 "forbidden" (lightweight trust fence)
90
+ * - dispatch error → 500 "handler failure: ..."
91
+ */
92
+ export declare function handleDirectorBridgeRequest(settings: SettingsProvider, req: IncomingMessage, res: ServerResponse): Promise<void>;
93
+ /**
94
+ * Install the Subagent Director setting bridge on the Host web server via a
95
+ * self-published prefix route. Lazy-acquires `ctx.webServer`; a deployment
96
+ * without that service (e.g. headless) logs a debug line naming the missing
97
+ * service and installs nothing. Returns a disposer.
98
+ */
99
+ export declare function installDirectorRemoteBridge(ctx: Context): () => void;
100
+ /** Convenience re-export for the namespaced schema used to document the view. */
101
+ export { SettingsSchema };
102
+ //# sourceMappingURL=remote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../src/remote.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EACL,qBAAqB,EAErB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EACV,SAAS,EACT,QAAQ,EACR,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EACL,cAAc,EAEf,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,4BAA4B,EAQ7B,MAAM,eAAe,CAAC;AAEvB,8DAA8D;AAC9D,OAAO,EAAE,4BAA4B,IAAI,6BAA6B,EAAE,CAAC;AACzE,gEAAgE;AAChE,OAAO,EAAE,0BAA0B,EAAE,CAAC;AACtC,kDAAkD;AAClD,OAAO,EAAE,4BAA4B,EAAE,CAAC;AACxC,8DAA8D;AAC9D,YAAY,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,CAAC;AAE3D;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,kBAAkB,GAAG,qBAAqB,CAc7F;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,SAAS,kBAAkB,EAAE,GACzC,qBAAqB,GAAG,SAAS,CAOnC;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,mBAAmB,CAMzF;AAED,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,QAAQ,CAMrE;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,QAAQ,CAa1E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,gBAAgB,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAEzF;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,EAClC,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,EACtC,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,SAAS,kBAAkB,EAAE,EAClC,gBAAgB,EAAE,MAAM,GAAG,SAAS,GACnC,OAAO,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC,CAwB3C;AAED,+EAA+E;AAC/E,OAAO,EACL,0BAA0B,EAC1B,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,2BAA2B,EAC3B,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,eAAe,CAAC;AAEvB;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,gBAAgB,EAC1B,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,IAAI,CAAC,CAEf;AAqFD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,IAAI,CA2BpE;AAiCD,iFAAiF;AACjF,OAAO,EAAE,cAAc,EAAE,CAAC"}