dsh-a2a-server 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.
- package/LICENSE +21 -0
- package/README.md +335 -0
- package/README.zh-CN.md +316 -0
- package/cordis.patch.yml +30 -0
- package/lib/config.d.ts +116 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +110 -0
- package/lib/config.js.map +1 -0
- package/lib/contexts.d.ts +84 -0
- package/lib/contexts.d.ts.map +1 -0
- package/lib/contexts.js +103 -0
- package/lib/contexts.js.map +1 -0
- package/lib/index.d.ts +33 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +505 -0
- package/lib/index.js.map +1 -0
- package/lib/projection.d.ts +131 -0
- package/lib/projection.d.ts.map +1 -0
- package/lib/projection.js +98 -0
- package/lib/projection.js.map +1 -0
- package/lib/protocol/brand.d.ts +32 -0
- package/lib/protocol/brand.d.ts.map +1 -0
- package/lib/protocol/brand.js +25 -0
- package/lib/protocol/brand.js.map +1 -0
- package/lib/protocol/card.d.ts +43 -0
- package/lib/protocol/card.d.ts.map +1 -0
- package/lib/protocol/card.js +58 -0
- package/lib/protocol/card.js.map +1 -0
- package/lib/protocol/index.d.ts +23 -0
- package/lib/protocol/index.d.ts.map +1 -0
- package/lib/protocol/index.js +20 -0
- package/lib/protocol/index.js.map +1 -0
- package/lib/protocol/jsonrpc.d.ts +93 -0
- package/lib/protocol/jsonrpc.d.ts.map +1 -0
- package/lib/protocol/jsonrpc.js +81 -0
- package/lib/protocol/jsonrpc.js.map +1 -0
- package/lib/protocol/normalize.d.ts +72 -0
- package/lib/protocol/normalize.d.ts.map +1 -0
- package/lib/protocol/normalize.js +278 -0
- package/lib/protocol/normalize.js.map +1 -0
- package/lib/protocol/sse.d.ts +20 -0
- package/lib/protocol/sse.d.ts.map +1 -0
- package/lib/protocol/sse.js +23 -0
- package/lib/protocol/sse.js.map +1 -0
- package/lib/protocol/wire.d.ts +164 -0
- package/lib/protocol/wire.d.ts.map +1 -0
- package/lib/protocol/wire.js +26 -0
- package/lib/protocol/wire.js.map +1 -0
- package/lib/router.d.ts +56 -0
- package/lib/router.d.ts.map +1 -0
- package/lib/router.js +432 -0
- package/lib/router.js.map +1 -0
- package/lib/security.d.ts +89 -0
- package/lib/security.d.ts.map +1 -0
- package/lib/security.js +171 -0
- package/lib/security.js.map +1 -0
- package/lib/tasks.d.ts +75 -0
- package/lib/tasks.d.ts.map +1 -0
- package/lib/tasks.js +84 -0
- package/lib/tasks.js.map +1 -0
- package/lib/types.d.ts +71 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +17 -0
- package/lib/types.js.map +1 -0
- package/package.json +94 -0
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# The layer this bundle contributes when a profile lists it.
|
|
2
|
+
#
|
|
3
|
+
# `isolation.workspaceRoot` has no safe default and must be supplied, and an
|
|
4
|
+
# empty `peers` table means every request is answered 401 — both deliberate, so
|
|
5
|
+
# an unconfigured install exposes nothing.
|
|
6
|
+
#
|
|
7
|
+
# REQUIRES ctx.webServer, which ships in `dsh-web-app`, NOT in `dsh-base`. On a
|
|
8
|
+
# profile without it this row loads but stays PENDING (Cordis holds a plugin
|
|
9
|
+
# whose injected services are absent), so nothing serves and nothing errors.
|
|
10
|
+
- insert:
|
|
11
|
+
- id: a2a-server
|
|
12
|
+
name: dsh-a2a-server
|
|
13
|
+
config:
|
|
14
|
+
basePath: /a2a
|
|
15
|
+
protocolVersion: '0.3.0'
|
|
16
|
+
card:
|
|
17
|
+
name: dsh-harness
|
|
18
|
+
description: A DeepSeek Harness agent reachable over A2A.
|
|
19
|
+
public: true
|
|
20
|
+
skills: []
|
|
21
|
+
peers: {}
|
|
22
|
+
isolation:
|
|
23
|
+
# Default posture is isolation: each peer gets its own working
|
|
24
|
+
# directory, which also makes the cwd-equality authority in
|
|
25
|
+
# cross-session tooling separate peers for free. A deployment whose
|
|
26
|
+
# peers collaborate on one repository must say so explicitly.
|
|
27
|
+
workspaceMode: per-peer
|
|
28
|
+
workspaceRoot: !!js `${process.env.DSH_HOME ?? process.env.HOME}/a2a-workspaces`
|
|
29
|
+
push:
|
|
30
|
+
enabled: false
|
package/lib/config.d.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin configuration schema.
|
|
3
|
+
*
|
|
4
|
+
* Every credential-shaped field carries a REFERENCE name resolved through
|
|
5
|
+
* `ctx.credentials`, never a value — the doctrine `dsh-credentials` states as
|
|
6
|
+
* "configuration carries references to secrets, never the secrets". A pasted
|
|
7
|
+
* token fails the POSIX-identifier check at load rather than silently becoming
|
|
8
|
+
* a reference nobody stored.
|
|
9
|
+
*
|
|
10
|
+
* @module dsh-a2a/config
|
|
11
|
+
*/
|
|
12
|
+
import Schema from '@deepseek-ai/schemastery';
|
|
13
|
+
/** One authenticated peer and where its credential lives. */
|
|
14
|
+
export interface PeerConfig {
|
|
15
|
+
/** Credential reference name, NOT the token itself. */
|
|
16
|
+
tokenEnv: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* How peers are kept from reaching each other.
|
|
20
|
+
*
|
|
21
|
+
* DEFERRED — a tool deny-list (`session_search`, `session_event_search`,
|
|
22
|
+
* `session_trace`, `session_event_trace`, `session_event_read`, `list_agents`)
|
|
23
|
+
* plus a named `unsafeAllowCrossSessionSearch` escape hatch for single-peer
|
|
24
|
+
* deployments. Both were designed as defense in depth behind `workspaceMode`,
|
|
25
|
+
* and neither is declared here until it is enforced: a security knob that
|
|
26
|
+
* silently does nothing is worse than no knob at all.
|
|
27
|
+
*/
|
|
28
|
+
export interface IsolationConfig {
|
|
29
|
+
/**
|
|
30
|
+
* `per-peer` gives each identity its own cwd, which also makes the existing
|
|
31
|
+
* cwd-equality authority in cross-session tooling isolate them for free.
|
|
32
|
+
* `shared` is the collaborative posture and must be chosen deliberately.
|
|
33
|
+
*/
|
|
34
|
+
workspaceMode: 'per-peer' | 'shared';
|
|
35
|
+
/** Parent directory in `per-peer` mode; the common cwd in `shared` mode. */
|
|
36
|
+
workspaceRoot: string;
|
|
37
|
+
/** Per-peer cwd overrides, e.g. pointing one trusted peer at a real repo. */
|
|
38
|
+
peerWorkspaces: Record<string, string>;
|
|
39
|
+
}
|
|
40
|
+
/** Agent Card content and exposure. */
|
|
41
|
+
export interface CardConfig {
|
|
42
|
+
name: string;
|
|
43
|
+
description: string;
|
|
44
|
+
/** Serve the card without a credential, as discovery expects. */
|
|
45
|
+
public: boolean;
|
|
46
|
+
skills: {
|
|
47
|
+
id: string;
|
|
48
|
+
name: string;
|
|
49
|
+
description: string;
|
|
50
|
+
tags: string[];
|
|
51
|
+
}[];
|
|
52
|
+
provider?: {
|
|
53
|
+
organization: string;
|
|
54
|
+
url: string;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Terminal-state webhook callbacks.
|
|
59
|
+
*
|
|
60
|
+
* Only `enabled` exists so far, and only to answer the push methods with the
|
|
61
|
+
* spec's own `PushNotificationNotSupported` and to keep the Agent Card honest.
|
|
62
|
+
*
|
|
63
|
+
* DEFERRED — the sender itself, plus its SSRF fence
|
|
64
|
+
* (`allowPrivateNetworkCallbacks`, `allowInsecureCallbacks`) and
|
|
65
|
+
* `requestTimeoutMs`. Those knobs arrive with the code that honors them; a
|
|
66
|
+
* deployment must not be able to set `allowPrivateNetworkCallbacks: false` and
|
|
67
|
+
* believe something is enforcing it.
|
|
68
|
+
*/
|
|
69
|
+
export interface PushConfig {
|
|
70
|
+
/**
|
|
71
|
+
* Reserved. Turning this on today only changes which error the push methods
|
|
72
|
+
* return, so it stays documented as unimplemented.
|
|
73
|
+
*/
|
|
74
|
+
enabled: boolean;
|
|
75
|
+
}
|
|
76
|
+
/** The whole plugin configuration. */
|
|
77
|
+
export interface A2AServerConfig {
|
|
78
|
+
basePath: string;
|
|
79
|
+
publicUrl?: string;
|
|
80
|
+
protocolVersion: string;
|
|
81
|
+
/**
|
|
82
|
+
* Provider route for every agent this server creates. Optional so another
|
|
83
|
+
* `agent/request` listener may supply the target instead; a runnable
|
|
84
|
+
* composition needs one of the two.
|
|
85
|
+
*/
|
|
86
|
+
provider?: string;
|
|
87
|
+
/** Model for every agent this server creates. */
|
|
88
|
+
model?: string;
|
|
89
|
+
card: CardConfig;
|
|
90
|
+
peers: Record<string, PeerConfig>;
|
|
91
|
+
trustedPeers?: string[];
|
|
92
|
+
rateLimitPerMinute: number;
|
|
93
|
+
maxContextTurns: number;
|
|
94
|
+
sendMode: 'block' | 'immediate';
|
|
95
|
+
blockTimeoutMs: number;
|
|
96
|
+
contextIdleTtlMs: number;
|
|
97
|
+
maxResidentContexts: number;
|
|
98
|
+
isolation: IsolationConfig;
|
|
99
|
+
push: PushConfig;
|
|
100
|
+
}
|
|
101
|
+
export declare const Config: Schema<A2AServerConfig>;
|
|
102
|
+
/** A configuration mistake found before anything starts serving. */
|
|
103
|
+
export declare class A2AConfigError extends Error {
|
|
104
|
+
constructor(message: string);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Check the config's cross-field rules that a schema cannot express.
|
|
108
|
+
*
|
|
109
|
+
* Every failure here is a misconfiguration that would otherwise surface as a
|
|
110
|
+
* peer mysteriously receiving 401 forever, or as a workspace path escaping its
|
|
111
|
+
* root — both far worse than refusing to load.
|
|
112
|
+
* @param config - the validated configuration.
|
|
113
|
+
* @throws {A2AConfigError} when a peer name, credential reference, or path is unusable.
|
|
114
|
+
*/
|
|
115
|
+
export declare function assertConfigCoherent(config: A2AServerConfig): void;
|
|
116
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,MAAM,MAAM,0BAA0B,CAAA;AAQ7C,6DAA6D;AAC7D,MAAM,WAAW,UAAU;IACzB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,aAAa,EAAE,UAAU,GAAG,QAAQ,CAAA;IACpC,4EAA4E;IAC5E,aAAa,EAAE,MAAM,CAAA;IACrB,6EAA6E;IAC7E,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACvC;AAED,uCAAuC;AACvC,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,iEAAiE;IACjE,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAA;IAC3E,QAAQ,CAAC,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CACjD;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,sCAAsC;AACtC,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,eAAe,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,UAAU,CAAA;IAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IACjC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,eAAe,EAAE,MAAM,CAAA;IACvB,QAAQ,EAAE,OAAO,GAAG,WAAW,CAAA;IAC/B,cAAc,EAAE,MAAM,CAAA;IACtB,gBAAgB,EAAE,MAAM,CAAA;IACxB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,SAAS,EAAE,eAAe,CAAA;IAC1B,IAAI,EAAE,UAAU,CAAA;CACjB;AAcD,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,eAAe,CA+CzC,CAAA;AAEF,oEAAoE;AACpE,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CA4BlE"}
|
package/lib/config.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin configuration schema.
|
|
3
|
+
*
|
|
4
|
+
* Every credential-shaped field carries a REFERENCE name resolved through
|
|
5
|
+
* `ctx.credentials`, never a value — the doctrine `dsh-credentials` states as
|
|
6
|
+
* "configuration carries references to secrets, never the secrets". A pasted
|
|
7
|
+
* token fails the POSIX-identifier check at load rather than silently becoming
|
|
8
|
+
* a reference nobody stored.
|
|
9
|
+
*
|
|
10
|
+
* @module dsh-a2a/config
|
|
11
|
+
*/
|
|
12
|
+
import Schema from '@deepseek-ai/schemastery';
|
|
13
|
+
/** A credential reference name: the shape `ctx.credentials` addresses. */
|
|
14
|
+
const CREDENTIAL_REF = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
15
|
+
/** A peer name: also the workspace directory component, so no separators. */
|
|
16
|
+
const PEER_NAME = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
|
|
17
|
+
/*
|
|
18
|
+
* DEFERRED configuration, removed rather than left inert:
|
|
19
|
+
*
|
|
20
|
+
* - `streamGranularity: 'message' | 'chunk'` — streaming currently emits only
|
|
21
|
+
* committed assistant messages. The `chunk` mode needs an `assistant/chunk`
|
|
22
|
+
* subscription and a decision about retried text reaching a peer.
|
|
23
|
+
* - `taskTimeoutMs` — the orphan-task watchdog that would fail a task stuck
|
|
24
|
+
* non-terminal. Nothing sweeps for those yet.
|
|
25
|
+
*
|
|
26
|
+
* Both were in the design; neither is wired. They return with their code.
|
|
27
|
+
*/
|
|
28
|
+
export const Config = Schema.object({
|
|
29
|
+
basePath: Schema.string().default('/a2a'),
|
|
30
|
+
publicUrl: Schema.string(),
|
|
31
|
+
protocolVersion: Schema.string().default('0.3.0'),
|
|
32
|
+
provider: Schema.string(),
|
|
33
|
+
model: Schema.string(),
|
|
34
|
+
card: Schema.object({
|
|
35
|
+
name: Schema.string().default('dsh-harness'),
|
|
36
|
+
description: Schema.string().default('A DeepSeek Harness agent reachable over A2A.'),
|
|
37
|
+
public: Schema.boolean().default(true),
|
|
38
|
+
skills: Schema.array(Schema.object({
|
|
39
|
+
id: Schema.string().required(),
|
|
40
|
+
name: Schema.string().required(),
|
|
41
|
+
description: Schema.string().default(''),
|
|
42
|
+
tags: Schema.array(Schema.string()).default([]),
|
|
43
|
+
})).default([]),
|
|
44
|
+
// Both members default rather than being required: schemastery instantiates
|
|
45
|
+
// a nested object even when the deployment omits it, so a `required()` here
|
|
46
|
+
// would make an absent `provider` a validation failure.
|
|
47
|
+
provider: Schema.object({
|
|
48
|
+
organization: Schema.string().default(''),
|
|
49
|
+
url: Schema.string().default(''),
|
|
50
|
+
}),
|
|
51
|
+
}),
|
|
52
|
+
peers: Schema.dict(Schema.object({
|
|
53
|
+
tokenEnv: Schema.string().required(),
|
|
54
|
+
})).default({}),
|
|
55
|
+
trustedPeers: Schema.array(Schema.string()),
|
|
56
|
+
rateLimitPerMinute: Schema.natural().default(60),
|
|
57
|
+
maxContextTurns: Schema.natural().default(5),
|
|
58
|
+
sendMode: Schema.union(['block', 'immediate']).default('block'),
|
|
59
|
+
blockTimeoutMs: Schema.natural().default(60_000),
|
|
60
|
+
contextIdleTtlMs: Schema.natural().default(1_800_000),
|
|
61
|
+
maxResidentContexts: Schema.natural().default(64),
|
|
62
|
+
isolation: Schema.object({
|
|
63
|
+
workspaceMode: Schema.union(['per-peer', 'shared']).default('per-peer'),
|
|
64
|
+
workspaceRoot: Schema.string().required(),
|
|
65
|
+
peerWorkspaces: Schema.dict(Schema.string()).default({}),
|
|
66
|
+
}).required(),
|
|
67
|
+
push: Schema.object({
|
|
68
|
+
enabled: Schema.boolean().default(false),
|
|
69
|
+
}),
|
|
70
|
+
});
|
|
71
|
+
/** A configuration mistake found before anything starts serving. */
|
|
72
|
+
export class A2AConfigError extends Error {
|
|
73
|
+
constructor(message) {
|
|
74
|
+
super(message);
|
|
75
|
+
this.name = 'A2AConfigError';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check the config's cross-field rules that a schema cannot express.
|
|
80
|
+
*
|
|
81
|
+
* Every failure here is a misconfiguration that would otherwise surface as a
|
|
82
|
+
* peer mysteriously receiving 401 forever, or as a workspace path escaping its
|
|
83
|
+
* root — both far worse than refusing to load.
|
|
84
|
+
* @param config - the validated configuration.
|
|
85
|
+
* @throws {A2AConfigError} when a peer name, credential reference, or path is unusable.
|
|
86
|
+
*/
|
|
87
|
+
export function assertConfigCoherent(config) {
|
|
88
|
+
for (const [peer, entry] of Object.entries(config.peers)) {
|
|
89
|
+
if (!PEER_NAME.test(peer)) {
|
|
90
|
+
throw new A2AConfigError(`peer name "${peer}" must match ${String(PEER_NAME)}: it becomes a workspace directory component`);
|
|
91
|
+
}
|
|
92
|
+
if (!CREDENTIAL_REF.test(entry.tokenEnv)) {
|
|
93
|
+
throw new A2AConfigError(`peers.${peer}.tokenEnv must be a credential REFERENCE name (${String(CREDENTIAL_REF)}), not a token value`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
for (const trusted of config.trustedPeers ?? []) {
|
|
97
|
+
if (!(trusted in config.peers)) {
|
|
98
|
+
throw new A2AConfigError(`trustedPeers names "${trusted}", which is not declared in peers`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
for (const peer of Object.keys(config.isolation.peerWorkspaces)) {
|
|
102
|
+
if (!(peer in config.peers)) {
|
|
103
|
+
throw new A2AConfigError(`isolation.peerWorkspaces names "${peer}", which is not declared in peers`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (!config.basePath.startsWith('/')) {
|
|
107
|
+
throw new A2AConfigError(`basePath must start with "/": ${config.basePath}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The contextId → Activation registry and its residency policy.
|
|
3
|
+
*
|
|
4
|
+
* This is the biggest structural difference from `dsh-acp`. ACP has a stdio
|
|
5
|
+
* connection whose lifetime owns its sessions; HTTP has no connection lifetime
|
|
6
|
+
* at all, so residency must be an explicit policy. An **Activation** is one
|
|
7
|
+
* residency epoch for a contextId — the same word `ctx.subagents` uses for a
|
|
8
|
+
* continuable child's residency, and the same shape: evicting an Activation
|
|
9
|
+
* releases the AgentHandle while the durable Session stays, so the next message
|
|
10
|
+
* cold-resumes rather than starting over.
|
|
11
|
+
*
|
|
12
|
+
* @module dsh-a2a/contexts
|
|
13
|
+
*/
|
|
14
|
+
import type { Agent, AgentHandle } from '@deepseek-ai/dsh-agent';
|
|
15
|
+
import type { A2AContextId, A2ATaskId } from './protocol/index.ts';
|
|
16
|
+
import type { TaskSlot } from './tasks.ts';
|
|
17
|
+
/** One resident contextId. */
|
|
18
|
+
export interface Activation {
|
|
19
|
+
readonly contextId: A2AContextId;
|
|
20
|
+
readonly agent: Agent;
|
|
21
|
+
readonly handle: AgentHandle;
|
|
22
|
+
/** The authenticated peer that created this context. Ownership is by identity. */
|
|
23
|
+
readonly peer: string;
|
|
24
|
+
/** The resolved working directory this context's agent runs in. */
|
|
25
|
+
readonly cwd: string;
|
|
26
|
+
/** In-flight tasks, keyed by task id. FIFO order comes from the agent inbox. */
|
|
27
|
+
readonly slots: Map<A2ATaskId, TaskSlot>;
|
|
28
|
+
/** Last time a request touched this context, for idle eviction. */
|
|
29
|
+
lastTouchedAt: number;
|
|
30
|
+
}
|
|
31
|
+
/** Why a context lookup did not produce an Activation. */
|
|
32
|
+
export type LookupFailure = 'unknown' | 'forbidden';
|
|
33
|
+
/** Registry of resident contexts with LRU + idle eviction. */
|
|
34
|
+
export declare class ContextRegistry {
|
|
35
|
+
private readonly maxResident;
|
|
36
|
+
private readonly idleTtlMs;
|
|
37
|
+
private readonly now;
|
|
38
|
+
private readonly activations;
|
|
39
|
+
/**
|
|
40
|
+
* @param maxResident - hard ceiling on resident contexts.
|
|
41
|
+
* @param idleTtlMs - how long an untouched, quiet context stays resident.
|
|
42
|
+
* @param now - clock injection point for tests.
|
|
43
|
+
*/
|
|
44
|
+
constructor(maxResident: number, idleTtlMs: number, now?: () => number);
|
|
45
|
+
/** Every resident Activation, in insertion order. */
|
|
46
|
+
values(): Activation[];
|
|
47
|
+
/** How many contexts are currently resident. */
|
|
48
|
+
get size(): number;
|
|
49
|
+
/**
|
|
50
|
+
* Look up a context on behalf of an authenticated peer.
|
|
51
|
+
*
|
|
52
|
+
* A context owned by ANOTHER peer reports `forbidden`, and the caller must
|
|
53
|
+
* answer exactly as it answers `unknown` — otherwise a peer could enumerate
|
|
54
|
+
* which context ids exist by comparing the two responses.
|
|
55
|
+
* @param contextId - the id the peer presented.
|
|
56
|
+
* @param peer - the authenticated identity making the request.
|
|
57
|
+
* @returns the Activation, or why it is unavailable.
|
|
58
|
+
*/
|
|
59
|
+
lookup(contextId: A2AContextId, peer: string): Activation | LookupFailure;
|
|
60
|
+
/**
|
|
61
|
+
* Register a freshly created or resumed Activation.
|
|
62
|
+
* @param activation - the Activation to hold.
|
|
63
|
+
*/
|
|
64
|
+
add(activation: Activation): void;
|
|
65
|
+
/**
|
|
66
|
+
* Remove an Activation from the registry without disposing it.
|
|
67
|
+
* @param contextId - the context to forget.
|
|
68
|
+
* @returns the removed Activation, if it was resident.
|
|
69
|
+
*/
|
|
70
|
+
remove(contextId: A2AContextId): Activation | undefined;
|
|
71
|
+
/** Forget every Activation and return them for the caller to dispose. */
|
|
72
|
+
drain(): Activation[];
|
|
73
|
+
/**
|
|
74
|
+
* Select Activations that may be evicted right now.
|
|
75
|
+
*
|
|
76
|
+
* An Activation is evictable only when nothing is owed: no in-flight task and
|
|
77
|
+
* no recent touch. A context over the resident ceiling is evicted by least
|
|
78
|
+
* recent touch — but a busy context is NEVER evicted to make room, because
|
|
79
|
+
* dropping work a peer is waiting on is worse than exceeding a soft ceiling.
|
|
80
|
+
* @returns Activations the caller should dispose and remove.
|
|
81
|
+
*/
|
|
82
|
+
evictable(): Activation[];
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=contexts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contexts.d.ts","sourceRoot":"","sources":["../src/contexts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE1C,8BAA8B;AAC9B,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAA;IAChC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,kFAAkF;IAClF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,mEAAmE;IACnE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IACxC,mEAAmE;IACnE,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,0DAA0D;AAC1D,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,WAAW,CAAA;AAEnD,8DAA8D;AAC9D,qBAAa,eAAe;IASxB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG;IAVtB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAsC;IAElE;;;;OAIG;gBAEgB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,MAAM,MAAiB;IAG/C,qDAAqD;IACrD,MAAM,IAAI,UAAU,EAAE;IAItB,gDAAgD;IAChD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,aAAa;IAQzE;;;OAGG;IACH,GAAG,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAIjC;;;;OAIG;IACH,MAAM,CAAC,SAAS,EAAE,YAAY,GAAG,UAAU,GAAG,SAAS;IAMvD,yEAAyE;IACzE,KAAK,IAAI,UAAU,EAAE;IAMrB;;;;;;;;OAQG;IACH,SAAS,IAAI,UAAU,EAAE;CAa1B"}
|
package/lib/contexts.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The contextId → Activation registry and its residency policy.
|
|
3
|
+
*
|
|
4
|
+
* This is the biggest structural difference from `dsh-acp`. ACP has a stdio
|
|
5
|
+
* connection whose lifetime owns its sessions; HTTP has no connection lifetime
|
|
6
|
+
* at all, so residency must be an explicit policy. An **Activation** is one
|
|
7
|
+
* residency epoch for a contextId — the same word `ctx.subagents` uses for a
|
|
8
|
+
* continuable child's residency, and the same shape: evicting an Activation
|
|
9
|
+
* releases the AgentHandle while the durable Session stays, so the next message
|
|
10
|
+
* cold-resumes rather than starting over.
|
|
11
|
+
*
|
|
12
|
+
* @module dsh-a2a/contexts
|
|
13
|
+
*/
|
|
14
|
+
/** Registry of resident contexts with LRU + idle eviction. */
|
|
15
|
+
export class ContextRegistry {
|
|
16
|
+
maxResident;
|
|
17
|
+
idleTtlMs;
|
|
18
|
+
now;
|
|
19
|
+
activations = new Map();
|
|
20
|
+
/**
|
|
21
|
+
* @param maxResident - hard ceiling on resident contexts.
|
|
22
|
+
* @param idleTtlMs - how long an untouched, quiet context stays resident.
|
|
23
|
+
* @param now - clock injection point for tests.
|
|
24
|
+
*/
|
|
25
|
+
constructor(maxResident, idleTtlMs, now = Date.now) {
|
|
26
|
+
this.maxResident = maxResident;
|
|
27
|
+
this.idleTtlMs = idleTtlMs;
|
|
28
|
+
this.now = now;
|
|
29
|
+
}
|
|
30
|
+
/** Every resident Activation, in insertion order. */
|
|
31
|
+
values() {
|
|
32
|
+
return [...this.activations.values()];
|
|
33
|
+
}
|
|
34
|
+
/** How many contexts are currently resident. */
|
|
35
|
+
get size() {
|
|
36
|
+
return this.activations.size;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Look up a context on behalf of an authenticated peer.
|
|
40
|
+
*
|
|
41
|
+
* A context owned by ANOTHER peer reports `forbidden`, and the caller must
|
|
42
|
+
* answer exactly as it answers `unknown` — otherwise a peer could enumerate
|
|
43
|
+
* which context ids exist by comparing the two responses.
|
|
44
|
+
* @param contextId - the id the peer presented.
|
|
45
|
+
* @param peer - the authenticated identity making the request.
|
|
46
|
+
* @returns the Activation, or why it is unavailable.
|
|
47
|
+
*/
|
|
48
|
+
lookup(contextId, peer) {
|
|
49
|
+
const activation = this.activations.get(contextId);
|
|
50
|
+
if (activation === undefined)
|
|
51
|
+
return 'unknown';
|
|
52
|
+
if (activation.peer !== peer)
|
|
53
|
+
return 'forbidden';
|
|
54
|
+
activation.lastTouchedAt = this.now();
|
|
55
|
+
return activation;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Register a freshly created or resumed Activation.
|
|
59
|
+
* @param activation - the Activation to hold.
|
|
60
|
+
*/
|
|
61
|
+
add(activation) {
|
|
62
|
+
this.activations.set(activation.contextId, activation);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Remove an Activation from the registry without disposing it.
|
|
66
|
+
* @param contextId - the context to forget.
|
|
67
|
+
* @returns the removed Activation, if it was resident.
|
|
68
|
+
*/
|
|
69
|
+
remove(contextId) {
|
|
70
|
+
const activation = this.activations.get(contextId);
|
|
71
|
+
this.activations.delete(contextId);
|
|
72
|
+
return activation;
|
|
73
|
+
}
|
|
74
|
+
/** Forget every Activation and return them for the caller to dispose. */
|
|
75
|
+
drain() {
|
|
76
|
+
const all = this.values();
|
|
77
|
+
this.activations.clear();
|
|
78
|
+
return all;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Select Activations that may be evicted right now.
|
|
82
|
+
*
|
|
83
|
+
* An Activation is evictable only when nothing is owed: no in-flight task and
|
|
84
|
+
* no recent touch. A context over the resident ceiling is evicted by least
|
|
85
|
+
* recent touch — but a busy context is NEVER evicted to make room, because
|
|
86
|
+
* dropping work a peer is waiting on is worse than exceeding a soft ceiling.
|
|
87
|
+
* @returns Activations the caller should dispose and remove.
|
|
88
|
+
*/
|
|
89
|
+
evictable() {
|
|
90
|
+
const cutoff = this.now() - this.idleTtlMs;
|
|
91
|
+
const quiet = this.values().filter(a => a.slots.size === 0);
|
|
92
|
+
const expired = quiet.filter(a => a.lastTouchedAt <= cutoff);
|
|
93
|
+
if (this.activations.size <= this.maxResident)
|
|
94
|
+
return expired;
|
|
95
|
+
const overflow = this.activations.size - this.maxResident;
|
|
96
|
+
const byOldest = quiet
|
|
97
|
+
.filter(a => !expired.includes(a))
|
|
98
|
+
.sort((a, b) => a.lastTouchedAt - b.lastTouchedAt)
|
|
99
|
+
.slice(0, Math.max(0, overflow - expired.length));
|
|
100
|
+
return [...expired, ...byOldest];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=contexts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contexts.js","sourceRoot":"","sources":["../src/contexts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAwBH,8DAA8D;AAC9D,MAAM,OAAO,eAAe;IASP;IACA;IACA;IAVF,WAAW,GAAG,IAAI,GAAG,EAA4B,CAAA;IAElE;;;;OAIG;IACH,YACmB,WAAmB,EACnB,SAAiB,EACjB,MAAoB,IAAI,CAAC,GAAG;QAF5B,gBAAW,GAAX,WAAW,CAAQ;QACnB,cAAS,GAAT,SAAS,CAAQ;QACjB,QAAG,GAAH,GAAG,CAAyB;IAC5C,CAAC;IAEJ,qDAAqD;IACrD,MAAM;QACJ,OAAO,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAA;IACvC,CAAC;IAED,gDAAgD;IAChD,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAA;IAC9B,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,SAAuB,EAAE,IAAY;QAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QAClD,IAAI,UAAU,KAAK,SAAS;YAAE,OAAO,SAAS,CAAA;QAC9C,IAAI,UAAU,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO,WAAW,CAAA;QAChD,UAAU,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACrC,OAAO,UAAU,CAAA;IACnB,CAAC;IAED;;;OAGG;IACH,GAAG,CAAC,UAAsB;QACxB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,EAAE,UAAU,CAAC,CAAA;IACxD,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,SAAuB;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QAClD,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QAClC,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,yEAAyE;IACzE,KAAK;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAA;QACzB,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAA;QACxB,OAAO,GAAG,CAAA;IACZ,CAAC;IAED;;;;;;;;OAQG;IACH,SAAS;QACP,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAA;QAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAA;QAC3D,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,IAAI,MAAM,CAAC,CAAA;QAC5D,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO,OAAO,CAAA;QAE7D,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAA;QACzD,MAAM,QAAQ,GAAG,KAAK;aACnB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;aACjC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa,CAAC;aACjD,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAA;QACnD,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,QAAQ,CAAC,CAAA;IAClC,CAAC;CACF"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inbound A2A protocol server for DeepSeek Harness.
|
|
3
|
+
*
|
|
4
|
+
* Publishes an Agent Card at a well-known URI and serves the A2A v0.3.0
|
|
5
|
+
* JSON-RPC binding, so any compliant peer that knows this deployment's URL can
|
|
6
|
+
* discover it and submit tasks to a harness agent. There is no outbound client:
|
|
7
|
+
* this plugin never connects to another agent.
|
|
8
|
+
*
|
|
9
|
+
* It is a TRANSPORT ADAPTER, not a capability seam — the same self-limitation
|
|
10
|
+
* `dsh-acp` states. It exposes no editor navigation, transcript replay,
|
|
11
|
+
* commands, modes, or tool presentation.
|
|
12
|
+
*
|
|
13
|
+
* @module dsh-a2a-server
|
|
14
|
+
*/
|
|
15
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
16
|
+
import { Config, type A2AServerConfig } from './config.ts';
|
|
17
|
+
export { Config };
|
|
18
|
+
export type { A2AServerConfig };
|
|
19
|
+
export declare const name = "a2a-server";
|
|
20
|
+
/**
|
|
21
|
+
* The server creates and owns agents, needs an HTTP carrier for its routes, and
|
|
22
|
+
* cannot authenticate a single request without the credential seam. Everything
|
|
23
|
+
* else it uses is probed with `ctx.get()` so a composition missing an optional
|
|
24
|
+
* capability still boots with A2A serving.
|
|
25
|
+
*/
|
|
26
|
+
export declare const inject: string[];
|
|
27
|
+
/**
|
|
28
|
+
* Mount the inbound A2A server.
|
|
29
|
+
* @param ctx - the Cordis context carrying the agent factory, HTTP carrier, and credentials.
|
|
30
|
+
* @param config - the validated plugin configuration.
|
|
31
|
+
*/
|
|
32
|
+
export declare function apply(ctx: Context, config: A2AServerConfig): void;
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAalD,OAAO,EAAwB,MAAM,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAA;AAchF,OAAO,EAAE,MAAM,EAAE,CAAA;AACjB,YAAY,EAAE,eAAe,EAAE,CAAA;AAE/B,eAAO,MAAM,IAAI,eAAe,CAAA;AAEhC;;;;;GAKG;AACH,eAAO,MAAM,MAAM,UAAyC,CAAA;AAW5D;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAyejE"}
|