@tt-a1i/openpi 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.
- package/README.md +643 -0
- package/SETUP.md +74 -0
- package/THIRD_PARTY_NOTICES.md +16 -0
- package/assets/openpi-package.png +0 -0
- package/assets/readme-hero-mobile.svg +72 -0
- package/assets/readme-hero.svg +118 -0
- package/assets/readme-runtime-mobile.svg +91 -0
- package/assets/readme-runtime.svg +111 -0
- package/extensions/ask-user/handoff.ts +205 -0
- package/extensions/ask-user/index.ts +1110 -0
- package/extensions/ask-user/limits.ts +89 -0
- package/extensions/ask-user/prompt.ts +76 -0
- package/extensions/background-terminals/index.ts +653 -0
- package/extensions/background-terminals/src/domain.ts +99 -0
- package/extensions/background-terminals/src/manager.ts +989 -0
- package/extensions/background-terminals/src/output.ts +84 -0
- package/extensions/background-terminals/src/prompt.ts +195 -0
- package/extensions/background-terminals/src/result-delivery.ts +43 -0
- package/extensions/background-terminals/src/runtime.ts +36 -0
- package/extensions/background-terminals/src/ui/output-view.ts +55 -0
- package/extensions/background-terminals/src/ui/ps.ts +642 -0
- package/extensions/background-terminals/src/ui/tool-result.ts +146 -0
- package/extensions/background-terminals/src/watch.ts +192 -0
- package/extensions/context-pivot/index.ts +222 -0
- package/extensions/copy-all/index.ts +65 -0
- package/extensions/cron/index.ts +173 -0
- package/extensions/cron/schedule.ts +127 -0
- package/extensions/file-mutation-display/index.ts +105 -0
- package/extensions/file-mutation-display/render.ts +107 -0
- package/extensions/file-search/index.ts +515 -0
- package/extensions/file-search/src/args.ts +129 -0
- package/extensions/file-search/src/binaries.ts +419 -0
- package/extensions/file-search/src/output.ts +142 -0
- package/extensions/file-search/src/process.ts +309 -0
- package/extensions/file-search/src/prompt.ts +53 -0
- package/extensions/git-info/index.ts +272 -0
- package/extensions/git-info/src/changed-files-view.ts +414 -0
- package/extensions/git-info/src/process.ts +107 -0
- package/extensions/git-info/src/refresh-coordinator.ts +13 -0
- package/extensions/git-info/src/runtime.ts +28 -0
- package/extensions/goal/controller.ts +794 -0
- package/extensions/goal/index.ts +521 -0
- package/extensions/goal/prompts.ts +122 -0
- package/extensions/goal/state.ts +763 -0
- package/extensions/goal/ui.ts +158 -0
- package/extensions/model-info/index.ts +234 -0
- package/extensions/plan-mode/bash-policy.ts +313 -0
- package/extensions/plan-mode/index.ts +539 -0
- package/extensions/post-edit/index.ts +129 -0
- package/extensions/sessions/LICENSE.upstream +21 -0
- package/extensions/sessions/git-stats.ts +226 -0
- package/extensions/sessions/index.ts +1092 -0
- package/extensions/sessions/sessions.ts +385 -0
- package/extensions/setup/index.ts +408 -0
- package/extensions/shared/activity-status.ts +65 -0
- package/extensions/shared/below-editor-navigation.ts +343 -0
- package/extensions/shared/child-session.ts +352 -0
- package/extensions/shared/context-utilization.ts +47 -0
- package/extensions/shared/dashboard-state.ts +102 -0
- package/extensions/shared/plan-mode-state.ts +65 -0
- package/extensions/shared/setup-config.ts +971 -0
- package/extensions/shared/subagent-roles.ts +22 -0
- package/extensions/shared/terminal-text.ts +38 -0
- package/extensions/shared/tool-call-timeout.ts +104 -0
- package/extensions/shared/worktree.ts +526 -0
- package/extensions/subagents/index.ts +1225 -0
- package/extensions/subagents/navigation.ts +121 -0
- package/extensions/subagents/src/agent-types.ts +543 -0
- package/extensions/subagents/src/backend.ts +63 -0
- package/extensions/subagents/src/backends/pi.ts +493 -0
- package/extensions/subagents/src/backends/stub.ts +296 -0
- package/extensions/subagents/src/by-the-way.ts +21 -0
- package/extensions/subagents/src/domain.ts +271 -0
- package/extensions/subagents/src/format.ts +48 -0
- package/extensions/subagents/src/manager.ts +769 -0
- package/extensions/subagents/src/prompt.ts +190 -0
- package/extensions/subagents/src/result-delivery.ts +20 -0
- package/extensions/subagents/src/runtime.ts +51 -0
- package/extensions/subagents/src/ui/takeover.ts +615 -0
- package/extensions/subagents/src/ui/transcript.ts +293 -0
- package/extensions/subagents/src/ui/wait-result.ts +89 -0
- package/extensions/suggestions/index.ts +172 -0
- package/extensions/suggestions/src/config.ts +12 -0
- package/extensions/suggestions/src/predictor.ts +147 -0
- package/extensions/suggestions/src/prompt.ts +20 -0
- package/extensions/suggestions/src/transcript.ts +233 -0
- package/extensions/suggestions/src/ui.ts +224 -0
- package/extensions/tasks/index.ts +512 -0
- package/extensions/tasks/tasks.ts +649 -0
- package/extensions/tasks/ui.ts +421 -0
- package/extensions/turn-time/index.ts +61 -0
- package/extensions/ui-customization/footer.ts +512 -0
- package/extensions/ui-customization/index.ts +217 -0
- package/extensions/workflows/acceptance.ts +298 -0
- package/extensions/workflows/artifacts.ts +225 -0
- package/extensions/workflows/controller.ts +210 -0
- package/extensions/workflows/dashboard.ts +1226 -0
- package/extensions/workflows/index.ts +1884 -0
- package/extensions/workflows/journal.ts +188 -0
- package/extensions/workflows/meta.ts +250 -0
- package/extensions/workflows/model.ts +423 -0
- package/extensions/workflows/navigation.ts +93 -0
- package/extensions/workflows/prompt.ts +212 -0
- package/extensions/workflows/replay-safety.ts +577 -0
- package/extensions/workflows/runner.ts +786 -0
- package/extensions/workflows/sandbox-child.cjs +402 -0
- package/extensions/workflows/sandbox.ts +397 -0
- package/extensions/workflows/serialization.ts +162 -0
- package/extensions/workflows/worktree-handoff.ts +216 -0
- package/package.json +87 -0
- package/scripts/prepare-effect-tsgo.mjs +16 -0
- package/skills/background-terminals/SKILL.md +30 -0
- package/skills/subagents/SKILL.md +15 -0
- package/themes/github-dark-default.json +89 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { sanitizeTerminalText } from "../shared/terminal-text.ts";
|
|
2
|
+
|
|
3
|
+
export const MAX_ANSWER_DRAFT_UTF8_BYTES = 8_000;
|
|
4
|
+
|
|
5
|
+
function utf8BytesAtMost(value: string, maximum: number) {
|
|
6
|
+
let bytes = 0;
|
|
7
|
+
for (const character of value) {
|
|
8
|
+
const codePoint = character.codePointAt(0)!;
|
|
9
|
+
bytes +=
|
|
10
|
+
codePoint <= 0x7f
|
|
11
|
+
? 1
|
|
12
|
+
: codePoint <= 0x7ff
|
|
13
|
+
? 2
|
|
14
|
+
: codePoint <= 0xffff
|
|
15
|
+
? 3
|
|
16
|
+
: 4;
|
|
17
|
+
if (bytes > maximum) return undefined;
|
|
18
|
+
}
|
|
19
|
+
return bytes;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function answerDraftByteLength(value: string) {
|
|
23
|
+
return utf8BytesAtMost(value, Number.POSITIVE_INFINITY)!;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function answerDraftFits(value: string) {
|
|
27
|
+
return utf8BytesAtMost(value, MAX_ANSWER_DRAFT_UTF8_BYTES) !== undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function longerThanAnswerDraftLimit(next: string, previous: string) {
|
|
31
|
+
return answerDraftByteLength(next) > answerDraftByteLength(previous);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const BRACKETED_PASTE_START = "\u001b[200~";
|
|
35
|
+
export const BRACKETED_PASTE_END = "\u001b[201~";
|
|
36
|
+
// eslint-disable-next-line no-control-regex
|
|
37
|
+
const INPUT_CONTROL_PATTERN = /[\u0000-\u001f\u007f-\u009f]/;
|
|
38
|
+
|
|
39
|
+
function textBearingEditorInput(input: string) {
|
|
40
|
+
if (
|
|
41
|
+
input.startsWith(BRACKETED_PASTE_START) &&
|
|
42
|
+
input.endsWith(BRACKETED_PASTE_END)
|
|
43
|
+
) {
|
|
44
|
+
return {
|
|
45
|
+
bracketed: true,
|
|
46
|
+
text: input.slice(
|
|
47
|
+
BRACKETED_PASTE_START.length,
|
|
48
|
+
-BRACKETED_PASTE_END.length,
|
|
49
|
+
),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
// Escape-prefixed values and one-byte controls are editor commands. Other
|
|
53
|
+
// values are text, including non-bracketed multi-line/IME commits.
|
|
54
|
+
if (
|
|
55
|
+
input.startsWith("\u001b") ||
|
|
56
|
+
(input.length === 1 && INPUT_CONTROL_PATTERN.test(input))
|
|
57
|
+
) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
return { bracketed: false, text: input };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Strip terminal/bidi controls before text-bearing input reaches Editor. */
|
|
64
|
+
export function sanitizeAnswerDraftEditorInput(input: string) {
|
|
65
|
+
const insertion = textBearingEditorInput(input);
|
|
66
|
+
if (!insertion) return input;
|
|
67
|
+
const safe = sanitizeTerminalText(insertion.text);
|
|
68
|
+
return insertion.bracketed
|
|
69
|
+
? `${BRACKETED_PASTE_START}${safe}${BRACKETED_PASTE_END}`
|
|
70
|
+
: safe;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Reject text-bearing input before Editor stores a bracketed or bulk paste.
|
|
75
|
+
* Small control-key sequences are left to Editor and checked after handling.
|
|
76
|
+
*/
|
|
77
|
+
export function prospectiveAnswerDraftFits(current: string, input: string) {
|
|
78
|
+
const insertion = textBearingEditorInput(input);
|
|
79
|
+
if (!insertion && !answerDraftFits(input)) {
|
|
80
|
+
// Unknown large control-bearing input must not reach Editor's paste map.
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
if (!insertion) return true;
|
|
84
|
+
const remaining =
|
|
85
|
+
MAX_ANSWER_DRAFT_UTF8_BYTES - answerDraftByteLength(current);
|
|
86
|
+
return (
|
|
87
|
+
remaining >= 0 && utf8BytesAtMost(insertion.text, remaining) !== undefined
|
|
88
|
+
);
|
|
89
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { sanitizeTerminalText } from "../shared/terminal-text.ts";
|
|
2
|
+
|
|
3
|
+
interface AskUserAnswer {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly selected?: string;
|
|
6
|
+
readonly note?: string;
|
|
7
|
+
readonly custom?: string;
|
|
8
|
+
readonly rephrase?: true;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function safeSingleLine(value: string) {
|
|
12
|
+
return sanitizeTerminalText(value).replace(/\s+/g, " ").trim();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Model-facing schema descriptions for structured user questions. */
|
|
16
|
+
export const ASK_USER_PARAMETER_DESCRIPTIONS = {
|
|
17
|
+
id: "Stable snake_case identifier used to map the answer",
|
|
18
|
+
header: "Short UI header, ideally 12 characters or fewer",
|
|
19
|
+
optionLabel:
|
|
20
|
+
'Concise user-facing label. Put the recommended option first and suffix its label with "(Recommended)".',
|
|
21
|
+
optionDescription:
|
|
22
|
+
"One short sentence explaining the impact or tradeoff if selected",
|
|
23
|
+
optionPreview:
|
|
24
|
+
"Optional concrete artifact shown while this option is highlighted — a short code snippet, config, or ASCII layout the user can compare against the other options. Lines are shown as written (indentation preserved, no re-wrapping), so keep them narrow. Omit unless seeing the artifact genuinely changes the decision; the description already carries the tradeoff.",
|
|
25
|
+
question: "A single-sentence question shown to the user",
|
|
26
|
+
options:
|
|
27
|
+
"Between 2 and 5 mutually exclusive choices. Never include an Other/custom option; the UI adds one automatically.",
|
|
28
|
+
questions:
|
|
29
|
+
"One to three independent questions (see the tool guidelines for when to batch more than one).",
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const ASK_USER_TOOL_DESCRIPTION =
|
|
33
|
+
"Ask the user one to three short, independent multiple-choice questions and wait for explicitly reviewed answers. Each question gets a free-form answer option; submitting it blank requests a clearer or split question. The user may add notes, revise any draft answer from the review screen, or dismiss the request. Prefer one question unless several independent decisions should be answered together.";
|
|
34
|
+
|
|
35
|
+
export const ASK_USER_PROMPT_SNIPPET =
|
|
36
|
+
"Ask 1-3 structured user questions with draft answers, final review, optional notes, and free-form answers";
|
|
37
|
+
|
|
38
|
+
export const ASK_USER_PROMPT_GUIDELINES = [
|
|
39
|
+
"Use ask_user only for a genuine ambiguity or user preference that cannot be resolved from the code, docs, or conversation and would materially change the result. Never use it to ask whether to continue.",
|
|
40
|
+
'Before calling ask_user, analyze the choice: provide mutually exclusive options, put your recommendation first, suffix its label with "(Recommended)", and explain each option\'s impact or tradeoff.',
|
|
41
|
+
"Prefer one ask_user question. Include up to three only when the decisions are independent and batching them avoids unnecessary round trips.",
|
|
42
|
+
"For review findings that genuinely require user disposition, use one question per independent finding and batch at most three; do not ask about findings your instructions already authorize you to fix.",
|
|
43
|
+
"A blank free-form answer means the user wants the question rephrased or split. Do not treat it as consent, rejection, or an empty factual answer.",
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
export function buildAskUserResultMessage(
|
|
47
|
+
outcome:
|
|
48
|
+
| { kind: "no-ui" }
|
|
49
|
+
| { kind: "cancelled" }
|
|
50
|
+
| { kind: "dismissed" }
|
|
51
|
+
| { kind: "answered"; answers: readonly AskUserAnswer[] },
|
|
52
|
+
) {
|
|
53
|
+
switch (outcome.kind) {
|
|
54
|
+
case "no-ui":
|
|
55
|
+
return "No interactive UI is available, so the questions could not be shown. Ask the user in plain text instead.";
|
|
56
|
+
case "cancelled":
|
|
57
|
+
return "Cancelled";
|
|
58
|
+
case "dismissed":
|
|
59
|
+
return "User dismissed the questions without answering. Do not assume answers; proceed accordingly or ask differently.";
|
|
60
|
+
case "answered":
|
|
61
|
+
return `User answered:\n${outcome.answers
|
|
62
|
+
.map((answer) => {
|
|
63
|
+
const id = safeSingleLine(answer.id);
|
|
64
|
+
const value = answer.rephrase
|
|
65
|
+
? "[rephrase or split this question]"
|
|
66
|
+
: safeSingleLine(
|
|
67
|
+
answer.custom ?? answer.selected ?? "(unanswered)",
|
|
68
|
+
);
|
|
69
|
+
const note = answer.note
|
|
70
|
+
? ` — note: ${safeSingleLine(answer.note)}`
|
|
71
|
+
: "";
|
|
72
|
+
return `- ${id}: ${value}${note}`;
|
|
73
|
+
})
|
|
74
|
+
.join("\n")}`;
|
|
75
|
+
}
|
|
76
|
+
}
|