@camstack/addon-smtp-nodemailer 1.0.4 → 1.0.5

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.
@@ -5019,6 +5019,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5019
5019
  */
5020
5020
  EventCategory["PipelineEngineMetricsSnapshot"] = "pipeline.engine-metrics-snapshot";
5021
5021
  /**
5022
+ * Per-node detection-engine runtime-provisioning transition. Emitted by
5023
+ * the detection-pipeline provider on every state change of its lazy
5024
+ * engine-provisioning machine (idle → installing → verifying → ready,
5025
+ * or → failed with a `nextRetryAt`). Payload is the
5026
+ * `EngineProvisioningState` snapshot; `event.source.nodeId` carries the
5027
+ * node. The Pipeline page subscribes to drive a live "installing
5028
+ * OpenVINO… / ready" indicator per node without polling
5029
+ * `pipelineExecutor.getEngineProvisioning`. Telemetry-grade (D8): the UI
5030
+ * also reads the cap snapshot on mount / reconnect. Phase 2.
5031
+ */
5032
+ EventCategory["PipelineEngineProvisioning"] = "pipeline.engine-provisioning";
5033
+ /**
5022
5034
  * Cluster topology snapshot. Carries the same payload returned by
5023
5035
  * `nodes.topology` (every reachable node + addons + processes).
5024
5036
  * Emitted by the hub on any agent / addon lifecycle change
@@ -9183,6 +9195,24 @@ var DetectorOutputSchema = object({
9183
9195
  inferenceMs: number(),
9184
9196
  modelId: string()
9185
9197
  });
9198
+ var EngineProvisioningSchema = object({
9199
+ runtimeId: _enum([
9200
+ "onnx",
9201
+ "openvino",
9202
+ "coreml"
9203
+ ]).nullable(),
9204
+ device: string().nullable(),
9205
+ state: _enum([
9206
+ "idle",
9207
+ "installing",
9208
+ "verifying",
9209
+ "ready",
9210
+ "failed"
9211
+ ]),
9212
+ progress: number().optional(),
9213
+ error: string().optional(),
9214
+ nextRetryAt: number().optional()
9215
+ });
9186
9216
  var PipelineStepInputSchema = lazy(() => object({
9187
9217
  addonId: string(),
9188
9218
  modelId: string(),
@@ -9251,7 +9281,7 @@ var PipelineRunResultBridge = custom();
9251
9281
  method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
9252
9282
  kind: "mutation",
9253
9283
  auth: "admin"
9254
- }), method(_void(), record(string(), object({
9284
+ }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
9255
9285
  modelId: string(),
9256
9286
  settings: record(string(), unknown()).readonly()
9257
9287
  }))), method(object({ steps: record(string(), object({
@@ -12851,7 +12881,10 @@ var AgentAddonConfigSchema = object({
12851
12881
  modelId: string(),
12852
12882
  settings: record(string(), unknown()).readonly()
12853
12883
  });
12854
- var AgentPipelineSettingsSchema = object({ addonDefaults: record(string(), AgentAddonConfigSchema).readonly() });
12884
+ var AgentPipelineSettingsSchema = object({
12885
+ addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
12886
+ maxCameras: number().int().nonnegative().nullable().default(null)
12887
+ });
12855
12888
  var CameraPipelineForAgentSchema = object({
12856
12889
  steps: array(PipelineStepInputSchema).readonly(),
12857
12890
  audio: object({
@@ -12953,6 +12986,133 @@ var GlobalMetricsSchema = object({
12953
12986
  * capability providers.
12954
12987
  */
12955
12988
  var CapabilityBindingsSchema = record(string(), string());
12989
+ /** Source block — always present; derives from the stream catalog. */
12990
+ var CameraSourceStatusSchema = object({ streams: array(object({
12991
+ camStreamId: string(),
12992
+ codec: string(),
12993
+ width: number(),
12994
+ height: number(),
12995
+ fps: number(),
12996
+ kind: string()
12997
+ })).readonly() });
12998
+ /** Assignment block — always present (orchestrator-local, no remote call). */
12999
+ var CameraAssignmentStatusSchema = object({
13000
+ detectionNodeId: string().nullable(),
13001
+ decoderNodeId: string().nullable(),
13002
+ audioNodeId: string().nullable(),
13003
+ pinned: object({
13004
+ detection: boolean(),
13005
+ decoder: boolean(),
13006
+ audio: boolean()
13007
+ }),
13008
+ reasons: object({
13009
+ detection: string().optional(),
13010
+ decoder: string().optional(),
13011
+ audio: string().optional()
13012
+ })
13013
+ });
13014
+ /** Broker block — null when the broker stage is unreachable or inactive. */
13015
+ var CameraBrokerStatusSchema = object({
13016
+ profiles: array(object({
13017
+ profile: string(),
13018
+ status: string(),
13019
+ codec: string(),
13020
+ width: number(),
13021
+ height: number(),
13022
+ subscribers: number(),
13023
+ inFps: number(),
13024
+ outFps: number()
13025
+ })).readonly(),
13026
+ webrtcSessions: number(),
13027
+ rtspRestream: boolean()
13028
+ });
13029
+ /** Shared-memory ring statistics within the decoder block. */
13030
+ var CameraDecoderShmSchema = object({
13031
+ framesWritten: number(),
13032
+ getFrameHits: number(),
13033
+ getFrameMisses: number(),
13034
+ budgetMb: number()
13035
+ });
13036
+ /** Decoder block — null when the decoder stage is unreachable or inactive. */
13037
+ var CameraDecoderStatusSchema = object({
13038
+ nodeId: string(),
13039
+ formats: array(string()).readonly(),
13040
+ sessionCount: number(),
13041
+ shm: CameraDecoderShmSchema
13042
+ });
13043
+ /** Motion block — null when motion detection is not active for this device. */
13044
+ var CameraMotionStatusSchema = object({
13045
+ enabled: boolean(),
13046
+ fps: number()
13047
+ });
13048
+ /** Detection provisioning sub-block. */
13049
+ var CameraDetectionProvisioningSchema = object({
13050
+ state: _enum([
13051
+ "idle",
13052
+ "installing",
13053
+ "verifying",
13054
+ "ready",
13055
+ "failed"
13056
+ ]),
13057
+ error: string().optional()
13058
+ });
13059
+ /** Detection phase — derived from the runner's engine phase. */
13060
+ var CameraDetectionPhaseSchema = _enum([
13061
+ "idle",
13062
+ "watching",
13063
+ "active"
13064
+ ]);
13065
+ /** Detection block — null when no detection node is assigned or reachable. */
13066
+ var CameraDetectionStatusSchema = object({
13067
+ nodeId: string(),
13068
+ engine: object({
13069
+ backend: string(),
13070
+ device: string()
13071
+ }),
13072
+ phase: CameraDetectionPhaseSchema,
13073
+ configuredFps: number(),
13074
+ actualFps: number(),
13075
+ queueDepth: number(),
13076
+ avgInferenceMs: number(),
13077
+ provisioning: CameraDetectionProvisioningSchema
13078
+ });
13079
+ /** Audio block — null when no audio node is assigned or reachable. */
13080
+ var CameraAudioStatusSchema = object({
13081
+ nodeId: string(),
13082
+ enabled: boolean()
13083
+ });
13084
+ /** Recording block — null when no recording cap is active for this device. */
13085
+ var CameraRecordingStatusSchema = object({
13086
+ mode: _enum([
13087
+ "off",
13088
+ "continuous",
13089
+ "events"
13090
+ ]),
13091
+ active: boolean(),
13092
+ storageBytes: number()
13093
+ });
13094
+ /**
13095
+ * Aggregated per-camera pipeline status — server-composed, single call.
13096
+ *
13097
+ * The `assignment` and `source` blocks are always present.
13098
+ * Every other block is `null` when the stage is inactive or unreachable
13099
+ * during the bounded parallel fan-out in the orchestrator implementation.
13100
+ *
13101
+ * See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
13102
+ */
13103
+ var CameraStatusSchema = object({
13104
+ deviceId: number(),
13105
+ assignment: CameraAssignmentStatusSchema,
13106
+ source: CameraSourceStatusSchema,
13107
+ broker: CameraBrokerStatusSchema.nullable(),
13108
+ decoder: CameraDecoderStatusSchema.nullable(),
13109
+ motion: CameraMotionStatusSchema.nullable(),
13110
+ detection: CameraDetectionStatusSchema.nullable(),
13111
+ audio: CameraAudioStatusSchema.nullable(),
13112
+ recording: CameraRecordingStatusSchema.nullable(),
13113
+ /** Unix timestamp (ms) when this snapshot was composed server-side. */
13114
+ fetchedAt: number()
13115
+ });
12956
13116
  method(object({
12957
13117
  deviceId: number(),
12958
13118
  agentNodeId: string()
@@ -13020,6 +13180,12 @@ method(object({
13020
13180
  }), {
13021
13181
  kind: "mutation",
13022
13182
  auth: "admin"
13183
+ }), method(object({
13184
+ agentNodeId: string(),
13185
+ maxCameras: number().int().nonnegative().nullable()
13186
+ }), object({ success: literal(true) }), {
13187
+ kind: "mutation",
13188
+ auth: "admin"
13023
13189
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
13024
13190
  deviceId: number(),
13025
13191
  addonId: string(),
@@ -13045,7 +13211,7 @@ method(object({
13045
13211
  }), method(object({
13046
13212
  deviceId: number(),
13047
13213
  agentNodeId: string().optional()
13048
- }), CameraPipelineConfigSchema), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13214
+ }), CameraPipelineConfigSchema), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13049
13215
  name: string(),
13050
13216
  description: string().optional(),
13051
13217
  config: CameraPipelineConfigSchema
@@ -18837,6 +19003,12 @@ Object.freeze({
18837
19003
  addonId: null,
18838
19004
  access: "view"
18839
19005
  },
19006
+ "pipelineExecutor.getEngineProvisioning": {
19007
+ capName: "pipeline-executor",
19008
+ capScope: "system",
19009
+ addonId: null,
19010
+ access: "view"
19011
+ },
18840
19012
  "pipelineExecutor.getGlobalPipelineConfig": {
18841
19013
  capName: "pipeline-executor",
18842
19014
  capScope: "system",
@@ -19041,6 +19213,18 @@ Object.freeze({
19041
19213
  addonId: null,
19042
19214
  access: "view"
19043
19215
  },
19216
+ "pipelineOrchestrator.getCameraStatus": {
19217
+ capName: "pipeline-orchestrator",
19218
+ capScope: "system",
19219
+ addonId: null,
19220
+ access: "view"
19221
+ },
19222
+ "pipelineOrchestrator.getCameraStatuses": {
19223
+ capName: "pipeline-orchestrator",
19224
+ capScope: "system",
19225
+ addonId: null,
19226
+ access: "view"
19227
+ },
19044
19228
  "pipelineOrchestrator.getCameraStepOverrides": {
19045
19229
  capName: "pipeline-orchestrator",
19046
19230
  capScope: "system",
@@ -19125,6 +19309,12 @@ Object.freeze({
19125
19309
  addonId: null,
19126
19310
  access: "create"
19127
19311
  },
19312
+ "pipelineOrchestrator.setAgentMaxCameras": {
19313
+ capName: "pipeline-orchestrator",
19314
+ capScope: "system",
19315
+ addonId: null,
19316
+ access: "create"
19317
+ },
19128
19318
  "pipelineOrchestrator.setCameraPipelineForAgent": {
19129
19319
  capName: "pipeline-orchestrator",
19130
19320
  capScope: "system",
@@ -5017,6 +5017,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
5017
5017
  */
5018
5018
  EventCategory["PipelineEngineMetricsSnapshot"] = "pipeline.engine-metrics-snapshot";
5019
5019
  /**
5020
+ * Per-node detection-engine runtime-provisioning transition. Emitted by
5021
+ * the detection-pipeline provider on every state change of its lazy
5022
+ * engine-provisioning machine (idle → installing → verifying → ready,
5023
+ * or → failed with a `nextRetryAt`). Payload is the
5024
+ * `EngineProvisioningState` snapshot; `event.source.nodeId` carries the
5025
+ * node. The Pipeline page subscribes to drive a live "installing
5026
+ * OpenVINO… / ready" indicator per node without polling
5027
+ * `pipelineExecutor.getEngineProvisioning`. Telemetry-grade (D8): the UI
5028
+ * also reads the cap snapshot on mount / reconnect. Phase 2.
5029
+ */
5030
+ EventCategory["PipelineEngineProvisioning"] = "pipeline.engine-provisioning";
5031
+ /**
5020
5032
  * Cluster topology snapshot. Carries the same payload returned by
5021
5033
  * `nodes.topology` (every reachable node + addons + processes).
5022
5034
  * Emitted by the hub on any agent / addon lifecycle change
@@ -9181,6 +9193,24 @@ var DetectorOutputSchema = object({
9181
9193
  inferenceMs: number(),
9182
9194
  modelId: string()
9183
9195
  });
9196
+ var EngineProvisioningSchema = object({
9197
+ runtimeId: _enum([
9198
+ "onnx",
9199
+ "openvino",
9200
+ "coreml"
9201
+ ]).nullable(),
9202
+ device: string().nullable(),
9203
+ state: _enum([
9204
+ "idle",
9205
+ "installing",
9206
+ "verifying",
9207
+ "ready",
9208
+ "failed"
9209
+ ]),
9210
+ progress: number().optional(),
9211
+ error: string().optional(),
9212
+ nextRetryAt: number().optional()
9213
+ });
9184
9214
  var PipelineStepInputSchema = lazy(() => object({
9185
9215
  addonId: string(),
9186
9216
  modelId: string(),
@@ -9249,7 +9279,7 @@ var PipelineRunResultBridge = custom();
9249
9279
  method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(PipelineEngineChoiceSchema, array(PipelineDefaultStepSchema)), method(_void(), PipelineEngineChoiceSchema, {
9250
9280
  kind: "mutation",
9251
9281
  auth: "admin"
9252
- }), method(_void(), record(string(), object({
9282
+ }), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
9253
9283
  modelId: string(),
9254
9284
  settings: record(string(), unknown()).readonly()
9255
9285
  }))), method(object({ steps: record(string(), object({
@@ -12849,7 +12879,10 @@ var AgentAddonConfigSchema = object({
12849
12879
  modelId: string(),
12850
12880
  settings: record(string(), unknown()).readonly()
12851
12881
  });
12852
- var AgentPipelineSettingsSchema = object({ addonDefaults: record(string(), AgentAddonConfigSchema).readonly() });
12882
+ var AgentPipelineSettingsSchema = object({
12883
+ addonDefaults: record(string(), AgentAddonConfigSchema).readonly(),
12884
+ maxCameras: number().int().nonnegative().nullable().default(null)
12885
+ });
12853
12886
  var CameraPipelineForAgentSchema = object({
12854
12887
  steps: array(PipelineStepInputSchema).readonly(),
12855
12888
  audio: object({
@@ -12951,6 +12984,133 @@ var GlobalMetricsSchema = object({
12951
12984
  * capability providers.
12952
12985
  */
12953
12986
  var CapabilityBindingsSchema = record(string(), string());
12987
+ /** Source block — always present; derives from the stream catalog. */
12988
+ var CameraSourceStatusSchema = object({ streams: array(object({
12989
+ camStreamId: string(),
12990
+ codec: string(),
12991
+ width: number(),
12992
+ height: number(),
12993
+ fps: number(),
12994
+ kind: string()
12995
+ })).readonly() });
12996
+ /** Assignment block — always present (orchestrator-local, no remote call). */
12997
+ var CameraAssignmentStatusSchema = object({
12998
+ detectionNodeId: string().nullable(),
12999
+ decoderNodeId: string().nullable(),
13000
+ audioNodeId: string().nullable(),
13001
+ pinned: object({
13002
+ detection: boolean(),
13003
+ decoder: boolean(),
13004
+ audio: boolean()
13005
+ }),
13006
+ reasons: object({
13007
+ detection: string().optional(),
13008
+ decoder: string().optional(),
13009
+ audio: string().optional()
13010
+ })
13011
+ });
13012
+ /** Broker block — null when the broker stage is unreachable or inactive. */
13013
+ var CameraBrokerStatusSchema = object({
13014
+ profiles: array(object({
13015
+ profile: string(),
13016
+ status: string(),
13017
+ codec: string(),
13018
+ width: number(),
13019
+ height: number(),
13020
+ subscribers: number(),
13021
+ inFps: number(),
13022
+ outFps: number()
13023
+ })).readonly(),
13024
+ webrtcSessions: number(),
13025
+ rtspRestream: boolean()
13026
+ });
13027
+ /** Shared-memory ring statistics within the decoder block. */
13028
+ var CameraDecoderShmSchema = object({
13029
+ framesWritten: number(),
13030
+ getFrameHits: number(),
13031
+ getFrameMisses: number(),
13032
+ budgetMb: number()
13033
+ });
13034
+ /** Decoder block — null when the decoder stage is unreachable or inactive. */
13035
+ var CameraDecoderStatusSchema = object({
13036
+ nodeId: string(),
13037
+ formats: array(string()).readonly(),
13038
+ sessionCount: number(),
13039
+ shm: CameraDecoderShmSchema
13040
+ });
13041
+ /** Motion block — null when motion detection is not active for this device. */
13042
+ var CameraMotionStatusSchema = object({
13043
+ enabled: boolean(),
13044
+ fps: number()
13045
+ });
13046
+ /** Detection provisioning sub-block. */
13047
+ var CameraDetectionProvisioningSchema = object({
13048
+ state: _enum([
13049
+ "idle",
13050
+ "installing",
13051
+ "verifying",
13052
+ "ready",
13053
+ "failed"
13054
+ ]),
13055
+ error: string().optional()
13056
+ });
13057
+ /** Detection phase — derived from the runner's engine phase. */
13058
+ var CameraDetectionPhaseSchema = _enum([
13059
+ "idle",
13060
+ "watching",
13061
+ "active"
13062
+ ]);
13063
+ /** Detection block — null when no detection node is assigned or reachable. */
13064
+ var CameraDetectionStatusSchema = object({
13065
+ nodeId: string(),
13066
+ engine: object({
13067
+ backend: string(),
13068
+ device: string()
13069
+ }),
13070
+ phase: CameraDetectionPhaseSchema,
13071
+ configuredFps: number(),
13072
+ actualFps: number(),
13073
+ queueDepth: number(),
13074
+ avgInferenceMs: number(),
13075
+ provisioning: CameraDetectionProvisioningSchema
13076
+ });
13077
+ /** Audio block — null when no audio node is assigned or reachable. */
13078
+ var CameraAudioStatusSchema = object({
13079
+ nodeId: string(),
13080
+ enabled: boolean()
13081
+ });
13082
+ /** Recording block — null when no recording cap is active for this device. */
13083
+ var CameraRecordingStatusSchema = object({
13084
+ mode: _enum([
13085
+ "off",
13086
+ "continuous",
13087
+ "events"
13088
+ ]),
13089
+ active: boolean(),
13090
+ storageBytes: number()
13091
+ });
13092
+ /**
13093
+ * Aggregated per-camera pipeline status — server-composed, single call.
13094
+ *
13095
+ * The `assignment` and `source` blocks are always present.
13096
+ * Every other block is `null` when the stage is inactive or unreachable
13097
+ * during the bounded parallel fan-out in the orchestrator implementation.
13098
+ *
13099
+ * See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
13100
+ */
13101
+ var CameraStatusSchema = object({
13102
+ deviceId: number(),
13103
+ assignment: CameraAssignmentStatusSchema,
13104
+ source: CameraSourceStatusSchema,
13105
+ broker: CameraBrokerStatusSchema.nullable(),
13106
+ decoder: CameraDecoderStatusSchema.nullable(),
13107
+ motion: CameraMotionStatusSchema.nullable(),
13108
+ detection: CameraDetectionStatusSchema.nullable(),
13109
+ audio: CameraAudioStatusSchema.nullable(),
13110
+ recording: CameraRecordingStatusSchema.nullable(),
13111
+ /** Unix timestamp (ms) when this snapshot was composed server-side. */
13112
+ fetchedAt: number()
13113
+ });
12954
13114
  method(object({
12955
13115
  deviceId: number(),
12956
13116
  agentNodeId: string()
@@ -13018,6 +13178,12 @@ method(object({
13018
13178
  }), {
13019
13179
  kind: "mutation",
13020
13180
  auth: "admin"
13181
+ }), method(object({
13182
+ agentNodeId: string(),
13183
+ maxCameras: number().int().nonnegative().nullable()
13184
+ }), object({ success: literal(true) }), {
13185
+ kind: "mutation",
13186
+ auth: "admin"
13021
13187
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
13022
13188
  deviceId: number(),
13023
13189
  addonId: string(),
@@ -13043,7 +13209,7 @@ method(object({
13043
13209
  }), method(object({
13044
13210
  deviceId: number(),
13045
13211
  agentNodeId: string().optional()
13046
- }), CameraPipelineConfigSchema), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13212
+ }), CameraPipelineConfigSchema), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
13047
13213
  name: string(),
13048
13214
  description: string().optional(),
13049
13215
  config: CameraPipelineConfigSchema
@@ -18835,6 +19001,12 @@ Object.freeze({
18835
19001
  addonId: null,
18836
19002
  access: "view"
18837
19003
  },
19004
+ "pipelineExecutor.getEngineProvisioning": {
19005
+ capName: "pipeline-executor",
19006
+ capScope: "system",
19007
+ addonId: null,
19008
+ access: "view"
19009
+ },
18838
19010
  "pipelineExecutor.getGlobalPipelineConfig": {
18839
19011
  capName: "pipeline-executor",
18840
19012
  capScope: "system",
@@ -19039,6 +19211,18 @@ Object.freeze({
19039
19211
  addonId: null,
19040
19212
  access: "view"
19041
19213
  },
19214
+ "pipelineOrchestrator.getCameraStatus": {
19215
+ capName: "pipeline-orchestrator",
19216
+ capScope: "system",
19217
+ addonId: null,
19218
+ access: "view"
19219
+ },
19220
+ "pipelineOrchestrator.getCameraStatuses": {
19221
+ capName: "pipeline-orchestrator",
19222
+ capScope: "system",
19223
+ addonId: null,
19224
+ access: "view"
19225
+ },
19042
19226
  "pipelineOrchestrator.getCameraStepOverrides": {
19043
19227
  capName: "pipeline-orchestrator",
19044
19228
  capScope: "system",
@@ -19123,6 +19307,12 @@ Object.freeze({
19123
19307
  addonId: null,
19124
19308
  access: "create"
19125
19309
  },
19310
+ "pipelineOrchestrator.setAgentMaxCameras": {
19311
+ capName: "pipeline-orchestrator",
19312
+ capScope: "system",
19313
+ addonId: null,
19314
+ access: "create"
19315
+ },
19126
19316
  "pipelineOrchestrator.setCameraPipelineForAgent": {
19127
19317
  capName: "pipeline-orchestrator",
19128
19318
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-smtp-nodemailer",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "SMTP email provider addon for CamStack — wraps `nodemailer` and registers a `smtp-provider` cap collection entry. Used by magic-link login + notifier addons.",
5
5
  "keywords": [
6
6
  "camstack",