@plumbus/core 0.4.2 → 0.6.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 +2 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/ai/ai/cost-tracker.d.ts +93 -0
- package/dist/ai/ai/derive-ledger-usage.d.ts +10 -0
- package/dist/ai/ai/model-pricing.d.ts +51 -0
- package/dist/ai/ai/provider.d.ts +214 -0
- package/dist/ai/ai/refusal.d.ts +27 -0
- package/dist/ai/ai/usage-client.d.ts +30 -0
- package/dist/ai/ai-service.d.ts +1 -1
- package/dist/ai/ai-service.d.ts.map +1 -1
- package/dist/ai/ai-service.js +21 -16
- package/dist/ai/ai-service.js.map +1 -1
- package/dist/ai/cost-tracker.d.ts +17 -1
- package/dist/ai/cost-tracker.d.ts.map +1 -1
- package/dist/ai/cost-tracker.js +8 -6
- package/dist/ai/cost-tracker.js.map +1 -1
- package/dist/ai/derive-ledger-usage.d.ts +11 -0
- package/dist/ai/derive-ledger-usage.d.ts.map +1 -0
- package/dist/ai/derive-ledger-usage.js +36 -0
- package/dist/ai/derive-ledger-usage.js.map +1 -0
- package/dist/ai/index.d.ts +1 -0
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +1 -0
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/types/config.d.ts +72 -0
- package/dist/ai/types/enums.d.ts +73 -0
- 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 +3 -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-schedule-list.d.ts +31 -0
- package/dist/cli/commands/flow-schedule-list.d.ts.map +1 -0
- package/dist/cli/commands/flow-schedule-list.js +93 -0
- package/dist/cli/commands/flow-schedule-list.js.map +1 -0
- package/dist/cli/commands/flow.d.ts.map +1 -1
- package/dist/cli/commands/flow.js +75 -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 +2 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +2 -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 +55 -4
- 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/voice.d.ts +12 -0
- package/dist/cli/commands/voice.d.ts.map +1 -0
- package/dist/cli/commands/voice.js +109 -0
- package/dist/cli/commands/voice.js.map +1 -0
- 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 +133 -111
- 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/cli/voice-agent-bootstrap.d.ts +22 -0
- package/dist/cli/voice-agent-bootstrap.d.ts.map +1 -0
- package/dist/cli/voice-agent-bootstrap.js +12 -0
- package/dist/cli/voice-agent-bootstrap.js.map +1 -0
- package/dist/cli/voice-serve-context.d.ts +7 -0
- package/dist/cli/voice-serve-context.d.ts.map +1 -0
- package/dist/cli/voice-serve-context.js +26 -0
- package/dist/cli/voice-serve-context.js.map +1 -0
- 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 +18 -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 +75 -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 +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- 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 +24 -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 +12 -0
- package/dist/testing/context.js.map +1 -1
- package/dist/testing/e2e.d.ts +6 -0
- package/dist/testing/e2e.d.ts.map +1 -1
- package/dist/testing/e2e.js +2 -0
- package/dist/testing/e2e.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 +49 -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 +16 -4
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PlumbusConfig } from '../types/config.js';
|
|
2
|
+
import type { RuntimeQueues } from '../runtime/queue-factory.js';
|
|
3
|
+
/** Factory that creates runtime queue triplets for a deployment environment. */
|
|
4
|
+
export interface QueueAdapterFactory {
|
|
5
|
+
createQueues(config: PlumbusConfig): Promise<RuntimeQueues>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=queue-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-adapter.d.ts","sourceRoot":"","sources":["../../src/events/queue-adapter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,gFAAgF;AAChF,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CAC7D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-adapter.js","sourceRoot":"","sources":["../../src/events/queue-adapter.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,4EAA4E"}
|
package/dist/events/queue.d.ts
CHANGED
|
@@ -40,19 +40,22 @@ export interface RedisClient {
|
|
|
40
40
|
rpoplpush?(source: string, destination: string): Promise<string | null>;
|
|
41
41
|
lrem(key: string, count: number, value: string): Promise<number>;
|
|
42
42
|
lrange(key: string, start: number, stop: number): Promise<string[]>;
|
|
43
|
+
llen?(key: string): Promise<number>;
|
|
44
|
+
zadd?(key: string, score: number, member: string): Promise<number>;
|
|
45
|
+
zrangebyscore?(key: string, min: number, max: number, options?: {
|
|
46
|
+
limit?: number;
|
|
47
|
+
}): Promise<string[]>;
|
|
48
|
+
zrem?(key: string, member: string): Promise<number>;
|
|
49
|
+
ping?(): Promise<string>;
|
|
50
|
+
eval?(script: string, options: {
|
|
51
|
+
keys: string[];
|
|
52
|
+
arguments: string[];
|
|
53
|
+
}): Promise<unknown>;
|
|
43
54
|
quit(): Promise<unknown>;
|
|
44
55
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
* - Subscribe: Poll with RPOPLPUSH to a processing list
|
|
51
|
-
* - Ack: LREM from processing list after successful handling
|
|
52
|
-
*
|
|
53
|
-
* This provides at-least-once delivery with crash recovery:
|
|
54
|
-
* if the consumer crashes, unacknowledged events remain in the
|
|
55
|
-
* processing list and can be recovered.
|
|
56
|
-
*/
|
|
57
|
-
export declare function createRedisQueue(client: RedisClient, config?: Partial<RedisQueueConfig>): EventQueue;
|
|
56
|
+
export interface RedisQueueOptions extends Partial<RedisQueueConfig> {
|
|
57
|
+
/** When false, close() does not quit the shared Redis client (default: true). */
|
|
58
|
+
ownsClient?: boolean;
|
|
59
|
+
}
|
|
60
|
+
export declare function createRedisQueue(client: RedisClient, config?: RedisQueueOptions): EventQueue;
|
|
58
61
|
//# sourceMappingURL=queue.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/events/queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,iDAAiD;IACjD,OAAO,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,qEAAqE;IACrE,SAAS,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC;IAC3E,4CAA4C;IAC5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,UAAU,CA+BhD;AAOD,MAAM,WAAW,gBAAgB;IAC/B,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+FAA+F;IAC/F,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACzD,UAAU,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1F,SAAS,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACjE,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACpE,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/events/queue.ts"],"names":[],"mappings":"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"}
|
package/dist/events/queue.js
CHANGED
|
@@ -34,45 +34,100 @@ export function createInMemoryQueue() {
|
|
|
34
34
|
},
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
37
|
+
function parseProcessingEntry(raw) {
|
|
38
|
+
try {
|
|
39
|
+
const parsed = JSON.parse(raw);
|
|
40
|
+
if (typeof parsed.envelope === 'string' && typeof parsed.dequeuedAt === 'number') {
|
|
41
|
+
return { raw, dequeuedAt: parsed.dequeuedAt };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
/* legacy plain envelope payload */
|
|
46
|
+
}
|
|
47
|
+
return { raw, dequeuedAt: 0 };
|
|
48
|
+
}
|
|
49
|
+
function wrapForProcessing(envelopeJson) {
|
|
50
|
+
return JSON.stringify({ envelope: envelopeJson, dequeuedAt: Date.now() });
|
|
51
|
+
}
|
|
52
|
+
function unwrapEnvelope(raw) {
|
|
53
|
+
try {
|
|
54
|
+
const parsed = JSON.parse(raw);
|
|
55
|
+
if (typeof parsed.envelope === 'string') {
|
|
56
|
+
return parsed.envelope;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
/* legacy */
|
|
61
|
+
}
|
|
62
|
+
return raw;
|
|
63
|
+
}
|
|
49
64
|
export function createRedisQueue(client, config) {
|
|
50
65
|
const prefix = config?.prefix ?? 'plumbus:events';
|
|
51
66
|
const pollIntervalMs = config?.pollIntervalMs ?? 1000;
|
|
67
|
+
const visibilityTimeoutMs = (config?.visibilityTimeoutSec ?? 30) * 1000;
|
|
68
|
+
const ownsClient = config?.ownsClient ?? true;
|
|
52
69
|
const queueKey = `${prefix}:pending`;
|
|
53
70
|
const processingKey = `${prefix}:processing`;
|
|
71
|
+
const REWRAP_SCRIPT = `
|
|
72
|
+
local raw = redis.call('RPOPLPUSH', KEYS[1], KEYS[2])
|
|
73
|
+
if not raw then return nil end
|
|
74
|
+
local wrapped = cjson.encode({ envelope = raw, dequeuedAt = tonumber(ARGV[1]) })
|
|
75
|
+
redis.call('LREM', KEYS[2], 1, raw)
|
|
76
|
+
redis.call('LPUSH', KEYS[2], wrapped)
|
|
77
|
+
return wrapped
|
|
78
|
+
`;
|
|
79
|
+
async function dequeueWrapped() {
|
|
80
|
+
if (client.eval) {
|
|
81
|
+
const result = await client.eval(REWRAP_SCRIPT, {
|
|
82
|
+
keys: [queueKey, processingKey],
|
|
83
|
+
arguments: [String(Date.now())],
|
|
84
|
+
});
|
|
85
|
+
return typeof result === 'string' ? result : null;
|
|
86
|
+
}
|
|
87
|
+
let raw = null;
|
|
88
|
+
if (client.rpoplpush) {
|
|
89
|
+
raw = await client.rpoplpush(queueKey, processingKey);
|
|
90
|
+
}
|
|
91
|
+
else if (client.brpoplpush) {
|
|
92
|
+
raw = await client.brpoplpush(queueKey, processingKey, 0);
|
|
93
|
+
}
|
|
94
|
+
if (!raw)
|
|
95
|
+
return null;
|
|
96
|
+
const wrapped = wrapForProcessing(raw);
|
|
97
|
+
await client.lrem(processingKey, 1, raw);
|
|
98
|
+
await client.lpush(processingKey, wrapped);
|
|
99
|
+
return wrapped;
|
|
100
|
+
}
|
|
54
101
|
const subscribers = [];
|
|
55
102
|
let closed = false;
|
|
56
103
|
let pollTimer = null;
|
|
57
104
|
let polling = false;
|
|
105
|
+
async function recoverStaleProcessing() {
|
|
106
|
+
const processing = await client.lrange(processingKey, 0, -1);
|
|
107
|
+
const now = Date.now();
|
|
108
|
+
for (const entry of processing) {
|
|
109
|
+
const { raw, dequeuedAt } = parseProcessingEntry(entry);
|
|
110
|
+
const isLegacy = dequeuedAt === 0;
|
|
111
|
+
const isStale = isLegacy || (dequeuedAt > 0 && now - dequeuedAt >= visibilityTimeoutMs);
|
|
112
|
+
if (isStale) {
|
|
113
|
+
await client.lrem(processingKey, 1, raw);
|
|
114
|
+
await client.lpush(queueKey, unwrapEnvelope(raw));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
58
118
|
async function pollOnce() {
|
|
59
119
|
if (closed || polling || subscribers.length === 0)
|
|
60
120
|
return;
|
|
61
121
|
polling = true;
|
|
62
122
|
try {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (client.rpoplpush) {
|
|
66
|
-
raw = await client.rpoplpush(queueKey, processingKey);
|
|
67
|
-
}
|
|
68
|
-
else if (client.brpoplpush) {
|
|
69
|
-
raw = await client.brpoplpush(queueKey, processingKey, 0);
|
|
70
|
-
}
|
|
123
|
+
await recoverStaleProcessing();
|
|
124
|
+
const raw = await dequeueWrapped();
|
|
71
125
|
if (!raw) {
|
|
72
126
|
polling = false;
|
|
73
127
|
return;
|
|
74
128
|
}
|
|
75
|
-
const
|
|
129
|
+
const envelopeJson = unwrapEnvelope(raw);
|
|
130
|
+
const envelope = JSON.parse(envelopeJson);
|
|
76
131
|
// Restore Date object
|
|
77
132
|
if (typeof envelope.occurredAt === 'string') {
|
|
78
133
|
envelope.occurredAt = new Date(envelope.occurredAt);
|
|
@@ -128,7 +183,9 @@ export function createRedisQueue(client, config) {
|
|
|
128
183
|
pollTimer = null;
|
|
129
184
|
}
|
|
130
185
|
subscribers.length = 0;
|
|
131
|
-
|
|
186
|
+
if (ownsClient) {
|
|
187
|
+
await client.quit();
|
|
188
|
+
}
|
|
132
189
|
},
|
|
133
190
|
};
|
|
134
191
|
}
|
package/dist/events/queue.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/events/queue.ts"],"names":[],"mappings":"AAgBA;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,WAAW,GAAsD,EAAE,CAAC;IAC1E,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,MAAM,OAAO,GAAoB,EAAE,CAAC;IAEpC,OAAO;QACL,KAAK,CAAC,OAAO,CAAC,QAAuB;YACnC,IAAI,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;YAC/C,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;gBAClC,MAAM,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;oBACrC,uCAAuC;gBACzC,CAAC,CAAC,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QAED,SAAS,CAAC,OAAmD;YAC3D,IAAI,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;YAC/C,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1B,OAAO,GAAG,EAAE;gBACV,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACzC,IAAI,GAAG,KAAK,CAAC,CAAC;oBAAE,WAAW,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAC7C,CAAC,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,KAAK;YACT,MAAM,GAAG,IAAI,CAAC;YACd,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YAClC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;QACzB,CAAC;KACF,CAAC;AACJ,CAAC;
|
|
1
|
+
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/events/queue.ts"],"names":[],"mappings":"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"}
|
package/dist/events/worker.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
|
|
2
|
+
import type { PlumbusMetrics } from '../observability/metrics.js';
|
|
3
|
+
import type { AuditService } from '../types/audit.js';
|
|
2
4
|
import type { EventEnvelope } from '../types/event.js';
|
|
3
5
|
import type { ConsumerRegistry } from './consumer-registry.js';
|
|
4
6
|
import type { IdempotencyService } from './idempotency.js';
|
|
@@ -8,6 +10,8 @@ export interface WorkerConfig {
|
|
|
8
10
|
queue: EventQueue;
|
|
9
11
|
consumers: ConsumerRegistry;
|
|
10
12
|
idempotency: IdempotencyService;
|
|
13
|
+
audit?: AuditService;
|
|
14
|
+
metrics?: PlumbusMetrics;
|
|
11
15
|
/** Default max retries per consumer (default: 3) */
|
|
12
16
|
defaultMaxRetries?: number;
|
|
13
17
|
/** Base delay in ms for exponential backoff between retries (default: 100) */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/events/worker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/events/worker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,kBAAkB,CAAC;IACvB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,WAAW,EAAE,kBAAkB,CAAC;IAChC,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,oDAAoD;IACpD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,8EAA8E;IAC9E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,8CAA8C;IAC9C,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY;IA0HlD,qDAAqD;wBAhGtB,aAAa,KAAG,OAAO,CAAC,IAAI,CAAC;IAmG5D,qCAAqC;aAC5B,IAAI;IAKb,sBAAsB;YACd,IAAI;wBAOK,OAAO;EAI3B"}
|
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":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAItD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAkB9C;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAoB;IACpD,MAAM,EACJ,EAAE,EACF,KAAK,EACL,SAAS,EACT,WAAW,EACX,iBAAiB,GAAG,CAAC,EACrB,OAAO,EACP,KAAK,EACL,kBAAkB,GAAG,GAAG,EACxB,iBAAiB,GAAG,IAAI,GACzB,GAAG,MAAM,CAAC;IAEX,IAAI,WAAW,GAAwB,IAAI,CAAC;IAE5C,8CAA8C;IAC9C,SAAS,iBAAiB,CAAC,OAAe;QACxC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,kBAAkB,GAAG,CAAC,IAAI,OAAO,EAAE,iBAAiB,CAAC,CAAC;QAC5E,8CAA8C;QAC9C,OAAO,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC;IACvD,CAAC;IAED,SAAS,KAAK,CAAC,EAAU;QACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED,KAAK,UAAU,OAAO,CAAC,QAAuB;QAC5C,MAAM,OAAO,GAAG,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC7E,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEnC,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;YAC/B,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,IAAI,iBAAiB,CAAC;YAE5D,oBAAoB;YACpB,MAAM,gBAAgB,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YACjF,IAAI,gBAAgB;gBAAE,SAAS;YAE/B,IAAI,SAA6B,CAAC;YAClC,IAAI,OAAO,GAAG,CAAC,CAAC;YAChB,IAAI,SAAS,GAAG,KAAK,CAAC;YAEtB,OAAO,OAAO,GAAG,UAAU,IAAI,CAAC,SAAS,EAAE,CAAC;gBAC1C,OAAO,EAAE,CAAC;gBACV,IAAI,CAAC;oBACH,MAAM,KAAK,EAAE,MAAM,CAAC,wBAAwB,EAAE;wBAC5C,OAAO,EAAE,QAAQ,CAAC,EAAE;wBACpB,SAAS,EAAE,QAAQ,CAAC,SAAS;wBAC7B,UAAU,EAAE,QAAQ,CAAC,EAAE;wBACvB,OAAO;wBACP,QAAQ,EAAE,QAAQ,CAAC,QAAQ;wBAC3B,OAAO,EAAE,SAAS;qBACnB,CAAC,CAAC;oBACH,MAAM,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;oBACjC,SAAS,GAAG,IAAI,CAAC;gBACnB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,SAAS,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;oBAC7D,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;wBACzB,MAAM,KAAK,CAAC,iBAAiB,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;oBAC9C,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,WAAW,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAC1D,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;gBACvD,OAAO,EAAE,qBAAqB,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,eAAe,EAAE;oBACnE,QAAQ,EAAE,QAAQ,CAAC,EAAE;oBACrB,OAAO,EAAE,WAAW;iBACrB,CAAC,CAAC;gBACH,MAAM,KAAK,EAAE,MAAM,CAAC,0BAA0B,EAAE;oBAC9C,OAAO,EAAE,QAAQ,CAAC,EAAE;oBACpB,SAAS,EAAE,QAAQ,CAAC,SAAS;oBAC7B,UAAU,EAAE,QAAQ,CAAC,EAAE;oBACvB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;oBAC3B,OAAO,EAAE,SAAS;iBACnB,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;gBACpD,OAAO,EAAE,qBAAqB,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,eAAe,EAAE;oBACnE,QAAQ,EAAE,QAAQ,CAAC,EAAE;oBACrB,OAAO,EAAE,QAAQ;iBAClB,CAAC,CAAC;gBACH,MAAM,KAAK,EAAE,MAAM,CAAC,8BAA8B,EAAE;oBAClD,OAAO,EAAE,QAAQ,CAAC,EAAE;oBACpB,SAAS,EAAE,QAAQ,CAAC,SAAS;oBAC7B,UAAU,EAAE,QAAQ,CAAC,EAAE;oBACvB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;oBAC3B,SAAS;oBACT,QAAQ,EAAE,OAAO;oBACjB,OAAO,EAAE,eAAe;iBACzB,CAAC,CAAC;gBACH,cAAc;gBACd,MAAM,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC;oBACtC,OAAO,EAAE,QAAQ,CAAC,EAAE;oBACpB,SAAS,EAAE,QAAQ,CAAC,SAAS;oBAC7B,OAAO,EAAE,QAAQ,CAAC,OAAc;oBAChC,UAAU,EAAE,QAAQ,CAAC,EAAE;oBACvB,SAAS,EAAE,SAAS,IAAI,eAAe;oBACvC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC;oBAC3B,QAAQ,EAAE;wBACR,aAAa,EAAE,QAAQ,CAAC,aAAa;wBACrC,WAAW,EAAE,QAAQ,CAAC,WAAW;wBACjC,KAAK,EAAE,QAAQ,CAAC,KAAK;wBACrB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;qBAC5B;iBACF,CAAC,CAAC;gBAEH,IAAI,QAAQ,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;oBACnC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAA0B,CAAC;oBACpD,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;wBAC3B,MAAM,IAAI,GAAG,gBAAgB,CAAC,EAAE,CAAC,CAAC;wBAClC,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,cAAc,EAAE;4BAClD,IAAI,EAAE,oBAAoB;4BAC1B,OAAO,EAAE,SAAS,IAAI,gCAAgC;yBACvD,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,qDAAqD;QACrD,OAAO;QAEP,qCAAqC;QACrC,KAAK;YACH,IAAI,WAAW;gBAAE,OAAO;YACxB,WAAW,GAAG,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACzC,CAAC;QAED,sBAAsB;QACtB,IAAI;YACF,IAAI,WAAW,EAAE,CAAC;gBAChB,WAAW,EAAE,CAAC;gBACd,WAAW,GAAG,IAAI,CAAC;YACrB,CAAC;QACH,CAAC;QAED,IAAI,SAAS;YACX,OAAO,WAAW,KAAK,IAAI,CAAC;QAC9B,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -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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"}
|