@tt-a1i/openpi 0.4.0 → 0.6.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 (141) hide show
  1. package/README.md +116 -46
  2. package/SETUP.md +29 -7
  3. package/THIRD_PARTY_NOTICES.md +16 -0
  4. package/assets/openpi-launch-card-v1.webp +0 -0
  5. package/bin/openpi.js +155 -0
  6. package/extensions/ai-providers/LICENSE.upstream +23 -0
  7. package/extensions/ai-providers/README.md +59 -0
  8. package/extensions/ai-providers/antigravity/credentials.ts +52 -0
  9. package/extensions/ai-providers/antigravity/discovery.ts +130 -0
  10. package/extensions/ai-providers/antigravity/google-conversion.ts +455 -0
  11. package/extensions/ai-providers/antigravity/models.ts +84 -0
  12. package/extensions/ai-providers/antigravity/oauth.ts +700 -0
  13. package/extensions/ai-providers/antigravity/provider.ts +1116 -0
  14. package/extensions/ai-providers/antigravity/routing.ts +340 -0
  15. package/extensions/ai-providers/antigravity/with-resolvers.d.ts +19 -0
  16. package/extensions/ai-providers/cursor/constants.ts +5 -0
  17. package/extensions/ai-providers/cursor/credentials.ts +14 -0
  18. package/extensions/ai-providers/cursor/discovery.ts +291 -0
  19. package/extensions/ai-providers/cursor/input-images.ts +106 -0
  20. package/extensions/ai-providers/cursor/models.ts +45 -0
  21. package/extensions/ai-providers/cursor/oauth.ts +263 -0
  22. package/extensions/ai-providers/cursor/proto.ts +1064 -0
  23. package/extensions/ai-providers/cursor/protobuf.ts +1171 -0
  24. package/extensions/ai-providers/cursor/provider.ts +1175 -0
  25. package/extensions/ai-providers/cursor/proxy.ts +213 -0
  26. package/extensions/ai-providers/cursor/with-resolvers.d.ts +12 -0
  27. package/extensions/ai-providers/index.ts +86 -0
  28. package/extensions/ai-providers/oauth-adapter.ts +81 -0
  29. package/extensions/ai-providers/usage.ts +10 -0
  30. package/extensions/background-terminals/index.ts +38 -3
  31. package/extensions/background-terminals/src/domain.ts +2 -0
  32. package/extensions/background-terminals/src/manager.ts +484 -106
  33. package/extensions/background-terminals/src/output.ts +33 -0
  34. package/extensions/background-terminals/src/prompt.ts +13 -5
  35. package/extensions/background-terminals/src/result-delivery.ts +47 -24
  36. package/extensions/clear-context/index.ts +83 -0
  37. package/extensions/context-pivot/index.ts +16 -6
  38. package/extensions/cron/index.ts +68 -27
  39. package/extensions/cron/schedule.ts +12 -2
  40. package/extensions/file-mutation-display/render.ts +17 -257
  41. package/extensions/file-search/src/binaries.ts +57 -41
  42. package/extensions/git-read/index.ts +1 -3
  43. package/extensions/model-info/cache-diagnostics.ts +220 -0
  44. package/extensions/model-info/index.ts +65 -33
  45. package/extensions/model-info/session-metrics.ts +96 -0
  46. package/extensions/plan-mode/bash-policy.ts +54 -9
  47. package/extensions/plan-mode/index.ts +82 -6
  48. package/extensions/post-edit/index.ts +16 -6
  49. package/extensions/sessions/git-stats.ts +258 -72
  50. package/extensions/sessions/index.ts +153 -86
  51. package/extensions/sessions/preview-cache.ts +104 -0
  52. package/extensions/sessions/preview-loader.ts +856 -0
  53. package/extensions/sessions/sessions.ts +43 -4
  54. package/extensions/setup/index.ts +138 -130
  55. package/extensions/shared/activity-status.ts +30 -0
  56. package/extensions/shared/agent-session-page.ts +319 -0
  57. package/extensions/shared/agent-tool-renderer.ts +218 -0
  58. package/extensions/shared/agent-transcript.ts +524 -0
  59. package/extensions/shared/capability-intent.ts +1 -1
  60. package/extensions/shared/child-session.ts +457 -21
  61. package/extensions/shared/completion-inbox.ts +193 -0
  62. package/extensions/shared/result-delivery.ts +34 -0
  63. package/extensions/shared/setup-config.ts +83 -34
  64. package/extensions/shared/setup-episode-state.ts +1 -1
  65. package/extensions/shared/structured-output.ts +154 -0
  66. package/extensions/shared/terminal-text.ts +110 -23
  67. package/extensions/shared/text-projection.ts +72 -15
  68. package/extensions/shared/tool-activity.ts +382 -0
  69. package/extensions/shared/tool-surface.ts +29 -2
  70. package/extensions/shared/transcript-viewport.ts +46 -0
  71. package/extensions/shared/web-observer-registry.ts +390 -0
  72. package/extensions/shared/worktree.ts +11 -0
  73. package/extensions/subagents/index.ts +313 -62
  74. package/extensions/subagents/navigation.ts +34 -5
  75. package/extensions/subagents/src/backend.ts +12 -1
  76. package/extensions/subagents/src/backends/pi.ts +450 -70
  77. package/extensions/subagents/src/domain.ts +21 -1
  78. package/extensions/subagents/src/manager.ts +39 -2
  79. package/extensions/subagents/src/prompt.ts +49 -7
  80. package/extensions/subagents/src/result-artifact.ts +36 -0
  81. package/extensions/subagents/src/result-delivery.ts +39 -14
  82. package/extensions/subagents/src/runtime.ts +15 -1
  83. package/extensions/subagents/src/ui/takeover.ts +73 -257
  84. package/extensions/subagents/src/ui/transcript.ts +38 -535
  85. package/extensions/subagents/src/ui/wait-result.ts +103 -15
  86. package/extensions/suggestions/src/ui.ts +10 -4
  87. package/extensions/tasks/index.ts +0 -3
  88. package/extensions/ui-customization/footer.ts +16 -45
  89. package/extensions/ui-customization/index.ts +0 -4
  90. package/extensions/user-input-fold/index.ts +42 -6
  91. package/extensions/web/index.ts +257 -0
  92. package/extensions/workflows/acceptance.ts +43 -19
  93. package/extensions/workflows/artifacts.ts +137 -47
  94. package/extensions/workflows/completion-projection.ts +459 -0
  95. package/extensions/workflows/coordinator.ts +8 -10
  96. package/extensions/workflows/dashboard.ts +175 -228
  97. package/extensions/workflows/handoff.ts +70 -16
  98. package/extensions/workflows/index.ts +501 -198
  99. package/extensions/workflows/journal.ts +148 -13
  100. package/extensions/workflows/model.ts +79 -5
  101. package/extensions/workflows/navigation.ts +32 -8
  102. package/extensions/workflows/progress-projection.ts +306 -0
  103. package/extensions/workflows/prompt.ts +70 -16
  104. package/extensions/workflows/replay-safety.ts +42 -21
  105. package/extensions/workflows/result-delivery.ts +214 -76
  106. package/extensions/workflows/retention.ts +599 -0
  107. package/extensions/workflows/runner.ts +389 -345
  108. package/extensions/workflows/sandbox-child.cjs +25 -3
  109. package/extensions/workflows/sandbox.ts +62 -8
  110. package/extensions/workflows/serialization.ts +325 -17
  111. package/extensions/workflows/tool-renderer.ts +22 -0
  112. package/extensions/workflows/transcript.ts +149 -0
  113. package/extensions/workspace-cleanup-guard/index.ts +54 -0
  114. package/extensions/workspace-cleanup-guard/workspace-provenance.ts +563 -0
  115. package/package.json +34 -14
  116. package/skills/subagents/REFERENCE.md +190 -0
  117. package/skills/subagents/SKILL.md +2 -1
  118. package/skills/workflows/REFERENCE.md +6 -4
  119. package/skills/workflows/SKILL.md +1 -1
  120. package/web/adapter/pi-adapter.ts +664 -0
  121. package/web/host/browser-launcher.ts +20 -0
  122. package/web/host/pi-coding-agent-entry.ts +162 -0
  123. package/web/host/static-assets.ts +4 -0
  124. package/web/host/terminal-status.ts +38 -0
  125. package/web/host/web-host.ts +1069 -0
  126. package/web/http-dispatcher.ts +125 -0
  127. package/web/protocol/types.ts +467 -0
  128. package/web/runtime/pi-runtime.ts +1206 -0
  129. package/web/runtime/types.ts +102 -0
  130. package/web/runtime/web-host-lease.ts +497 -0
  131. package/web/trace.ts +18 -0
  132. package/web/ui/app.js +1700 -0
  133. package/web/ui/index.html +142 -0
  134. package/web/ui/styles.css +680 -0
  135. package/web/vite.config.mjs +34 -0
  136. package/extensions/execution-convergence/active-evidence.ts +0 -129
  137. package/extensions/execution-convergence/index.ts +0 -442
  138. package/extensions/execution-convergence/workspace-provenance.ts +0 -338
  139. package/extensions/setup/intercom-fs-helper.cjs +0 -130
  140. package/extensions/setup/intercom.ts +0 -603
  141. package/extensions/subagents/src/backends/stub.ts +0 -303
@@ -1,303 +0,0 @@
1
- /**
2
- * Scripted stub sessions, test-only: they stand in for the pi backend so the
3
- * manager can be driven without a real child session. A stub session:
4
- *
5
- * - streams a plausible turn (thinking deltas, one fake tool cycle, text
6
- * deltas, usage ramp, a final assistant message, RunSettled) over a few
7
- * seconds so streaming UI, wait, and the footer counters are observable;
8
- * - supports send() while running (queued-steer rendering) and while idle
9
- * (fresh run);
10
- * - supports interrupt (RunSettled Interrupted -> status "error", matching v1);
11
- * - fails the run when the prompt starts with "FAIL:", and refuses to spawn
12
- * at all when it starts with "SPAWNFAIL:" (error-path testing);
13
- * - hangs the run after RunStarted without any assistant event when the
14
- * prompt starts with "HANG:" (first-response watchdog testing);
15
- * - appends every event to a JSONL "session file" in tmpdir so the
16
- * "full transcript in session file" pointers resolve.
17
- */
18
-
19
- import * as fs from "node:fs";
20
- import * as os from "node:os";
21
- import * as path from "node:path";
22
- import type { Cause, Scope } from "effect";
23
- import { Duration, Effect, Fiber, Queue, Ref, Stream } from "effect";
24
- import type { SubagentBackend, SubagentSession } from "../backend.ts";
25
- import type {
26
- BackendName,
27
- QueuedMessage,
28
- SpawnTask,
29
- SubagentEvent,
30
- SubagentMeta,
31
- } from "../domain.ts";
32
- import { SendError, SpawnError } from "../domain.ts";
33
-
34
- export interface StubProfile {
35
- readonly backend: BackendName;
36
- readonly defaultModelLabel: string;
37
- readonly contextWindow: number;
38
- readonly toolName: string;
39
- /** Delay between scripted events; varies per backend so streams differ. */
40
- readonly cadenceMs: number;
41
- }
42
-
43
- const STUB_DIR = path.join(os.tmpdir(), "subagents-stub");
44
- let sessionCounter = 0;
45
-
46
- export function makeStubBackend(profile: StubProfile): SubagentBackend {
47
- return {
48
- name: profile.backend,
49
- spawn: (task) =>
50
- task.prompt.startsWith("SPAWNFAIL:")
51
- ? Effect.fail(new SpawnError({ message: "stub refused to spawn" }))
52
- : makeStubSession(profile, task),
53
- };
54
- }
55
-
56
- function firstLine(text: string): string {
57
- return (
58
- text
59
- .split("\n")
60
- .find((line) => line.trim())
61
- ?.trim() ?? ""
62
- );
63
- }
64
-
65
- function chunked(text: string, size: number): string[] {
66
- const chunks: string[] = [];
67
- for (let i = 0; i < text.length; i += size)
68
- chunks.push(text.slice(i, i + size));
69
- return chunks;
70
- }
71
-
72
- const makeStubSession = (
73
- profile: StubProfile,
74
- task: SpawnTask,
75
- ): Effect.Effect<SubagentSession, never, Scope.Scope> =>
76
- Effect.gen(function* () {
77
- const sessionId = `stub-${profile.backend}-${++sessionCounter}`;
78
- const sessionFile = path.join(STUB_DIR, `${sessionId}.jsonl`);
79
-
80
- const state = {
81
- meta: {
82
- backend: profile.backend,
83
- modelLabel: task.model ?? profile.defaultModelLabel,
84
- contextWindow: profile.contextWindow,
85
- sessionFilePath: sessionFile,
86
- } satisfies SubagentMeta as SubagentMeta,
87
- pending: [] as string[],
88
- turnCount: 0,
89
- closed: false,
90
- /** True between the driver dequeuing a prompt and registering its turn fiber. */
91
- dispatching: false,
92
- };
93
-
94
- const events = yield* Queue.make<SubagentEvent, Cause.Done>();
95
- const inbox = yield* Queue.make<string, Cause.Done>();
96
- const activeTurn = yield* Ref.make<Fiber.Fiber<void> | undefined>(
97
- undefined,
98
- );
99
-
100
- const emit = (event: SubagentEvent) =>
101
- Effect.suspend(() => {
102
- try {
103
- fs.appendFileSync(sessionFile, `${JSON.stringify(event)}\n`);
104
- } catch {
105
- // The fake session file is best-effort.
106
- }
107
- if (event._tag === "MetaChanged") {
108
- state.meta = { ...state.meta, ...event.meta };
109
- }
110
- return Queue.offer(events, event);
111
- }).pipe(Effect.asVoid);
112
-
113
- const pause = Effect.sleep(Duration.millis(profile.cadenceMs));
114
-
115
- const runTurn = (userText: string, turn: number) =>
116
- Effect.gen(function* () {
117
- yield* emit({ _tag: "RunStarted" });
118
- const failing = userText.trimStart().startsWith("FAIL:");
119
- // Stand in for a provider that accepts the request but never emits
120
- // its first assistant event.
121
- if (userText.trimStart().startsWith("HANG:")) {
122
- return yield* Effect.never;
123
- }
124
-
125
- const thinking = "Looking at the task and planning an approach...";
126
- for (const delta of chunked(thinking, 16)) {
127
- yield* emit({ _tag: "AssistantDelta", kind: "thinking", delta });
128
- yield* pause;
129
- }
130
-
131
- const toolId = `${sessionId}-tool-${turn}`;
132
- const argsPreview = `{"command":"ls ${task.cwd}"}`;
133
- yield* emit({
134
- _tag: "AssistantMessage",
135
- parts: [
136
- { type: "thinking", text: thinking },
137
- {
138
- type: "text",
139
- text: `I'll run ${profile.toolName} to look around first.`,
140
- },
141
- { type: "toolCall", toolId, name: profile.toolName, argsPreview },
142
- ],
143
- });
144
- yield* emit({
145
- _tag: "ToolStart",
146
- toolId,
147
- name: profile.toolName,
148
- argsPreview,
149
- });
150
- yield* pause;
151
- yield* emit({
152
- _tag: "ToolUpdate",
153
- toolId,
154
- outputPreview: "src docs package.json",
155
- });
156
- yield* pause;
157
- yield* emit({
158
- _tag: "ToolEnd",
159
- toolId,
160
- name: profile.toolName,
161
- isError: false,
162
- outputPreview: "src docs package.json",
163
- });
164
- yield* emit({
165
- _tag: "UsageChanged",
166
- tokens: Math.min(profile.contextWindow, 2400 * (turn + 1)),
167
- contextWindow: profile.contextWindow,
168
- });
169
-
170
- if (failing) {
171
- yield* pause;
172
- yield* emit({
173
- _tag: "RunSettled",
174
- outcome: {
175
- _tag: "Failed",
176
- errorText: `[stub:${profile.backend}] task failed as requested by FAIL: prefix`,
177
- },
178
- });
179
- return;
180
- }
181
-
182
- const finalText =
183
- `[stub:${profile.backend}] completed: ${firstLine(userText).slice(0, 200)}\n\n` +
184
- `This is a stubbed ${profile.backend} subagent turn ${turn + 1}. ` +
185
- `The real backend integration will replace this scripted output.`;
186
- for (const delta of chunked(finalText, 24)) {
187
- yield* emit({ _tag: "AssistantDelta", kind: "text", delta });
188
- yield* pause;
189
- }
190
- yield* emit({
191
- _tag: "AssistantMessage",
192
- parts: [{ type: "text", text: finalText }],
193
- });
194
- yield* emit({
195
- _tag: "UsageChanged",
196
- tokens: Math.min(profile.contextWindow, 2400 * (turn + 1) + 900),
197
- contextWindow: profile.contextWindow,
198
- });
199
- yield* emit({
200
- _tag: "RunSettled",
201
- outcome: { _tag: "Completed", finalText },
202
- });
203
- });
204
-
205
- const queuedView = (): ReadonlyArray<QueuedMessage> =>
206
- state.pending.map((text) => ({ text, kind: "steer" as const }));
207
-
208
- // Driver: one turn at a time, in submission order. Turns run as child
209
- // fibers so interrupt() stops the turn without killing the driver.
210
- const driver = Effect.gen(function* () {
211
- while (true) {
212
- const text = yield* Queue.take(inbox);
213
- state.dispatching = true;
214
- state.pending.shift();
215
- yield* emit({ _tag: "QueueChanged", queued: queuedView() });
216
- yield* emit({ _tag: "UserMessage", text });
217
- const turn = state.turnCount++;
218
- const fiber = yield* Effect.forkChild(
219
- runTurn(text, turn).pipe(
220
- Effect.onInterrupt(() =>
221
- emit({
222
- _tag: "RunSettled",
223
- outcome: { _tag: "Interrupted" },
224
- }).pipe(Effect.ignore),
225
- ),
226
- ),
227
- );
228
- yield* Ref.set(activeTurn, fiber);
229
- state.dispatching = false;
230
- yield* Fiber.await(fiber);
231
- yield* Ref.set(activeTurn, undefined);
232
- }
233
- });
234
- yield* Effect.forkScoped(driver.pipe(Effect.ignore));
235
-
236
- yield* Effect.addFinalizer(() =>
237
- Effect.gen(function* () {
238
- state.closed = true;
239
- yield* Queue.end(inbox).pipe(Effect.ignore);
240
- yield* Queue.end(events).pipe(Effect.ignore);
241
- }),
242
- );
243
-
244
- const submit = (text: string) =>
245
- Effect.gen(function* () {
246
- if (state.closed) {
247
- return yield* new SendError({
248
- message: "Subagent session is closed.",
249
- });
250
- }
251
- state.pending.push(text);
252
- const busy = (yield* Ref.get(activeTurn)) !== undefined;
253
- if (busy) {
254
- // Show the queued steer line until the driver picks it up.
255
- yield* emit({ _tag: "QueueChanged", queued: queuedView() });
256
- }
257
- yield* Queue.offer(inbox, text);
258
- });
259
-
260
- // Announce metadata, then kick off the initial run.
261
- yield* Effect.try(() => fs.mkdirSync(STUB_DIR, { recursive: true })).pipe(
262
- Effect.ignore, // The fake session file directory is best-effort.
263
- );
264
- yield* emit({ _tag: "MetaChanged", meta: state.meta });
265
- // The session cannot be closed yet, so the initial submit cannot fail.
266
- yield* submit(task.prompt).pipe(Effect.orDie);
267
-
268
- return {
269
- meta: Effect.sync(() => state.meta),
270
- events: Stream.fromQueue(events),
271
- send: submit,
272
- interrupt: Effect.gen(function* () {
273
- // Drop queued prompts so interrupting cannot immediately start
274
- // another turn, then stop the active turn. A prompt may be mid-flight
275
- // between the driver dequeuing it and registering its fiber, so wait
276
- // that window out instead of silently missing the turn.
277
- const cleared = yield* Queue.clear(inbox).pipe(
278
- Effect.orElseSucceed(() => []),
279
- );
280
- state.pending = [];
281
- yield* emit({ _tag: "QueueChanged", queued: [] });
282
- while (true) {
283
- const fiber = yield* Ref.get(activeTurn);
284
- if (fiber) {
285
- yield* Fiber.interrupt(fiber);
286
- return;
287
- }
288
- if (!state.dispatching) {
289
- // No turn ever started. If we cancelled queued prompts, the run
290
- // still needs a terminal event or it would look running forever.
291
- if (cleared.length > 0) {
292
- yield* emit({
293
- _tag: "RunSettled",
294
- outcome: { _tag: "Interrupted" },
295
- });
296
- }
297
- return;
298
- }
299
- yield* Effect.sleep(Duration.millis(5));
300
- }
301
- }),
302
- } satisfies SubagentSession;
303
- });