@reactive-agents/interaction 0.1.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/dist/index.js ADDED
@@ -0,0 +1,782 @@
1
+ // src/types/mode.ts
2
+ import { Schema } from "effect";
3
+ var InteractionModeType = Schema.Literal(
4
+ "autonomous",
5
+ // Fire-and-forget: agent runs independently
6
+ "supervised",
7
+ // Checkpoints: agent pauses at milestones for approval
8
+ "collaborative",
9
+ // Real-time: agent and user work together
10
+ "consultative",
11
+ // Advisory: agent observes and suggests
12
+ "interrogative"
13
+ // Drill-down: user explores agent state/reasoning
14
+ );
15
+ var SessionId = Schema.String.pipe(Schema.brand("SessionId"));
16
+ var InteractionModeSchema = Schema.Struct({
17
+ mode: InteractionModeType,
18
+ agentId: Schema.String,
19
+ sessionId: SessionId,
20
+ startedAt: Schema.DateFromSelf,
21
+ metadata: Schema.optional(
22
+ Schema.Record({ key: Schema.String, value: Schema.Unknown })
23
+ )
24
+ });
25
+
26
+ // src/types/checkpoint.ts
27
+ import { Schema as Schema2 } from "effect";
28
+ var CheckpointStatus = Schema2.Literal(
29
+ "pending",
30
+ "approved",
31
+ "rejected",
32
+ "auto-approved",
33
+ "expired"
34
+ );
35
+ var CheckpointSchema = Schema2.Struct({
36
+ id: Schema2.String,
37
+ agentId: Schema2.String,
38
+ taskId: Schema2.String,
39
+ milestoneName: Schema2.String,
40
+ description: Schema2.String,
41
+ status: CheckpointStatus,
42
+ createdAt: Schema2.DateFromSelf,
43
+ resolvedAt: Schema2.optional(Schema2.DateFromSelf),
44
+ userComment: Schema2.optional(Schema2.String)
45
+ });
46
+ var CheckpointFrequency = Schema2.Literal("milestone", "time-based");
47
+ var AutoApproveAction = Schema2.Literal("approve", "reject", "pause");
48
+ var CheckpointConfigSchema = Schema2.Struct({
49
+ frequency: CheckpointFrequency,
50
+ intervalMs: Schema2.optional(Schema2.Number),
51
+ milestones: Schema2.optional(Schema2.Array(Schema2.String)),
52
+ autoApprove: Schema2.Struct({
53
+ enabled: Schema2.Boolean,
54
+ timeoutMs: Schema2.Number,
55
+ defaultAction: AutoApproveAction
56
+ })
57
+ });
58
+
59
+ // src/types/notification.ts
60
+ import { Schema as Schema3 } from "effect";
61
+ var NotificationChannel = Schema3.Literal(
62
+ "in-app",
63
+ // Dashboard notification
64
+ "callback",
65
+ // Programmatic callback
66
+ "event-bus"
67
+ // EventBus from Layer 1
68
+ );
69
+ var NotificationPriority = Schema3.Literal(
70
+ "low",
71
+ "normal",
72
+ "high",
73
+ "urgent"
74
+ );
75
+ var NotificationSchema = Schema3.Struct({
76
+ id: Schema3.String,
77
+ agentId: Schema3.String,
78
+ channel: NotificationChannel,
79
+ priority: NotificationPriority,
80
+ title: Schema3.String,
81
+ body: Schema3.String,
82
+ data: Schema3.optional(Schema3.Unknown),
83
+ createdAt: Schema3.DateFromSelf,
84
+ readAt: Schema3.optional(Schema3.DateFromSelf)
85
+ });
86
+ var ReportingFrequency = Schema3.Literal(
87
+ "realtime",
88
+ "milestone",
89
+ "hourly",
90
+ "daily"
91
+ );
92
+ var ReportingDetailLevel = Schema3.Literal(
93
+ "minimal",
94
+ "summary",
95
+ "detailed"
96
+ );
97
+ var ReportingConfigSchema = Schema3.Struct({
98
+ frequency: ReportingFrequency,
99
+ channel: NotificationChannel,
100
+ detail: ReportingDetailLevel,
101
+ streaming: Schema3.Boolean
102
+ });
103
+
104
+ // src/types/interrupt.ts
105
+ import { Schema as Schema4 } from "effect";
106
+ var InterruptTrigger = Schema4.Literal(
107
+ "error",
108
+ "uncertainty",
109
+ "high-cost",
110
+ "critical-decision",
111
+ "user-requested",
112
+ "custom"
113
+ );
114
+ var InterruptSeverity = Schema4.Literal("low", "medium", "high", "critical");
115
+ var InterruptRuleSchema = Schema4.Struct({
116
+ trigger: InterruptTrigger,
117
+ severity: InterruptSeverity,
118
+ threshold: Schema4.optional(Schema4.Number),
119
+ enabled: Schema4.Boolean
120
+ });
121
+ var InterruptEventSchema = Schema4.Struct({
122
+ id: Schema4.String,
123
+ trigger: InterruptTrigger,
124
+ severity: InterruptSeverity,
125
+ agentId: Schema4.String,
126
+ taskId: Schema4.String,
127
+ message: Schema4.String,
128
+ context: Schema4.optional(Schema4.Unknown),
129
+ timestamp: Schema4.DateFromSelf,
130
+ acknowledged: Schema4.Boolean
131
+ });
132
+
133
+ // src/types/collaboration.ts
134
+ import { Schema as Schema5 } from "effect";
135
+ var CollaborationStatus = Schema5.Literal("active", "paused", "ended");
136
+ var QuestionStyle = Schema5.Literal("inline", "batch", "separate");
137
+ var CollaborationSessionSchema = Schema5.Struct({
138
+ id: SessionId,
139
+ agentId: Schema5.String,
140
+ taskId: Schema5.String,
141
+ status: CollaborationStatus,
142
+ thinkingVisible: Schema5.Boolean,
143
+ streamingEnabled: Schema5.Boolean,
144
+ questionStyle: QuestionStyle,
145
+ rollbackEnabled: Schema5.Boolean,
146
+ startedAt: Schema5.DateFromSelf,
147
+ endedAt: Schema5.optional(Schema5.DateFromSelf)
148
+ });
149
+ var CollaborationMessageType = Schema5.Literal(
150
+ "thought",
151
+ "question",
152
+ "answer",
153
+ "suggestion",
154
+ "update",
155
+ "action"
156
+ );
157
+ var CollaborationMessageSchema = Schema5.Struct({
158
+ id: Schema5.String,
159
+ sessionId: SessionId,
160
+ type: CollaborationMessageType,
161
+ sender: Schema5.Literal("agent", "user"),
162
+ content: Schema5.String,
163
+ timestamp: Schema5.DateFromSelf
164
+ });
165
+
166
+ // src/types/preference.ts
167
+ import { Schema as Schema6 } from "effect";
168
+ var ApprovalAction = Schema6.Literal("auto-approve", "auto-reject", "ask");
169
+ var ApprovalPatternSchema = Schema6.Struct({
170
+ id: Schema6.String,
171
+ taskType: Schema6.String,
172
+ costThreshold: Schema6.optional(Schema6.Number),
173
+ action: ApprovalAction,
174
+ confidence: Schema6.Number,
175
+ occurrences: Schema6.Number,
176
+ lastSeen: Schema6.DateFromSelf
177
+ });
178
+ var InterruptionTolerance = Schema6.Literal("low", "medium", "high");
179
+ var UserPreferenceSchema = Schema6.Struct({
180
+ userId: Schema6.String,
181
+ learningEnabled: Schema6.Boolean,
182
+ interruptionTolerance: InterruptionTolerance,
183
+ preferredMode: Schema6.optional(Schema6.String),
184
+ approvalPatterns: Schema6.Array(ApprovalPatternSchema),
185
+ lastUpdated: Schema6.DateFromSelf
186
+ });
187
+
188
+ // src/types/config.ts
189
+ import { Schema as Schema7 } from "effect";
190
+ var EscalationConditionType = Schema7.Literal(
191
+ "uncertainty",
192
+ "cost",
193
+ "duration",
194
+ "user-active",
195
+ "confidence",
196
+ "consecutive-approvals"
197
+ );
198
+ var EscalationConditionSchema = Schema7.Struct({
199
+ type: EscalationConditionType,
200
+ threshold: Schema7.Number
201
+ });
202
+ var ModeTransitionRuleSchema = Schema7.Struct({
203
+ from: InteractionModeType,
204
+ to: InteractionModeType,
205
+ conditions: Schema7.Array(EscalationConditionSchema)
206
+ });
207
+ var InteractionConfigSchema = Schema7.Struct({
208
+ defaultMode: InteractionModeType,
209
+ interruptRules: Schema7.Array(InterruptRuleSchema),
210
+ reporting: ReportingConfigSchema,
211
+ checkpoints: Schema7.optional(CheckpointConfigSchema),
212
+ escalationRules: Schema7.Array(ModeTransitionRuleSchema),
213
+ deescalationRules: Schema7.Array(ModeTransitionRuleSchema),
214
+ learningEnabled: Schema7.Boolean
215
+ });
216
+ var defaultInteractionConfig = {
217
+ defaultMode: "autonomous",
218
+ interruptRules: [
219
+ { trigger: "error", severity: "high", enabled: true },
220
+ { trigger: "uncertainty", severity: "medium", threshold: 0.3, enabled: true },
221
+ { trigger: "high-cost", severity: "medium", threshold: 10, enabled: true },
222
+ { trigger: "critical-decision", severity: "critical", enabled: true }
223
+ ],
224
+ reporting: {
225
+ frequency: "milestone",
226
+ channel: "event-bus",
227
+ detail: "summary",
228
+ streaming: false
229
+ },
230
+ escalationRules: [
231
+ {
232
+ from: "autonomous",
233
+ to: "supervised",
234
+ conditions: [{ type: "uncertainty", threshold: 0.3 }]
235
+ },
236
+ {
237
+ from: "supervised",
238
+ to: "collaborative",
239
+ conditions: [
240
+ { type: "uncertainty", threshold: 0.5 },
241
+ { type: "user-active", threshold: 1 }
242
+ ]
243
+ }
244
+ ],
245
+ deescalationRules: [
246
+ {
247
+ from: "collaborative",
248
+ to: "autonomous",
249
+ conditions: [
250
+ { type: "confidence", threshold: 0.9 },
251
+ { type: "consecutive-approvals", threshold: 3 }
252
+ ]
253
+ }
254
+ ],
255
+ learningEnabled: true
256
+ };
257
+
258
+ // src/errors/errors.ts
259
+ import { Data } from "effect";
260
+ var InteractionError = class extends Data.TaggedError("InteractionError") {
261
+ };
262
+ var ModeError = class extends Data.TaggedError("ModeError") {
263
+ };
264
+ var CheckpointError = class extends Data.TaggedError("CheckpointError") {
265
+ };
266
+ var SessionNotFoundError = class extends Data.TaggedError("SessionNotFoundError") {
267
+ };
268
+ var NotificationError = class extends Data.TaggedError("NotificationError") {
269
+ };
270
+ var InputTimeoutError = class extends Data.TaggedError("InputTimeoutError") {
271
+ };
272
+
273
+ // src/services/interaction-manager.ts
274
+ import { Context as Context6, Effect as Effect6, Layer as Layer6 } from "effect";
275
+
276
+ // src/services/mode-switcher.ts
277
+ import { Context, Effect, Layer, Ref } from "effect";
278
+ import { EventBus } from "@reactive-agents/core";
279
+ var ModeSwitcher = class extends Context.Tag("ModeSwitcher")() {
280
+ };
281
+ var ModeSwitcherLive = (config = defaultInteractionConfig) => Layer.effect(
282
+ ModeSwitcher,
283
+ Effect.gen(function* () {
284
+ const eventBus = yield* EventBus;
285
+ const modesRef = yield* Ref.make(/* @__PURE__ */ new Map());
286
+ const checkConditions = (rule, context) => {
287
+ return rule.conditions.every((condition) => {
288
+ switch (condition.type) {
289
+ case "uncertainty":
290
+ return context.confidence !== void 0 && context.confidence < condition.threshold;
291
+ case "cost":
292
+ return context.cost !== void 0 && context.cost > condition.threshold;
293
+ case "duration":
294
+ return context.durationMs !== void 0 && context.durationMs > condition.threshold;
295
+ case "user-active":
296
+ return context.userActive === true;
297
+ case "confidence":
298
+ return context.confidence !== void 0 && context.confidence >= condition.threshold;
299
+ case "consecutive-approvals":
300
+ return context.consecutiveApprovals !== void 0 && context.consecutiveApprovals >= condition.threshold;
301
+ default:
302
+ return false;
303
+ }
304
+ });
305
+ };
306
+ return {
307
+ getMode: (agentId) => Ref.get(modesRef).pipe(
308
+ Effect.map((m) => m.get(agentId) ?? config.defaultMode)
309
+ ),
310
+ setMode: (agentId, targetMode) => Effect.gen(function* () {
311
+ const currentMode = yield* Ref.get(modesRef).pipe(
312
+ Effect.map((m) => m.get(agentId) ?? config.defaultMode)
313
+ );
314
+ if (currentMode === targetMode) return;
315
+ yield* Ref.update(modesRef, (m) => {
316
+ const next = new Map(m);
317
+ next.set(agentId, targetMode);
318
+ return next;
319
+ });
320
+ yield* eventBus.publish({
321
+ _tag: "Custom",
322
+ type: "interaction.mode-changed",
323
+ payload: { agentId, from: currentMode, to: targetMode }
324
+ });
325
+ }),
326
+ evaluateTransition: (agentId, context) => Effect.gen(function* () {
327
+ const currentMode = yield* Ref.get(modesRef).pipe(
328
+ Effect.map((m) => m.get(agentId) ?? config.defaultMode)
329
+ );
330
+ for (const rule of config.escalationRules) {
331
+ if (rule.from === currentMode && checkConditions(rule, context)) {
332
+ return rule.to;
333
+ }
334
+ }
335
+ for (const rule of config.deescalationRules) {
336
+ if (rule.from === currentMode && checkConditions(rule, context)) {
337
+ return rule.to;
338
+ }
339
+ }
340
+ return null;
341
+ })
342
+ };
343
+ })
344
+ );
345
+
346
+ // src/services/notification-service.ts
347
+ import { Context as Context2, Effect as Effect2, Layer as Layer2, Ref as Ref2 } from "effect";
348
+ import { ulid } from "ulid";
349
+ import { EventBus as EventBus2 } from "@reactive-agents/core";
350
+ var NotificationService = class extends Context2.Tag("NotificationService")() {
351
+ };
352
+ var NotificationServiceLive = Layer2.effect(
353
+ NotificationService,
354
+ Effect2.gen(function* () {
355
+ const eventBus = yield* EventBus2;
356
+ const notificationsRef = yield* Ref2.make(
357
+ /* @__PURE__ */ new Map()
358
+ );
359
+ return {
360
+ send: (params) => Effect2.gen(function* () {
361
+ const notification = {
362
+ id: ulid(),
363
+ agentId: params.agentId,
364
+ channel: params.channel,
365
+ priority: params.priority,
366
+ title: params.title,
367
+ body: params.body,
368
+ data: params.data,
369
+ createdAt: /* @__PURE__ */ new Date(),
370
+ readAt: void 0
371
+ };
372
+ yield* Ref2.update(notificationsRef, (m) => {
373
+ const next = new Map(m);
374
+ next.set(notification.id, notification);
375
+ return next;
376
+ });
377
+ yield* eventBus.publish({
378
+ _tag: "Custom",
379
+ type: "interaction.notification",
380
+ payload: notification
381
+ });
382
+ return notification;
383
+ }),
384
+ listUnread: () => Ref2.get(notificationsRef).pipe(
385
+ Effect2.map(
386
+ (m) => Array.from(m.values()).filter((n) => n.readAt == null)
387
+ )
388
+ ),
389
+ markRead: (notificationId) => Ref2.update(notificationsRef, (m) => {
390
+ const next = new Map(m);
391
+ const n = next.get(notificationId);
392
+ if (n) {
393
+ next.set(notificationId, { ...n, readAt: /* @__PURE__ */ new Date() });
394
+ }
395
+ return next;
396
+ })
397
+ };
398
+ })
399
+ );
400
+
401
+ // src/services/checkpoint-service.ts
402
+ import { Context as Context3, Effect as Effect3, Layer as Layer3, Ref as Ref3 } from "effect";
403
+ import { EventBus as EventBus3 } from "@reactive-agents/core";
404
+ var CheckpointService = class extends Context3.Tag("CheckpointService")() {
405
+ };
406
+ var CheckpointServiceLive = Layer3.effect(
407
+ CheckpointService,
408
+ Effect3.gen(function* () {
409
+ const eventBus = yield* EventBus3;
410
+ const checkpointsRef = yield* Ref3.make(/* @__PURE__ */ new Map());
411
+ return {
412
+ createCheckpoint: (params) => Effect3.gen(function* () {
413
+ const checkpoint = {
414
+ id: crypto.randomUUID(),
415
+ agentId: params.agentId,
416
+ taskId: params.taskId,
417
+ milestoneName: params.milestoneName,
418
+ description: params.description,
419
+ status: "pending",
420
+ createdAt: /* @__PURE__ */ new Date()
421
+ };
422
+ yield* Ref3.update(checkpointsRef, (m) => {
423
+ const next = new Map(m);
424
+ next.set(checkpoint.id, checkpoint);
425
+ return next;
426
+ });
427
+ yield* eventBus.publish({
428
+ _tag: "Custom",
429
+ type: "interaction.checkpoint-created",
430
+ payload: checkpoint
431
+ });
432
+ return checkpoint;
433
+ }),
434
+ resolveCheckpoint: (checkpointId, status, comment) => Effect3.gen(function* () {
435
+ const checkpoints = yield* Ref3.get(checkpointsRef);
436
+ const existing = checkpoints.get(checkpointId);
437
+ if (!existing) {
438
+ return yield* Effect3.fail(
439
+ new CheckpointError({ checkpointId, message: "Checkpoint not found" })
440
+ );
441
+ }
442
+ const resolved = {
443
+ ...existing,
444
+ status,
445
+ resolvedAt: /* @__PURE__ */ new Date(),
446
+ userComment: comment
447
+ };
448
+ yield* Ref3.update(checkpointsRef, (m) => {
449
+ const next = new Map(m);
450
+ next.set(checkpointId, resolved);
451
+ return next;
452
+ });
453
+ yield* eventBus.publish({
454
+ _tag: "Custom",
455
+ type: "interaction.checkpoint-resolved",
456
+ payload: resolved
457
+ });
458
+ return resolved;
459
+ }),
460
+ getCheckpoint: (checkpointId) => Effect3.gen(function* () {
461
+ const checkpoints = yield* Ref3.get(checkpointsRef);
462
+ const cp = checkpoints.get(checkpointId);
463
+ if (!cp) {
464
+ return yield* Effect3.fail(
465
+ new CheckpointError({ checkpointId, message: "Checkpoint not found" })
466
+ );
467
+ }
468
+ return cp;
469
+ }),
470
+ listPending: (agentId) => Ref3.get(checkpointsRef).pipe(
471
+ Effect3.map(
472
+ (m) => Array.from(m.values()).filter(
473
+ (cp) => cp.status === "pending" && (!agentId || cp.agentId === agentId)
474
+ )
475
+ )
476
+ )
477
+ };
478
+ })
479
+ );
480
+
481
+ // src/services/collaboration-service.ts
482
+ import { Context as Context4, Effect as Effect4, Layer as Layer4, Ref as Ref4 } from "effect";
483
+ import { EventBus as EventBus4 } from "@reactive-agents/core";
484
+ var CollaborationService = class extends Context4.Tag("CollaborationService")() {
485
+ };
486
+ var CollaborationServiceLive = Layer4.effect(
487
+ CollaborationService,
488
+ Effect4.gen(function* () {
489
+ const eventBus = yield* EventBus4;
490
+ const sessionsRef = yield* Ref4.make(/* @__PURE__ */ new Map());
491
+ const messagesRef = yield* Ref4.make(/* @__PURE__ */ new Map());
492
+ return {
493
+ startSession: (params) => Effect4.gen(function* () {
494
+ const sessionId = crypto.randomUUID();
495
+ const session = {
496
+ id: sessionId,
497
+ agentId: params.agentId,
498
+ taskId: params.taskId,
499
+ status: "active",
500
+ thinkingVisible: params.thinkingVisible ?? true,
501
+ streamingEnabled: params.streamingEnabled ?? false,
502
+ questionStyle: "inline",
503
+ rollbackEnabled: false,
504
+ startedAt: /* @__PURE__ */ new Date()
505
+ };
506
+ yield* Ref4.update(sessionsRef, (m) => {
507
+ const next = new Map(m);
508
+ next.set(sessionId, session);
509
+ return next;
510
+ });
511
+ yield* Ref4.update(messagesRef, (m) => {
512
+ const next = new Map(m);
513
+ next.set(sessionId, []);
514
+ return next;
515
+ });
516
+ yield* eventBus.publish({
517
+ _tag: "Custom",
518
+ type: "interaction.collaboration-started",
519
+ payload: session
520
+ });
521
+ return session;
522
+ }),
523
+ endSession: (sessionId) => Effect4.gen(function* () {
524
+ const sessions = yield* Ref4.get(sessionsRef);
525
+ const session = sessions.get(sessionId);
526
+ if (!session) {
527
+ return yield* Effect4.fail(new SessionNotFoundError({ sessionId }));
528
+ }
529
+ yield* Ref4.update(sessionsRef, (m) => {
530
+ const next = new Map(m);
531
+ next.set(sessionId, { ...session, status: "ended", endedAt: /* @__PURE__ */ new Date() });
532
+ return next;
533
+ });
534
+ }),
535
+ sendMessage: (params) => Effect4.gen(function* () {
536
+ const sessions = yield* Ref4.get(sessionsRef);
537
+ if (!sessions.has(params.sessionId)) {
538
+ return yield* Effect4.fail(new SessionNotFoundError({ sessionId: params.sessionId }));
539
+ }
540
+ const message = {
541
+ id: crypto.randomUUID(),
542
+ sessionId: params.sessionId,
543
+ type: params.type,
544
+ sender: params.sender,
545
+ content: params.content,
546
+ timestamp: /* @__PURE__ */ new Date()
547
+ };
548
+ yield* Ref4.update(messagesRef, (m) => {
549
+ const next = new Map(m);
550
+ const existing = next.get(params.sessionId) ?? [];
551
+ next.set(params.sessionId, [...existing, message]);
552
+ return next;
553
+ });
554
+ return message;
555
+ }),
556
+ getMessages: (sessionId) => Effect4.gen(function* () {
557
+ const sessions = yield* Ref4.get(sessionsRef);
558
+ if (!sessions.has(sessionId)) {
559
+ return yield* Effect4.fail(new SessionNotFoundError({ sessionId }));
560
+ }
561
+ const msgs = yield* Ref4.get(messagesRef);
562
+ return msgs.get(sessionId) ?? [];
563
+ }),
564
+ getSession: (sessionId) => Effect4.gen(function* () {
565
+ const sessions = yield* Ref4.get(sessionsRef);
566
+ const session = sessions.get(sessionId);
567
+ if (!session) {
568
+ return yield* Effect4.fail(new SessionNotFoundError({ sessionId }));
569
+ }
570
+ return session;
571
+ })
572
+ };
573
+ })
574
+ );
575
+
576
+ // src/services/preference-learner.ts
577
+ import { Context as Context5, Effect as Effect5, Layer as Layer5, Ref as Ref5 } from "effect";
578
+ var PreferenceLearner = class extends Context5.Tag("PreferenceLearner")() {
579
+ };
580
+ var PreferenceLearnerLive = Layer5.effect(
581
+ PreferenceLearner,
582
+ Effect5.gen(function* () {
583
+ const prefsRef = yield* Ref5.make(/* @__PURE__ */ new Map());
584
+ const getOrCreatePref = (userId) => Ref5.get(prefsRef).pipe(
585
+ Effect5.map(
586
+ (m) => m.get(userId) ?? {
587
+ userId,
588
+ learningEnabled: true,
589
+ interruptionTolerance: "medium",
590
+ approvalPatterns: [],
591
+ lastUpdated: /* @__PURE__ */ new Date()
592
+ }
593
+ )
594
+ );
595
+ return {
596
+ getPreference: (userId) => getOrCreatePref(userId),
597
+ recordApproval: (params) => Effect5.gen(function* () {
598
+ const pref = yield* getOrCreatePref(params.userId);
599
+ const existing = pref.approvalPatterns.find(
600
+ (p) => p.taskType === params.taskType
601
+ );
602
+ let updatedPatterns;
603
+ if (existing) {
604
+ updatedPatterns = pref.approvalPatterns.map(
605
+ (p) => p.taskType === params.taskType ? {
606
+ ...p,
607
+ occurrences: p.occurrences + 1,
608
+ confidence: Math.min(1, p.confidence + 0.1),
609
+ action: params.approved ? "auto-approve" : p.action,
610
+ lastSeen: /* @__PURE__ */ new Date()
611
+ } : p
612
+ );
613
+ } else {
614
+ updatedPatterns = [
615
+ ...pref.approvalPatterns,
616
+ {
617
+ id: crypto.randomUUID(),
618
+ taskType: params.taskType,
619
+ costThreshold: params.cost,
620
+ action: params.approved ? "auto-approve" : "ask",
621
+ confidence: 0.3,
622
+ occurrences: 1,
623
+ lastSeen: /* @__PURE__ */ new Date()
624
+ }
625
+ ];
626
+ }
627
+ yield* Ref5.update(prefsRef, (m) => {
628
+ const next = new Map(m);
629
+ next.set(params.userId, {
630
+ ...pref,
631
+ approvalPatterns: updatedPatterns,
632
+ lastUpdated: /* @__PURE__ */ new Date()
633
+ });
634
+ return next;
635
+ });
636
+ }),
637
+ shouldAutoApprove: (params) => Effect5.gen(function* () {
638
+ const pref = yield* getOrCreatePref(params.userId);
639
+ if (!pref.learningEnabled) return false;
640
+ const pattern = pref.approvalPatterns.find(
641
+ (p) => p.taskType === params.taskType
642
+ );
643
+ if (!pattern) return false;
644
+ if (pattern.confidence < 0.7 || pattern.occurrences < 3) return false;
645
+ if (pattern.action !== "auto-approve") return false;
646
+ if (params.cost && pattern.costThreshold && params.cost > pattern.costThreshold) {
647
+ return false;
648
+ }
649
+ return true;
650
+ }),
651
+ updateTolerance: (userId, tolerance) => Effect5.gen(function* () {
652
+ const pref = yield* getOrCreatePref(userId);
653
+ yield* Ref5.update(prefsRef, (m) => {
654
+ const next = new Map(m);
655
+ next.set(userId, {
656
+ ...pref,
657
+ interruptionTolerance: tolerance,
658
+ lastUpdated: /* @__PURE__ */ new Date()
659
+ });
660
+ return next;
661
+ });
662
+ })
663
+ };
664
+ })
665
+ );
666
+
667
+ // src/services/interaction-manager.ts
668
+ import { EventBus as EventBus5 } from "@reactive-agents/core";
669
+ var InteractionManager = class extends Context6.Tag("InteractionManager")() {
670
+ };
671
+ var InteractionManagerLive = Layer6.effect(
672
+ InteractionManager,
673
+ Effect6.gen(function* () {
674
+ const modeSwitcher = yield* ModeSwitcher;
675
+ const notifications = yield* NotificationService;
676
+ const checkpoints = yield* CheckpointService;
677
+ const collaboration = yield* CollaborationService;
678
+ const preferences = yield* PreferenceLearner;
679
+ const eventBus = yield* EventBus5;
680
+ return {
681
+ // Mode
682
+ getMode: (agentId) => modeSwitcher.getMode(agentId),
683
+ switchMode: (agentId, mode) => Effect6.gen(function* () {
684
+ yield* modeSwitcher.setMode(agentId, mode);
685
+ yield* eventBus.publish({
686
+ _tag: "Custom",
687
+ type: "interaction.mode-changed",
688
+ payload: { agentId, mode }
689
+ });
690
+ }),
691
+ evaluateTransition: (agentId, context) => modeSwitcher.evaluateTransition(agentId, context),
692
+ // Notifications
693
+ notify: (params) => notifications.send({ ...params, data: void 0 }),
694
+ listUnread: () => notifications.listUnread(),
695
+ markRead: (notificationId) => notifications.markRead(notificationId),
696
+ // Checkpoints
697
+ createCheckpoint: (params) => checkpoints.createCheckpoint(params),
698
+ resolveCheckpoint: (id, status, comment) => checkpoints.resolveCheckpoint(id, status, comment),
699
+ listPendingCheckpoints: (agentId) => checkpoints.listPending(agentId),
700
+ // Collaboration
701
+ startCollaboration: (params) => collaboration.startSession(params),
702
+ endCollaboration: (sessionId) => collaboration.endSession(sessionId),
703
+ sendCollaborationMessage: (params) => collaboration.sendMessage(params),
704
+ // Preferences
705
+ getPreference: (userId) => preferences.getPreference(userId),
706
+ shouldAutoApprove: (params) => preferences.shouldAutoApprove(params)
707
+ };
708
+ })
709
+ );
710
+
711
+ // src/runtime.ts
712
+ import { Layer as Layer7 } from "effect";
713
+ var createInteractionLayer = (config = defaultInteractionConfig) => {
714
+ const NotificationLayer = NotificationServiceLive;
715
+ const SwitcherLayer = ModeSwitcherLive(config);
716
+ const CheckpointLayer = CheckpointServiceLive;
717
+ const CollaborationLayer = CollaborationServiceLive;
718
+ const PreferenceLayer = PreferenceLearnerLive;
719
+ const LeafLayers = Layer7.mergeAll(
720
+ NotificationLayer,
721
+ SwitcherLayer,
722
+ CheckpointLayer,
723
+ CollaborationLayer,
724
+ PreferenceLayer
725
+ );
726
+ const ManagerLayer = InteractionManagerLive.pipe(Layer7.provide(LeafLayers));
727
+ return Layer7.mergeAll(ManagerLayer, LeafLayers);
728
+ };
729
+ export {
730
+ ApprovalAction,
731
+ ApprovalPatternSchema,
732
+ AutoApproveAction,
733
+ CheckpointConfigSchema,
734
+ CheckpointError,
735
+ CheckpointFrequency,
736
+ CheckpointSchema,
737
+ CheckpointService,
738
+ CheckpointServiceLive,
739
+ CheckpointStatus,
740
+ CollaborationMessageSchema,
741
+ CollaborationMessageType,
742
+ CollaborationService,
743
+ CollaborationServiceLive,
744
+ CollaborationSessionSchema,
745
+ CollaborationStatus,
746
+ EscalationConditionSchema,
747
+ EscalationConditionType,
748
+ InputTimeoutError,
749
+ InteractionConfigSchema,
750
+ InteractionError,
751
+ InteractionManager,
752
+ InteractionManagerLive,
753
+ InteractionModeSchema,
754
+ InteractionModeType,
755
+ InterruptEventSchema,
756
+ InterruptRuleSchema,
757
+ InterruptSeverity,
758
+ InterruptTrigger,
759
+ InterruptionTolerance,
760
+ ModeError,
761
+ ModeSwitcher,
762
+ ModeSwitcherLive,
763
+ ModeTransitionRuleSchema,
764
+ NotificationChannel,
765
+ NotificationError,
766
+ NotificationPriority,
767
+ NotificationSchema,
768
+ NotificationService,
769
+ NotificationServiceLive,
770
+ PreferenceLearner,
771
+ PreferenceLearnerLive,
772
+ QuestionStyle,
773
+ ReportingConfigSchema,
774
+ ReportingDetailLevel,
775
+ ReportingFrequency,
776
+ SessionId,
777
+ SessionNotFoundError,
778
+ UserPreferenceSchema,
779
+ createInteractionLayer,
780
+ defaultInteractionConfig
781
+ };
782
+ //# sourceMappingURL=index.js.map