@zq-silk/yui 0.15.7 → 0.15.8
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/ARCHITECTURE.md +192 -399
- package/README.md +127 -1149
- package/dist/agent/adapterCatalog.js +15 -2
- package/dist/agent/agent.js +23 -3
- package/dist/agent/argumentPolicy.js +7 -1
- package/dist/agent/connectionPlan.js +62 -0
- package/dist/agent/executionComponents.js +158 -0
- package/dist/agent/launchEnvironment.js +31 -3
- package/dist/agent/managedRuntimeEnvironment.js +3 -5
- package/dist/{turn/turn.js → agentRun/agentRun.js} +166 -109
- package/dist/{turn/turnIdentity.js → agentRun/runIdentity.js} +4 -4
- package/dist/brief/taskBrief.js +12 -0
- package/dist/cli/agentConfigurationPicker.js +13 -0
- package/dist/cli/commandCatalog.js +157 -70
- package/dist/cli/interactionCandidates.js +5 -5
- package/dist/cli/interactionPolicy.js +38 -8
- package/dist/cli/invocationRouter.js +1 -1
- package/dist/cli/managedDiagnostics.js +28 -0
- package/dist/cli/operatorWizard.js +1 -7
- package/dist/cli/roleOptionOrder.js +27 -0
- package/dist/cli/roleWizard.js +50 -14
- package/dist/cli/updateOrchestrator.js +1 -1
- package/dist/cli/updatePorts.js +3 -4
- package/dist/cli.js +178 -95
- package/dist/commands/agentCommands.js +72 -14
- package/dist/commands/capabilityCommands.js +9 -6
- package/dist/commands/configCommands.js +20 -20
- package/dist/commands/deliveryGuardPreflight.js +2 -2
- package/dist/commands/executionAuditCommands.js +24 -24
- package/dist/commands/globalRoleCommands.js +1 -1
- package/dist/commands/grantCommands.js +4 -4
- package/dist/commands/operatorCommands.js +1 -7
- package/dist/commands/projectCommands.js +4 -4
- package/dist/commands/resourcesCommands.js +2 -2
- package/dist/commands/roleConfiguration.js +25 -5
- package/dist/commands/roleRuntimeGuard.js +4 -5
- package/dist/commands/sessionCommands.js +3 -7
- package/dist/commands/taskActivationCommands.js +259 -0
- package/dist/commands/taskActor.js +28 -49
- package/dist/commands/taskCommands.js +1188 -710
- package/dist/commands/taskContextCommand.js +39 -583
- package/dist/commands/taskExecutionCommands.js +32 -32
- package/dist/commands/taskInputCommands.js +40 -104
- package/dist/commands/taskIntegrationCommands.js +3 -2
- package/dist/commands/taskIntegrationQueueCommands.js +1 -1
- package/dist/commands/taskNextActionCommand.js +8 -8
- package/dist/commands/taskOverviewCommand.js +33 -45
- package/dist/commands/taskRemoteDeliveryCommand.js +2 -2
- package/dist/commands/taskRoleRuntimeStatus.js +133 -102
- package/dist/commands/telemetryCommands.js +36 -38
- package/dist/config/configCatalog.js +4 -4
- package/dist/config/yuiConfig.js +8 -8
- package/dist/context/contextSnapshot.js +10 -10
- package/dist/context/dispatchContext.js +11 -11
- package/dist/context/roleSessionContext.js +6 -3
- package/dist/context/{turnContextPack.js → runContextPack.js} +146 -81
- package/dist/context/{turnInputContract.js → runInputContract.js} +73 -60
- package/dist/context/sessionBootstrapManifest.js +21 -2
- package/dist/context/sourceRunContext.js +30 -0
- package/dist/context/taskContext.js +458 -0
- package/dist/context/wakeNotification.js +27 -27
- package/dist/controller/agentRuntimeObserver.js +21 -24
- package/dist/controller/capabilityBridge.js +17 -6
- package/dist/controller/clientRuntime.js +65 -92
- package/dist/controller/controller.js +114 -188
- package/dist/controller/fileSchedulerStoreAdapter.js +787 -887
- package/dist/controller/jobControl.js +54 -85
- package/dist/controller/resourceInventory.js +8 -27
- package/dist/controller/resourceInventoryLinux.js +12 -13
- package/dist/controller/runtime.js +529 -479
- package/dist/controller/runtimeEventInbox.js +55 -25
- package/dist/controller/runtimeEventProcessor.js +22 -31
- package/dist/controller/{runtimeHookTurnFence.js → runtimeHookRunFence.js} +91 -115
- package/dist/controller/runtimeLaunchCoordinator.js +80 -426
- package/dist/controller/runtimeObservationHook.js +14 -18
- package/dist/controller/sessionNotify.js +16 -24
- package/dist/controller/sessionOwnerReconciliation.js +168 -50
- package/dist/controller/structuredProviderObservation.js +138 -99
- package/dist/coordination/workMailbox.js +3 -3
- package/dist/coordination/workMailboxQueue.js +36 -33
- package/dist/core/boundedRpc.js +8 -1
- package/dist/core/controllerClient.js +20 -1
- package/dist/core/controllerServer.js +4 -4
- package/dist/doctor/doctor.js +13 -2
- package/dist/domain/agentResultTransport.js +9 -9
- package/dist/execution/codexThreadNaming.js +2 -8
- package/dist/execution/executionHealth.js +51 -63
- package/dist/execution/reviewMainRun.js +137 -0
- package/dist/execution/workItemExecution.js +28 -29
- package/dist/execution/workItemExecutionProjection.js +99 -107
- package/dist/execution/workItemMainRun.js +141 -0
- package/dist/executor/agentAdapter.js +227 -20
- package/dist/executor/agentConfigurationCatalog.js +126 -4
- package/dist/executor/agentConfigurationProbe.js +162 -4
- package/dist/executor/agentExecutor.js +79 -78
- package/dist/executor/effectiveLaunch.js +105 -18
- package/dist/executor/executorRegistry.js +29 -44
- package/dist/executor/fileRoleLaunchPlanner.js +229 -154
- package/dist/executor/workspacePreflightClassification.js +16 -16
- package/dist/grant/capabilityGrant.js +6 -3
- package/dist/input/inputRequest.js +12 -10
- package/dist/integration/gitIntegrationService.js +4 -11
- package/dist/integration/integrationQueueService.js +4 -4
- package/dist/interaction/operatorPresentation.js +1 -1
- package/dist/kernel/builtinCapabilities.js +247 -12
- package/dist/kernel/capabilityRegistry.js +64 -18
- package/dist/kernel/instanceHost.js +12 -1
- package/dist/kernel/kernelPorts.js +2 -2
- package/dist/lifecycle/canonicalLifecycleEvent.js +44 -49
- package/dist/lifecycle/exactRunTerminalization.js +449 -0
- package/dist/message/message.js +62 -6
- package/dist/message/messageContinuation.js +204 -0
- package/dist/observability/executionAudit.js +70 -72
- package/dist/observability/faultClassification.js +2 -2
- package/dist/observability/orchestrationMetrics.js +8 -8
- package/dist/operator/operatorSessionHistory.js +1 -7
- package/dist/output/agentConfigurationPresentation.js +8 -3
- package/dist/output/agentRunConfigurationPresentation.js +128 -0
- package/dist/output/rolePresentation.js +54 -3
- package/dist/plugins/pluginChild.js +104 -0
- package/dist/plugins/pluginIntent.js +26 -0
- package/dist/plugins/pluginInterpreter.js +43 -0
- package/dist/plugins/pluginPackage.js +101 -0
- package/dist/plugins/pluginProcess.js +112 -0
- package/dist/plugins/pluginService.js +380 -0
- package/dist/profile/agentProfile.js +1 -1
- package/dist/repository/gitWorkspace.js +26 -4
- package/dist/repository/project.js +19 -4
- package/dist/repository/taskBaseFreshness.js +13 -13
- package/dist/repository/taskWorkspaceCoordinator.js +20 -27
- package/dist/repository/taskWorkspacePreparer.js +344 -83
- package/dist/resources/autoResourceGc.js +3 -3
- package/dist/resources/liveReferences.js +3 -3
- package/dist/resources/projectResource.js +123 -0
- package/dist/resources/projectResourceService.js +421 -0
- package/dist/resources/resourceDiscovery.js +6 -6
- package/dist/resources/resourceGc.js +1 -1
- package/dist/resources/resourceRegistrar.js +1 -1
- package/dist/resources/resourceTypes.js +1 -1
- package/dist/review/deltaRecheck.js +3 -3
- package/dist/review/reviewAcceptance.js +16 -16
- package/dist/review/reviewDecision.js +7 -7
- package/dist/review/reviewRound.js +21 -20
- package/dist/review/reviewerAvailability.js +2 -2
- package/dist/role/role.js +51 -7
- package/dist/role/taskRoleUpdate.js +30 -0
- package/dist/runtime/acpProtocol.js +425 -0
- package/dist/runtime/acpSession.js +731 -0
- package/dist/runtime/acpSessionConfiguration.js +260 -0
- package/dist/runtime/agentDriver.js +30 -11
- package/dist/runtime/agentEndpoint.js +278 -0
- package/dist/runtime/agentEndpointIdentity.js +86 -0
- package/dist/runtime/agentEndpointOwnership.js +239 -0
- package/dist/runtime/agentError.js +2 -10
- package/dist/runtime/agentHost.js +565 -314
- package/dist/runtime/agentRunConfiguration.js +258 -0
- package/dist/runtime/builtinAgentDrivers.js +134 -18
- package/dist/runtime/builtinAgentErrorMappers.js +55 -3
- package/dist/runtime/builtinTranscriptUsage.js +1 -1
- package/dist/runtime/claude-process-owner +0 -0
- package/dist/runtime/codexAppServerRuntime.js +38 -30
- package/dist/runtime/codexInteractiveHost.js +41 -6
- package/dist/runtime/continuationManager.js +2 -6
- package/dist/runtime/executionEnvironment.js +30 -0
- package/dist/runtime/firstProgressAdvisory.js +11 -11
- package/dist/runtime/index.js +4 -3
- package/dist/runtime/jsonLineChannel.js +109 -0
- package/dist/runtime/launchBroker.js +91 -16
- package/dist/runtime/launchDiagnostics.js +2 -2
- package/dist/runtime/lifecycleReservation.js +10 -18
- package/dist/runtime/managedCaller.js +61 -17
- package/dist/runtime/nativeSessionControl.js +102 -0
- package/dist/runtime/ports.js +6 -21
- package/dist/runtime/processExitObservation.js +8 -7
- package/dist/runtime/promptEnvelope.js +17 -6
- package/dist/runtime/providerContinuation.js +3 -9
- package/dist/runtime/providerContinuationReconciliationService.js +4 -13
- package/dist/runtime/providerControl.js +2 -7
- package/dist/runtime/providerRuntimeIdentity.js +110 -222
- package/dist/runtime/providerRuntimeReconciler.js +5 -9
- package/dist/runtime/runtimeBinding.js +0 -1
- package/dist/runtime/runtimeContinuationProjection.js +4 -7
- package/dist/runtime/runtimeDeadlines.js +9 -0
- package/dist/runtime/runtimeHealthPolicy.js +1 -1
- package/dist/runtime/runtimeObservation.js +29 -65
- package/dist/runtime/runtimeProjection.js +43 -51
- package/dist/runtime/runtimeSessionCandidate.js +1 -3
- package/dist/runtime/sessionLaunchRequest.js +3 -7
- package/dist/runtime/sessionOwnerIdentity.js +7 -54
- package/dist/runtime/sessionOwnerRegistry.js +22 -17
- package/dist/runtime/sessionReconciliation.js +4 -8
- package/dist/runtime/sessionTerminationGuard.js +70 -259
- package/dist/runtime/sessionTokenMetrics.js +5 -16
- package/dist/runtime/structuredProviderHost.js +237 -117
- package/dist/runtime/taskRuntimeIsolation.js +39 -122
- package/dist/runtime/tmuxAdapters.js +39 -86
- package/dist/scheduler/activeRoleRunDelivery.js +354 -0
- package/dist/scheduler/leaderWakeupProcessor.js +75 -266
- package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
- package/dist/scheduler/ports.js +80 -9
- package/dist/scheduler/{roleTurnLiveness.js → roleRunLiveness.js} +26 -30
- package/dist/scheduler/{roleTurnStall.js → roleRunStall.js} +128 -139
- package/dist/scheduler/taskExecutionProjection.js +120 -124
- package/dist/scheduler/taskObservabilityProjection.js +29 -29
- package/dist/scheduler/taskWake.js +11 -4
- package/dist/scheduler/wakeReason.js +9 -1
- package/dist/setup/setupCommand.js +1 -0
- package/dist/storage/migrations/agentRunContract.js +159 -0
- package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
- package/dist/storage/sqliteSchema.js +431 -5
- package/dist/storage/sqliteStore.js +375 -220
- package/dist/storage/storageVersions.js +1 -1
- package/dist/storage/storeRpc.js +10 -5
- package/dist/storage/taskStore.js +13 -11
- package/dist/storage/upgrade/upgradeOrchestrator.js +5 -7
- package/dist/surface/surfaceContributions.js +102 -0
- package/dist/task/completionReadiness.js +32 -6
- package/dist/task/deliveryGuard.js +16 -16
- package/dist/task/draftPlan.js +72 -12
- package/dist/task/nextAction.js +144 -128
- package/dist/task/remoteDelivery.js +6 -6
- package/dist/task/task.js +184 -18
- package/dist/task/taskActivation.js +301 -0
- package/dist/task/taskActivationService.js +392 -0
- package/dist/task/taskRecordReference.js +5 -4
- package/dist/task/taskRecordRetirement.js +1 -1
- package/dist/telemetry/sqliteTelemetryStore.js +55 -68
- package/dist/telemetry/telemetryConfig.js +14 -14
- package/dist/telemetry/telemetryWiring.js +2 -2
- package/dist/web/assets/assetManifest.js +2 -0
- package/dist/web/assets/client/app.js +120 -20
- package/dist/web/assets/client/components.js +87 -54
- package/dist/web/assets/client/i18n.js +83 -41
- package/dist/web/assets/client/markdown.js +1 -1
- package/dist/web/assets/client/taskSurface.js +353 -0
- package/dist/web/assets/client/view.js +49 -44
- package/dist/web/assets/shell.js +1 -1
- package/dist/web/assets/styles/cards.js +22 -4
- package/dist/web/controllerWeb.js +60 -0
- package/dist/web/webMutation.js +28 -0
- package/dist/web/webServer.js +118 -8
- package/dist/web/webSnapshot.js +81 -74
- package/dist/web/webTaskSurface.js +64 -0
- package/dist/workItem/dependencyGate.js +1 -1
- package/dist/workItem/workItem.js +80 -48
- package/dist/workspace/workItemChangeSetManager.js +16 -9
- package/docs/agent-result-consumption.md +94 -0
- package/docs/agent-runtime-drivers.md +91 -0
- package/docs/architecture/README.md +38 -0
- package/docs/architecture/capabilities-and-resources.md +79 -0
- package/docs/managed-turn-and-session-runtime.md +222 -0
- package/docs/observability/README.md +81 -0
- package/docs/plugin-sdk.md +290 -0
- package/docs/provider-runtime.md +163 -0
- package/docs/release-workflow.md +303 -0
- package/docs/roles-and-configuration.md +113 -0
- package/docs/sqlite-control-plane-design.md +76 -0
- package/docs/task-dag-semantics.md +57 -0
- package/docs/task-delivery.md +103 -0
- package/docs/task-local-identity.md +6 -6
- package/docs/testing/verification-levels.md +86 -0
- package/i18n/README.zh-CN.md +98 -739
- package/package.json +2 -2
- package/skills/yui-leader/SKILL.md +130 -103
- package/skills/yui-leader/references/integration.md +39 -0
- package/skills/yui-leader/references/replicated-execution.md +42 -0
- package/skills/yui-leader/references/task-plugins.md +33 -0
- package/skills/yui-operator/SKILL.md +30 -59
- package/skills/yui-reviewer/SKILL.md +35 -36
- package/skills/yui-runtime/SKILL.md +88 -24
- package/skills/yui-runtime/references/publication.md +22 -0
- package/skills/yui-runtime/references/recovery.md +64 -0
- package/skills/yui-worker/SKILL.md +37 -39
- package/dist/cli/roleOptionCatalog.js +0 -68
- package/dist/context/sourceTurnContext.js +0 -30
- package/dist/execution/reviewMainTurn.js +0 -161
- package/dist/execution/workItemMainTurn.js +0 -164
- package/dist/lifecycle/exactTurnTerminalization.js +0 -407
- package/dist/runtime/preallocatedNativeSession.js +0 -13
- package/dist/runtime/runtimeStopReceipt.js +0 -42
- package/dist/scheduler/activeRoleTurnDelivery.js +0 -315
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { capabilitySchemaError, checkCapabilitySchema } from "./capabilitySchema.js";
|
|
2
|
+
import { checkSurfaceDescriptors } from "../surface/surfaceContributions.js";
|
|
3
|
+
/** Trusted owners may accompany a failed operation with its current read model.
|
|
4
|
+
* This is diagnostic data, not an operation receipt or an authority token. */
|
|
5
|
+
export class CapabilityExecutionError extends Error {
|
|
6
|
+
value;
|
|
7
|
+
constructor(message, value) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.value = structuredClone(value);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
2
12
|
const effectRank = { query: 0, "local-mutation": 1, "external-operation": 2 };
|
|
3
|
-
const reserved = new Set(["yui", "task", "config", "job", "resource", "plugin", "runtime", "grant", "capability"]);
|
|
13
|
+
const reserved = new Set(["yui", "task", "context", "config", "job", "resource", "plugin", "runtime", "grant", "capability", "artifact", "environment", "project"]);
|
|
4
14
|
/** One rebuildable descriptor view over the composition root's existing Host.
|
|
5
15
|
* Only the trusted root owns this object. Extensions receive a bound invocation
|
|
6
16
|
* port, never the registry/Host or an actor-selecting call interface. */
|
|
@@ -21,6 +31,30 @@ export class CapabilityRegistry {
|
|
|
21
31
|
register(descriptors) {
|
|
22
32
|
this.#publish(descriptors, false);
|
|
23
33
|
}
|
|
34
|
+
/** Data-only candidate check before author initialization; no acquisition or
|
|
35
|
+
* publication. Repeat immediately before publishing after any async work. */
|
|
36
|
+
checkRegistration(context, descriptors) {
|
|
37
|
+
const prepared = this.#prepare(descriptors, false);
|
|
38
|
+
if (!prepared.length)
|
|
39
|
+
throw new Error("Plugin must contribute capabilities.");
|
|
40
|
+
const available = [
|
|
41
|
+
...this.search(context).filter((entry) => entry.provider.id !== prepared[0].provider.id),
|
|
42
|
+
...prepared
|
|
43
|
+
];
|
|
44
|
+
const check = (entry, path) => {
|
|
45
|
+
this.authorize(context, entry);
|
|
46
|
+
if (path.has(entry))
|
|
47
|
+
throw new Error("Required capability dependency cycle.");
|
|
48
|
+
for (const dependency of entry.required ?? []) {
|
|
49
|
+
const matches = available.filter((candidate) => candidate.name === dependency.name
|
|
50
|
+
&& candidate.contractVersion === dependency.contractVersion && candidate.unavailable === undefined);
|
|
51
|
+
if (matches.length !== 1)
|
|
52
|
+
throw new Error(`Required capability is missing or ambiguous: ${dependency.name}.`);
|
|
53
|
+
check(matches[0], new Set([...path, entry]));
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
prepared.forEach((entry) => check(entry, new Set()));
|
|
57
|
+
}
|
|
24
58
|
disable(providerId) {
|
|
25
59
|
this.#descriptors = this.#descriptors.filter((entry) => entry.provider.id !== providerId);
|
|
26
60
|
}
|
|
@@ -70,7 +104,7 @@ export class CapabilityRegistry {
|
|
|
70
104
|
call(context, request) {
|
|
71
105
|
return this.#call(context, request, "external-operation");
|
|
72
106
|
}
|
|
73
|
-
async #call(context, request, ceiling) {
|
|
107
|
+
async #call(context, request, ceiling, permissions) {
|
|
74
108
|
// Freeze one input snapshot across validation/acquisition and async nesting.
|
|
75
109
|
try {
|
|
76
110
|
request = deepFreeze(structuredClone(request));
|
|
@@ -86,6 +120,9 @@ export class CapabilityRegistry {
|
|
|
86
120
|
if (effectRank[descriptor.effect] > effectRank[ceiling]) {
|
|
87
121
|
return { ...result("denied", "Nested call exceeds the parent's effect boundary."), ...origin };
|
|
88
122
|
}
|
|
123
|
+
if (permissions !== undefined && descriptor.requiredPermissions.some((permission) => !permissions.includes(permission))) {
|
|
124
|
+
return { ...result("denied", "Nested call exceeds the parent's declared permissions."), ...origin };
|
|
125
|
+
}
|
|
89
126
|
const inputError = capabilitySchemaError(descriptor.inputSchema, request.input);
|
|
90
127
|
if (inputError)
|
|
91
128
|
return { ...result("invalid", inputError), ...origin };
|
|
@@ -121,7 +158,7 @@ export class CapabilityRegistry {
|
|
|
121
158
|
call: (nested) => {
|
|
122
159
|
if (!open)
|
|
123
160
|
return Promise.resolve(result("denied", "Capability invocation has ended."));
|
|
124
|
-
const child = this.#call(context, nested, descriptor.effect).then((outcome) => {
|
|
161
|
+
const child = this.#call(context, nested, descriptor.effect, descriptor.requiredPermissions).then((outcome) => {
|
|
125
162
|
outcome.operations.forEach(observe);
|
|
126
163
|
effect = accumulatedEffect(effect, outcome.effect);
|
|
127
164
|
return outcome;
|
|
@@ -177,6 +214,7 @@ export class CapabilityRegistry {
|
|
|
177
214
|
return {
|
|
178
215
|
kind: entered ? "failed" : "unavailable",
|
|
179
216
|
detail: error instanceof Error ? error.message : "Capability invocation failed.",
|
|
217
|
+
...(error instanceof CapabilityExecutionError ? { value: error.value } : {}),
|
|
180
218
|
effect, operations, ...origin
|
|
181
219
|
};
|
|
182
220
|
}
|
|
@@ -200,6 +238,27 @@ export class CapabilityRegistry {
|
|
|
200
238
|
#publish(descriptors, core) {
|
|
201
239
|
if (!descriptors.length)
|
|
202
240
|
return;
|
|
241
|
+
const prepared = this.#prepare(descriptors, core);
|
|
242
|
+
const provider = prepared[0].provider;
|
|
243
|
+
// Validate acquisition before publishing; no implementation is invoked.
|
|
244
|
+
if (prepared.some((entry) => !entry.unavailable)) {
|
|
245
|
+
const handle = this.host.acquire(provider);
|
|
246
|
+
try {
|
|
247
|
+
if (typeof handle.value?.invoke !== "function")
|
|
248
|
+
throw new Error("Provider has no capability implementation.");
|
|
249
|
+
}
|
|
250
|
+
finally {
|
|
251
|
+
void handle.release();
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
this.#descriptors = [
|
|
255
|
+
...this.#descriptors.filter((entry) => entry.provider.id !== provider.id),
|
|
256
|
+
...prepared.map((entry) => deepFreeze(entry))
|
|
257
|
+
];
|
|
258
|
+
}
|
|
259
|
+
#prepare(descriptors, core) {
|
|
260
|
+
if (!descriptors.length)
|
|
261
|
+
return [];
|
|
203
262
|
const prepared = structuredClone(descriptors);
|
|
204
263
|
const provider = prepared[0].provider;
|
|
205
264
|
if (!core && this.#coreProviders.has(provider.id))
|
|
@@ -227,26 +286,13 @@ export class CapabilityRegistry {
|
|
|
227
286
|
names.add(key);
|
|
228
287
|
checkCapabilitySchema(entry.inputSchema);
|
|
229
288
|
checkCapabilitySchema(entry.outputSchema);
|
|
289
|
+
checkSurfaceDescriptors(entry);
|
|
230
290
|
for (const dependency of entry.required ?? []) {
|
|
231
291
|
if (!dependency.name?.trim() || !dependency.contractVersion?.trim())
|
|
232
292
|
throw new Error("Invalid required capability.");
|
|
233
293
|
}
|
|
234
294
|
}
|
|
235
|
-
|
|
236
|
-
if (prepared.some((entry) => !entry.unavailable)) {
|
|
237
|
-
const handle = this.host.acquire(provider);
|
|
238
|
-
try {
|
|
239
|
-
if (typeof handle.value?.invoke !== "function")
|
|
240
|
-
throw new Error("Provider has no capability implementation.");
|
|
241
|
-
}
|
|
242
|
-
finally {
|
|
243
|
-
void handle.release();
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
this.#descriptors = [
|
|
247
|
-
...this.#descriptors.filter((entry) => entry.provider.id !== provider.id),
|
|
248
|
-
...prepared.map((entry) => deepFreeze(entry))
|
|
249
|
-
];
|
|
295
|
+
return [...prepared];
|
|
250
296
|
}
|
|
251
297
|
}
|
|
252
298
|
function visible(scope, visibility) {
|
|
@@ -14,7 +14,7 @@ export class InstanceHost {
|
|
|
14
14
|
void drained.catch(() => undefined);
|
|
15
15
|
const ref = Object.freeze({ ...implementation });
|
|
16
16
|
this.#instances.set(key, {
|
|
17
|
-
implementation: ref, value, references: 0, detached: false,
|
|
17
|
+
implementation: ref, value, references: 0, detached: false, disposed: false,
|
|
18
18
|
disposers: [...ownedDisposers], drained, resolve, reject
|
|
19
19
|
});
|
|
20
20
|
return ref;
|
|
@@ -25,6 +25,16 @@ export class InstanceHost {
|
|
|
25
25
|
const instance = this.#instances.get(implementationKey(implementation));
|
|
26
26
|
return !this.#closed && instance !== undefined && !instance.detached;
|
|
27
27
|
}
|
|
28
|
+
/** Only the Host reports actual reference/disposal facts. Metadata consumers
|
|
29
|
+
* must not persist these observations as independently writable state. */
|
|
30
|
+
inspect(providerId) {
|
|
31
|
+
return [...this.#instances.values()].filter((instance) => instance.implementation.id === providerId && !instance.disposed)
|
|
32
|
+
.map((instance) => Object.freeze({
|
|
33
|
+
implementation: instance.implementation,
|
|
34
|
+
references: instance.references,
|
|
35
|
+
accepting: !this.#closed && !instance.detached
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
28
38
|
acquire(implementation) {
|
|
29
39
|
const instance = this.#instances.get(implementationKey(implementation));
|
|
30
40
|
if (this.#closed || instance === undefined || instance.detached) {
|
|
@@ -86,6 +96,7 @@ export class InstanceHost {
|
|
|
86
96
|
// Re-attaching a generation must not resurrect an old reference.
|
|
87
97
|
instance.value = undefined;
|
|
88
98
|
instance.disposers = [];
|
|
99
|
+
instance.disposed = true;
|
|
89
100
|
if (errors.length)
|
|
90
101
|
throw new AggregateError(errors, "Instance cleanup failed.");
|
|
91
102
|
})();
|
|
@@ -6,14 +6,14 @@ import { createBuiltinCapabilities } from "./builtinCapabilities.js";
|
|
|
6
6
|
* another Controller, or provide arbitrary persistence to plugin code.
|
|
7
7
|
* T02 registers contributions on this Host and wraps this same Job control.
|
|
8
8
|
*/
|
|
9
|
-
export function createKernelPorts(store, runner, signal = () => undefined) {
|
|
9
|
+
export function createKernelPorts(store, runner, signal = () => undefined, contextProviders = []) {
|
|
10
10
|
const host = new InstanceHost();
|
|
11
11
|
const runnerImplementation = host.attach(JOB_RUNNER_IMPLEMENTATION, runner);
|
|
12
12
|
const runnerHandle = host.acquire(runnerImplementation);
|
|
13
13
|
const jobImplementation = host.attach({ id: "yui:job-control", generation: "1" }, createDurableJobControl(store));
|
|
14
14
|
// The Controller is a long-lived consumer of this exact implementation.
|
|
15
15
|
const jobHandle = host.acquire(jobImplementation);
|
|
16
|
-
const capabilities = createBuiltinCapabilities(host, store, jobHandle.value, signal);
|
|
16
|
+
const capabilities = createBuiltinCapabilities(host, store, jobHandle.value, signal, contextProviders);
|
|
17
17
|
return {
|
|
18
18
|
host,
|
|
19
19
|
capabilities,
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The smallest stable, provider-neutral Yui lifecycle vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* Each phase is a durable semantic fact about a managed Agent Session or the
|
|
5
|
+
* AgentRun whose prompt it carries. Agent Drivers translate native signals into
|
|
6
|
+
* these phases; the scheduler and durable fold reason about phases, sources,
|
|
7
|
+
* and evidence — never about provider names.
|
|
8
|
+
*/
|
|
9
|
+
import { isAgentAdapterId } from "../agent/adapterCatalog.js";
|
|
1
10
|
export function isPreInputReadinessSupported(capability) {
|
|
2
11
|
return capability.status === "supported";
|
|
3
12
|
}
|
|
@@ -9,17 +18,17 @@ export class CanonicalLifecycleError extends Error {
|
|
|
9
18
|
this.name = "CanonicalLifecycleError";
|
|
10
19
|
}
|
|
11
20
|
}
|
|
12
|
-
const
|
|
21
|
+
const RUN_SCOPED_PHASES = new Set([
|
|
13
22
|
"prompt-pushed",
|
|
14
23
|
"provider-accepted",
|
|
15
24
|
"turn-progress",
|
|
16
25
|
"turn-terminal"
|
|
17
26
|
]);
|
|
18
27
|
/**
|
|
19
|
-
* Phases that assert durable provider truth about a
|
|
20
|
-
* the complete turn-scoped identity — turnId AND the
|
|
21
|
-
* (nativeSessionId
|
|
22
|
-
* because a missing or wrong fence must fail closed rather than advance a
|
|
28
|
+
* Phases that assert durable provider truth about a AgentRun. Every one must carry
|
|
29
|
+
* the complete turn-scoped identity — turnId AND the Session fences
|
|
30
|
+
* (nativeSessionId) AND, where the transport owns it, the receiptId —
|
|
31
|
+
* because a missing or wrong fence must fail closed rather than advance a AgentRun or
|
|
23
32
|
* its successor.
|
|
24
33
|
*/
|
|
25
34
|
const PROVIDER_TRUTH_PHASES = new Set([
|
|
@@ -34,7 +43,7 @@ const PROVIDER_TRUTH_PHASES = new Set([
|
|
|
34
43
|
* (acceptance/progress/terminal), so neither a transport/liveness signal nor a
|
|
35
44
|
* shape-only `adapter-mapped` observation can ever forge or terminalize a turn.
|
|
36
45
|
* `adapter-mapped` remains permissible only for the pre-acceptance
|
|
37
|
-
* session-started/ready phases, whose fold never advances
|
|
46
|
+
* session-started/ready phases, whose fold never advances AgentRun truth.
|
|
38
47
|
*/
|
|
39
48
|
const PHASE_EVIDENCE_MATRIX = {
|
|
40
49
|
"host-process-created": { sources: ["controller"], evidence: ["controller"] },
|
|
@@ -77,18 +86,15 @@ export function createCanonicalLifecycleEvent(input) {
|
|
|
77
86
|
throw new CanonicalLifecycleError(`Phase ${input.phase} rejects evidence ${input.evidence}; only ${rule.evidence.join("/")} may prove it.`);
|
|
78
87
|
}
|
|
79
88
|
const fence = normalizeFence(input.fence);
|
|
80
|
-
if (
|
|
81
|
-
throw new CanonicalLifecycleError(`Phase ${input.phase} requires a
|
|
89
|
+
if (RUN_SCOPED_PHASES.has(input.phase) && fence.runId === undefined) {
|
|
90
|
+
throw new CanonicalLifecycleError(`Phase ${input.phase} requires a runId fence.`);
|
|
82
91
|
}
|
|
83
|
-
// Provider-truth phases must carry the complete
|
|
84
|
-
// wrong
|
|
92
|
+
// Provider-truth phases must carry the complete Session fence so a stale or
|
|
93
|
+
// wrong Session can never advance the AgentRun.
|
|
85
94
|
if (PROVIDER_TRUTH_PHASES.has(input.phase)) {
|
|
86
95
|
if (fence.nativeSessionId === undefined) {
|
|
87
96
|
throw new CanonicalLifecycleError(`Phase ${input.phase} requires a nativeSessionId fence.`);
|
|
88
97
|
}
|
|
89
|
-
if (fence.runtimeGenerationId === undefined) {
|
|
90
|
-
throw new CanonicalLifecycleError(`Phase ${input.phase} requires a runtimeGenerationId fence.`);
|
|
91
|
-
}
|
|
92
98
|
}
|
|
93
99
|
if (input.phase === "prompt-pushed" && fence.receiptId === undefined) {
|
|
94
100
|
throw new CanonicalLifecycleError("A prompt-pushed event requires a transport receiptId.");
|
|
@@ -133,7 +139,7 @@ export function createCanonicalLifecycleEvent(input) {
|
|
|
133
139
|
* The provider-neutral decision. Given a validated canonical event and the
|
|
134
140
|
* consumer's current expectation, it returns what should happen — idempotent for
|
|
135
141
|
* duplicates, deferred for not-yet-applicable facts, obsolete for stale/wrong
|
|
136
|
-
*
|
|
142
|
+
* Session, fail-closed for contract violations. It reads only phase / source
|
|
137
143
|
* / evidence / identity, never the adapter name, and mutates nothing.
|
|
138
144
|
*/
|
|
139
145
|
export function foldCanonicalLifecycleEvent(event, expectation) {
|
|
@@ -154,10 +160,7 @@ export function foldCanonicalLifecycleEvent(event, expectation) {
|
|
|
154
160
|
}
|
|
155
161
|
// Discovery may bind a previously-unknown native id, but only under the
|
|
156
162
|
// exact launch fence and only when none is bound yet.
|
|
157
|
-
if (expectation.boundNativeSessionId === undefined
|
|
158
|
-
&& event.fence.nativeSessionId !== undefined
|
|
159
|
-
&& event.fence.runtimeGenerationId !== undefined
|
|
160
|
-
&& event.fence.runtimeGenerationId === expectation.fence.runtimeGenerationId) {
|
|
163
|
+
if (expectation.boundNativeSessionId === undefined && event.fence.nativeSessionId !== undefined) {
|
|
161
164
|
return { outcome: "bind-native-session", nativeSessionId: event.fence.nativeSessionId };
|
|
162
165
|
}
|
|
163
166
|
return { outcome: "mark-session-started" };
|
|
@@ -176,7 +179,7 @@ export function foldCanonicalLifecycleEvent(event, expectation) {
|
|
|
176
179
|
return { outcome: "obsolete", reason: "push-after-terminal" };
|
|
177
180
|
if (expectation.accepted)
|
|
178
181
|
return { outcome: "obsolete", reason: "push-after-accepted" };
|
|
179
|
-
// Exactly one push: a repeat for an already-pushed
|
|
182
|
+
// Exactly one push: a repeat for an already-pushed AgentRun is a no-op, never a
|
|
180
183
|
// second Enter.
|
|
181
184
|
if (expectation.pushed)
|
|
182
185
|
return { outcome: "idempotent", reason: "already-pushed" };
|
|
@@ -209,7 +212,7 @@ export function foldCanonicalLifecycleEvent(event, expectation) {
|
|
|
209
212
|
return { outcome: "idempotent", reason: "already-terminal" };
|
|
210
213
|
if (expectation.accepted)
|
|
211
214
|
return { outcome: "advance-terminal" };
|
|
212
|
-
// A terminal for a pushed-but-unaccepted
|
|
215
|
+
// A terminal for a pushed-but-unaccepted AgentRun must NOT promote acceptance;
|
|
213
216
|
// hold the immutable fact until (or unless) acceptance folds first.
|
|
214
217
|
if (expectation.pushed)
|
|
215
218
|
return { outcome: "deferred", reason: "terminal-before-accept" };
|
|
@@ -219,12 +222,12 @@ export function foldCanonicalLifecycleEvent(event, expectation) {
|
|
|
219
222
|
}
|
|
220
223
|
}
|
|
221
224
|
/**
|
|
222
|
-
* Returns null when the event belongs to the expected
|
|
225
|
+
* Returns null when the event belongs to the expected Session/AgentRun, or a
|
|
223
226
|
* mismatch reason otherwise. Owner/adapter and turn-scoped turnId are always
|
|
224
227
|
* compared. Provider-truth phases (acceptance/progress/terminal) require the
|
|
225
|
-
* COMPLETE
|
|
226
|
-
* receiptId must be present and equal, so a missing or wrong
|
|
227
|
-
* fails closed rather than advancing a
|
|
228
|
+
* COMPLETE Session fence — nativeSessionId, and (for acceptance)
|
|
229
|
+
* receiptId must be present and equal, so a missing or wrong Session/receipt
|
|
230
|
+
* fails closed rather than advancing a AgentRun or its successor. Where a native id
|
|
228
231
|
* is already bound, every turn-scoped fact must match it.
|
|
229
232
|
*/
|
|
230
233
|
function matchesFence(expectation, event) {
|
|
@@ -239,29 +242,23 @@ function matchesFence(expectation, event) {
|
|
|
239
242
|
return "fence-mismatch:agentId";
|
|
240
243
|
if (expected.adapterId !== actual.adapterId)
|
|
241
244
|
return "fence-mismatch:adapterId";
|
|
242
|
-
//
|
|
243
|
-
if (
|
|
244
|
-
if (expected.
|
|
245
|
+
// AgentRun-scoped phases must name the exact expected AgentRun.
|
|
246
|
+
if (RUN_SCOPED_PHASES.has(phase)) {
|
|
247
|
+
if (expected.runId === undefined)
|
|
245
248
|
return "fence-mismatch:expected-turn-missing";
|
|
246
|
-
if (actual.
|
|
247
|
-
return "fence-mismatch:
|
|
249
|
+
if (actual.runId !== expected.runId)
|
|
250
|
+
return "fence-mismatch:runId";
|
|
248
251
|
}
|
|
249
|
-
else if (actual.
|
|
250
|
-
&& expected.
|
|
251
|
-
&& actual.
|
|
252
|
-
return "fence-mismatch:
|
|
252
|
+
else if (actual.runId !== undefined
|
|
253
|
+
&& expected.runId !== undefined
|
|
254
|
+
&& actual.runId !== expected.runId) {
|
|
255
|
+
return "fence-mismatch:runId";
|
|
253
256
|
}
|
|
254
|
-
// Provider-truth phases require the complete, equal
|
|
257
|
+
// Provider-truth phases require the complete, equal Session fence. A
|
|
255
258
|
// provider-accepted event additionally must carry the exact receipt it accepts.
|
|
256
259
|
if (PROVIDER_TRUTH_PHASES.has(phase)) {
|
|
257
260
|
if (actual.nativeSessionId === undefined)
|
|
258
261
|
return "fence-mismatch:missing-native-session";
|
|
259
|
-
if (actual.runtimeGenerationId === undefined) {
|
|
260
|
-
return "fence-mismatch:missing-runtime-generation";
|
|
261
|
-
}
|
|
262
|
-
if (expected.runtimeGenerationId !== undefined && actual.runtimeGenerationId !== expected.runtimeGenerationId) {
|
|
263
|
-
return "fence-mismatch:runtimeGenerationId";
|
|
264
|
-
}
|
|
265
262
|
// Once a native id is bound, every provider-truth fact must match it. Before
|
|
266
263
|
// binding (discovery still open) the expected fence's own nativeSessionId, if
|
|
267
264
|
// present, still constrains it.
|
|
@@ -279,7 +276,7 @@ function matchesFence(expectation, event) {
|
|
|
279
276
|
return null;
|
|
280
277
|
}
|
|
281
278
|
// Pre-acceptance phases (host/session/ready and the transport push): compare
|
|
282
|
-
// the
|
|
279
|
+
// the Session dimensions that are present on both sides. A push must match
|
|
283
280
|
// its expected receipt when both name one.
|
|
284
281
|
if (actual.nativeSessionId !== undefined
|
|
285
282
|
&& expectation.boundNativeSessionId !== undefined
|
|
@@ -291,11 +288,6 @@ function matchesFence(expectation, event) {
|
|
|
291
288
|
&& actual.nativeSessionId !== expected.nativeSessionId) {
|
|
292
289
|
return "fence-mismatch:nativeSessionId";
|
|
293
290
|
}
|
|
294
|
-
if (actual.runtimeGenerationId !== undefined
|
|
295
|
-
&& expected.runtimeGenerationId !== undefined
|
|
296
|
-
&& actual.runtimeGenerationId !== expected.runtimeGenerationId) {
|
|
297
|
-
return "fence-mismatch:runtimeGenerationId";
|
|
298
|
-
}
|
|
299
291
|
if (phase === "prompt-pushed"
|
|
300
292
|
&& actual.receiptId !== undefined
|
|
301
293
|
&& expected.receiptId !== undefined
|
|
@@ -308,7 +300,11 @@ function normalizeFence(fence) {
|
|
|
308
300
|
const taskId = requireFenceText(fence.taskId, "taskId");
|
|
309
301
|
const roleName = requireFenceText(fence.roleName, "roleName");
|
|
310
302
|
const agentId = requireFenceText(fence.agentId, "agentId");
|
|
311
|
-
|
|
303
|
+
// The fence names an adapter, and the catalog is what defines which adapters
|
|
304
|
+
// exist. Re-listing them here would silently exclude a catalogued adapter
|
|
305
|
+
// from the durable fold, which reads as an identity mismatch rather than as
|
|
306
|
+
// the missing registration it actually is.
|
|
307
|
+
if (!isAgentAdapterId(fence.adapterId)) {
|
|
312
308
|
throw new CanonicalLifecycleError(`Unsupported adapter fence: ${String(fence.adapterId)}.`);
|
|
313
309
|
}
|
|
314
310
|
return Object.freeze({
|
|
@@ -316,11 +312,10 @@ function normalizeFence(fence) {
|
|
|
316
312
|
roleName,
|
|
317
313
|
agentId,
|
|
318
314
|
adapterId: fence.adapterId,
|
|
319
|
-
...(fence.
|
|
315
|
+
...(fence.runId === undefined ? {} : { runId: requireFenceText(fence.runId, "runId") }),
|
|
320
316
|
...(fence.nativeSessionId === undefined
|
|
321
317
|
? {}
|
|
322
318
|
: { nativeSessionId: requireFenceText(fence.nativeSessionId, "nativeSessionId") }),
|
|
323
|
-
...(fence.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: requireFenceText(fence.runtimeGenerationId, "runtimeGenerationId") }),
|
|
324
319
|
...(fence.receiptId === undefined ? {} : { receiptId: requireFenceText(fence.receiptId, "receiptId") })
|
|
325
320
|
});
|
|
326
321
|
}
|