@skaile/workspaces 1.12.1 → 1.12.2
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 +11 -0
- package/dist/{chunk-ZA465CPE.js → chunk-IO3K4PTB.js} +89 -2
- package/dist/chunk-IO3K4PTB.js.map +1 -0
- package/dist/{chunk-OZGZREH4.js → chunk-YSEKT6AV.js} +2 -2
- package/dist/{chunk-OZGZREH4.js.map → chunk-YSEKT6AV.js.map} +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/factory-assets/connectors/flow/run-flow.js +1 -1
- package/dist/runner/index.js +1 -1
- package/dist/runner/src/driver-swap-gate.d.ts +44 -0
- package/dist/runner/src/driver-swap-gate.d.ts.map +1 -0
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/sdk/index.js +1 -1
- package/dist/sdk/runner.js +1 -1
- package/dist/tui/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-ZA465CPE.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.12.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#422](https://github.com/skaile-ai/workspaces/pull/422) [`47a9896`](https://github.com/skaile-ai/workspaces/commit/47a989633a22c0c090fb7c50c4c3355738f73aca) Thanks [@Frozen666](https://github.com/Frozen666)! - Fix a dropped in-flight prompt when a skill-change driver restart races a live
|
|
8
|
+
turn. The runner now serializes prompt turns against out-of-band driver swaps via
|
|
9
|
+
a bidirectional gate: a swap defers to an in-flight turn (so the driver is never
|
|
10
|
+
killed mid-prompt), and a prompt arriving during a swap binds to the fresh driver.
|
|
11
|
+
Previously the killed SDK process emitted no completion event and the UI hung on
|
|
12
|
+
"AI is thinking…" forever.
|
|
13
|
+
|
|
3
14
|
## 1.12.1
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
|
@@ -2939,6 +2939,70 @@ function cleanupCloudCredentialFiles(projectDir) {
|
|
|
2939
2939
|
}
|
|
2940
2940
|
}
|
|
2941
2941
|
|
|
2942
|
+
// runner/src/driver-swap-gate.ts
|
|
2943
|
+
var DriverSwapGate = class {
|
|
2944
|
+
/** Resolves when the in-flight driver recreate settles (resolve or reject). */
|
|
2945
|
+
activeDriverSwap = null;
|
|
2946
|
+
/** FIFO chain; resolves once every started turn has settled. */
|
|
2947
|
+
turnTail = Promise.resolve();
|
|
2948
|
+
/**
|
|
2949
|
+
* Mark a turn as in flight. Call at the real `driver.prompt()` dispatch — not
|
|
2950
|
+
* earlier — so a same-handler restart (e.g. restaging skills before the turn)
|
|
2951
|
+
* cannot self-deadlock by awaiting the very turn that spawned it. Returns an
|
|
2952
|
+
* idempotent `endTurn`; call it in a `finally` around the dispatch.
|
|
2953
|
+
*/
|
|
2954
|
+
beginTurn() {
|
|
2955
|
+
let resolveTurn;
|
|
2956
|
+
const turn = new Promise((resolve4) => {
|
|
2957
|
+
resolveTurn = resolve4;
|
|
2958
|
+
});
|
|
2959
|
+
this.turnTail = this.turnTail.then(() => turn);
|
|
2960
|
+
let ended = false;
|
|
2961
|
+
return () => {
|
|
2962
|
+
if (ended) return;
|
|
2963
|
+
ended = true;
|
|
2964
|
+
resolveTurn();
|
|
2965
|
+
};
|
|
2966
|
+
}
|
|
2967
|
+
/**
|
|
2968
|
+
* Await any in-flight turn before tearing a driver down. Awaits the FIFO tail
|
|
2969
|
+
* (not a single "latest turn" field) so an earlier turn that outlives a later
|
|
2970
|
+
* one still holds the swap off — the tail resolves only once every started
|
|
2971
|
+
* turn has settled. Never throws: a rejected turn is still a settled turn, and
|
|
2972
|
+
* the swap may proceed (the driver is idle either way).
|
|
2973
|
+
*/
|
|
2974
|
+
async awaitActiveTurn() {
|
|
2975
|
+
try {
|
|
2976
|
+
await this.turnTail;
|
|
2977
|
+
} catch {
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2980
|
+
/**
|
|
2981
|
+
* Register the in-flight recreate promise so concurrent prompts defer to it.
|
|
2982
|
+
* Auto-clears when `recreate` settles (resolve OR reject) so a failed recreate
|
|
2983
|
+
* never blocks prompts forever.
|
|
2984
|
+
*/
|
|
2985
|
+
beginSwap(recreate) {
|
|
2986
|
+
this.activeDriverSwap = recreate;
|
|
2987
|
+
const clear = () => {
|
|
2988
|
+
if (this.activeDriverSwap === recreate) this.activeDriverSwap = null;
|
|
2989
|
+
};
|
|
2990
|
+
recreate.then(clear, clear);
|
|
2991
|
+
}
|
|
2992
|
+
/**
|
|
2993
|
+
* Await the in-flight swap before reading the live driver. Re-checks in a loop
|
|
2994
|
+
* so a second swap starting during the wait is also awaited.
|
|
2995
|
+
*/
|
|
2996
|
+
async awaitSwap() {
|
|
2997
|
+
while (this.activeDriverSwap) {
|
|
2998
|
+
try {
|
|
2999
|
+
await this.activeDriverSwap;
|
|
3000
|
+
} catch {
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
};
|
|
3005
|
+
|
|
2942
3006
|
// runner/src/compaction/prompt.ts
|
|
2943
3007
|
var DEFAULT_COMPACTION_PROMPT = `You are being asked to compact this conversation into a structured summary.
|
|
2944
3008
|
This summary will replace the full conversation history when the session
|
|
@@ -4837,6 +4901,7 @@ async function startAgentServer(opts) {
|
|
|
4837
4901
|
sendEvent(rewriteFileChangedPath(event, opts.projectDir, mounts));
|
|
4838
4902
|
}
|
|
4839
4903
|
let driverStarted = false;
|
|
4904
|
+
const driverSwapGate = new DriverSwapGate();
|
|
4840
4905
|
let driver = secretsMode === "env" ? agentSession.driver : void 0;
|
|
4841
4906
|
let secretsProvisioned = secretsMode === "env";
|
|
4842
4907
|
function swapDriver() {
|
|
@@ -5250,6 +5315,20 @@ async function startAgentServer(opts) {
|
|
|
5250
5315
|
return { needsWireFallbackRecreate, needsWireAgentConfigRecreate };
|
|
5251
5316
|
}
|
|
5252
5317
|
async function recreateAgentSession(overrides) {
|
|
5318
|
+
let markSwapDone;
|
|
5319
|
+
driverSwapGate.beginSwap(
|
|
5320
|
+
new Promise((resolve4) => {
|
|
5321
|
+
markSwapDone = resolve4;
|
|
5322
|
+
})
|
|
5323
|
+
);
|
|
5324
|
+
try {
|
|
5325
|
+
await driverSwapGate.awaitActiveTurn();
|
|
5326
|
+
await recreateAgentSessionInner(overrides);
|
|
5327
|
+
} finally {
|
|
5328
|
+
markSwapDone();
|
|
5329
|
+
}
|
|
5330
|
+
}
|
|
5331
|
+
async function recreateAgentSessionInner(overrides) {
|
|
5253
5332
|
const disposedManager = agentSession.resourceManager;
|
|
5254
5333
|
await agentSession.dispose();
|
|
5255
5334
|
agentSession = await createAgentSession({ ...sessionConfig, ...overrides });
|
|
@@ -5582,6 +5661,7 @@ async function startAgentServer(opts) {
|
|
|
5582
5661
|
return;
|
|
5583
5662
|
}
|
|
5584
5663
|
log(`[serve] prompt: ${cmd.prompt.slice(0, 80)}...`);
|
|
5664
|
+
await driverSwapGate.awaitSwap();
|
|
5585
5665
|
await restageMaterializedSkills(true);
|
|
5586
5666
|
const activeFlow = getOnlyActiveFlow();
|
|
5587
5667
|
if (activeFlow) {
|
|
@@ -5631,18 +5711,23 @@ async function startAgentServer(opts) {
|
|
|
5631
5711
|
});
|
|
5632
5712
|
}
|
|
5633
5713
|
sendEvent({ type: "status", phase: "thinking" });
|
|
5714
|
+
const endTurn = driverSwapGate.beginTurn();
|
|
5634
5715
|
try {
|
|
5635
5716
|
await driver.prompt(cmd.prompt);
|
|
5636
5717
|
} catch (err) {
|
|
5637
5718
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
5638
5719
|
log(`[serve] prompt failed: ${errMsg}`);
|
|
5639
5720
|
sendEvent({ type: "error", message: `Prompt failed: ${errMsg}`, fatal: true });
|
|
5721
|
+
} finally {
|
|
5722
|
+
endTurn();
|
|
5640
5723
|
}
|
|
5641
5724
|
}
|
|
5642
5725
|
async function handleReply(cmd) {
|
|
5643
5726
|
if (!await awaitSessionReadyOrFail()) return;
|
|
5644
5727
|
log(`[serve] reply: ${cmd.answer.slice(0, 80)}...`);
|
|
5728
|
+
await driverSwapGate.awaitSwap();
|
|
5645
5729
|
if (driver.hasPendingQuestion() && driver.answerQuestion(cmd.answer)) return;
|
|
5730
|
+
const endTurn = driverSwapGate.beginTurn();
|
|
5646
5731
|
try {
|
|
5647
5732
|
await driver.prompt(cmd.answer);
|
|
5648
5733
|
} catch (err) {
|
|
@@ -5651,6 +5736,8 @@ async function startAgentServer(opts) {
|
|
|
5651
5736
|
message: `Reply failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
5652
5737
|
fatal: false
|
|
5653
5738
|
});
|
|
5739
|
+
} finally {
|
|
5740
|
+
endTurn();
|
|
5654
5741
|
}
|
|
5655
5742
|
}
|
|
5656
5743
|
async function handleCancel() {
|
|
@@ -6225,5 +6312,5 @@ function touchSession(state) {
|
|
|
6225
6312
|
}
|
|
6226
6313
|
|
|
6227
6314
|
export { CLAUDE_CODE_CREDENTIALS_KEY, COMPILE_MANIFEST_FILENAME, CapabilityRegistry, DEFAULT_CAPABILITY_CALL_TIMEOUT_MS, DEFAULT_COALESCE_MS, MarkdownStreamer, PreInitRingSink, agentDefinitionExists, bootstrapCapabilityRegistry, bootstrapRunnerLogStore, buildAgentResources, buildClientCapabilityHandler, buildConnectorTokenMediator, buildContextSection, buildEnvironmentSection, buildResourcesAvailablePayload, buildStoreSnapshotReplay, builtinCapabilities, capabilityLogInstance, clearPreInitRingSink, clearSession, compileComposition, computeCapabilitySignature, connectorRefreshKind, createAgentSession, createSessionStimulusBus, defineCapability, deleteSession, dispatchRunnerCapabilityInvocation, emitSystemPromptComposed, ensureGitConfigInclude, extractClaudeAiOauthExpiresAt, getPreInitRingSink, handleMountResourceRequest, handleResourceRequest, hasNonTerminalFlow, hostOpResumeStimulus, installPreInitRingSink, isTerminalFlowStatus, listSessions, loadAgentManifest, loadCompileManifest, loadCompileManifestFromDir, loadSession, loadSessionById, mcpAuthSecretKey, newSession, pickRepointedManager, planFlowMutate, registerActiveFlow, registerCompositionCapabilities, rejectCapabilityOnApprovalDeny, resetRunnerLogStore, resolveAgentComposition, resolveAgentMixins, resolveBinding, resolveCapabilityCallTimeoutMs, resolveCapabilityResult, resolveComposition, resolveMixin, runAgentChat, saveSession, setCurrentSession, startAgentServer, stimulusFromMetas, touchSession, writeClaudeCodeCredentialsFile };
|
|
6228
|
-
//# sourceMappingURL=chunk-
|
|
6229
|
-
//# sourceMappingURL=chunk-
|
|
6315
|
+
//# sourceMappingURL=chunk-IO3K4PTB.js.map
|
|
6316
|
+
//# sourceMappingURL=chunk-IO3K4PTB.js.map
|