@zq-silk/yui 2.20.0 → 2.22.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 +5 -0
- package/dist/cli/commandCatalog.js +88 -28
- package/dist/cli/dynamicCompletion.js +4 -1
- package/dist/cli/helpRenderer.js +12 -1
- package/dist/cli/interactionPolicy.js +2 -0
- package/dist/cli/invocationAuthority.js +2 -6
- package/dist/cli/invocationRouter.js +5 -5
- package/dist/cli/managedDiagnostics.js +24 -16
- package/dist/cli/roleWizard.js +5 -1
- package/dist/commands/durableJobCommands.js +2 -3
- package/dist/commands/globalRoleCommands.js +33 -8
- package/dist/commands/inboxCommands.js +39 -12
- package/dist/commands/operatorCommands.js +2 -5
- package/dist/commands/releaseCommands.js +16 -2
- package/dist/commands/roleConfiguration.js +25 -2
- package/dist/commands/sessionCommands.js +5 -2
- package/dist/commands/taskCommands.js +225 -99
- package/dist/commands/taskContextCommand.js +26 -4
- package/dist/commands/taskFactCommands.js +20 -7
- package/dist/commands/taskIntegrationCommands.js +3 -3
- package/dist/commands/taskRoleRuntimeStatus.js +15 -5
- package/dist/commands/taskUsageCommand.js +2 -6
- package/dist/commands/textInput.js +2 -2
- package/dist/context/contextFamilies.js +10 -0
- package/dist/context/currentSkills.js +6 -4
- package/dist/context/runContextPack.js +44 -5
- package/dist/context/runInputContract.js +1 -1
- package/dist/context/sessionBootstrapManifest.js +7 -5
- package/dist/context/sessionSkillNotice.js +53 -0
- package/dist/context/taskCatalog.js +4 -13
- package/dist/context/taskContext.js +135 -103
- package/dist/context/taskSearch.js +3 -7
- package/dist/controlPlaneCli.js +23 -25
- package/dist/controller/agentRuntimeObserver.js +57 -12
- package/dist/controller/clientRuntime.js +37 -8
- package/dist/controller/controller.js +3 -1
- package/dist/controller/diagnosticJournal.js +10 -2
- package/dist/controller/fileSchedulerStoreAdapter.js +72 -24
- package/dist/controller/jobClient.js +2 -2
- package/dist/controller/jobControl.js +2 -2
- package/dist/controller/jobDefinitionControl.js +5 -1
- package/dist/controller/messageHealth.js +4 -3
- package/dist/controller/providerRetryAdmission.js +15 -1
- package/dist/controller/providerRetryDelivery.js +18 -2
- package/dist/controller/runtime.js +15 -5
- package/dist/controller/runtimeEventInbox.js +107 -13
- package/dist/controller/runtimeEventProcessor.js +3 -3
- package/dist/controller/taskRunRecovery.js +153 -0
- package/dist/core/controllerClient.js +16 -2
- package/dist/core/controllerServer.js +14 -5
- package/dist/core/controllerTelemetry.js +51 -5
- package/dist/errors/cliFailure.js +14 -5
- package/dist/executor/agentAdapter.js +32 -4
- package/dist/executor/agentConfigurationFields.js +2 -0
- package/dist/executor/taskAgentCapabilities.js +2 -2
- package/dist/integration/gitIntegrationService.js +3 -2
- package/dist/integration/integrationSourceApplication.js +12 -1
- package/dist/interaction/notificationPresentation.js +11 -16
- package/dist/interaction/operatorPresentation.js +1 -1
- package/dist/message/messageContinuation.js +3 -1
- package/dist/output/boundedRead.js +36 -7
- package/dist/output/rolePresentation.js +3 -1
- package/dist/runtime/agentHost.js +12 -3
- package/dist/runtime/codexAppServerRuntime.js +110 -24
- package/dist/runtime/codexInteractiveHost.js +46 -0
- package/dist/runtime/providerRetry.js +5 -2
- package/dist/runtime/providerRuntimeIdentity.js +1 -1
- package/dist/runtime/structuredProviderHost.js +32 -34
- package/dist/scheduler/wakeupQueue.js +10 -4
- package/dist/storage/sqliteSchema.js +9 -0
- package/dist/storage/storageVersions.js +1 -1
- package/dist/task/taskAuthority.js +7 -3
- package/dist/tmux/tmuxManager.js +4 -2
- package/dist/web/webSettings.js +2 -0
- package/docs/authorization.md +18 -3
- package/docs/cli-information-contract.md +245 -6
- package/docs/cli-information-contract.zh-CN.md +107 -5
- package/docs/managed-turn-and-session-runtime.md +82 -21
- package/docs/managed-turn-and-session-runtime.zh-CN.md +56 -13
- package/docs/provider-retry.md +11 -0
- package/docs/release-workflow.md +62 -0
- package/docs/release-workflow.zh-CN.md +46 -0
- package/docs/roles-and-configuration.md +28 -0
- package/docs/roles-and-configuration.zh-CN.md +21 -0
- package/docs/storage-baseline.md +4 -1
- package/docs/storage-baseline.zh-CN.md +1 -1
- package/docs/task-delivery.md +7 -0
- package/docs/task-delivery.zh-CN.md +5 -0
- package/docs/task-discovery.md +5 -5
- package/docs/task-discovery.zh-CN.md +4 -4
- package/docs/testing/review-evaluation.md +7 -7
- package/docs/testing/review-evaluation.zh-CN.md +7 -7
- package/docs/testing/verification-levels.md +45 -2
- package/docs/testing/verification-levels.zh-CN.md +21 -2
- package/i18n/README.zh-CN.md +6 -0
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +98 -189
- package/skills/yui-leader/VERSION +1 -1
- package/skills/yui-leader/references/artifacts.md +41 -0
- package/skills/yui-leader/references/assignment-execution.md +140 -0
- package/skills/yui-leader/references/completion.md +79 -0
- package/skills/yui-leader/references/delivery-scope.md +26 -0
- package/skills/yui-leader/references/execution.md +16 -487
- package/skills/yui-leader/references/implementation.md +81 -0
- package/skills/yui-leader/references/planning.md +7 -45
- package/skills/yui-leader/references/review.md +90 -0
- package/skills/yui-leader/references/task-progress.md +23 -0
- package/skills/yui-leader/references/work-allocation.md +118 -0
- package/skills/yui-operator/SKILL.md +77 -331
- package/skills/yui-operator/VERSION +1 -1
- package/skills/yui-operator/references/body-transport.md +62 -0
- package/skills/yui-operator/references/configuration.md +47 -0
- package/skills/yui-operator/references/lifecycle.md +41 -0
- package/skills/yui-operator/references/progress.md +39 -0
- package/skills/yui-operator/references/routing.md +57 -0
- package/skills/yui-operator/references/submission.md +56 -0
- package/skills/yui-operator/references/task-delivery.md +5 -2
- package/skills/yui-operator/references/web-lifecycle.md +19 -0
- package/skills/yui-operator/scripts/verify-submission.mjs +37 -0
- package/skills/yui-reviewer/SKILL.md +4 -2
- package/skills/yui-reviewer/VERSION +1 -1
- package/skills/yui-runtime/SKILL.md +177 -505
- package/skills/yui-runtime/VERSION +1 -1
- package/skills/yui-runtime/references/archive.md +51 -0
- package/skills/yui-runtime/references/command-discovery.md +41 -0
- package/skills/yui-runtime/references/completed-followup.md +65 -0
- package/skills/yui-runtime/references/context-ordering.md +3 -34
- package/skills/yui-runtime/references/context-reads.md +61 -0
- package/skills/yui-runtime/references/dispatched-run.md +61 -0
- package/skills/yui-runtime/references/execution-failure.md +105 -0
- package/skills/yui-runtime/references/global-context.md +18 -0
- package/skills/yui-runtime/references/global-input-controls.md +44 -0
- package/skills/yui-runtime/references/host-custody.md +30 -0
- package/skills/yui-runtime/references/inbox-recovery.md +77 -0
- package/skills/yui-runtime/references/incremental-context.md +40 -0
- package/skills/yui-runtime/references/publication.md +4 -104
- package/skills/yui-runtime/references/recovery.md +32 -192
- package/skills/yui-runtime/references/session-identity.md +18 -0
- package/skills/yui-runtime/references/session-replacement.md +45 -0
- package/skills/yui-runtime/references/uncertain-execution.md +29 -0
- package/skills/yui-worker/SKILL.md +7 -4
- package/skills/yui-worker/VERSION +1 -1
|
@@ -4,6 +4,7 @@ import { once } from "node:events";
|
|
|
4
4
|
import WebSocket, { WebSocketServer } from "ws";
|
|
5
5
|
import { AGENT_HOST_CONTROL_PROTOCOL } from "./agentHostProtocol.js";
|
|
6
6
|
import { openCodexInteractiveConnection } from "./structuredProviderHost.js";
|
|
7
|
+
import { createSessionSkillNotice } from "../context/sessionSkillNotice.js";
|
|
7
8
|
/**
|
|
8
9
|
* Keep the native TUI and its transparent App Server attachment in one pane.
|
|
9
10
|
* The existing Host acknowledgement carries the ID from that TUI's exact
|
|
@@ -15,6 +16,8 @@ import { openCodexInteractiveConnection } from "./structuredProviderHost.js";
|
|
|
15
16
|
*/
|
|
16
17
|
export async function runCodexInteractiveHost(home, payload, openAgentHostControl) {
|
|
17
18
|
const environment = payload.environment;
|
|
19
|
+
const skillNotice = createSessionSkillNotice(home);
|
|
20
|
+
const pendingNotices = new Map();
|
|
18
21
|
if (environment.YUI_SESSION_SCOPE !== "global" || environment.YUI_ADAPTER_ID !== "codex"
|
|
19
22
|
|| payload.providerControl !== undefined) {
|
|
20
23
|
throw new Error("Interactive Codex Host requires a global native TUI launch.");
|
|
@@ -106,6 +109,23 @@ export async function runCodexInteractiveHost(home, payload, openAgentHostContro
|
|
|
106
109
|
startupRequestId = message.id;
|
|
107
110
|
message.params = codexInteractiveStartupParameters(payload, params);
|
|
108
111
|
}
|
|
112
|
+
if (message.method === "turn/start" || message.method === "turn/steer") {
|
|
113
|
+
if (snapshot.nativeSessionId === undefined)
|
|
114
|
+
throw new Error("Skill check requires the reserved native Thread.");
|
|
115
|
+
if (typeof message.id !== "string" && typeof message.id !== "number"
|
|
116
|
+
|| pendingNotices.has(message.id))
|
|
117
|
+
throw new Error("Turn input requires a unique correlation id.");
|
|
118
|
+
const params = jsonObject(message.params);
|
|
119
|
+
if (params.threadId !== snapshot.nativeSessionId)
|
|
120
|
+
throw new Error("Turn input targets another Thread.");
|
|
121
|
+
const prepared = codexInteractiveSkillInput(skillNotice, environment, snapshot.nativeSessionId, params);
|
|
122
|
+
message.params = prepared.params;
|
|
123
|
+
pendingNotices.set(message.id, {
|
|
124
|
+
commit: prepared.commit,
|
|
125
|
+
...(message.method === "turn/steer" && typeof params.expectedTurnId === "string"
|
|
126
|
+
? { expectedTurnId: params.expectedTurnId } : {})
|
|
127
|
+
});
|
|
128
|
+
}
|
|
109
129
|
void connection.send(message).catch(fail);
|
|
110
130
|
}
|
|
111
131
|
catch (error) {
|
|
@@ -115,6 +135,17 @@ export async function runCodexInteractiveHost(home, payload, openAgentHostContro
|
|
|
115
135
|
});
|
|
116
136
|
connection.onMessage((message) => {
|
|
117
137
|
try {
|
|
138
|
+
if (message.method === undefined && (typeof message.id === "string" || typeof message.id === "number")) {
|
|
139
|
+
const pending = pendingNotices.get(message.id);
|
|
140
|
+
if (pending !== undefined) {
|
|
141
|
+
pendingNotices.delete(message.id);
|
|
142
|
+
const result = message.result;
|
|
143
|
+
const turnId = result?.turn?.id ?? result?.turnId;
|
|
144
|
+
if (message.error === undefined && typeof turnId === "string" && turnId.length > 0
|
|
145
|
+
&& (pending.expectedTurnId === undefined || pending.expectedTurnId === turnId))
|
|
146
|
+
pending.commit();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
118
149
|
let nativeSessionId;
|
|
119
150
|
if (startupRequestId !== undefined && message.id === startupRequestId
|
|
120
151
|
&& message.method === undefined) {
|
|
@@ -183,6 +214,21 @@ export async function runCodexInteractiveHost(home, payload, openAgentHostContro
|
|
|
183
214
|
await control.close();
|
|
184
215
|
}
|
|
185
216
|
}
|
|
217
|
+
/** Preserve all native content parts (including images), adding only Host metadata. */
|
|
218
|
+
export function codexInteractiveSkillInput(notice, environment, nativeSessionId, params) {
|
|
219
|
+
if (!Array.isArray(params.input))
|
|
220
|
+
throw new Error("Turn input must be an array.");
|
|
221
|
+
const prepared = notice.prepare("", environment, nativeSessionId);
|
|
222
|
+
return {
|
|
223
|
+
params: {
|
|
224
|
+
...params,
|
|
225
|
+
input: prepared.text.length === 0 ? params.input : [
|
|
226
|
+
{ type: "text", text: prepared.text.trimEnd(), text_elements: [] }, ...params.input
|
|
227
|
+
]
|
|
228
|
+
},
|
|
229
|
+
commit: prepared.commit
|
|
230
|
+
};
|
|
231
|
+
}
|
|
186
232
|
/** The remote TUI can omit local launch configuration. Apply the reserved
|
|
187
233
|
* workspace and managed identity on its actual startup, never by starting a
|
|
188
234
|
* second Thread or changing daemon-wide configuration. */
|
|
@@ -211,7 +211,7 @@ export function providerRetryProjection(binding) {
|
|
|
211
211
|
}
|
|
212
212
|
/** Entry-point facts, never accumulated retry history or raw diagnostics.
|
|
213
213
|
* Exact Session retry/show and failureRef retain the original evidence. */
|
|
214
|
-
export function providerRetrySummary(binding) {
|
|
214
|
+
export function providerRetrySummary(binding, detailCommand) {
|
|
215
215
|
const view = providerRetryProjection(binding);
|
|
216
216
|
if (view === null)
|
|
217
217
|
return null;
|
|
@@ -224,7 +224,10 @@ export function providerRetrySummary(binding) {
|
|
|
224
224
|
currentTurn: currentTurn === null ? null : {
|
|
225
225
|
attemptId: currentTurn.attemptId, status: currentTurn.status, nativeTurnId: currentTurn.nativeTurnId
|
|
226
226
|
},
|
|
227
|
-
historyCount: history.length, detailOmitted: true
|
|
227
|
+
historyCount: history.length, detailOmitted: true,
|
|
228
|
+
// This reads current Session evidence, not a frozen Run snapshot. The
|
|
229
|
+
// returned chain/attempt identities must still be compared by the caller.
|
|
230
|
+
...(detailCommand === undefined ? {} : { currentDetailCommand: detailCommand })
|
|
228
231
|
};
|
|
229
232
|
}
|
|
230
233
|
export function controlProviderRetry(binding, action, at) {
|
|
@@ -462,7 +462,7 @@ function orderedRunTimestamp(run, value, label) {
|
|
|
462
462
|
}
|
|
463
463
|
return normalized;
|
|
464
464
|
}
|
|
465
|
-
function providerTurnIsActive(run) {
|
|
465
|
+
export function providerTurnIsActive(run) {
|
|
466
466
|
return run !== null && ["submitting", "accepted", "delivery-unknown"]
|
|
467
467
|
.includes(run.status);
|
|
468
468
|
}
|
|
@@ -31,7 +31,7 @@ export async function startStructuredProviderSession(payload, input = {}) {
|
|
|
31
31
|
if (control.adapterId === "codex" && control.transport === "codex-app-server-proxy") {
|
|
32
32
|
const proxy = await connectCodexProxy(payload, mirror, true);
|
|
33
33
|
try {
|
|
34
|
-
const opened = await CodexStructuredProviderSession.open(proxy.child, proxy.exit, proxy.processInstanceId, payload, control, proxy.channel, input.onStarted, input.onTerminal, input.onGoal, input.onInput, input.onActivity,
|
|
34
|
+
const opened = await CodexStructuredProviderSession.open(proxy.child, proxy.exit, proxy.processInstanceId, payload, control, proxy.channel, input.onStarted, input.onTerminal, input.onGoal, input.onInput, input.onActivity, mirror);
|
|
35
35
|
return Object.freeze({
|
|
36
36
|
session: opened.session,
|
|
37
37
|
...(opened.recoveredTerminal === undefined
|
|
@@ -238,7 +238,10 @@ class CodexProxyWebSocketChannel {
|
|
|
238
238
|
this.#pending.delete(id);
|
|
239
239
|
reject(new Error(`Provider request timed out: ${method}.`));
|
|
240
240
|
}, PROVIDER_ACCEPT_TIMEOUT_MS);
|
|
241
|
-
this.#pending.set(id, {
|
|
241
|
+
this.#pending.set(id, {
|
|
242
|
+
resolve: resolvePromise, reject, timer, method,
|
|
243
|
+
requestBytes: Buffer.byteLength(JSON.stringify({ id, method, params }), "utf8")
|
|
244
|
+
});
|
|
242
245
|
});
|
|
243
246
|
try {
|
|
244
247
|
await this.send({ id, method, params });
|
|
@@ -282,7 +285,7 @@ class CodexProxyWebSocketChannel {
|
|
|
282
285
|
if (isBinary || encoded.byteLength > PROVIDER_MESSAGE_MAX_BYTES) {
|
|
283
286
|
this.#close(new Error(isBinary
|
|
284
287
|
? "Provider returned an unsupported binary WebSocket message."
|
|
285
|
-
:
|
|
288
|
+
: `Provider response message exceeds its bound (receivedBytes=${encoded.byteLength}).`));
|
|
286
289
|
terminateProcessGroup(this.child, "SIGTERM");
|
|
287
290
|
return;
|
|
288
291
|
}
|
|
@@ -320,6 +323,15 @@ class CodexProxyWebSocketChannel {
|
|
|
320
323
|
#close(error) {
|
|
321
324
|
if (this.#closedError !== undefined)
|
|
322
325
|
return;
|
|
326
|
+
// A rejected WebSocket frame has not reached #receive: its full size and
|
|
327
|
+
// response/notification identity are unknown. Record pending request
|
|
328
|
+
// metadata, not parameters or transcript bytes, and never blame a specific
|
|
329
|
+
// response just because that request was in flight.
|
|
330
|
+
const pendingMetadata = [...this.#pending].slice(0, 8).map(([id, pending]) => ({
|
|
331
|
+
id, method: pending.method, requestBytes: pending.requestBytes
|
|
332
|
+
}));
|
|
333
|
+
error = new Error(`Codex proxy transport closed: ${error.message}; messageLimitBytes=${PROVIDER_MESSAGE_MAX_BYTES}; `
|
|
334
|
+
+ `pendingRequests=${JSON.stringify(pendingMetadata)}; pendingCount=${this.#pending.size}.`, { cause: error });
|
|
323
335
|
this.#closedError = error;
|
|
324
336
|
if (!this.#ready)
|
|
325
337
|
this.#rejectReady(error);
|
|
@@ -410,7 +422,7 @@ class CodexStructuredProviderSession {
|
|
|
410
422
|
this.mirror = mirror;
|
|
411
423
|
this.nativeAccountHome = nativeAccountHome;
|
|
412
424
|
}
|
|
413
|
-
static async open(child, exit, processInstanceId, payload, control, channel, onStarted, onTerminal, onGoal, onInput, onActivity,
|
|
425
|
+
static async open(child, exit, processInstanceId, payload, control, channel, onStarted, onTerminal, onGoal, onInput, onActivity, mirror) {
|
|
414
426
|
const openingMessages = [];
|
|
415
427
|
const stopOpeningBuffer = channel.onMessage((message) => openingMessages.push(message));
|
|
416
428
|
const initialized = await channel.request("initialize", codexClientInitialization());
|
|
@@ -419,7 +431,6 @@ class CodexStructuredProviderSession {
|
|
|
419
431
|
let conversationId;
|
|
420
432
|
let nativeConfiguration;
|
|
421
433
|
let resumedActiveTurnId;
|
|
422
|
-
let resumedTurns = [];
|
|
423
434
|
if (control.mode === "new") {
|
|
424
435
|
const opened = await runtime.openConversation({
|
|
425
436
|
cwd: payload.cwd,
|
|
@@ -437,7 +448,6 @@ class CodexStructuredProviderSession {
|
|
|
437
448
|
conversationId = resumed.threadId;
|
|
438
449
|
nativeConfiguration = resumed.raw;
|
|
439
450
|
resumedActiveTurnId = resumed.activeTurnId;
|
|
440
|
-
resumedTurns = resumed.turns;
|
|
441
451
|
}
|
|
442
452
|
catch (error) {
|
|
443
453
|
if (codexAppServerErrorIsMissing(error)) {
|
|
@@ -446,37 +456,25 @@ class CodexStructuredProviderSession {
|
|
|
446
456
|
throw error;
|
|
447
457
|
}
|
|
448
458
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
await runtime.setConversationName({
|
|
459
|
-
conversationId,
|
|
460
|
-
name: control.sessionTitle
|
|
461
|
-
});
|
|
462
|
-
appliedGeneratedTitle = control.sessionTitle;
|
|
463
|
-
}
|
|
464
|
-
catch (error) {
|
|
465
|
-
onDiagnostic?.({
|
|
466
|
-
nativeSessionId: conversationId,
|
|
467
|
-
failure: providerDeliveryFailureFrom(error, {
|
|
468
|
-
phase: "session-start",
|
|
469
|
-
inputDisposition: "not-accepted",
|
|
470
|
-
sessionDisposition: "recoverable"
|
|
471
|
-
})
|
|
472
|
-
});
|
|
473
|
-
}
|
|
459
|
+
if (control.sessionTitle !== undefined) {
|
|
460
|
+
// The native title mutation can persist without replying and stall later
|
|
461
|
+
// Goal/Turn requests, even through a separate metadata connection. Keep
|
|
462
|
+
// Yui's launch title, but do not put that optional mutation on a managed
|
|
463
|
+
// Session's execution path. Reconnect must not replay it either.
|
|
464
|
+
// This is an intentional omission, not a failed delivery or unavailable
|
|
465
|
+
// observer. Keep it in the Host log without waking an Agent to recover
|
|
466
|
+
// an operation that was never attempted.
|
|
467
|
+
mirror("stderr", "Native title synchronization was not submitted; Yui retains its Session title without blocking native Goal/Turn control.\n");
|
|
474
468
|
}
|
|
469
|
+
const ownedTurn = control.kind === "restore" ? control.ownedTurn : undefined;
|
|
470
|
+
// Keep notifications buffered during paginated recovery. Otherwise a live
|
|
471
|
+
// terminal can be emitted before open returns and then returned again as a
|
|
472
|
+
// synthetic recovered terminal, or a newer start can be overwritten.
|
|
473
|
+
const recoveredOwnedTurn = ownedTurn !== undefined && resumedActiveTurnId !== ownedTurn.turnId
|
|
474
|
+
? await runtime.readTurn(conversationId, ownedTurn.turnId) : undefined;
|
|
475
475
|
const session = new CodexStructuredProviderSession(child, exit, processInstanceId, conversationId, runtime, onStarted, onTerminal, onGoal, onInput, onActivity, mirror, optionalId(initialized.codexHome));
|
|
476
476
|
session.nativeAccess = createCodexNativeAccess(conversationId, initialized, channel, openingMessages, nativeConfiguration);
|
|
477
|
-
session.appliedGeneratedTitle = appliedGeneratedTitle;
|
|
478
477
|
session.#activeTurnId = resumedActiveTurnId;
|
|
479
|
-
const ownedTurn = control.kind === "restore" ? control.ownedTurn : undefined;
|
|
480
478
|
session.#clientOwnedTurnId = ownedTurn?.turnId;
|
|
481
479
|
session.#clientOwnedAttemptId = ownedTurn?.attemptId;
|
|
482
480
|
if (ownedTurn !== undefined)
|
|
@@ -493,7 +491,7 @@ class CodexStructuredProviderSession {
|
|
|
493
491
|
});
|
|
494
492
|
if (ownedTurn !== undefined && recoveredTerminal === undefined
|
|
495
493
|
&& session.#activeTurnId !== ownedTurn.turnId) {
|
|
496
|
-
const recovered =
|
|
494
|
+
const recovered = recoveredOwnedTurn;
|
|
497
495
|
if (recovered?.status === "completed"
|
|
498
496
|
|| recovered?.status === "interrupted"
|
|
499
497
|
|| recovered?.status === "failed") {
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { enqueueWork } from "../coordination/workMailboxQueue.js";
|
|
2
2
|
/** The caller's TaskStore transaction owns this read/merge/write operation. */
|
|
3
3
|
export function queueLeaderWakeup(store, taskId, reason, now) {
|
|
4
4
|
if (store.getTask(taskId)?.status === "archived")
|
|
5
5
|
return null;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
// The scheduler's pending-wakeup projection may expose an already-owned
|
|
7
|
+
// processing prefix. Append to the actual suffix, never write that read
|
|
8
|
+
// projection back over independent inputs.
|
|
9
|
+
const pending = enqueueWork(store, { kind: "role", taskId, roleName: "leader" }, reason, now).pending;
|
|
10
|
+
return {
|
|
11
|
+
schemaVersion: 1, taskId, reasons: [...pending.reasons],
|
|
12
|
+
requestCount: pending.requestCount,
|
|
13
|
+
firstRequestedAt: pending.firstQueuedAt, lastRequestedAt: pending.lastQueuedAt
|
|
14
|
+
};
|
|
9
15
|
}
|
|
@@ -286,6 +286,15 @@ const MINOR_UPGRADES = Object.freeze([{
|
|
|
286
286
|
// Optional Role presentation and generated-title provenance. Never infer
|
|
287
287
|
// ownership of historical titles, rewrite frozen profiles, or fill defaults.
|
|
288
288
|
sql: ""
|
|
289
|
+
}, {
|
|
290
|
+
fromVersion: "1.25",
|
|
291
|
+
toVersion: "1.26",
|
|
292
|
+
name: "codex-workspace-temp-exclusions",
|
|
293
|
+
introducedIn: "next",
|
|
294
|
+
sourceChecksum: CURRENT_SCHEMA_CHECKSUM,
|
|
295
|
+
targetChecksum: CURRENT_SCHEMA_CHECKSUM,
|
|
296
|
+
// Optional workspace-write permission fields; preserve all existing payloads.
|
|
297
|
+
sql: ""
|
|
289
298
|
}]);
|
|
290
299
|
export function storageMinorUpgradePlan(from) {
|
|
291
300
|
if (from === CURRENT_STORAGE_VERSION)
|
|
@@ -146,10 +146,14 @@ export function projectActor(environment) {
|
|
|
146
146
|
}
|
|
147
147
|
return "user";
|
|
148
148
|
}
|
|
149
|
+
/** Read-only Job requests carry the original identity, not the record's owner.
|
|
150
|
+
* The Controller authenticates it; mutations keep resolveJobCaller's target check. */
|
|
151
|
+
export function resolveJobReadCaller(environment, taskId) {
|
|
152
|
+
return resolveJobCaller(environment, environment?.YUI_SESSION_SCOPE === "task" ? environment.YUI_TASK_ID ?? "" : taskId);
|
|
153
|
+
}
|
|
149
154
|
/**
|
|
150
|
-
* Resolve
|
|
151
|
-
*
|
|
152
|
-
* caller cannot control another Task; an incomplete identity is not a user.
|
|
155
|
+
* Resolve execution identity. The Controller verifies it against durable state;
|
|
156
|
+
* a Task caller cannot control another Task or infer user authority.
|
|
153
157
|
*/
|
|
154
158
|
export function resolveJobCaller(environment, taskId) {
|
|
155
159
|
const env = environment ?? {};
|
package/dist/tmux/tmuxManager.js
CHANGED
|
@@ -62,7 +62,9 @@ export class TmuxManager {
|
|
|
62
62
|
this.#yuiHome = options.yuiHome ?? process.env.YUI_HOME ?? process.cwd();
|
|
63
63
|
this.#serverName = yuiTmuxServerName(this.#yuiHome);
|
|
64
64
|
this.#onRoleTargetRecorded = options.onRoleTargetRecorded;
|
|
65
|
-
|
|
65
|
+
// Creating Node's stdin stream can make piped fd 0 nonblocking. Commands
|
|
66
|
+
// may still need to read that pipe synchronously before any attach.
|
|
67
|
+
this.#terminalInput = options.terminalInput;
|
|
66
68
|
this.#terminalType = usableInteractiveTerminal(options.terminalType ?? process.env.TERM);
|
|
67
69
|
this.#closeInteractiveInput = options.closeInteractiveInput ?? (() => { });
|
|
68
70
|
this.#readinessTimeoutMs = positiveInteger(options.readinessTimeoutMs, DEFAULT_READINESS_TIMEOUT_MS, "readiness timeout");
|
|
@@ -228,7 +230,7 @@ export class TmuxManager {
|
|
|
228
230
|
}
|
|
229
231
|
if (resolvedAccess === "read-write")
|
|
230
232
|
options.revalidateWritableAttach?.();
|
|
231
|
-
handoffTerminal(this.#terminalInput, this.#closeInteractiveInput);
|
|
233
|
+
handoffTerminal(this.#terminalInput ?? process.stdin, this.#closeInteractiveInput);
|
|
232
234
|
this.run([
|
|
233
235
|
"attach-session",
|
|
234
236
|
...(resolvedAccess === "read-only" ? ["-r"] : []),
|
package/dist/web/webSettings.js
CHANGED
|
@@ -276,6 +276,8 @@ const ROLE_FIELDS = {
|
|
|
276
276
|
model: { set: "--model", clear: "--clear-model" }, effort: { set: "--effort", clear: "--clear-effort" },
|
|
277
277
|
"permission.strategy": { set: "--permission-strategy" }, "permission.sandbox": { set: "--sandbox" },
|
|
278
278
|
"permission.approval": { set: "--approval" }, "permission.mode": { set: "--permission-mode" },
|
|
279
|
+
"permission.excludeTmpdirEnvVar": { set: "--exclude-tmpdir-env-var", clear: "--clear-exclude-tmpdir-env-var" },
|
|
280
|
+
"permission.excludeSlashTmp": { set: "--exclude-slash-tmp", clear: "--clear-exclude-slash-tmp" },
|
|
279
281
|
"permission.allowedTools": { set: "--allowed-tool", clear: "--clear-allowed-tools", many: true },
|
|
280
282
|
"permission.disallowedTools": { set: "--disallowed-tool", clear: "--clear-disallowed-tools", many: true },
|
|
281
283
|
search: { set: "--search", clear: "--clear-search" },
|
package/docs/authorization.md
CHANGED
|
@@ -20,9 +20,24 @@ authorization for any external effect.
|
|
|
20
20
|
| May it access an additional resource or irreversible effect? | `CapabilityGrant`, `grant/taskAuthorization.ts`, resource/plugin/release consumers | Task activation does not authorize arbitrary resources |
|
|
21
21
|
|
|
22
22
|
The full command inventory is generated from the catalog, not maintained as a
|
|
23
|
-
second per-command permissions table
|
|
24
|
-
`yui --json help task
|
|
25
|
-
|
|
23
|
+
second per-command permissions table. `yui --json help` and scoped
|
|
24
|
+
`yui --json help task` return the selected command's full details and all its
|
|
25
|
+
immediate child **summaries**, not a recursively expanded tree. The `discovery`
|
|
26
|
+
field labels this boundary and gives the detail and full-tree commands. Follow
|
|
27
|
+
each child's `path` with `yui --json help <command ...>` for full usage, options,
|
|
28
|
+
values and examples, or use `yui --json help [command ...] --recursive` for the
|
|
29
|
+
complete caller-filtered tree in one call.
|
|
30
|
+
|
|
31
|
+
This changes the default JSON help shape: consumers that previously traversed
|
|
32
|
+
nested `children` must request `--recursive`; absence of child details in the
|
|
33
|
+
default view is not proof that the child has no options or descendants.
|
|
34
|
+
Focused leaf details are unchanged, with additive discovery metadata.
|
|
35
|
+
Text help still shows immediate children; `--recursive` requires `--json`.
|
|
36
|
+
`config describe --json` and the offline
|
|
37
|
+
`describeCommandTree(discoveryCommandTree(env))` API retain full recursive
|
|
38
|
+
descriptions. Native `yui agent` product help is a separate surface and unchanged.
|
|
39
|
+
|
|
40
|
+
Complete role hints retain an offline template even without
|
|
26
41
|
a running Home; that is not authentication. Native-ID-only callers are resolved
|
|
27
42
|
from read-only local storage for help/completion; if that read fails the CLI shows
|
|
28
43
|
the restricted `unbound` template. No Controller or provider is started for that
|