@polpo-ai/core 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.
Files changed (122) hide show
  1. package/LICENSE +21 -0
  2. package/dist/adapter.d.ts +61 -0
  3. package/dist/adapter.d.ts.map +1 -0
  4. package/dist/adapter.js +9 -0
  5. package/dist/adapter.js.map +1 -0
  6. package/dist/agent-manager.d.ts +36 -0
  7. package/dist/agent-manager.d.ts.map +1 -0
  8. package/dist/agent-manager.js +176 -0
  9. package/dist/agent-manager.js.map +1 -0
  10. package/dist/approval-manager.d.ts +49 -0
  11. package/dist/approval-manager.d.ts.map +1 -0
  12. package/dist/approval-manager.js +325 -0
  13. package/dist/approval-manager.js.map +1 -0
  14. package/dist/approval-store.d.ts +19 -0
  15. package/dist/approval-store.d.ts.map +1 -0
  16. package/dist/approval-store.js +2 -0
  17. package/dist/approval-store.js.map +1 -0
  18. package/dist/checkpoint-store.d.ts +20 -0
  19. package/dist/checkpoint-store.d.ts.map +1 -0
  20. package/dist/checkpoint-store.js +2 -0
  21. package/dist/checkpoint-store.js.map +1 -0
  22. package/dist/config-store.d.ts +13 -0
  23. package/dist/config-store.d.ts.map +1 -0
  24. package/dist/config-store.js +2 -0
  25. package/dist/config-store.js.map +1 -0
  26. package/dist/cron.d.ts +29 -0
  27. package/dist/cron.d.ts.map +1 -0
  28. package/dist/cron.js +105 -0
  29. package/dist/cron.js.map +1 -0
  30. package/dist/delay-store.d.ts +21 -0
  31. package/dist/delay-store.d.ts.map +1 -0
  32. package/dist/delay-store.js +2 -0
  33. package/dist/delay-store.js.map +1 -0
  34. package/dist/escalation-manager.d.ts +31 -0
  35. package/dist/escalation-manager.d.ts.map +1 -0
  36. package/dist/escalation-manager.js +281 -0
  37. package/dist/escalation-manager.js.map +1 -0
  38. package/dist/event-bus.d.ts +18 -0
  39. package/dist/event-bus.d.ts.map +1 -0
  40. package/dist/event-bus.js +2 -0
  41. package/dist/event-bus.js.map +1 -0
  42. package/dist/events.d.ts +377 -0
  43. package/dist/events.d.ts.map +1 -0
  44. package/dist/events.js +9 -0
  45. package/dist/events.js.map +1 -0
  46. package/dist/hooks.d.ts +185 -0
  47. package/dist/hooks.d.ts.map +1 -0
  48. package/dist/hooks.js +152 -0
  49. package/dist/hooks.js.map +1 -0
  50. package/dist/index.d.ts +31 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +22 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/log-store.d.ts +31 -0
  55. package/dist/log-store.d.ts.map +1 -0
  56. package/dist/log-store.js +6 -0
  57. package/dist/log-store.js.map +1 -0
  58. package/dist/memory-store.d.ts +17 -0
  59. package/dist/memory-store.d.ts.map +1 -0
  60. package/dist/memory-store.js +2 -0
  61. package/dist/memory-store.js.map +1 -0
  62. package/dist/notification-router-port.d.ts +11 -0
  63. package/dist/notification-router-port.d.ts.map +1 -0
  64. package/dist/notification-router-port.js +2 -0
  65. package/dist/notification-router-port.js.map +1 -0
  66. package/dist/notification-store.d.ts +58 -0
  67. package/dist/notification-store.d.ts.map +1 -0
  68. package/dist/notification-store.js +9 -0
  69. package/dist/notification-store.js.map +1 -0
  70. package/dist/orchestrator-context.d.ts +87 -0
  71. package/dist/orchestrator-context.d.ts.map +1 -0
  72. package/dist/orchestrator-context.js +2 -0
  73. package/dist/orchestrator-context.js.map +1 -0
  74. package/dist/peer-store.d.ts +29 -0
  75. package/dist/peer-store.d.ts.map +1 -0
  76. package/dist/peer-store.js +6 -0
  77. package/dist/peer-store.js.map +1 -0
  78. package/dist/quality-controller.d.ts +46 -0
  79. package/dist/quality-controller.d.ts.map +1 -0
  80. package/dist/quality-controller.js +373 -0
  81. package/dist/quality-controller.js.map +1 -0
  82. package/dist/run-store.d.ts +31 -0
  83. package/dist/run-store.d.ts.map +1 -0
  84. package/dist/run-store.js +2 -0
  85. package/dist/run-store.js.map +1 -0
  86. package/dist/scheduler.d.ts +35 -0
  87. package/dist/scheduler.d.ts.map +1 -0
  88. package/dist/scheduler.js +195 -0
  89. package/dist/scheduler.js.map +1 -0
  90. package/dist/schemas.d.ts +104 -0
  91. package/dist/schemas.d.ts.map +1 -0
  92. package/dist/schemas.js +200 -0
  93. package/dist/schemas.js.map +1 -0
  94. package/dist/session-store.d.ts +50 -0
  95. package/dist/session-store.d.ts.map +1 -0
  96. package/dist/session-store.js +6 -0
  97. package/dist/session-store.js.map +1 -0
  98. package/dist/sla-monitor.d.ts +30 -0
  99. package/dist/sla-monitor.d.ts.map +1 -0
  100. package/dist/sla-monitor.js +156 -0
  101. package/dist/sla-monitor.js.map +1 -0
  102. package/dist/state-machine.d.ts +8 -0
  103. package/dist/state-machine.d.ts.map +1 -0
  104. package/dist/state-machine.js +23 -0
  105. package/dist/state-machine.js.map +1 -0
  106. package/dist/task-manager.d.ts +38 -0
  107. package/dist/task-manager.d.ts.map +1 -0
  108. package/dist/task-manager.js +308 -0
  109. package/dist/task-manager.js.map +1 -0
  110. package/dist/task-store.d.ts +33 -0
  111. package/dist/task-store.d.ts.map +1 -0
  112. package/dist/task-store.js +2 -0
  113. package/dist/task-store.js.map +1 -0
  114. package/dist/task-watcher.d.ts +38 -0
  115. package/dist/task-watcher.d.ts.map +1 -0
  116. package/dist/task-watcher.js +103 -0
  117. package/dist/task-watcher.js.map +1 -0
  118. package/dist/types.d.ts +1073 -0
  119. package/dist/types.d.ts.map +1 -0
  120. package/dist/types.js +35 -0
  121. package/dist/types.js.map +1 -0
  122. package/package.json +170 -0
@@ -0,0 +1,1073 @@
1
+ /** Reasoning level for LLM calls (maps to pi-ai ThinkingLevel). */
2
+ export type ReasoningLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
3
+ export type TaskStatus = "draft" | "pending" | "awaiting_approval" | "assigned" | "in_progress" | "review" | "done" | "failed";
4
+ export interface EvalDimension {
5
+ name: string;
6
+ description: string;
7
+ weight: number;
8
+ rubric?: Record<number, string>;
9
+ }
10
+ export interface DimensionScore {
11
+ dimension: string;
12
+ score: number;
13
+ reasoning: string;
14
+ weight: number;
15
+ evidence?: {
16
+ file: string;
17
+ line: number;
18
+ note: string;
19
+ }[];
20
+ }
21
+ export interface TaskExpectation {
22
+ type: "test" | "file_exists" | "script" | "llm_review";
23
+ command?: string;
24
+ paths?: string[];
25
+ criteria?: string;
26
+ /** For llm_review: evaluation dimensions with weights and rubrics */
27
+ dimensions?: EvalDimension[];
28
+ /** For llm_review: minimum weighted score (1-5) to pass. Default 3.0 */
29
+ threshold?: number;
30
+ /** Whether this expectation is a firm requirement or an estimate that can be auto-corrected.
31
+ * Default: "estimated" for file_exists, "firm" for test/script/llm_review. */
32
+ confidence?: "firm" | "estimated";
33
+ }
34
+ export interface TaskMetric {
35
+ name: string;
36
+ command: string;
37
+ threshold: number;
38
+ }
39
+ export interface RetryPolicy {
40
+ /** After this many failures, escalate to fallbackAgent */
41
+ escalateAfter?: number;
42
+ /** Agent to use for escalation retries */
43
+ fallbackAgent?: string;
44
+ /** Model override for escalation (e.g. switch from haiku to sonnet) */
45
+ escalateModel?: string;
46
+ }
47
+ export type TaskPhase = "execution" | "review" | "fix" | "clarification";
48
+ /** What type of artifact a task can produce. */
49
+ export type OutcomeType = "file" | "text" | "url" | "json" | "media";
50
+ /**
51
+ * A concrete artifact produced by a task at runtime.
52
+ * Populated automatically by tool interception and/or explicitly by agent output.
53
+ */
54
+ export interface TaskOutcome {
55
+ /** Unique outcome ID (nanoid). */
56
+ id: string;
57
+ /** Outcome category. */
58
+ type: OutcomeType;
59
+ /** Human-readable label (e.g. "Sales Report", "Transcription", "Generated Audio"). */
60
+ label: string;
61
+ /** file/media: relative or absolute path to the produced file. */
62
+ path?: string;
63
+ /** file/media: MIME type (auto-detected from extension or explicit). */
64
+ mimeType?: string;
65
+ /** file/media: file size in bytes. */
66
+ size?: number;
67
+ /** text: the content itself (transcription, summary, analysis, etc.). */
68
+ text?: string;
69
+ /** url: link to external resource (deploy URL, PR, page, etc.). */
70
+ url?: string;
71
+ /** json: structured data payload (query results, metrics, report, etc.). */
72
+ data?: unknown;
73
+ /** Tool name that generated this outcome (auto-collected). */
74
+ producedBy?: string;
75
+ /** ISO timestamp when the outcome was created. */
76
+ producedAt: string;
77
+ /** User-defined tags for filtering and categorization. */
78
+ tags?: string[];
79
+ }
80
+ /**
81
+ * Declared in task/mission definitions — tells the agent what it should produce.
82
+ * Used for validation: the orchestrator checks that expected outcomes are fulfilled.
83
+ */
84
+ export interface ExpectedOutcome {
85
+ /** Expected outcome type. */
86
+ type: OutcomeType;
87
+ /** Human-readable label — also used to match against produced TaskOutcome.label. */
88
+ label: string;
89
+ /** Hints for the agent about what to produce. */
90
+ description?: string;
91
+ /** Expected file path (optional — agent can choose). */
92
+ path?: string;
93
+ /** Expected MIME type (e.g. "audio/mpeg", "application/pdf"). */
94
+ mimeType?: string;
95
+ /** Whether this outcome is required for the task to pass. Default: true. */
96
+ required?: boolean;
97
+ /** Tags to auto-apply to the produced outcome. */
98
+ tags?: string[];
99
+ }
100
+ export interface Task {
101
+ id: string;
102
+ title: string;
103
+ description: string;
104
+ assignTo: string;
105
+ group?: string;
106
+ /** ID of the mission this task belongs to (set when created via executeMission). */
107
+ missionId?: string;
108
+ dependsOn: string[];
109
+ status: TaskStatus;
110
+ expectations: TaskExpectation[];
111
+ metrics: TaskMetric[];
112
+ retries: number;
113
+ maxRetries: number;
114
+ maxDuration?: number;
115
+ retryPolicy?: RetryPolicy;
116
+ result?: TaskResult;
117
+ phase?: TaskPhase;
118
+ fixAttempts?: number;
119
+ questionRounds?: number;
120
+ resolutionAttempts?: number;
121
+ originalDescription?: string;
122
+ sessionId?: string;
123
+ /** Absolute deadline (ISO timestamp). Task is SLA-violated if not done by this time. */
124
+ deadline?: string;
125
+ /** Priority weight for quality scoring (higher = more important). Default: 1.0 */
126
+ priority?: number;
127
+ /** Declared expected outcomes — what this task should produce. */
128
+ expectedOutcomes?: ExpectedOutcome[];
129
+ /** Actual outcomes produced at runtime (auto-collected + explicit). */
130
+ outcomes?: TaskOutcome[];
131
+ /** Number of approval revision rounds this task has gone through. */
132
+ revisionCount?: number;
133
+ /** Scoped notification rules — override or extend global/mission rules for this task. */
134
+ notifications?: ScopedNotificationRules;
135
+ /**
136
+ * Whether this task produces irreversible side effects (email sends, API calls,
137
+ * WhatsApp messages, etc.). When true, automatic retry/fix is blocked and the
138
+ * task transitions to `awaiting_approval` so a human can approve re-execution.
139
+ * Set by the orchestrator LLM when creating/planning tasks.
140
+ */
141
+ sideEffects?: boolean;
142
+ createdAt: string;
143
+ updatedAt: string;
144
+ }
145
+ export interface TaskResult {
146
+ exitCode: number;
147
+ stdout: string;
148
+ stderr: string;
149
+ duration: number;
150
+ assessment?: AssessmentResult;
151
+ /** All previous assessments (oldest first). Current assessment is always in `assessment`. */
152
+ assessmentHistory?: AssessmentResult[];
153
+ }
154
+ /** Agent identity — who this agent is and how it behaves */
155
+ /** A structured responsibility area */
156
+ export interface AgentResponsibility {
157
+ /** Responsibility area (e.g. "Customer Relations", "Content Creation") */
158
+ area: string;
159
+ /** What the agent does in this area */
160
+ description: string;
161
+ /** Priority level — affects how the agent prioritizes competing tasks */
162
+ priority?: "critical" | "high" | "medium" | "low";
163
+ }
164
+ export interface AgentIdentity {
165
+ displayName?: string;
166
+ title?: string;
167
+ company?: string;
168
+ email?: string;
169
+ bio?: string;
170
+ timezone?: string;
171
+ /** Avatar image path relative to project root (e.g. ".polpo/avatars/alice.png").
172
+ * Served via GET /api/v1/files/read?path=<avatar> */
173
+ avatar?: string;
174
+ /** Responsibilities — simple strings or structured objects with area/description/priority.
175
+ * Structured format is preferred for clarity. */
176
+ responsibilities?: (string | AgentResponsibility)[];
177
+ /** Communication tone — HOW the agent communicates.
178
+ * Examples: "Professional but warm", "Concise and data-driven", "Casual and friendly" */
179
+ tone?: string;
180
+ /** Personality traits — WHO the agent IS as a persona.
181
+ * Examples: "Detail-oriented and empathetic", "Creative problem-solver" */
182
+ personality?: string;
183
+ /** Social & web accounts — free-form key-value.
184
+ * Keys are platform names, values are handles/URLs.
185
+ * Examples: { x: "@alice", linkedin: "linkedin.com/in/alice", github: "alice", website: "https://alice.dev" } */
186
+ socials?: Record<string, string>;
187
+ }
188
+ /** Vault credential entry */
189
+ export interface VaultEntry {
190
+ /** Service type for semantic meaning */
191
+ type: "smtp" | "imap" | "oauth" | "api_key" | "login" | "custom";
192
+ /** Human-readable label */
193
+ label?: string;
194
+ /** Credential fields — values can be literals or ${ENV_VAR} references */
195
+ credentials: Record<string, string>;
196
+ }
197
+ export interface AgentConfig {
198
+ name: string;
199
+ /** ISO timestamp of when this agent was created / added to the team. Auto-set by addAgent(). */
200
+ createdAt?: string;
201
+ role?: string;
202
+ /** Model to use. Format: "provider:model" (e.g. "anthropic:claude-sonnet-4-5-20250929") or bare model ID (auto-inferred). */
203
+ model?: string;
204
+ /** Allowed tools for the agent (e.g. ["read", "write", "edit", "bash", "glob", "grep", "browser_*", "email_*", "image_*", "video_*", "audio_*", "excel_*", "pdf_*", "docx_*"]).
205
+ * Core tools (always available): read, write, edit, bash, glob, grep, ls, http_fetch, http_download, register_outcome, vault_get, vault_list. */
206
+ allowedTools?: string[];
207
+ /** Filesystem sandbox — directories the agent is allowed to access.
208
+ * Paths can be absolute or relative to workDir. When set, all file tool operations
209
+ * and bash cwd are validated against these paths. When omitted, defaults to [workDir]. */
210
+ allowedPaths?: string[];
211
+ /** Agent's identity — persona, responsibilities, communication style */
212
+ identity?: AgentIdentity;
213
+ /** Agent this one reports to — org chart hierarchy for escalation.
214
+ * When a task fails or needs a decision, escalates up the chain. */
215
+ reportsTo?: string;
216
+ /** System prompt appended to the agent's base prompt */
217
+ systemPrompt?: string;
218
+ /** Installed skill names (e.g. "find-skills", "frontend-design") */
219
+ skills?: string[];
220
+ /** Max conversation turns before stopping. Default 150 */
221
+ maxTurns?: number;
222
+ /** Max concurrent tasks for this agent. Default: unlimited (undefined). */
223
+ maxConcurrency?: number;
224
+ /** Reasoning / deep thinking level for this agent's LLM calls.
225
+ * "off" disables thinking (default). Higher levels = more reasoning tokens = better quality but slower + more expensive.
226
+ * Falls back to the global `settings.reasoning` when not set. */
227
+ reasoning?: ReasoningLevel;
228
+ /** Volatile agent — created for a specific mission, auto-removed when mission completes */
229
+ volatile?: boolean;
230
+ /** Mission group this volatile agent belongs to */
231
+ missionGroup?: string;
232
+ /** Browser profile name for persistent context (cookies, auth, localStorage).
233
+ * Defaults to agent name. Used with agent-browser's --profile flag.
234
+ * Profiles stored in .polpo/browser-profiles/<name>/. */
235
+ browserProfile?: string;
236
+ /** Allowed recipient email domains for email_send (e.g. ["acme.com", "partner.io"]).
237
+ * When set, emails can only be sent to addresses in these domains.
238
+ * When omitted, all domains are allowed (backwards compatible). */
239
+ emailAllowedDomains?: string[];
240
+ /** Semantic version (e.g. "1.0.0"). Used by Ink registry for package identification. */
241
+ version?: string;
242
+ /** Author name or "Name <email>" string. */
243
+ author?: string;
244
+ /** Searchable tags for registry discovery (e.g. ["frontend", "react", "testing"]). */
245
+ tags?: string[];
246
+ }
247
+ export interface AgentActivity {
248
+ lastTool?: string;
249
+ lastFile?: string;
250
+ filesCreated: string[];
251
+ filesEdited: string[];
252
+ toolCalls: number;
253
+ totalTokens: number;
254
+ lastUpdate: string;
255
+ summary?: string;
256
+ sessionId?: string;
257
+ }
258
+ export interface AgentProcess {
259
+ agentName: string;
260
+ pid: number;
261
+ taskId: string;
262
+ startedAt: string;
263
+ alive: boolean;
264
+ activity: AgentActivity;
265
+ }
266
+ export interface Team {
267
+ name: string;
268
+ description?: string;
269
+ agents: AgentConfig[];
270
+ }
271
+ /** Serializable representation of a single message in the reviewer's conversation */
272
+ export interface ReviewerMessage {
273
+ role: "user" | "assistant" | "toolResult";
274
+ /** For user/assistant: text content. For toolResult: the tool output text. */
275
+ content: string;
276
+ /** Tool calls made by the assistant (if role === "assistant") */
277
+ toolCalls?: {
278
+ id: string;
279
+ name: string;
280
+ arguments: Record<string, unknown>;
281
+ }[];
282
+ /** For toolResult messages */
283
+ toolCallId?: string;
284
+ toolName?: string;
285
+ isError?: boolean;
286
+ timestamp: number;
287
+ }
288
+ /** Phase 1 exploration trace from a single reviewer */
289
+ export interface ReviewerExploration {
290
+ /** Full analysis text produced by the reviewer during exploration */
291
+ analysis: string;
292
+ /** Files read by the reviewer during exploration */
293
+ filesRead: string[];
294
+ /** Complete conversation (user prompts, assistant responses, tool calls & results) */
295
+ messages: ReviewerMessage[];
296
+ }
297
+ /** Individual reviewer result from llm_review multi-evaluator consensus */
298
+ export interface ReviewerResult {
299
+ /** Reviewer index (1-based) */
300
+ index: number;
301
+ /** Per-dimension scores from this reviewer */
302
+ scores: {
303
+ dimension: string;
304
+ score: number;
305
+ reasoning: string;
306
+ evidence?: {
307
+ file: string;
308
+ line: number;
309
+ note: string;
310
+ }[];
311
+ }[];
312
+ /** Reviewer's summary */
313
+ summary: string;
314
+ /** Weighted average score for this reviewer */
315
+ globalScore: number;
316
+ /** Phase 1 exploration trace (analysis, files read, full conversation) */
317
+ exploration?: ReviewerExploration;
318
+ /** Errors from scoring strategy attempts (Phase 2 fallback chain) */
319
+ scoringAttemptErrors?: string[];
320
+ }
321
+ export interface CheckResult {
322
+ type: TaskExpectation["type"];
323
+ passed: boolean;
324
+ message: string;
325
+ details?: string;
326
+ /** Per-dimension scores from llm_review (consensus/median) */
327
+ scores?: DimensionScore[];
328
+ /** Weighted average score (1-5) from llm_review */
329
+ globalScore?: number;
330
+ /** Individual reviewer results (llm_review only) — shows how each reviewer voted */
331
+ reviewers?: ReviewerResult[];
332
+ }
333
+ export interface MetricResult {
334
+ name: string;
335
+ value: number;
336
+ threshold: number;
337
+ passed: boolean;
338
+ }
339
+ export type AssessmentTrigger = "initial" | "reassess" | "fix" | "retry" | "auto-correct" | "judge";
340
+ export interface AssessmentResult {
341
+ passed: boolean;
342
+ checks: CheckResult[];
343
+ metrics: MetricResult[];
344
+ llmReview?: string;
345
+ scores?: DimensionScore[];
346
+ globalScore?: number;
347
+ timestamp: string;
348
+ /** What triggered this assessment. Defaults to "initial" for backwards compatibility. */
349
+ trigger?: AssessmentTrigger;
350
+ }
351
+ /**
352
+ * Replace the current assessment on a TaskResult, archiving the old one in assessmentHistory.
353
+ * Also tags the new assessment with the given trigger.
354
+ */
355
+ export declare function setAssessment(result: TaskResult, assessment: AssessmentResult, trigger: AssessmentTrigger): void;
356
+ export interface ReviewContext {
357
+ taskTitle: string;
358
+ taskDescription: string;
359
+ /** Last assistant message from the agent conversation. */
360
+ agentOutput?: string;
361
+ /** Agent stderr (errors, warnings). */
362
+ agentStderr?: string;
363
+ /** Agent exit code. */
364
+ exitCode?: number;
365
+ /** Agent execution duration in ms. */
366
+ duration?: number;
367
+ filesCreated?: string[];
368
+ filesEdited?: string[];
369
+ /** Total tool calls made by the agent. */
370
+ toolCalls?: number;
371
+ /** Summary of tools used (name → count). */
372
+ toolsSummary?: string;
373
+ /**
374
+ * Structured execution timeline built from the JSONL activity log.
375
+ * Shows what the agent did step-by-step: tool calls, text messages, outcomes.
376
+ * This is the primary evidence for reviewing non-file-based tasks.
377
+ */
378
+ executionSummary?: string;
379
+ /** Explicit outcomes registered by the agent (files, text, URLs, JSON data). */
380
+ outcomes?: TaskOutcome[];
381
+ }
382
+ export interface AskUserOption {
383
+ label: string;
384
+ description?: string;
385
+ }
386
+ export interface AskUserQuestion {
387
+ /** Unique question key for matching answers (e.g. "auth-method") */
388
+ id: string;
389
+ /** The question text */
390
+ question: string;
391
+ /** Short label for compact display (max 30 chars) */
392
+ header?: string;
393
+ /** Pre-populated selectable options */
394
+ options: AskUserOption[];
395
+ /** Allow selecting multiple options (default: false) */
396
+ multiple?: boolean;
397
+ /** Whether to add a "Type your own answer" custom input (default: true) */
398
+ custom?: boolean;
399
+ }
400
+ export interface AskUserAnswer {
401
+ questionId: string;
402
+ /** Labels of selected options */
403
+ selected: string[];
404
+ /** Custom text typed by user (if custom input was used) */
405
+ customText?: string;
406
+ }
407
+ export interface AskUserRequest {
408
+ questions: AskUserQuestion[];
409
+ }
410
+ export type MissionStatus = "draft" | "scheduled" | "recurring" | "active" | "paused" | "completed" | "failed" | "cancelled";
411
+ export interface Mission {
412
+ id: string;
413
+ name: string;
414
+ data: string;
415
+ prompt?: string;
416
+ status: MissionStatus;
417
+ /** Absolute deadline for the entire mission (ISO timestamp). */
418
+ deadline?: string;
419
+ /** Cron expression or ISO timestamp for scheduled execution. */
420
+ schedule?: string;
421
+ /** End date for recurring schedules (ISO timestamp). After this date the schedule stops firing and the mission transitions to completed. */
422
+ endDate?: string;
423
+ /** Minimum average score for the mission to be considered successful. */
424
+ qualityThreshold?: number;
425
+ /** Scoped notification rules — override or extend global rules for tasks in this mission. */
426
+ notifications?: ScopedNotificationRules;
427
+ /** How many times this mission has been executed. Incremented on each run (useful for recurring missions). */
428
+ executionCount?: number;
429
+ createdAt: string;
430
+ updatedAt: string;
431
+ }
432
+ /** Completion report for a mission — aggregated results across all tasks. */
433
+ export interface MissionReport {
434
+ missionId: string;
435
+ group: string;
436
+ allPassed: boolean;
437
+ totalDuration: number;
438
+ tasks: {
439
+ title: string;
440
+ status: "done" | "failed";
441
+ duration: number;
442
+ score?: number;
443
+ filesCreated: string[];
444
+ filesEdited: string[];
445
+ outcomes?: TaskOutcome[];
446
+ }[];
447
+ filesCreated: string[];
448
+ filesEdited: string[];
449
+ outcomes?: TaskOutcome[];
450
+ avgScore?: number;
451
+ }
452
+ export interface RunnerConfig {
453
+ runId: string;
454
+ taskId: string;
455
+ agent: AgentConfig;
456
+ task: Task;
457
+ polpoDir: string;
458
+ cwd: string;
459
+ /** Per-task output directory (.polpo/output/<taskId>/). Agents should write deliverables here. */
460
+ outputDir: string;
461
+ storage?: "file" | "sqlite" | "postgres";
462
+ /** PostgreSQL connection URL (for storage: "postgres"). */
463
+ databaseUrl?: string;
464
+ /** UDS path for push-notifying the orchestrator on completion. */
465
+ notifySocket?: string;
466
+ /** Email domain allowlist (from settings or agent config). */
467
+ emailAllowedDomains?: string[];
468
+ /** Global reasoning level from settings — used as fallback for agents that don't specify one. */
469
+ reasoning?: ReasoningLevel;
470
+ /** WhatsApp message DB path (for whatsapp_* agent tools). */
471
+ whatsappDbPath?: string;
472
+ /** WhatsApp Baileys profile path (for whatsapp_send — creates a temporary connection). */
473
+ whatsappProfilePath?: string;
474
+ }
475
+ export interface PolpoFileConfig {
476
+ project: string;
477
+ /** Multiple teams — each with its own agents.
478
+ * @since 0.2 — replaces the old singular `team` field. */
479
+ teams: Team[];
480
+ settings: PolpoSettings;
481
+ providers?: Record<string, ProviderConfig>;
482
+ /** Semantic version (e.g. "1.0.0"). Used by Ink registry for company package identification. */
483
+ version?: string;
484
+ /** Author name or "Name <email>" string. */
485
+ author?: string;
486
+ /** Searchable tags for registry discovery (e.g. ["saas", "startup", "fullstack"]). */
487
+ tags?: string[];
488
+ }
489
+ /** Shape that parseConfig() accepts from disk — supports both old `team` and new `teams`. */
490
+ export interface PolpoFileConfigRaw {
491
+ project: string;
492
+ /** @deprecated Use `teams` instead. Kept for backward-compatible migration. */
493
+ team?: Team;
494
+ teams?: Team[];
495
+ settings?: Partial<PolpoSettings>;
496
+ providers?: Record<string, ProviderConfig>;
497
+ }
498
+ export interface ProviderConfig {
499
+ /** API key (direct value or "${ENV_VAR}" reference). */
500
+ apiKey?: string;
501
+ /** Override base URL for the provider (e.g. custom proxy, Ollama, vLLM). */
502
+ baseUrl?: string;
503
+ /** API compatibility mode for custom endpoints. */
504
+ api?: "openai-completions" | "openai-responses" | "anthropic-messages";
505
+ /** Custom model definitions for this provider (used with custom endpoints). */
506
+ models?: CustomModelDef[];
507
+ }
508
+ /** Custom model definition for non-catalog providers (Ollama, vLLM, LM Studio, etc.) */
509
+ export interface CustomModelDef {
510
+ /** Model ID used in API calls. */
511
+ id: string;
512
+ /** Human-readable name. */
513
+ name: string;
514
+ /** Whether the model supports extended thinking / reasoning. */
515
+ reasoning?: boolean;
516
+ /** Supported input types. Default: ["text"] */
517
+ input?: ("text" | "image")[];
518
+ /** Cost per million tokens. Default: all zeros (free/local). */
519
+ cost?: {
520
+ input: number;
521
+ output: number;
522
+ cacheRead: number;
523
+ cacheWrite: number;
524
+ };
525
+ /** Context window size in tokens. Default: 200000 */
526
+ contextWindow?: number;
527
+ /** Max output tokens. Default: 8192 */
528
+ maxTokens?: number;
529
+ }
530
+ export interface ModelConfig {
531
+ /** Primary model spec (e.g. "anthropic:claude-opus-4-6"). */
532
+ primary?: string;
533
+ /** Ordered fallback models — tried when primary fails. */
534
+ fallbacks?: string[];
535
+ }
536
+ /** Model allowlist entry with optional alias. */
537
+ export interface ModelAllowlistEntry {
538
+ /** Display alias for this model (e.g. "Sonnet", "GPT"). */
539
+ alias?: string;
540
+ /** Per-model parameter overrides. */
541
+ params?: Record<string, unknown>;
542
+ }
543
+ export interface PolpoConfig {
544
+ version: string;
545
+ project: string;
546
+ teams: Team[];
547
+ tasks: Omit<Task, "status" | "retries" | "result" | "createdAt" | "updatedAt">[];
548
+ settings: PolpoSettings;
549
+ /** Per-provider API key and base URL overrides. */
550
+ providers?: Record<string, ProviderConfig>;
551
+ }
552
+ export interface PolpoSettings {
553
+ maxRetries: number;
554
+ workDir: string;
555
+ logLevel: "quiet" | "normal" | "verbose";
556
+ taskTimeout?: number;
557
+ staleThreshold?: number;
558
+ defaultRetryPolicy?: RetryPolicy;
559
+ /** Whether missions can define volatile agents in their team: section. Default: true */
560
+ enableVolatileTeams?: boolean;
561
+ /** When to clean up volatile agents: "on_complete" (default) removes them when the mission
562
+ * finishes, "manual" keeps them until the user explicitly removes them or the mission is deleted */
563
+ volatileCleanup?: "on_complete" | "manual";
564
+ /** Max fix attempts per review cycle before falling back to full retry. Default: 2 */
565
+ maxFixAttempts?: number;
566
+ /** Max auto-answer rounds per task when agent asks questions. Default: 2 */
567
+ maxQuestionRounds?: number;
568
+ /** Max deadlock resolution attempts per task. Default: 2 */
569
+ maxResolutionAttempts?: number;
570
+ /** Auto-correct correctable expectations (e.g. file_exists paths) on assessment failure. Default: true */
571
+ autoCorrectExpectations?: boolean;
572
+ /** Skills to load into the orchestrator's system prompt.
573
+ * Skill names are resolved against the pool (project + global). */
574
+ orchestratorSkills?: string[];
575
+ /** Model for orchestrator LLM calls (question detection, deadlock, missions).
576
+ * Can be a simple string ("anthropic:claude-opus-4-6") or a ModelConfig with fallbacks. */
577
+ orchestratorModel?: string | ModelConfig;
578
+ /** Image-capable model for tasks that need vision (falls back to orchestratorModel). */
579
+ imageModel?: string;
580
+ /** Model allowlist — when set, only these models can be used.
581
+ * Keys are model specs (e.g. "anthropic:claude-opus-4-6"), values are aliases/params. */
582
+ modelAllowlist?: Record<string, ModelAllowlistEntry>;
583
+ /** Global reasoning / deep thinking level for orchestrator LLM calls (chat, plan generation, assessment).
584
+ * "off" disables thinking (default). Can be overridden per-agent via AgentConfig.reasoning.
585
+ * Higher levels produce better results but are slower and more expensive. */
586
+ reasoning?: ReasoningLevel;
587
+ /** Storage backend for tasks, missions, and runs. Default: "file" (filesystem JSON).
588
+ * "postgres" requires @polpo-ai/drizzle and a databaseUrl. */
589
+ storage?: "file" | "sqlite" | "postgres";
590
+ /** PostgreSQL connection URL (required when storage is "postgres").
591
+ * Example: "postgres://user:pass@localhost:5432/polpo" */
592
+ databaseUrl?: string;
593
+ /** Max assessment retries when all reviewers fail before falling back to fix/retry. Default: 1 */
594
+ maxAssessmentRetries?: number;
595
+ /** Max concurrent agent processes. Default: unlimited (undefined). */
596
+ maxConcurrency?: number;
597
+ /** Approval gates — checkpoints that block task/mission execution until approved. */
598
+ approvalGates?: ApprovalGate[];
599
+ /** Notification system — routes events to external channels (Slack, email, Telegram). */
600
+ notifications?: NotificationsConfig;
601
+ /** Default escalation policy — defines escalation chain when tasks fail repeatedly. */
602
+ escalationPolicy?: EscalationPolicy;
603
+ /** SLA monitoring configuration. */
604
+ sla?: SLAConfig;
605
+ /** Enable the scheduling engine. Default: true if any mission has a schedule. */
606
+ enableScheduler?: boolean;
607
+ /** Default quality threshold for missions (1-5). Missions below this score are marked failed. */
608
+ defaultQualityThreshold?: number;
609
+ /** Allowed recipient email domains — applies to all agents (can be overridden per-agent). */
610
+ emailAllowedDomains?: string[];
611
+ }
612
+ export interface PolpoState {
613
+ project: string;
614
+ teams: Team[];
615
+ tasks: Task[];
616
+ processes: AgentProcess[];
617
+ startedAt?: string;
618
+ completedAt?: string;
619
+ }
620
+ /** Get all agents across all teams (flattened). */
621
+ export declare function getAllAgents(teams: Team[]): AgentConfig[];
622
+ /** Find a specific agent by name across all teams. */
623
+ export declare function findAgent(teams: Team[], agentName: string): AgentConfig | undefined;
624
+ /** Find the team an agent belongs to. */
625
+ export declare function findAgentTeam(teams: Team[], agentName: string): Team | undefined;
626
+ /** Legacy project config stored in config.json */
627
+ export interface ProjectConfig {
628
+ project: string;
629
+ judge?: string;
630
+ agent?: string;
631
+ model?: string;
632
+ }
633
+ export type ApprovalGateHandler = "auto" | "human";
634
+ export interface ApprovalGateCondition {
635
+ /** JS-like expression evaluated against the hook payload.
636
+ * For "auto" gates — if condition passes, task proceeds. If it fails, task is blocked.
637
+ * For "human" gates — condition determines WHEN to trigger the gate. */
638
+ expression: string;
639
+ }
640
+ export interface ApprovalGate {
641
+ /** Unique gate ID. */
642
+ id: string;
643
+ /** Human-readable name. */
644
+ name: string;
645
+ /** "auto" = system evaluates condition. "human" = blocks for human approval. */
646
+ handler: ApprovalGateHandler;
647
+ /** Which lifecycle hook triggers this gate. */
648
+ hook: string;
649
+ /** Optional condition — when to activate the gate. */
650
+ condition?: ApprovalGateCondition;
651
+ /** Notification channels to alert on gate activation (for "human" gates). */
652
+ notifyChannels?: string[];
653
+ /** Timeout in ms (for "human" gates). 0 = no timeout. */
654
+ timeoutMs?: number;
655
+ /** Action when timeout expires. Default: "reject". */
656
+ timeoutAction?: "approve" | "reject";
657
+ /** Priority within the same hook point. Lower = first. Default: 100. */
658
+ priority?: number;
659
+ /** Max revision rounds before only approve/reject is allowed. Default: 3. */
660
+ maxRevisions?: number;
661
+ /** Include task outcomes as attachments in the approval notification. */
662
+ includeOutcomes?: boolean;
663
+ }
664
+ export type ApprovalStatus = "pending" | "approved" | "rejected" | "timeout";
665
+ export interface ApprovalRequest {
666
+ /** Unique request ID. */
667
+ id: string;
668
+ /** Gate that triggered this request. */
669
+ gateId: string;
670
+ /** Gate name (denormalized for display). */
671
+ gateName: string;
672
+ /** Related task ID, if applicable. */
673
+ taskId?: string;
674
+ /** Related mission ID, if applicable. */
675
+ missionId?: string;
676
+ /** Current status. */
677
+ status: ApprovalStatus;
678
+ /** Hook payload snapshot at time of request. */
679
+ payload: unknown;
680
+ /** When the request was created. */
681
+ requestedAt: string;
682
+ /** When the request was resolved (approved/rejected/timeout). */
683
+ resolvedAt?: string;
684
+ /** Who resolved it (user ID, "system", "timeout"). */
685
+ resolvedBy?: string;
686
+ /** Optional resolution note. */
687
+ note?: string;
688
+ }
689
+ /** Supported messaging channel types for inbound message routing. */
690
+ export type ChannelType = "telegram" | "whatsapp" | "slack" | "discord" | "webchat";
691
+ /**
692
+ * Peer identity — represents a person talking to the bot from a messaging channel.
693
+ * Inspired by OpenClaw's session key model but adapted for orchestrator use-cases.
694
+ *
695
+ * A peer is identified by their channel-specific ID (e.g., Telegram chatId, WhatsApp phone).
696
+ * Identity links allow the same person on multiple channels to share a session.
697
+ */
698
+ export interface PeerIdentity {
699
+ /** Canonical peer ID (format: "channel:externalId", e.g. "telegram:123456789"). */
700
+ id: string;
701
+ /** Channel type. */
702
+ channel: ChannelType;
703
+ /** Channel-specific external ID (chatId, phone number, user ID, etc.). */
704
+ externalId: string;
705
+ /** Display name (from channel profile, if available). */
706
+ displayName?: string;
707
+ /** When this peer was first seen. */
708
+ firstSeenAt: string;
709
+ /** When this peer last sent a message. */
710
+ lastSeenAt: string;
711
+ /** Linked canonical identity — allows cross-channel session sharing.
712
+ * If set, this peer shares sessions with the peer identified by this ID. */
713
+ linkedTo?: string;
714
+ }
715
+ /**
716
+ * DM access policy — controls who can message the bot.
717
+ * Modeled after OpenClaw's 4-tier DM security model.
718
+ */
719
+ export type DmPolicy = "pairing" | "allowlist" | "open" | "disabled";
720
+ /** Pairing request — pending approval for a new peer to talk to the bot. */
721
+ export interface PairingRequest {
722
+ /** Unique request ID. */
723
+ id: string;
724
+ /** Peer requesting access. */
725
+ peerId: string;
726
+ /** Channel type. */
727
+ channel: ChannelType;
728
+ /** Channel-specific external ID. */
729
+ externalId: string;
730
+ /** Display name of the requester. */
731
+ displayName?: string;
732
+ /** Short pairing code sent to the user. */
733
+ code: string;
734
+ /** When the request was created. */
735
+ createdAt: string;
736
+ /** When the request expires (1 hour from creation). */
737
+ expiresAt: string;
738
+ /** Whether the request has been resolved. */
739
+ resolved: boolean;
740
+ }
741
+ /**
742
+ * Channel gateway configuration — extends notification channel config
743
+ * with inbound message handling settings.
744
+ */
745
+ export interface ChannelGatewayConfig {
746
+ /** DM access policy. Default: "allowlist". */
747
+ dmPolicy?: DmPolicy;
748
+ /** Allowlist of external IDs that can message the bot.
749
+ * Use "*" to allow all (only with dmPolicy="open"). */
750
+ allowFrom?: string[];
751
+ /** Enable inbound message routing (chat with orchestrator). Default: false. */
752
+ enableInbound?: boolean;
753
+ /** Session idle timeout in minutes before creating a new session. Default: 60. */
754
+ sessionIdleMinutes?: number;
755
+ }
756
+ /**
757
+ * Presence entry — lightweight, ephemeral tracking of connected peers.
758
+ * Inspired by OpenClaw's in-memory presence with TTL.
759
+ */
760
+ export interface PresenceEntry {
761
+ /** Peer ID (format: "channel:externalId"). */
762
+ peerId: string;
763
+ /** Display name. */
764
+ displayName?: string;
765
+ /** Channel type. */
766
+ channel: ChannelType;
767
+ /** Last activity timestamp (ISO). */
768
+ lastActivityAt: string;
769
+ /** What the peer is doing ("idle" | "chatting" | "approving"). */
770
+ activity: "idle" | "chatting" | "approving";
771
+ }
772
+ export type NotificationChannelType = "slack" | "email" | "telegram" | "whatsapp" | "webhook";
773
+ export interface NotificationChannelConfig {
774
+ type: NotificationChannelType;
775
+ /** Slack: webhook URL. */
776
+ webhookUrl?: string;
777
+ /** Email: recipient addresses. */
778
+ to?: string[];
779
+ /** Email: provider ("smtp" | "resend" | "sendgrid"). */
780
+ provider?: string;
781
+ /** API key (direct value or "${ENV_VAR}" reference). */
782
+ apiKey?: string;
783
+ /** Telegram: bot token. */
784
+ botToken?: string;
785
+ /** Telegram: chat ID. */
786
+ chatId?: string;
787
+ /** WhatsApp: credentials directory path (relative to .polpo/). Defaults to "whatsapp-profiles/default". */
788
+ profileDir?: string;
789
+ /** Webhook: target URL. */
790
+ url?: string;
791
+ /** Webhook: custom headers. */
792
+ headers?: Record<string, string>;
793
+ /** SMTP host. */
794
+ host?: string;
795
+ /** SMTP port. */
796
+ port?: number;
797
+ /** SMTP from address. */
798
+ from?: string;
799
+ /** Channel gateway config — enables inbound message routing for this channel. */
800
+ gateway?: ChannelGatewayConfig;
801
+ }
802
+ export type NotificationSeverity = "info" | "warning" | "critical";
803
+ /**
804
+ * JSON-based condition for notification rule filtering.
805
+ *
806
+ * Supports:
807
+ * - Single comparison: { "field": "status", "op": "==", "value": "failed" }
808
+ * - Logical AND: { "and": [ ...conditions ] }
809
+ * - Logical OR: { "or": [ ...conditions ] }
810
+ * - Logical NOT: { "not": condition }
811
+ * - Inclusion: { "field": "tags", "op": "includes", "value": "urgent" }
812
+ * - Existence: { "field": "error", "op": "exists" }
813
+ *
814
+ * Fields are dot-paths resolved on the event data (e.g. "task.status", "score").
815
+ */
816
+ export type ConditionOp = "==" | "!=" | ">" | ">=" | "<" | "<=" | "includes" | "not_includes" | "exists" | "not_exists";
817
+ export interface ConditionExpr {
818
+ field: string;
819
+ op: ConditionOp;
820
+ value?: string | number | boolean | null;
821
+ }
822
+ export interface ConditionAnd {
823
+ and: NotificationCondition[];
824
+ }
825
+ export interface ConditionOr {
826
+ or: NotificationCondition[];
827
+ }
828
+ export interface ConditionNot {
829
+ not: NotificationCondition;
830
+ }
831
+ export type NotificationCondition = ConditionExpr | ConditionAnd | ConditionOr | ConditionNot;
832
+ export interface NotificationRule {
833
+ /** Unique rule ID. */
834
+ id: string;
835
+ /** Human-readable name. */
836
+ name: string;
837
+ /** Event patterns to match (glob-style: "task:*", "mission:completed"). */
838
+ events: string[];
839
+ /** Optional JSON condition on the event payload. No eval — pure data. */
840
+ condition?: NotificationCondition;
841
+ /** Channels to notify (references to channel IDs in config). */
842
+ channels: string[];
843
+ /** Severity level. Default: "info". */
844
+ severity?: NotificationSeverity;
845
+ /** Mustache-style template for the notification body. */
846
+ template?: string;
847
+ /** Minimum interval between notifications for the same rule (ms). */
848
+ cooldownMs?: number;
849
+ /** Attach task outcomes to the notification (files sent as attachments). Default: false. */
850
+ includeOutcomes?: boolean;
851
+ /** Only include outcomes of these types. When omitted, all types are included. */
852
+ outcomeFilter?: OutcomeType[];
853
+ /** Max file size per attachment in bytes. Files larger than this are skipped. Default: 10MB. */
854
+ maxAttachmentSize?: number;
855
+ /** Action triggers — executed when the rule fires, in addition to sending notifications. */
856
+ actions?: NotificationAction[];
857
+ }
858
+ /** Action types that can be triggered by notification rules. */
859
+ export type NotificationActionType = "create_task" | "execute_mission" | "run_script" | "send_notification";
860
+ /** Base action interface. */
861
+ interface NotificationActionBase {
862
+ type: NotificationActionType;
863
+ }
864
+ /** Create a task when the rule fires. */
865
+ export interface CreateTaskAction extends NotificationActionBase {
866
+ type: "create_task";
867
+ title: string;
868
+ description: string;
869
+ assignTo: string;
870
+ expectations?: TaskExpectation[];
871
+ }
872
+ /** Execute an existing mission when the rule fires. */
873
+ export interface ExecuteMissionAction extends NotificationActionBase {
874
+ type: "execute_mission";
875
+ missionId: string;
876
+ }
877
+ /** Run a shell script when the rule fires. */
878
+ export interface RunScriptAction extends NotificationActionBase {
879
+ type: "run_script";
880
+ command: string;
881
+ /** Max execution time in ms. Default: 30000. */
882
+ timeoutMs?: number;
883
+ }
884
+ /** Send an additional notification to different channels. */
885
+ export interface SendNotificationAction extends NotificationActionBase {
886
+ type: "send_notification";
887
+ channel: string;
888
+ title: string;
889
+ body: string;
890
+ severity?: NotificationSeverity;
891
+ }
892
+ export type NotificationAction = CreateTaskAction | ExecuteMissionAction | RunScriptAction | SendNotificationAction;
893
+ export interface NotificationsConfig {
894
+ channels: Record<string, NotificationChannelConfig>;
895
+ rules: NotificationRule[];
896
+ }
897
+ /**
898
+ * Scoped notification rules — can be attached to a Task or Mission to override
899
+ * or extend the global notification rules.
900
+ *
901
+ * Precedence: task > mission > global.
902
+ * - Default: more-specific scope **replaces** global rules for matching events.
903
+ * - With `inherit: true`: scoped rules are **added** on top of the parent scope.
904
+ */
905
+ export interface ScopedNotificationRules {
906
+ /** Notification rules for this scope. */
907
+ rules: NotificationRule[];
908
+ /** If true, these rules are added on top of the parent scope (plan or global).
909
+ * If false (default), they replace parent rules for matching events. */
910
+ inherit?: boolean;
911
+ }
912
+ export type EscalationHandlerType = "agent" | "orchestrator" | "human";
913
+ export interface EscalationLevel {
914
+ /** Level number (0 = first). */
915
+ level: number;
916
+ /** Who handles at this level. */
917
+ handler: EscalationHandlerType;
918
+ /** Target agent name (for "agent"), notification channel (for "human"). */
919
+ target?: string;
920
+ /** Timeout before escalating to next level (ms). */
921
+ timeoutMs?: number;
922
+ /** Notification channels to alert at this level. */
923
+ notifyChannels?: string[];
924
+ }
925
+ export interface EscalationPolicy {
926
+ /** Policy name. */
927
+ name: string;
928
+ /** Ordered escalation levels. */
929
+ levels: EscalationLevel[];
930
+ }
931
+ /** Quality gate defined within a mission — checkpoint between task phases. */
932
+ export interface MissionQualityGate {
933
+ /** Gate name. */
934
+ name: string;
935
+ /** Tasks that must be completed before this gate is evaluated. */
936
+ afterTasks: string[];
937
+ /** Tasks that are blocked until this gate passes. */
938
+ blocksTasks: string[];
939
+ /** Minimum average score of `afterTasks` to pass. */
940
+ minScore?: number;
941
+ /** All `afterTasks` must have status "done" (not just completed — they must pass). */
942
+ requireAllPassed?: boolean;
943
+ /** Custom condition expression evaluated against gate context. */
944
+ condition?: string;
945
+ /** Notification channels to alert on gate pass/fail. */
946
+ notifyChannels?: string[];
947
+ }
948
+ /** Checkpoint defined within a mission — planned stopping point for human review.
949
+ *
950
+ * Unlike approval gates (which ask yes/no and auto-resume on approval),
951
+ * checkpoints unconditionally pause the mission until explicitly resumed.
952
+ * Use checkpoints for human-in-the-loop review at defined milestones. */
953
+ export interface MissionCheckpoint {
954
+ /** Checkpoint name (used in events and notifications). */
955
+ name: string;
956
+ /** Tasks that must be completed before this checkpoint triggers. */
957
+ afterTasks: string[];
958
+ /** Tasks that are blocked until the checkpoint is resumed. */
959
+ blocksTasks: string[];
960
+ /** Notification channels to alert when the checkpoint is reached. */
961
+ notifyChannels?: string[];
962
+ /** Optional message included in the notification when the checkpoint triggers. */
963
+ message?: string;
964
+ }
965
+ /** Delay defined within a mission — timed wait between task groups.
966
+ *
967
+ * Unlike checkpoints (which pause until a human resumes), delays
968
+ * automatically resume after a specified duration elapses.
969
+ * The timer starts when ALL afterTasks reach a terminal state (done/failed).
970
+ * Use delays for cooldown periods, staggered rollouts, rate-limiting, etc. */
971
+ export interface MissionDelay {
972
+ /** Delay name (used in events and notifications). */
973
+ name: string;
974
+ /** Tasks that must be completed before this delay timer starts. */
975
+ afterTasks: string[];
976
+ /** Tasks that are blocked until the delay timer expires. */
977
+ blocksTasks: string[];
978
+ /** ISO 8601 duration (e.g. "PT2H" = 2 hours, "PT30M" = 30 minutes, "P1D" = 1 day). */
979
+ duration: string;
980
+ /** Notification channels to alert when the delay starts / expires. */
981
+ notifyChannels?: string[];
982
+ /** Optional message included in the notification when the delay starts. */
983
+ message?: string;
984
+ }
985
+ /** SLA configuration for deadline monitoring. */
986
+ export interface SLAConfig {
987
+ /** Percentage of deadline elapsed before emitting a warning (0-1). Default: 0.8 */
988
+ warningThreshold?: number;
989
+ /** Check interval in ms. Default: 30000 (30s). */
990
+ checkIntervalMs?: number;
991
+ /** Notification channels for SLA warnings. */
992
+ warningChannels?: string[];
993
+ /** Notification channels for SLA violations. */
994
+ violationChannels?: string[];
995
+ /** Action on SLA violation: "notify" (default) or "fail" (force-fail the task). */
996
+ violationAction?: "notify" | "fail";
997
+ }
998
+ /** Quality metrics snapshot for a single entity (task, agent, mission). */
999
+ export interface QualityMetrics {
1000
+ /** Entity identifier. */
1001
+ entityId: string;
1002
+ /** Entity type. */
1003
+ entityType: "task" | "agent" | "mission";
1004
+ /** Total assessments run. */
1005
+ totalAssessments: number;
1006
+ /** Assessments that passed. */
1007
+ passedAssessments: number;
1008
+ /** Average global score (1-5). */
1009
+ avgScore?: number;
1010
+ /** Minimum score observed. */
1011
+ minScore?: number;
1012
+ /** Maximum score observed. */
1013
+ maxScore?: number;
1014
+ /** Per-dimension average scores. */
1015
+ dimensionScores: Record<string, number>;
1016
+ /** Total retries consumed. */
1017
+ totalRetries: number;
1018
+ /** Total fix attempts consumed. */
1019
+ totalFixes: number;
1020
+ /** Deadlines met vs missed. */
1021
+ deadlinesMet: number;
1022
+ deadlinesMissed: number;
1023
+ /** Last updated. */
1024
+ updatedAt: string;
1025
+ }
1026
+ /** Scheduled mission entry — runtime artifact derived from Mission fields. */
1027
+ export interface ScheduleEntry {
1028
+ /** Unique schedule ID. */
1029
+ id: string;
1030
+ /** Mission ID to execute. */
1031
+ missionId: string;
1032
+ /** Cron expression (e.g. "0 2 * * *") or ISO timestamp for one-shot. */
1033
+ expression: string;
1034
+ /** Whether this schedule recurs (derived from mission status === "recurring"). */
1035
+ recurring: boolean;
1036
+ /** Whether this schedule is active. */
1037
+ enabled: boolean;
1038
+ /** Last execution time (ISO). */
1039
+ lastRunAt?: string;
1040
+ /** Next scheduled execution time (ISO). */
1041
+ nextRunAt?: string;
1042
+ /** Deadline offset — auto-set task/mission deadline to N ms after execution start. */
1043
+ deadlineOffsetMs?: number;
1044
+ /** Created at. */
1045
+ createdAt: string;
1046
+ }
1047
+ /** A watcher that fires an action when a task reaches a target status. */
1048
+ export interface TaskWatcher {
1049
+ /** Unique watcher ID. */
1050
+ id: string;
1051
+ /** Task ID to watch. */
1052
+ taskId: string;
1053
+ /** Target status to trigger on. */
1054
+ targetStatus: TaskStatus;
1055
+ /** Action to execute when triggered. */
1056
+ action: NotificationAction;
1057
+ /** Whether the watcher has already fired. */
1058
+ fired: boolean;
1059
+ /** Created at (ISO). */
1060
+ createdAt: string;
1061
+ /** Fired at (ISO). */
1062
+ firedAt?: string;
1063
+ }
1064
+ export interface PolpoSettingsExtended {
1065
+ /** Approval gates configuration. */
1066
+ approvalGates?: ApprovalGate[];
1067
+ /** Notification system configuration. */
1068
+ notifications?: NotificationsConfig;
1069
+ /** Default escalation policy for tasks. */
1070
+ escalationPolicy?: EscalationPolicy;
1071
+ }
1072
+ export {};
1073
+ //# sourceMappingURL=types.d.ts.map