@maxanstey-meridian/tandem 0.1.0-alpha.1 → 0.1.2
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/index.d.ts +57 -14
- package/dist/index.js +134 -79
- package/dist/runtime/FluentValidation.dll +0 -0
- package/dist/runtime/Google.Protobuf.dll +0 -0
- package/dist/runtime/Microsoft.Agents.AI.Abstractions.dll +0 -0
- package/dist/runtime/Microsoft.Agents.AI.Harness.dll +0 -0
- package/dist/runtime/Microsoft.Agents.AI.Tools.Shell.dll +0 -0
- package/dist/runtime/Microsoft.Agents.AI.Workflows.dll +0 -0
- package/dist/runtime/Microsoft.Agents.AI.dll +0 -0
- package/dist/runtime/Microsoft.CodeAnalysis.CSharp.dll +0 -0
- package/dist/runtime/Microsoft.CodeAnalysis.dll +0 -0
- package/dist/runtime/Microsoft.Data.Sqlite.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.AI.Abstractions.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.AI.Evaluation.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.AI.OpenAI.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.AI.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.Caching.Abstractions.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.Compliance.Abstractions.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.Configuration.Abstractions.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.DependencyInjection.Abstractions.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.Diagnostics.Abstractions.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.FileProviders.Abstractions.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.FileSystemGlobbing.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.Hosting.Abstractions.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.Logging.Abstractions.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.ObjectPool.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.Options.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.Primitives.dll +0 -0
- package/dist/runtime/Microsoft.Extensions.VectorData.Abstractions.dll +0 -0
- package/dist/runtime/Microsoft.JavaScript.NodeApi.dll +0 -0
- package/dist/runtime/Microsoft.ML.Tokenizers.dll +0 -0
- package/dist/runtime/OpenAI.dll +0 -0
- package/dist/runtime/OpenTelemetry.Api.dll +0 -0
- package/dist/runtime/SQLitePCLRaw.batteries_v2.dll +0 -0
- package/dist/runtime/SQLitePCLRaw.core.dll +0 -0
- package/dist/runtime/SQLitePCLRaw.provider.e_sqlite3.dll +0 -0
- package/dist/runtime/Spectre.Console.Ansi.dll +0 -0
- package/dist/runtime/Spectre.Console.dll +0 -0
- package/dist/runtime/System.ClientModel.dll +0 -0
- package/dist/runtime/System.Memory.Data.dll +0 -0
- package/dist/runtime/System.Numerics.Tensors.dll +0 -0
- package/dist/runtime/System.Reflection.MetadataLoadContext.dll +0 -0
- package/dist/runtime/Tandem.Advanced.dll +0 -0
- package/dist/runtime/Tandem.Ledger.dll +0 -0
- package/dist/runtime/Tandem.NodeApiSpike.Bridge.cjs +26 -0
- package/dist/runtime/Tandem.NodeApiSpike.Bridge.d.ts +23 -0
- package/dist/runtime/Tandem.NodeApiSpike.Bridge.deps.json +1097 -0
- package/dist/runtime/Tandem.NodeApiSpike.Bridge.dll +0 -0
- package/dist/runtime/Tandem.NodeApiSpike.Bridge.mjs +31 -0
- package/dist/runtime/Tandem.NodeApiSpike.Bridge.runtimeconfig.json +13 -0
- package/dist/runtime/Tandem.OpenAICompatible.dll +0 -0
- package/dist/runtime/Tandem.Terminal.dll +0 -0
- package/dist/runtime/Tandem.dll +0 -0
- package/dist/runtime/libe_sqlite3.dylib +0 -0
- package/dist/runtime/loader.d.mts +10 -0
- package/dist/runtime/loader.mjs +35 -0
- package/package.json +20 -6
- package/runtime/FluentValidation.dll +0 -0
- package/runtime/Google.Protobuf.dll +0 -0
- package/runtime/Microsoft.Agents.AI.Abstractions.dll +0 -0
- package/runtime/Microsoft.Agents.AI.Harness.dll +0 -0
- package/runtime/Microsoft.Agents.AI.Tools.Shell.dll +0 -0
- package/runtime/Microsoft.Agents.AI.Workflows.dll +0 -0
- package/runtime/Microsoft.Agents.AI.dll +0 -0
- package/runtime/Microsoft.CodeAnalysis.CSharp.dll +0 -0
- package/runtime/Microsoft.CodeAnalysis.dll +0 -0
- package/runtime/Microsoft.Data.Sqlite.dll +0 -0
- package/runtime/Microsoft.Extensions.AI.Abstractions.dll +0 -0
- package/runtime/Microsoft.Extensions.AI.Evaluation.dll +0 -0
- package/runtime/Microsoft.Extensions.AI.OpenAI.dll +0 -0
- package/runtime/Microsoft.Extensions.AI.dll +0 -0
- package/runtime/Microsoft.Extensions.Caching.Abstractions.dll +0 -0
- package/runtime/Microsoft.Extensions.Compliance.Abstractions.dll +0 -0
- package/runtime/Microsoft.Extensions.Configuration.Abstractions.dll +0 -0
- package/runtime/Microsoft.Extensions.DependencyInjection.Abstractions.dll +0 -0
- package/runtime/Microsoft.Extensions.Diagnostics.Abstractions.dll +0 -0
- package/runtime/Microsoft.Extensions.FileProviders.Abstractions.dll +0 -0
- package/runtime/Microsoft.Extensions.FileSystemGlobbing.dll +0 -0
- package/runtime/Microsoft.Extensions.Hosting.Abstractions.dll +0 -0
- package/runtime/Microsoft.Extensions.Logging.Abstractions.dll +0 -0
- package/runtime/Microsoft.Extensions.ObjectPool.dll +0 -0
- package/runtime/Microsoft.Extensions.Options.dll +0 -0
- package/runtime/Microsoft.Extensions.Primitives.dll +0 -0
- package/runtime/Microsoft.Extensions.VectorData.Abstractions.dll +0 -0
- package/runtime/Microsoft.JavaScript.NodeApi.dll +0 -0
- package/runtime/Microsoft.ML.Tokenizers.dll +0 -0
- package/runtime/OpenAI.dll +0 -0
- package/runtime/OpenTelemetry.Api.dll +0 -0
- package/runtime/SQLitePCLRaw.batteries_v2.dll +0 -0
- package/runtime/SQLitePCLRaw.core.dll +0 -0
- package/runtime/SQLitePCLRaw.provider.e_sqlite3.dll +0 -0
- package/runtime/Spectre.Console.Ansi.dll +0 -0
- package/runtime/Spectre.Console.dll +0 -0
- package/runtime/System.ClientModel.dll +0 -0
- package/runtime/System.Memory.Data.dll +0 -0
- package/runtime/System.Numerics.Tensors.dll +0 -0
- package/runtime/System.Reflection.MetadataLoadContext.dll +0 -0
- package/runtime/Tandem.Advanced.dll +0 -0
- package/runtime/Tandem.Ledger.dll +0 -0
- package/runtime/Tandem.NodeApiSpike.Bridge.cjs +26 -0
- package/runtime/Tandem.NodeApiSpike.Bridge.d.ts +23 -0
- package/runtime/Tandem.NodeApiSpike.Bridge.deps.json +1097 -0
- package/runtime/Tandem.NodeApiSpike.Bridge.dll +0 -0
- package/runtime/Tandem.NodeApiSpike.Bridge.mjs +31 -0
- package/runtime/Tandem.NodeApiSpike.Bridge.runtimeconfig.json +13 -0
- package/runtime/Tandem.OpenAICompatible.dll +0 -0
- package/runtime/Tandem.Terminal.dll +0 -0
- package/runtime/Tandem.dll +0 -0
- package/runtime/libe_sqlite3.dylib +0 -0
- package/runtime/loader.d.mts +10 -0
- package/runtime/loader.mjs +35 -0
- package/scripts/install-runtime.mjs +75 -0
- package/src/cli.ts +72 -0
- package/src/index.ts +2096 -0
- package/src/runtime/loader.d.mts +10 -0
- package/tsconfig.json +14 -0
package/dist/index.d.ts
CHANGED
|
@@ -104,6 +104,10 @@ export interface OpenAiCompatibleChatClient {
|
|
|
104
104
|
readonly wireApi: "completions" | "responses";
|
|
105
105
|
readonly apiKeyEnvironmentVariable?: string;
|
|
106
106
|
readonly verifyModel?: boolean;
|
|
107
|
+
/** Per-attempt transport limits; omitted preserves provider defaults. */
|
|
108
|
+
readonly requestTimeoutMs?: number;
|
|
109
|
+
readonly idleTimeoutMs?: number;
|
|
110
|
+
readonly maxAttempts?: number;
|
|
107
111
|
}
|
|
108
112
|
export type ChatClient = OpenAiCompatibleChatClient;
|
|
109
113
|
export type AgentReasoning = {
|
|
@@ -117,24 +121,11 @@ export interface AgentSkill {
|
|
|
117
121
|
readonly directory: string;
|
|
118
122
|
}
|
|
119
123
|
export type AgentToolName = "read_file" | "ls" | "grep" | "write_file" | "delete_file" | "replace" | "replace_lines" | "git:ro" | "shell" | "web_search" | "web_fetch";
|
|
120
|
-
interface AgentCommandArgumentBase {
|
|
121
|
-
readonly name: string;
|
|
122
|
-
readonly description: string;
|
|
123
|
-
readonly flag: string;
|
|
124
|
-
readonly maxLength?: number;
|
|
125
|
-
}
|
|
126
|
-
export type AgentCommandArgument = AgentCommandArgumentBase & ({
|
|
127
|
-
readonly pattern: string;
|
|
128
|
-
readonly allowedValues?: never;
|
|
129
|
-
} | {
|
|
130
|
-
readonly allowedValues: readonly string[];
|
|
131
|
-
readonly pattern?: never;
|
|
132
|
-
});
|
|
133
124
|
export interface AgentCommand {
|
|
134
125
|
readonly name: string;
|
|
135
126
|
readonly description: string;
|
|
136
127
|
readonly command: string;
|
|
137
|
-
readonly arguments?: readonly
|
|
128
|
+
readonly arguments?: readonly string[];
|
|
138
129
|
}
|
|
139
130
|
interface AgentCommandSelection {
|
|
140
131
|
readonly [commandSelectionBrand]: object;
|
|
@@ -182,6 +173,12 @@ export interface AgentDefinition<TState, TOutput = never> {
|
|
|
182
173
|
readonly schema: z.ZodType<TOutput>;
|
|
183
174
|
readonly validateFor?: (state: TState, output: TOutput) => readonly ValidationProblem[];
|
|
184
175
|
readonly apply: (state: TState, output: TOutput) => TState;
|
|
176
|
+
} | {
|
|
177
|
+
readonly instructions: string;
|
|
178
|
+
readonly raw: true;
|
|
179
|
+
readonly parse: (response: string) => TOutput;
|
|
180
|
+
readonly validateFor?: (state: TState, output: TOutput) => readonly ValidationProblem[];
|
|
181
|
+
readonly apply: (state: TState, output: TOutput) => TState;
|
|
185
182
|
};
|
|
186
183
|
readonly capabilities?: readonly Capability<TState>[];
|
|
187
184
|
readonly skills?: readonly AgentSkill[];
|
|
@@ -211,6 +208,8 @@ type ParallelDefinition<TState, TBranches extends ParallelBranches<TState>> = {
|
|
|
211
208
|
readonly merge: (baseline: TState, results: {
|
|
212
209
|
readonly [K in keyof TBranches]: TState;
|
|
213
210
|
}) => TState;
|
|
211
|
+
/** Maximum active branches per invocation; omitted means all branches. */
|
|
212
|
+
readonly max?: number;
|
|
214
213
|
readonly persist?: boolean;
|
|
215
214
|
};
|
|
216
215
|
export declare function parallel<TState>(): <const TBranches extends ParallelBranches<TState>>(definition: ParallelDefinition<TState, TBranches>) => Parallel<TState>;
|
|
@@ -256,6 +255,48 @@ export declare function pipeline<TState>(definition: {
|
|
|
256
255
|
outputs: readonly Terminal<NoInfer<TState>>[];
|
|
257
256
|
persist?: boolean;
|
|
258
257
|
}): Pipeline<TState>;
|
|
258
|
+
export interface PipelineInspection {
|
|
259
|
+
readonly name: string;
|
|
260
|
+
readonly stateSchema: unknown;
|
|
261
|
+
readonly start: string;
|
|
262
|
+
readonly persist: boolean;
|
|
263
|
+
readonly nodes: readonly InspectedNode[];
|
|
264
|
+
readonly routes: readonly InspectedRoute[];
|
|
265
|
+
readonly outputs: readonly string[];
|
|
266
|
+
}
|
|
267
|
+
export interface InspectedRoute {
|
|
268
|
+
readonly id: string;
|
|
269
|
+
readonly source: string;
|
|
270
|
+
readonly target: string;
|
|
271
|
+
readonly label: string;
|
|
272
|
+
readonly order: number;
|
|
273
|
+
readonly outcome?: "success" | "failed";
|
|
274
|
+
readonly conditional: boolean;
|
|
275
|
+
}
|
|
276
|
+
export interface InspectedNode {
|
|
277
|
+
readonly id: string;
|
|
278
|
+
readonly kind: "stage" | "interaction" | "agent" | "parallel" | "completion" | "failure";
|
|
279
|
+
readonly persist?: boolean;
|
|
280
|
+
readonly interaction?: {
|
|
281
|
+
readonly requestSchema: unknown;
|
|
282
|
+
readonly responseSchema: unknown;
|
|
283
|
+
};
|
|
284
|
+
readonly agent?: {
|
|
285
|
+
readonly capabilities: readonly {
|
|
286
|
+
readonly name: string;
|
|
287
|
+
readonly requestSchema: unknown;
|
|
288
|
+
}[];
|
|
289
|
+
readonly outputSchema?: unknown;
|
|
290
|
+
readonly workspace: boolean;
|
|
291
|
+
};
|
|
292
|
+
readonly max?: number;
|
|
293
|
+
readonly branches?: readonly {
|
|
294
|
+
readonly id: string;
|
|
295
|
+
readonly participant: InspectedNode;
|
|
296
|
+
}[];
|
|
297
|
+
}
|
|
298
|
+
/** Projects an instantiated pipeline without compiling, registering, or invoking callbacks. */
|
|
299
|
+
export declare function inspectPipeline<TState>(graph: Pipeline<TState>): PipelineInspection;
|
|
259
300
|
export interface RunResult<TState> {
|
|
260
301
|
readonly runId: string;
|
|
261
302
|
readonly succeeded: boolean;
|
|
@@ -319,6 +360,8 @@ export interface TerminalPresentationOptions {
|
|
|
319
360
|
}
|
|
320
361
|
export interface RunOptions {
|
|
321
362
|
readonly ledgerPath?: string;
|
|
363
|
+
/** Expose ledger read/search tools to agents. Disabled by default; does not affect logging. */
|
|
364
|
+
readonly enableLedgerTools?: boolean;
|
|
322
365
|
readonly signal?: AbortSignal;
|
|
323
366
|
readonly interactions?: InteractionHandlers;
|
|
324
367
|
readonly presentation?: "terminal";
|
package/dist/index.js
CHANGED
|
@@ -494,9 +494,7 @@ function copyAgentCommand(command) {
|
|
|
494
494
|
? { ...command }
|
|
495
495
|
: {
|
|
496
496
|
...command,
|
|
497
|
-
arguments: command.arguments
|
|
498
|
-
? { ...argument }
|
|
499
|
-
: { ...argument, allowedValues: [...argument.allowedValues] }),
|
|
497
|
+
arguments: [...command.arguments],
|
|
500
498
|
};
|
|
501
499
|
}
|
|
502
500
|
function validateAgentCommands(commands, context) {
|
|
@@ -519,65 +517,22 @@ function validateAgentCommands(commands, context) {
|
|
|
519
517
|
throw new TandemError(`${commandContext}.command must be non-blank.`);
|
|
520
518
|
}
|
|
521
519
|
if (candidate.arguments !== undefined && !Array.isArray(candidate.arguments)) {
|
|
522
|
-
throw new TandemError(`${commandContext}.arguments must be an array.`);
|
|
520
|
+
throw new TandemError(`${commandContext}.arguments must be an array of strings.`);
|
|
523
521
|
}
|
|
524
|
-
const
|
|
525
|
-
|
|
522
|
+
const argumentList = candidate.arguments ?? [];
|
|
523
|
+
if (argumentList.length > 16) {
|
|
524
|
+
throw new TandemError(`${commandContext}.arguments accepts at most 16 arguments.`);
|
|
525
|
+
}
|
|
526
|
+
for (const [argumentIndex, argument] of argumentList.entries()) {
|
|
526
527
|
const argumentContext = `${commandContext}.arguments[${argumentIndex}]`;
|
|
527
|
-
if (typeof argument !== "
|
|
528
|
-
throw new TandemError(`${argumentContext} must be
|
|
529
|
-
}
|
|
530
|
-
const candidateArgument = argument;
|
|
531
|
-
if (typeof candidateArgument.name !== "string" ||
|
|
532
|
-
!/^[A-Za-z_][A-Za-z0-9_]*$/.test(candidateArgument.name)) {
|
|
533
|
-
throw new TandemError(`${argumentContext}.name must be a valid JSON property identifier.`);
|
|
534
|
-
}
|
|
535
|
-
if (argumentNames.has(candidateArgument.name)) {
|
|
536
|
-
throw new TandemError(`${argumentContext}.name duplicates '${candidateArgument.name}'.`);
|
|
537
|
-
}
|
|
538
|
-
argumentNames.add(candidateArgument.name);
|
|
539
|
-
if (typeof candidateArgument.description !== "string" ||
|
|
540
|
-
candidateArgument.description.trim().length === 0) {
|
|
541
|
-
throw new TandemError(`${argumentContext}.description must be non-blank.`);
|
|
542
|
-
}
|
|
543
|
-
if (typeof candidateArgument.flag !== "string" ||
|
|
544
|
-
candidateArgument.flag.trim().length === 0 ||
|
|
545
|
-
/\s/.test(candidateArgument.flag)) {
|
|
546
|
-
throw new TandemError(`${argumentContext}.flag must be a whitespace-free switch token.`);
|
|
528
|
+
if (typeof argument !== "string") {
|
|
529
|
+
throw new TandemError(`${argumentContext} must be a string.`);
|
|
547
530
|
}
|
|
548
|
-
if (
|
|
549
|
-
|
|
550
|
-
throw new TandemError(`${argumentContext}.pattern must be a string.`);
|
|
531
|
+
if (argument.trim().length === 0) {
|
|
532
|
+
throw new TandemError(`${argumentContext} must not be blank.`);
|
|
551
533
|
}
|
|
552
|
-
if (
|
|
553
|
-
|
|
554
|
-
throw new TandemError(`${argumentContext}.allowedValues must be an array.`);
|
|
555
|
-
}
|
|
556
|
-
const hasPattern = typeof candidateArgument.pattern === "string";
|
|
557
|
-
const hasAllowedValues = Array.isArray(candidateArgument.allowedValues);
|
|
558
|
-
if (hasPattern === hasAllowedValues) {
|
|
559
|
-
throw new TandemError(`${argumentContext} requires exactly one of pattern or allowedValues.`);
|
|
560
|
-
}
|
|
561
|
-
if (candidateArgument.maxLength !== undefined &&
|
|
562
|
-
(!Number.isSafeInteger(candidateArgument.maxLength) ||
|
|
563
|
-
candidateArgument.maxLength <= 0 ||
|
|
564
|
-
candidateArgument.maxLength > 2_147_483_647)) {
|
|
565
|
-
throw new TandemError(`${argumentContext}.maxLength must be a positive integer.`);
|
|
566
|
-
}
|
|
567
|
-
if (candidateArgument.allowedValues !== undefined) {
|
|
568
|
-
if (candidateArgument.allowedValues.length === 0) {
|
|
569
|
-
throw new TandemError(`${argumentContext}.allowedValues must not be empty.`);
|
|
570
|
-
}
|
|
571
|
-
const values = new Set();
|
|
572
|
-
for (const value of candidateArgument.allowedValues) {
|
|
573
|
-
if (typeof value !== "string" || value.trim().length === 0) {
|
|
574
|
-
throw new TandemError(`${argumentContext}.allowedValues must be non-blank strings.`);
|
|
575
|
-
}
|
|
576
|
-
if (values.has(value)) {
|
|
577
|
-
throw new TandemError(`${argumentContext}.allowedValues duplicates '${value}'.`);
|
|
578
|
-
}
|
|
579
|
-
values.add(value);
|
|
580
|
-
}
|
|
534
|
+
if (argument.length > 200) {
|
|
535
|
+
throw new TandemError(`${argumentContext} must be at most 200 characters.`);
|
|
581
536
|
}
|
|
582
537
|
}
|
|
583
538
|
}
|
|
@@ -641,6 +596,20 @@ export function agent(definition) {
|
|
|
641
596
|
}
|
|
642
597
|
if (definition.output) {
|
|
643
598
|
requireInstructions(definition.output.instructions, `Agent '${definition.id}' output instructions`);
|
|
599
|
+
if ("raw" in definition.output) {
|
|
600
|
+
if (definition.output.raw !== true) {
|
|
601
|
+
throw new TandemError(`Agent '${definition.id}' output raw must be true.`);
|
|
602
|
+
}
|
|
603
|
+
if ("schema" in definition.output) {
|
|
604
|
+
throw new TandemError(`Agent '${definition.id}' output schema is forbidden for raw output.`);
|
|
605
|
+
}
|
|
606
|
+
if (typeof definition.output.parse !== "function") {
|
|
607
|
+
throw new TandemError(`Agent '${definition.id}' raw output requires a parse function.`);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
else if ("parse" in definition.output) {
|
|
611
|
+
throw new TandemError(`Agent '${definition.id}' output parse requires raw output mode.`);
|
|
612
|
+
}
|
|
644
613
|
}
|
|
645
614
|
const capabilities = definition.capabilities ?? [];
|
|
646
615
|
const names = new Set();
|
|
@@ -710,11 +679,13 @@ export function agent(definition) {
|
|
|
710
679
|
}
|
|
711
680
|
class ParallelImplementation extends NodeImplementation {
|
|
712
681
|
branches;
|
|
682
|
+
max;
|
|
713
683
|
merge;
|
|
714
684
|
kind = "parallel";
|
|
715
|
-
constructor(id, persist, branches, merge) {
|
|
685
|
+
constructor(id, persist, branches, max, merge) {
|
|
716
686
|
super(id, persist);
|
|
717
687
|
this.branches = branches;
|
|
688
|
+
this.max = max;
|
|
718
689
|
this.merge = merge;
|
|
719
690
|
}
|
|
720
691
|
}
|
|
@@ -725,6 +696,10 @@ export function parallel(definition) {
|
|
|
725
696
|
return createParallel(definition);
|
|
726
697
|
}
|
|
727
698
|
function createParallel(definition) {
|
|
699
|
+
if (definition.max !== undefined &&
|
|
700
|
+
(!Number.isInteger(definition.max) || definition.max < 1 || definition.max > 2147483647)) {
|
|
701
|
+
throw new TandemError(`Parallel group '${definition.id}' max must be a positive 32-bit integer.`);
|
|
702
|
+
}
|
|
728
703
|
const entries = Object.entries(definition.branches);
|
|
729
704
|
if (entries.length < 2) {
|
|
730
705
|
throw new TandemError(`Parallel group '${definition.id}' requires at least two branches.`);
|
|
@@ -733,7 +708,7 @@ function createParallel(definition) {
|
|
|
733
708
|
if (participants.size !== entries.length) {
|
|
734
709
|
throw new TandemError(`Parallel group '${definition.id}' must own a distinct participant per branch.`);
|
|
735
710
|
}
|
|
736
|
-
return new ParallelImplementation(definition.id, definition.persist, definition.branches, definition.merge);
|
|
711
|
+
return new ParallelImplementation(definition.id, definition.persist, definition.branches, definition.max, definition.merge);
|
|
737
712
|
}
|
|
738
713
|
class TerminalImplementation extends NodeImplementation {
|
|
739
714
|
failed;
|
|
@@ -838,6 +813,78 @@ export function pipeline(definition) {
|
|
|
838
813
|
}
|
|
839
814
|
return { ...definition, persist: definition.persist ?? false };
|
|
840
815
|
}
|
|
816
|
+
/** Projects an instantiated pipeline without compiling, registering, or invoking callbacks. */
|
|
817
|
+
export function inspectPipeline(graph) {
|
|
818
|
+
const inspectNode = (node) => {
|
|
819
|
+
const implementation = node;
|
|
820
|
+
const persist = implementation.persist;
|
|
821
|
+
if (node.kind === "interaction") {
|
|
822
|
+
const interaction = implementation;
|
|
823
|
+
return {
|
|
824
|
+
id: node.id,
|
|
825
|
+
kind: "interaction",
|
|
826
|
+
persist,
|
|
827
|
+
interaction: {
|
|
828
|
+
requestSchema: z.toJSONSchema(interaction.requestSchema, { io: "input" }),
|
|
829
|
+
responseSchema: z.toJSONSchema(interaction.responseSchema, { io: "input" }),
|
|
830
|
+
},
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
if (node.kind === "agent") {
|
|
834
|
+
const agent = implementation;
|
|
835
|
+
return {
|
|
836
|
+
id: node.id,
|
|
837
|
+
kind: "agent",
|
|
838
|
+
persist,
|
|
839
|
+
agent: {
|
|
840
|
+
capabilities: agent.granted.map((item) => ({
|
|
841
|
+
name: item.name,
|
|
842
|
+
requestSchema: JSON.parse(item.requestJsonSchema),
|
|
843
|
+
})),
|
|
844
|
+
...(!agent.output || "raw" in agent.output
|
|
845
|
+
? {}
|
|
846
|
+
: { outputSchema: z.toJSONSchema(agent.output.schema, { io: "input" }) }),
|
|
847
|
+
workspace: agent.workspace !== undefined,
|
|
848
|
+
},
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
if (node.kind === "parallel") {
|
|
852
|
+
const parallel = implementation;
|
|
853
|
+
return {
|
|
854
|
+
id: node.id,
|
|
855
|
+
kind: "parallel",
|
|
856
|
+
persist,
|
|
857
|
+
...(parallel.max !== undefined ? { max: parallel.max } : {}),
|
|
858
|
+
branches: Object.entries(parallel.branches).map(([id, participant]) => ({
|
|
859
|
+
id,
|
|
860
|
+
participant: inspectNode(participant),
|
|
861
|
+
})),
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
if (node.kind === "terminal") {
|
|
865
|
+
const terminal = implementation;
|
|
866
|
+
return { id: node.id, kind: terminal.failed ? "failure" : "completion", persist };
|
|
867
|
+
}
|
|
868
|
+
return { id: node.id, kind: "stage", persist };
|
|
869
|
+
};
|
|
870
|
+
return {
|
|
871
|
+
name: graph.name,
|
|
872
|
+
stateSchema: z.toJSONSchema(graph.state, { io: "input" }),
|
|
873
|
+
start: graph.start.id,
|
|
874
|
+
persist: graph.persist,
|
|
875
|
+
nodes: graph.nodes.map(inspectNode),
|
|
876
|
+
routes: graph.routes.map((item, order) => ({
|
|
877
|
+
id: `route:${order}`,
|
|
878
|
+
source: item.from.id,
|
|
879
|
+
target: item.to.id,
|
|
880
|
+
label: item.label,
|
|
881
|
+
order,
|
|
882
|
+
...(item.outcome === undefined ? {} : { outcome: item.outcome }),
|
|
883
|
+
conditional: item.when !== undefined,
|
|
884
|
+
})),
|
|
885
|
+
outputs: graph.outputs.map((item) => item.id),
|
|
886
|
+
};
|
|
887
|
+
}
|
|
841
888
|
const runObservationSchema = z.discriminatedUnion("kind", [
|
|
842
889
|
z
|
|
843
890
|
.object({ version: z.literal(1), kind: z.literal("stepStarted"), stepId: z.string().min(1) })
|
|
@@ -932,7 +979,7 @@ const runResultSchema = z
|
|
|
932
979
|
.strict();
|
|
933
980
|
export async function inspectAccepted(options) {
|
|
934
981
|
try {
|
|
935
|
-
const { inspectAcceptedAsync } = await import("
|
|
982
|
+
const { inspectAcceptedAsync } = await import("./runtime/loader.mjs");
|
|
936
983
|
return parseJson(acceptedValuesSchema, await inspectAcceptedAsync(options.ledgerPath, options.runId), "accepted values").map((value) => ({
|
|
937
984
|
version: 1,
|
|
938
985
|
kind: value.kind,
|
|
@@ -994,7 +1041,7 @@ export async function run(graph, initial, options = {}) {
|
|
|
994
1041
|
return "";
|
|
995
1042
|
})
|
|
996
1043
|
: undefined;
|
|
997
|
-
const { runRegisteredGraphAsync } = await import("
|
|
1044
|
+
const { runRegisteredGraphAsync } = await import("./runtime/loader.mjs");
|
|
998
1045
|
const resultJson = await runRegisteredGraphAsync(JSON.stringify({
|
|
999
1046
|
contractVersion: 10,
|
|
1000
1047
|
name: graph.name,
|
|
@@ -1002,6 +1049,7 @@ export async function run(graph, initial, options = {}) {
|
|
|
1002
1049
|
initialState,
|
|
1003
1050
|
persist: graph.persist,
|
|
1004
1051
|
ledgerPath: options.ledgerPath,
|
|
1052
|
+
enableLedgerTools: options.enableLedgerTools ?? false,
|
|
1005
1053
|
presentation: options.presentation,
|
|
1006
1054
|
terminal: options.terminal,
|
|
1007
1055
|
observationCallback,
|
|
@@ -1047,6 +1095,9 @@ function issues(schema, input) {
|
|
|
1047
1095
|
catch {
|
|
1048
1096
|
return JSON.stringify([{ path: "$", message: "Invalid JSON" }]);
|
|
1049
1097
|
}
|
|
1098
|
+
return issuesParsed(schema, value);
|
|
1099
|
+
}
|
|
1100
|
+
function issuesParsed(schema, value) {
|
|
1050
1101
|
try {
|
|
1051
1102
|
parse(schema, value, "agent contract");
|
|
1052
1103
|
return "";
|
|
@@ -1169,6 +1220,7 @@ function compileNode(node, stateSchema, callbacks) {
|
|
|
1169
1220
|
return {
|
|
1170
1221
|
...base,
|
|
1171
1222
|
kind: "parallel",
|
|
1223
|
+
...(implementation.max !== undefined ? { max: implementation.max } : {}),
|
|
1172
1224
|
branches: entries.map(([id, participant]) => ({
|
|
1173
1225
|
id,
|
|
1174
1226
|
participant: compileNode(participant, stateSchema, callbacks),
|
|
@@ -1203,18 +1255,7 @@ function compileWorkspace(id, configuration, stateSchema, callbacks) {
|
|
|
1203
1255
|
name: z.string(),
|
|
1204
1256
|
description: z.string(),
|
|
1205
1257
|
command: z.string(),
|
|
1206
|
-
arguments: z
|
|
1207
|
-
.array(z
|
|
1208
|
-
.object({
|
|
1209
|
-
name: z.string(),
|
|
1210
|
-
description: z.string(),
|
|
1211
|
-
flag: z.string(),
|
|
1212
|
-
pattern: z.string().optional(),
|
|
1213
|
-
allowedValues: z.array(z.string()).optional(),
|
|
1214
|
-
maxLength: z.number().optional(),
|
|
1215
|
-
})
|
|
1216
|
-
.strict())
|
|
1217
|
-
.optional(),
|
|
1258
|
+
arguments: z.array(z.string()).optional(),
|
|
1218
1259
|
})
|
|
1219
1260
|
.strict()), value, `${id} workspace commands`);
|
|
1220
1261
|
});
|
|
@@ -1275,15 +1316,29 @@ function compileWorkspace(id, configuration, stateSchema, callbacks) {
|
|
|
1275
1316
|
return { pathCallback, commandsCallback, toolGroups, interceptCallback };
|
|
1276
1317
|
}
|
|
1277
1318
|
function compileAgentOutput(id, output, stateSchema, callbacks) {
|
|
1278
|
-
const
|
|
1319
|
+
const raw = output.raw === true;
|
|
1320
|
+
const validate = raw
|
|
1321
|
+
? callbacks.registerSync((_, input) => issuesParsed(z.unknown(), output.parse(JSON.parse(input))))
|
|
1322
|
+
: callbacks.registerSync((_, input) => issues(output.schema, input));
|
|
1279
1323
|
const validateFor = output.validateFor
|
|
1280
|
-
? callbacks.registerSync((state, input) => validationProblems(output.validateFor(parseJson(stateSchema, state, `${id} state`),
|
|
1324
|
+
? callbacks.registerSync((state, input) => validationProblems(output.validateFor(parseJson(stateSchema, state, `${id} state`), raw
|
|
1325
|
+
? JSON.parse(input)
|
|
1326
|
+
: parseJson(output.schema, input, `${id} output`)), `${id} output contextual validation`))
|
|
1281
1327
|
: undefined;
|
|
1282
|
-
const apply = callbacks.registerSync((state, input) => serializeBoundary(stateSchema, output.apply(parseJson(stateSchema, state, `${id} state`),
|
|
1328
|
+
const apply = callbacks.registerSync((state, input) => serializeBoundary(stateSchema, output.apply(parseJson(stateSchema, state, `${id} state`), raw
|
|
1329
|
+
? JSON.parse(input)
|
|
1330
|
+
: parseJson(output.schema, input, `${id} output`)), `${id} applied state`));
|
|
1283
1331
|
return {
|
|
1284
1332
|
instructions: output.instructions,
|
|
1285
|
-
|
|
1286
|
-
|
|
1333
|
+
...(raw
|
|
1334
|
+
? {
|
|
1335
|
+
raw: true,
|
|
1336
|
+
rawParseCallback: callbacks.registerSync((_, input) => JSON.stringify(output.parse(input))),
|
|
1337
|
+
}
|
|
1338
|
+
: {
|
|
1339
|
+
jsonSchema: inputJsonSchema(output.schema, `${id} output schema`),
|
|
1340
|
+
validateCallback: validate,
|
|
1341
|
+
}),
|
|
1287
1342
|
validateForCallback: validateFor,
|
|
1288
1343
|
applyCallback: apply,
|
|
1289
1344
|
valueType: `${id}.output`,
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Generated for: Tandem.NodeApiSpike.Bridge 0.1.0.0
|
|
2
|
+
// Generated by: Microsoft.JavaScript.NodeApi.Generator 0.9.0.0
|
|
3
|
+
/* eslint-disable */
|
|
4
|
+
|
|
5
|
+
const dotnet = require('node-api-dotnet/net10.0');
|
|
6
|
+
const path = require('node:path');
|
|
7
|
+
// @ts-ignore - https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/65252
|
|
8
|
+
const { dlopen, platform, arch } = require('node:process');
|
|
9
|
+
|
|
10
|
+
const moduleName = path.basename(__filename, __filename.match(/(\.[cm]?js)?$/)[0]);
|
|
11
|
+
module.exports = dotnet ? importDotnetModule(moduleName) : importAotModule(moduleName);
|
|
12
|
+
|
|
13
|
+
function importDotnetModule(moduleName) {
|
|
14
|
+
const moduleFilePath = path.join(__dirname, moduleName + '.dll');
|
|
15
|
+
return dotnet.require(moduleFilePath);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function importAotModule(moduleName) {
|
|
19
|
+
const ridPlatform = platform === 'win32' ? 'win' : platform === 'darwin' ? 'osx' : platform;
|
|
20
|
+
const ridArch = arch === 'ia32' ? 'x86' : arch;
|
|
21
|
+
const rid = `${ridPlatform}-${ridArch}`;
|
|
22
|
+
const moduleFilePath = path.join(__dirname, rid, moduleName + '.node');
|
|
23
|
+
const module = { exports: {} };
|
|
24
|
+
dlopen(module, moduleFilePath);
|
|
25
|
+
return module.exports;
|
|
26
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Generated for: Tandem.NodeApiSpike.Bridge 0.1.0.0
|
|
2
|
+
// Generated by: Microsoft.JavaScript.NodeApi.Generator 0.9.0.0
|
|
3
|
+
/* eslint-disable */
|
|
4
|
+
|
|
5
|
+
import './System.Runtime';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/** Adapts JavaScript-authored participants to the Tandem runtime. */
|
|
9
|
+
export namespace NodePipelineBridge {
|
|
10
|
+
/** Reads accepted semantic journal values from a packaged SQLite ledger. */
|
|
11
|
+
export function inspectAcceptedAsync(
|
|
12
|
+
ledgerPath: string,
|
|
13
|
+
runId: string,
|
|
14
|
+
): Promise<string>;
|
|
15
|
+
|
|
16
|
+
/** Registers and runs a complete JavaScript-authored Tandem graph. */
|
|
17
|
+
export function runRegisteredGraphAsync(
|
|
18
|
+
definitionJson: string,
|
|
19
|
+
invokeSyncCallback: Func$4<string, string, string, string>,
|
|
20
|
+
invokeAsyncCallback: Func$5<string, string, string, AbortSignal, Promise<string>>,
|
|
21
|
+
cancellationToken?: AbortSignal,
|
|
22
|
+
): Promise<string>;
|
|
23
|
+
}
|