File size: 3,389 Bytes
68d7816
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/* oxlint-disable typescript-eslint/no-unsafe-declaration-merging, eslint-plugin-import/namespace -- Event2 class+payload-interface declaration merging is the sanctioned event-declaration idiom. */
import { z } from 'zod';

import { AgentStatusUpdated } from '#/agent/usage/usageEvents';
import { AgentEvent2 } from '#/app/event/event2';
import { defineState } from '#/state/state';

import '#/agent/contextMemory/conversationTime';

export interface PlanState {
  readonly active: boolean;
  readonly id?: string;
  readonly revisionCount?: Readonly<Record<string, number>>;
}

const planModeEnterSchema = z.object({ agentId: z.string(), id: z.string() });

export class PlanModeEnter extends AgentEvent2<z.infer<typeof planModeEnterSchema>> {
  static override readonly type = 'plan_mode.enter';
  static override readonly durable = true;
  static override readonly schema = planModeEnterSchema;
}
export interface PlanModeEnter {
  readonly agentId: string;
  readonly id: string;
}

const planModeCancelSchema = z.object({
  agentId: z.string(),
  id: z.string().optional(),
});

export class PlanModeCancel extends AgentEvent2<z.infer<typeof planModeCancelSchema>> {
  static override readonly type = 'plan_mode.cancel';
  static override readonly durable = true;
  static override readonly schema = planModeCancelSchema;
}
export interface PlanModeCancel {
  readonly agentId: string;
  readonly id?: string;
}

const planModeExitSchema = z.object({
  agentId: z.string(),
  id: z.string().optional(),
});

export class PlanModeExit extends AgentEvent2<z.infer<typeof planModeExitSchema>> {
  static override readonly type = 'plan_mode.exit';
  static override readonly durable = true;
  static override readonly schema = planModeExitSchema;
}
export interface PlanModeExit {
  readonly agentId: string;
  readonly id?: string;
}

export interface PlanRevisionRecordedEvent {
  readonly agentId: string;
  readonly id: string;
  readonly version: number;
  readonly key: string;
  readonly sha256: string;
  readonly bytes: number;
}

const planRevisionSchema = z.object({
  agentId: z.string(),
  id: z.string(),
  version: z.number(),
  key: z.string(),
  sha256: z.string(),
  bytes: z.number(),
});

export class PlanRevision extends AgentEvent2<PlanRevisionRecordedEvent> {
  static override readonly type = 'plan.revision';
  static override readonly durable = true;
  static override readonly observable = true;
  static override readonly schema = planRevisionSchema;
}
export interface PlanRevision extends PlanRevisionRecordedEvent {}

export const planKey = defineState('plan', (): PlanState => ({ active: false }))
  .replayable({ schema: z.custom<PlanState>() })
  .undoable()
  .on(PlanModeEnter, (s, e, ctx) => {
    if (!(s.active && s.id === e.id)) {
      s.active = true;
      s.id = e.id;
    }
    ctx.emit(new AgentStatusUpdated({ agentId: e.agentId, planMode: true }));
  })
  .on(PlanModeCancel, (s, e, ctx) => {
    if (s.active) {
      s.active = false;
      delete s.id;
    }
    ctx.emit(new AgentStatusUpdated({ agentId: e.agentId, planMode: false }));
  })
  .on(PlanModeExit, (s, e, ctx) => {
    if (s.active) {
      s.active = false;
      delete s.id;
    }
    ctx.emit(new AgentStatusUpdated({ agentId: e.agentId, planMode: false }));
  })
  .on(PlanRevision, (s, e) => {
    s.revisionCount = { ...s.revisionCount, [e.id]: e.version };
  });