openhorse 0.2.23 → 0.2.24

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.
Files changed (59) hide show
  1. package/dist/commands/target-command.d.ts +21 -0
  2. package/dist/commands/target-command.d.ts.map +1 -0
  3. package/dist/commands/target-command.js +81 -0
  4. package/dist/commands/target-command.js.map +1 -0
  5. package/dist/runtime/agent-runtime-controller.d.ts +5 -0
  6. package/dist/runtime/agent-runtime-controller.d.ts.map +1 -1
  7. package/dist/runtime/agent-runtime-controller.js +54 -0
  8. package/dist/runtime/agent-runtime-controller.js.map +1 -1
  9. package/dist/runtime/agent-runtime-protocol.d.ts +4 -0
  10. package/dist/runtime/agent-runtime-protocol.d.ts.map +1 -1
  11. package/dist/runtime/agent-runtime-protocol.js.map +1 -1
  12. package/dist/runtime/goal-coordinator.d.ts +66 -0
  13. package/dist/runtime/goal-coordinator.d.ts.map +1 -0
  14. package/dist/runtime/goal-coordinator.js +200 -0
  15. package/dist/runtime/goal-coordinator.js.map +1 -0
  16. package/dist/runtime/goals/accounting.d.ts +17 -0
  17. package/dist/runtime/goals/accounting.d.ts.map +1 -0
  18. package/dist/runtime/goals/accounting.js +45 -0
  19. package/dist/runtime/goals/accounting.js.map +1 -0
  20. package/dist/runtime/goals/completion-audit.d.ts +24 -0
  21. package/dist/runtime/goals/completion-audit.d.ts.map +1 -0
  22. package/dist/runtime/goals/completion-audit.js +48 -0
  23. package/dist/runtime/goals/completion-audit.js.map +1 -0
  24. package/dist/runtime/goals/coordinator.d.ts +42 -0
  25. package/dist/runtime/goals/coordinator.d.ts.map +1 -0
  26. package/dist/runtime/goals/coordinator.js +277 -0
  27. package/dist/runtime/goals/coordinator.js.map +1 -0
  28. package/dist/runtime/goals/prompt.d.ts +16 -0
  29. package/dist/runtime/goals/prompt.d.ts.map +1 -0
  30. package/dist/runtime/goals/prompt.js +50 -0
  31. package/dist/runtime/goals/prompt.js.map +1 -0
  32. package/dist/runtime/goals/tools.d.ts +43 -0
  33. package/dist/runtime/goals/tools.d.ts.map +1 -0
  34. package/dist/runtime/goals/tools.js +88 -0
  35. package/dist/runtime/goals/tools.js.map +1 -0
  36. package/dist/runtime/goals/types.d.ts +167 -0
  37. package/dist/runtime/goals/types.d.ts.map +1 -0
  38. package/dist/runtime/goals/types.js +72 -0
  39. package/dist/runtime/goals/types.js.map +1 -0
  40. package/dist/services/goal-sidecar.d.ts +96 -0
  41. package/dist/services/goal-sidecar.d.ts.map +1 -0
  42. package/dist/services/goal-sidecar.js +145 -0
  43. package/dist/services/goal-sidecar.js.map +1 -0
  44. package/dist/services/goal-storage.d.ts +22 -0
  45. package/dist/services/goal-storage.d.ts.map +1 -0
  46. package/dist/services/goal-storage.js +153 -0
  47. package/dist/services/goal-storage.js.map +1 -0
  48. package/dist/services/session-storage.d.ts +4 -0
  49. package/dist/services/session-storage.d.ts.map +1 -1
  50. package/dist/services/session-storage.js +10 -0
  51. package/dist/services/session-storage.js.map +1 -1
  52. package/dist/terminal-ui/launch.d.ts.map +1 -1
  53. package/dist/terminal-ui/launch.js +49 -0
  54. package/dist/terminal-ui/launch.js.map +1 -1
  55. package/dist/tools/goal.d.ts +17 -0
  56. package/dist/tools/goal.d.ts.map +1 -0
  57. package/dist/tools/goal.js +191 -0
  58. package/dist/tools/goal.js.map +1 -0
  59. package/package.json +1 -1
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ /**
3
+ * v0.2.24 — Goal Model Tools.
4
+ *
5
+ * get_goal, create_goal, update_goal tool definitions for the Agent.
6
+ * These tools allow the model to read and request changes to the
7
+ * persistent goal. Actual state changes go through GoalCoordinator.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.buildGetGoalTool = buildGetGoalTool;
11
+ exports.executeGetGoal = executeGetGoal;
12
+ exports.buildCreateGoalTool = buildCreateGoalTool;
13
+ exports.executeCreateGoal = executeCreateGoal;
14
+ exports.buildUpdateGoalTool = buildUpdateGoalTool;
15
+ exports.executeUpdateGoal = executeUpdateGoal;
16
+ function buildGetGoalTool() {
17
+ return {
18
+ name: 'get_goal',
19
+ description: 'Read the current persistent goal for this session. Returns null if no goal is active.',
20
+ parameters: {
21
+ type: 'object',
22
+ properties: {},
23
+ required: [],
24
+ },
25
+ };
26
+ }
27
+ function executeGetGoal(bindings) {
28
+ return bindings.coordinator.snapshot();
29
+ }
30
+ function buildCreateGoalTool() {
31
+ return {
32
+ name: 'create_goal',
33
+ description: 'Create a persistent goal for this session. Only use when the user explicitly requests a long-running goal. Rejects if a goal already exists.',
34
+ parameters: {
35
+ type: 'object',
36
+ properties: {
37
+ objective: {
38
+ type: 'string',
39
+ description: 'The goal objective. Must be clear, specific, and verifiable.',
40
+ },
41
+ token_budget: {
42
+ type: 'number',
43
+ description: 'Optional token budget. Only set when the user explicitly provides a budget.',
44
+ },
45
+ },
46
+ required: ['objective'],
47
+ },
48
+ };
49
+ }
50
+ function executeCreateGoal(bindings, objective, tokenBudget) {
51
+ const result = bindings.coordinator.create(objective);
52
+ if (!result.ok)
53
+ return { ok: false, error: result.error };
54
+ if (tokenBudget && tokenBudget > 0) {
55
+ bindings.coordinator.setBudget(tokenBudget);
56
+ }
57
+ const snap = bindings.coordinator.snapshot();
58
+ return snap ? { ok: true, goal: snap } : { ok: false, error: 'Goal was created but snapshot is unavailable.' };
59
+ }
60
+ function buildUpdateGoalTool() {
61
+ return {
62
+ name: 'update_goal',
63
+ description: 'Request a status change for the current goal. The request is audited before the change takes effect.',
64
+ parameters: {
65
+ type: 'object',
66
+ properties: {
67
+ status: {
68
+ type: 'string',
69
+ enum: ['complete', 'blocked'],
70
+ description: 'The requested target status: "complete" when all requirements are verified; "blocked" when the same blocker persisted for 3+ turns.',
71
+ },
72
+ },
73
+ required: ['status'],
74
+ },
75
+ };
76
+ }
77
+ function executeUpdateGoal(bindings, status) {
78
+ const goal = bindings.coordinator.goal;
79
+ if (!goal)
80
+ return { ok: false, error: 'No active goal to update.' };
81
+ if (goal.status !== 'active')
82
+ return { ok: false, error: `Goal is not active (current status: ${goal.status}).` };
83
+ return {
84
+ ok: true,
85
+ message: `Goal ${status} request recorded. Audit will verify before applying.`,
86
+ };
87
+ }
88
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/runtime/goals/tools.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AASH,4CAcC;AAED,wCAEC;AAED,kDAuBC;AAED,8CAcC;AAED,kDAoBC;AAED,8CAYC;AA/FD,SAAgB,gBAAgB;IAK9B,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,uFAAuF;QACpG,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE;YACd,QAAQ,EAAE,EAAE;SACb;KACF,CAAC;AACJ,CAAC;AAED,SAAgB,cAAc,CAAC,QAA0B;IACvD,OAAO,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;AACzC,CAAC;AAED,SAAgB,mBAAmB;IAKjC,OAAO;QACL,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,8IAA8I;QAC3J,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,8DAA8D;iBAC5E;gBACD,YAAY,EAAE;oBACZ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,6EAA6E;iBAC3F;aACF;YACD,QAAQ,EAAE,CAAC,WAAW,CAAC;SACxB;KACF,CAAC;AACJ,CAAC;AAED,SAAgB,iBAAiB,CAC/B,QAA0B,EAC1B,SAAiB,EACjB,WAAoB;IAEpB,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACtD,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;IAE1D,IAAI,WAAW,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QACnC,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;IAC7C,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,+CAA+C,EAAE,CAAC;AACjH,CAAC;AAED,SAAgB,mBAAmB;IAKjC,OAAO;QACL,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,sGAAsG;QACnH,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC;oBAC7B,WAAW,EAAE,qIAAqI;iBACnJ;aACF;YACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;SACrB;KACF,CAAC;AACJ,CAAC;AAED,SAAgB,iBAAiB,CAC/B,QAA0B,EAC1B,MAA8B;IAE9B,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC;IACvC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,2BAA2B,EAAE,CAAC;IACpE,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,uCAAuC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;IAElH,OAAO;QACL,EAAE,EAAE,IAAI;QACR,OAAO,EAAE,QAAQ,MAAM,uDAAuD;KAC/E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * v0.2.24 — Goal / Target Mode domain types.
3
+ *
4
+ * Goal is a persistent, single-session entity that the Agent pursues across
5
+ * multiple turns, Compact, process restart, and /resume. It is NOT a
6
+ * Harness field, a prompt string, or a UI state — it is an independent
7
+ * lifecycle entity with its own sidecar storage.
8
+ */
9
+ export type GoalStatus = 'active' | 'paused' | 'blocked' | 'usage_limited' | 'budget_limited' | 'complete';
10
+ export declare const GOAL_ACTIVE_STATES: ReadonlySet<GoalStatus>;
11
+ export declare const GOAL_TERMINAL_STATES: ReadonlySet<GoalStatus>;
12
+ export declare const GOAL_USER_RECOVERABLE_STATES: ReadonlySet<GoalStatus>;
13
+ export interface GoalBlocker {
14
+ fingerprint: string;
15
+ firstSeenAt: number;
16
+ lastSeenAt: number;
17
+ consecutiveTurns: number;
18
+ summary: string;
19
+ }
20
+ export interface GoalLastTurn {
21
+ turnId: string;
22
+ finishReason: string;
23
+ endedAt: number;
24
+ promptTokens: number;
25
+ completionTokens: number;
26
+ subagentTokens: number;
27
+ totalTokens: number;
28
+ madeProgress: boolean;
29
+ }
30
+ export interface GoalCompletionAudit {
31
+ requestedAt: number;
32
+ auditedAt: number;
33
+ passed: boolean;
34
+ verificationSummary: string;
35
+ remainingRequirements: string[];
36
+ evidenceRefs: string[];
37
+ }
38
+ export interface GoalStopReason {
39
+ kind: 'user' | 'blocked' | 'usage_limit' | 'budget_limit' | 'runtime_error';
40
+ message: string;
41
+ at: number;
42
+ }
43
+ export interface SessionGoalV1 {
44
+ version: 1;
45
+ goalId: string;
46
+ sessionId: string;
47
+ revision: number;
48
+ objective: string;
49
+ status: GoalStatus;
50
+ tokenBudget?: number;
51
+ tokensUsed: number;
52
+ timeUsedMs: number;
53
+ createdAt: number;
54
+ updatedAt: number;
55
+ activeSince?: number;
56
+ completedAt?: number;
57
+ continuationCount: number;
58
+ noProgressCount: number;
59
+ blocker?: GoalBlocker;
60
+ lastTurn?: GoalLastTurn;
61
+ completionAudit?: GoalCompletionAudit;
62
+ stopReason?: GoalStopReason;
63
+ }
64
+ export interface RuntimeGoalSnapshot {
65
+ goalId: string;
66
+ revision: number;
67
+ objective: string;
68
+ status: GoalStatus;
69
+ tokenBudget?: number;
70
+ tokensUsed: number;
71
+ timeUsedMs: number;
72
+ continuationCount: number;
73
+ updatedAt: number;
74
+ stopReason?: string;
75
+ }
76
+ export type AgentInputKind = 'user' | 'revision' | 'goal_continuation' | 'command';
77
+ export interface GoalTurnContext {
78
+ goalId: string;
79
+ revision: number;
80
+ continuationIndex: number;
81
+ }
82
+ export interface AgentTurnRequest {
83
+ inputKind: AgentInputKind;
84
+ text?: string;
85
+ sessionId: string;
86
+ goal?: GoalTurnContext;
87
+ persistAsUserMessage: boolean;
88
+ echoToTranscript: boolean;
89
+ }
90
+ export interface AgentTurnOutcome {
91
+ turnId: string;
92
+ sessionId: string;
93
+ goalId?: string;
94
+ goalRevision?: number;
95
+ startedAt: number;
96
+ endedAt: number;
97
+ finishReason: string;
98
+ usage: {
99
+ promptTokens: number;
100
+ completionTokens: number;
101
+ subagentTokens: number;
102
+ totalTokens: number;
103
+ };
104
+ madeProgress: boolean;
105
+ blocker?: {
106
+ fingerprint: string;
107
+ summary: string;
108
+ retryable: boolean;
109
+ };
110
+ providerError?: {
111
+ kind: 'usage_limit' | 'rate_limit' | 'auth' | 'network' | 'unknown';
112
+ retryable: boolean;
113
+ };
114
+ pendingTerminalRequest?: {
115
+ requestedStatus: 'complete' | 'blocked';
116
+ requestedAt: number;
117
+ };
118
+ }
119
+ export type GoalControlAction = 'show' | 'create' | 'edit' | 'replace' | 'pause' | 'resume' | 'clear' | 'set_budget';
120
+ export interface GoalControlInput {
121
+ type: 'goal_control';
122
+ action: GoalControlAction;
123
+ payload?: {
124
+ objective?: string;
125
+ tokenBudget?: number | null;
126
+ confirmed?: boolean;
127
+ };
128
+ }
129
+ export interface GoalUpdatedEvent {
130
+ type: 'goal_updated';
131
+ goal: RuntimeGoalSnapshot;
132
+ reason: string;
133
+ }
134
+ export interface GoalClearedEvent {
135
+ type: 'goal_cleared';
136
+ goalId: string;
137
+ reason: string;
138
+ }
139
+ export interface GoalContinuationEvent {
140
+ type: 'goal_continuation';
141
+ goalId: string;
142
+ phase: 'scheduled' | 'started' | 'deferred' | 'stopped';
143
+ reason: string;
144
+ }
145
+ export interface GoalAuditFailedEvent {
146
+ type: 'goal_audit_failed';
147
+ goalId: string;
148
+ audit: 'completion' | 'blocked';
149
+ summary: string;
150
+ }
151
+ export interface GoalRestoredEvent {
152
+ type: 'goal_restored';
153
+ goal: RuntimeGoalSnapshot;
154
+ }
155
+ /**
156
+ * Valid status transitions for the Goal state machine.
157
+ * Returns the allowed next status, or null if the transition is invalid.
158
+ */
159
+ export declare function goalTransition(current: GoalStatus | null, event: 'create' | 'pause' | 'resume' | 'complete' | 'block' | 'usage_limit' | 'budget_limit' | 'replace' | 'clear'): GoalStatus | null;
160
+ /** Constraints from the goal plan that must hold across the state machine. */
161
+ export declare const GOAL_INVARIANTS: {
162
+ readonly maxObjectiveChars: 4000;
163
+ readonly maxConsecutiveBlockerTurns: 3;
164
+ readonly maxConsecutiveNoProgressTurns: 3;
165
+ readonly tokenBudgetMin: 1;
166
+ };
167
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/runtime/goals/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ /**
3
+ * v0.2.24 — Goal / Target Mode domain types.
4
+ *
5
+ * Goal is a persistent, single-session entity that the Agent pursues across
6
+ * multiple turns, Compact, process restart, and /resume. It is NOT a
7
+ * Harness field, a prompt string, or a UI state — it is an independent
8
+ * lifecycle entity with its own sidecar storage.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.GOAL_INVARIANTS = exports.GOAL_USER_RECOVERABLE_STATES = exports.GOAL_TERMINAL_STATES = exports.GOAL_ACTIVE_STATES = void 0;
12
+ exports.goalTransition = goalTransition;
13
+ exports.GOAL_ACTIVE_STATES = new Set(['active']);
14
+ exports.GOAL_TERMINAL_STATES = new Set([
15
+ 'blocked', 'usage_limited', 'budget_limited', 'complete',
16
+ ]);
17
+ exports.GOAL_USER_RECOVERABLE_STATES = new Set([
18
+ 'paused', 'blocked', 'usage_limited', 'budget_limited',
19
+ ]);
20
+ // ============================================================================
21
+ // State machine
22
+ // ============================================================================
23
+ /**
24
+ * Valid status transitions for the Goal state machine.
25
+ * Returns the allowed next status, or null if the transition is invalid.
26
+ */
27
+ function goalTransition(current, event) {
28
+ if (event === 'create')
29
+ return current === null ? 'active' : null;
30
+ if (event === 'replace')
31
+ return 'active'; // always allowed, generates new goalId
32
+ if (event === 'clear')
33
+ return null; // removes goal entirely
34
+ if (current === null)
35
+ return null;
36
+ switch (current) {
37
+ case 'active':
38
+ if (event === 'pause')
39
+ return 'paused';
40
+ if (event === 'complete')
41
+ return 'complete';
42
+ if (event === 'block')
43
+ return 'blocked';
44
+ if (event === 'usage_limit')
45
+ return 'usage_limited';
46
+ if (event === 'budget_limit')
47
+ return 'budget_limited';
48
+ return null;
49
+ case 'paused':
50
+ if (event === 'resume')
51
+ return 'active';
52
+ return null;
53
+ case 'blocked':
54
+ case 'usage_limited':
55
+ case 'budget_limited':
56
+ if (event === 'resume')
57
+ return 'active';
58
+ return null;
59
+ case 'complete':
60
+ return null; // terminal — only replace or clear
61
+ default:
62
+ return null;
63
+ }
64
+ }
65
+ /** Constraints from the goal plan that must hold across the state machine. */
66
+ exports.GOAL_INVARIANTS = {
67
+ maxObjectiveChars: 4000,
68
+ maxConsecutiveBlockerTurns: 3,
69
+ maxConsecutiveNoProgressTurns: 3,
70
+ tokenBudgetMin: 1,
71
+ };
72
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/runtime/goals/types.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAqOH,wCAmCC;AA1PY,QAAA,kBAAkB,GAA4B,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AAClE,QAAA,oBAAoB,GAA4B,IAAI,GAAG,CAAC;IACnE,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,UAAU;CACzD,CAAC,CAAC;AACU,QAAA,4BAA4B,GAA4B,IAAI,GAAG,CAAC;IAC3E,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB;CACvD,CAAC,CAAC;AAyMH,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E;;;GAGG;AACH,SAAgB,cAAc,CAC5B,OAA0B,EAC1B,KAAkH;IAElH,IAAI,KAAK,KAAK,QAAQ;QAAE,OAAO,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IAClE,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC,CAAE,uCAAuC;IAClF,IAAI,KAAK,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC,CAAQ,wBAAwB;IAEnE,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAElC,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,QAAQ;YACX,IAAI,KAAK,KAAK,OAAO;gBAAE,OAAO,QAAQ,CAAC;YACvC,IAAI,KAAK,KAAK,UAAU;gBAAE,OAAO,UAAU,CAAC;YAC5C,IAAI,KAAK,KAAK,OAAO;gBAAE,OAAO,SAAS,CAAC;YACxC,IAAI,KAAK,KAAK,aAAa;gBAAE,OAAO,eAAe,CAAC;YACpD,IAAI,KAAK,KAAK,cAAc;gBAAE,OAAO,gBAAgB,CAAC;YACtD,OAAO,IAAI,CAAC;QAEd,KAAK,QAAQ;YACX,IAAI,KAAK,KAAK,QAAQ;gBAAE,OAAO,QAAQ,CAAC;YACxC,OAAO,IAAI,CAAC;QAEd,KAAK,SAAS,CAAC;QACf,KAAK,eAAe,CAAC;QACrB,KAAK,gBAAgB;YACnB,IAAI,KAAK,KAAK,QAAQ;gBAAE,OAAO,QAAQ,CAAC;YACxC,OAAO,IAAI,CAAC;QAEd,KAAK,UAAU;YACb,OAAO,IAAI,CAAC,CAAE,mCAAmC;QAEnD;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED,8EAA8E;AACjE,QAAA,eAAe,GAAG;IAC7B,iBAAiB,EAAE,IAAI;IACvB,0BAA0B,EAAE,CAAC;IAC7B,6BAA6B,EAAE,CAAC;IAChC,cAAc,EAAE,CAAC;CACT,CAAC"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * openhorse — Goal Sidecar
3
+ *
4
+ * Persistent target mode state, stored as a JSON sidecar under the session
5
+ * directory. Implements cross-turn goal lifecycle, idle continuation, and
6
+ * per-resume recovery per v0.2.24-target-mode-plan section 8.
7
+ *
8
+ * This sidecar is the source of truth for goal state; Compact summaries and
9
+ * HarnessState.rootObjective are derived shadows, not the canonical record.
10
+ */
11
+ import { getProjectSessionGoalPath } from './config-dir';
12
+ import type { SessionMeta } from './session-storage';
13
+ export type GoalStatus = 'active' | 'paused' | 'blocked' | 'usage_limited' | 'budget_limited' | 'complete';
14
+ export declare const GOAL_ACTIVE_STATUSES: Set<GoalStatus>;
15
+ export declare const GOAL_TERMINAL_STATUSES: Set<GoalStatus>;
16
+ export declare const GOAL_PAUSABLE_STATUSES: Set<GoalStatus>;
17
+ export declare const GOAL_RESUMABLE_STATUSES: Set<GoalStatus>;
18
+ export declare const GOAL_CLEARABLE_STATUSES: Set<GoalStatus>;
19
+ /**
20
+ * Accounting counters accumulated across all goal turns.
21
+ * These are separate from SessionMeta.tokenCount/cost so a replaced
22
+ * goal does not lose track of its own spend.
23
+ */
24
+ export interface GoalAccounting {
25
+ /** Total prompt tokens consumed across all goal turns. */
26
+ promptTokens: number;
27
+ /** Total completion tokens consumed across all goal turns. */
28
+ completionTokens: number;
29
+ /** Total estimated cost (USD) across all goal turns. */
30
+ cost: number;
31
+ /** Number of goal turns (autonomous continuation fires). */
32
+ turnCount: number;
33
+ /** Wall-clock milliseconds accumulated across goal turns. */
34
+ elapsedMs: number;
35
+ }
36
+ export interface GoalBlockedInfo {
37
+ /** The reason string from the last blocked turn's tool result. */
38
+ reason: string;
39
+ /** How many consecutive turns this blocker has been reported. */
40
+ consecutiveTurns: number;
41
+ }
42
+ export interface GoalCompletionEvidence {
43
+ /** Requirement-by-requirement audit result. */
44
+ requirements: Array<{
45
+ requirement: string;
46
+ met: boolean;
47
+ evidence: string;
48
+ }>;
49
+ /** Agent-provided summary of completed work. */
50
+ summary: string;
51
+ /** Timestamp when completion was proposed. */
52
+ proposedAt: number;
53
+ }
54
+ export interface GoalSidecarV1 {
55
+ version: 1;
56
+ goalId: string;
57
+ sessionId: string;
58
+ projectPath: string;
59
+ /** The original user objective text. Never overwritten by Compact. */
60
+ objective: string;
61
+ status: GoalStatus;
62
+ /** Monotonic CAS revision; incremented on every write. */
63
+ revision: number;
64
+ createdAt: number;
65
+ updatedAt: number;
66
+ /** Optional user-specified token budget (null = unlimited). */
67
+ tokenBudget: number | null;
68
+ accounting: GoalAccounting;
69
+ /** Blocking information when status === 'blocked'. */
70
+ blocked?: GoalBlockedInfo;
71
+ /** Completion evidence when status === 'complete'. */
72
+ completion?: GoalCompletionEvidence;
73
+ /** Fingerprint of the last known continueReason; used for blocking detection. */
74
+ lastContinueReason: string | null;
75
+ }
76
+ export declare function createGoalSidecar(goalId: string, session: Pick<SessionMeta, 'id' | 'projectPath'>, objective: string, tokenBudget?: number | null, now?: number): GoalSidecarV1;
77
+ export declare function loadGoalSidecar(session: Pick<SessionMeta, 'id' | 'projectPath'>): GoalSidecarV1 | null;
78
+ export declare function saveGoalSidecar(sidecar: GoalSidecarV1): void;
79
+ export declare function transitionGoalStatus(sidecar: GoalSidecarV1, target: GoalStatus, metadata?: Partial<Pick<GoalSidecarV1, 'blocked' | 'completion'>>): GoalSidecarV1;
80
+ export declare function accumulateGoalUsage(sidecar: GoalSidecarV1, usage: {
81
+ promptTokens: number;
82
+ completionTokens: number;
83
+ cost: number;
84
+ }, elapsedMs: number): GoalSidecarV1;
85
+ /**
86
+ * Check whether accumulated cost exceeds the budget.
87
+ * Returns true when over budget (nil budget = never over).
88
+ */
89
+ export declare function isGoalOverBudget(sidecar: GoalSidecarV1): boolean;
90
+ /**
91
+ * Check whether the same blocker reason has persisted for enough
92
+ * consecutive turns to enter 'blocked' status.
93
+ */
94
+ export declare function shouldMarkBlocked(sidecar: GoalSidecarV1, currentContinueReason: string, consecutiveThreshold?: number): boolean;
95
+ export { getProjectSessionGoalPath };
96
+ //# sourceMappingURL=goal-sidecar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goal-sidecar.d.ts","sourceRoot":"","sources":["../../src/services/goal-sidecar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ /**
3
+ * openhorse — Goal Sidecar
4
+ *
5
+ * Persistent target mode state, stored as a JSON sidecar under the session
6
+ * directory. Implements cross-turn goal lifecycle, idle continuation, and
7
+ * per-resume recovery per v0.2.24-target-mode-plan section 8.
8
+ *
9
+ * This sidecar is the source of truth for goal state; Compact summaries and
10
+ * HarnessState.rootObjective are derived shadows, not the canonical record.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.getProjectSessionGoalPath = exports.GOAL_CLEARABLE_STATUSES = exports.GOAL_RESUMABLE_STATUSES = exports.GOAL_PAUSABLE_STATUSES = exports.GOAL_TERMINAL_STATUSES = exports.GOAL_ACTIVE_STATUSES = void 0;
14
+ exports.createGoalSidecar = createGoalSidecar;
15
+ exports.loadGoalSidecar = loadGoalSidecar;
16
+ exports.saveGoalSidecar = saveGoalSidecar;
17
+ exports.transitionGoalStatus = transitionGoalStatus;
18
+ exports.accumulateGoalUsage = accumulateGoalUsage;
19
+ exports.isGoalOverBudget = isGoalOverBudget;
20
+ exports.shouldMarkBlocked = shouldMarkBlocked;
21
+ const fs_1 = require("fs");
22
+ const atomic_write_1 = require("./atomic-write");
23
+ const config_dir_1 = require("./config-dir");
24
+ Object.defineProperty(exports, "getProjectSessionGoalPath", { enumerable: true, get: function () { return config_dir_1.getProjectSessionGoalPath; } });
25
+ exports.GOAL_ACTIVE_STATUSES = new Set(['active']);
26
+ exports.GOAL_TERMINAL_STATUSES = new Set([
27
+ 'complete',
28
+ 'budget_limited',
29
+ 'usage_limited', // usage_limited is terminal until user resets
30
+ ]);
31
+ exports.GOAL_PAUSABLE_STATUSES = new Set(['active']);
32
+ exports.GOAL_RESUMABLE_STATUSES = new Set(['paused']);
33
+ exports.GOAL_CLEARABLE_STATUSES = new Set([
34
+ 'active',
35
+ 'paused',
36
+ 'blocked',
37
+ 'complete',
38
+ 'usage_limited',
39
+ 'budget_limited',
40
+ ]);
41
+ // ============================================================================
42
+ // Factory & helpers
43
+ // ============================================================================
44
+ function createGoalSidecar(goalId, session, objective, tokenBudget = null, now = Date.now()) {
45
+ return {
46
+ version: 1,
47
+ goalId,
48
+ sessionId: session.id,
49
+ projectPath: session.projectPath,
50
+ objective,
51
+ status: 'active',
52
+ revision: 1,
53
+ createdAt: now,
54
+ updatedAt: now,
55
+ tokenBudget,
56
+ accounting: {
57
+ promptTokens: 0,
58
+ completionTokens: 0,
59
+ cost: 0,
60
+ turnCount: 0,
61
+ elapsedMs: 0,
62
+ },
63
+ lastContinueReason: null,
64
+ };
65
+ }
66
+ // ============================================================================
67
+ // Persistence
68
+ // ============================================================================
69
+ function loadGoalSidecar(session) {
70
+ const path = (0, config_dir_1.getProjectSessionGoalPath)(session.projectPath, session.id);
71
+ if (!(0, fs_1.existsSync)(path))
72
+ return null;
73
+ try {
74
+ const parsed = JSON.parse((0, fs_1.readFileSync)(path, 'utf-8'));
75
+ if (parsed.version !== 1 || typeof parsed.goalId !== 'string' || !parsed.goalId) {
76
+ return null;
77
+ }
78
+ if (typeof parsed.objective !== 'string' || !parsed.objective) {
79
+ return null;
80
+ }
81
+ if (typeof parsed.status !== 'string') {
82
+ return null;
83
+ }
84
+ return parsed;
85
+ }
86
+ catch {
87
+ return null;
88
+ }
89
+ }
90
+ function saveGoalSidecar(sidecar) {
91
+ sidecar.revision = (sidecar.revision ?? 0) + 1;
92
+ sidecar.updatedAt = Date.now();
93
+ (0, config_dir_1.ensureProjectDir)(sidecar.projectPath);
94
+ (0, atomic_write_1.atomicWriteFileSync)((0, config_dir_1.getProjectSessionGoalPath)(sidecar.projectPath, sidecar.sessionId), JSON.stringify(sidecar, null, 2), { mode: 0o600 });
95
+ }
96
+ // ============================================================================
97
+ // Status transitions (idempotent, validated)
98
+ // ============================================================================
99
+ function transitionGoalStatus(sidecar, target, metadata) {
100
+ if (sidecar.status === target)
101
+ return sidecar;
102
+ if (target === 'blocked' && metadata?.blocked) {
103
+ sidecar.status = 'blocked';
104
+ sidecar.blocked = metadata.blocked;
105
+ }
106
+ else if (target === 'complete' && metadata?.completion) {
107
+ sidecar.status = 'complete';
108
+ sidecar.completion = metadata.completion;
109
+ }
110
+ else {
111
+ sidecar.status = target;
112
+ }
113
+ return sidecar;
114
+ }
115
+ // ============================================================================
116
+ // Accounting accumulation
117
+ // ============================================================================
118
+ function accumulateGoalUsage(sidecar, usage, elapsedMs) {
119
+ sidecar.accounting.promptTokens += usage.promptTokens;
120
+ sidecar.accounting.completionTokens += usage.completionTokens;
121
+ sidecar.accounting.cost += usage.cost;
122
+ sidecar.accounting.turnCount += 1;
123
+ sidecar.accounting.elapsedMs += elapsedMs;
124
+ return sidecar;
125
+ }
126
+ /**
127
+ * Check whether accumulated cost exceeds the budget.
128
+ * Returns true when over budget (nil budget = never over).
129
+ */
130
+ function isGoalOverBudget(sidecar) {
131
+ if (sidecar.tokenBudget === null)
132
+ return false;
133
+ return sidecar.accounting.cost >= sidecar.tokenBudget;
134
+ }
135
+ /**
136
+ * Check whether the same blocker reason has persisted for enough
137
+ * consecutive turns to enter 'blocked' status.
138
+ */
139
+ function shouldMarkBlocked(sidecar, currentContinueReason, consecutiveThreshold = 3) {
140
+ if (sidecar.lastContinueReason === currentContinueReason) {
141
+ return (sidecar.blocked?.consecutiveTurns ?? 0) + 1 >= consecutiveThreshold;
142
+ }
143
+ return false;
144
+ }
145
+ //# sourceMappingURL=goal-sidecar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goal-sidecar.js","sourceRoot":"","sources":["../../src/services/goal-sidecar.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAkHH,8CA2BC;AAMD,0CAmBC;AAED,0CASC;AAMD,oDAkBC;AAMD,kDAWC;AAMD,4CAGC;AAMD,8CASC;AAhPD,2BAA8C;AAC9C,iDAAqD;AACrD,6CAA2E;AAoPlE,0GApPkB,sCAAyB,OAoPlB;AArOrB,QAAA,oBAAoB,GAAoB,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AAE5D,QAAA,sBAAsB,GAAoB,IAAI,GAAG,CAAC;IAC7D,UAAU;IACV,gBAAgB;IAChB,eAAe,EAAE,8CAA8C;CAChE,CAAC,CAAC;AAEU,QAAA,sBAAsB,GAAoB,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AAE9D,QAAA,uBAAuB,GAAoB,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AAE/D,QAAA,uBAAuB,GAAoB,IAAI,GAAG,CAAC;IAC9D,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,UAAU;IACV,eAAe;IACf,gBAAgB;CACjB,CAAC,CAAC;AAwEH,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E,SAAgB,iBAAiB,CAC/B,MAAc,EACd,OAAgD,EAChD,SAAiB,EACjB,cAA6B,IAAI,EACjC,MAAc,IAAI,CAAC,GAAG,EAAE;IAExB,OAAO;QACL,OAAO,EAAE,CAAC;QACV,MAAM;QACN,SAAS,EAAE,OAAO,CAAC,EAAE;QACrB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,SAAS;QACT,MAAM,EAAE,QAAQ;QAChB,QAAQ,EAAE,CAAC;QACX,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,GAAG;QACd,WAAW;QACX,UAAU,EAAE;YACV,YAAY,EAAE,CAAC;YACf,gBAAgB,EAAE,CAAC;YACnB,IAAI,EAAE,CAAC;YACP,SAAS,EAAE,CAAC;YACZ,SAAS,EAAE,CAAC;SACb;QACD,kBAAkB,EAAE,IAAI;KACzB,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,cAAc;AACd,+EAA+E;AAE/E,SAAgB,eAAe,CAAC,OAAgD;IAC9E,MAAM,IAAI,GAAG,IAAA,sCAAyB,EAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IACxE,IAAI,CAAC,IAAA,eAAU,EAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEnC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAY,EAAC,IAAI,EAAE,OAAO,CAAC,CAA2B,CAAC;QACjF,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YAChF,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YAC9D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACtC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,MAAuB,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,eAAe,CAAC,OAAsB;IACpD,OAAO,CAAC,QAAQ,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC/B,IAAA,6BAAgB,EAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACtC,IAAA,kCAAmB,EACjB,IAAA,sCAAyB,EAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,SAAS,CAAC,EACjE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAChC,EAAE,IAAI,EAAE,KAAK,EAAE,CAChB,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,6CAA6C;AAC7C,+EAA+E;AAE/E,SAAgB,oBAAoB,CAClC,OAAsB,EACtB,MAAkB,EAClB,QAAiE;IAEjE,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM;QAAE,OAAO,OAAO,CAAC;IAE9C,IAAI,MAAM,KAAK,SAAS,IAAI,QAAQ,EAAE,OAAO,EAAE,CAAC;QAC9C,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;QAC3B,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;IACrC,CAAC;SAAM,IAAI,MAAM,KAAK,UAAU,IAAI,QAAQ,EAAE,UAAU,EAAE,CAAC;QACzD,OAAO,CAAC,MAAM,GAAG,UAAU,CAAC;QAC5B,OAAO,CAAC,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC;IAC3C,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IAC1B,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,+EAA+E;AAC/E,0BAA0B;AAC1B,+EAA+E;AAE/E,SAAgB,mBAAmB,CACjC,OAAsB,EACtB,KAAuE,EACvE,SAAiB;IAEjB,OAAO,CAAC,UAAU,CAAC,YAAY,IAAI,KAAK,CAAC,YAAY,CAAC;IACtD,OAAO,CAAC,UAAU,CAAC,gBAAgB,IAAI,KAAK,CAAC,gBAAgB,CAAC;IAC9D,OAAO,CAAC,UAAU,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC;IACtC,OAAO,CAAC,UAAU,CAAC,SAAS,IAAI,CAAC,CAAC;IAClC,OAAO,CAAC,UAAU,CAAC,SAAS,IAAI,SAAS,CAAC;IAC1C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,OAAsB;IACrD,IAAI,OAAO,CAAC,WAAW,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC/C,OAAO,OAAO,CAAC,UAAU,CAAC,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC;AACxD,CAAC;AAED;;;GAGG;AACH,SAAgB,iBAAiB,CAC/B,OAAsB,EACtB,qBAA6B,EAC7B,uBAA+B,CAAC;IAEhC,IAAI,OAAO,CAAC,kBAAkB,KAAK,qBAAqB,EAAE,CAAC;QACzD,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,gBAAgB,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,oBAAoB,CAAC;IAC9E,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * v0.2.24 — Goal Storage.
3
+ *
4
+ * Atomic sidecar persistence for Session goals. Uses compare-and-swap
5
+ * revision, temporary file + atomic rename, and corrupt quarantine.
6
+ */
7
+ import type { SessionGoalV1 } from '../runtime/goals/types';
8
+ export type GoalStorageResult<T = void> = {
9
+ ok: true;
10
+ value: T;
11
+ } | {
12
+ ok: false;
13
+ error: 'not_found' | 'revision_stale' | 'corrupt' | 'io_error';
14
+ message: string;
15
+ };
16
+ export declare function loadGoal(projectPath: string, sessionId: string): GoalStorageResult<SessionGoalV1>;
17
+ export declare function saveGoal(projectPath: string, sessionId: string, goal: SessionGoalV1, expectedRevision?: number): GoalStorageResult;
18
+ export declare function deleteGoal(projectPath: string, sessionId: string): GoalStorageResult;
19
+ export declare function createGoal(projectPath: string, sessionId: string, objective: string): GoalStorageResult<SessionGoalV1>;
20
+ export declare const GOAL_SIDECAR_SUFFIX = ".goal.json";
21
+ export declare const GOAL_TMP_PREFIX = ".goal.json.tmp-";
22
+ //# sourceMappingURL=goal-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goal-storage.d.ts","sourceRoot":"","sources":["../../src/services/goal-storage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,wBAAwB,CAAC;AAcxE,MAAM,MAAM,iBAAiB,CAAC,CAAC,GAAG,IAAI,IAClC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GACtB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,WAAW,GAAG,gBAAgB,GAAG,SAAS,GAAG,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnG,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,iBAAiB,CAAC,aAAa,CAAC,CA4BjG;AAED,wBAAgB,QAAQ,CACtB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,aAAa,EACnB,gBAAgB,CAAC,EAAE,MAAM,GACxB,iBAAiB,CA0BnB;AAED,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,iBAAiB,CAsBpF;AAED,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,iBAAiB,CAAC,aAAa,CAAC,CAqBtH;AAqBD,eAAO,MAAM,mBAAmB,eAAe,CAAC;AAChD,eAAO,MAAM,eAAe,oBAAoB,CAAC"}