@noetic-tools/core 0.3.0 → 1.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/dist/harness/agent-harness.d.ts +2 -2
- package/dist/harness/agent-harness.js +17 -5
- package/dist/harness/model-call.js +9 -8
- package/dist/harness/model-schema.d.ts +8 -0
- package/dist/harness/model-schema.js +8 -0
- package/dist/index.d.ts +1 -1
- package/dist/interpreter/execute-action.js +19 -2
- package/dist/interpreter/execute-control.js +59 -4
- package/dist/runtime/channel-store.d.ts +42 -2
- package/dist/runtime/channel-store.js +232 -35
- package/dist/runtime/context-impl.d.ts +17 -1
- package/dist/runtime/context-impl.js +30 -3
- package/dist/runtime/durable/stall-nudge.d.ts +16 -9
- package/dist/runtime/durable/stall-nudge.js +29 -10
- package/dist/runtime/event-broadcaster.d.ts +9 -1
- package/dist/runtime/event-broadcaster.js +43 -19
- package/dist/schemas/workflow.js +21 -5
- package/package.json +7 -4
- package/schema/noetic-workflow.schema.json +523 -0
|
@@ -152,8 +152,8 @@ export declare class AgentHarness<TParams extends Record<string, unknown> = Reco
|
|
|
152
152
|
cwdInit?: string;
|
|
153
153
|
_broadcaster?: EventBroadcaster;
|
|
154
154
|
}): Context;
|
|
155
|
-
send<T>(channel: Channel<T>, value: T,
|
|
156
|
-
recv<T>(channel: Channel<T>,
|
|
155
|
+
send<T>(channel: Channel<T>, value: T, ctx: Context): Promise<void>;
|
|
156
|
+
recv<T>(channel: Channel<T>, ctx: Context, opts?: {
|
|
157
157
|
timeout?: number;
|
|
158
158
|
}): Promise<T>;
|
|
159
159
|
tryRecv<T>(channel: Channel<T>, _ctx: Context): T | null;
|
|
@@ -137,7 +137,11 @@ export class AgentHarness {
|
|
|
137
137
|
this.client = opts._testCallModel ? undefined : createClient(opts.llm);
|
|
138
138
|
this.channelStore = new ChannelStore();
|
|
139
139
|
this.traceExporter = opts.traceExporter ?? new NoopExporter();
|
|
140
|
-
this.layerStateStore =
|
|
140
|
+
this.layerStateStore =
|
|
141
|
+
opts.layerStateStore ??
|
|
142
|
+
createLayerStateStore((layerId, hook, error) => {
|
|
143
|
+
console.warn(`[noetic] memory layer '${layerId}' ${hook} error:`, error);
|
|
144
|
+
});
|
|
141
145
|
this.recallCache = createRecallCache();
|
|
142
146
|
this.defaultDeliveryMode = opts.defaultDeliveryMode ?? 'next-turn';
|
|
143
147
|
this.streamIdleTimeoutMs = opts.streamIdleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS;
|
|
@@ -366,11 +370,19 @@ export class AgentHarness {
|
|
|
366
370
|
cwdState: resolveContextCwdState(this.rootCwdState, opts?.parent, cwdInit),
|
|
367
371
|
});
|
|
368
372
|
}
|
|
369
|
-
send(channel, value,
|
|
370
|
-
|
|
373
|
+
send(channel, value, ctx) {
|
|
374
|
+
// Internal sender: back-pressured on full queue channels. The calling
|
|
375
|
+
// context's abort signal rejects a parked send with 'cancelled'.
|
|
376
|
+
const signal = ctx instanceof ContextImpl ? ctx.abortSignal : undefined;
|
|
377
|
+
return this.channelStore.send(channel, value, {
|
|
378
|
+
signal,
|
|
379
|
+
});
|
|
371
380
|
}
|
|
372
|
-
recv(channel,
|
|
373
|
-
|
|
381
|
+
recv(channel, ctx, opts) {
|
|
382
|
+
// Wire the calling context's abort signal so ctx.abort() rejects a
|
|
383
|
+
// pending recv with { kind: 'cancelled' } instead of hanging.
|
|
384
|
+
const signal = ctx instanceof ContextImpl ? ctx.abortSignal : undefined;
|
|
385
|
+
return this.channelStore.recv(channel, opts?.timeout, signal);
|
|
374
386
|
}
|
|
375
387
|
tryRecv(channel, _ctx) {
|
|
376
388
|
return this.channelStore.tryRecv(channel);
|
|
@@ -400,7 +400,6 @@ export class AgentHarnessModelCaller {
|
|
|
400
400
|
await this.executeToolRound({
|
|
401
401
|
functionCalls,
|
|
402
402
|
request,
|
|
403
|
-
roundItemSchemas,
|
|
404
403
|
allItems,
|
|
405
404
|
conversationInput,
|
|
406
405
|
round,
|
|
@@ -517,7 +516,7 @@ export class AgentHarnessModelCaller {
|
|
|
517
516
|
};
|
|
518
517
|
}
|
|
519
518
|
async executeToolRound(params) {
|
|
520
|
-
const { functionCalls, request,
|
|
519
|
+
const { functionCalls, request, allItems, conversationInput } = params;
|
|
521
520
|
params.emitIfAllowed('tool_round_started', {
|
|
522
521
|
round: params.round,
|
|
523
522
|
toolCount: functionCalls.length,
|
|
@@ -538,7 +537,6 @@ export class AgentHarnessModelCaller {
|
|
|
538
537
|
await this.executeFunctionCall({
|
|
539
538
|
fc,
|
|
540
539
|
request,
|
|
541
|
-
roundItemSchemas,
|
|
542
540
|
allItems,
|
|
543
541
|
conversationInput,
|
|
544
542
|
emitIfAllowed: params.emitIfAllowed,
|
|
@@ -550,7 +548,7 @@ export class AgentHarnessModelCaller {
|
|
|
550
548
|
});
|
|
551
549
|
}
|
|
552
550
|
async executeFunctionCall(params) {
|
|
553
|
-
const { fc, request,
|
|
551
|
+
const { fc, request, allItems, conversationInput } = params;
|
|
554
552
|
params.emitIfAllowed('tool_call_started', {
|
|
555
553
|
name: fc.name,
|
|
556
554
|
callId: fc.callId,
|
|
@@ -563,7 +561,6 @@ export class AgentHarnessModelCaller {
|
|
|
563
561
|
this.recordMalformedToolCall({
|
|
564
562
|
fc,
|
|
565
563
|
request,
|
|
566
|
-
roundItemSchemas,
|
|
567
564
|
allItems,
|
|
568
565
|
conversationInput,
|
|
569
566
|
emitIfAllowed: params.emitIfAllowed,
|
|
@@ -582,10 +579,13 @@ export class AgentHarnessModelCaller {
|
|
|
582
579
|
harness: this.opts.harness,
|
|
583
580
|
layers: request.layers,
|
|
584
581
|
});
|
|
582
|
+
// Owner-scoped result validation: a tool's `toolResults` schemas apply
|
|
583
|
+
// only to that tool's own result items. Harness-level `opts.itemSchemas`
|
|
584
|
+
// stay global by design; sibling tools' schemas never reject this item.
|
|
585
585
|
const outputItem = createToolResultItem({
|
|
586
586
|
output: toolResult.output,
|
|
587
587
|
callId: fc.callId,
|
|
588
|
-
roundItemSchemas,
|
|
588
|
+
roundItemSchemas: this.opts.itemSchemas.extend(toolForCall?.itemSchemas),
|
|
589
589
|
tool: toolForCall,
|
|
590
590
|
callItem: fc,
|
|
591
591
|
args: parsedArgs,
|
|
@@ -605,13 +605,14 @@ export class AgentHarnessModelCaller {
|
|
|
605
605
|
});
|
|
606
606
|
}
|
|
607
607
|
recordMalformedToolCall(params) {
|
|
608
|
-
const { fc, request,
|
|
608
|
+
const { fc, request, allItems, conversationInput } = params;
|
|
609
609
|
const errorOutput = `Error: malformed JSON in tool arguments: ${fc.arguments}`;
|
|
610
610
|
const toolForCall = request.tools?.find((tool) => tool.name === fc.name);
|
|
611
|
+
// Owner-scoped result validation (see executeFunctionCall).
|
|
611
612
|
const outputItem = createToolResultItem({
|
|
612
613
|
output: errorOutput,
|
|
613
614
|
callId: fc.callId,
|
|
614
|
-
roundItemSchemas,
|
|
615
|
+
roundItemSchemas: this.opts.itemSchemas.extend(toolForCall?.itemSchemas),
|
|
615
616
|
tool: toolForCall,
|
|
616
617
|
callItem: fc,
|
|
617
618
|
error: true,
|
|
@@ -5,6 +5,14 @@ export declare function buildItemSchemaRegistry({ base, layers, tools, }: {
|
|
|
5
5
|
layers?: ReadonlyArray<MemoryLayer>;
|
|
6
6
|
tools?: ReadonlyArray<Tool>;
|
|
7
7
|
}): ItemSchemaRegistry;
|
|
8
|
+
/**
|
|
9
|
+
* Build and validate a `function_call_output` item for a tool result.
|
|
10
|
+
*
|
|
11
|
+
* `roundItemSchemas` must be the OWNER-SCOPED registry for the called tool
|
|
12
|
+
* (harness base extended with only that tool's `itemSchemas`), so one tool's
|
|
13
|
+
* `toolResults` schemas never reject a sibling tool's result items. Tools
|
|
14
|
+
* without `itemSchemas` fall back to the base structural parse.
|
|
15
|
+
*/
|
|
8
16
|
export declare function createToolResultItem({ output, callId, roundItemSchemas, tool, callItem, args, result, error, }: {
|
|
9
17
|
output: string;
|
|
10
18
|
callId: string;
|
|
@@ -24,6 +24,14 @@ export function buildItemSchemaRegistry({ base, layers, tools, }) {
|
|
|
24
24
|
.extend(collectLayerItemSchemaExtensions(layers))
|
|
25
25
|
.extend(collectToolItemSchemaExtensions(tools));
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Build and validate a `function_call_output` item for a tool result.
|
|
29
|
+
*
|
|
30
|
+
* `roundItemSchemas` must be the OWNER-SCOPED registry for the called tool
|
|
31
|
+
* (harness base extended with only that tool's `itemSchemas`), so one tool's
|
|
32
|
+
* `toolResults` schemas never reject a sibling tool's result items. Tools
|
|
33
|
+
* without `itemSchemas` fall back to the base structural parse.
|
|
34
|
+
*/
|
|
27
35
|
export function createToolResultItem({ output, callId, roundItemSchemas, tool, callItem, args, result, error, }) {
|
|
28
36
|
const baseItem = {
|
|
29
37
|
id: crypto.randomUUID(),
|
package/dist/index.d.ts
CHANGED
|
@@ -55,7 +55,7 @@ export { execute } from './interpreter/execute.js';
|
|
|
55
55
|
/** @public */
|
|
56
56
|
/** @public */
|
|
57
57
|
/** @public */
|
|
58
|
-
export type { DurableTaskState,
|
|
58
|
+
export type { DurableTaskState, FactExtractor, FactSearcher, HistoryWindowConfig, ObservationalMemoryConfig, ObservationalState, PlanEnterSessionCallback, PlanExecutionEntry, PlanExitCallback, PlanMemoryConfig, PlanState, TemporalFact, TemporalMemoryConfig, TemporalSearchResult, WorkingMemoryConfig, WorkingMemoryState, } from '@noetic-tools/memory';
|
|
59
59
|
/** @public */
|
|
60
60
|
/** @public */
|
|
61
61
|
/** @public */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Action step handlers: run, llm, spawn, provide, tool.
|
|
3
3
|
*/
|
|
4
|
-
import { createMessage, estimateTokens, extractAssistantText, frameworkCast, NoeticConfigError, NoeticErrorImpl, } from '@noetic-tools/types';
|
|
4
|
+
import { createMessage, estimateTokens, extractAssistantText, frameworkCast, isNoeticError, NoeticConfigError, NoeticErrorImpl, } from '@noetic-tools/types';
|
|
5
5
|
import { ZodError } from 'zod';
|
|
6
6
|
import { allocateBudgets, assembleView, buildToolExecutionContext, ContextImpl, commitLayerUsage, computeLayerUsage, contextToExecCtx, DEFAULT_PROJECTION, defaultItemSchemaRegistry, emitFrameworkEvent, getBroadcaster, resolveLayerTools, returnLayers, snapshotCwdState, spawnLayers, } from './action-deps.js';
|
|
7
7
|
import { SteeringAction } from './action-types.js';
|
|
@@ -15,10 +15,23 @@ export async function executeRun(step, input, ctx) {
|
|
|
15
15
|
const maxAttempts = retry?.maxAttempts ?? 1;
|
|
16
16
|
let lastError = new Error('No attempts executed');
|
|
17
17
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
18
|
+
// Cancellation is not a retriable error (spec 09) — an abort that
|
|
19
|
+
// arrived between attempts must stop the loop before re-executing.
|
|
20
|
+
if (ctx.aborted) {
|
|
21
|
+
throw new NoeticErrorImpl({
|
|
22
|
+
kind: 'cancelled',
|
|
23
|
+
reason: ctx.abortReason ?? 'context aborted',
|
|
24
|
+
});
|
|
25
|
+
}
|
|
18
26
|
try {
|
|
19
27
|
return await step.execute(input, ctx);
|
|
20
28
|
}
|
|
21
29
|
catch (e) {
|
|
30
|
+
// Rethrow cancellation immediately — retrying it would re-run side
|
|
31
|
+
// effects after abort and bury the 'cancelled' kind under step_failed.
|
|
32
|
+
if (isNoeticError(e) && e.noeticError.kind === 'cancelled') {
|
|
33
|
+
throw e;
|
|
34
|
+
}
|
|
22
35
|
lastError = e instanceof Error ? e : new Error(String(e));
|
|
23
36
|
if (attempt < maxAttempts - 1 && retry) {
|
|
24
37
|
const delay = computeDelay(retry, attempt);
|
|
@@ -290,6 +303,11 @@ export async function executeLLM(step, input, ctx, layers) {
|
|
|
290
303
|
emit: step.emit,
|
|
291
304
|
};
|
|
292
305
|
const response = await baseCtx.harness.callModel(request);
|
|
306
|
+
// Track tokens/cost for EVERY model call, including responses steering
|
|
307
|
+
// subsequently rejects (Deny throw / Guide retry below) — the spend is
|
|
308
|
+
// real, and until.maxCost / HarnessResponse.usage must see it (spec 07:
|
|
309
|
+
// tokens accumulate across all LLM calls).
|
|
310
|
+
trackUsage(baseCtx, response);
|
|
293
311
|
if (hasLayers) {
|
|
294
312
|
const decision = await baseCtx.harness.afterModelCall(layers, response, baseCtx);
|
|
295
313
|
if (decision.action === SteeringAction.Deny) {
|
|
@@ -320,7 +338,6 @@ export async function executeLLM(step, input, ctx, layers) {
|
|
|
320
338
|
if (isMutableContext(baseCtx)) {
|
|
321
339
|
baseCtx.lastStepMeta = meta;
|
|
322
340
|
}
|
|
323
|
-
trackUsage(baseCtx, response);
|
|
324
341
|
commitLayerUsage(baseCtx, computeLayerUsage({
|
|
325
342
|
ctx: baseCtx,
|
|
326
343
|
modelId: resolvedModel,
|
|
@@ -135,9 +135,46 @@ function classifyResults(settled, paths) {
|
|
|
135
135
|
};
|
|
136
136
|
}
|
|
137
137
|
async function executeAll(step, paths, _input, ctx, childContexts, executeStep, concurrency) {
|
|
138
|
-
|
|
138
|
+
// Fail-fast (specs 03/09): the first genuine path failure aborts every
|
|
139
|
+
// sibling child context. Cancellation is cooperative — in-flight siblings
|
|
140
|
+
// are still awaited (they stop at their next step boundary / blocked
|
|
141
|
+
// channel op) so fork_partial's succeeded/failed stay accurate; paths
|
|
142
|
+
// still queued behind the concurrency limit are skipped outright. Skipped
|
|
143
|
+
// and aborted paths appear in `failed` with kind 'cancelled'.
|
|
144
|
+
let firstFailureSeen = false;
|
|
145
|
+
const tasks = paths.map((path, i) => async () => {
|
|
146
|
+
if (firstFailureSeen) {
|
|
147
|
+
throw new NoeticErrorImpl({
|
|
148
|
+
kind: 'cancelled',
|
|
149
|
+
reason: `fork '${step.id}' sibling failed`,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
return await executeStep(path, _input, frameworkCast(childContexts[i]));
|
|
154
|
+
}
|
|
155
|
+
catch (e) {
|
|
156
|
+
const isCancellation = isNoeticError(e) && e.noeticError.kind === 'cancelled';
|
|
157
|
+
if (!isCancellation && !firstFailureSeen) {
|
|
158
|
+
firstFailureSeen = true;
|
|
159
|
+
for (let j = 0; j < childContexts.length; j++) {
|
|
160
|
+
if (j !== i) {
|
|
161
|
+
childContexts[j].abort(`fork '${step.id}' sibling failed`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
throw e;
|
|
166
|
+
}
|
|
167
|
+
});
|
|
139
168
|
const settled = await runWithConcurrency(tasks, concurrency);
|
|
140
169
|
const { succeeded, failed } = classifyResults(settled, paths);
|
|
170
|
+
// If the PARENT context was aborted mid-fork, the whole fork is cancelled —
|
|
171
|
+
// surface 'cancelled', not a partial-failure shape (spec 09, item 3).
|
|
172
|
+
if (ctx.aborted) {
|
|
173
|
+
throw new NoeticErrorImpl({
|
|
174
|
+
kind: 'cancelled',
|
|
175
|
+
reason: ctx.abortReason ?? 'context aborted',
|
|
176
|
+
});
|
|
177
|
+
}
|
|
141
178
|
if (failed.length > 0) {
|
|
142
179
|
throw new NoeticErrorImpl({
|
|
143
180
|
kind: 'fork_partial',
|
|
@@ -208,9 +245,17 @@ async function executeRace(step, paths, input, ctx, childContexts, executeStep,
|
|
|
208
245
|
}
|
|
209
246
|
});
|
|
210
247
|
}
|
|
211
|
-
async function executeSettle(step, paths, input,
|
|
248
|
+
async function executeSettle(step, paths, input, ctx, childContexts, executeStep, concurrency) {
|
|
212
249
|
const tasks = paths.map((path, i) => () => executeStep(path, input, frameworkCast(childContexts[i])));
|
|
213
250
|
const settled = await runWithConcurrency(tasks, concurrency);
|
|
251
|
+
// Parent aborted mid-fork: the fork is cancelled, merge never runs
|
|
252
|
+
// (spec 09, Cancellation item 3 — same rule as mode 'all').
|
|
253
|
+
if (ctx.aborted) {
|
|
254
|
+
throw new NoeticErrorImpl({
|
|
255
|
+
kind: 'cancelled',
|
|
256
|
+
reason: ctx.abortReason ?? 'context aborted',
|
|
257
|
+
});
|
|
258
|
+
}
|
|
214
259
|
const results = settled.map((result, i) => {
|
|
215
260
|
if (result.status === 'fulfilled') {
|
|
216
261
|
return {
|
|
@@ -225,7 +270,7 @@ async function executeSettle(step, paths, input, _ctx, childContexts, executeSte
|
|
|
225
270
|
error: toNoeticError(result.reason, paths[i].id),
|
|
226
271
|
};
|
|
227
272
|
});
|
|
228
|
-
return step.merge(results,
|
|
273
|
+
return step.merge(results, ctx);
|
|
229
274
|
}
|
|
230
275
|
function hasTextField(value) {
|
|
231
276
|
return typeof value === 'object' && value !== null && 'text' in value;
|
|
@@ -242,7 +287,11 @@ async function recvInboxWithTimeout(ctx, step) {
|
|
|
242
287
|
timeout: step.parkTimeout,
|
|
243
288
|
});
|
|
244
289
|
}
|
|
245
|
-
catch {
|
|
290
|
+
catch (e) {
|
|
291
|
+
// Cancellation must terminate the loop, not read as "no message".
|
|
292
|
+
if (isNoeticError(e) && e.noeticError.kind === 'cancelled') {
|
|
293
|
+
throw e;
|
|
294
|
+
}
|
|
246
295
|
// Expected: channel_timeout error when parkTimeout expires with no message.
|
|
247
296
|
return null;
|
|
248
297
|
}
|
|
@@ -307,6 +356,12 @@ export async function executeLoop(step, input, ctx, executeStep) {
|
|
|
307
356
|
if (!step.onError || !isNoeticError(e)) {
|
|
308
357
|
throw e;
|
|
309
358
|
}
|
|
359
|
+
// Cancellation is not a retriable error (spec 09): it must terminate
|
|
360
|
+
// the loop promptly rather than be consumed by 'retry'/'skip'. Same
|
|
361
|
+
// guard as executeEvery's 'continue' policy below.
|
|
362
|
+
if (e.noeticError.kind === 'cancelled') {
|
|
363
|
+
throw e;
|
|
364
|
+
}
|
|
310
365
|
const action = step.onError(e.noeticError, ctx);
|
|
311
366
|
if (action === 'retry') {
|
|
312
367
|
continue;
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import type { Channel, ChannelHandle, ExternalChannel } from '@noetic-tools/types';
|
|
2
|
+
/** Options accepted by internal (back-pressured) `send`. */
|
|
3
|
+
export interface ChannelSendOpts {
|
|
4
|
+
/**
|
|
5
|
+
* How long a sender may stay parked on a full queue before rejecting with
|
|
6
|
+
* `channel_timeout`. Default 30s; `0` disables the timeout.
|
|
7
|
+
*/
|
|
8
|
+
timeout?: number;
|
|
9
|
+
/** Abort signal — rejects a parked sender with `cancelled`. */
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
}
|
|
2
12
|
export declare class ChannelStore {
|
|
3
13
|
private channels;
|
|
4
14
|
private closedExecutions;
|
|
@@ -9,10 +19,40 @@ export declare class ChannelStore {
|
|
|
9
19
|
* an `unsubscribe` so the caller can detach if it cancels first.
|
|
10
20
|
*/
|
|
11
21
|
subscribeWake<T>(channel: Channel<T>, callback: () => void): () => void;
|
|
12
|
-
|
|
13
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Internal-sender write with back-pressure (spec 06). Delivery is
|
|
24
|
+
* synchronous when possible; the returned promise only parks when a queue
|
|
25
|
+
* channel is at capacity:
|
|
26
|
+
*
|
|
27
|
+
* - **value**: store last-write-wins value, drain ALL parked recv waiters,
|
|
28
|
+
* resolve immediately.
|
|
29
|
+
* - **queue**: hand off to a parked recv waiter or push below capacity —
|
|
30
|
+
* resolve immediately. At capacity, park the sender FIFO until a consumer
|
|
31
|
+
* dequeues an item; reject `channel_timeout` after `opts.timeout`
|
|
32
|
+
* (default 30s) or `cancelled` when `opts.signal` aborts.
|
|
33
|
+
* - **topic**: deliver to current subscribers, resolve immediately.
|
|
34
|
+
*
|
|
35
|
+
* External callers use `ChannelHandle.send` (sync, drop-oldest) instead.
|
|
36
|
+
*/
|
|
37
|
+
send<T>(channel: Channel<T>, value: T, opts?: ChannelSendOpts): Promise<void>;
|
|
38
|
+
/** Park an internal sender on a full queue until a slot frees (FIFO). */
|
|
39
|
+
private parkSender;
|
|
40
|
+
/**
|
|
41
|
+
* A dequeue freed a queue slot — shift the oldest parked sender's value
|
|
42
|
+
* into it (FIFO) and resolve that sender's promise.
|
|
43
|
+
*/
|
|
44
|
+
private promotePendingSender;
|
|
45
|
+
/** Fire-and-reset the one-shot wake subscribers for a channel state. */
|
|
46
|
+
private fireWakes;
|
|
47
|
+
recv<T>(channel: Channel<T>, timeout?: number, signal?: AbortSignal): Promise<T>;
|
|
14
48
|
tryRecv<T>(channel: Channel<T>): T | null;
|
|
15
49
|
private waitWithTimeout;
|
|
50
|
+
/**
|
|
51
|
+
* External-sender write: synchronous, never back-pressured (spec 06,
|
|
52
|
+
* External Sender Back-Pressure). At capacity the OLDEST queued item is
|
|
53
|
+
* dropped (with a warning) so external callers never block.
|
|
54
|
+
*/
|
|
55
|
+
private sendExternal;
|
|
16
56
|
getHandle<T>(channel: ExternalChannel<T>, executionId: string): ChannelHandle<T>;
|
|
17
57
|
closeExecution(executionId: string): void;
|
|
18
58
|
}
|