@plumbus/core 0.4.2 → 0.5.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/README.md +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/api/route-generator.d.ts.map +1 -1
- package/dist/api/route-generator.js +27 -14
- package/dist/api/route-generator.js.map +1 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +2 -1
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +38 -149
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +6 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +92 -4
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/event.d.ts.map +1 -1
- package/dist/cli/commands/event.js +3 -0
- package/dist/cli/commands/event.js.map +1 -1
- package/dist/cli/commands/events-ops.d.ts +4 -0
- package/dist/cli/commands/events-ops.d.ts.map +1 -0
- package/dist/cli/commands/events-ops.js +203 -0
- package/dist/cli/commands/events-ops.js.map +1 -0
- package/dist/cli/commands/flow.d.ts.map +1 -1
- package/dist/cli/commands/flow.js +49 -1
- package/dist/cli/commands/flow.js.map +1 -1
- package/dist/cli/commands/generate.d.ts +4 -0
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +94 -3
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +1 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +13 -3
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/mcp.d.ts.map +1 -1
- package/dist/cli/commands/mcp.js +2 -0
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/start.d.ts +3 -6
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +71 -180
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/verify.d.ts +3 -1
- package/dist/cli/commands/verify.d.ts.map +1 -1
- package/dist/cli/commands/verify.js +17 -9
- package/dist/cli/commands/verify.js.map +1 -1
- package/dist/cli/commands/worker.d.ts +19 -0
- package/dist/cli/commands/worker.d.ts.map +1 -0
- package/dist/cli/commands/worker.js +234 -0
- package/dist/cli/commands/worker.js.map +1 -0
- package/dist/cli/mcp-serve-context.d.ts +3 -0
- package/dist/cli/mcp-serve-context.d.ts.map +1 -1
- package/dist/cli/mcp-serve-context.js +16 -1
- package/dist/cli/mcp-serve-context.js.map +1 -1
- package/dist/cli/templates/resources.d.ts.map +1 -1
- package/dist/cli/templates/resources.js +7 -2
- package/dist/cli/templates/resources.js.map +1 -1
- package/dist/cli/utils.d.ts +4 -0
- package/dist/cli/utils.d.ts.map +1 -1
- package/dist/cli/utils.js +9 -0
- package/dist/cli/utils.js.map +1 -1
- package/dist/data/drift-inspector.d.ts +2 -2
- package/dist/data/drift-inspector.d.ts.map +1 -1
- package/dist/data/drift-inspector.js +2 -1
- package/dist/data/drift-inspector.js.map +1 -1
- package/dist/data/migration.d.ts.map +1 -1
- package/dist/data/migration.js +2 -0
- package/dist/data/migration.js.map +1 -1
- package/dist/define/defineCapability.d.ts +5 -0
- package/dist/define/defineCapability.d.ts.map +1 -1
- package/dist/define/defineCapability.js +23 -0
- package/dist/define/defineCapability.js.map +1 -1
- package/dist/errors/http.d.ts.map +1 -1
- package/dist/errors/http.js +1 -0
- package/dist/errors/http.js.map +1 -1
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +1 -0
- package/dist/errors/index.js.map +1 -1
- package/dist/events/dispatcher.d.ts +4 -0
- package/dist/events/dispatcher.d.ts.map +1 -1
- package/dist/events/dispatcher.js +24 -1
- package/dist/events/dispatcher.js.map +1 -1
- package/dist/events/emitter.d.ts +2 -0
- package/dist/events/emitter.d.ts.map +1 -1
- package/dist/events/emitter.js +6 -3
- package/dist/events/emitter.js.map +1 -1
- package/dist/events/queue-adapter.d.ts +7 -0
- package/dist/events/queue-adapter.d.ts.map +1 -0
- package/dist/events/queue-adapter.js +4 -0
- package/dist/events/queue-adapter.js.map +1 -0
- package/dist/events/queue.d.ts +16 -13
- package/dist/events/queue.d.ts.map +1 -1
- package/dist/events/queue.js +79 -22
- package/dist/events/queue.js.map +1 -1
- package/dist/events/worker.d.ts +4 -0
- package/dist/events/worker.d.ts.map +1 -1
- package/dist/events/worker.js +47 -1
- package/dist/events/worker.js.map +1 -1
- package/dist/execution/canonical-name.d.ts +13 -0
- package/dist/execution/canonical-name.d.ts.map +1 -0
- package/dist/execution/canonical-name.js +17 -0
- package/dist/execution/canonical-name.js.map +1 -0
- package/dist/execution/capability-executor.d.ts +1 -1
- package/dist/execution/capability-executor.d.ts.map +1 -1
- package/dist/execution/capability-executor.js +52 -24
- package/dist/execution/capability-executor.js.map +1 -1
- package/dist/execution/capability-invocation.d.ts +34 -0
- package/dist/execution/capability-invocation.d.ts.map +1 -0
- package/dist/execution/capability-invocation.js +138 -0
- package/dist/execution/capability-invocation.js.map +1 -0
- package/dist/execution/capability-registry.d.ts +6 -4
- package/dist/execution/capability-registry.d.ts.map +1 -1
- package/dist/execution/capability-registry.js +13 -7
- package/dist/execution/capability-registry.js.map +1 -1
- package/dist/execution/context-factory.d.ts.map +1 -1
- package/dist/execution/context-factory.js +12 -1
- package/dist/execution/context-factory.js.map +1 -1
- package/dist/execution/index.d.ts +4 -0
- package/dist/execution/index.d.ts.map +1 -1
- package/dist/execution/index.js +2 -0
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/invocation-emit-scope.d.ts +11 -0
- package/dist/execution/invocation-emit-scope.d.ts.map +1 -0
- package/dist/execution/invocation-emit-scope.js +8 -0
- package/dist/execution/invocation-emit-scope.js.map +1 -0
- package/dist/flows/engine.d.ts +7 -1
- package/dist/flows/engine.d.ts.map +1 -1
- package/dist/flows/engine.js +73 -10
- package/dist/flows/engine.js.map +1 -1
- package/dist/flows/flow-delayed.d.ts +34 -0
- package/dist/flows/flow-delayed.d.ts.map +1 -0
- package/dist/flows/flow-delayed.js +60 -0
- package/dist/flows/flow-delayed.js.map +1 -0
- package/dist/flows/flow-queue.d.ts +10 -0
- package/dist/flows/flow-queue.d.ts.map +1 -0
- package/dist/flows/flow-queue.js +25 -0
- package/dist/flows/flow-queue.js.map +1 -0
- package/dist/flows/scheduler.d.ts +0 -12
- package/dist/flows/scheduler.d.ts.map +1 -1
- package/dist/flows/scheduler.js +15 -0
- package/dist/flows/scheduler.js.map +1 -1
- package/dist/flows/schema.d.ts +17 -0
- package/dist/flows/schema.d.ts.map +1 -1
- package/dist/flows/schema.js +2 -0
- package/dist/flows/schema.js.map +1 -1
- package/dist/flows/step-consumer.d.ts +24 -0
- package/dist/flows/step-consumer.d.ts.map +1 -0
- package/dist/flows/step-consumer.js +72 -0
- package/dist/flows/step-consumer.js.map +1 -0
- package/dist/flows/triggers.d.ts +1 -1
- package/dist/flows/triggers.d.ts.map +1 -1
- package/dist/flows/triggers.js +5 -7
- package/dist/flows/triggers.js.map +1 -1
- package/dist/governance/capability-source-scan.d.ts +7 -0
- package/dist/governance/capability-source-scan.d.ts.map +1 -0
- package/dist/governance/capability-source-scan.js +80 -0
- package/dist/governance/capability-source-scan.js.map +1 -0
- package/dist/governance/rules/architecture.d.ts.map +1 -1
- package/dist/governance/rules/architecture.js +2 -0
- package/dist/governance/rules/architecture.js.map +1 -1
- package/dist/governance/rules/capability-dependencies.d.ts +8 -0
- package/dist/governance/rules/capability-dependencies.d.ts.map +1 -0
- package/dist/governance/rules/capability-dependencies.js +195 -0
- package/dist/governance/rules/capability-dependencies.js.map +1 -0
- package/dist/governance/rules/index.d.ts +2 -0
- package/dist/governance/rules/index.d.ts.map +1 -1
- package/dist/governance/rules/index.js +2 -0
- package/dist/governance/rules/index.js.map +1 -1
- package/dist/governance/rules/worker.d.ts +9 -0
- package/dist/governance/rules/worker.d.ts.map +1 -0
- package/dist/governance/rules/worker.js +89 -0
- package/dist/governance/rules/worker.js.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/jobs/dispatch.d.ts +18 -0
- package/dist/jobs/dispatch.d.ts.map +1 -0
- package/dist/jobs/dispatch.js +50 -0
- package/dist/jobs/dispatch.js.map +1 -0
- package/dist/jobs/index.d.ts +9 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +8 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/jobs/routes.d.ts +10 -0
- package/dist/jobs/routes.d.ts.map +1 -0
- package/dist/jobs/routes.js +44 -0
- package/dist/jobs/routes.js.map +1 -0
- package/dist/jobs/schema.d.ts +264 -0
- package/dist/jobs/schema.d.ts.map +1 -0
- package/dist/jobs/schema.js +34 -0
- package/dist/jobs/schema.js.map +1 -0
- package/dist/jobs/service.d.ts +52 -0
- package/dist/jobs/service.d.ts.map +1 -0
- package/dist/jobs/service.js +168 -0
- package/dist/jobs/service.js.map +1 -0
- package/dist/jobs/types.d.ts +30 -0
- package/dist/jobs/types.d.ts.map +1 -0
- package/dist/jobs/types.js +4 -0
- package/dist/jobs/types.js.map +1 -0
- package/dist/mcp/manifest-generator.d.ts.map +1 -1
- package/dist/mcp/manifest-generator.js +3 -2
- package/dist/mcp/manifest-generator.js.map +1 -1
- package/dist/observability/metrics.d.ts +9 -1
- package/dist/observability/metrics.d.ts.map +1 -1
- package/dist/observability/metrics.js +28 -1
- package/dist/observability/metrics.js.map +1 -1
- package/dist/runtime/bootstrap.d.ts +51 -0
- package/dist/runtime/bootstrap.d.ts.map +1 -0
- package/dist/runtime/bootstrap.js +140 -0
- package/dist/runtime/bootstrap.js.map +1 -0
- package/dist/runtime/index.d.ts +7 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +6 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/load-extensions.d.ts +4 -0
- package/dist/runtime/load-extensions.d.ts.map +1 -0
- package/dist/runtime/load-extensions.js +41 -0
- package/dist/runtime/load-extensions.js.map +1 -0
- package/dist/runtime/queue-factory.d.ts +44 -0
- package/dist/runtime/queue-factory.d.ts.map +1 -0
- package/dist/runtime/queue-factory.js +156 -0
- package/dist/runtime/queue-factory.js.map +1 -0
- package/dist/runtime/register-consumers.d.ts +29 -0
- package/dist/runtime/register-consumers.d.ts.map +1 -0
- package/dist/runtime/register-consumers.js +233 -0
- package/dist/runtime/register-consumers.js.map +1 -0
- package/dist/runtime/start-worker-pool.d.ts +32 -0
- package/dist/runtime/start-worker-pool.d.ts.map +1 -0
- package/dist/runtime/start-worker-pool.js +91 -0
- package/dist/runtime/start-worker-pool.js.map +1 -0
- package/dist/runtime/worker-health.d.ts +19 -0
- package/dist/runtime/worker-health.d.ts.map +1 -0
- package/dist/runtime/worker-health.js +41 -0
- package/dist/runtime/worker-health.js.map +1 -0
- package/dist/server/bootstrap.d.ts +6 -0
- package/dist/server/bootstrap.d.ts.map +1 -1
- package/dist/server/bootstrap.js +18 -1
- package/dist/server/bootstrap.js.map +1 -1
- package/dist/testing/context.d.ts +3 -0
- package/dist/testing/context.d.ts.map +1 -1
- package/dist/testing/context.js +10 -0
- package/dist/testing/context.js.map +1 -1
- package/dist/testing/simulate-flow.d.ts.map +1 -1
- package/dist/testing/simulate-flow.js +10 -0
- package/dist/testing/simulate-flow.js.map +1 -1
- package/dist/types/capability.d.ts +8 -0
- package/dist/types/capability.d.ts.map +1 -1
- package/dist/types/capability.js.map +1 -1
- package/dist/types/config.d.ts +2 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/context.d.ts +34 -1
- package/dist/types/context.d.ts.map +1 -1
- package/dist/types/enums.d.ts +1 -0
- package/dist/types/enums.d.ts.map +1 -1
- package/dist/types/enums.js +1 -0
- package/dist/types/enums.js.map +1 -1
- package/dist/types/errors.d.ts +1 -0
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/event.d.ts +10 -0
- package/dist/types/event.d.ts.map +1 -1
- package/dist/types/event.js +5 -1
- package/dist/types/event.js.map +1 -1
- package/dist/worker/bootstrap.d.ts +32 -1
- package/dist/worker/bootstrap.d.ts.map +1 -1
- package/dist/worker/bootstrap.js +166 -2
- package/dist/worker/bootstrap.js.map +1 -1
- package/instructions/capabilities.md +36 -1
- package/instructions/deployment.md +96 -11
- package/instructions/events.md +11 -0
- package/instructions/flows.md +12 -4
- package/instructions/governance.md +6 -0
- package/instructions/mcp.md +1 -1
- package/instructions/patterns.md +1 -0
- package/instructions/security.md +9 -0
- package/instructions/testing.md +12 -1
- package/instructions/upgrading-0.5-capabilities.md +181 -0
- package/package.json +12 -4
package/dist/events/worker.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createJobService } from '../jobs/service.js';
|
|
1
2
|
import { deadLetterTable } from './outbox.js';
|
|
2
3
|
/**
|
|
3
4
|
* Creates an event delivery worker that subscribes to the queue,
|
|
@@ -7,7 +8,7 @@ import { deadLetterTable } from './outbox.js';
|
|
|
7
8
|
* Returns start/stop controls.
|
|
8
9
|
*/
|
|
9
10
|
export function createEventWorker(config) {
|
|
10
|
-
const { db, queue, consumers, idempotency, defaultMaxRetries = 3, retryBackoffBaseMs = 100, retryBackoffMaxMs = 5000, } = config;
|
|
11
|
+
const { db, queue, consumers, idempotency, defaultMaxRetries = 3, metrics, audit, retryBackoffBaseMs = 100, retryBackoffMaxMs = 5000, } = config;
|
|
11
12
|
let unsubscribe = null;
|
|
12
13
|
/** Compute exponential backoff with jitter */
|
|
13
14
|
function computeRetryDelay(attempt) {
|
|
@@ -20,6 +21,7 @@ export function createEventWorker(config) {
|
|
|
20
21
|
}
|
|
21
22
|
async function deliver(envelope) {
|
|
22
23
|
const matched = consumers.getConsumers(envelope.eventType, envelope.version);
|
|
24
|
+
const deliveryStarted = Date.now();
|
|
23
25
|
for (const consumer of matched) {
|
|
24
26
|
const maxRetries = consumer.maxRetries ?? defaultMaxRetries;
|
|
25
27
|
// Idempotency guard
|
|
@@ -32,6 +34,14 @@ export function createEventWorker(config) {
|
|
|
32
34
|
while (attempt < maxRetries && !succeeded) {
|
|
33
35
|
attempt++;
|
|
34
36
|
try {
|
|
37
|
+
await audit?.record('event.consumer.attempt', {
|
|
38
|
+
eventId: envelope.id,
|
|
39
|
+
eventType: envelope.eventType,
|
|
40
|
+
consumerId: consumer.id,
|
|
41
|
+
attempt,
|
|
42
|
+
tenantId: envelope.tenantId,
|
|
43
|
+
outcome: 'pending',
|
|
44
|
+
});
|
|
35
45
|
await consumer.handler(envelope);
|
|
36
46
|
succeeded = true;
|
|
37
47
|
}
|
|
@@ -44,8 +54,34 @@ export function createEventWorker(config) {
|
|
|
44
54
|
}
|
|
45
55
|
if (succeeded) {
|
|
46
56
|
await idempotency.markProcessed(envelope.id, consumer.id);
|
|
57
|
+
metrics?.eventDelivered.inc({ consumer: consumer.id });
|
|
58
|
+
metrics?.eventDeliveryDuration.observe(Date.now() - deliveryStarted, {
|
|
59
|
+
consumer: consumer.id,
|
|
60
|
+
outcome: 'delivered',
|
|
61
|
+
});
|
|
62
|
+
await audit?.record('event.consumer.delivered', {
|
|
63
|
+
eventId: envelope.id,
|
|
64
|
+
eventType: envelope.eventType,
|
|
65
|
+
consumerId: consumer.id,
|
|
66
|
+
tenantId: envelope.tenantId,
|
|
67
|
+
outcome: 'success',
|
|
68
|
+
});
|
|
47
69
|
}
|
|
48
70
|
else {
|
|
71
|
+
metrics?.eventFailed.inc({ consumer: consumer.id });
|
|
72
|
+
metrics?.eventDeliveryDuration.observe(Date.now() - deliveryStarted, {
|
|
73
|
+
consumer: consumer.id,
|
|
74
|
+
outcome: 'failed',
|
|
75
|
+
});
|
|
76
|
+
await audit?.record('event.consumer.dead_lettered', {
|
|
77
|
+
eventId: envelope.id,
|
|
78
|
+
eventType: envelope.eventType,
|
|
79
|
+
consumerId: consumer.id,
|
|
80
|
+
tenantId: envelope.tenantId,
|
|
81
|
+
lastError,
|
|
82
|
+
attempts: attempt,
|
|
83
|
+
outcome: 'dead_lettered',
|
|
84
|
+
});
|
|
49
85
|
// Dead-letter
|
|
50
86
|
await db.insert(deadLetterTable).values({
|
|
51
87
|
eventId: envelope.id,
|
|
@@ -61,6 +97,16 @@ export function createEventWorker(config) {
|
|
|
61
97
|
tenantId: envelope.tenantId,
|
|
62
98
|
},
|
|
63
99
|
});
|
|
100
|
+
if (consumer.id.startsWith('job:')) {
|
|
101
|
+
const payload = envelope.payload;
|
|
102
|
+
if (payload.jobExecutionId) {
|
|
103
|
+
const jobs = createJobService(db);
|
|
104
|
+
await jobs.markDeadLettered(payload.jobExecutionId, {
|
|
105
|
+
code: 'delivery_exhausted',
|
|
106
|
+
message: lastError ?? 'Job delivery exhausted retries',
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
64
110
|
}
|
|
65
111
|
}
|
|
66
112
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/events/worker.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/events/worker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Minimal shape for deriving a registered capability name. */
|
|
2
|
+
export interface CanonicalCapabilityRef {
|
|
3
|
+
domain: string;
|
|
4
|
+
name: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Canonical registered capability name: `<domain>.<capabilityName>`.
|
|
8
|
+
* Used for registry lookup, effects.capabilities, flow steps, invoke, manifests, and audit.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getCanonicalCapabilityName(ref: CanonicalCapabilityRef): string;
|
|
11
|
+
/** True when `value` looks like a canonical capability name (contains a domain prefix). */
|
|
12
|
+
export declare function isCanonicalCapabilityName(value: string): boolean;
|
|
13
|
+
//# sourceMappingURL=canonical-name.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical-name.d.ts","sourceRoot":"","sources":["../../src/execution/canonical-name.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,sBAAsB,GAAG,MAAM,CAE9E;AAED,2FAA2F;AAC3F,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAOhE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical registered capability name: `<domain>.<capabilityName>`.
|
|
3
|
+
* Used for registry lookup, effects.capabilities, flow steps, invoke, manifests, and audit.
|
|
4
|
+
*/
|
|
5
|
+
export function getCanonicalCapabilityName(ref) {
|
|
6
|
+
return `${ref.domain}.${ref.name}`;
|
|
7
|
+
}
|
|
8
|
+
/** True when `value` looks like a canonical capability name (contains a domain prefix). */
|
|
9
|
+
export function isCanonicalCapabilityName(value) {
|
|
10
|
+
const trimmed = value.trim();
|
|
11
|
+
if (!trimmed.includes('.')) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
const dot = trimmed.indexOf('.');
|
|
15
|
+
return dot > 0 && dot < trimmed.length - 1;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=canonical-name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical-name.js","sourceRoot":"","sources":["../../src/execution/canonical-name.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CAAC,GAA2B;IACpE,OAAO,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;AACrC,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,yBAAyB,CAAC,KAAa;IACrD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,OAAO,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -15,7 +15,7 @@ export type CapabilityResult<T = unknown> = ExecutionResult<T> | ExecutionFailur
|
|
|
15
15
|
* Execute a capability through the full pipeline:
|
|
16
16
|
* 1. Validate input
|
|
17
17
|
* 2. Evaluate access policy
|
|
18
|
-
* 3. Execute handler
|
|
18
|
+
* 3. Execute handler (with scoped ctx.capabilities)
|
|
19
19
|
* 4. Validate output
|
|
20
20
|
* 5. Record audit
|
|
21
21
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability-executor.d.ts","sourceRoot":"","sources":["../../src/execution/capability-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAG7B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"capability-executor.d.ts","sourceRoot":"","sources":["../../src/execution/capability-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAG7B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAU3D,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,CAAC,CAAC;CACT;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAED,MAAM,MAAM,gBAAgB,CAAC,CAAC,GAAG,OAAO,IAAI,eAAe,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC;AAElF;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,SAAS,CAAC,CAAC,UAAU,EAAE,OAAO,SAAS,CAAC,CAAC,UAAU,EAC/F,UAAU,EAAE,kBAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/C,GAAG,EAAE,gBAAgB,EACrB,QAAQ,EAAE,OAAO,GAChB,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CA6H7C"}
|
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
import { isProviderAPIError } from '../ai/provider.js';
|
|
2
2
|
import { isPlumbusError } from '../errors/index.js';
|
|
3
3
|
import { evaluateAccess } from './authorization.js';
|
|
4
|
+
import { getCanonicalCapabilityName } from './canonical-name.js';
|
|
5
|
+
import { createCapabilityInvokeService, createUnavailableCapabilityService, stripHandlerRuntime, } from './capability-invocation.js';
|
|
4
6
|
/**
|
|
5
7
|
* Execute a capability through the full pipeline:
|
|
6
8
|
* 1. Validate input
|
|
7
9
|
* 2. Evaluate access policy
|
|
8
|
-
* 3. Execute handler
|
|
10
|
+
* 3. Execute handler (with scoped ctx.capabilities)
|
|
9
11
|
* 4. Validate output
|
|
10
12
|
* 5. Record audit
|
|
11
13
|
*/
|
|
12
14
|
export async function executeCapability(capability, ctx, rawInput) {
|
|
15
|
+
const canonicalName = getCanonicalCapabilityName(capability);
|
|
13
16
|
// 1. Validate input against schema
|
|
14
17
|
const inputResult = capability.input.safeParse(rawInput);
|
|
15
18
|
if (!inputResult.success) {
|
|
16
19
|
const error = ctx.errors.validation('Invalid input', {
|
|
17
|
-
capability:
|
|
20
|
+
capability: canonicalName,
|
|
18
21
|
issues: inputResult.error.issues,
|
|
19
22
|
});
|
|
20
|
-
await recordAudit(ctx, capability, 'failure', { error });
|
|
23
|
+
await recordAudit(ctx, capability, canonicalName, 'failure', { error });
|
|
21
24
|
return { success: false, error };
|
|
22
25
|
}
|
|
23
26
|
const input = inputResult.data;
|
|
@@ -25,26 +28,42 @@ export async function executeCapability(capability, ctx, rawInput) {
|
|
|
25
28
|
const authResult = evaluateAccess(capability.access, ctx.auth);
|
|
26
29
|
if (!authResult.allowed) {
|
|
27
30
|
const error = ctx.errors.forbidden(authResult.reason ?? 'Access denied', {
|
|
28
|
-
capability:
|
|
31
|
+
capability: canonicalName,
|
|
29
32
|
});
|
|
30
|
-
await recordAudit(ctx, capability, 'denied', { error });
|
|
33
|
+
await recordAudit(ctx, capability, canonicalName, 'denied', { error });
|
|
31
34
|
return { success: false, error };
|
|
32
35
|
}
|
|
33
|
-
// 3. Execute handler
|
|
36
|
+
// 3. Execute handler with scoped capabilities service (invoker not exposed on __runtime)
|
|
37
|
+
const invoker = ctx.__runtime?.invokeCapability;
|
|
38
|
+
const resolveCapability = ctx.__runtime?.resolveCapability;
|
|
39
|
+
const emitScope = ctx.__runtime?.invocationEmitScope;
|
|
40
|
+
const invocationRuntime = invoker && resolveCapability
|
|
41
|
+
? { invoker: invoker, resolveCapability, emitScope }
|
|
42
|
+
: undefined;
|
|
43
|
+
const handlerCtx = {
|
|
44
|
+
...ctx,
|
|
45
|
+
capabilities: invocationRuntime
|
|
46
|
+
? createCapabilityInvokeService(capability, ctx, invocationRuntime)
|
|
47
|
+
: createUnavailableCapabilityService(ctx),
|
|
48
|
+
__runtime: stripHandlerRuntime(ctx.__runtime),
|
|
49
|
+
};
|
|
50
|
+
if (emitScope) {
|
|
51
|
+
emitScope.executingCapability = canonicalName;
|
|
52
|
+
}
|
|
34
53
|
let rawOutput;
|
|
35
54
|
try {
|
|
36
|
-
rawOutput = await capability.handler(
|
|
55
|
+
rawOutput = await capability.handler(handlerCtx, input);
|
|
37
56
|
}
|
|
38
57
|
catch (err) {
|
|
39
58
|
// If the handler threw a PlumbusError, surface it directly
|
|
40
59
|
if (isPlumbusError(err)) {
|
|
41
|
-
await recordAudit(ctx, capability, 'failure', { error: err });
|
|
60
|
+
await recordAudit(ctx, capability, canonicalName, 'failure', { error: err });
|
|
42
61
|
return { success: false, error: err };
|
|
43
62
|
}
|
|
44
63
|
if (isProviderAPIError(err) && err.retryable) {
|
|
45
64
|
const statusCode = err.statusCode === 429 ? 503 : (err.statusCode ?? 503);
|
|
46
65
|
const error = ctx.errors.internal('AI provider temporarily unavailable. Please try again in a moment.', {
|
|
47
|
-
capability:
|
|
66
|
+
capability: canonicalName,
|
|
48
67
|
message: err.message,
|
|
49
68
|
provider: err.providerName,
|
|
50
69
|
retryAttempts: err.attempts,
|
|
@@ -52,13 +71,13 @@ export async function executeCapability(capability, ctx, rawInput) {
|
|
|
52
71
|
upstreamStatusCode: err.statusCode,
|
|
53
72
|
httpStatus: statusCode,
|
|
54
73
|
});
|
|
55
|
-
ctx.logger.error(`Capability "${
|
|
74
|
+
ctx.logger.error(`Capability "${canonicalName}" failed due to transient AI provider error`, {
|
|
56
75
|
error: err.message,
|
|
57
76
|
provider: err.providerName,
|
|
58
77
|
upstreamStatusCode: err.statusCode,
|
|
59
78
|
attempts: err.attempts,
|
|
60
79
|
});
|
|
61
|
-
await recordAudit(ctx, capability, 'failure', { error });
|
|
80
|
+
await recordAudit(ctx, capability, canonicalName, 'failure', { error });
|
|
62
81
|
return { success: false, error };
|
|
63
82
|
}
|
|
64
83
|
const causeMessage = err instanceof Error && err.cause instanceof Error ? err.cause.message : undefined;
|
|
@@ -68,51 +87,60 @@ export async function executeCapability(capability, ctx, rawInput) {
|
|
|
68
87
|
? err.message
|
|
69
88
|
: String(err);
|
|
70
89
|
const error = ctx.errors.internal('Capability execution failed', {
|
|
71
|
-
capability:
|
|
90
|
+
capability: canonicalName,
|
|
72
91
|
message: errorMessage,
|
|
73
92
|
});
|
|
74
|
-
ctx.logger.error(`Capability "${
|
|
93
|
+
ctx.logger.error(`Capability "${canonicalName}" threw an error`, {
|
|
75
94
|
error: errorMessage,
|
|
76
95
|
});
|
|
77
|
-
await recordAudit(ctx, capability, 'failure', { error });
|
|
96
|
+
await recordAudit(ctx, capability, canonicalName, 'failure', { error });
|
|
78
97
|
return { success: false, error };
|
|
79
98
|
}
|
|
99
|
+
finally {
|
|
100
|
+
if (emitScope) {
|
|
101
|
+
emitScope.executingCapability = undefined;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
80
104
|
// 4. Validate output against schema
|
|
81
105
|
const outputResult = capability.output.safeParse(rawOutput);
|
|
82
106
|
if (!outputResult.success) {
|
|
83
107
|
const error = ctx.errors.internal('Invalid output from capability', {
|
|
84
|
-
capability:
|
|
108
|
+
capability: canonicalName,
|
|
85
109
|
issues: outputResult.error.issues,
|
|
86
110
|
});
|
|
87
|
-
ctx.logger.error(`Capability "${
|
|
111
|
+
ctx.logger.error(`Capability "${canonicalName}" returned invalid output`, {
|
|
88
112
|
issues: outputResult.error.issues,
|
|
89
113
|
});
|
|
90
|
-
await recordAudit(ctx, capability, 'failure', { error });
|
|
114
|
+
await recordAudit(ctx, capability, canonicalName, 'failure', { error });
|
|
91
115
|
return { success: false, error };
|
|
92
116
|
}
|
|
93
117
|
// 5. Record success audit
|
|
94
|
-
await recordAudit(ctx, capability, 'success');
|
|
118
|
+
await recordAudit(ctx, capability, canonicalName, 'success');
|
|
95
119
|
return { success: true, data: outputResult.data };
|
|
96
120
|
}
|
|
97
|
-
async function recordAudit(ctx, capability, outcome, metadata) {
|
|
98
|
-
// Skip if audit is explicitly disabled for this capability
|
|
121
|
+
async function recordAudit(ctx, capability, canonicalName, outcome, metadata) {
|
|
99
122
|
if (capability.audit?.enabled === false)
|
|
100
123
|
return;
|
|
101
|
-
const auditEvent = capability.audit?.event ?? `capability.${
|
|
124
|
+
const auditEvent = capability.audit?.event ?? `capability.${canonicalName}`;
|
|
125
|
+
const stack = ctx.__runtime?.capabilityStack ?? [];
|
|
126
|
+
const caller = ctx.__runtime?.invocationCaller;
|
|
127
|
+
const correlationId = ctx.__runtime?.correlationId;
|
|
102
128
|
try {
|
|
103
129
|
await ctx.audit.record(auditEvent, {
|
|
104
|
-
capability:
|
|
130
|
+
capability: canonicalName,
|
|
105
131
|
domain: capability.domain,
|
|
106
132
|
kind: capability.kind,
|
|
107
133
|
outcome,
|
|
108
134
|
actor: ctx.auth.userId,
|
|
109
135
|
tenantId: ctx.auth.tenantId,
|
|
136
|
+
...(caller ? { caller } : {}),
|
|
137
|
+
...(stack.length > 0 ? { capabilityStack: stack } : {}),
|
|
138
|
+
...(correlationId ? { correlationId } : {}),
|
|
110
139
|
...metadata,
|
|
111
140
|
});
|
|
112
141
|
}
|
|
113
142
|
catch {
|
|
114
|
-
|
|
115
|
-
ctx.logger.error(`Failed to record audit for capability "${capability.name}"`);
|
|
143
|
+
ctx.logger.error(`Failed to record audit for capability "${canonicalName}"`);
|
|
116
144
|
}
|
|
117
145
|
}
|
|
118
146
|
//# sourceMappingURL=capability-executor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability-executor.js","sourceRoot":"","sources":["../../src/execution/capability-executor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIpD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"capability-executor.js","sourceRoot":"","sources":["../../src/execution/capability-executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { CapabilityContract } from '../types/capability.js';
|
|
2
|
+
import type { CapabilityService, ExecutionContext, ExecutionRuntimeMetadata } from '../types/context.js';
|
|
3
|
+
import type { CapabilityRegistry } from './capability-registry.js';
|
|
4
|
+
import type { CapabilityResult } from './capability-executor.js';
|
|
5
|
+
import type { InvocationEmitScope } from './invocation-emit-scope.js';
|
|
6
|
+
export type DependencyViolationReason = 'undeclaredInvocation' | 'circularInvocation' | 'missingCapability' | 'invocationUnavailable' | 'unsupportedTargetKind';
|
|
7
|
+
export interface DependencyViolationMetadata {
|
|
8
|
+
caller?: string;
|
|
9
|
+
target: string;
|
|
10
|
+
reason: DependencyViolationReason;
|
|
11
|
+
capabilityStack: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
export type InternalCapabilityInvoker = (name: string, ctx: ExecutionContext, input: unknown) => Promise<CapabilityResult<unknown>>;
|
|
14
|
+
export interface CapabilityInvocationRuntime {
|
|
15
|
+
invoker: InternalCapabilityInvoker;
|
|
16
|
+
resolveCapability: (name: string) => CapabilityContract | undefined;
|
|
17
|
+
emitScope?: InvocationEmitScope;
|
|
18
|
+
}
|
|
19
|
+
/** Strip internal invoker/registry/emit scope from handler-visible runtime metadata. */
|
|
20
|
+
export declare function stripHandlerRuntime(runtime?: ExecutionRuntimeMetadata): ExecutionRuntimeMetadata | undefined;
|
|
21
|
+
/** Runtime deps for nested capability invocation (wire into ContextDependencies). */
|
|
22
|
+
export declare function buildCapabilityRuntimeDeps(registry: CapabilityRegistry): {
|
|
23
|
+
invokeCapability: InternalCapabilityInvoker;
|
|
24
|
+
resolveCapability: (name: string) => CapabilityContract | undefined;
|
|
25
|
+
};
|
|
26
|
+
export declare function buildRegistryInvoker(registry: CapabilityRegistry): InternalCapabilityInvoker;
|
|
27
|
+
export declare function buildDependencyViolationMessage(metadata: DependencyViolationMetadata): string;
|
|
28
|
+
/**
|
|
29
|
+
* Build the public `ctx.capabilities` service for a running capability handler.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createCapabilityInvokeService(capability: CapabilityContract, ctx: ExecutionContext, runtime: CapabilityInvocationRuntime): CapabilityService;
|
|
32
|
+
/** Invoke surface that always reports invocation unavailability. */
|
|
33
|
+
export declare function createUnavailableCapabilityService(ctx: ExecutionContext): CapabilityService;
|
|
34
|
+
//# sourceMappingURL=capability-invocation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-invocation.d.ts","sourceRoot":"","sources":["../../src/execution/capability-invocation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,MAAM,MAAM,yBAAyB,GACjC,sBAAsB,GACtB,oBAAoB,GACpB,mBAAmB,GACnB,uBAAuB,GACvB,uBAAuB,CAAC;AAE5B,MAAM,WAAW,2BAA2B;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,yBAAyB,CAAC;IAClC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,MAAM,yBAAyB,GAAG,CACtC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE,OAAO,KACX,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;AAExC,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,yBAAyB,CAAC;IACnC,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACpE,SAAS,CAAC,EAAE,mBAAmB,CAAC;CACjC;AAED,wFAAwF;AACxF,wBAAgB,mBAAmB,CACjC,OAAO,CAAC,EAAE,wBAAwB,GACjC,wBAAwB,GAAG,SAAS,CAStC;AAED,qFAAqF;AACrF,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,kBAAkB,GAAG;IACxE,gBAAgB,EAAE,yBAAyB,CAAC;IAC5C,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;CACrE,CAKA;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,yBAAyB,CAW5F;AAED,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,2BAA2B,GAAG,MAAM,CAkB7F;AAcD;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,kBAAkB,EAC9B,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,2BAA2B,GACnC,iBAAiB,CA0EnB;AAED,oEAAoE;AACpE,wBAAgB,kCAAkC,CAAC,GAAG,EAAE,gBAAgB,GAAG,iBAAiB,CAU3F"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { CapabilityKind } from '../types/enums.js';
|
|
2
|
+
import { getCanonicalCapabilityName } from './canonical-name.js';
|
|
3
|
+
import { executeCapability } from './capability-executor.js';
|
|
4
|
+
/** Strip internal invoker/registry/emit scope from handler-visible runtime metadata. */
|
|
5
|
+
export function stripHandlerRuntime(runtime) {
|
|
6
|
+
if (!runtime)
|
|
7
|
+
return undefined;
|
|
8
|
+
const { invokeCapability: _invoker, resolveCapability: _resolve, invocationEmitScope: _emitScope, ...handlerVisible } = runtime;
|
|
9
|
+
return handlerVisible;
|
|
10
|
+
}
|
|
11
|
+
/** Runtime deps for nested capability invocation (wire into ContextDependencies). */
|
|
12
|
+
export function buildCapabilityRuntimeDeps(registry) {
|
|
13
|
+
return {
|
|
14
|
+
invokeCapability: buildRegistryInvoker(registry),
|
|
15
|
+
resolveCapability: (name) => registry.get(name),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function buildRegistryInvoker(registry) {
|
|
19
|
+
return async (name, ctx, input) => {
|
|
20
|
+
const capability = registry.get(name);
|
|
21
|
+
if (!capability) {
|
|
22
|
+
return {
|
|
23
|
+
success: false,
|
|
24
|
+
error: ctx.errors.notFound(`Capability "${name}" not found`, { capability: name }),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return executeCapability(capability, ctx, input);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function buildDependencyViolationMessage(metadata) {
|
|
31
|
+
const { caller, target, reason, capabilityStack } = metadata;
|
|
32
|
+
switch (reason) {
|
|
33
|
+
case 'undeclaredInvocation':
|
|
34
|
+
return `Capability ${caller ?? '(unknown)'} attempted to invoke ${target}, but ${target} is not declared in ${caller ?? '(unknown)'} effects.capabilities.`;
|
|
35
|
+
case 'circularInvocation':
|
|
36
|
+
return `Circular capability invocation detected: ${[...capabilityStack, target].join(' -> ')}.`;
|
|
37
|
+
case 'missingCapability':
|
|
38
|
+
return `Capability ${caller ?? '(unknown)'} declared or attempted to invoke ${target}, but no registered capability with that name exists.`;
|
|
39
|
+
case 'invocationUnavailable':
|
|
40
|
+
return 'Capability invocation is unavailable in this execution context because no capability registry-backed invoker was provided.';
|
|
41
|
+
case 'unsupportedTargetKind':
|
|
42
|
+
return `Capability ${caller ?? '(unknown)'} attempted to invoke ${target}, but job capabilities cannot be invoked synchronously — use job dispatch, flows, or events instead.`;
|
|
43
|
+
default: {
|
|
44
|
+
const _exhaustive = reason;
|
|
45
|
+
return _exhaustive;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function throwDependencyViolation(ctx, metadata) {
|
|
50
|
+
const message = buildDependencyViolationMessage(metadata);
|
|
51
|
+
throw ctx.errors.dependencyViolation(message, { ...metadata });
|
|
52
|
+
}
|
|
53
|
+
function isDeclaredCapabilityDependency(capability, target) {
|
|
54
|
+
return (capability.effects.capabilities ?? []).includes(target);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Build the public `ctx.capabilities` service for a running capability handler.
|
|
58
|
+
*/
|
|
59
|
+
export function createCapabilityInvokeService(capability, ctx, runtime) {
|
|
60
|
+
const caller = getCanonicalCapabilityName(capability);
|
|
61
|
+
const { invoker, resolveCapability, emitScope } = runtime;
|
|
62
|
+
return {
|
|
63
|
+
async invoke(name, input) {
|
|
64
|
+
const stack = ctx.__runtime?.capabilityStack ?? [];
|
|
65
|
+
if (!isDeclaredCapabilityDependency(capability, name)) {
|
|
66
|
+
throwDependencyViolation(ctx, {
|
|
67
|
+
caller,
|
|
68
|
+
target: name,
|
|
69
|
+
reason: 'undeclaredInvocation',
|
|
70
|
+
capabilityStack: stack,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (stack.includes(name)) {
|
|
74
|
+
throwDependencyViolation(ctx, {
|
|
75
|
+
caller,
|
|
76
|
+
target: name,
|
|
77
|
+
reason: 'circularInvocation',
|
|
78
|
+
capabilityStack: stack,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
const targetCap = resolveCapability(name);
|
|
82
|
+
if (!targetCap) {
|
|
83
|
+
throwDependencyViolation(ctx, {
|
|
84
|
+
caller,
|
|
85
|
+
target: name,
|
|
86
|
+
reason: 'missingCapability',
|
|
87
|
+
capabilityStack: stack,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (targetCap.kind === CapabilityKind.Job) {
|
|
91
|
+
throwDependencyViolation(ctx, {
|
|
92
|
+
caller,
|
|
93
|
+
target: name,
|
|
94
|
+
reason: 'unsupportedTargetKind',
|
|
95
|
+
capabilityStack: stack,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
const nestedCtx = {
|
|
99
|
+
...ctx,
|
|
100
|
+
__runtime: {
|
|
101
|
+
...ctx.__runtime,
|
|
102
|
+
capabilityStack: [...stack, caller],
|
|
103
|
+
invocationCaller: caller,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
const prevInvocationCaller = emitScope?.invocationCaller;
|
|
107
|
+
if (emitScope) {
|
|
108
|
+
emitScope.invocationCaller = caller;
|
|
109
|
+
}
|
|
110
|
+
let result;
|
|
111
|
+
try {
|
|
112
|
+
result = await invoker(name, nestedCtx, input);
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
if (emitScope) {
|
|
116
|
+
emitScope.invocationCaller = prevInvocationCaller;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (!result.success) {
|
|
120
|
+
throw result.error;
|
|
121
|
+
}
|
|
122
|
+
return result.data;
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/** Invoke surface that always reports invocation unavailability. */
|
|
127
|
+
export function createUnavailableCapabilityService(ctx) {
|
|
128
|
+
return {
|
|
129
|
+
async invoke(name) {
|
|
130
|
+
throwDependencyViolation(ctx, {
|
|
131
|
+
target: name,
|
|
132
|
+
reason: 'invocationUnavailable',
|
|
133
|
+
capabilityStack: ctx.__runtime?.capabilityStack ?? [],
|
|
134
|
+
});
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=capability-invocation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-invocation.js","sourceRoot":"","sources":["../../src/execution/capability-invocation.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { CapabilityContract } from '../types/capability.js';
|
|
2
2
|
/**
|
|
3
3
|
* Registry that holds all discovered/registered capabilities,
|
|
4
|
-
* indexed by name for lookup during execution
|
|
4
|
+
* indexed by canonical name (`<domain>.<capabilityName>`) for lookup during execution.
|
|
5
5
|
*/
|
|
6
6
|
export declare class CapabilityRegistry {
|
|
7
7
|
private capabilities;
|
|
8
8
|
/**
|
|
9
|
-
* Register a capability contract. Throws on duplicate names.
|
|
9
|
+
* Register a capability contract. Throws on duplicate canonical names.
|
|
10
10
|
*/
|
|
11
11
|
register(capability: CapabilityContract): void;
|
|
12
12
|
/**
|
|
@@ -14,7 +14,7 @@ export declare class CapabilityRegistry {
|
|
|
14
14
|
*/
|
|
15
15
|
registerAll(capabilities: CapabilityContract[]): void;
|
|
16
16
|
/**
|
|
17
|
-
* Get a capability by name.
|
|
17
|
+
* Get a capability by canonical name.
|
|
18
18
|
*/
|
|
19
19
|
get(name: string): CapabilityContract | undefined;
|
|
20
20
|
/**
|
|
@@ -26,8 +26,10 @@ export declare class CapabilityRegistry {
|
|
|
26
26
|
*/
|
|
27
27
|
getByDomain(domain: string): CapabilityContract[];
|
|
28
28
|
/**
|
|
29
|
-
* Check if a capability is registered.
|
|
29
|
+
* Check if a capability is registered by canonical name.
|
|
30
30
|
*/
|
|
31
31
|
has(name: string): boolean;
|
|
32
|
+
/** Canonical names of all registered capabilities. */
|
|
33
|
+
getCanonicalNames(): string[];
|
|
32
34
|
}
|
|
33
35
|
//# sourceMappingURL=capability-registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability-registry.d.ts","sourceRoot":"","sources":["../../src/execution/capability-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"capability-registry.d.ts","sourceRoot":"","sources":["../../src/execution/capability-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAGjE;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,YAAY,CAAyC;IAE7D;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,kBAAkB,GAAG,IAAI;IAQ9C;;OAEG;IACH,WAAW,CAAC,YAAY,EAAE,kBAAkB,EAAE,GAAG,IAAI;IAMrD;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAIjD;;OAEG;IACH,MAAM,IAAI,kBAAkB,EAAE;IAI9B;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,EAAE;IAIjD;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B,sDAAsD;IACtD,iBAAiB,IAAI,MAAM,EAAE;CAG9B"}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
+
import { getCanonicalCapabilityName } from './canonical-name.js';
|
|
1
2
|
/**
|
|
2
3
|
* Registry that holds all discovered/registered capabilities,
|
|
3
|
-
* indexed by name for lookup during execution
|
|
4
|
+
* indexed by canonical name (`<domain>.<capabilityName>`) for lookup during execution.
|
|
4
5
|
*/
|
|
5
6
|
export class CapabilityRegistry {
|
|
6
7
|
capabilities = new Map();
|
|
7
8
|
/**
|
|
8
|
-
* Register a capability contract. Throws on duplicate names.
|
|
9
|
+
* Register a capability contract. Throws on duplicate canonical names.
|
|
9
10
|
*/
|
|
10
11
|
register(capability) {
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
const canonical = getCanonicalCapabilityName(capability);
|
|
13
|
+
if (this.capabilities.has(canonical)) {
|
|
14
|
+
throw new Error(`Capability "${canonical}" is already registered`);
|
|
13
15
|
}
|
|
14
|
-
this.capabilities.set(
|
|
16
|
+
this.capabilities.set(canonical, capability);
|
|
15
17
|
}
|
|
16
18
|
/**
|
|
17
19
|
* Register multiple capabilities at once.
|
|
@@ -22,7 +24,7 @@ export class CapabilityRegistry {
|
|
|
22
24
|
}
|
|
23
25
|
}
|
|
24
26
|
/**
|
|
25
|
-
* Get a capability by name.
|
|
27
|
+
* Get a capability by canonical name.
|
|
26
28
|
*/
|
|
27
29
|
get(name) {
|
|
28
30
|
return this.capabilities.get(name);
|
|
@@ -40,10 +42,14 @@ export class CapabilityRegistry {
|
|
|
40
42
|
return this.getAll().filter((c) => c.domain === domain);
|
|
41
43
|
}
|
|
42
44
|
/**
|
|
43
|
-
* Check if a capability is registered.
|
|
45
|
+
* Check if a capability is registered by canonical name.
|
|
44
46
|
*/
|
|
45
47
|
has(name) {
|
|
46
48
|
return this.capabilities.has(name);
|
|
47
49
|
}
|
|
50
|
+
/** Canonical names of all registered capabilities. */
|
|
51
|
+
getCanonicalNames() {
|
|
52
|
+
return Array.from(this.capabilities.keys());
|
|
53
|
+
}
|
|
48
54
|
}
|
|
49
55
|
//# sourceMappingURL=capability-registry.js.map
|