@piagent/platform 1.51.0 → 1.51.1
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/CHANGELOG.md +8 -0
- package/docs/command-reference-vietnamese.md +2 -2
- package/docs/distribution-standard.md +6 -6
- package/docs/operator-manual-vietnamese.md +7 -7
- package/docs/publishing-for-teams.md +1 -0
- package/docs/release-install-policy.md +2 -2
- package/docs/team-onboarding.md +2 -2
- package/docs-site/architecture.html +1 -1
- package/docs-site/assets/search-en.json +1 -1
- package/docs-site/assets/search-vi.json +1 -1
- package/docs-site/benchmark.html +1 -1
- package/docs-site/commands.html +1 -1
- package/docs-site/context-engine.html +1 -1
- package/docs-site/ecosystem.html +1 -1
- package/docs-site/en/architecture.html +1 -1
- package/docs-site/en/benchmark.html +1 -1
- package/docs-site/en/commands.html +1 -1
- package/docs-site/en/context-engine.html +1 -1
- package/docs-site/en/ecosystem.html +1 -1
- package/docs-site/en/index.html +9 -9
- package/docs-site/en/mcp-approval.html +1 -1
- package/docs-site/en/mcp-auth.html +1 -1
- package/docs-site/en/mcp-servers.html +1 -1
- package/docs-site/en/mcp.html +1 -1
- package/docs-site/en/permissions.html +1 -1
- package/docs-site/en/profiles.html +1 -1
- package/docs-site/en/quickstart.html +1 -1
- package/docs-site/en/runtime.html +1 -1
- package/docs-site/en/scope.html +1 -1
- package/docs-site/en/security.html +1 -1
- package/docs-site/en/team.html +1 -1
- package/docs-site/en/update.html +3 -3
- package/docs-site/en/whats-new.html +27 -18
- package/docs-site/en/windows.html +1 -1
- package/docs-site/en/workflows.html +1 -1
- package/docs-site/index.html +9 -9
- package/docs-site/mcp-approval.html +1 -1
- package/docs-site/mcp-auth.html +1 -1
- package/docs-site/mcp-servers.html +1 -1
- package/docs-site/mcp.html +1 -1
- package/docs-site/permissions.html +1 -1
- package/docs-site/profiles.html +1 -1
- package/docs-site/quickstart.html +1 -1
- package/docs-site/releases.json +21 -0
- package/docs-site/runtime.html +1 -1
- package/docs-site/scope.html +1 -1
- package/docs-site/security.html +1 -1
- package/docs-site/team.html +1 -1
- package/docs-site/update.html +3 -3
- package/docs-site/whats-new.html +27 -18
- package/docs-site/windows.html +1 -1
- package/docs-site/workflows.html +1 -1
- package/evals/private-holdout-v1/public-exposure.v2.json +1 -1
- package/package.json +1 -1
- package/packages/piagent-core/managed/check-questions.mjs +21 -11
- package/packages/piagent-core/package.json +1 -1
|
@@ -8,6 +8,10 @@ import { digestsOnce, knownFast, markCheckStart, missingSuites, pushQuestion, pu
|
|
|
8
8
|
// suite and before a push, on the dashboard card or in the Terminal. Bypass skips
|
|
9
9
|
// the questions about the work (it runs the tests that cover the change) but not
|
|
10
10
|
// the one before a push. With no screen nobody can answer: nothing is asked.
|
|
11
|
+
// A question nobody answers in UNANSWERED_MS (the member left the task running
|
|
12
|
+
// overnight) is taken back and the cheap answer goes on: only the tests that
|
|
13
|
+
// cover the change, and no push. Before this a turn waited until morning.
|
|
14
|
+
export const UNANSWERED_MS = 10 * 60_000;
|
|
11
15
|
|
|
12
16
|
// How much of the suite a test command covers: 'partial' (a filter, one file, one
|
|
13
17
|
// package), 'suite' (the whole test command) or null when it runs no tests.
|
|
@@ -82,14 +86,20 @@ function surfaceOf(self, ctx) {
|
|
|
82
86
|
const runner = self.session?.extensionRunner, ui = ctx ? ctx.hasUI && ctx.ui : runner?.hasUI?.() && runner.getUIContext?.();
|
|
83
87
|
return ui?.select && !ui[GATEWAY_UI] ? { ui } : null;
|
|
84
88
|
}
|
|
85
|
-
// The label picked, { other } for the member's own words, undefined for no
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
// The label picked, { other } for the member's own words, undefined for no
|
|
90
|
+
// answer (Esc, stopped, or nobody answered in time).
|
|
91
|
+
async function ask(surface, question, labels, signal, waitMs = UNANSWERED_MS) {
|
|
92
|
+
// A plain timer, not AbortSignal.timeout: the wait itself keeps the process up.
|
|
93
|
+
const expired = new AbortController(), timer = setTimeout(() => expired.abort(), waitMs);
|
|
94
|
+
const until = signal ? AbortSignal.any([signal, expired.signal]) : expired.signal;
|
|
95
|
+
try {
|
|
96
|
+
if (surface.ui) return await surface.ui.select(question, labels, { signal: until });
|
|
97
|
+
const questions = [{ header: 'Test', question, options: labels.map(label => ({ label, description: '' })), multiSelect: false }];
|
|
98
|
+
const answer = await memberQuestions.ask({ sessionId: surface.sessionId, toolCallId: `check-scope-${randomUUID()}`, questions, signal: until }).catch(() => null);
|
|
99
|
+
if (!answer || answer.skipped) return undefined;
|
|
100
|
+
const { selected, other } = answer.answers[0];
|
|
101
|
+
return other ? { other } : labels[selected[0]];
|
|
102
|
+
} finally { clearTimeout(timer); }
|
|
93
103
|
}
|
|
94
104
|
|
|
95
105
|
// At the end of a change: { choice: 'partial' | 'full' | 'skip', words? }, or null
|
|
@@ -99,7 +109,7 @@ export async function askCheckScope(self, { partPassed = false, signal } = {}) {
|
|
|
99
109
|
if (!surface) return null;
|
|
100
110
|
if (['bypass', 'always-bypass'].includes(effectivePermission(self))) return { choice: 'partial' };
|
|
101
111
|
const part = partPassed ? KEEP : PART;
|
|
102
|
-
const picked = await ask(surface, partPassed ? 'Code đã đổi, phần test liên quan đã pass. Có chạy toàn bộ test không?' : 'Code đã đổi, chưa chạy test. Chạy phần nào?', [part, FULL, NONE], signal);
|
|
112
|
+
const picked = await ask(surface, partPassed ? 'Code đã đổi, phần test liên quan đã pass. Có chạy toàn bộ test không?' : 'Code đã đổi, chưa chạy test. Chạy phần nào?', [part, FULL, NONE], signal, self.unansweredMs);
|
|
103
113
|
if (signal?.aborted) return null;
|
|
104
114
|
if (picked?.other) return { choice: 'partial', words: picked.other };
|
|
105
115
|
return { choice: picked === FULL ? 'full' : picked === NONE ? 'skip' : 'partial' };
|
|
@@ -133,7 +143,7 @@ async function holdOrLet(self, run, command, ctx, signal) {
|
|
|
133
143
|
const now = await digestOf('.'), repositories = pushRepositories(self, command), single = !repositories.length || repositories[0] === '.';
|
|
134
144
|
const missing = await missingSuites(digestOf, run, repositories.length ? repositories : ['.']);
|
|
135
145
|
if ((single ? run.suitePassedOn(now) : false) || !missing.length || (run.pushAllowedOn !== undefined && run.pushAllowedOn === now)) return;
|
|
136
|
-
const picked = await ask(surface, await pushQuestion(self, digestOf, run, repositories, missing), [PUSH_FULL, PUSH_NOW], signal);
|
|
146
|
+
const picked = await ask(surface, await pushQuestion(self, digestOf, run, repositories, missing), [PUSH_FULL, PUSH_NOW], signal, self.unansweredMs);
|
|
137
147
|
if (picked === PUSH_NOW) { run.pushAllowedOn = now; return; }
|
|
138
148
|
if (picked?.other) throw Error(WORDS_REASON(picked.other));
|
|
139
149
|
if (picked !== PUSH_FULL) throw Error(STOPPED_REASON);
|
|
@@ -144,7 +154,7 @@ async function holdOrLet(self, run, command, ctx, signal) {
|
|
|
144
154
|
const held = run.scopeHeld ??= new Set(), again = held.has(command); held.add(command);
|
|
145
155
|
if (effectivePermission(self) === 'bypass') { if (again || knownFast(self, command, suitePart(command))) return; throw Error(BYPASS_REASON); }
|
|
146
156
|
if (run.scopeChoice === 'partial' && !again) throw Error(PARTIAL_REASON);
|
|
147
|
-
const picked = await ask(surface, `Agent muốn chạy toàn bộ test: ${String(command).slice(0, 160)}`, [PART, FULL], signal);
|
|
157
|
+
const picked = await ask(surface, `Agent muốn chạy toàn bộ test: ${String(command).slice(0, 160)}`, [PART, FULL], signal, self.unansweredMs);
|
|
148
158
|
if (picked === FULL) { run.scopeChoice = 'full'; return; }
|
|
149
159
|
run.scopeChoice = 'partial';
|
|
150
160
|
throw Error(picked?.other ? WORDS_REASON(picked.other) : PARTIAL_REASON);
|