@desplega.ai/agent-swarm 1.57.4 → 1.58.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/openapi.json +1 -1
- package/package.json +1 -1
- package/src/agentmail/handlers.ts +20 -0
- package/src/be/db.ts +265 -2
- package/src/be/migrations/031_user_registry.sql +35 -0
- package/src/commands/runner.ts +8 -1
- package/src/github/handlers.ts +18 -1
- package/src/gitlab/handlers.ts +12 -1
- package/src/hooks/hook.ts +17 -2
- package/src/http/poll.ts +9 -0
- package/src/linear/sync.ts +25 -1
- package/src/server.ts +6 -0
- package/src/slack/actions.ts +10 -1
- package/src/slack/assistant.ts +7 -0
- package/src/slack/handlers.ts +9 -2
- package/src/tests/events-http.test.ts +2 -2
- package/src/tests/http-api-integration.test.ts +3 -3
- package/src/tests/linear-outbound-sync.test.ts +7 -7
- package/src/tests/preload.ts +14 -0
- package/src/tests/rest-api.test.ts +1 -1
- package/src/tests/user-identity.test.ts +306 -0
- package/src/tests/workflow-async-v2.test.ts +7 -7
- package/src/tests/workflow-engine-v2.test.ts +3 -3
- package/src/tests/workflow-hitl-routing.test.ts +7 -7
- package/src/tests/workflow-http-v2.test.ts +1 -1
- package/src/tests/workflow-retry-v2.test.ts +4 -4
- package/src/tests/workflow-retry-validation.test.ts +3 -3
- package/src/tests/workflow-validation-port-routing.test.ts +221 -0
- package/src/tools/get-task-details.ts +14 -1
- package/src/tools/manage-user.ts +172 -0
- package/src/tools/resolve-user.ts +55 -0
- package/src/tools/tool-config.ts +4 -0
- package/src/types.ts +26 -0
- package/src/workflows/engine.ts +18 -4
- package/src/workflows/executors/script.ts +16 -1
- package/src/workflows/validation.ts +6 -3
package/src/tools/tool-config.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -153,8 +153,34 @@ export const AgentTaskSchema = z.object({
|
|
|
153
153
|
// Credential tracking
|
|
154
154
|
credentialKeySuffix: z.string().optional(),
|
|
155
155
|
credentialKeyType: z.string().optional(),
|
|
156
|
+
|
|
157
|
+
// User identity — canonical user who requested this task
|
|
158
|
+
requestedByUserId: z.string().optional(),
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// ============================================================================
|
|
162
|
+
// User Identity Types
|
|
163
|
+
// ============================================================================
|
|
164
|
+
|
|
165
|
+
export const UserSchema = z.object({
|
|
166
|
+
id: z.string(),
|
|
167
|
+
name: z.string().min(1),
|
|
168
|
+
email: z.string().optional(),
|
|
169
|
+
role: z.string().optional(),
|
|
170
|
+
notes: z.string().optional(),
|
|
171
|
+
slackUserId: z.string().optional(),
|
|
172
|
+
linearUserId: z.string().optional(),
|
|
173
|
+
githubUsername: z.string().optional(),
|
|
174
|
+
gitlabUsername: z.string().optional(),
|
|
175
|
+
emailAliases: z.array(z.string()).default([]),
|
|
176
|
+
preferredChannel: z.string().default("slack"),
|
|
177
|
+
timezone: z.string().optional(),
|
|
178
|
+
createdAt: z.iso.datetime(),
|
|
179
|
+
lastUpdatedAt: z.iso.datetime(),
|
|
156
180
|
});
|
|
157
181
|
|
|
182
|
+
export type User = z.infer<typeof UserSchema>;
|
|
183
|
+
|
|
158
184
|
export const AgentStatusSchema = z.enum(["idle", "busy", "offline"]);
|
|
159
185
|
|
|
160
186
|
export const AgentSchema = z.object({
|
package/src/workflows/engine.ts
CHANGED
|
@@ -19,7 +19,7 @@ import type { ExecutorRegistry } from "./executors/registry";
|
|
|
19
19
|
import { resolveInputs } from "./input";
|
|
20
20
|
import { validateJsonSchema } from "./json-schema-validator";
|
|
21
21
|
import { deepInterpolate } from "./template";
|
|
22
|
-
import { runStepValidation } from "./validation";
|
|
22
|
+
import { runStepValidation, type ValidationRunResult } from "./validation";
|
|
23
23
|
|
|
24
24
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
25
25
|
const MAX_ITERATIONS = Number(process.env.WORKFLOW_MAX_ITERATIONS) || 100;
|
|
@@ -526,8 +526,9 @@ async function executeStep(
|
|
|
526
526
|
}
|
|
527
527
|
|
|
528
528
|
// 7. Run validation if configured
|
|
529
|
+
let validationResult: ValidationRunResult | undefined;
|
|
529
530
|
if (node.validation) {
|
|
530
|
-
|
|
531
|
+
validationResult = await runStepValidation(registry, node, result.output, ctx, meta);
|
|
531
532
|
|
|
532
533
|
if (validationResult.outcome === "halt") {
|
|
533
534
|
const errorMsg = "Validation failed (mustPass)";
|
|
@@ -555,10 +556,23 @@ async function executeStep(
|
|
|
555
556
|
}
|
|
556
557
|
}
|
|
557
558
|
|
|
558
|
-
// 8.
|
|
559
|
+
// 8. Set nextPort from validation result for record-based routing
|
|
560
|
+
// When validation determines pass/fail and the node uses port-based `next`,
|
|
561
|
+
// route to the correct port instead of activating all ports.
|
|
562
|
+
if (
|
|
563
|
+
validationResult?.passed !== undefined &&
|
|
564
|
+
!result.nextPort &&
|
|
565
|
+
node.next &&
|
|
566
|
+
typeof node.next === "object" &&
|
|
567
|
+
!Array.isArray(node.next)
|
|
568
|
+
) {
|
|
569
|
+
result.nextPort = validationResult.passed ? "pass" : "fail";
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// 9. Checkpoint success
|
|
559
573
|
checkpointStep(runId, stepId, node.id, result, ctx);
|
|
560
574
|
|
|
561
|
-
//
|
|
575
|
+
// 10. Determine successors based on nextPort
|
|
562
576
|
// If executor returned a specific port, use it. Otherwise, get all successors
|
|
563
577
|
// (fan-out behavior for non-branching nodes with record-based `next`).
|
|
564
578
|
const successors = result.nextPort
|
|
@@ -41,9 +41,24 @@ export class ScriptExecutor extends BaseExecutor<
|
|
|
41
41
|
try {
|
|
42
42
|
const result = await Promise.race([this.runScript(config), this.timeoutPromise(timeoutMs)]);
|
|
43
43
|
|
|
44
|
+
// If stdout is valid JSON object, merge parsed fields into output
|
|
45
|
+
// so downstream nodes can access them via {{myScript.field}} interpolation
|
|
46
|
+
// (mirrors how agent-task nodes parse JSON in resume.ts)
|
|
47
|
+
let output: Record<string, unknown> = result;
|
|
48
|
+
if (result.exitCode === 0 && result.stdout) {
|
|
49
|
+
try {
|
|
50
|
+
const parsed = JSON.parse(result.stdout);
|
|
51
|
+
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
52
|
+
output = { ...result, ...parsed };
|
|
53
|
+
}
|
|
54
|
+
} catch {
|
|
55
|
+
// Not valid JSON — keep raw {exitCode, stdout, stderr}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
44
59
|
return {
|
|
45
60
|
status: "success",
|
|
46
|
-
output: result,
|
|
61
|
+
output: output as typeof result,
|
|
47
62
|
nextPort: result.exitCode === 0 ? "success" : "failure",
|
|
48
63
|
};
|
|
49
64
|
} catch (err) {
|
|
@@ -5,6 +5,8 @@ export type ValidationOutcome = "pass" | "halt" | "retry";
|
|
|
5
5
|
|
|
6
6
|
export interface ValidationRunResult {
|
|
7
7
|
outcome: ValidationOutcome;
|
|
8
|
+
/** Whether the validation actually passed (true) or failed (false). */
|
|
9
|
+
passed?: boolean;
|
|
8
10
|
/** Context additions if retry is needed */
|
|
9
11
|
retryContext?: Record<string, unknown>;
|
|
10
12
|
}
|
|
@@ -82,7 +84,7 @@ export async function runStepValidation(
|
|
|
82
84
|
const passed = result.status === "success" && extractPassResult(executorType, result.output);
|
|
83
85
|
|
|
84
86
|
if (passed) {
|
|
85
|
-
return { outcome: "pass" };
|
|
87
|
+
return { outcome: "pass", passed: true };
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
// Validation failed
|
|
@@ -90,15 +92,16 @@ export async function runStepValidation(
|
|
|
90
92
|
if (validation.retry) {
|
|
91
93
|
return {
|
|
92
94
|
outcome: "retry",
|
|
95
|
+
passed: false,
|
|
93
96
|
retryContext: {
|
|
94
97
|
previousOutput: stepOutput,
|
|
95
98
|
validationResult: result.output,
|
|
96
99
|
},
|
|
97
100
|
};
|
|
98
101
|
}
|
|
99
|
-
return { outcome: "halt" };
|
|
102
|
+
return { outcome: "halt", passed: false };
|
|
100
103
|
}
|
|
101
104
|
|
|
102
105
|
// mustPass is false — treat failure as pass (advisory validation)
|
|
103
|
-
return { outcome: "pass" };
|
|
106
|
+
return { outcome: "pass", passed: false };
|
|
104
107
|
}
|