create-windy 0.6.14 → 0.6.15
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/cli.js +215 -24
- package/package.json +1 -1
- package/template/.agents/skills/windy-business-module/SKILL.md +58 -8
- package/template/.windy-template.json +2 -2
- package/template/apps/server/src/agent/client-session/attempt-authority.test.ts +162 -0
- package/template/apps/server/src/agent/client-session/attempt-authority.ts +191 -0
- package/template/apps/server/src/agent/client-session/bootstrap.ts +27 -11
- package/template/apps/server/src/agent/client-session/completion.ts +75 -24
- package/template/apps/server/src/agent/client-session/contracts.ts +23 -0
- package/template/apps/server/src/agent/client-session/creation.ts +103 -0
- package/template/apps/server/src/agent/client-session/digest.ts +11 -1
- package/template/apps/server/src/agent/client-session/drizzle-records.ts +150 -0
- package/template/apps/server/src/agent/client-session/drizzle-repository.integration.test.ts +30 -3
- package/template/apps/server/src/agent/client-session/drizzle-repository.ts +23 -132
- package/template/apps/server/src/agent/client-session/finalization.ts +99 -0
- package/template/apps/server/src/agent/client-session/host-auth.ts +22 -10
- package/template/apps/server/src/agent/client-session/host-revocation-composition.test.ts +77 -0
- package/template/apps/server/src/agent/client-session/host-revocation-composition.ts +28 -0
- package/template/apps/server/src/agent/client-session/launch-authority.contract.test.ts +21 -0
- package/template/apps/server/src/agent/client-session/manifest-admission.ts +11 -0
- package/template/apps/server/src/agent/client-session/service.test-support.ts +22 -0
- package/template/apps/server/src/agent/client-session/service.ts +104 -134
- package/template/apps/server/src/agent/client-session/terminal-digest.test.ts +23 -0
- package/template/apps/server/src/agent/client-workflow-artifact/active-blob-references.ts +8 -0
- package/template/apps/server/src/agent/client-workflow-artifact/artifact-builder.ts +60 -0
- package/template/apps/server/src/agent/client-workflow-artifact/authority-current.ts +59 -0
- package/template/apps/server/src/agent/client-workflow-artifact/binding-registry.test.ts +189 -0
- package/template/apps/server/src/agent/client-workflow-artifact/binding-registry.ts +153 -0
- package/template/apps/server/src/agent/client-workflow-artifact/bootstrap.ts +77 -0
- package/template/apps/server/src/agent/client-workflow-artifact/cancellation.ts +47 -0
- package/template/apps/server/src/agent/client-workflow-artifact/completed-recovery.ts +31 -0
- package/template/apps/server/src/agent/client-workflow-artifact/contracts.ts +104 -0
- package/template/apps/server/src/agent/client-workflow-artifact/drizzle-locks.ts +30 -0
- package/template/apps/server/src/agent/client-workflow-artifact/drizzle-mapper.ts +138 -0
- package/template/apps/server/src/agent/client-workflow-artifact/drizzle-repository.ts +346 -0
- package/template/apps/server/src/agent/client-workflow-artifact/error.ts +21 -0
- package/template/apps/server/src/agent/client-workflow-artifact/handler.ts +167 -0
- package/template/apps/server/src/agent/client-workflow-artifact/host-revocation.ts +29 -0
- package/template/apps/server/src/agent/client-workflow-artifact/in-memory-repository.ts +232 -0
- package/template/apps/server/src/agent/client-workflow-artifact/job-port.ts +101 -0
- package/template/apps/server/src/agent/client-workflow-artifact/presentation.ts +41 -0
- package/template/apps/server/src/agent/client-workflow-artifact/recovery.contract.test.ts +253 -0
- package/template/apps/server/src/agent/client-workflow-artifact/release-binding.ts +85 -0
- package/template/apps/server/src/agent/client-workflow-artifact/repository.test.ts +204 -0
- package/template/apps/server/src/agent/client-workflow-artifact/repository.ts +97 -0
- package/template/apps/server/src/agent/client-workflow-artifact/routes-handler.contract.test.ts +201 -0
- package/template/apps/server/src/agent/client-workflow-artifact/routes.ts +161 -0
- package/template/apps/server/src/agent/client-workflow-artifact/runtime-composition.ts +101 -0
- package/template/apps/server/src/agent/client-workflow-artifact/scope-authority.ts +39 -0
- package/template/apps/server/src/agent/client-workflow-artifact/service-authorization.ts +117 -0
- package/template/apps/server/src/agent/client-workflow-artifact/service-support.ts +28 -0
- package/template/apps/server/src/agent/client-workflow-artifact/service.contract.test.ts +345 -0
- package/template/apps/server/src/agent/client-workflow-artifact/service.ts +350 -0
- package/template/apps/server/src/agent/client-workflow-artifact/session-boundary.ts +39 -0
- package/template/apps/server/src/agent/client-workflow-artifact/source-access.contract.test.ts +98 -0
- package/template/apps/server/src/agent/client-workflow-artifact/source-access.ts +80 -0
- package/template/apps/server/src/agent/client-workflow-artifact/takeover.ts +122 -0
- package/template/apps/server/src/agent/client-workflow-artifact/task-authority.contract.test.ts +97 -0
- package/template/apps/server/src/agent/client-workflow-artifact/task-authority.ts +147 -0
- package/template/apps/server/src/agent/client-workflow-artifact/terminal-authority.contract.test.ts +100 -0
- package/template/apps/server/src/agent/client-workflow-artifact/terminal-replay.ts +31 -0
- package/template/apps/server/src/agent/client-workflow-artifact/terminal-seal.ts +211 -0
- package/template/apps/server/src/agent/client-workflow-artifact/workflow-artifact.test-support.ts +173 -0
- package/template/apps/server/src/agent/client-workflow-artifact/workflow-loader.contract.test.ts +254 -0
- package/template/apps/server/src/agent/client-workflow-artifact/workflow-loader.ts +285 -0
- package/template/apps/server/src/agent/run-facade.test-support.ts +17 -4
- package/template/apps/server/src/agent/run-facade.test.ts +16 -0
- package/template/apps/server/src/agent/run-session-authorization.ts +12 -10
- package/template/apps/server/src/agent/runtime-bootstrap-input.ts +5 -1
- package/template/apps/server/src/agent/runtime-bootstrap.ts +33 -33
- package/template/apps/server/src/agent/runtime-public-ports.ts +40 -0
- package/template/apps/server/src/agent/session-invalidation/contracts.ts +25 -26
- package/template/apps/server/src/agent/session-projection-access.ts +31 -19
- package/template/apps/server/src/agent/unavailable-routes.ts +21 -0
- package/template/apps/server/src/agent/workflow-runtime-bootstrap.ts +2 -0
- package/template/apps/server/src/agent-workflow/artifact-source-authorization.ts +12 -6
- package/template/apps/server/src/agent-workflow/command-facade.ts +70 -11
- package/template/apps/server/src/agent-workflow/drizzle-artifact-port.ts +9 -9
- package/template/apps/server/src/agent-workflow/drizzle-delegation-completion.ts +1 -1
- package/template/apps/server/src/agent-workflow/platform-node-adapters.ts +14 -6
- package/template/apps/server/src/agent-workflow/project-launch-authority.contract.test.ts +53 -0
- package/template/apps/server/src/agent-workflow/project-launch-authority.ts +92 -0
- package/template/apps/server/src/agent-workflow/runtime-composition.ts +30 -14
- package/template/apps/server/src/app/agent-runtime-composition.ts +6 -1
- package/template/apps/server/src/app/client-agent-workflow-artifact-binding.ts +14 -0
- package/template/apps/server/src/application-services.ts +6 -0
- package/template/apps/server/src/data-access/scope-containment.test.ts +31 -0
- package/template/apps/server/src/data-access/scope-containment.ts +48 -0
- package/template/apps/server/src/jobs/artifact-publication.test.ts +192 -0
- package/template/apps/server/src/jobs/artifact-publication.ts +56 -0
- package/template/apps/server/src/jobs/artifact-publisher.ts +101 -0
- package/template/apps/server/src/jobs/drizzle-artifact.ts +73 -1
- package/template/apps/server/src/jobs/drizzle-execution-repository.ts +14 -1
- package/template/apps/server/src/jobs/drizzle-execution.integration.test.ts +65 -0
- package/template/apps/server/src/jobs/drizzle-repository.integration.test.ts +1 -0
- package/template/apps/server/src/jobs/execution-repository.ts +28 -0
- package/template/apps/server/src/jobs/execution.test.ts +3 -1
- package/template/apps/server/src/jobs/in-memory-execution.ts +16 -0
- package/template/apps/server/src/jobs/in-memory-lease.ts +45 -1
- package/template/apps/server/src/jobs/legacy-adapter.integration.test.ts +2 -0
- package/template/apps/server/src/jobs/postgres-cleanup-contract.test.ts +58 -0
- package/template/apps/server/src/jobs/worker.ts +8 -14
- package/template/apps/server/src/module-host/background-ai-unavailable.ts +18 -0
- package/template/apps/server/src/module-host/durable-context.ts +19 -22
- package/template/apps/server/src/module-host/implementation-completeness.test.ts +80 -1
- package/template/apps/server/src/module-host/implementation-completeness.ts +28 -1
- package/template/apps/server/src/module-host/request-context.ts +32 -8
- package/template/apps/server/src/module-host/storage-port.ts +3 -0
- package/template/apps/server/src/module-host/workflow-input-artifact-port.test.ts +104 -0
- package/template/apps/server/src/module-host/workflow-input-artifact-port.ts +229 -0
- package/template/apps/server/src/module-host/workflow-input-materialization.test.ts +163 -0
- package/template/apps/server/src/module-host/workflow-input-materialization.ts +161 -0
- package/template/apps/server/src/workflow/drizzle-repository.integration.test.ts +1 -0
- package/template/docs/architecture/agent-workflow.md +13 -2
- package/template/docs/architecture/durable-jobs.md +7 -0
- package/template/docs/operations/agent-session-memory.md +2 -1
- package/template/docs/operations/agent-session-troubleshooting.md +87 -2
- package/template/docs/operations/agent-workflow-recovery.md +25 -14
- package/template/docs/platform/client-agent-session.md +148 -2
- package/template/packages/ai-client/package.json +2 -1
- package/template/packages/ai-client/src/client-agent/index.ts +1 -0
- package/template/packages/ai-client/src/client-agent/workflow-artifact/contracts.ts +85 -0
- package/template/packages/ai-client/src/client-agent/workflow-artifact/http.test.ts +49 -0
- package/template/packages/ai-client/src/client-agent/workflow-artifact/http.ts +82 -0
- package/template/packages/ai-client/src/client-agent/workflow-artifact/index.ts +3 -0
- package/template/packages/ai-client/src/client-agent/workflow-artifact/validation.test.ts +154 -0
- package/template/packages/ai-client/src/client-agent/workflow-artifact/validation.ts +332 -0
- package/template/packages/database/drizzle/0062_client_agent_workflow_artifact.sql +63 -0
- package/template/packages/database/drizzle/meta/0062_snapshot.json +14839 -0
- package/template/packages/database/drizzle/meta/_journal.json +7 -0
- package/template/packages/database/package.json +1 -1
- package/template/packages/database/src/agent-runtime-schema.test.ts +177 -0
- package/template/packages/database/src/schema/client-agent-workflow-artifact.ts +158 -0
- package/template/packages/database/src/schema/index.ts +1 -0
- package/template/packages/jobs/package.json +1 -1
- package/template/packages/jobs/src/handlers.test.ts +10 -0
- package/template/packages/jobs/src/handlers.ts +28 -11
- package/template/packages/modules/package.json +1 -1
- package/template/packages/modules/src/ai-client-execution-policy.ts +6 -0
- package/template/packages/modules/src/manifest.ts +2 -0
- package/template/packages/modules/src/system-agent-audit-actions.ts +3 -0
- package/template/packages/modules/src/system-ai-api-bindings.ts +15 -0
- package/template/packages/modules/src/system-audit-actions.ts +15 -0
- package/template/packages/server-sdk/index.ts +52 -0
- package/template/packages/server-sdk/package.json +5 -1
- package/template/packages/server-sdk/src/client-agent-session.ts +13 -1
- package/template/packages/server-sdk/src/client-agent-workflow-artifact.contract.test.ts +113 -0
- package/template/packages/server-sdk/src/client-agent-workflow-artifact.ts +183 -0
- package/template/packages/server-sdk/src/durable-handler.ts +7 -0
- package/template/packages/server-sdk/src/request-context.ts +7 -0
- package/template/packages/server-sdk/src/workflow-input-artifact-port.ts +104 -0
- package/template/packages/server-sdk/src/workflow-input-artifact-validation.contract.test.ts +124 -0
- package/template/packages/server-sdk/src/workflow-input-artifact-validation.ts +347 -0
- package/template/packages/server-sdk/src/workflow-input-materialization-handler.ts +43 -0
- package/template/packages/storage/package.json +1 -1
- package/template/packages/storage/src/blob-store-put-once.test.ts +70 -0
- package/template/packages/storage/src/blob-store.ts +9 -0
- package/template/packages/storage/src/local-file-blob-put-once.ts +120 -0
- package/template/packages/storage/src/local-file-blob-store.ts +53 -1
- package/template/packages/storage/src/memory-blob-store.ts +73 -33
|
@@ -14,15 +14,11 @@ import {
|
|
|
14
14
|
|
|
15
15
|
export interface CurrentSourceAuthorizationPort {
|
|
16
16
|
/** Resolve the current canonical authorization generation, never a client claim. */
|
|
17
|
-
current(
|
|
18
|
-
context: RequestGuardContext,
|
|
19
|
-
): Promise<SourceAuthorizationCoordinate>;
|
|
17
|
+
current(context: RequestGuardContext): Promise<SourceAuthorizationCoordinate>;
|
|
20
18
|
}
|
|
21
19
|
|
|
22
20
|
/** Re-resolves the Actor from the canonical user/role repositories per read. */
|
|
23
|
-
export class ResolvingCurrentSourceAuthorizationPort
|
|
24
|
-
implements CurrentSourceAuthorizationPort
|
|
25
|
-
{
|
|
21
|
+
export class ResolvingCurrentSourceAuthorizationPort implements CurrentSourceAuthorizationPort {
|
|
26
22
|
constructor(
|
|
27
23
|
private readonly resolveActor: (
|
|
28
24
|
actorId: string,
|
|
@@ -34,7 +30,7 @@ export class ResolvingCurrentSourceAuthorizationPort
|
|
|
34
30
|
): Promise<SourceAuthorizationCoordinate> {
|
|
35
31
|
const actor = await this.resolveActor(context.actor.id);
|
|
36
32
|
if (!actor || actor.type === "anonymous") throw unavailable();
|
|
37
|
-
return
|
|
33
|
+
return authorizationReadCoordinateForActor(actor);
|
|
38
34
|
}
|
|
39
35
|
}
|
|
40
36
|
|
|
@@ -76,9 +72,9 @@ export class SessionProjectionSourceAuthorizer {
|
|
|
76
72
|
} catch {
|
|
77
73
|
throw unavailable();
|
|
78
74
|
}
|
|
79
|
-
const expectedScope = `sha256:${
|
|
80
|
-
context.actor.scopeContext
|
|
81
|
-
|
|
75
|
+
const expectedScope = `sha256:${
|
|
76
|
+
captureAuthorizationScope(context.actor.scopeContext).hash
|
|
77
|
+
}`;
|
|
82
78
|
if (
|
|
83
79
|
authorization.actorId !== context.actor.id ||
|
|
84
80
|
authorization.scopeDigest !== expectedScope ||
|
|
@@ -91,11 +87,17 @@ export class SessionProjectionSourceAuthorizer {
|
|
|
91
87
|
for (const coordinate of coordinates) {
|
|
92
88
|
if (!validCoordinate(coordinate)) throw unavailable();
|
|
93
89
|
try {
|
|
94
|
-
await requireAuthoritativeSourceRead(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
90
|
+
await requireAuthoritativeSourceRead(
|
|
91
|
+
this.sources,
|
|
92
|
+
withSourceChainAudit(
|
|
93
|
+
{
|
|
94
|
+
source: causalSource(coordinate),
|
|
95
|
+
authorization,
|
|
96
|
+
requestId: context.requestId,
|
|
97
|
+
},
|
|
98
|
+
chainAudit,
|
|
99
|
+
),
|
|
100
|
+
);
|
|
99
101
|
} catch {
|
|
100
102
|
throw unavailable();
|
|
101
103
|
}
|
|
@@ -136,9 +138,8 @@ function unavailable(): SessionProjectionSourceUnavailableError {
|
|
|
136
138
|
export function authorizationCoordinateForActor(
|
|
137
139
|
actor: RequestActor,
|
|
138
140
|
): SourceAuthorizationCoordinate {
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
).hash}`;
|
|
141
|
+
const scope = captureAuthorizationScope(actor.scopeContext);
|
|
142
|
+
const scopeDigest = `sha256:${scope.hash}`;
|
|
142
143
|
const fingerprint = JSON.stringify({
|
|
143
144
|
actorId: actor.id,
|
|
144
145
|
actorType: actor.type,
|
|
@@ -146,10 +147,21 @@ export function authorizationCoordinateForActor(
|
|
|
146
147
|
roles: [...actor.roleCodes].sort(),
|
|
147
148
|
scopeDigest,
|
|
148
149
|
});
|
|
149
|
-
const prefix = createHash("sha256")
|
|
150
|
+
const prefix = createHash("sha256")
|
|
151
|
+
.update(fingerprint)
|
|
152
|
+
.digest("hex")
|
|
153
|
+
.slice(0, 13);
|
|
150
154
|
return {
|
|
151
155
|
actorId: actor.id,
|
|
152
156
|
scopeDigest,
|
|
153
157
|
generation: Math.max(1, Number.parseInt(prefix, 16)),
|
|
154
158
|
};
|
|
155
159
|
}
|
|
160
|
+
|
|
161
|
+
/** Read-only authority coordinate may carry the server-captured scope; invalidation envelopes stay small. */
|
|
162
|
+
export function authorizationReadCoordinateForActor(actor: RequestActor) {
|
|
163
|
+
return {
|
|
164
|
+
...authorizationCoordinateForActor(actor),
|
|
165
|
+
scopeSnapshot: captureAuthorizationScope(actor.scopeContext).snapshot,
|
|
166
|
+
} satisfies SourceAuthorizationCoordinate;
|
|
167
|
+
}
|
|
@@ -11,6 +11,12 @@ const clientSessionUnavailableRoutes = [
|
|
|
11
11
|
["POST", "/agent/client-sessions/:sessionId/cancel"],
|
|
12
12
|
] as const;
|
|
13
13
|
|
|
14
|
+
const clientWorkflowArtifactUnavailableRoutes = [
|
|
15
|
+
["POST", "/agent/client-workflow-artifacts/claim"],
|
|
16
|
+
["POST", "/agent/client-workflow-artifacts/advance"],
|
|
17
|
+
["POST", "/agent/client-workflow-artifacts/cancel"],
|
|
18
|
+
] as const;
|
|
19
|
+
|
|
14
20
|
const longSessionUnavailableRoutes = [
|
|
15
21
|
["GET", "/agent/harness/sessions"],
|
|
16
22
|
["GET", "/agent/harness/sessions/:sessionId"],
|
|
@@ -65,6 +71,21 @@ export function registerUnavailableAiRoutes(app: RouteApp): void {
|
|
|
65
71
|
"AI Runtime 未启用",
|
|
66
72
|
);
|
|
67
73
|
registerUnavailableClientAgentSessionRoutes(app, "AI Runtime 未启用");
|
|
74
|
+
registerUnavailableClientAgentWorkflowArtifactRoutes(
|
|
75
|
+
app,
|
|
76
|
+
"AI Runtime 未启用",
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function registerUnavailableClientAgentWorkflowArtifactRoutes(
|
|
81
|
+
app: RouteApp,
|
|
82
|
+
message = "Client Agent Workflow Artifact 未装配",
|
|
83
|
+
): void {
|
|
84
|
+
registerUnavailableRoutes(
|
|
85
|
+
app,
|
|
86
|
+
clientWorkflowArtifactUnavailableRoutes,
|
|
87
|
+
message,
|
|
88
|
+
);
|
|
68
89
|
}
|
|
69
90
|
|
|
70
91
|
export function registerUnavailableClientAgentSessionRoutes(
|
|
@@ -43,6 +43,8 @@ export function registerProductionAgentWorkflowRuntime(
|
|
|
43
43
|
modelPricingJson: input.platformConfig.agentWorkflow?.modelPricingJson,
|
|
44
44
|
evaluationTools: resolveProductionEvaluationToolRegistration(tools),
|
|
45
45
|
workspacePolicies: input.agentWorkflowWorkspacePolicies,
|
|
46
|
+
clientAgentWorkflowArtifactBindings:
|
|
47
|
+
input.clientAgentWorkflowArtifactBindings,
|
|
46
48
|
...dependencies,
|
|
47
49
|
...(dependencies
|
|
48
50
|
? {
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import type { AgentWorkflowArtifactRef } from "@southwind-ai/shared";
|
|
3
|
+
import type { AuthorizationScopeSnapshot } from "@southwind-ai/shared";
|
|
3
4
|
import type { RequestActor } from "../guards.js";
|
|
4
5
|
import type { AuthoritativeSourceAccessPort } from "../agent/session-invalidation/contracts.js";
|
|
5
6
|
import { requireAuthoritativeSourceRead } from "../agent/session-invalidation/read-guard.js";
|
|
6
|
-
import {
|
|
7
|
+
import { authorizationReadCoordinateForActor } from "../agent/session-projection-access.js";
|
|
8
|
+
import { captureAuthorizationScope } from "../data-access/scope-snapshot.js";
|
|
9
|
+
import { authorizationScopeContains } from "../data-access/scope-containment.js";
|
|
7
10
|
|
|
8
11
|
type CausalArtifactSource = AgentWorkflowArtifactRef["source"] & {
|
|
9
12
|
readonly sequence: number;
|
|
@@ -14,7 +17,7 @@ export interface AgentWorkflowArtifactSourceAuthorizationPort {
|
|
|
14
17
|
requireCurrent(input: {
|
|
15
18
|
readonly artifact: AgentWorkflowArtifactRef;
|
|
16
19
|
readonly actorId: string;
|
|
17
|
-
readonly
|
|
20
|
+
readonly frozenScope: AuthorizationScopeSnapshot;
|
|
18
21
|
}): Promise<void>;
|
|
19
22
|
}
|
|
20
23
|
|
|
@@ -30,20 +33,23 @@ export class ProductionAgentWorkflowArtifactSourceAuthorization implements Agent
|
|
|
30
33
|
async requireCurrent(input: {
|
|
31
34
|
readonly artifact: AgentWorkflowArtifactRef;
|
|
32
35
|
readonly actorId: string;
|
|
33
|
-
readonly
|
|
36
|
+
readonly frozenScope: AuthorizationScopeSnapshot;
|
|
34
37
|
}) {
|
|
35
38
|
try {
|
|
36
39
|
const source = causalSource(input.artifact);
|
|
37
40
|
assertSource(source);
|
|
38
41
|
const actor = await this.resolveActor(input.actorId);
|
|
39
42
|
if (!actor || actor.type === "anonymous") throw denied();
|
|
40
|
-
const
|
|
43
|
+
const currentScope = captureAuthorizationScope(actor.scopeContext);
|
|
41
44
|
if (
|
|
42
|
-
|
|
43
|
-
authorization.scopeDigest !== input.scopeDigest
|
|
45
|
+
!authorizationScopeContains(currentScope.snapshot, input.frozenScope)
|
|
44
46
|
) {
|
|
45
47
|
throw denied();
|
|
46
48
|
}
|
|
49
|
+
const authorization = authorizationReadCoordinateForActor(actor);
|
|
50
|
+
if (authorization.actorId !== input.actorId) {
|
|
51
|
+
throw denied();
|
|
52
|
+
}
|
|
47
53
|
await requireAuthoritativeSourceRead(this.sources, {
|
|
48
54
|
source: {
|
|
49
55
|
moduleKey: source.moduleKey,
|
|
@@ -38,11 +38,11 @@ import {
|
|
|
38
38
|
workflowRequestText,
|
|
39
39
|
} from "./command-input.js";
|
|
40
40
|
import { governedDefinitionToolSchemaVersion } from "./governed-tool-schema.js";
|
|
41
|
+
import { buildAgentWorkflowRelease } from "./release.js";
|
|
42
|
+
import type { ProjectAgentWorkflowLaunchAuthority } from "./project-launch-authority.js";
|
|
41
43
|
|
|
42
44
|
export { AgentWorkflowCommandError } from "./command-error.js";
|
|
43
45
|
|
|
44
|
-
type ServerRuntime = ReturnType<typeof createServerRuntime>;
|
|
45
|
-
|
|
46
46
|
export class ProductionAgentWorkflowCommandFacade {
|
|
47
47
|
constructor(
|
|
48
48
|
private readonly repository: AgentWorkflowRepository,
|
|
@@ -51,20 +51,37 @@ export class ProductionAgentWorkflowCommandFacade {
|
|
|
51
51
|
private readonly evaluations: AgentWorkflowEvaluationService,
|
|
52
52
|
private readonly evaluationRepository: AgentWorkflowEvaluationRepository,
|
|
53
53
|
private readonly modules: readonly ModuleManifest[],
|
|
54
|
-
private readonly runtime:
|
|
54
|
+
private readonly runtime: ReturnType<typeof createServerRuntime>,
|
|
55
55
|
private readonly tools: GovernedToolRegistry,
|
|
56
56
|
private readonly waitSignals: AgentWorkflowWaitSignalService,
|
|
57
57
|
private readonly artifacts: AgentWorkflowArtifactPort,
|
|
58
58
|
private readonly workspacePolicies: AgentWorkflowWorkspacePolicyPort,
|
|
59
|
+
private readonly projectAuthority: ProjectAgentWorkflowLaunchAuthority,
|
|
59
60
|
private readonly schedulerFor: (
|
|
60
61
|
context: RequestGuardContext,
|
|
61
62
|
) => AgentWorkflowSchedulerCommandPort,
|
|
62
63
|
) {}
|
|
63
64
|
|
|
64
|
-
publish(body: unknown, context: RequestGuardContext) {
|
|
65
|
+
async publish(body: unknown, context: RequestGuardContext) {
|
|
66
|
+
return this.publishWithAuthority(body, context);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async publishProject(
|
|
70
|
+
body: unknown,
|
|
71
|
+
context: RequestGuardContext,
|
|
72
|
+
signal: AbortSignal,
|
|
73
|
+
) {
|
|
74
|
+
return this.publishWithAuthority(body, context, signal);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private async publishWithAuthority(
|
|
78
|
+
body: unknown,
|
|
79
|
+
context: RequestGuardContext,
|
|
80
|
+
signal?: AbortSignal,
|
|
81
|
+
) {
|
|
65
82
|
const value = workflowRequestObject(body);
|
|
66
83
|
const coordinates = workflowRequestObject(value.coordinates);
|
|
67
|
-
|
|
84
|
+
const publishInput = {
|
|
68
85
|
definition: value.definition as AgentWorkflowDefinition,
|
|
69
86
|
coordinates: {
|
|
70
87
|
runtimeVersion: workflowRequestText(
|
|
@@ -87,23 +104,66 @@ export class ProductionAgentWorkflowCommandFacade {
|
|
|
87
104
|
} satisfies AgentWorkflowReleaseCoordinates,
|
|
88
105
|
publishedBy: workflowActor(context),
|
|
89
106
|
publishedAt: new Date().toISOString(),
|
|
90
|
-
}
|
|
107
|
+
};
|
|
108
|
+
const release = buildAgentWorkflowRelease(publishInput);
|
|
109
|
+
if (signal) {
|
|
110
|
+
await this.projectAuthority.authorizeRelease({
|
|
111
|
+
definition: release.definition,
|
|
112
|
+
coordinates: release.coordinates,
|
|
113
|
+
releaseDigest: release.releaseDigest,
|
|
114
|
+
actorId: context.actor.id,
|
|
115
|
+
signal,
|
|
116
|
+
});
|
|
117
|
+
} else {
|
|
118
|
+
this.projectAuthority.requireDirect(release.definition.workflowKey);
|
|
119
|
+
}
|
|
120
|
+
return this.service.publish(publishInput);
|
|
91
121
|
}
|
|
92
122
|
|
|
93
123
|
async createRun(
|
|
94
124
|
body: unknown,
|
|
95
125
|
context: RequestGuardContext,
|
|
96
126
|
signal: AbortSignal,
|
|
127
|
+
) {
|
|
128
|
+
return this.createRunWithAuthority(body, context, signal, false);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async createProjectRun(
|
|
132
|
+
body: unknown,
|
|
133
|
+
context: RequestGuardContext,
|
|
134
|
+
signal: AbortSignal,
|
|
135
|
+
) {
|
|
136
|
+
return this.createRunWithAuthority(body, context, signal, true);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private async createRunWithAuthority(
|
|
140
|
+
body: unknown,
|
|
141
|
+
context: RequestGuardContext,
|
|
142
|
+
signal: AbortSignal,
|
|
143
|
+
project: boolean,
|
|
97
144
|
) {
|
|
98
145
|
const value = workflowRequestObject(body);
|
|
99
146
|
const releaseId = workflowRequestText(value.releaseId, "releaseId");
|
|
100
147
|
const release = await this.repository.getRelease(releaseId);
|
|
101
148
|
if (!release) throw new AgentWorkflowCommandError("RELEASE_NOT_FOUND", 404);
|
|
102
|
-
const
|
|
149
|
+
const inputValue = (value.input ?? {}) as JsonValue;
|
|
150
|
+
const inputArtifacts = workflowArtifactRefs(value.inputArtifacts);
|
|
151
|
+
const authorizedContext = project
|
|
152
|
+
? await this.projectAuthority.authorizeRun({
|
|
153
|
+
release,
|
|
154
|
+
workflowInput: inputValue,
|
|
155
|
+
inputArtifacts,
|
|
156
|
+
context,
|
|
157
|
+
signal,
|
|
158
|
+
})
|
|
159
|
+
: context;
|
|
160
|
+
if (!project) {
|
|
161
|
+
this.projectAuthority.requireDirect(release.definition.workflowKey);
|
|
162
|
+
}
|
|
163
|
+
const authorization = await this.authorization(authorizedContext, release);
|
|
103
164
|
const now = new Date();
|
|
104
165
|
const budget = optionalWorkflowBudget(value.budget);
|
|
105
166
|
const effectiveBudget = budget ?? release.definition.budget;
|
|
106
|
-
const inputValue = (value.input ?? {}) as JsonValue;
|
|
107
167
|
const entry = release.definition.nodes.find(
|
|
108
168
|
({ id }) => id === release.definition.entryNodeId,
|
|
109
169
|
)!;
|
|
@@ -113,7 +173,6 @@ export class ProductionAgentWorkflowCommandFacade {
|
|
|
113
173
|
at: now.toISOString(),
|
|
114
174
|
});
|
|
115
175
|
const inputDigest = inputReceipt.valueDigest;
|
|
116
|
-
const inputArtifacts = workflowArtifactRefs(value.inputArtifacts);
|
|
117
176
|
if (
|
|
118
177
|
inputArtifacts.length &&
|
|
119
178
|
!(await this.artifacts.reauthorize({
|
|
@@ -150,12 +209,12 @@ export class ProductionAgentWorkflowCommandFacade {
|
|
|
150
209
|
});
|
|
151
210
|
await driveWorkflowBatch({
|
|
152
211
|
repository: this.repository,
|
|
153
|
-
scheduler: this.schedulerFor(
|
|
212
|
+
scheduler: this.schedulerFor(authorizedContext),
|
|
154
213
|
runId: result.record.run.runId,
|
|
155
214
|
authorizationFence: authorization.fence,
|
|
156
215
|
signal,
|
|
157
216
|
});
|
|
158
|
-
return this.query.detail(result.record.run.runId,
|
|
217
|
+
return this.query.detail(result.record.run.runId, authorizedContext);
|
|
159
218
|
}
|
|
160
219
|
|
|
161
220
|
async cancel(
|
|
@@ -155,15 +155,6 @@ export class DrizzleAgentWorkflowArtifactPort implements AgentWorkflowArtifactPo
|
|
|
155
155
|
) {
|
|
156
156
|
const durable = await this.durableById(artifact.artifactId);
|
|
157
157
|
if (!durable || !sameWorkflowArtifact(durable, artifact)) return undefined;
|
|
158
|
-
try {
|
|
159
|
-
await this.sourceAuthorization.requireCurrent({
|
|
160
|
-
artifact,
|
|
161
|
-
actorId,
|
|
162
|
-
scopeDigest,
|
|
163
|
-
});
|
|
164
|
-
} catch {
|
|
165
|
-
return undefined;
|
|
166
|
-
}
|
|
167
158
|
const [job] = await this.db
|
|
168
159
|
.select({ authorizationScope: durableJobs.authorizationScope })
|
|
169
160
|
.from(durableJobs)
|
|
@@ -175,6 +166,15 @@ export class DrizzleAgentWorkflowArtifactPort implements AgentWorkflowArtifactPo
|
|
|
175
166
|
) {
|
|
176
167
|
return undefined;
|
|
177
168
|
}
|
|
169
|
+
try {
|
|
170
|
+
await this.sourceAuthorization.requireCurrent({
|
|
171
|
+
artifact,
|
|
172
|
+
actorId,
|
|
173
|
+
frozenScope: job.authorizationScope,
|
|
174
|
+
});
|
|
175
|
+
} catch {
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
178
|
const inspected = await this.durableArtifacts
|
|
179
179
|
.inspect(durable.jobId, durable.kind, actorId)
|
|
180
180
|
.catch(() => undefined);
|
|
@@ -46,7 +46,7 @@ export async function completeDelegation(input: {
|
|
|
46
46
|
await input.artifactSources!.requireCurrent({
|
|
47
47
|
artifact,
|
|
48
48
|
actorId: parent.actorId,
|
|
49
|
-
|
|
49
|
+
frozenScope: input.row.grantJson.capabilityCeiling.scopeSnapshot,
|
|
50
50
|
});
|
|
51
51
|
}
|
|
52
52
|
await bindDelegationChild({
|
|
@@ -18,6 +18,7 @@ import type {
|
|
|
18
18
|
AgentWorkflowNodeAdapterContext,
|
|
19
19
|
} from "./adapter-dispatch.js";
|
|
20
20
|
import type { WorkflowEffectCommandFence } from "./effect-command-fence.js";
|
|
21
|
+
import { CLIENT_AGENT_WORKFLOW_ARTIFACT_TASK_KEY } from "@southwind-ai/server-sdk";
|
|
21
22
|
import { createAgentWorkflowNodeAdapterRegistry } from "./node-adapter-factory.js";
|
|
22
23
|
import {
|
|
23
24
|
directPlatformNodeAdapter,
|
|
@@ -93,7 +94,11 @@ function jobAdapter(
|
|
|
93
94
|
const scope = captureAuthorizationScope(context.actor.scopeContext);
|
|
94
95
|
const submit = async (
|
|
95
96
|
nodeContext: AgentWorkflowNodeAdapterContext,
|
|
96
|
-
|
|
97
|
+
command: {
|
|
98
|
+
readonly commandId: string;
|
|
99
|
+
readonly generation: number;
|
|
100
|
+
readonly requestDigest: string;
|
|
101
|
+
},
|
|
97
102
|
idempotencyKey: string,
|
|
98
103
|
) => {
|
|
99
104
|
const node = nodeContext.node;
|
|
@@ -103,13 +108,16 @@ function jobAdapter(
|
|
|
103
108
|
queue: "agent-workflow",
|
|
104
109
|
idempotencyKey,
|
|
105
110
|
payload: {
|
|
106
|
-
commandId,
|
|
111
|
+
commandId: command.commandId,
|
|
107
112
|
runId: nodeContext.run.runId,
|
|
108
113
|
nodeRunId: nodeContext.nodeRun.nodeRunId,
|
|
114
|
+
effectGeneration: command.generation,
|
|
115
|
+
requestDigest: command.requestDigest,
|
|
109
116
|
},
|
|
110
117
|
requestedBy: context.actor.id,
|
|
111
118
|
authorizationScope: scope.snapshot,
|
|
112
|
-
maxAttempts:
|
|
119
|
+
maxAttempts:
|
|
120
|
+
node.taskKey === CLIENT_AGENT_WORKFLOW_ARTIFACT_TASK_KEY ? 3 : 1,
|
|
113
121
|
timeoutSeconds: node.timeoutSeconds ?? 900,
|
|
114
122
|
});
|
|
115
123
|
if (
|
|
@@ -140,7 +148,7 @@ function jobAdapter(
|
|
|
140
148
|
async dispatch({ context: nodeContext, command, fence }) {
|
|
141
149
|
const submitted = await submit(
|
|
142
150
|
nodeContext,
|
|
143
|
-
command.
|
|
151
|
+
{ ...command, generation: fence.generation },
|
|
144
152
|
command.idempotencyKey,
|
|
145
153
|
);
|
|
146
154
|
return jobResult(nodeContext, fence, await jobs.get(submitted.job.id));
|
|
@@ -153,7 +161,7 @@ function jobAdapter(
|
|
|
153
161
|
}) {
|
|
154
162
|
const submitted = await submit(
|
|
155
163
|
nodeContext,
|
|
156
|
-
command
|
|
164
|
+
command,
|
|
157
165
|
command.idempotencyKey,
|
|
158
166
|
);
|
|
159
167
|
const snapshot = await jobs.get(submitted.job.id);
|
|
@@ -171,7 +179,7 @@ function jobAdapter(
|
|
|
171
179
|
if (!command) return { cancelled: true };
|
|
172
180
|
const submitted = await submit(
|
|
173
181
|
nodeContext,
|
|
174
|
-
command
|
|
182
|
+
command,
|
|
175
183
|
command.idempotencyKey,
|
|
176
184
|
);
|
|
177
185
|
const snapshot = await jobs.get(submitted.job.id);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import type { ModuleClientAgentWorkflowArtifactProjectBinding } from "@southwind-ai/server-sdk";
|
|
3
|
+
import { ClientAgentWorkflowArtifactBindingRegistry } from "../agent/client-workflow-artifact/binding-registry.js";
|
|
4
|
+
import { ProjectAgentWorkflowLaunchAuthority } from "./project-launch-authority.js";
|
|
5
|
+
|
|
6
|
+
const binding = {
|
|
7
|
+
workflowKey: "analysis.full-case",
|
|
8
|
+
nodeId: "client-artifact",
|
|
9
|
+
operationKey: "analysis.page-agent",
|
|
10
|
+
releaseDigest: `sha256:${"d".repeat(64)}`,
|
|
11
|
+
scopeContainmentContractVersion: 1,
|
|
12
|
+
terminalResultAuthority: {
|
|
13
|
+
version: "sharp.result.v1",
|
|
14
|
+
digest: `sha256:${"e".repeat(64)}`,
|
|
15
|
+
async canonicalize({ proposedResult }) {
|
|
16
|
+
return proposedResult;
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
clientTaskAuthority: {
|
|
20
|
+
version: "sharp.task.v1",
|
|
21
|
+
digest: `sha256:${"f".repeat(64)}`,
|
|
22
|
+
async build({ workflowInput }) {
|
|
23
|
+
return { taskKey: "sharp.full-case", input: workflowInput };
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
launchAuthority: {
|
|
27
|
+
version: "sharp.launch.v1",
|
|
28
|
+
digest: `sha256:${"a".repeat(64)}`,
|
|
29
|
+
async authorizeRelease() {},
|
|
30
|
+
async authorizeRun({ currentAuthorizationScope }) {
|
|
31
|
+
return {
|
|
32
|
+
authorizationScope: currentAuthorizationScope,
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
artifact: {
|
|
37
|
+
kind: "analysis",
|
|
38
|
+
contentType: "application/json",
|
|
39
|
+
filename: "analysis.json",
|
|
40
|
+
retentionPolicyKey: "case-analysis",
|
|
41
|
+
maxByteSize: 65_536,
|
|
42
|
+
},
|
|
43
|
+
} satisfies ModuleClientAgentWorkflowArtifactProjectBinding;
|
|
44
|
+
|
|
45
|
+
test("generic command 对 project-protected Workflow 始终隐藏", () => {
|
|
46
|
+
const authority = new ProjectAgentWorkflowLaunchAuthority(
|
|
47
|
+
new ClientAgentWorkflowArtifactBindingRegistry([binding]),
|
|
48
|
+
);
|
|
49
|
+
expect(() => authority.requireDirect(binding.workflowKey)).toThrow(
|
|
50
|
+
"RELEASE_NOT_FOUND",
|
|
51
|
+
);
|
|
52
|
+
expect(() => authority.requireDirect("analysis.direct")).not.toThrow();
|
|
53
|
+
});
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AgentWorkflowArtifactRef,
|
|
3
|
+
AgentWorkflowDefinition,
|
|
4
|
+
AgentWorkflowRelease,
|
|
5
|
+
AgentWorkflowReleaseCoordinates,
|
|
6
|
+
JsonValue,
|
|
7
|
+
} from "@southwind-ai/shared";
|
|
8
|
+
import { authorizationScopeContains } from "../data-access/scope-containment.js";
|
|
9
|
+
import { captureAuthorizationScope } from "../data-access/scope-snapshot.js";
|
|
10
|
+
import { restoreServerScopeContext } from "../data-access/context.js";
|
|
11
|
+
import type { RequestGuardContext } from "../guards.js";
|
|
12
|
+
import { ClientAgentWorkflowArtifactBindingRegistry } from "../agent/client-workflow-artifact/binding-registry.js";
|
|
13
|
+
import { AgentWorkflowCommandError } from "./command-error.js";
|
|
14
|
+
|
|
15
|
+
export class ProjectAgentWorkflowLaunchAuthority {
|
|
16
|
+
constructor(
|
|
17
|
+
private readonly bindings: ClientAgentWorkflowArtifactBindingRegistry,
|
|
18
|
+
) {}
|
|
19
|
+
|
|
20
|
+
requireDirect(workflowKey: string) {
|
|
21
|
+
if (this.bindings.findWorkflow(workflowKey)) throw hidden();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async authorizeRelease(input: {
|
|
25
|
+
definition: AgentWorkflowDefinition;
|
|
26
|
+
coordinates: AgentWorkflowReleaseCoordinates;
|
|
27
|
+
actorId: string;
|
|
28
|
+
releaseDigest: string;
|
|
29
|
+
signal: AbortSignal;
|
|
30
|
+
}) {
|
|
31
|
+
const binding = this.requireBinding(
|
|
32
|
+
input.definition.workflowKey,
|
|
33
|
+
input.releaseDigest,
|
|
34
|
+
);
|
|
35
|
+
try {
|
|
36
|
+
await binding.launchAuthority.authorizeRelease(input);
|
|
37
|
+
} catch {
|
|
38
|
+
throw hidden();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async authorizeRun(input: {
|
|
43
|
+
release: AgentWorkflowRelease;
|
|
44
|
+
workflowInput: JsonValue;
|
|
45
|
+
inputArtifacts: readonly AgentWorkflowArtifactRef[];
|
|
46
|
+
context: RequestGuardContext;
|
|
47
|
+
signal: AbortSignal;
|
|
48
|
+
}): Promise<RequestGuardContext> {
|
|
49
|
+
const binding = this.requireBinding(
|
|
50
|
+
input.release.definition.workflowKey,
|
|
51
|
+
input.release.releaseDigest,
|
|
52
|
+
);
|
|
53
|
+
try {
|
|
54
|
+
const current = captureAuthorizationScope(
|
|
55
|
+
input.context.actor.scopeContext,
|
|
56
|
+
).snapshot;
|
|
57
|
+
const decision = await binding.launchAuthority.authorizeRun({
|
|
58
|
+
releaseId: input.release.releaseId,
|
|
59
|
+
releaseDigest: input.release.releaseDigest,
|
|
60
|
+
workflowInput: input.workflowInput,
|
|
61
|
+
inputArtifacts: input.inputArtifacts,
|
|
62
|
+
actorId: input.context.actor.id,
|
|
63
|
+
currentAuthorizationScope: structuredClone(current),
|
|
64
|
+
signal: input.signal,
|
|
65
|
+
});
|
|
66
|
+
if (!authorizationScopeContains(current, decision.authorizationScope)) {
|
|
67
|
+
throw hidden();
|
|
68
|
+
}
|
|
69
|
+
const scope = restoreServerScopeContext(decision.authorizationScope);
|
|
70
|
+
return {
|
|
71
|
+
...input.context,
|
|
72
|
+
actor: {
|
|
73
|
+
...input.context.actor,
|
|
74
|
+
dataAccess: scope,
|
|
75
|
+
scopeContext: scope,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
} catch {
|
|
79
|
+
throw hidden();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private requireBinding(workflowKey: string, releaseDigest: string) {
|
|
84
|
+
const binding = this.bindings.findWorkflow(workflowKey);
|
|
85
|
+
if (!binding || binding.releaseDigest !== releaseDigest) throw hidden();
|
|
86
|
+
return binding;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function hidden() {
|
|
91
|
+
return new AgentWorkflowCommandError("RELEASE_NOT_FOUND", 404);
|
|
92
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ModuleManifest } from "@southwind-ai/modules";
|
|
2
|
+
import type { ModuleClientAgentWorkflowArtifactProjectBinding } from "@southwind-ai/server-sdk";
|
|
2
3
|
import {
|
|
3
4
|
DurableHandlerError,
|
|
4
5
|
type DurableHandlerRegistry,
|
|
@@ -55,6 +56,8 @@ import {
|
|
|
55
56
|
createProductionWorkflowConditions,
|
|
56
57
|
createProductionWorkspacePolicies,
|
|
57
58
|
} from "./production-node-policies.js";
|
|
59
|
+
import { ClientAgentWorkflowArtifactBindingRegistry } from "../agent/client-workflow-artifact/binding-registry.js";
|
|
60
|
+
import { ProjectAgentWorkflowLaunchAuthority } from "./project-launch-authority.js";
|
|
58
61
|
|
|
59
62
|
export function composeProductionAgentWorkflowRuntime(input: {
|
|
60
63
|
readonly db?: NodePgDatabase;
|
|
@@ -80,6 +83,7 @@ export function composeProductionAgentWorkflowRuntime(input: {
|
|
|
80
83
|
readonly resolveActor?: (
|
|
81
84
|
actorId: string,
|
|
82
85
|
) => Promise<RequestActor | undefined>;
|
|
86
|
+
readonly clientAgentWorkflowArtifactBindings?: readonly ModuleClientAgentWorkflowArtifactProjectBinding[];
|
|
83
87
|
}) {
|
|
84
88
|
if (
|
|
85
89
|
!input.db ||
|
|
@@ -119,6 +123,11 @@ export function composeProductionAgentWorkflowRuntime(input: {
|
|
|
119
123
|
artifactSourceAuthorization,
|
|
120
124
|
input.artifactAccessSecret,
|
|
121
125
|
);
|
|
126
|
+
const projectAuthority = new ProjectAgentWorkflowLaunchAuthority(
|
|
127
|
+
new ClientAgentWorkflowArtifactBindingRegistry(
|
|
128
|
+
input.clientAgentWorkflowArtifactBindings ?? [],
|
|
129
|
+
),
|
|
130
|
+
);
|
|
122
131
|
const modelPricing = AgentWorkflowModelPricingCatalog.fromJson(
|
|
123
132
|
input.modelPricingJson,
|
|
124
133
|
);
|
|
@@ -275,6 +284,21 @@ export function composeProductionAgentWorkflowRuntime(input: {
|
|
|
275
284
|
return port;
|
|
276
285
|
}
|
|
277
286
|
continuations.start();
|
|
287
|
+
const commands = new ProductionAgentWorkflowCommandFacade(
|
|
288
|
+
repository,
|
|
289
|
+
service,
|
|
290
|
+
query,
|
|
291
|
+
evaluations,
|
|
292
|
+
evaluationRepository,
|
|
293
|
+
input.modules,
|
|
294
|
+
input.runtime,
|
|
295
|
+
input.tools,
|
|
296
|
+
waitSignals,
|
|
297
|
+
artifacts,
|
|
298
|
+
workspacePolicies,
|
|
299
|
+
projectAuthority,
|
|
300
|
+
schedulerFor,
|
|
301
|
+
);
|
|
278
302
|
return {
|
|
279
303
|
query,
|
|
280
304
|
artifacts,
|
|
@@ -290,19 +314,11 @@ export function composeProductionAgentWorkflowRuntime(input: {
|
|
|
290
314
|
safeCode: "MODEL_PRICING_UNAVAILABLE",
|
|
291
315
|
},
|
|
292
316
|
},
|
|
293
|
-
commands
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
input.modules,
|
|
300
|
-
input.runtime,
|
|
301
|
-
input.tools,
|
|
302
|
-
waitSignals,
|
|
303
|
-
artifacts,
|
|
304
|
-
workspacePolicies,
|
|
305
|
-
schedulerFor,
|
|
306
|
-
),
|
|
317
|
+
commands,
|
|
318
|
+
/** Project-owned application Seam; intentionally not mounted on generic routes. */
|
|
319
|
+
projectCommands: {
|
|
320
|
+
publish: commands.publishProject.bind(commands),
|
|
321
|
+
createRun: commands.createProjectRun.bind(commands),
|
|
322
|
+
},
|
|
307
323
|
};
|
|
308
324
|
}
|