@amaster.ai/dsh-a2a 0.1.35 → 0.1.37
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 +20 -17
- package/lib/inbox-api.js +2 -2
- package/lib/inbox.js +107 -56
- package/lib/index.js +1 -3
- package/lib/types/inbox.d.ts +1 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,13 +20,15 @@ Standard `SendMessage` / `SendStreamingMessage`, task queries, cancellation and
|
|
|
20
20
|
|
|
21
21
|
The same-process `a2aInbox` service exposes `resolve`, `content`, `enqueue`, `promote`, `cancel`, `get`, `update`, `move`, `remove`, `clearPending`, and `executePending`, plus the existing pause/wake/resume controls. Pending-only clearing preserves active work; context clearing discards all work.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Pause is process-local and writes no custom required session event. After restart, restored input stays parked until a waking admission or explicit execution. Retention recovery accepts snapshots under the historical extension URI as well as the current URI, writes only the current metadata key, and clears both keys after consumption. Explicit resume durably transfers input to a fresh task before waking it; retry after an interrupted cleanup reuses the existing replacement instead of replaying its input.
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
For external clients, the [native inbox extension specification](#native-inbox-extension-v1) defines `inbox/get`, `update`, `move`, `remove`, `clear`, `execute`, `steer`, and `subscribe` at the advertised JSONRPC endpoint. Activate it with the `A2A-Extensions` header set to the extension URI. Updates use standard A2A 1.0 user Messages; operations address native inbox IDs. REST/gRPC clients use the advertised JSONRPC endpoint for these extension methods. No extra queue or consumer is created.
|
|
26
|
+
|
|
27
|
+
`inbox/subscribe` streams checkpointed invalidations `{contextId, version}` over SSE, including native consumption and edits. It registers before its initial checkpoint and sends only after owner-scoped `ctx.sessions.flush()` returns true. A false/rejected checkpoint sends no success notification. Re-read the live inbox on invalidation and reconnect; there is no replay or durable outbox. Slow clients disconnect instead of accumulating notifications. To publish the same invalidations to host listeners on `a2a/inbox-checkpointed` without an SSE subscriber, enable `inbox.notifications: true` (default false). Hosts retain authentication, authorization and product-specific fan-out.
|
|
26
28
|
|
|
27
29
|
Existing native agents keep their setup and lifecycle owner. Reading/subscribing does not block their producers. Plugin shutdown detaches its own queued A2A inputs from a borrowed agent, retaining recovery data when configured; native work and the caller's agent remain available.
|
|
28
30
|
|
|
29
|
-
Wire snapshots are paginated: 50 entries by default, `pageSize: 1..100`, with `totalSize` and `nextPageToken`. Read `
|
|
31
|
+
Wire snapshots are paginated: 50 entries by default, `pageSize: 1..100`, with `totalSize` and `nextPageToken`. Read `inbox/get` until the token is empty, traversing next-step before next-turn. Any session-version change invalidates the cursor; restart from the first page. Mutations accept `pageSize` and return the first page. Same-process calls without page options still return the full snapshot. Adjacent reorders log only their affected interval, and slow notification checkpoints keep one pending version/error observer per batch.
|
|
30
32
|
|
|
31
33
|
The `E2E (dsh-a2a.inbox-api)` matrix leg installs the packed plugin into the pinned CLI and uses the real model gateway. It checks queue editing/reordering/removal/clearing, execution and steering, two checkpointed SSE subscribers, native consumption, and model recall in a subsequent context turn. A local loopback forwarder only gates the first model request to make steering deterministic; it never generates model responses.
|
|
32
34
|
|
|
@@ -77,11 +79,10 @@ DSH_NATIVE_OWNERSHIP_LANGFUSE_LIVE=true node .github/scripts/check-inbox.mjs -t
|
|
|
77
79
|
|
|
78
80
|
## Native inbox extension v1
|
|
79
81
|
|
|
80
|
-
|
|
82
|
+
Protocol identifier: `https://github.com/TGYD-helige/dsh-plugins/blob/main/packages/dsh-a2a/README.md`
|
|
81
83
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
`documentationUrl` pointing to this section.
|
|
84
|
+
This README contains the extension specification. The URI identifies the
|
|
85
|
+
extension during negotiation; no additional documentation parameter is advertised.
|
|
85
86
|
|
|
86
87
|
This is a project extension, not an official A2A extension. It follows the
|
|
87
88
|
[A2A extension mechanism](https://a2a-protocol.org/v1.0.1/topics/extensions/).
|
|
@@ -91,6 +92,8 @@ states, subscriptions and Push configurations keep their official meanings.
|
|
|
91
92
|
|
|
92
93
|
### Methods
|
|
93
94
|
|
|
95
|
+
Methods use the implementation-neutral `inbox/` namespace.
|
|
96
|
+
|
|
94
97
|
Send JSON-RPC 2.0 requests to the advertised JSONRPC endpoint. All methods take
|
|
95
98
|
`contextId`. IDs named `id` below are **native inbox message IDs**, not task IDs.
|
|
96
99
|
The extension adds no REST or gRPC service; those clients can discover and use
|
|
@@ -98,14 +101,14 @@ the advertised JSONRPC endpoint for these operations.
|
|
|
98
101
|
|
|
99
102
|
| Method | Additional parameters | Result |
|
|
100
103
|
| --- | --- | --- |
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
| `
|
|
108
|
-
| `
|
|
104
|
+
| `inbox/get` | Optional `pageSize`, `pageToken` | Live inbox snapshot page |
|
|
105
|
+
| `inbox/update` | `id`, `message` (A2A 1.0 user Message) | Updated snapshot |
|
|
106
|
+
| `inbox/move` | `id`, `index` (zero-based destination in the same list) | Updated snapshot |
|
|
107
|
+
| `inbox/remove` | `id` | Updated snapshot |
|
|
108
|
+
| `inbox/clear` | — | Snapshot after clearing pending input |
|
|
109
|
+
| `inbox/execute` | Optional `id` to move first in the next-turn list | Snapshot after waking pending work |
|
|
110
|
+
| `inbox/steer` | `id`, `taskId` (active target) | Snapshot after promotion |
|
|
111
|
+
| `inbox/subscribe` | — | SSE JSON-RPC result stream of `{contextId, version}` |
|
|
109
112
|
|
|
110
113
|
A snapshot is `{contextId, version, nextTurn, nextStep, totalSize, nextPageToken}`. Each entry is
|
|
111
114
|
`{id, message, editable}`: `message` uses the standard A2A 1.0 Message JSON shape.
|
|
@@ -129,7 +132,7 @@ limit serialized entries to about 1 MiB; one oversized Message is returned intac
|
|
|
129
132
|
to ensure progress, so a page may contain fewer items than requested. All mutation
|
|
130
133
|
methods accept `pageSize` for their returned first page; invalid values reject
|
|
131
134
|
before changing the queue. Pages traverse `nextStep` before `nextTurn`, keeping
|
|
132
|
-
native order within each list. Continue via `
|
|
135
|
+
native order within each list. Continue via `inbox/get` and `nextPageToken`
|
|
133
136
|
until the token is empty. Tokens bind the context and session version; a changed
|
|
134
137
|
version rejects stale tokens instead of silently skipping or duplicating input.
|
|
135
138
|
Re-read from the first page after invalidation. Same-process `get(contextId)`
|
|
@@ -165,7 +168,7 @@ coalesce changes per context, and checkpoint before publishing. A rejected or
|
|
|
165
168
|
false checkpoint produces no success notification. Later changes or reconnects
|
|
166
169
|
retry the current state; there is no durable outbox, replay or exactly-once
|
|
167
170
|
delivery. A host can consume the same feed through `a2a/inbox-checkpointed`.
|
|
168
|
-
Notification data contains no message bodies. Re-read `
|
|
171
|
+
Notification data contains no message bodies. Re-read `inbox/get` after an
|
|
169
172
|
invalidation and on reconnect. Each context checkpoints independently; slow SSE
|
|
170
173
|
clients disconnect instead of creating an unbounded notification backlog.
|
|
171
174
|
Closing the plugin unregisters observers/subscriptions and suppresses late sends.
|
package/lib/inbox-api.js
CHANGED
|
@@ -6,7 +6,7 @@ import { INBOX_EXTENSION, validateInboxPage } from './inbox.js';
|
|
|
6
6
|
export function inboxRpcHandler(inbox, card) {
|
|
7
7
|
return async (req, res, next) => {
|
|
8
8
|
const body = req.body;
|
|
9
|
-
if (typeof body?.method !== 'string' || !body.method.startsWith('
|
|
9
|
+
if (typeof body?.method !== 'string' || !body.method.startsWith('inbox/'))
|
|
10
10
|
return next();
|
|
11
11
|
try {
|
|
12
12
|
if (body.jsonrpc !== '2.0' || !['string', 'number'].includes(typeof body.id))
|
|
@@ -23,7 +23,7 @@ export function inboxRpcHandler(inbox, card) {
|
|
|
23
23
|
!params.contextId.trim() ||
|
|
24
24
|
(params.tenant !== undefined && params.tenant !== ''))
|
|
25
25
|
throw new RequestMalformedError('A contextId and the default tenant are required.');
|
|
26
|
-
const method = body.method.slice('
|
|
26
|
+
const method = body.method.slice('inbox/'.length);
|
|
27
27
|
const page = { pageSize: params.pageSize, pageToken: params.pageToken };
|
|
28
28
|
validateInboxPage(page);
|
|
29
29
|
if (method !== 'get' && page.pageToken)
|
package/lib/inbox.js
CHANGED
|
@@ -7,8 +7,18 @@ import { createUserMessage } from '@deepseek-ai/dsh-llm/message';
|
|
|
7
7
|
import { InboxChanges } from './inbox-changes.js';
|
|
8
8
|
import { commitInboxInput, markInboxInputPending } from './task-store.js';
|
|
9
9
|
import { agentTextMessage, SessionTranslator, terminalStatusUpdate } from './translator.js';
|
|
10
|
-
export const INBOX_EXTENSION = 'https://github.com/TGYD-helige/dsh-plugins/blob/main/
|
|
10
|
+
export const INBOX_EXTENSION = 'https://github.com/TGYD-helige/dsh-plugins/blob/main/packages/dsh-a2a/README.md';
|
|
11
11
|
const RETAINED_INPUTS = `${INBOX_EXTENSION}#retained-inputs`;
|
|
12
|
+
const LEGACY_RETAINED_INPUTS = 'https://github.com/TGYD-helige/dsh-plugins/blob/main/docs/protocol/inbox-v1.md#retained-inputs';
|
|
13
|
+
function retainedSnapshot(task) {
|
|
14
|
+
return task.metadata?.[RETAINED_INPUTS] ?? task.metadata?.[LEGACY_RETAINED_INPUTS];
|
|
15
|
+
}
|
|
16
|
+
function clearRetainedSnapshot(task) {
|
|
17
|
+
if (!task.metadata)
|
|
18
|
+
return;
|
|
19
|
+
delete task.metadata[RETAINED_INPUTS];
|
|
20
|
+
delete task.metadata[LEGACY_RETAINED_INPUTS];
|
|
21
|
+
}
|
|
12
22
|
export function validateInboxPage(page) {
|
|
13
23
|
if (page === undefined)
|
|
14
24
|
return;
|
|
@@ -508,56 +518,103 @@ export class NativeInbox {
|
|
|
508
518
|
}
|
|
509
519
|
async resume(contextId, taskId) {
|
|
510
520
|
const context = new ServerCallContext();
|
|
511
|
-
const previous = await this.store.load(taskId, context);
|
|
512
|
-
if (!previous || previous.contextId !== contextId || !this.terminal(previous))
|
|
513
|
-
throw new Error('Resume requires a terminal retained task.');
|
|
514
|
-
const retained = previous.metadata?.[RETAINED_INPUTS];
|
|
515
|
-
if (typeof retained !== 'string')
|
|
516
|
-
throw new Error('Task has no retained input to resume.');
|
|
517
|
-
const inputs = JSON.parse(retained);
|
|
518
|
-
if (!inputs.length)
|
|
519
|
-
throw new Error('Task has no retained input to resume.');
|
|
520
521
|
const run = await this.context(contextId, context);
|
|
521
|
-
const
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
message
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
522
|
+
const operation = run.admissionTail.then(async () => {
|
|
523
|
+
if (this.stopping || this.bridge.isClearing(contextId))
|
|
524
|
+
throw new Error('Context is unavailable.');
|
|
525
|
+
const previous = await this.store.load(taskId, context);
|
|
526
|
+
if (!previous || previous.contextId !== contextId || !this.terminal(previous))
|
|
527
|
+
throw new Error('Resume requires a terminal retained task.');
|
|
528
|
+
const retained = retainedSnapshot(previous);
|
|
529
|
+
if (typeof retained !== 'string')
|
|
530
|
+
throw new Error('Task has no retained input to resume.');
|
|
531
|
+
const inputs = JSON.parse(retained);
|
|
532
|
+
if (!inputs.length)
|
|
533
|
+
throw new Error('Task has no retained input to resume.');
|
|
534
|
+
const nativeIds = new Set(inputs.map((input) => input.message.id));
|
|
535
|
+
const resumed = new Map();
|
|
536
|
+
const messages = [
|
|
537
|
+
...run.entry.handle.agent.session
|
|
538
|
+
.snapshotEvents()
|
|
539
|
+
.flatMap((event) => (event.type === 'user/message' ? [event.data] : [])),
|
|
540
|
+
...this.pending(run),
|
|
541
|
+
...[...run.tasks.values()].flatMap((task) => task.claimedInputs ?? []),
|
|
542
|
+
];
|
|
543
|
+
for (const message of messages) {
|
|
544
|
+
if (!nativeIds.has(message.id) || message.source.kind !== 'a2a')
|
|
545
|
+
continue;
|
|
546
|
+
const original = Message.fromJSON(JSON.parse(message.source.message));
|
|
547
|
+
if (message.source.taskId !== taskId && original.referenceTaskIds.includes(taskId))
|
|
548
|
+
resumed.set(message.id, message.source.taskId);
|
|
549
|
+
}
|
|
550
|
+
if (resumed.size) {
|
|
551
|
+
const replacements = new Set(resumed.values());
|
|
552
|
+
if (resumed.size !== nativeIds.size || replacements.size !== 1)
|
|
553
|
+
throw new Error('Retained input has already been partially resumed.');
|
|
554
|
+
const id = resumed.values().next().value;
|
|
555
|
+
await this.flush(run.entry.handle.agent.session);
|
|
556
|
+
const replacement = run.tasks.get(id)?.task ?? (await this.store.load(id, context));
|
|
557
|
+
if (!replacement)
|
|
558
|
+
throw new Error('Resumed task is unavailable.');
|
|
559
|
+
clearRetainedSnapshot(replacement);
|
|
560
|
+
await this.checkpoint(replacement, context);
|
|
561
|
+
clearRetainedSnapshot(previous);
|
|
562
|
+
await this.checkpoint(previous, context);
|
|
563
|
+
if (this.pending(run).some((message) => message.source.kind === 'a2a' && message.source.taskId === id))
|
|
564
|
+
await this.wake(contextId);
|
|
565
|
+
return id;
|
|
566
|
+
}
|
|
567
|
+
const id = randomUUID();
|
|
568
|
+
const replacement = {
|
|
569
|
+
...previous,
|
|
570
|
+
id,
|
|
571
|
+
status: {
|
|
572
|
+
state: TaskState.TASK_STATE_SUBMITTED,
|
|
573
|
+
timestamp: new Date().toISOString(),
|
|
574
|
+
message: undefined,
|
|
550
575
|
},
|
|
576
|
+
history: [],
|
|
577
|
+
metadata: { ...previous.metadata },
|
|
551
578
|
};
|
|
579
|
+
clearRetainedSnapshot(replacement);
|
|
580
|
+
const retainedInputs = inputs.map((input) => {
|
|
581
|
+
if (input.message.source.kind !== 'a2a')
|
|
582
|
+
throw new Error('Retained input has invalid task ownership.');
|
|
583
|
+
const original = Message.fromJSON(JSON.parse(input.message.source.message));
|
|
584
|
+
original.taskId = id;
|
|
585
|
+
original.referenceTaskIds = [...new Set([...original.referenceTaskIds, taskId])];
|
|
586
|
+
replacement.history.push(markInboxInputPending(original));
|
|
587
|
+
return {
|
|
588
|
+
...input,
|
|
589
|
+
message: {
|
|
590
|
+
...input.message,
|
|
591
|
+
source: {
|
|
592
|
+
...input.message.source,
|
|
593
|
+
taskId: id,
|
|
594
|
+
message: JSON.stringify(Message.toJSON(original)),
|
|
595
|
+
},
|
|
596
|
+
},
|
|
597
|
+
};
|
|
598
|
+
});
|
|
599
|
+
replacement.metadata[RETAINED_INPUTS] = JSON.stringify(retainedInputs);
|
|
600
|
+
await this.checkpoint(replacement, context);
|
|
601
|
+
for (const input of retainedInputs) {
|
|
602
|
+
if (this.pending(run).some((pending) => pending.id === input.message.id))
|
|
603
|
+
run.entry.handle.agent.inbox.remove(input.message.id);
|
|
604
|
+
run.entry.handle.agent.send(input.message, input.target, false);
|
|
605
|
+
}
|
|
606
|
+
this.restoreTask(run, replacement, context);
|
|
607
|
+
// Consume the old snapshot only after its replacement input is durable.
|
|
608
|
+
await this.flush(run.entry.handle.agent.session);
|
|
609
|
+
clearRetainedSnapshot(replacement);
|
|
610
|
+
await this.checkpoint(replacement, context);
|
|
611
|
+
clearRetainedSnapshot(previous);
|
|
612
|
+
await this.checkpoint(previous, context);
|
|
613
|
+
await this.wake(contextId);
|
|
614
|
+
return id;
|
|
552
615
|
});
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
if (this.pending(run).some((pending) => pending.id === input.message.id))
|
|
556
|
-
run.entry.handle.agent.inbox.remove(input.message.id);
|
|
557
|
-
run.entry.handle.agent.send(input.message, input.target, index === retainedInputs.length - 1);
|
|
558
|
-
}
|
|
559
|
-
this.restoreTask(run, replacement, context);
|
|
560
|
-
return id;
|
|
616
|
+
run.admissionTail = operation.then(() => { }, () => { });
|
|
617
|
+
return operation;
|
|
561
618
|
}
|
|
562
619
|
/** Repair only an incomplete ownership move, never an ordinary DSH claim. */
|
|
563
620
|
async recoverPromotions(run, context) {
|
|
@@ -632,7 +689,7 @@ export class NativeInbox {
|
|
|
632
689
|
statusTimestampAfter: undefined,
|
|
633
690
|
}, context);
|
|
634
691
|
for (const task of page.tasks) {
|
|
635
|
-
const retained = task
|
|
692
|
+
const retained = retainedSnapshot(task);
|
|
636
693
|
if (typeof retained !== 'string')
|
|
637
694
|
continue;
|
|
638
695
|
// Terminal snapshots belong to explicit resume(); do not consume their
|
|
@@ -736,7 +793,7 @@ export class NativeInbox {
|
|
|
736
793
|
return;
|
|
737
794
|
await this.flush(agent.session);
|
|
738
795
|
for (const task of snapshots) {
|
|
739
|
-
|
|
796
|
+
clearRetainedSnapshot(task);
|
|
740
797
|
await this.checkpoint(task, context);
|
|
741
798
|
}
|
|
742
799
|
}
|
|
@@ -762,11 +819,6 @@ export class NativeInbox {
|
|
|
762
819
|
rolledBack: new Set(),
|
|
763
820
|
retained: { 'next-step': [], 'next-turn': [] },
|
|
764
821
|
};
|
|
765
|
-
const pause = [...run.entry.handle.agent.session.snapshotEvents()]
|
|
766
|
-
.reverse()
|
|
767
|
-
.find((event) => event.type === 'agent/inbox/paused');
|
|
768
|
-
if (pause)
|
|
769
|
-
run.paused = pause.data.paused;
|
|
770
822
|
await this.recoverRetained(run, context);
|
|
771
823
|
await this.recoverPromotions(run, context);
|
|
772
824
|
const snapshots = new Map();
|
|
@@ -1548,7 +1600,6 @@ export class NativeInbox {
|
|
|
1548
1600
|
if (run.paused)
|
|
1549
1601
|
return;
|
|
1550
1602
|
run.paused = true;
|
|
1551
|
-
run.entry.handle.agent.session.append('agent/inbox/paused', { paused: true });
|
|
1552
1603
|
for (const admission of run.admissions)
|
|
1553
1604
|
admission.abort();
|
|
1554
1605
|
run.entry.handle.agent.cancel({ kind: 'user' }, { keepInbox: true });
|
|
@@ -1560,7 +1611,6 @@ export class NativeInbox {
|
|
|
1560
1611
|
const agent = run.entry.handle.agent;
|
|
1561
1612
|
const pending = this.pending(run);
|
|
1562
1613
|
run.paused = false;
|
|
1563
|
-
agent.session.append('agent/inbox/paused', { paused: false });
|
|
1564
1614
|
const target = agent.inbox.nextTurn.length ? 'next-turn' : 'next-step';
|
|
1565
1615
|
const items = target === 'next-turn' ? agent.inbox.nextTurn : agent.inbox.nextStep;
|
|
1566
1616
|
const input = items.at(-1);
|
|
@@ -1732,6 +1782,7 @@ export class NativeInbox {
|
|
|
1732
1782
|
if (this.retainPending) {
|
|
1733
1783
|
const pending = retainedByTask.get(task.task.id) ?? [];
|
|
1734
1784
|
if (pending.length) {
|
|
1785
|
+
clearRetainedSnapshot(task.task);
|
|
1735
1786
|
task.task.metadata = {
|
|
1736
1787
|
...task.task.metadata,
|
|
1737
1788
|
[RETAINED_INPUTS]: JSON.stringify(pending),
|
package/lib/index.js
CHANGED
|
@@ -178,9 +178,7 @@ export function apply(ctx, config) {
|
|
|
178
178
|
uri: INBOX_EXTENSION,
|
|
179
179
|
description: 'Native inbox management, steering and checkpointed invalidation',
|
|
180
180
|
required: false,
|
|
181
|
-
params:
|
|
182
|
-
documentationUrl: 'https://github.com/TGYD-helige/dsh-plugins/blob/main/packages/dsh-a2a/README.md#native-inbox-extension-v1',
|
|
183
|
-
},
|
|
181
|
+
params: undefined,
|
|
184
182
|
},
|
|
185
183
|
]
|
|
186
184
|
: [],
|
package/lib/types/inbox.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { InboxChanges } from './inbox-changes.js';
|
|
|
10
10
|
import type { A2aTurnContext } from './index.js';
|
|
11
11
|
import type { A2aServer } from './server.js';
|
|
12
12
|
import { type ManagedTaskStore } from './task-store.js';
|
|
13
|
-
export declare const INBOX_EXTENSION = "https://github.com/TGYD-helige/dsh-plugins/blob/main/
|
|
13
|
+
export declare const INBOX_EXTENSION = "https://github.com/TGYD-helige/dsh-plugins/blob/main/packages/dsh-a2a/README.md";
|
|
14
14
|
export interface A2aInboxEvent {
|
|
15
15
|
phase: string;
|
|
16
16
|
contextId: string;
|
|
@@ -46,13 +46,6 @@ declare module '@deepseek-ai/dsh-llm/types' {
|
|
|
46
46
|
goal: GoalMessageSource;
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
declare module '@deepseek-ai/dsh-session/types' {
|
|
50
|
-
interface SessionEventMap {
|
|
51
|
-
'agent/inbox/paused': {
|
|
52
|
-
paused: boolean;
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
49
|
declare module '@deepseek-ai/cordis' {
|
|
57
50
|
interface Events {
|
|
58
51
|
/** Native inbox lifecycle; content consumers must honor their capture settings. */
|
package/package.json
CHANGED