@ponythewhite/base-context 1.0.15 → 1.0.16
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 +9 -0
- package/dist/base-context-runtime/pyproject.toml +1 -1
- package/dist/base-context-runtime/src/rlm/bash.py +19 -0
- package/dist/base-context-runtime/src/rlm/job_watch.py +156 -0
- package/dist/base-context-runtime/src/rlm/repl.md +28 -6
- package/dist/base-context-runtime/src/rlm/repl.py +6 -1
- package/dist/base-context-runtime/test/test_bash.py +4 -4
- package/dist/base-context-runtime/test/test_job_watch.py +67 -0
- package/dist/base-context-runtime/uv.lock +1 -1
- package/dist/build-info.json +1 -1
- package/dist/bundle/{bundled-modules-O67MEO74.js → bundled-modules-2DMTK7VK.js} +2 -2
- package/dist/bundle/{chunk-RQFC34FM.js → chunk-MSH6QRP5.js} +1601 -820
- package/dist/bundle/{chunk-DGO66I3L.js → chunk-T2OK7SRV.js} +3 -2
- package/dist/bundle/{cli-main-2RER6PBE.js → cli-main-WL2L5IEQ.js} +2 -2
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/{main-YERLD3T4.js → main-XPIEIEQJ.js} +2 -2
- package/dist/core/agent-session.d.ts +2 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +155 -9
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/history-index-worker.d.ts.map +1 -1
- package/dist/core/history-index-worker.js +22 -1
- package/dist/core/history-index-worker.js.map +1 -1
- package/dist/core/history-index.d.ts +2 -0
- package/dist/core/history-index.d.ts.map +1 -1
- package/dist/core/history-index.js.map +1 -1
- package/dist/core/job-watch.d.ts +120 -0
- package/dist/core/job-watch.d.ts.map +1 -0
- package/dist/core/job-watch.js +648 -0
- package/dist/core/job-watch.js.map +1 -0
- package/dist/core/kernel/repl-manager.d.ts +5 -1
- package/dist/core/kernel/repl-manager.d.ts.map +1 -1
- package/dist/core/kernel/repl-manager.js +52 -0
- package/dist/core/kernel/repl-manager.js.map +1 -1
- package/dist/core/kernel/shared.d.ts +12 -0
- package/dist/core/kernel/shared.d.ts.map +1 -1
- package/dist/core/kernel/shared.js.map +1 -1
- package/dist/core/prompts/rlm.d.ts.map +1 -1
- package/dist/core/prompts/rlm.js +49 -39
- package/dist/core/prompts/rlm.js.map +1 -1
- package/dist/core/session-manager.d.ts +2 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +9 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/tools/prime-context.d.ts.map +1 -1
- package/dist/core/tools/prime-context.js +1 -1
- package/dist/core/tools/prime-context.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +2 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/skills/agent-message/SKILL.md +8 -2
- package/dist/skills/bounded-inspect/SKILL.md +78 -0
- package/dist/skills/bounded-inspect/pyproject.toml +16 -0
- package/dist/skills/bounded-inspect/src/bounded_inspect/__init__.py +313 -0
- package/dist/skills/bounded-inspect/src/bounded_inspect/__main__.py +3 -0
- package/dist/skills/job-watch/SKILL.md +43 -0
- package/dist/skills/job-watch/pyproject.toml +13 -0
- package/dist/skills/job-watch/src/job_watch/__init__.py +61 -0
- package/dist/skills/rlm-heartbeat/SKILL.md +10 -6
- package/dist/utils/file-lines.d.ts.map +1 -1
- package/dist/utils/file-lines.js +6 -2
- package/dist/utils/file-lines.js.map +1 -1
- package/docs/rlm-runtime.md +4 -1
- package/docs/skills.md +18 -26
- package/package.json +4 -4
- package/skills/agent-message/SKILL.md +8 -2
- package/skills/bounded-inspect/SKILL.md +78 -0
- package/skills/bounded-inspect/pyproject.toml +16 -0
- package/skills/bounded-inspect/src/bounded_inspect/__init__.py +313 -0
- package/skills/bounded-inspect/src/bounded_inspect/__main__.py +3 -0
- package/skills/job-watch/SKILL.md +43 -0
- package/skills/job-watch/pyproject.toml +13 -0
- package/skills/job-watch/src/job_watch/__init__.py +61 -0
- package/skills/rlm-heartbeat/SKILL.md +10 -6
|
@@ -27,6 +27,7 @@ import { ExtensionRunner, wrapRegisteredTools, } from "./extensions/index.js";
|
|
|
27
27
|
import { emitSessionShutdownEvent } from "./extensions/runner.js";
|
|
28
28
|
import { createGoalContextMessage, emptyGoalState, GOAL_CONTEXT_CUSTOM_TYPE, GOAL_CONTEXT_PREVIEW_LABEL, GOAL_SKILL_NAME, GOAL_STATE_CUSTOM_TYPE, goalHostResponse, goalTokenDeltaForUsage, isPersistedGoalState, normalizeGoalState, validateGoalBudget, validateGoalObjective, } from "./goals.js";
|
|
29
29
|
import { captureNativeBranchRequests, captureNativeCompactionRequests, captureNativePlannerRequests, captureNativeReviewerRequests, InferenceCoordinator, takeNativeInferenceAuthSource, } from "./inference-coordinator.js";
|
|
30
|
+
import { JOB_WATCH_STATE, JobWatchController } from "./job-watch.js";
|
|
30
31
|
import { snapshotPathIn } from "./kernel/state-snapshot.js";
|
|
31
32
|
import { convertToLlm, createCompactionOutcomeMessage, createHeartbeatPromptMessage, createRefinementOutcomeMessage, createRlmChildFailureMessage, createRlmChildTerminalNoticeMessage, createSessionSlashCommandMessage, createSessionSlashCommandResultMessage, HARNESS_SNAPSHOT_CUSTOM_TYPE, HEARTBEAT_PROMPT_CUSTOM_TYPE, HEARTBEAT_PROMPT_PREVIEW_LABEL, IPYTHON_STATE_RESTORED_CUSTOM_TYPE, isSessionSlashCommandMessage, RLM_CHILD_FAILURE_CUSTOM_TYPE, RLM_CHILD_TERMINAL_NOTICE_CUSTOM_TYPE, } from "./messages.js";
|
|
32
33
|
import { throwIfPromptAdmissionCancelled } from "./prompt-admission.js";
|
|
@@ -35,6 +36,7 @@ import { appendGlobalRefinement, applyRefinementProposal, formatHarnessStateForP
|
|
|
35
36
|
import { getRecoveryCompactionAuthorization, PublicContextBudgetError } from "./request-view-selection.js";
|
|
36
37
|
import { resolveConfigValue } from "./resolve-config-value.js";
|
|
37
38
|
import { assertResourceCurrent } from "./resource-view.js";
|
|
39
|
+
import { retainToolOutput } from "./retained-tool-output.js";
|
|
38
40
|
import { createDefaultRlmSubagentSessionName, createRlmDeleteSubagentHostHandler, createRlmFindModelsHostHandler, createRlmListSubagentsHostHandler, createRlmRunHostHandler, findRlmModelMatches, normalizeRequestedRlmSubagentModel, normalizeRequestedRlmSubagentSessionName, normalizeRequestedRlmSubagentThinkingLevel, } from "./rlm-runtime.js";
|
|
39
41
|
import { captureSelectedSkill, captureSkillDescriptor, readSkillSelection, sameSelectedSkills, selectedSkillBlock, selectedSkillIdentity, } from "./selected-skills.js";
|
|
40
42
|
import { createNativeRecoveryRefusal, DEFAULT_NATIVE_RECOVERY_LIMITS, NativeRecoveryBudgetRefusal, NativeRecoveryCursorStore, parseNativeRecoveryInput, recoverCapturedHistory, } from "./selective-recovery.js";
|
|
@@ -328,6 +330,7 @@ export class AgentSession {
|
|
|
328
330
|
_goalStateRevision = 0;
|
|
329
331
|
_goalAccountingStartedAt = undefined;
|
|
330
332
|
_goalContinuationAwaitsRlmWork = false;
|
|
333
|
+
_jobWatchController;
|
|
331
334
|
_goalAccountedAssistantMessages = new WeakSet();
|
|
332
335
|
_goalAbortInProgress = false;
|
|
333
336
|
_autonomousState;
|
|
@@ -1110,6 +1113,10 @@ export class AgentSession {
|
|
|
1110
1113
|
activeToolNames: this._initialActiveToolNames,
|
|
1111
1114
|
includeAllExtensionTools: true,
|
|
1112
1115
|
});
|
|
1116
|
+
if (bootstrap.jobWatchState)
|
|
1117
|
+
await this._getJobWatchController().restore(bootstrap.jobWatchState);
|
|
1118
|
+
if (bootstrap.jobWatchUnavailable)
|
|
1119
|
+
this._surfaceSessionInputError(new Error(bootstrap.jobWatchUnavailable));
|
|
1113
1120
|
if (this._goalState.status === "active" &&
|
|
1114
1121
|
this._includeGoals &&
|
|
1115
1122
|
!this.getActiveToolNames().includes("ipython")) {
|
|
@@ -1625,8 +1632,28 @@ export class AgentSession {
|
|
|
1625
1632
|
!isPersistedRlmMaxDepthState(hydrated.entry.data))
|
|
1626
1633
|
throw new Error("Bootstrap RLM depth source is unavailable or ineligible");
|
|
1627
1634
|
rlmMaxDepth = hydrated.entry.data;
|
|
1635
|
+
remaining -= bootstrap.rlmMaxDepth.locator.length;
|
|
1636
|
+
}
|
|
1637
|
+
let jobWatchState;
|
|
1638
|
+
let jobWatchUnavailable = bootstrap.jobWatchUnavailable
|
|
1639
|
+
? `Monitoring unavailable: optional job-watch bootstrap candidate budget exceeded. Inspect ${this.sessionManager.getSessionFile()}; no watches were resumed.`
|
|
1640
|
+
: undefined;
|
|
1641
|
+
if (bootstrap.jobWatchState) {
|
|
1642
|
+
if (bootstrap.jobWatchState.locator.length >
|
|
1643
|
+
Math.min(remaining, 64 * 1024 + 1024, Math.floor(maxSourceBytes / 2) + 1024)) {
|
|
1644
|
+
jobWatchUnavailable = `Monitoring unavailable: optional job-watch state exceeds the existing source budget. Inspect ${this.sessionManager.getSessionFile()} entry ${bootstrap.jobWatchState.id}; no watches were resumed.`;
|
|
1645
|
+
}
|
|
1646
|
+
else {
|
|
1647
|
+
const hydrated = await view.hydrateEntry(bootstrap.jobWatchState.id, remaining);
|
|
1648
|
+
if (hydrated?.entry.type === "custom" &&
|
|
1649
|
+
hydrated.entry.customType === JOB_WATCH_STATE &&
|
|
1650
|
+
hydrated.source.retention !== "retained-import")
|
|
1651
|
+
jobWatchState = hydrated.entry.data;
|
|
1652
|
+
}
|
|
1628
1653
|
}
|
|
1629
1654
|
return {
|
|
1655
|
+
jobWatchState,
|
|
1656
|
+
jobWatchUnavailable,
|
|
1630
1657
|
goalState,
|
|
1631
1658
|
goalSeedable: bootstrap.goalSeedable,
|
|
1632
1659
|
rlmMaxDepth,
|
|
@@ -1675,6 +1702,8 @@ export class AgentSession {
|
|
|
1675
1702
|
return true;
|
|
1676
1703
|
}
|
|
1677
1704
|
async _reloadBranchRuntimeState() {
|
|
1705
|
+
this._jobWatchController?.dispose();
|
|
1706
|
+
this._jobWatchController = undefined;
|
|
1678
1707
|
this._contextMode = await this._readContextMode();
|
|
1679
1708
|
const bootstrap = this.sessionManager.isPersisted()
|
|
1680
1709
|
? await this._readRuntimeBootstrap()
|
|
@@ -2123,7 +2152,10 @@ export class AgentSession {
|
|
|
2123
2152
|
async _resumeGoalContinuationAfterRlmWork() {
|
|
2124
2153
|
if (!this._goalContinuationAwaitsRlmWork)
|
|
2125
2154
|
return;
|
|
2126
|
-
if (this._disposed ||
|
|
2155
|
+
if (this._disposed ||
|
|
2156
|
+
this._disposing ||
|
|
2157
|
+
this._hasUnsettledRlmQuiescenceWork() ||
|
|
2158
|
+
this._jobWatchController?.isParked())
|
|
2127
2159
|
return;
|
|
2128
2160
|
if (this._goalState.status !== "active" || !this._goalState.objective) {
|
|
2129
2161
|
this._goalContinuationAwaitsRlmWork = false;
|
|
@@ -3002,7 +3034,9 @@ export class AgentSession {
|
|
|
3002
3034
|
: undefined;
|
|
3003
3035
|
}
|
|
3004
3036
|
async _queueAutonomousContinuationForThresholdCompaction(message, owner = this._captureCompactionOwner(this.agent.signal), capture = this._captureThresholdAutonomousOwner()) {
|
|
3005
|
-
if (!this._isCompactionOwnerCurrent(owner) ||
|
|
3037
|
+
if (!this._isCompactionOwnerCurrent(owner) ||
|
|
3038
|
+
!this._contextOptimizationAllowed() ||
|
|
3039
|
+
this._jobWatchController?.isParked())
|
|
3006
3040
|
return undefined;
|
|
3007
3041
|
const queued = this._queuedAutonomousThresholdContinuations.get(message);
|
|
3008
3042
|
if (queued && this._checkpointActionPending(queued))
|
|
@@ -3059,7 +3093,7 @@ export class AgentSession {
|
|
|
3059
3093
|
return undefined;
|
|
3060
3094
|
if (message.stopReason === "error" || message.stopReason === "aborted")
|
|
3061
3095
|
return undefined;
|
|
3062
|
-
if (owner.goal.status !== "active" || !owner.goal.objective)
|
|
3096
|
+
if (owner.goal.status !== "active" || !owner.goal.objective || this._jobWatchController?.isParked())
|
|
3063
3097
|
return undefined;
|
|
3064
3098
|
const queued = this._queuedGoalThresholdContinuation;
|
|
3065
3099
|
if (queued && this._checkpointActionPending(queued))
|
|
@@ -3548,6 +3582,8 @@ export class AgentSession {
|
|
|
3548
3582
|
if (this._goalState.status !== "active" || !this._goalState.objective) {
|
|
3549
3583
|
return { kind: "finish" };
|
|
3550
3584
|
}
|
|
3585
|
+
if (this._jobWatchController?.isParked())
|
|
3586
|
+
return { kind: "wait_for_owned_work" };
|
|
3551
3587
|
// Delegating and ending the turn is correct behavior; retain the existing wakeup owner.
|
|
3552
3588
|
if (this._hasUnsettledRlmQuiescenceWork()) {
|
|
3553
3589
|
this._goalContinuationAwaitsRlmWork = true;
|
|
@@ -3590,6 +3626,8 @@ export class AgentSession {
|
|
|
3590
3626
|
return this._stoppedContinuationOutcome(signal);
|
|
3591
3627
|
if (this.queuedActionCount > 0)
|
|
3592
3628
|
return { kind: "finish" };
|
|
3629
|
+
if (this._jobWatchController?.isParked())
|
|
3630
|
+
return { kind: "wait_for_owned_work" };
|
|
3593
3631
|
const owner = this._captureGoalContinuationOwner(signal);
|
|
3594
3632
|
const arrivalEpoch = this._sessionInputArrivalEpoch;
|
|
3595
3633
|
const goalSnapshot = owner.goal;
|
|
@@ -4412,6 +4450,13 @@ export class AgentSession {
|
|
|
4412
4450
|
await drain(() => this._agentEventQueue);
|
|
4413
4451
|
await drain(() => this._goalResumeOperation);
|
|
4414
4452
|
await drain(() => this._waitForChildUsageWrites());
|
|
4453
|
+
if (this._jobWatchController) {
|
|
4454
|
+
const undelivered = new Set(this._actionStore
|
|
4455
|
+
.unfinishedActions()
|
|
4456
|
+
.filter((action) => action.queueKey && action.payload.kind === "turn" && !primaryDeliveryRecord(action).durable)
|
|
4457
|
+
.map((action) => action.queueKey));
|
|
4458
|
+
await drain(() => this._jobWatchController?.settleShutdown(undelivered));
|
|
4459
|
+
}
|
|
4415
4460
|
await drain(() => this.dispose());
|
|
4416
4461
|
}
|
|
4417
4462
|
catch (error) {
|
|
@@ -4460,6 +4505,7 @@ export class AgentSession {
|
|
|
4460
4505
|
}
|
|
4461
4506
|
this.requests.stopAdmission();
|
|
4462
4507
|
this._disposed = true;
|
|
4508
|
+
this._jobWatchController?.dispose();
|
|
4463
4509
|
for (const run of this._unsettledRlmChildRuns)
|
|
4464
4510
|
run.suppressTerminalNotice = true;
|
|
4465
4511
|
for (const controller of this._rlmQuiescenceWaitAborts)
|
|
@@ -4812,10 +4858,10 @@ export class AgentSession {
|
|
|
4812
4858
|
/** Persist mutable advice before the request owner captures its source and epoch ACK boundary. */
|
|
4813
4859
|
async _appendHarnessSnapshotIfChanged() {
|
|
4814
4860
|
const manager = this.sessionManager;
|
|
4815
|
-
|
|
4816
|
-
|
|
4861
|
+
const sourceIsCurrent = manager.captureCompactionContentOwner();
|
|
4862
|
+
let ownAppends = 0;
|
|
4817
4863
|
const assertCurrent = () => {
|
|
4818
|
-
if (this._disposed || this.sessionManager !== manager || !sourceIsCurrent()
|
|
4864
|
+
if (this._disposed || this.sessionManager !== manager || !sourceIsCurrent(ownAppends))
|
|
4819
4865
|
throw new Error("Harness snapshot source changed before request ownership");
|
|
4820
4866
|
};
|
|
4821
4867
|
let previous;
|
|
@@ -4844,8 +4890,9 @@ export class AgentSession {
|
|
|
4844
4890
|
});
|
|
4845
4891
|
if (previous === content)
|
|
4846
4892
|
return assertCurrent;
|
|
4847
|
-
|
|
4848
|
-
|
|
4893
|
+
await manager.appendCustomMessageEntryWithRollback(HARNESS_SNAPSHOT_CUSTOM_TYPE, content, false);
|
|
4894
|
+
ownAppends++;
|
|
4895
|
+
if (this._disposed || this.sessionManager !== manager || !sourceIsCurrent(ownAppends))
|
|
4849
4896
|
throw new Error("Harness snapshot source changed during append");
|
|
4850
4897
|
if (!manager.isPersisted())
|
|
4851
4898
|
this.agent.state.messages.push({
|
|
@@ -4855,7 +4902,6 @@ export class AgentSession {
|
|
|
4855
4902
|
display: false,
|
|
4856
4903
|
timestamp: Date.now(),
|
|
4857
4904
|
});
|
|
4858
|
-
leafId = entryId;
|
|
4859
4905
|
return assertCurrent;
|
|
4860
4906
|
}
|
|
4861
4907
|
_refreshExtensionSystemPrompt(extensionPrompt, baseSnapshot) {
|
|
@@ -7065,6 +7111,7 @@ export class AgentSession {
|
|
|
7065
7111
|
this._advanceCheckpointPauseEpoch();
|
|
7066
7112
|
this._notifySessionInputCheckpointChange();
|
|
7067
7113
|
this._flushDeferredRlmTerminalNotices();
|
|
7114
|
+
void this._jobWatchController?.flushPending().catch((error) => this._surfaceSessionInputError(error));
|
|
7068
7115
|
this._scheduleGoalContinuationAfterRlmWork();
|
|
7069
7116
|
this._scheduleSessionInputPump();
|
|
7070
7117
|
},
|
|
@@ -7181,6 +7228,7 @@ export class AgentSession {
|
|
|
7181
7228
|
this._sessionInputPumpEpoch++;
|
|
7182
7229
|
this._notifySessionInputCheckpointChange();
|
|
7183
7230
|
this._flushDeferredRlmTerminalNotices();
|
|
7231
|
+
void this._jobWatchController?.flushPending().catch((error) => this._surfaceSessionInputError(error));
|
|
7184
7232
|
}
|
|
7185
7233
|
/** Resume the scheduler after requestAbort/abortForUpdateRestart suspended it; owned pause leases are unaffected. */
|
|
7186
7234
|
resumeQueuedWork() {
|
|
@@ -10027,6 +10075,75 @@ export class AgentSession {
|
|
|
10027
10075
|
return createNativeRecoveryRefusal("unavailable", "captured_history_unavailable", responseBytes);
|
|
10028
10076
|
}
|
|
10029
10077
|
}
|
|
10078
|
+
_getJobWatchController() {
|
|
10079
|
+
if (this._jobWatchController?.isCurrent())
|
|
10080
|
+
return this._jobWatchController;
|
|
10081
|
+
this._jobWatchController?.dispose();
|
|
10082
|
+
const manager = this.sessionManager;
|
|
10083
|
+
const ownsSource = manager.captureCompactionSourceOwner();
|
|
10084
|
+
const controller = new JobWatchController({
|
|
10085
|
+
sessionId: manager.getSessionId(),
|
|
10086
|
+
sessionFile: manager.getSessionFile(),
|
|
10087
|
+
current: () => !this._disposed && !this._disposing && this.sessionManager === manager && ownsSource(),
|
|
10088
|
+
goalId: () => this._goalState.goalId,
|
|
10089
|
+
persist: async (state) => {
|
|
10090
|
+
if (this.sessionManager !== manager || !ownsSource())
|
|
10091
|
+
return;
|
|
10092
|
+
await manager.appendCustomEntry(JOB_WATCH_STATE, state);
|
|
10093
|
+
},
|
|
10094
|
+
waitForDelivery: true,
|
|
10095
|
+
stateBudgetBytes: Math.min(64 * 1024, Math.floor(this.settingsManager.getCanonicalContextLimits().maxSourceBytes / 2)),
|
|
10096
|
+
probe: async (request) => {
|
|
10097
|
+
const kernel = await this._ipythonKernelProvisioner?.ensure();
|
|
10098
|
+
if (!kernel?.jobWatchProbe)
|
|
10099
|
+
throw new Error("Kernel job_watch_probe_v1 is unavailable");
|
|
10100
|
+
const result = await kernel.jobWatchProbe({
|
|
10101
|
+
watchId: request.id,
|
|
10102
|
+
generation: request.generation,
|
|
10103
|
+
resourceId: request.resource_id,
|
|
10104
|
+
jobId: request.job_id,
|
|
10105
|
+
completionSource: request.completion_source,
|
|
10106
|
+
command: request.command ?? null,
|
|
10107
|
+
timeoutMs: request.timeout_ms,
|
|
10108
|
+
});
|
|
10109
|
+
await controller.observe({ id: request.id, generation: request.generation, ...result });
|
|
10110
|
+
},
|
|
10111
|
+
cancelProbe: (id) => this._ipythonKernelProvisioner?.manager?.cancelJobWatchProbe?.(id),
|
|
10112
|
+
retain: async (output) => {
|
|
10113
|
+
const directory = manager.getSessionArtifactDir();
|
|
10114
|
+
if (!directory)
|
|
10115
|
+
return undefined;
|
|
10116
|
+
const retained = await retainToolOutput(directory, [output], false);
|
|
10117
|
+
return join(directory, retained.artifactId);
|
|
10118
|
+
},
|
|
10119
|
+
onError: (error) => this._surfaceSessionInputError(error),
|
|
10120
|
+
admit: (text, eventId) => {
|
|
10121
|
+
if (this._sessionInputAdmissionPauses.size)
|
|
10122
|
+
return false;
|
|
10123
|
+
const content = `[job-watch] ${text}`;
|
|
10124
|
+
const admission = this._admitSessionInput(this._createPreparedTurnAction("followUp", content, undefined, {
|
|
10125
|
+
message: {
|
|
10126
|
+
role: "custom",
|
|
10127
|
+
customType: "job_watch_event",
|
|
10128
|
+
content,
|
|
10129
|
+
display: true,
|
|
10130
|
+
timestamp: Date.now(),
|
|
10131
|
+
},
|
|
10132
|
+
queueKey: eventId,
|
|
10133
|
+
resumeIfIdle: !this._sessionInputPumpSuspended,
|
|
10134
|
+
}), { wake: !this._sessionInputPumpSuspended });
|
|
10135
|
+
if (admission.ticket)
|
|
10136
|
+
void admission.ticket.delivered
|
|
10137
|
+
.then((outcome) => outcome.status === "delivered"
|
|
10138
|
+
? controller.acknowledge(eventId)
|
|
10139
|
+
: controller.releaseDelivery(eventId, true), () => controller.releaseDelivery(eventId, false))
|
|
10140
|
+
.catch((error) => this._surfaceSessionInputError(error));
|
|
10141
|
+
return admission.accepted;
|
|
10142
|
+
},
|
|
10143
|
+
});
|
|
10144
|
+
this._jobWatchController = controller;
|
|
10145
|
+
return controller;
|
|
10146
|
+
}
|
|
10030
10147
|
_createKernelHostHandlers() {
|
|
10031
10148
|
const handlers = {
|
|
10032
10149
|
prime_context: async (payload, context) => {
|
|
@@ -10073,6 +10190,35 @@ export class AgentSession {
|
|
|
10073
10190
|
handlers[type] = async (payload) => this.handleRlmHeartbeatHostRequest(type, payload);
|
|
10074
10191
|
}
|
|
10075
10192
|
}
|
|
10193
|
+
for (const type of ["watch", "status", "park", "unregister", "observation"]) {
|
|
10194
|
+
handlers[`job_watch.${type}`] = async (payload) => {
|
|
10195
|
+
if (this._disposed || this._disposing)
|
|
10196
|
+
throw new Error("Job watch source owner changed");
|
|
10197
|
+
if (type === "observation" && !this._jobWatchController?.isCurrent())
|
|
10198
|
+
return { ignored: true };
|
|
10199
|
+
const controller = this._getJobWatchController();
|
|
10200
|
+
switch (type) {
|
|
10201
|
+
case "watch":
|
|
10202
|
+
return { ...(await controller.watch(payload)) };
|
|
10203
|
+
case "status":
|
|
10204
|
+
return controller.status(typeof payload.id === "string" ? payload.id : undefined);
|
|
10205
|
+
case "park":
|
|
10206
|
+
if (!Array.isArray(payload.ids) || !payload.ids.every((id) => typeof id === "string"))
|
|
10207
|
+
throw new Error("park requires watch ids");
|
|
10208
|
+
return controller.park(payload.ids);
|
|
10209
|
+
case "unregister":
|
|
10210
|
+
return controller.unregister(String(payload.id));
|
|
10211
|
+
default:
|
|
10212
|
+
if (typeof payload.id !== "string" ||
|
|
10213
|
+
typeof payload.generation !== "string" ||
|
|
10214
|
+
!payload.result ||
|
|
10215
|
+
typeof payload.result !== "object")
|
|
10216
|
+
throw new Error("Invalid job watch observation");
|
|
10217
|
+
await controller.observe({ ...payload.result, id: payload.id, generation: payload.generation });
|
|
10218
|
+
return {};
|
|
10219
|
+
}
|
|
10220
|
+
};
|
|
10221
|
+
}
|
|
10076
10222
|
const visibleKernelSkillNames = new Set(this._modelVisibleSkills()
|
|
10077
10223
|
.filter((skill) => !skill.disableModelInvocation)
|
|
10078
10224
|
.map((skill) => skill.name));
|