@oharness/engine 0.9.2 → 0.10.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 (119) hide show
  1. package/dist/agent/agent.d.ts +207 -1
  2. package/dist/agent/agent.js +691 -55
  3. package/dist/agent/agent.js.map +1 -1
  4. package/dist/agent/background.d.ts +135 -0
  5. package/dist/agent/background.js +307 -0
  6. package/dist/agent/background.js.map +1 -0
  7. package/dist/agent/compaction.d.ts +7 -0
  8. package/dist/agent/compaction.js +11 -3
  9. package/dist/agent/compaction.js.map +1 -1
  10. package/dist/agent/goal.d.ts +36 -0
  11. package/dist/agent/goal.js +71 -0
  12. package/dist/agent/goal.js.map +1 -0
  13. package/dist/agent/permissions.d.ts +6 -0
  14. package/dist/agent/permissions.js +2 -1
  15. package/dist/agent/permissions.js.map +1 -1
  16. package/dist/agent/session.d.ts +36 -0
  17. package/dist/agent/session.js +72 -0
  18. package/dist/agent/session.js.map +1 -1
  19. package/dist/agent/store.d.ts +25 -0
  20. package/dist/agent/store.js +21 -0
  21. package/dist/agent/store.js.map +1 -1
  22. package/dist/agent/subagent.d.ts +12 -0
  23. package/dist/agent/subagent.js +11 -1
  24. package/dist/agent/subagent.js.map +1 -1
  25. package/dist/agent/workspace.d.ts +9 -0
  26. package/dist/agent/workspace.js +59 -5
  27. package/dist/agent/workspace.js.map +1 -1
  28. package/dist/auth/manager.d.ts +9 -0
  29. package/dist/auth/manager.js +67 -6
  30. package/dist/auth/manager.js.map +1 -1
  31. package/dist/auth/providers/account.js +5 -4
  32. package/dist/auth/providers/account.js.map +1 -1
  33. package/dist/browser/tools.js +3 -0
  34. package/dist/browser/tools.js.map +1 -1
  35. package/dist/computer/arbiter.d.ts +69 -0
  36. package/dist/computer/arbiter.js +128 -0
  37. package/dist/computer/arbiter.js.map +1 -0
  38. package/dist/computer/cua-driver.d.ts +115 -0
  39. package/dist/computer/cua-driver.js +453 -0
  40. package/dist/computer/cua-driver.js.map +1 -0
  41. package/dist/computer/helper-client.d.ts +78 -0
  42. package/dist/computer/helper-client.js +163 -0
  43. package/dist/computer/helper-client.js.map +1 -0
  44. package/dist/computer/index.d.ts +15 -0
  45. package/dist/computer/index.js +9 -0
  46. package/dist/computer/index.js.map +1 -0
  47. package/dist/computer/mode.d.ts +19 -0
  48. package/dist/computer/mode.js +42 -0
  49. package/dist/computer/mode.js.map +1 -0
  50. package/dist/computer/plugin.d.ts +24 -0
  51. package/dist/computer/plugin.js +17 -0
  52. package/dist/computer/plugin.js.map +1 -0
  53. package/dist/computer/policy.d.ts +29 -0
  54. package/dist/computer/policy.js +127 -0
  55. package/dist/computer/policy.js.map +1 -0
  56. package/dist/computer/session.d.ts +199 -0
  57. package/dist/computer/session.js +392 -0
  58. package/dist/computer/session.js.map +1 -0
  59. package/dist/computer/target.d.ts +187 -0
  60. package/dist/computer/target.js +31 -0
  61. package/dist/computer/target.js.map +1 -0
  62. package/dist/computer/tools.d.ts +8 -0
  63. package/dist/computer/tools.js +537 -0
  64. package/dist/computer/tools.js.map +1 -0
  65. package/dist/core/tokens.js +4 -0
  66. package/dist/core/tokens.js.map +1 -1
  67. package/dist/core/types.d.ts +16 -1
  68. package/dist/core/types.js.map +1 -1
  69. package/dist/harness.d.ts +76 -1
  70. package/dist/harness.js +178 -22
  71. package/dist/harness.js.map +1 -1
  72. package/dist/index.d.ts +3 -0
  73. package/dist/index.js +2 -0
  74. package/dist/index.js.map +1 -1
  75. package/dist/mcp/transport.js +3 -0
  76. package/dist/mcp/transport.js.map +1 -1
  77. package/dist/providers/catalog.js +6 -0
  78. package/dist/providers/catalog.js.map +1 -1
  79. package/dist/providers/discovery.js +10 -2
  80. package/dist/providers/discovery.js.map +1 -1
  81. package/dist/providers/models-dev.js +1 -0
  82. package/dist/providers/models-dev.js.map +1 -1
  83. package/dist/providers/models-dev.json +114 -102
  84. package/dist/providers/piai.d.ts +16 -1
  85. package/dist/providers/piai.js +84 -7
  86. package/dist/providers/piai.js.map +1 -1
  87. package/dist/providers/types.d.ts +6 -0
  88. package/dist/providers/types.js.map +1 -1
  89. package/dist/runtime-plugins/cloud-connector.js +5 -0
  90. package/dist/runtime-plugins/cloud-connector.js.map +1 -1
  91. package/dist/schedule/scheduler.d.ts +38 -0
  92. package/dist/schedule/scheduler.js +101 -1
  93. package/dist/schedule/scheduler.js.map +1 -1
  94. package/dist/tools/builtin/bash.d.ts +6 -0
  95. package/dist/tools/builtin/bash.js +2 -1
  96. package/dist/tools/builtin/bash.js.map +1 -1
  97. package/dist/tools/builtin/recall.js +4 -0
  98. package/dist/tools/builtin/recall.js.map +1 -1
  99. package/dist/tools/builtin/routine.d.ts +9 -0
  100. package/dist/tools/builtin/routine.js +23 -2
  101. package/dist/tools/builtin/routine.js.map +1 -1
  102. package/dist/tools/builtin/task-control.d.ts +21 -0
  103. package/dist/tools/builtin/task-control.js +120 -0
  104. package/dist/tools/builtin/task-control.js.map +1 -0
  105. package/dist/tools/builtin/task.js +50 -9
  106. package/dist/tools/builtin/task.js.map +1 -1
  107. package/dist/tools/builtin/todo.d.ts +1 -1
  108. package/dist/tools/builtin/worktree.d.ts +10 -0
  109. package/dist/tools/builtin/worktree.js +52 -0
  110. package/dist/tools/builtin/worktree.js.map +1 -0
  111. package/dist/tools/define.d.ts +4 -1
  112. package/dist/tools/define.js +2 -0
  113. package/dist/tools/define.js.map +1 -1
  114. package/dist/tools/types.d.ts +112 -0
  115. package/dist/tools/types.js.map +1 -1
  116. package/dist/worktree/index.d.ts +109 -0
  117. package/dist/worktree/index.js +463 -0
  118. package/dist/worktree/index.js.map +1 -0
  119. package/package.json +3 -3
@@ -1,9 +1,10 @@
1
+ import type { SessionGoal } from "./goal.ts";
1
2
  import type { RuntimeAuditEvent } from "../core/audit.ts";
2
3
  import type { Message, StopReason, Usage } from "../core/types.ts";
3
4
  import type { McpManager } from "../mcp/manager.ts";
4
5
  import type { ThinkingConfig } from "../providers/types.ts";
5
6
  import type { ToolFilter, ToolRegistry } from "../tools/registry.ts";
6
- import type { SubagentRunOptions, SubagentRunResult, ToolHost, ToolProgress, ToolResult } from "../tools/types.ts";
7
+ import type { BackgroundTaskHost, BackgroundTaskView, SubagentRunOptions, SubagentRunResult, ToolHost, ToolProgress, ToolResult, WorktreeLauncher, WorktreeStartOptions, WorktreeStartResult } from "../tools/types.ts";
7
8
  import type { ArtifactDescriptor } from "../artifacts/store.ts";
8
9
  import type { Logger } from "../util/logger.ts";
9
10
  import type { WorkspacePolicy } from "./workspace.ts";
@@ -89,6 +90,8 @@ export type AgentEvent = {
89
90
  reason?: string;
90
91
  /** Pattern written to settings, when the approval was persisted. */
91
92
  remembered?: string;
93
+ /** Held back by plan mode: the mode doing its job, not a refusal. */
94
+ plan?: boolean;
92
95
  }
93
96
  /**
94
97
  * Something the user said while the turn was already running has just been
@@ -99,6 +102,15 @@ export type AgentEvent = {
99
102
  type: "interjected";
100
103
  id: string;
101
104
  text: string;
105
+ }
106
+ /**
107
+ * Background tasks have ended and their results were just read into the
108
+ * conversation, as `text`. Emitted where they enter, like an interjection.
109
+ */
110
+ | {
111
+ type: "task_notification";
112
+ tasks: BackgroundTaskView[];
113
+ text: string;
102
114
  } | {
103
115
  type: "compacted";
104
116
  tokensBefore: number;
@@ -130,6 +142,11 @@ export type AgentEvent = {
130
142
  type: "notice";
131
143
  message: string;
132
144
  }
145
+ /** The session's goal was set, nudged, achieved or reported blocked. */
146
+ | {
147
+ type: "goal";
148
+ goal: SessionGoal;
149
+ }
133
150
  /**
134
151
  * `status` is the HTTP status behind a provider failure, when one could be
135
152
  * recovered. It travels beside the message because some statuses are not
@@ -191,6 +208,11 @@ export interface AgentOptions {
191
208
  onSkillsChanged?: () => Promise<unknown>;
192
209
  /** Restricts where writes may land. A policy gate, not an OS sandbox. */
193
210
  workspace?: WorkspacePolicy;
211
+ /**
212
+ * Who can host a session in a new worktree. A getter, because the frontend
213
+ * wires it after the harness — and so the agent it builds — already exists.
214
+ */
215
+ worktreeLauncher?: () => WorktreeLauncher | undefined;
194
216
  /** Enable provider prompt caching where the model supports it. */
195
217
  cache?: boolean;
196
218
  agentId?: string;
@@ -200,8 +222,38 @@ export interface AgentOptions {
200
222
  onAudit?: (event: RuntimeAuditEvent) => void;
201
223
  /** Internal host lifecycle accounting; inherited by subagents. */
202
224
  onRunStart?: () => () => void;
225
+ /**
226
+ * Who starts a turn to read in background results that end while this agent
227
+ * is idle. A getter, like worktreeLauncher, because the frontend wires it
228
+ * after the agent exists. Without one, background tasks are not offered:
229
+ * a result arriving after the run had ended would reach nobody.
230
+ */
231
+ taskWaker?: () => ((sessionId: string) => void) | undefined;
232
+ /** How many background tasks run at once; the rest queue. */
233
+ maxBackgroundTasks?: number;
234
+ /**
235
+ * Give a subagent its own browser and computer, so it never drives the
236
+ * parent's tabs or acts under the parent's window leases. Rebinds the
237
+ * per-conversation tools already in `tools`; `release` closes them again.
238
+ */
239
+ equipSubagent?: (sessionId: string, label: string, tools: ToolRegistry) => SubagentEquipment;
240
+ /**
241
+ * The conversation this agent's permission cards belong to. A subagent's
242
+ * own session is invisible to every frontend, so its questions are placed
243
+ * in the conversation that started it.
244
+ */
245
+ interactionSessionId?: string;
246
+ /** Who is asking, on those cards: "general: fix the flaky test". */
247
+ interactionLabel?: string;
203
248
  logger?: Logger;
204
249
  }
250
+ export interface SubagentEquipment {
251
+ /** Replaces the parent's run accounting, which would release the parent's leases. */
252
+ onRunStart?: () => () => void;
253
+ /** Rebind its tools into another registry: the same browser and computer, for a later run. */
254
+ bind?(tools: ToolRegistry): void;
255
+ release(): Promise<void>;
256
+ }
205
257
  /**
206
258
  * Notes attached to messages still in the transcript.
207
259
  *
@@ -218,6 +270,22 @@ export declare function recalledInTranscript(messages: readonly Message[]): Set<
218
270
  * same regardless of which model is selected — including when the model
219
271
  * changes partway through a session.
220
272
  */
273
+ /** How a conversation fills the model's window; see Agent.contextBreakdown(). */
274
+ export interface ContextBreakdown {
275
+ /** Tokens in use: measured from the last request when there was one. */
276
+ total: number;
277
+ window: number;
278
+ /** Estimated: the system prompt, with skills, memory and project notes. */
279
+ system: number;
280
+ /** Estimated: the definitions of the tools offered to the model. */
281
+ tools: number;
282
+ /** The rest of the total: the conversation itself. */
283
+ messages: number;
284
+ /** Whether `total` came from the provider rather than an estimate. */
285
+ measured: boolean;
286
+ /** Tokens at which automatic compaction fires; absent when it is off. */
287
+ compactAt?: number;
288
+ }
221
289
  export declare class Agent implements ToolHost {
222
290
  readonly session: Session;
223
291
  readonly tools: ToolRegistry;
@@ -248,6 +316,18 @@ export declare class Agent implements ToolHost {
248
316
  private pluginSections;
249
317
  /** Recall over `memory` for agents embedded without a plugin host. */
250
318
  private legacyMemory?;
319
+ /** Subagents running in the background; made on first use. */
320
+ private background?;
321
+ private wakeTimer?;
322
+ /** Frontends watching background tasks, kept until the tasks exist. */
323
+ private readonly changeListeners;
324
+ /** What each background task was asked, and its subagent once it has one. */
325
+ private readonly taskStates;
326
+ private restoring?;
327
+ private saveTimer?;
328
+ /** Closed or deleted: nothing more is saved, and nothing more starts. */
329
+ private tasksClosed;
330
+ private saveChain;
251
331
  constructor(opts: AgentOptions);
252
332
  /**
253
333
  * Announce a model switch so a UI can render it and hooks can react.
@@ -295,14 +375,106 @@ export declare class Agent implements ToolHost {
295
375
  * tools ask rather than each re-deriving a notion of "inside the project".
296
376
  */
297
377
  resolvePath(input: string, access: "read" | "write"): string;
378
+ startWorktree(opts: WorktreeStartOptions): Promise<WorktreeStartResult>;
298
379
  listSubagentTypes(): Array<{
299
380
  name: string;
300
381
  description: string;
382
+ readOnly?: boolean;
383
+ isolation?: "worktree";
301
384
  }>;
302
385
  runSubagent(opts: SubagentRunOptions): Promise<SubagentRunResult>;
386
+ /**
387
+ * Subagents running behind this conversation, offered only while someone
388
+ * can start a turn to read their results in. Once any exist they stay
389
+ * reachable, so they can still be listed, messaged and stopped.
390
+ */
391
+ get backgroundTasks(): BackgroundTaskHost | undefined;
392
+ /** A task's conversation so far, for a frontend to show. */
393
+ backgroundTranscript(id: string): readonly Message[] | undefined;
394
+ /** Every change to a background task, for a frontend to redraw from. */
395
+ onBackgroundChange(listener: (task: BackgroundTaskView) => void): () => void;
396
+ /**
397
+ * The conversation is being closed, not ended: write its tasks down as they
398
+ * stand, then stop them. Opened again, the ones that were running come back
399
+ * interrupted and can be followed up — as after a restart.
400
+ */
401
+ closeBackgroundTasks(): Promise<void>;
402
+ /**
403
+ * The conversation is being deleted: stop its tasks and write nothing more.
404
+ * Resolves once a write already under way has landed, so deleting the
405
+ * store afterwards cannot be undone by it.
406
+ */
407
+ discardBackgroundTasks(): Promise<void>;
408
+ private endBackgroundTasks;
409
+ private backgroundAvailable;
410
+ private tasks;
411
+ /**
412
+ * A background task's subagent, made for each run and let go after it.
413
+ *
414
+ * Between runs a task holds only its conversation and, if it changed
415
+ * anything, its worktree: no browser, no claim on the computer, no agent.
416
+ * A follow-up — or the first one after a restart — builds the subagent
417
+ * again from those, so both paths are the same path.
418
+ */
419
+ private backgroundSpec;
420
+ /**
421
+ * Put back the background tasks this conversation had before a restart.
422
+ *
423
+ * Called by a frontend when it opens the conversation; safe to call again.
424
+ * A task that was still running when the app closed comes back as failed
425
+ * and says why — its subagent's process is gone — but keeps its
426
+ * conversation, so a follow-up carries on from where it stopped. A result
427
+ * nobody had been told about is still read in with the next turn.
428
+ */
429
+ restoreBackgroundTasks(): Promise<number>;
430
+ /** Write the tasks down a moment after they change, so a burst is one write. */
431
+ private scheduleSave;
432
+ /**
433
+ * One write at a time, in order. Each takes its snapshot when its turn
434
+ * comes, so a later state is never overwritten by an earlier one landing
435
+ * last — a task that ended would come back as running.
436
+ */
437
+ private saveTasks;
438
+ private writeTasks;
439
+ private scheduleWake;
440
+ /**
441
+ * Read the results of background tasks that have ended into the
442
+ * conversation, as one message saying what is still running.
443
+ *
444
+ * Synthetic, like a goal nudge: nobody typed it, so it skips the prompt hook
445
+ * and memory recall, and never titles the session.
446
+ */
447
+ private takeNotices;
448
+ /** Where this agent's permission cards go, and who they say is asking. */
449
+ private interactionPlace;
450
+ /** A subagent ready to run: its agent, the tree it works in, what it holds. */
451
+ private prepareSubagent;
452
+ /**
453
+ * One run of a subagent, to its end: its first prompt, or a later message.
454
+ *
455
+ * `report` is there only for a background task: it is what lets a look at
456
+ * the task say what the subagent is doing now.
457
+ */
458
+ private runChild;
459
+ /** What a subagent left in its worktree, when it left anything. */
460
+ private worktreeNote;
461
+ /**
462
+ * A subagent is finished with: its browser and computer go, and a worktree
463
+ * it changed nothing in is removed. One that it changed is kept — the
464
+ * parent has to decide what happens to that work.
465
+ */
466
+ private disposeChild;
467
+ private dropIfUntouched;
303
468
  run(input: string | Message[], runOpts?: {
304
469
  signal?: AbortSignal;
305
470
  }): AsyncGenerator<AgentEvent, void, void>;
471
+ /**
472
+ * Where a reply ends with a goal still active: ask for more work.
473
+ *
474
+ * Returns whether the loop should go on. A model that keeps stopping short
475
+ * of its goal gets a bounded number of reminders, not an endless supply.
476
+ */
477
+ private pushTowardGoal;
306
478
  private ingestInput;
307
479
  /**
308
480
  * Put what the user said into the conversation, as its own message.
@@ -343,12 +515,46 @@ export declare class Agent implements ToolHost {
343
515
  private scheduleExtraction;
344
516
  /** Where the next end-of-run extraction starts, clamped to the transcript. */
345
517
  private extractedUpTo;
518
+ /**
519
+ * How full the model's window is, in tokens: what the last request measured,
520
+ * or, before one has (a new or reopened conversation), an estimate of the
521
+ * next request — system prompt and tools included, which are a large share
522
+ * of a short conversation.
523
+ */
524
+ contextTokens(): number;
525
+ /**
526
+ * The window, split the way the context panel draws it. Providers report one
527
+ * number for the prompt, so the system prompt and the tool definitions are
528
+ * estimated and the messages are what is left of the measured total; until
529
+ * something is measured all three are estimates.
530
+ */
531
+ contextBreakdown(): ContextBreakdown;
532
+ private contextEstimate;
533
+ /**
534
+ * Compact now, whatever the window says: the /compact command. Goes through
535
+ * the same path as the automatic kind, so what it drops is archived for
536
+ * recall and handed to memory extraction rather than simply discarded.
537
+ * Returns what happened, or undefined when there was nothing safe to cut.
538
+ */
539
+ compactNow(): Promise<AgentEvent | undefined>;
346
540
  private maybeCompact;
541
+ /**
542
+ * The tools offered to the model: the goal tool only while there is a goal,
543
+ * and the computer tools only while this conversation has Computer Use on.
544
+ */
545
+ private visibleTools;
347
546
  private systemPrompt;
348
547
  private buildRequest;
349
548
  /** Consume the provider stream, emitting deltas and assembling the message. */
350
549
  private streamAssistant;
351
550
  private executeCalls;
352
551
  private executeOne;
552
+ /**
553
+ * Ask about a write the workspace policy would refuse.
554
+ *
555
+ * Bypass mode approves it as it approves everything else. Read-only and plan
556
+ * mode refuse it, as does a frontend with no way to ask.
557
+ */
558
+ private askOutsideRoots;
353
559
  private checkPermission;
354
560
  }