kiokuko-dsh 0.2.26 → 0.2.27
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/dist/context/replay-model-memory.d.ts +2 -2
- package/dist/context/replay-model-memory.d.ts.map +1 -1
- package/dist/context/replay-model-memory.js +70 -16
- package/dist/context/replay-model-memory.js.map +1 -1
- package/dist/dsh/host-adapter/lifecycle.d.ts +20 -18
- package/dist/dsh/host-adapter/lifecycle.d.ts.map +1 -1
- package/dist/dsh/host-adapter/lifecycle.js +298 -102
- package/dist/dsh/host-adapter/lifecycle.js.map +1 -1
- package/dist/dsh/host-adapter.d.ts +47 -47
- package/dist/dsh/host-adapter.d.ts.map +1 -1
- package/dist/dsh/host-adapter.js +1213 -592
- package/dist/dsh/host-adapter.js.map +1 -1
- package/dist/dsh/index.d.ts +42 -41
- package/dist/dsh/index.d.ts.map +1 -1
- package/dist/dsh/index.js +166 -92
- package/dist/dsh/index.js.map +1 -1
- package/dist/dsh/lifecycle-memory.d.ts +11 -7
- package/dist/dsh/lifecycle-memory.d.ts.map +1 -1
- package/dist/dsh/lifecycle-memory.js +599 -172
- package/dist/dsh/lifecycle-memory.js.map +1 -1
- package/dist/dsh/task-completion.d.ts +7 -7
- package/dist/dsh/task-completion.d.ts.map +1 -1
- package/dist/dsh/task-completion.js +554 -194
- package/dist/dsh/task-completion.js.map +1 -1
- package/dist/dsh/task-state-host.d.ts +10 -10
- package/dist/dsh/task-state-host.d.ts.map +1 -1
- package/dist/dsh/task-state-host.js +337 -145
- package/dist/dsh/task-state-host.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/locale/en.json +1 -1
- package/dist/locale/ja.json +1 -1
- package/dist/locale/ko.json +1 -1
- package/dist/locale/zh-CN.json +1 -1
- package/dist/memory/replay-reflection.d.ts +94 -0
- package/dist/memory/replay-reflection.d.ts.map +1 -0
- package/dist/memory/replay-reflection.js +149 -0
- package/dist/memory/replay-reflection.js.map +1 -0
- package/dist/memory/replay-review.d.ts +18 -12
- package/dist/memory/replay-review.d.ts.map +1 -1
- package/dist/memory/replay-review.js +107 -46
- package/dist/memory/replay-review.js.map +1 -1
- package/package.json +2 -1
package/dist/dsh/host-adapter.js
CHANGED
|
@@ -1,147 +1,147 @@
|
|
|
1
|
-
import { assessRequestIntent } from
|
|
2
|
-
import { nativeExecutionOwnership } from
|
|
3
|
-
import { NativeTaskAuthority } from
|
|
4
|
-
import { readOwnedIdentity } from
|
|
5
|
-
import { NativeWorkerRouting } from
|
|
6
|
-
import { validateHeadWorker } from
|
|
7
|
-
import { getHeadWorkerSessionSelection, clearHeadWorkerForSession, updateHeadWorkerEffortForSession } from
|
|
8
|
-
import { answerSkillContext } from
|
|
9
|
-
import { DshAnswerContext } from
|
|
10
|
-
import { IntakeModeConfig } from
|
|
11
|
-
import { OnDemandIntake } from
|
|
12
|
-
import { LISP_ASSEMBLY_SERVICE } from
|
|
13
|
-
import { DshTaskWorkflow, TASK_STATE_EVENT, TASK_WORKFLOW_SERVICE } from
|
|
14
|
-
import { mountOwnedExecution } from
|
|
15
|
-
import { mountPlanTransition } from
|
|
16
|
-
import { classifyTaskForIntake } from
|
|
17
|
-
import { classifyRequestIntent, requestIntentMessageRefs } from
|
|
18
|
-
import { authorizeTaskLease } from
|
|
19
|
-
import { dshTurnRequestId } from
|
|
20
|
-
import { resolveProjectWorkspaceReadOnly } from
|
|
21
|
-
import { MemoryIndexReasoningConfig } from
|
|
22
|
-
import { createTurnState } from
|
|
23
|
-
import { createRouting } from
|
|
24
|
-
import { createAdmission } from
|
|
25
|
-
import { createSessionObservation } from
|
|
26
|
-
import { createContextMessages } from
|
|
27
|
-
import { createToolHost } from
|
|
28
|
-
import { createBoundaries } from
|
|
29
|
-
import { isNativeSubagent } from
|
|
30
|
-
import { createLifecycle } from
|
|
31
|
-
import { mountHostMemoryApplication } from
|
|
32
|
-
import { mountTaskCompletion } from
|
|
33
|
-
import { mountCodingWorkflow } from
|
|
34
|
-
import { readCodingWorkflow } from
|
|
35
|
-
import { stableLispCapabilities } from
|
|
36
|
-
import { createEfficiencyHost } from
|
|
37
|
-
import { createMemoryReviewHost } from
|
|
38
|
-
import { createEnnoMemoryHost } from
|
|
39
|
-
import { createSessionAccess } from
|
|
40
|
-
import { createEvolutionHost } from
|
|
41
|
-
import { onNativeEvent, onNativeServiceEvent } from
|
|
42
|
-
import { isKiokukoDshSource, KIOKUKO_DSH_SOURCE_KIND } from
|
|
43
|
-
import { SemanticCompactionCoordinator } from
|
|
44
|
-
import { ModelHandoff } from
|
|
45
|
-
import { DshLifecycleMemory } from
|
|
46
|
-
import { ModelAutoConfig } from
|
|
47
|
-
import { ModelAutoCoordinator } from
|
|
48
|
-
import { ModelAutoStore } from
|
|
49
|
-
import { SemanticCompactionConfig } from
|
|
50
|
-
import { MemoryReuseConfig } from
|
|
51
|
-
import { createDecisionService } from
|
|
52
|
-
import { createIntakeDiagnosticSink } from
|
|
53
|
-
import { TypedDecisionsConfig } from
|
|
54
|
-
import { AnswerReviewCoordinator } from
|
|
55
|
-
import { AnswerReviewConfig } from
|
|
56
|
-
import { AutoMemoryReviewCoordinator } from
|
|
57
|
-
import { MemoryReviewConfig } from
|
|
58
|
-
import { MemoryRetrievalConfig } from
|
|
59
|
-
import { DshEnnoMemoryRefresh } from
|
|
60
|
-
import { EnnoMemoryConfig } from
|
|
61
|
-
import { CompletionConfig } from
|
|
62
|
-
import { saveSessionNotice } from
|
|
63
|
-
import { MemoryEvolutionConfig } from
|
|
64
|
-
import { AgenticReplayConfig, EfficiencyConfig, FinalizationConfig, AkinatorMemoryConfig, ContinuityConfig } from
|
|
65
|
-
import { readExecutionSelection, writeExecutionSelection } from
|
|
66
|
-
import { LISP_CODING_SERVICE } from
|
|
67
|
-
import { DshSkillPrompts } from
|
|
68
|
-
import { nativeModelCatalog } from
|
|
69
|
-
import { DshEnnoDelegation } from
|
|
70
|
-
import { createDshAgenticReplayHost } from
|
|
71
|
-
import { fileURLToPath } from
|
|
72
|
-
import { realpathSync } from
|
|
73
|
-
import { KIOKUKO_DSH_HOST_SERVICE } from
|
|
74
|
-
import { DshRuntime } from
|
|
75
|
-
import { DshToolPolicy } from
|
|
76
|
-
import { ToolExposureConfig } from
|
|
77
|
-
import { DiffReviewConfig } from
|
|
78
|
-
import { DiffReviewController } from
|
|
79
|
-
import { DshMemoryFinalizer } from
|
|
80
|
-
import { DshPonytailModes } from
|
|
81
|
-
import { createDshConfirmationAnswerer } from
|
|
82
|
-
import { createDshCapabilityCatalog } from
|
|
83
|
-
import { STANDARD_SKILL_MANIFESTS } from
|
|
84
|
-
import { canonicalContentHash, compareCanonicalStrings } from
|
|
85
|
-
import { KiokukoError } from
|
|
86
|
-
import { stateForSnapshot } from
|
|
87
|
-
import { readEnnoSnapshot } from
|
|
88
|
-
import { DeepPlanningController } from
|
|
89
|
-
import { DshSessionLogMirror } from
|
|
90
|
-
import { DshExecutionSupport } from
|
|
1
|
+
import { assessRequestIntent } from "./decisions/intent-assessment.js";
|
|
2
|
+
import { nativeExecutionOwnership } from "./native-execution-ownership.js";
|
|
3
|
+
import { NativeTaskAuthority } from "./native-task-authority.js";
|
|
4
|
+
import { readOwnedIdentity } from "./owned-read-owner.js";
|
|
5
|
+
import { NativeWorkerRouting } from "./native-worker-routing.js";
|
|
6
|
+
import { validateHeadWorker } from "./head-worker-configuration.js";
|
|
7
|
+
import { getHeadWorkerSessionSelection, clearHeadWorkerForSession, updateHeadWorkerEffortForSession, } from "./models/session-selection.js";
|
|
8
|
+
import { answerSkillContext, } from "./answer-skills.js";
|
|
9
|
+
import { DshAnswerContext } from "./answer-context.js";
|
|
10
|
+
import { IntakeModeConfig } from "./intake-mode.js";
|
|
11
|
+
import { OnDemandIntake } from "./on-demand-intake.js";
|
|
12
|
+
import { LISP_ASSEMBLY_SERVICE } from "./lisp-service-key.js";
|
|
13
|
+
import { DshTaskWorkflow, TASK_STATE_EVENT, TASK_WORKFLOW_SERVICE, } from "./task-state-host.js";
|
|
14
|
+
import { mountOwnedExecution } from "./owned-execution.js";
|
|
15
|
+
import { mountPlanTransition } from "./plan-transition.js";
|
|
16
|
+
import { classifyTaskForIntake } from "./decisions/workflows.js";
|
|
17
|
+
import { classifyRequestIntent, requestIntentMessageRefs, } from "./decisions/request-intent.js";
|
|
18
|
+
import { authorizeTaskLease } from "./task-state.js";
|
|
19
|
+
import { dshTurnRequestId } from "./intake-profile-resolver.js";
|
|
20
|
+
import { resolveProjectWorkspaceReadOnly } from "../memory/workspaces.js";
|
|
21
|
+
import { MemoryIndexReasoningConfig } from "../memory/index-reasoning/contracts.js";
|
|
22
|
+
import { createTurnState, } from "./host-adapter/turn-state.js";
|
|
23
|
+
import { createRouting } from "./host-adapter/routing.js";
|
|
24
|
+
import { createAdmission } from "./host-adapter/admission.js";
|
|
25
|
+
import { createSessionObservation } from "./host-adapter/session-observation.js";
|
|
26
|
+
import { createContextMessages } from "./host-adapter/context.js";
|
|
27
|
+
import { createToolHost } from "./host-adapter/tool-host.js";
|
|
28
|
+
import { createBoundaries } from "./host-adapter/boundaries.js";
|
|
29
|
+
import { isNativeSubagent } from "./native-subagent.js";
|
|
30
|
+
import { createLifecycle } from "./host-adapter/lifecycle.js";
|
|
31
|
+
import { mountHostMemoryApplication } from "./host-adapter/memory-application-host.js";
|
|
32
|
+
import { mountTaskCompletion } from "./task-completion-host.js";
|
|
33
|
+
import { mountCodingWorkflow } from "./coding-workflow/host.js";
|
|
34
|
+
import { readCodingWorkflow } from "./coding-workflow/store.js";
|
|
35
|
+
import { stableLispCapabilities } from "./lisp-service-key.js";
|
|
36
|
+
import { createEfficiencyHost } from "./host-adapter/efficiency-host.js";
|
|
37
|
+
import { createMemoryReviewHost } from "./host-adapter/memory-review-host.js";
|
|
38
|
+
import { createEnnoMemoryHost } from "./host-adapter/enno-memory-host.js";
|
|
39
|
+
import { createSessionAccess } from "./host-adapter/session-access.js";
|
|
40
|
+
import { createEvolutionHost } from "./host-adapter/evolution-host.js";
|
|
41
|
+
import { onNativeEvent, onNativeServiceEvent, } from "./host-adapter/native-events.js";
|
|
42
|
+
import { isKiokukoDshSource, KIOKUKO_DSH_SOURCE_KIND, } from "./plugin-source.js";
|
|
43
|
+
import { SemanticCompactionCoordinator } from "./semantic-compaction/coordinator.js";
|
|
44
|
+
import { ModelHandoff } from "./model-handoff.js";
|
|
45
|
+
import { DshLifecycleMemory } from "./lifecycle-memory.js";
|
|
46
|
+
import { ModelAutoConfig } from "./model-auto/contracts.js";
|
|
47
|
+
import { ModelAutoCoordinator } from "./model-auto/coordinator.js";
|
|
48
|
+
import { ModelAutoStore } from "./model-auto/store.js";
|
|
49
|
+
import { SemanticCompactionConfig } from "./semantic-compaction/contracts.js";
|
|
50
|
+
import { MemoryReuseConfig } from "../memory/reuse.js";
|
|
51
|
+
import { createDecisionService } from "./decisions/host.js";
|
|
52
|
+
import { createIntakeDiagnosticSink } from "./decisions/diagnostics.js";
|
|
53
|
+
import { TypedDecisionsConfig } from "./decisions/config.js";
|
|
54
|
+
import { AnswerReviewCoordinator } from "./answer-review/coordinator.js";
|
|
55
|
+
import { AnswerReviewConfig } from "./answer-review/contracts.js";
|
|
56
|
+
import { AutoMemoryReviewCoordinator, } from "./auto-memory-review.js";
|
|
57
|
+
import { MemoryReviewConfig } from "../memory/review/contracts.js";
|
|
58
|
+
import { MemoryRetrievalConfig } from "../memory/retrieval-contracts.js";
|
|
59
|
+
import { DshEnnoMemoryRefresh } from "./enno-memory-refresh.js";
|
|
60
|
+
import { EnnoMemoryConfig } from "./config.js";
|
|
61
|
+
import { CompletionConfig } from "./task-completion.js";
|
|
62
|
+
import { saveSessionNotice } from "./plugin-records.js";
|
|
63
|
+
import { MemoryEvolutionConfig, } from "../memory/evolution/contracts.js";
|
|
64
|
+
import { AgenticReplayConfig, EfficiencyConfig, FinalizationConfig, AkinatorMemoryConfig, ContinuityConfig, } from "./config.js";
|
|
65
|
+
import { readExecutionSelection, writeExecutionSelection, } from "./execution-selection.js";
|
|
66
|
+
import { LISP_CODING_SERVICE, } from "./lisp/coding-choice.js";
|
|
67
|
+
import { DshSkillPrompts } from "./skill-prompts.js";
|
|
68
|
+
import { nativeModelCatalog } from "./native-model-catalog.js";
|
|
69
|
+
import { DshEnnoDelegation } from "./enno-delegation.js";
|
|
70
|
+
import { createDshAgenticReplayHost } from "./agenticreplay-host.js";
|
|
71
|
+
import { fileURLToPath } from "node:url";
|
|
72
|
+
import { realpathSync } from "node:fs";
|
|
73
|
+
import { KIOKUKO_DSH_HOST_SERVICE, } from "./composition.js";
|
|
74
|
+
import { DshRuntime } from "./runtime.js";
|
|
75
|
+
import { DshToolPolicy } from "./tool-policy.js";
|
|
76
|
+
import { ToolExposureConfig, } from "./tool-exposure.js";
|
|
77
|
+
import { DiffReviewConfig } from "./config.js";
|
|
78
|
+
import { DiffReviewController } from "../diff-review/controller.js";
|
|
79
|
+
import { DshMemoryFinalizer, } from "./session-memory-finalizer.js";
|
|
80
|
+
import { DshPonytailModes } from "./commands.js";
|
|
81
|
+
import { createDshConfirmationAnswerer, } from "./user-interaction.js";
|
|
82
|
+
import { createDshCapabilityCatalog, } from "./capability-catalog.js";
|
|
83
|
+
import { STANDARD_SKILL_MANIFESTS } from "./standard-skills.js";
|
|
84
|
+
import { canonicalContentHash, compareCanonicalStrings, } from "../serialization/validate.js";
|
|
85
|
+
import { KiokukoError } from "../errors.js";
|
|
86
|
+
import { stateForSnapshot } from "../enno-oduno/service.js";
|
|
87
|
+
import { readEnnoSnapshot } from "../enno-oduno/store.js";
|
|
88
|
+
import { DeepPlanningController } from "../deep-thinker/controller.js";
|
|
89
|
+
import { DshSessionLogMirror, } from "./session-log-mirror.js";
|
|
90
|
+
import { DshExecutionSupport } from "./execution-support.js";
|
|
91
91
|
function sessionEventSource(value) {
|
|
92
92
|
const source = value;
|
|
93
|
-
if (typeof source?.snapshotEvents !==
|
|
94
|
-
throw new KiokukoError(
|
|
93
|
+
if (typeof source?.snapshotEvents !== "function") {
|
|
94
|
+
throw new KiokukoError("INTEGRITY_ERROR", "The exact native DSH session event source is unavailable");
|
|
95
95
|
}
|
|
96
96
|
return source;
|
|
97
97
|
}
|
|
98
98
|
function textFromMessages(messages, fallback) {
|
|
99
99
|
const userTexts = [];
|
|
100
100
|
for (const value of messages) {
|
|
101
|
-
if (typeof value !==
|
|
101
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
102
102
|
continue;
|
|
103
103
|
const message = value;
|
|
104
|
-
if (message.role !== undefined && message.role !==
|
|
104
|
+
if (message.role !== undefined && message.role !== "user")
|
|
105
105
|
continue;
|
|
106
106
|
const source = message.source;
|
|
107
|
-
const sourceKind = typeof source ===
|
|
107
|
+
const sourceKind = typeof source === "object" && source !== null && !Array.isArray(source)
|
|
108
108
|
? source.kind
|
|
109
109
|
: undefined;
|
|
110
110
|
// File/session context and other host instructions may intentionally use
|
|
111
111
|
// the user role so the model sees them. They are still not the human's
|
|
112
112
|
// request and must not influence intake classification or task identity.
|
|
113
113
|
// Only messages carrying explicit user provenance are the human's task.
|
|
114
|
-
if (sourceKind !==
|
|
114
|
+
if (sourceKind !== "user")
|
|
115
115
|
continue;
|
|
116
116
|
const content = message.content;
|
|
117
117
|
if (!Array.isArray(content))
|
|
118
118
|
continue;
|
|
119
119
|
for (const block of content) {
|
|
120
|
-
if (typeof block !==
|
|
120
|
+
if (typeof block !== "object" || block === null || Array.isArray(block))
|
|
121
121
|
continue;
|
|
122
122
|
const text = block.text;
|
|
123
|
-
if (typeof text !==
|
|
123
|
+
if (typeof text !== "string" || text.length === 0)
|
|
124
124
|
continue;
|
|
125
125
|
userTexts.push(text);
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
|
-
const task = userTexts.join(
|
|
128
|
+
const task = userTexts.join("\n").trim();
|
|
129
129
|
if (task.length === 0) {
|
|
130
130
|
if (fallback !== undefined && fallback.trim().length > 0)
|
|
131
131
|
return fallback;
|
|
132
|
-
throw new Error(
|
|
132
|
+
throw new Error("dsh pre-step did not contain a user task");
|
|
133
133
|
}
|
|
134
134
|
return task;
|
|
135
135
|
}
|
|
136
136
|
function objectRecord(value) {
|
|
137
|
-
return typeof value ===
|
|
137
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
138
138
|
? value
|
|
139
139
|
: undefined;
|
|
140
140
|
}
|
|
141
141
|
function isHumanMessage(value) {
|
|
142
142
|
const message = objectRecord(value);
|
|
143
143
|
const source = objectRecord(message?.source);
|
|
144
|
-
return source?.kind ===
|
|
144
|
+
return source?.kind === "user";
|
|
145
145
|
}
|
|
146
146
|
const CONTINUATION_ID = /^[0-9a-f]{64}$/u;
|
|
147
147
|
export function pluginContinuationId(value) {
|
|
@@ -150,43 +150,54 @@ export function pluginContinuationId(value) {
|
|
|
150
150
|
if (!isKiokukoDshSource(source))
|
|
151
151
|
return undefined;
|
|
152
152
|
const messageId = message?.id;
|
|
153
|
-
if (source.form ===
|
|
153
|
+
if (source.form === "instructions" &&
|
|
154
|
+
typeof messageId === "string" &&
|
|
155
|
+
CONTINUATION_ID.test(messageId)) {
|
|
154
156
|
return messageId;
|
|
155
157
|
}
|
|
156
|
-
if ((source.form !==
|
|
157
|
-
|
|
158
|
+
if ((source.form !== "continuation" &&
|
|
159
|
+
source.form !== "loop-recovery" &&
|
|
160
|
+
source.form !== "instructions") ||
|
|
161
|
+
typeof source.deliveryId !== "string" ||
|
|
162
|
+
!CONTINUATION_ID.test(source.deliveryId))
|
|
158
163
|
return undefined;
|
|
159
164
|
return source.deliveryId;
|
|
160
165
|
}
|
|
161
166
|
function isLoopRecoveryMessage(value) {
|
|
162
167
|
const source = objectRecord(objectRecord(value)?.source);
|
|
163
|
-
return isKiokukoDshSource(source) && source?.form ===
|
|
168
|
+
return isKiokukoDshSource(source) && source?.form === "loop-recovery";
|
|
164
169
|
}
|
|
165
170
|
export function recoveryMessage(continuationId, answer) {
|
|
166
171
|
return Object.freeze({
|
|
167
172
|
id: continuationId,
|
|
168
|
-
role:
|
|
169
|
-
content: [
|
|
170
|
-
|
|
173
|
+
role: "user",
|
|
174
|
+
content: [
|
|
175
|
+
{
|
|
176
|
+
type: "text",
|
|
171
177
|
text: `The user reviewed the stopped Kiokuko loop and supplied this recovery instruction:\n\n${answer}`,
|
|
172
|
-
}
|
|
173
|
-
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
source: { kind: KIOKUKO_DSH_SOURCE_KIND, form: "instructions" },
|
|
174
181
|
});
|
|
175
182
|
}
|
|
176
183
|
function boundedMessageText(value) {
|
|
177
184
|
const content = objectRecord(value)?.content;
|
|
178
185
|
if (!Array.isArray(content))
|
|
179
186
|
return undefined;
|
|
180
|
-
const block = content
|
|
181
|
-
|
|
187
|
+
const block = content
|
|
188
|
+
.map(objectRecord)
|
|
189
|
+
.find((candidate) => candidate?.type === "text" && typeof candidate.text === "string");
|
|
190
|
+
return typeof block?.text === "string"
|
|
191
|
+
? block.text.slice(0, 2_000)
|
|
192
|
+
: undefined;
|
|
182
193
|
}
|
|
183
194
|
function boundedUtf8Text(value, maximumBytes) {
|
|
184
|
-
if (Buffer.byteLength(value,
|
|
195
|
+
if (Buffer.byteLength(value, "utf8") <= maximumBytes)
|
|
185
196
|
return value;
|
|
186
|
-
let result =
|
|
197
|
+
let result = "";
|
|
187
198
|
let bytes = 0;
|
|
188
199
|
for (const point of value) {
|
|
189
|
-
const size = Buffer.byteLength(point,
|
|
200
|
+
const size = Buffer.byteLength(point, "utf8");
|
|
190
201
|
if (bytes + size > maximumBytes)
|
|
191
202
|
break;
|
|
192
203
|
result += point;
|
|
@@ -202,24 +213,28 @@ export function eventContinuationId(data) {
|
|
|
202
213
|
return pluginContinuationId(record?.message);
|
|
203
214
|
}
|
|
204
215
|
export function continuationMessage(continuationId, nextAction) {
|
|
205
|
-
const work = nextAction ===
|
|
206
|
-
?
|
|
216
|
+
const work = nextAction === "execute_work_unit"
|
|
217
|
+
? "The current WorkUnit is not accepted unless the latest Enno result says so. Correct or report only that WorkUnit."
|
|
207
218
|
: `Continue only the current Kiokuko phase for nextAction=${nextAction}. Do not skip ahead.`;
|
|
208
219
|
return Object.freeze({
|
|
209
220
|
id: continuationId,
|
|
210
|
-
role:
|
|
211
|
-
content: [{ type:
|
|
212
|
-
source: { kind: KIOKUKO_DSH_SOURCE_KIND, form:
|
|
221
|
+
role: "user",
|
|
222
|
+
content: [{ type: "text", text: work }],
|
|
223
|
+
source: { kind: KIOKUKO_DSH_SOURCE_KIND, form: "instructions" },
|
|
213
224
|
});
|
|
214
225
|
}
|
|
215
226
|
async function capabilityCatalog(skills, tools, context) {
|
|
216
227
|
if (skills?.snapshot === undefined || tools?.schemas === undefined) {
|
|
217
|
-
throw new Error(
|
|
228
|
+
throw new Error("kiokuko-dsh requires native Skill and tool snapshots");
|
|
218
229
|
}
|
|
219
230
|
const scope = context.nativeAgent ?? context.agent;
|
|
220
|
-
const skillSnapshot = await skills.snapshot({
|
|
231
|
+
const skillSnapshot = await skills.snapshot({
|
|
232
|
+
scope,
|
|
233
|
+
cwd: context.cwd,
|
|
234
|
+
signal: context.signal,
|
|
235
|
+
});
|
|
221
236
|
if (skillSnapshot.complete !== true)
|
|
222
|
-
throw new Error(
|
|
237
|
+
throw new Error("kiokuko-dsh native Skill snapshot is incomplete");
|
|
223
238
|
// A Skill visible to a user but not model-invocable is not a capability
|
|
224
239
|
// that can satisfy the model's required route. Treat it as unavailable by
|
|
225
240
|
// excluding it before the mandatory-catalog check below.
|
|
@@ -228,7 +243,13 @@ async function capabilityCatalog(skills, tools, context) {
|
|
|
228
243
|
const mandatoryOrder = new Map();
|
|
229
244
|
STANDARD_SKILL_MANIFESTS.forEach((manifest, index) => mandatoryOrder.set(manifest.name, index));
|
|
230
245
|
const skillDescriptors = nativeSkills
|
|
231
|
-
.map((skill) => ({
|
|
246
|
+
.map((skill) => ({
|
|
247
|
+
kind: "skill",
|
|
248
|
+
name: skill.name,
|
|
249
|
+
...(skill.description === undefined
|
|
250
|
+
? {}
|
|
251
|
+
: { description: skill.description }),
|
|
252
|
+
}))
|
|
232
253
|
.sort((left, right) => {
|
|
233
254
|
const leftMandatory = mandatoryOrder.has(left.name);
|
|
234
255
|
const rightMandatory = mandatoryOrder.has(right.name);
|
|
@@ -239,9 +260,18 @@ async function capabilityCatalog(skills, tools, context) {
|
|
|
239
260
|
return compareCanonicalStrings(left.name, right.name);
|
|
240
261
|
});
|
|
241
262
|
const toolDescriptors = nativeTools
|
|
242
|
-
.map((tool) => ({
|
|
263
|
+
.map((tool) => ({
|
|
264
|
+
kind: "tool",
|
|
265
|
+
name: tool.name,
|
|
266
|
+
...(tool.description === undefined
|
|
267
|
+
? {}
|
|
268
|
+
: { description: tool.description }),
|
|
269
|
+
}))
|
|
243
270
|
.sort((left, right) => compareCanonicalStrings(left.name, right.name));
|
|
244
|
-
return createDshCapabilityCatalog({
|
|
271
|
+
return createDshCapabilityCatalog({
|
|
272
|
+
skills: skillDescriptors,
|
|
273
|
+
tools: toolDescriptors,
|
|
274
|
+
});
|
|
245
275
|
}
|
|
246
276
|
export function createDshHostAdapter(ctx, options = {}) {
|
|
247
277
|
let skillPrompts = options.skillPrompts ?? new DshSkillPrompts();
|
|
@@ -251,15 +281,22 @@ export function createDshHostAdapter(ctx, options = {}) {
|
|
|
251
281
|
const reportedToolExposureProjections = new Set();
|
|
252
282
|
const reportToolExposureFallback = (fallback) => {
|
|
253
283
|
fallback = `${toolExposureConfig.mode}:${fallback}`;
|
|
254
|
-
if (toolExposureConfig.mode ===
|
|
284
|
+
if (toolExposureConfig.mode === "full" ||
|
|
285
|
+
reportedToolExposureFallbacks.has(fallback))
|
|
255
286
|
return;
|
|
256
287
|
reportedToolExposureFallbacks.add(fallback);
|
|
257
288
|
console.warn(`[kiokuko-dsh] [warn] toolExposure left the native surface unchanged: ${fallback}`);
|
|
258
289
|
};
|
|
259
290
|
const reportToolExposureProjection = (mode, reason, metrics) => {
|
|
260
|
-
if (toolExposureConfig.mode !==
|
|
291
|
+
if (toolExposureConfig.mode !== "lean" &&
|
|
292
|
+
toolExposureConfig.mode !== "auto")
|
|
261
293
|
return;
|
|
262
|
-
const diagnostic = {
|
|
294
|
+
const diagnostic = {
|
|
295
|
+
requestedMode: toolExposureConfig.mode,
|
|
296
|
+
mode,
|
|
297
|
+
reason,
|
|
298
|
+
...metrics,
|
|
299
|
+
};
|
|
263
300
|
const key = JSON.stringify(diagnostic);
|
|
264
301
|
if (reportedToolExposureProjections.has(key))
|
|
265
302
|
return;
|
|
@@ -272,97 +309,174 @@ export function createDshHostAdapter(ctx, options = {}) {
|
|
|
272
309
|
const finalizationConfig = FinalizationConfig.parse(options.finalization ?? {});
|
|
273
310
|
const memoryRetrievalConfig = MemoryRetrievalConfig.parse(options.memoryRetrieval ?? {});
|
|
274
311
|
const native = ctx;
|
|
275
|
-
const skills = native.get(
|
|
276
|
-
const systemPrompt = native.get(
|
|
277
|
-
const tools = native.get(
|
|
278
|
-
const commands = native.get(
|
|
279
|
-
const userQuestions = native.get(
|
|
280
|
-
const sessions = native.get(
|
|
281
|
-
const agents = native.get(
|
|
282
|
-
const attachments = native.get(
|
|
283
|
-
const sessionQuery = options.sessionQuery ??
|
|
284
|
-
|
|
312
|
+
const skills = native.get("skills", false);
|
|
313
|
+
const systemPrompt = native.get("systemPrompt", false);
|
|
314
|
+
const tools = native.get("tools", false);
|
|
315
|
+
const commands = native.get("commands", false);
|
|
316
|
+
const userQuestions = native.get("userQuestions", false);
|
|
317
|
+
const sessions = native.get("sessions", false);
|
|
318
|
+
const agents = native.get("agents", false);
|
|
319
|
+
const attachments = native.get("attachments", false);
|
|
320
|
+
const sessionQuery = options.sessionQuery ??
|
|
321
|
+
native.get("sessionQuery", false);
|
|
322
|
+
const llm = options.llm ?? native.get("llm", false);
|
|
285
323
|
const reviewConfig = DiffReviewConfig.parse(options.diffReview ?? {});
|
|
286
324
|
const completionMode = CompletionConfig.parse(options.completion ?? {}).mode;
|
|
287
|
-
const advisory = options.advisory ??
|
|
288
|
-
|
|
289
|
-
const
|
|
325
|
+
const advisory = options.advisory ??
|
|
326
|
+
native.get("dshAdvisory", false);
|
|
327
|
+
const modelCatalog = nativeModelCatalog(native.get("llm", false), native.get("settings", false));
|
|
328
|
+
const modelCompatibility = options.modelCompatibility ??
|
|
329
|
+
native.get("dshModelCompatibility", false);
|
|
290
330
|
const selections = new Map();
|
|
291
331
|
const root = realpathSync(options.repositoryRoot ?? process.cwd());
|
|
292
|
-
const runtime = options.runtime ??
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
332
|
+
const runtime = options.runtime ??
|
|
333
|
+
new DshRuntime({
|
|
334
|
+
repositoryRoot: root,
|
|
335
|
+
...(options.databasePath === undefined
|
|
336
|
+
? {}
|
|
337
|
+
: { databasePath: options.databasePath }),
|
|
338
|
+
migrationsDirectory: options.migrationsDirectory ??
|
|
339
|
+
fileURLToPath(new URL("../../migrations/", import.meta.url)),
|
|
340
|
+
embeddingConfig: {
|
|
341
|
+
mode: "off",
|
|
342
|
+
provider: "openai-compatible",
|
|
343
|
+
allowRemote: false,
|
|
344
|
+
vectorBackend: "auto",
|
|
345
|
+
timeoutMs: 30_000,
|
|
346
|
+
batchSize: 16,
|
|
347
|
+
},
|
|
348
|
+
autoRegisterRepository: true,
|
|
349
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
350
|
+
});
|
|
351
|
+
const diffReview = reviewConfig.enabled
|
|
352
|
+
? new DiffReviewController({
|
|
353
|
+
runtime,
|
|
354
|
+
...(sessions ? { sessions: sessions } : {}),
|
|
355
|
+
...(native.get("sessionPersistence", false)
|
|
356
|
+
? { persistence: native.get("sessionPersistence", false) }
|
|
357
|
+
: {}),
|
|
358
|
+
...(native.get("subprocess", false)
|
|
359
|
+
? { subprocess: native.get("subprocess", false) }
|
|
360
|
+
: {}),
|
|
361
|
+
...(native.get("workspaceChanges", false)
|
|
362
|
+
? { workspaceChanges: native.get("workspaceChanges", false) }
|
|
363
|
+
: {}),
|
|
364
|
+
...(llm ? { llm } : {}),
|
|
365
|
+
...(modelCatalog ? { catalog: modelCatalog } : {}),
|
|
366
|
+
}, reviewConfig)
|
|
367
|
+
: undefined;
|
|
368
|
+
const decisions = options.decisions ??
|
|
369
|
+
createDecisionService(ctx, runtime, TypedDecisionsConfig.parse(options.typedDecisions ?? {}), MemoryReuseConfig.parse(options.memoryReuse ?? {}), SemanticCompactionConfig.parse(options.semanticCompaction ?? {}), root);
|
|
310
370
|
const modelAutoConfig = ModelAutoConfig.parse(options.modelAutoMode ?? {});
|
|
311
371
|
const modelAuto = new ModelAutoCoordinator(new ModelAutoStore(runtime, modelAutoConfig.mode, canonicalContentHash(modelAutoConfig)), decisions, modelCatalog, modelAutoConfig);
|
|
312
372
|
const answerReview = new AnswerReviewCoordinator(runtime, decisions, AnswerReviewConfig.parse(options.answerReview ?? {}));
|
|
313
|
-
const semanticCompaction = options.semanticCompactionCoordinator ??
|
|
373
|
+
const semanticCompaction = options.semanticCompactionCoordinator ??
|
|
374
|
+
new SemanticCompactionCoordinator(ctx, decisions, root, options.observationPack);
|
|
314
375
|
const modelHandoff = new ModelHandoff(ctx, decisions, root, options.modelHandoff);
|
|
315
376
|
const lifecycleMemory = new DshLifecycleMemory(ctx, runtime, root);
|
|
316
|
-
const delegation = new DshEnnoDelegation(runtime, native.get(
|
|
317
|
-
const deepPlanning = new DeepPlanningController({
|
|
318
|
-
|
|
377
|
+
const delegation = new DshEnnoDelegation(runtime, native.get("subagents", false));
|
|
378
|
+
const deepPlanning = new DeepPlanningController({
|
|
379
|
+
runtime,
|
|
380
|
+
decisions,
|
|
381
|
+
ctx: ctx,
|
|
382
|
+
backend: native.get("subagents", false),
|
|
383
|
+
sessions,
|
|
384
|
+
agents,
|
|
385
|
+
catalog: modelCatalog,
|
|
386
|
+
questions: userQuestions,
|
|
387
|
+
routes: options.modelRoutes ?? [],
|
|
388
|
+
compatibility: modelCompatibility,
|
|
389
|
+
sessionQuery,
|
|
390
|
+
config: options.deepPlanning,
|
|
319
391
|
capabilities: async (agent, signal) => {
|
|
320
|
-
const catalog = await capabilityCatalog(skills, tools, {
|
|
392
|
+
const catalog = await capabilityCatalog(skills, tools, {
|
|
393
|
+
cwd: root,
|
|
394
|
+
signal,
|
|
395
|
+
agent,
|
|
396
|
+
nativeAgent: agent,
|
|
397
|
+
});
|
|
321
398
|
return [...catalog.skills, ...catalog.tools];
|
|
322
|
-
},
|
|
323
|
-
|
|
399
|
+
},
|
|
400
|
+
});
|
|
401
|
+
const isGenericNativeChild = (agent) => isNativeSubagent(agent) &&
|
|
402
|
+
!delegation.isChild(agent) &&
|
|
403
|
+
!deepPlanning.executor.isChild(agent);
|
|
324
404
|
const childGuardDisposer = tools?.guard((value) => {
|
|
325
405
|
const execution = value;
|
|
326
|
-
return execution.agent
|
|
406
|
+
return execution.agent
|
|
407
|
+
? delegation.toolDenial(execution.agent, execution.name ?? "", execution.arguments)
|
|
408
|
+
: undefined;
|
|
327
409
|
});
|
|
328
|
-
const childExecutionDisposer = onNativeEvent(ctx,
|
|
410
|
+
const childExecutionDisposer = onNativeEvent(ctx, "tools/execute", async (execution, next) => {
|
|
329
411
|
if (execution.agent && delegation.isChild(execution.agent)) {
|
|
330
412
|
await delegation.assertCurrent(execution.agent);
|
|
331
413
|
const denial = delegation.toolDenial(execution.agent, execution.name, execution.arguments);
|
|
332
414
|
if (denial)
|
|
333
|
-
throw new KiokukoError(
|
|
415
|
+
throw new KiokukoError("CONFLICT", denial);
|
|
334
416
|
}
|
|
335
417
|
return next();
|
|
336
418
|
}, { prepend: true });
|
|
337
|
-
const sessionCachePath = options.sessionCachePath
|
|
338
|
-
|
|
419
|
+
const sessionCachePath = options.sessionCachePath ??
|
|
420
|
+
(options.databasePath === undefined
|
|
421
|
+
? undefined
|
|
422
|
+
: `${options.databasePath}.session-cache`);
|
|
339
423
|
const sessionMirror = new DshSessionLogMirror({
|
|
340
424
|
runtime,
|
|
341
|
-
...(sessionCachePath === undefined
|
|
342
|
-
|
|
425
|
+
...(sessionCachePath === undefined
|
|
426
|
+
? {}
|
|
427
|
+
: { databasePath: sessionCachePath }),
|
|
428
|
+
...(attachments === undefined
|
|
429
|
+
? {}
|
|
430
|
+
: { readAttachment: attachments.readImage.bind(attachments) }),
|
|
343
431
|
...(options.now === undefined ? {} : { now: options.now }),
|
|
344
432
|
});
|
|
345
|
-
const { finalizationQuery, sessionExport } = createSessionAccess({
|
|
346
|
-
|
|
433
|
+
const { finalizationQuery, sessionExport } = createSessionAccess({
|
|
434
|
+
native,
|
|
435
|
+
sessions,
|
|
436
|
+
sessionQuery,
|
|
437
|
+
sessionMirror,
|
|
438
|
+
});
|
|
439
|
+
const policy = new DshToolPolicy({
|
|
440
|
+
phase: "intake",
|
|
441
|
+
runId: "pending",
|
|
442
|
+
workspace: "pending",
|
|
443
|
+
orchestrationId: "pending",
|
|
444
|
+
revision: 1,
|
|
445
|
+
routeEpoch: 0,
|
|
446
|
+
});
|
|
347
447
|
const modes = new DshPonytailModes();
|
|
348
|
-
const turnState = createTurnState(modes, policy, runId => selections.get(runId));
|
|
448
|
+
const turnState = createTurnState(modes, policy, (runId) => selections.get(runId));
|
|
349
449
|
const currentSession = turnState.currentSession;
|
|
350
450
|
const currentForAgentEvent = turnState.currentForAgentEvent;
|
|
351
|
-
const executionSupport = new DshExecutionSupport(runtime, {
|
|
352
|
-
|
|
353
|
-
|
|
451
|
+
const executionSupport = new DshExecutionSupport(runtime, {
|
|
452
|
+
continuity: continuityConfig,
|
|
453
|
+
observe: (value) => efficiencyHost.efficiency?.recordContinuity(value),
|
|
454
|
+
});
|
|
455
|
+
executionSupport.mount({
|
|
456
|
+
on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options),
|
|
354
457
|
...(systemPrompt === undefined ? {} : { systemPrompt }),
|
|
355
|
-
...(tools === undefined
|
|
356
|
-
|
|
458
|
+
...(tools === undefined
|
|
459
|
+
? {}
|
|
460
|
+
: { tools: { guard: tools.guard.bind(tools) } }),
|
|
461
|
+
});
|
|
462
|
+
const ennoMemory = new DshEnnoMemoryRefresh(runtime, EnnoMemoryConfig.parse(options.ennoMemory ?? {}), (value) => efficiencyHost.efficiency?.recordEnnoMemory(value));
|
|
357
463
|
const { refreshEnnoMemory } = createEnnoMemoryHost({
|
|
358
|
-
ennoMemory,
|
|
359
|
-
|
|
464
|
+
ennoMemory,
|
|
465
|
+
runtime,
|
|
466
|
+
executionSupport,
|
|
467
|
+
delegation,
|
|
468
|
+
getSelection: (runId) => selections.get(runId),
|
|
469
|
+
turnState,
|
|
470
|
+
currentSession,
|
|
471
|
+
capabilityCatalog,
|
|
472
|
+
skills,
|
|
473
|
+
tools,
|
|
360
474
|
assertTurnStoppingCatalog: (expected, actual) => gate.assertTurnStoppingCatalog(expected, actual),
|
|
361
475
|
isHumanMessage,
|
|
362
476
|
});
|
|
363
477
|
const executionBinding = turnState.executionBinding;
|
|
364
478
|
const memoryFinalizer = new DshMemoryFinalizer({
|
|
365
|
-
onDeepFinalized: sessionId => deepPlanning.deliver(sessionId),
|
|
479
|
+
onDeepFinalized: (sessionId) => deepPlanning.deliver(sessionId),
|
|
366
480
|
memoryEvolution: evolutionConfig,
|
|
367
481
|
memoryIndexReasoning: MemoryIndexReasoningConfig.parse(options.memoryIndexReasoning ?? {}),
|
|
368
482
|
autoGlobalizationEnabled: options.autoGlobalization?.enabled ?? true,
|
|
@@ -372,278 +486,464 @@ export function createDshHostAdapter(ctx, options = {}) {
|
|
|
372
486
|
...(llm === undefined ? {} : { llm }),
|
|
373
487
|
...(options.now === undefined ? {} : { now: options.now }),
|
|
374
488
|
});
|
|
375
|
-
const autoReview = new AutoMemoryReviewCoordinator({
|
|
376
|
-
|
|
489
|
+
const autoReview = new AutoMemoryReviewCoordinator({
|
|
490
|
+
runtime,
|
|
491
|
+
mirror: sessionMirror,
|
|
492
|
+
config: MemoryReviewConfig.parse(options.memoryReview ?? {}),
|
|
493
|
+
...(llm ? { llm } : {}),
|
|
377
494
|
onCapturePolicy: async (sessionId, mode) => {
|
|
378
495
|
const item = currentSession(sessionId);
|
|
379
496
|
if (!item)
|
|
380
497
|
return;
|
|
381
|
-
await runtime.withDatabase(db => saveSessionNotice(db, {
|
|
382
|
-
|
|
498
|
+
await runtime.withDatabase((db) => saveSessionNotice(db, {
|
|
499
|
+
id: `capture-notice:${item.runId}:${mode}`,
|
|
500
|
+
runId: item.runId,
|
|
501
|
+
sessionId,
|
|
502
|
+
rootPath: item.cwd,
|
|
503
|
+
kind: "status",
|
|
504
|
+
anchorSeq: 0,
|
|
505
|
+
text: mode === "held"
|
|
506
|
+
? "保存拒否の可能性を検出したため、この会話の自動メモリ生成を保留しました。/kioku-memory-review exclude session で除外を確定できます。再開する場合は履歴を継承しない新しい会話を開始してください。"
|
|
507
|
+
: "この会話の自動メモリ生成を除外しました。保存済み記憶と会話ログは残ります。",
|
|
508
|
+
}));
|
|
383
509
|
},
|
|
384
|
-
onChanged: async (job, result) => {
|
|
385
|
-
|
|
386
|
-
|
|
510
|
+
onChanged: async (job, result) => {
|
|
511
|
+
await runtime.withDatabase((db) => saveSessionNotice(db, {
|
|
512
|
+
id: `review-notice:${job.id}`,
|
|
513
|
+
runId: job.run_id,
|
|
514
|
+
sessionId: job.session_id,
|
|
515
|
+
rootPath: root,
|
|
516
|
+
kind: "status",
|
|
517
|
+
text: `記憶を更新しました(追加${result.added}件、更新${result.updated}件)`,
|
|
518
|
+
anchorSeq: job.end_seq,
|
|
519
|
+
}));
|
|
520
|
+
},
|
|
521
|
+
...(sessions?.flush
|
|
522
|
+
? { flush: (session) => sessions.flush(session) }
|
|
523
|
+
: {}),
|
|
524
|
+
...(options.now ? { now: options.now } : {}),
|
|
525
|
+
});
|
|
526
|
+
const reviewBinding = (item, session) => ({
|
|
527
|
+
workspace: item.workspace,
|
|
528
|
+
runId: item.runId,
|
|
529
|
+
session: session,
|
|
530
|
+
startSeq: 0,
|
|
531
|
+
});
|
|
387
532
|
deepPlanning.attachFinalizer(() => memoryFinalizer.kick());
|
|
388
|
-
const confirmationAnswerer = userQuestions === undefined
|
|
533
|
+
const confirmationAnswerer = userQuestions === undefined
|
|
534
|
+
? undefined
|
|
535
|
+
: createDshConfirmationAnswerer(userQuestions);
|
|
389
536
|
const observation = createSessionObservation(runtime);
|
|
390
537
|
const captureInitialInput = observation.captureInitialInput;
|
|
391
538
|
let retireSupersededRun;
|
|
392
539
|
const admission = createAdmission({
|
|
393
|
-
native,
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
540
|
+
native,
|
|
541
|
+
skills,
|
|
542
|
+
tools,
|
|
543
|
+
userQuestions,
|
|
544
|
+
sessions,
|
|
545
|
+
agents,
|
|
546
|
+
deepPlanning,
|
|
547
|
+
modelCatalog,
|
|
548
|
+
modelCompatibility,
|
|
549
|
+
modelRoutes: options.modelRoutes,
|
|
550
|
+
now: options.now,
|
|
551
|
+
runtime,
|
|
552
|
+
decisions,
|
|
553
|
+
answerReview,
|
|
554
|
+
delegation,
|
|
555
|
+
executionSupport,
|
|
556
|
+
ennoMemory,
|
|
557
|
+
memoryFinalizer,
|
|
558
|
+
autoReview,
|
|
559
|
+
sessionMirror,
|
|
560
|
+
akinatorMemoryConfig,
|
|
561
|
+
memoryRetrievalConfig,
|
|
562
|
+
completionMode,
|
|
563
|
+
turnState,
|
|
564
|
+
getSelection: (runId) => selections.get(runId),
|
|
565
|
+
setSelection: (runId, value) => {
|
|
566
|
+
selections.set(runId, value);
|
|
567
|
+
},
|
|
568
|
+
refreshEnnoMemory,
|
|
569
|
+
executionBinding,
|
|
570
|
+
captureInitialInput,
|
|
399
571
|
contextMessages: (event, pending) => contextMessages(event, pending),
|
|
400
572
|
resolveIdleClose: (agentId, sessionId, nativeSession, nativeAgent) => resolveIdleClose(agentId, sessionId, nativeSession, nativeAgent),
|
|
401
573
|
retireSupersededRun: (item, status) => {
|
|
402
574
|
if (retireSupersededRun === undefined)
|
|
403
|
-
throw new Error(
|
|
575
|
+
throw new Error("kiokuko-dsh run lifecycle is unavailable");
|
|
404
576
|
return retireSupersededRun(item, status);
|
|
405
577
|
},
|
|
406
|
-
cancelBoundarySession: sessionId => boundaryWorker.cancelSession(sessionId),
|
|
407
|
-
isSelectionBlocked: agent => routing.isSelectionBlocked(agent),
|
|
408
|
-
closeTurn: input => runLifecycle.closeTurn(input),
|
|
409
|
-
readStateForRun: item => runtime.withDatabase(db => stateForRun(db, item)),
|
|
410
|
-
capabilityCatalog,
|
|
411
|
-
|
|
578
|
+
cancelBoundarySession: (sessionId) => boundaryWorker.cancelSession(sessionId),
|
|
579
|
+
isSelectionBlocked: (agent) => routing.isSelectionBlocked(agent),
|
|
580
|
+
closeTurn: (input) => runLifecycle.closeTurn(input),
|
|
581
|
+
readStateForRun: (item) => runtime.withDatabase((db) => stateForRun(db, item)),
|
|
582
|
+
capabilityCatalog,
|
|
583
|
+
sessionEventSource,
|
|
584
|
+
objectRecord,
|
|
585
|
+
isHumanMessage,
|
|
586
|
+
textFromMessages,
|
|
587
|
+
pluginContinuationId,
|
|
588
|
+
isLoopRecoveryMessage,
|
|
412
589
|
});
|
|
413
590
|
const gate = admission.gate;
|
|
414
591
|
const mapPreStep = admission.mapPreStep;
|
|
415
592
|
const detachedDemandSessions = new Set();
|
|
416
593
|
// Archive/session-query adapters own no live execution ingress. A partial live
|
|
417
594
|
// tool/agent plane is not that read-only case and must not silently downgrade.
|
|
418
|
-
const conversationFirst = IntakeModeConfig.parse(options.intakeMode) ===
|
|
595
|
+
const conversationFirst = IntakeModeConfig.parse(options.intakeMode) === "on-demand";
|
|
419
596
|
const hasExecutionIngress = tools !== undefined || agents !== undefined;
|
|
420
|
-
const hasDemandTools = typeof objectRecord(tools)?.get ===
|
|
421
|
-
|
|
422
|
-
|
|
597
|
+
const hasDemandTools = typeof objectRecord(tools)?.get === "function" &&
|
|
598
|
+
typeof tools?.guard === "function" &&
|
|
599
|
+
typeof tools?.register === "function";
|
|
600
|
+
if (conversationFirst &&
|
|
601
|
+
hasExecutionIngress &&
|
|
602
|
+
(!hasDemandTools || !agents || !sessions)) {
|
|
603
|
+
throw new Error("Conversation-first execution requires native tools, agents and sessions; read-only history adapters must not expose a partial execution plane");
|
|
423
604
|
}
|
|
424
605
|
const answerCwd = (agent) => {
|
|
425
606
|
const session = agent.session;
|
|
426
|
-
if (!session ||
|
|
427
|
-
|
|
428
|
-
|
|
607
|
+
if (!session ||
|
|
608
|
+
agents?.get(agent.id) !== agent ||
|
|
609
|
+
sessions?.get(session.id) !== session ||
|
|
610
|
+
typeof session.header?.cwd !== "string" ||
|
|
611
|
+
!session.header.cwd)
|
|
612
|
+
throw new Error("On-demand native identity mismatch");
|
|
429
613
|
return realpathSync(session.header.cwd);
|
|
430
614
|
};
|
|
431
|
-
const demand = hasDemandTools && agents && sessions
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
615
|
+
const demand = hasDemandTools && agents && sessions
|
|
616
|
+
? new OnDemandIntake({
|
|
617
|
+
diagnostic: createIntakeDiagnosticSink(runtime),
|
|
618
|
+
assess: (input, context, decision) => assessRequestIntent(decisions, dshTurnRequestId({
|
|
619
|
+
dshSessionId: input.agent.session.id,
|
|
620
|
+
turn: input.turn,
|
|
621
|
+
}), context, decision, input.signal),
|
|
622
|
+
...(userQuestions ? { questions: userQuestions } : {}),
|
|
623
|
+
answerContext: new DshAnswerContext(runtime, {
|
|
624
|
+
root,
|
|
625
|
+
cwd: answerCwd,
|
|
626
|
+
projectOnly: false,
|
|
627
|
+
memoryRetrieval: memoryRetrievalConfig,
|
|
628
|
+
instructions: (input, task, taskType) => answerSkillContext(input, task, taskType, {
|
|
629
|
+
skills: skills,
|
|
630
|
+
prompts: skillPrompts,
|
|
631
|
+
decisions,
|
|
632
|
+
cwd: answerCwd(input.agent),
|
|
633
|
+
}),
|
|
634
|
+
}),
|
|
635
|
+
prepareNativeCoding: async (input, task, requestIntentContext) => {
|
|
636
|
+
const lisp = native.get(LISP_CODING_SERVICE, false);
|
|
637
|
+
const sessionId = input.agent.session?.id;
|
|
638
|
+
if (!lisp?.prepareNative || !sessionId)
|
|
639
|
+
return;
|
|
640
|
+
const requestIntent = requestIntentContext
|
|
641
|
+
? await classifyRequestIntent(decisions, dshTurnRequestId({
|
|
642
|
+
dshSessionId: sessionId,
|
|
643
|
+
turn: input.turn,
|
|
644
|
+
}), requestIntentContext, input.signal)
|
|
645
|
+
: undefined;
|
|
646
|
+
await lisp.prepareNative({
|
|
647
|
+
agent: input.agent,
|
|
648
|
+
turn: input.turn,
|
|
649
|
+
task,
|
|
650
|
+
taskType: null,
|
|
651
|
+
signal: input.signal,
|
|
652
|
+
...(requestIntent ? { requestIntent } : {}),
|
|
653
|
+
});
|
|
654
|
+
},
|
|
655
|
+
nativeOwnership: async (input) => {
|
|
656
|
+
const agent = input.agent;
|
|
657
|
+
answerCwd(agent);
|
|
658
|
+
const session = agent.session;
|
|
659
|
+
if (!session?.header)
|
|
660
|
+
throw new Error("Native ownership requires the current session header");
|
|
661
|
+
const header = session.header;
|
|
662
|
+
if (header.parentSession || header.isSeeded)
|
|
663
|
+
return "owned";
|
|
664
|
+
const jobs = native.get("jobs", false);
|
|
665
|
+
if (jobs &&
|
|
666
|
+
jobs
|
|
667
|
+
.list(session.id)
|
|
668
|
+
.some((job) => !["completed", "killed", "failed"].includes(job.status)))
|
|
669
|
+
return "owned";
|
|
670
|
+
const current = currentSession(session.id);
|
|
671
|
+
const ownership = await runtime.withDatabase((db) => nativeExecutionOwnership(db, session.id, current?.runId));
|
|
672
|
+
input.signal.throwIfAborted();
|
|
673
|
+
// Retire only the exact completed in-memory projection proven above.
|
|
674
|
+
// Durable history remains intact; no memory lookup or save is involved.
|
|
675
|
+
if (ownership === "unowned" &&
|
|
676
|
+
current &&
|
|
677
|
+
currentSession(session.id) === current)
|
|
678
|
+
turnState.releaseRun(current.runId, current.authority);
|
|
679
|
+
return ownership;
|
|
680
|
+
},
|
|
681
|
+
nativeChild: (agent) => agents?.get(agent.id) === agent &&
|
|
682
|
+
sessions?.get(agent.session?.id ?? "") === agent.session &&
|
|
683
|
+
isNativeSubagent(agent),
|
|
684
|
+
validate: async (input) => {
|
|
685
|
+
const agent = input.agent, session = agent.session;
|
|
686
|
+
answerCwd(agent);
|
|
687
|
+
await captureInitialInput(session.id, input.turn, input.messages);
|
|
688
|
+
},
|
|
689
|
+
advance: async (input) => {
|
|
690
|
+
policy.beginTurn(input.agent.session.id, input.turn);
|
|
691
|
+
},
|
|
692
|
+
resumeConfirmation: async (input) => runtime.withDatabase(async (db) => {
|
|
693
|
+
const sessionId = input.agent.session.id;
|
|
694
|
+
if (detachedDemandSessions.has(sessionId))
|
|
492
695
|
return false;
|
|
696
|
+
const current = currentSession(sessionId);
|
|
697
|
+
if (current !== undefined) {
|
|
698
|
+
if (current.nativeAgent !== input.agent ||
|
|
699
|
+
current.nativeSession !== input.agent.session ||
|
|
700
|
+
current.turn > input.turn) {
|
|
701
|
+
if (process.env.KIOKUKO_INTENT_DEBUG === "1")
|
|
702
|
+
console.error("confirmation resume current mismatch", {
|
|
703
|
+
turn: input.turn,
|
|
704
|
+
currentTurn: current.turn,
|
|
705
|
+
agent: current.nativeAgent === input.agent,
|
|
706
|
+
session: current.nativeSession === input.agent.session,
|
|
707
|
+
});
|
|
708
|
+
return false;
|
|
709
|
+
}
|
|
493
710
|
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
711
|
+
const project = await resolveProjectWorkspaceReadOnly(db, answerCwd(input.agent), { allowDirectory: true });
|
|
712
|
+
if (!project)
|
|
713
|
+
return false;
|
|
714
|
+
const candidates = db
|
|
715
|
+
.prepare(`SELECT lr.run_id AS runId
|
|
499
716
|
FROM ledger_runs AS lr
|
|
500
717
|
JOIN enno_contracts AS ec ON ec.run_id = lr.run_id
|
|
501
718
|
WHERE lr.workspace = ? AND lr.dsh_session_id = ? AND lr.status = 'active'
|
|
502
719
|
AND ec.repository_root = ? AND ec.status = 'needs_confirmation'
|
|
503
720
|
ORDER BY lr.created_at, lr.run_id LIMIT 2`)
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
721
|
+
.all(project.workspace, sessionId, project.repositoryRoot);
|
|
722
|
+
if (process.env.KIOKUKO_INTENT_DEBUG === "1")
|
|
723
|
+
console.error("confirmation resume candidates", candidates.length);
|
|
724
|
+
return (candidates.length === 1 &&
|
|
725
|
+
(current === undefined ||
|
|
726
|
+
current.runId === candidates[0].runId));
|
|
727
|
+
}),
|
|
728
|
+
replay: async (input) => runtime.withDatabase((db) => {
|
|
729
|
+
const sessionId = input.agent.session.id;
|
|
730
|
+
if (detachedDemandSessions.has(sessionId))
|
|
731
|
+
return false;
|
|
732
|
+
const current = currentSession(sessionId);
|
|
733
|
+
// Matching persisted text is a cold continuation, not a replay of a
|
|
734
|
+
// currently admitted native turn. Leave it on the interpretation path.
|
|
735
|
+
if (!current ||
|
|
736
|
+
current.turn !== input.turn ||
|
|
737
|
+
current.nativeAgent !== input.agent ||
|
|
738
|
+
current.nativeSession !== input.agent.session ||
|
|
739
|
+
agents?.get(input.agent.id) !== input.agent ||
|
|
740
|
+
sessions?.get(sessionId) !== input.agent.session ||
|
|
741
|
+
current.closed ||
|
|
742
|
+
current.failed ||
|
|
743
|
+
!current.authority ||
|
|
744
|
+
current.prepared.run.status !== "active" ||
|
|
745
|
+
!["ready", "exhausted"].includes(current.prepared.intake.status) ||
|
|
746
|
+
current.prepared.nextAction !== "proceed" ||
|
|
747
|
+
selections.get(current.runId)?.value.discussion)
|
|
748
|
+
return false;
|
|
749
|
+
const human = input.messages.filter(isHumanMessage);
|
|
750
|
+
if (!human.length)
|
|
751
|
+
return false;
|
|
752
|
+
const task = textFromMessages(human);
|
|
753
|
+
const references = current.requestIntentContext?.messageRefs;
|
|
754
|
+
if (current.task !== task ||
|
|
755
|
+
!references ||
|
|
756
|
+
canonicalContentHash(requestIntentMessageRefs(human, task)) !== canonicalContentHash(references))
|
|
757
|
+
return false;
|
|
758
|
+
try {
|
|
759
|
+
authorizeTaskLease(db, current.authority);
|
|
760
|
+
}
|
|
761
|
+
catch {
|
|
762
|
+
return false;
|
|
763
|
+
}
|
|
764
|
+
return true;
|
|
765
|
+
}),
|
|
766
|
+
existing: async (input, requestIntent) => runtime.withDatabase(async (db) => {
|
|
767
|
+
if (detachedDemandSessions.has(input.agent.session.id))
|
|
768
|
+
return false;
|
|
769
|
+
const current = currentSession(input.agent.session.id);
|
|
770
|
+
// A retired native identity is not live execution authority. Keep its durable
|
|
771
|
+
// owner intact, but let a reopened session answer before attempting recovery.
|
|
772
|
+
// A queued human request is not a continuation grant from a stale normal
|
|
773
|
+
// turn. Preserve its owner, but infer the new request before any effects.
|
|
774
|
+
const text = input.messages
|
|
775
|
+
.filter(isHumanMessage)
|
|
776
|
+
.flatMap((message) => typeof message.content === "string"
|
|
777
|
+
? [message.content]
|
|
778
|
+
: (message.content ?? [])
|
|
779
|
+
.filter((block) => block.type === "text")
|
|
780
|
+
.map((block) => block.text))
|
|
781
|
+
.join("\n");
|
|
782
|
+
const keepsCurrentScope = requestIntent?.relation !== "new";
|
|
783
|
+
const resumeCoding = keepsCurrentScope &&
|
|
784
|
+
current &&
|
|
785
|
+
readCodingWorkflow(db, current.runId);
|
|
786
|
+
if (current &&
|
|
787
|
+
current.turn < input.turn &&
|
|
788
|
+
input.messages.some(isHumanMessage) &&
|
|
789
|
+
!current.prepared.ennoOduno.applicable &&
|
|
790
|
+
!resumeCoding)
|
|
791
|
+
return false;
|
|
792
|
+
if (current)
|
|
793
|
+
return (!current.closed &&
|
|
794
|
+
!current.failed &&
|
|
795
|
+
current.nativeAgent === input.agent &&
|
|
796
|
+
current.nativeSession === input.agent.session);
|
|
797
|
+
const project = await resolveProjectWorkspaceReadOnly(db, answerCwd(input.agent), { allowDirectory: true });
|
|
798
|
+
if (!project)
|
|
799
|
+
return false;
|
|
800
|
+
// The full adapter owns ledger runs, not the modular core ownership table.
|
|
801
|
+
// Recovery still goes through admission's exact workspace/session checks.
|
|
802
|
+
return Boolean(db
|
|
803
|
+
.prepare(`SELECT 1 FROM ledger_runs lr
|
|
560
804
|
LEFT JOIN enno_contracts ec ON ec.run_id=lr.run_id
|
|
561
805
|
LEFT JOIN dsh_coding_workflows cw ON cw.run_id=lr.run_id
|
|
562
806
|
WHERE lr.workspace=? AND lr.dsh_session_id=? AND lr.status='active'
|
|
563
807
|
AND ((ec.repository_root=? AND ec.status NOT IN ('completed','cancelled','blocked'))
|
|
564
808
|
OR (?=1 AND json_extract(cw.snapshot_json,'$.state') NOT IN ('completed','cancelled','superseded'))) LIMIT 1`)
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
809
|
+
.get(project.workspace, input.agent.session.id, project.repositoryRoot, requestIntent?.relation === "new" ? 0 : 1));
|
|
810
|
+
}),
|
|
811
|
+
classify: (input, task) => classifyTaskForIntake(decisions, dshTurnRequestId({
|
|
812
|
+
dshSessionId: input.agent.session.id,
|
|
813
|
+
turn: input.turn,
|
|
814
|
+
}), task, undefined, input.signal),
|
|
815
|
+
interpret: (input) => admission.interpret({
|
|
816
|
+
agent: input.agent,
|
|
817
|
+
messages: input.messages,
|
|
818
|
+
turn: input.turn,
|
|
819
|
+
step: input.step,
|
|
820
|
+
signal: input.signal,
|
|
821
|
+
}),
|
|
822
|
+
prepare: async (input, taskType, requestIntent) => {
|
|
823
|
+
const event = await admission.mapPreStep(input, taskType, requestIntent);
|
|
824
|
+
const result = await gate.prepareRequestedWork(event);
|
|
825
|
+
if (result.admitted)
|
|
826
|
+
detachedDemandSessions.delete(input.agent.session.id);
|
|
827
|
+
return (result.admitted &&
|
|
828
|
+
result.prepared.intake.profile.taskType !== "chat");
|
|
829
|
+
},
|
|
830
|
+
ready: (agent, turn) => {
|
|
831
|
+
if (agents?.get(agent.id) !== agent ||
|
|
832
|
+
sessions?.get(agent.session?.id ?? "") !== agent.session)
|
|
833
|
+
return false;
|
|
834
|
+
const current = agent.session && currentSession(agent.session.id);
|
|
835
|
+
return (!!current &&
|
|
836
|
+
current.nativeAgent === agent &&
|
|
837
|
+
current.nativeSession === agent.session &&
|
|
838
|
+
(turn === undefined || current.turn === turn) &&
|
|
839
|
+
!current.closed &&
|
|
840
|
+
!current.failed &&
|
|
841
|
+
current.prepared.run.status === "active" &&
|
|
842
|
+
["ready", "exhausted"].includes(current.prepared.intake.status) &&
|
|
843
|
+
current.prepared.nextAction === "proceed" &&
|
|
844
|
+
!selections.get(current.runId)?.value.discussion);
|
|
845
|
+
},
|
|
846
|
+
}, { onlyWhenDeferred: !conversationFirst })
|
|
847
|
+
: undefined;
|
|
586
848
|
if (demand)
|
|
587
849
|
lifecycleMemory.connectIntake(demand);
|
|
588
850
|
const taskWorkflow = demand && agents && sessions && skills?.snapshot && tools?.schemas
|
|
589
|
-
? new DshTaskWorkflow({
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
851
|
+
? new DshTaskWorkflow({
|
|
852
|
+
runtime,
|
|
853
|
+
demand,
|
|
854
|
+
agents,
|
|
855
|
+
sessions,
|
|
856
|
+
skills: { snapshot: (options) => skills.snapshot(options) },
|
|
857
|
+
tools: { schemas: (agent) => tools.schemas(agent) },
|
|
858
|
+
lisp: () => native.get(LISP_ASSEMBLY_SERVICE, false),
|
|
859
|
+
checkpointSource: async (agent) => {
|
|
860
|
+
await sessions.flush?.(agent.session);
|
|
861
|
+
try {
|
|
862
|
+
await sessionMirror.checkpointAfterNativeFlush(agent.session);
|
|
863
|
+
}
|
|
864
|
+
catch {
|
|
865
|
+
/* Optional mirror cannot veto native completion or Stop. */
|
|
866
|
+
}
|
|
867
|
+
},
|
|
868
|
+
onCompleted: (task) => lifecycle.completeTask(task),
|
|
869
|
+
kickFinalizer: () => memoryFinalizer.kick(),
|
|
870
|
+
emit: (task) => {
|
|
871
|
+
ctx.emit(TASK_STATE_EVENT, task);
|
|
872
|
+
},
|
|
873
|
+
})
|
|
874
|
+
: undefined;
|
|
875
|
+
const demandEnd = demand
|
|
876
|
+
? onNativeEvent(ctx, "session/event", (session, event) => {
|
|
877
|
+
if (event.type === "turn/end")
|
|
878
|
+
demand.finish(session, event.data?.turn);
|
|
879
|
+
if (event.type === "request/context" && !currentSession(session.id)) {
|
|
880
|
+
const answer = demand.answerOwner(session);
|
|
881
|
+
if (answer) {
|
|
882
|
+
const header = [...(answer.agent.session?.snapshotEvents?.() ?? [])]
|
|
883
|
+
.reverse()
|
|
884
|
+
.find((e) => e.type === "request/header")?.data;
|
|
885
|
+
void memoryFinalizer
|
|
886
|
+
.admitConversationIndex(answer.workspace, session.id, {
|
|
887
|
+
...header?.header?.config,
|
|
888
|
+
contextWindow: event.data?.contextWindow,
|
|
889
|
+
}, () => agents?.get(answer.agent.id) === answer.agent &&
|
|
890
|
+
sessions?.get(session.id) === session &&
|
|
891
|
+
demand.answerOwner(session)?.workspace === answer.workspace)
|
|
892
|
+
.catch(() => { });
|
|
893
|
+
}
|
|
605
894
|
}
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
const demandDisposed = demand
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
895
|
+
})
|
|
896
|
+
: undefined;
|
|
897
|
+
const demandDisposed = demand
|
|
898
|
+
? onNativeEvent(ctx, "agent/disposed", ({ agent }) => {
|
|
899
|
+
demand.retire(agent);
|
|
900
|
+
const item = agent.session && currentSession(agent.session.id);
|
|
901
|
+
if (item?.nativeAgent !== agent || item.nativeSession !== agent.session)
|
|
902
|
+
return;
|
|
903
|
+
// Drop only dead in-memory bindings. Durable ownership and obligations remain
|
|
904
|
+
// untouched; a reopened session may answer but cannot borrow the old grant.
|
|
905
|
+
detachedDemandSessions.add(item.sessionId);
|
|
906
|
+
gate.clearTurn(item.sessionId, item.turn);
|
|
907
|
+
executionSupport.clear(item.sessionId);
|
|
908
|
+
turnState.releaseRun(item.runId);
|
|
909
|
+
})
|
|
910
|
+
: undefined;
|
|
620
911
|
const discussionGuardDisposer = tools?.guard((value) => {
|
|
621
912
|
const agent = value.agent;
|
|
622
913
|
if (!agent?.session)
|
|
623
914
|
return undefined;
|
|
624
915
|
const lispCoding = native.get(LISP_CODING_SERVICE, false);
|
|
625
916
|
if (lispCoding?.discussing(agent))
|
|
626
|
-
return
|
|
917
|
+
return "Lispモードの選択への自由入力に回答中です。ツールを使わず、ユーザーの発言に回答してください。";
|
|
627
918
|
const item = currentSession(agent.session.id);
|
|
628
|
-
if (item?.nativeAgent === agent &&
|
|
629
|
-
|
|
919
|
+
if (item?.nativeAgent === agent &&
|
|
920
|
+
item.nativeSession === agent.session &&
|
|
921
|
+
selections.get(item.runId)?.value.discussion) {
|
|
922
|
+
return "自由入力への回答中です。実行方式は未確定です。ツールを使わず、ユーザーの発言に回答してください。";
|
|
630
923
|
}
|
|
631
924
|
return undefined;
|
|
632
925
|
});
|
|
633
926
|
const pairChanges = new Map();
|
|
634
|
-
const pairLlm = native.get(
|
|
927
|
+
const pairLlm = native.get("llm", false);
|
|
635
928
|
const ownsPairRoot = (agent) => {
|
|
636
|
-
if (!agent.session ||
|
|
929
|
+
if (!agent.session ||
|
|
930
|
+
isNativeSubagent(agent) ||
|
|
931
|
+
agents?.get(agent.id) !== agent ||
|
|
932
|
+
sessions?.get(agent.session.id) !== agent.session)
|
|
637
933
|
return false;
|
|
638
934
|
try {
|
|
639
|
-
return typeof agent.session.header?.cwd ===
|
|
935
|
+
return (typeof agent.session.header?.cwd === "string" &&
|
|
936
|
+
realpathSync(agent.session.header.cwd) === root);
|
|
640
937
|
}
|
|
641
938
|
catch {
|
|
642
939
|
return false;
|
|
643
940
|
}
|
|
644
941
|
};
|
|
645
942
|
const nativeWorkers = new NativeWorkerRouting({
|
|
646
|
-
runtime,
|
|
943
|
+
runtime,
|
|
944
|
+
backend: native.get("subagents", false),
|
|
945
|
+
agents,
|
|
946
|
+
sessions,
|
|
647
947
|
resolveOwner: async (agent, signal) => {
|
|
648
948
|
if (!ownsPairRoot(agent))
|
|
649
949
|
return undefined;
|
|
@@ -651,35 +951,51 @@ export function createDshHostAdapter(ctx, options = {}) {
|
|
|
651
951
|
signal.throwIfAborted();
|
|
652
952
|
const item = currentSession(agent.session.id);
|
|
653
953
|
if (item && !item.closed) {
|
|
654
|
-
const stored = await runtime.withDatabase(db => readExecutionSelection(db, item.runId));
|
|
954
|
+
const stored = await runtime.withDatabase((db) => readExecutionSelection(db, item.runId));
|
|
655
955
|
if (stored?.value.headWorker) {
|
|
656
|
-
if (item.nativeAgent !== agent ||
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
throw new KiokukoError(
|
|
660
|
-
|
|
956
|
+
if (item.nativeAgent !== agent ||
|
|
957
|
+
item.nativeSession !== agent.session ||
|
|
958
|
+
item.failed)
|
|
959
|
+
throw new KiokukoError("CONFLICT", "Head/worker execution owner changed");
|
|
960
|
+
if (stored.value.status !== "ready" || stored.value.discussion)
|
|
961
|
+
throw new KiokukoError("CONFLICT", "Head/worker selection is not ready");
|
|
962
|
+
return {
|
|
963
|
+
id: `run:${item.runId}`,
|
|
964
|
+
sessionId: item.sessionId,
|
|
965
|
+
selectionId: String(stored.revision),
|
|
966
|
+
pair: stored.value.headWorker,
|
|
967
|
+
};
|
|
661
968
|
}
|
|
662
969
|
// An existing approved Enno or Deep configuration owns its own roles.
|
|
663
|
-
if (stored?.value.mode ===
|
|
970
|
+
if (stored?.value.mode === "enno" ||
|
|
971
|
+
stored?.value.mode === "deep-thinker")
|
|
664
972
|
return undefined;
|
|
665
973
|
}
|
|
666
974
|
if (!pairLlm)
|
|
667
975
|
return undefined;
|
|
668
976
|
const saved = await getHeadWorkerSessionSelection(pairLlm, agent.session.id);
|
|
669
|
-
return saved.configuration
|
|
977
|
+
return saved.configuration
|
|
978
|
+
? {
|
|
979
|
+
id: `session:${agent.session.id}`,
|
|
980
|
+
sessionId: agent.session.id,
|
|
981
|
+
selectionId: String(saved.revision),
|
|
982
|
+
pair: saved.configuration,
|
|
983
|
+
}
|
|
984
|
+
: undefined;
|
|
670
985
|
},
|
|
671
986
|
validate: async (pair, signal) => {
|
|
672
987
|
if (!modelCatalog)
|
|
673
|
-
throw new KiokukoError(
|
|
988
|
+
throw new KiokukoError("SERVICE_UNAVAILABLE", "Head/worker model catalog is unavailable");
|
|
674
989
|
signal.throwIfAborted();
|
|
675
990
|
const problems = await validateHeadWorker(pair, modelCatalog, options.modelRoutes ?? [], modelCompatibility);
|
|
676
991
|
signal.throwIfAborted();
|
|
677
992
|
if (problems.length)
|
|
678
|
-
throw new KiokukoError(
|
|
993
|
+
throw new KiokukoError("CONFLICT", problems.join("\n"));
|
|
679
994
|
},
|
|
680
995
|
});
|
|
681
|
-
const nativeWorkerToolDisposer = onNativeEvent(ctx,
|
|
682
|
-
if (execution.agent &&
|
|
996
|
+
const nativeWorkerToolDisposer = onNativeEvent(ctx, "tools/execute", async (execution, next) => {
|
|
997
|
+
if (execution.agent &&
|
|
998
|
+
isGenericNativeChild(execution.agent))
|
|
683
999
|
await nativeWorkers.assertCurrent(execution.agent);
|
|
684
1000
|
return next();
|
|
685
1001
|
}, { prepend: true });
|
|
@@ -690,72 +1006,103 @@ export function createDshHostAdapter(ctx, options = {}) {
|
|
|
690
1006
|
pairChanges.set(agent.session.id, pending);
|
|
691
1007
|
void pending.catch(() => { });
|
|
692
1008
|
};
|
|
693
|
-
const freezePairDisposer = onNativeEvent(ctx,
|
|
1009
|
+
const freezePairDisposer = onNativeEvent(ctx, "agent/created", ({ agent }) => freezePair(agent));
|
|
694
1010
|
for (const agent of agents?.list?.() ?? [])
|
|
695
1011
|
freezePair(agent);
|
|
696
1012
|
const clearRunPair = async (sessionId, isCurrent = () => true) => {
|
|
697
1013
|
const session = sessions?.get(sessionId);
|
|
698
|
-
const agent = agents
|
|
1014
|
+
const agent = agents
|
|
1015
|
+
?.list?.()
|
|
1016
|
+
.find((candidate) => candidate.session === session);
|
|
699
1017
|
if (!agent || !ownsPairRoot(agent))
|
|
700
1018
|
return;
|
|
701
1019
|
const item = currentSession(sessionId);
|
|
702
|
-
if (item &&
|
|
703
|
-
|
|
1020
|
+
if (item &&
|
|
1021
|
+
!item.closed &&
|
|
1022
|
+
item.nativeAgent === agent &&
|
|
1023
|
+
item.nativeSession === session)
|
|
1024
|
+
await runtime.withDatabase((db) => {
|
|
704
1025
|
if (!isCurrent())
|
|
705
1026
|
return;
|
|
706
1027
|
const stored = readExecutionSelection(db, item.runId);
|
|
707
|
-
if (stored?.value.mode ===
|
|
1028
|
+
if (stored?.value.mode === "normal" && stored.value.headWorker) {
|
|
708
1029
|
const { headWorker: _pair, ...value } = stored.value;
|
|
709
1030
|
selections.set(item.runId, writeExecutionSelection(db, item.runId, stored.revision, value));
|
|
710
1031
|
}
|
|
711
1032
|
});
|
|
712
1033
|
};
|
|
713
|
-
const pairSettingsDisposer = onNativeServiceEvent(ctx,
|
|
1034
|
+
const pairSettingsDisposer = onNativeServiceEvent(ctx, "kiokuko/head-worker-selected", (sessionId) => {
|
|
714
1035
|
// The settings commit and normal-run override removal are one dispatch fence.
|
|
715
1036
|
const pending = Promise.resolve().then(() => clearRunPair(sessionId, () => pairChanges.get(sessionId) === pending));
|
|
716
1037
|
pairChanges.set(sessionId, pending);
|
|
717
1038
|
void pending.catch(() => { });
|
|
718
1039
|
return pending;
|
|
719
1040
|
});
|
|
720
|
-
const pairSelectionDisposer = onNativeEvent(ctx,
|
|
721
|
-
if (event.type !==
|
|
1041
|
+
const pairSelectionDisposer = onNativeEvent(ctx, "session/event", (session, event) => {
|
|
1042
|
+
if (event.type !== "model/selection" ||
|
|
1043
|
+
sessions?.get(session.id) !== session ||
|
|
1044
|
+
!pairLlm)
|
|
722
1045
|
return;
|
|
723
|
-
const agent = agents
|
|
1046
|
+
const agent = agents
|
|
1047
|
+
?.list?.()
|
|
1048
|
+
.find((candidate) => candidate.session === session);
|
|
724
1049
|
if (!agent || !ownsPairRoot(agent))
|
|
725
1050
|
return;
|
|
726
1051
|
const previous = pairChanges.get(session.id);
|
|
727
|
-
const pending = Promise.resolve(previous)
|
|
1052
|
+
const pending = Promise.resolve(previous)
|
|
1053
|
+
.catch(() => { })
|
|
1054
|
+
.then(async () => {
|
|
728
1055
|
const isCurrent = () => pairChanges.get(session.id) === pending;
|
|
729
1056
|
if (!isCurrent())
|
|
730
1057
|
return;
|
|
731
1058
|
const item = currentSession(session.id);
|
|
732
|
-
const stored = item && !item.closed
|
|
1059
|
+
const stored = item && !item.closed
|
|
1060
|
+
? await runtime.withDatabase((db) => readExecutionSelection(db, item.runId))
|
|
1061
|
+
: undefined;
|
|
733
1062
|
if (!isCurrent())
|
|
734
1063
|
return;
|
|
735
|
-
const configured = stored?.value.headWorker ??
|
|
1064
|
+
const configured = stored?.value.headWorker ??
|
|
1065
|
+
(await getHeadWorkerSessionSelection(pairLlm, session.id))
|
|
1066
|
+
.configuration;
|
|
736
1067
|
if (!isCurrent())
|
|
737
1068
|
return;
|
|
738
1069
|
const selected = event.data;
|
|
739
1070
|
// Native pickers may publish an idempotent re-selection of the same head.
|
|
740
|
-
if (configured &&
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
1071
|
+
if (configured &&
|
|
1072
|
+
selected?.provider === configured.head.provider &&
|
|
1073
|
+
selected.model === configured.head.model) {
|
|
1074
|
+
if (typeof selected.reasoningEffort === "string" &&
|
|
1075
|
+
selected.reasoningEffort &&
|
|
1076
|
+
selected.reasoningEffort !== configured.head.reasoningEffort) {
|
|
1077
|
+
const pair = {
|
|
1078
|
+
...configured,
|
|
1079
|
+
head: {
|
|
1080
|
+
...configured.head,
|
|
1081
|
+
reasoningEffort: selected.reasoningEffort,
|
|
1082
|
+
},
|
|
1083
|
+
};
|
|
1084
|
+
if (stored?.value.mode === "normal" &&
|
|
1085
|
+
stored.value.headWorker &&
|
|
1086
|
+
item) {
|
|
744
1087
|
if (!modelCatalog)
|
|
745
|
-
throw new KiokukoError(
|
|
1088
|
+
throw new KiokukoError("SERVICE_UNAVAILABLE", "Head/worker model catalog is unavailable");
|
|
746
1089
|
const problems = await validateHeadWorker(pair, modelCatalog, options.modelRoutes ?? [], modelCompatibility);
|
|
747
1090
|
if (problems.length)
|
|
748
|
-
throw new KiokukoError(
|
|
749
|
-
await runtime.withDatabase(db => {
|
|
1091
|
+
throw new KiokukoError("CONFLICT", problems.join("\n"));
|
|
1092
|
+
await runtime.withDatabase((db) => {
|
|
750
1093
|
if (!isCurrent())
|
|
751
1094
|
return;
|
|
752
|
-
selections.set(item.runId, writeExecutionSelection(db, item.runId, stored.revision, {
|
|
1095
|
+
selections.set(item.runId, writeExecutionSelection(db, item.runId, stored.revision, {
|
|
1096
|
+
...stored.value,
|
|
1097
|
+
headWorker: pair,
|
|
1098
|
+
}));
|
|
753
1099
|
});
|
|
754
1100
|
}
|
|
755
1101
|
const saved = await getHeadWorkerSessionSelection(pairLlm, session.id);
|
|
756
1102
|
if (!isCurrent())
|
|
757
1103
|
return;
|
|
758
|
-
if (saved.configuration?.head.provider === selected.provider &&
|
|
1104
|
+
if (saved.configuration?.head.provider === selected.provider &&
|
|
1105
|
+
saved.configuration.head.model === selected.model)
|
|
759
1106
|
await updateHeadWorkerEffortForSession(pairLlm, session.id, selected.reasoningEffort, isCurrent);
|
|
760
1107
|
}
|
|
761
1108
|
return;
|
|
@@ -767,155 +1114,350 @@ export function createDshHostAdapter(ctx, options = {}) {
|
|
|
767
1114
|
void pending.catch(() => { });
|
|
768
1115
|
});
|
|
769
1116
|
const routing = createRouting({
|
|
770
|
-
ctx,
|
|
1117
|
+
ctx,
|
|
1118
|
+
native,
|
|
1119
|
+
tools,
|
|
1120
|
+
agents,
|
|
1121
|
+
sessions,
|
|
1122
|
+
runtime,
|
|
1123
|
+
modelAuto,
|
|
1124
|
+
answerReview,
|
|
1125
|
+
semanticCompaction,
|
|
1126
|
+
delegation,
|
|
1127
|
+
deepPlanning,
|
|
1128
|
+
isGenericNativeChild,
|
|
1129
|
+
demand,
|
|
1130
|
+
nativeWorkers,
|
|
771
1131
|
getSkillPrompts: () => skillPrompts,
|
|
772
|
-
getToolExposureConfig: () => toolExposureConfig,
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
1132
|
+
getToolExposureConfig: () => toolExposureConfig,
|
|
1133
|
+
reportToolExposureFallback,
|
|
1134
|
+
reportToolExposureProjection,
|
|
1135
|
+
modelCatalog,
|
|
1136
|
+
getSelection: (runId) => selections.get(runId),
|
|
1137
|
+
setSelection: (runId, value) => {
|
|
1138
|
+
selections.set(runId, value);
|
|
1139
|
+
},
|
|
1140
|
+
hasSelection: (runId) => selections.has(runId),
|
|
1141
|
+
getPolicyState: (runId) => turnState.policyState(runId),
|
|
1142
|
+
captureInitialInput,
|
|
1143
|
+
prepareTurn: (event) => gate.prepare(event),
|
|
1144
|
+
mapPreStep,
|
|
1145
|
+
currentSession,
|
|
1146
|
+
readStateForRun: (item) => runtime.withDatabase((db) => stateForRun(db, item)),
|
|
777
1147
|
refreshMemoryOwner: admission.refreshMemoryOwner,
|
|
778
1148
|
});
|
|
779
1149
|
const contextMessages = createContextMessages({
|
|
780
|
-
ctx,
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
1150
|
+
ctx,
|
|
1151
|
+
runtime,
|
|
1152
|
+
memoryRetrievalConfig,
|
|
1153
|
+
decisions,
|
|
1154
|
+
deepPlanning,
|
|
1155
|
+
executionSupport,
|
|
1156
|
+
continuityMode: continuityConfig.mode,
|
|
1157
|
+
getSkillPrompts: () => skillPrompts,
|
|
1158
|
+
systemSkillsFor: routing.systemSkillsFor,
|
|
1159
|
+
getSelection: (runId) => selections.get(runId),
|
|
1160
|
+
currentForAgentEvent,
|
|
1161
|
+
advisoryEvidenceFor: (item, state) => toolHostModule.advisoryEvidenceFor(item, state),
|
|
1162
|
+
executionBinding,
|
|
1163
|
+
sessionEventSource,
|
|
784
1164
|
});
|
|
785
1165
|
const toolHostModule = createToolHost({
|
|
786
|
-
runtime,
|
|
787
|
-
|
|
788
|
-
|
|
1166
|
+
runtime,
|
|
1167
|
+
turnState,
|
|
1168
|
+
currentSession,
|
|
1169
|
+
currentForAgentEvent,
|
|
1170
|
+
skills,
|
|
1171
|
+
tools,
|
|
1172
|
+
sessions,
|
|
1173
|
+
agents,
|
|
1174
|
+
gate,
|
|
1175
|
+
decisions,
|
|
1176
|
+
delegation,
|
|
1177
|
+
llm,
|
|
1178
|
+
modelCatalog,
|
|
1179
|
+
executionSupport,
|
|
1180
|
+
executionBinding,
|
|
1181
|
+
policy,
|
|
1182
|
+
advisory,
|
|
1183
|
+
capabilityCatalog,
|
|
1184
|
+
objectRecord,
|
|
789
1185
|
});
|
|
790
1186
|
const { toolHost, advisoryRunner, assertTurnBoundary, submitAdvisory } = toolHostModule;
|
|
791
1187
|
const advisoryEvidenceFor = toolHostModule.advisoryEvidenceFor;
|
|
792
1188
|
const boundaries = createBoundaries({
|
|
793
1189
|
isGenericNativeChild,
|
|
794
|
-
ctx,
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
1190
|
+
ctx,
|
|
1191
|
+
runtime,
|
|
1192
|
+
now: options.now,
|
|
1193
|
+
agents,
|
|
1194
|
+
sessions,
|
|
1195
|
+
skills,
|
|
1196
|
+
tools,
|
|
1197
|
+
userQuestions,
|
|
1198
|
+
gate,
|
|
1199
|
+
delegation,
|
|
1200
|
+
executionSupport,
|
|
1201
|
+
answerReview,
|
|
1202
|
+
sessionMirror,
|
|
1203
|
+
currentSession,
|
|
1204
|
+
currentForAgentEvent,
|
|
1205
|
+
stateForRun,
|
|
1206
|
+
systemSkillsFor: routing.systemSkillsFor,
|
|
1207
|
+
getSkillPrompts: () => skillPrompts,
|
|
1208
|
+
refreshEnnoMemory,
|
|
1209
|
+
confirmationAnswerer,
|
|
1210
|
+
assertTurnBoundary,
|
|
1211
|
+
advisoryRunner,
|
|
1212
|
+
submitAdvisory,
|
|
1213
|
+
advisoryEvidenceFor,
|
|
1214
|
+
applyPolicy: turnState.applyPolicy,
|
|
1215
|
+
capabilityCatalog,
|
|
1216
|
+
closeTurn: (input) => runLifecycle.closeTurn(input),
|
|
1217
|
+
sessionEventSource,
|
|
1218
|
+
boundedUtf8Text,
|
|
1219
|
+
boundedMessageText,
|
|
1220
|
+
recoveryMessage,
|
|
1221
|
+
continuationMessage,
|
|
801
1222
|
});
|
|
802
|
-
const { boundaryWorker, ennoController, deliverCompletionReport, boundarySessionStartDisposer } = boundaries;
|
|
1223
|
+
const { boundaryWorker, ennoController, deliverCompletionReport, boundarySessionStartDisposer, } = boundaries;
|
|
803
1224
|
const applicationDisposer = mountHostMemoryApplication({
|
|
804
1225
|
questions: userQuestions,
|
|
805
|
-
ctx,
|
|
806
|
-
turnState, gate, capabilityCatalog, memoryRetrievalConfig, demand,
|
|
807
|
-
});
|
|
808
|
-
const codingDisposer = tools ? mountCodingWorkflow({ tools: tools,
|
|
809
|
-
on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options) }, {
|
|
810
|
-
runtime, ...(userQuestions ? { questions: userQuestions } : {}),
|
|
811
|
-
lisp: () => native.get(LISP_CODING_SERVICE, false),
|
|
812
|
-
preparationOnly: execution => demand?.preparationOnly(execution) === true,
|
|
813
|
-
nativeCommand: execution => demand?.nativeCommand(execution) === true,
|
|
814
|
-
nativeLisp: execution => demand?.nativeLisp(execution) === true,
|
|
815
|
-
resolve(execution) {
|
|
816
|
-
const agent = execution.agent, session = agent?.session;
|
|
817
|
-
if (!agent || !session || agents?.get(agent.id) !== agent || sessions?.get(session.id) !== session)
|
|
818
|
-
return undefined;
|
|
819
|
-
const child = delegation.observationBinding(agent);
|
|
820
|
-
const item = currentSession(child?.parentSessionId ?? session.id);
|
|
821
|
-
if (!item || item.closed || child && child.runId !== item.runId || !child && (item.nativeAgent !== agent || item.nativeSession !== session))
|
|
822
|
-
return undefined;
|
|
823
|
-
return { runId: item.runId, sessionId: item.sessionId, repositoryRoot: item.repositoryRoot, agent, task: item.task,
|
|
824
|
-
requestIntent: item.requestIntent, requestIntentContext: item.requestIntentContext };
|
|
825
|
-
},
|
|
826
|
-
}) : undefined;
|
|
827
|
-
const completionDisposer = tools ? mountTaskCompletion({ tools: tools,
|
|
828
|
-
on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options) }, {
|
|
1226
|
+
ctx,
|
|
829
1227
|
runtime,
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
1228
|
+
tools,
|
|
1229
|
+
commands,
|
|
1230
|
+
skills,
|
|
1231
|
+
agents,
|
|
1232
|
+
sessions,
|
|
1233
|
+
delegation,
|
|
1234
|
+
currentSession,
|
|
1235
|
+
turnState,
|
|
1236
|
+
gate,
|
|
1237
|
+
capabilityCatalog,
|
|
1238
|
+
memoryRetrievalConfig,
|
|
1239
|
+
demand,
|
|
1240
|
+
});
|
|
1241
|
+
const codingDisposer = tools
|
|
1242
|
+
? mountCodingWorkflow({
|
|
1243
|
+
tools: tools,
|
|
1244
|
+
on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options),
|
|
1245
|
+
}, {
|
|
1246
|
+
runtime,
|
|
1247
|
+
...(userQuestions ? { questions: userQuestions } : {}),
|
|
1248
|
+
lisp: () => native.get(LISP_CODING_SERVICE, false),
|
|
1249
|
+
preparationOnly: (execution) => demand?.preparationOnly(execution) === true,
|
|
1250
|
+
nativeCommand: (execution) => demand?.nativeCommand(execution) === true,
|
|
1251
|
+
nativeLisp: (execution) => demand?.nativeLisp(execution) === true,
|
|
1252
|
+
resolve(execution) {
|
|
1253
|
+
const agent = execution.agent, session = agent?.session;
|
|
1254
|
+
if (!agent ||
|
|
1255
|
+
!session ||
|
|
1256
|
+
agents?.get(agent.id) !== agent ||
|
|
1257
|
+
sessions?.get(session.id) !== session)
|
|
1258
|
+
return undefined;
|
|
1259
|
+
const child = delegation.observationBinding(agent);
|
|
1260
|
+
const item = currentSession(child?.parentSessionId ?? session.id);
|
|
1261
|
+
if (!item ||
|
|
1262
|
+
item.closed ||
|
|
1263
|
+
(child && child.runId !== item.runId) ||
|
|
1264
|
+
(!child &&
|
|
1265
|
+
(item.nativeAgent !== agent || item.nativeSession !== session)))
|
|
1266
|
+
return undefined;
|
|
1267
|
+
return {
|
|
1268
|
+
runId: item.runId,
|
|
1269
|
+
sessionId: item.sessionId,
|
|
1270
|
+
repositoryRoot: item.repositoryRoot,
|
|
1271
|
+
agent,
|
|
1272
|
+
task: item.task,
|
|
1273
|
+
requestIntent: item.requestIntent,
|
|
1274
|
+
requestIntentContext: item.requestIntentContext,
|
|
1275
|
+
};
|
|
1276
|
+
},
|
|
1277
|
+
})
|
|
1278
|
+
: undefined;
|
|
1279
|
+
const completionDisposer = tools
|
|
1280
|
+
? mountTaskCompletion({
|
|
1281
|
+
tools: tools,
|
|
1282
|
+
on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options),
|
|
1283
|
+
}, {
|
|
1284
|
+
runtime,
|
|
1285
|
+
resolve(execution) {
|
|
1286
|
+
const agent = execution.agent;
|
|
1287
|
+
const session = agent?.session;
|
|
1288
|
+
const item = session ? currentSession(session.id) : undefined;
|
|
1289
|
+
if (!agent ||
|
|
1290
|
+
!session ||
|
|
1291
|
+
agents?.get(agent.id) !== agent ||
|
|
1292
|
+
sessions?.get(session.id) !== session ||
|
|
1293
|
+
!item ||
|
|
1294
|
+
item.closed ||
|
|
1295
|
+
item.nativeAgent !== agent ||
|
|
1296
|
+
item.nativeSession !== session ||
|
|
1297
|
+
delegation.isChild(agent) ||
|
|
1298
|
+
isGenericNativeChild(agent))
|
|
1299
|
+
return undefined;
|
|
1300
|
+
return {
|
|
1301
|
+
runId: item.runId,
|
|
1302
|
+
sessionId: item.sessionId,
|
|
1303
|
+
repositoryRoot: item.repositoryRoot,
|
|
1304
|
+
agent,
|
|
1305
|
+
};
|
|
1306
|
+
},
|
|
1307
|
+
async approve() {
|
|
1308
|
+
return true;
|
|
1309
|
+
},
|
|
1310
|
+
})
|
|
1311
|
+
: undefined;
|
|
842
1312
|
const resolveParentOwned = (execution) => {
|
|
843
1313
|
const agent = execution.agent, session = agent?.session;
|
|
844
|
-
if (!agent ||
|
|
1314
|
+
if (!agent ||
|
|
1315
|
+
!session ||
|
|
1316
|
+
agents?.get(agent.id) !== agent ||
|
|
1317
|
+
sessions?.get(session.id) !== session ||
|
|
1318
|
+
isGenericNativeChild(agent))
|
|
845
1319
|
return undefined;
|
|
846
1320
|
const child = delegation.observationBinding(agent);
|
|
847
1321
|
const item = currentSession(child?.parentSessionId ?? session.id);
|
|
848
|
-
if (!item ||
|
|
1322
|
+
if (!item ||
|
|
1323
|
+
item.closed ||
|
|
1324
|
+
(child && child.runId !== item.runId) ||
|
|
1325
|
+
(!child && (item.nativeAgent !== agent || item.nativeSession !== session)))
|
|
849
1326
|
return undefined;
|
|
850
|
-
if (child &&
|
|
1327
|
+
if (child &&
|
|
1328
|
+
delegation.toolDenial(agent, execution.name, execution.arguments))
|
|
851
1329
|
return undefined;
|
|
852
|
-
return {
|
|
853
|
-
|
|
1330
|
+
return {
|
|
1331
|
+
runId: item.runId,
|
|
1332
|
+
sessionId: session.id,
|
|
1333
|
+
workflowSessionId: item.sessionId,
|
|
1334
|
+
workspace: item.workspace,
|
|
1335
|
+
repositoryRoot: item.repositoryRoot,
|
|
1336
|
+
generation: executionBinding(item).generation,
|
|
1337
|
+
agent,
|
|
1338
|
+
requestIntent: item.requestIntent,
|
|
1339
|
+
requestIntentContext: item.requestIntentContext,
|
|
1340
|
+
};
|
|
854
1341
|
};
|
|
855
|
-
const nativeTaskAuthority = new NativeTaskAuthority({
|
|
856
|
-
const ownedDisposer = tools ? mountOwnedExecution({ tools: tools, on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options) }, {
|
|
1342
|
+
const nativeTaskAuthority = new NativeTaskAuthority({
|
|
857
1343
|
runtime,
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
const current = resolveParentOwned(execution);
|
|
883
|
-
if (execution.name === 'kioku_read' && current) {
|
|
884
|
-
const item = currentSession(session.id);
|
|
885
|
-
if (!item?.authority || item.cwd !== cwd || item.repositoryRoot !== current.repositoryRoot)
|
|
1344
|
+
repositoryRoot: root,
|
|
1345
|
+
backend: native.get("subagents", false),
|
|
1346
|
+
agents,
|
|
1347
|
+
sessions,
|
|
1348
|
+
resolveParent: resolveParentOwned,
|
|
1349
|
+
});
|
|
1350
|
+
const ownedDisposer = tools
|
|
1351
|
+
? mountOwnedExecution({
|
|
1352
|
+
tools: tools,
|
|
1353
|
+
on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options),
|
|
1354
|
+
}, {
|
|
1355
|
+
runtime,
|
|
1356
|
+
unownedNative: (execution) => demand?.unownedNative(execution) === true,
|
|
1357
|
+
nativeCommand: (execution) => demand?.nativeCommand(execution) === true,
|
|
1358
|
+
nativeLisp: (execution) => demand?.nativeLisp(execution) === true,
|
|
1359
|
+
isTaskControl: (execution) => ctx.get(TASK_WORKFLOW_SERVICE, false)?.isControl(execution) === true,
|
|
1360
|
+
resolve: (execution) => nativeTaskAuthority.resolve(execution) ??
|
|
1361
|
+
resolveParentOwned(execution),
|
|
1362
|
+
async resolveRead(execution) {
|
|
1363
|
+
const agent = execution.agent, session = agent?.session;
|
|
1364
|
+
if (!agent ||
|
|
1365
|
+
!session ||
|
|
1366
|
+
agents?.get(agent.id) !== agent ||
|
|
1367
|
+
sessions?.get(session.id) !== session)
|
|
886
1368
|
return undefined;
|
|
887
|
-
|
|
1369
|
+
let cwd;
|
|
888
1370
|
try {
|
|
889
|
-
|
|
1371
|
+
if (typeof session.header?.cwd !== "string")
|
|
1372
|
+
return undefined;
|
|
1373
|
+
cwd = realpathSync(session.header.cwd);
|
|
890
1374
|
}
|
|
891
1375
|
catch {
|
|
892
1376
|
return undefined;
|
|
893
1377
|
}
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
1378
|
+
// Child scopes retain their independent lineage checks. A primary session
|
|
1379
|
+
// may have been admitted from a directory other than plugin startup cwd.
|
|
1380
|
+
if (isGenericNativeChild(agent))
|
|
1381
|
+
return cwd === root
|
|
1382
|
+
? nativeTaskAuthority.read(execution)
|
|
1383
|
+
: undefined;
|
|
1384
|
+
if (delegation.isChild(agent))
|
|
1385
|
+
return cwd === root ? resolveParentOwned(execution) : undefined;
|
|
1386
|
+
const current = resolveParentOwned(execution);
|
|
1387
|
+
if (execution.name === "kioku_read" && current) {
|
|
1388
|
+
const item = currentSession(session.id);
|
|
1389
|
+
if (!item?.authority ||
|
|
1390
|
+
item.cwd !== cwd ||
|
|
1391
|
+
item.repositoryRoot !== current.repositoryRoot)
|
|
1392
|
+
return undefined;
|
|
1393
|
+
const authority = item.authority;
|
|
1394
|
+
try {
|
|
1395
|
+
await runtime.withDatabase((db) => authorizeTaskLease(db, authority));
|
|
1396
|
+
}
|
|
1397
|
+
catch {
|
|
1398
|
+
return undefined;
|
|
1399
|
+
}
|
|
1400
|
+
if (currentSession(session.id) !== item ||
|
|
1401
|
+
item.authority !== authority ||
|
|
1402
|
+
item.closed ||
|
|
1403
|
+
agents?.get(agent.id) !== agent ||
|
|
1404
|
+
sessions?.get(session.id) !== session)
|
|
1405
|
+
return undefined;
|
|
1406
|
+
return current;
|
|
1407
|
+
}
|
|
1408
|
+
return ((await runtime.withDatabase(async (db) => {
|
|
1409
|
+
const project = await resolveProjectWorkspaceReadOnly(db, cwd, {
|
|
1410
|
+
allowDirectory: true,
|
|
1411
|
+
});
|
|
1412
|
+
return project
|
|
1413
|
+
? readOwnedIdentity(db, agent, project.repositoryRoot, execution.name === "kioku_result"
|
|
1414
|
+
? execution.arguments?.operationId
|
|
1415
|
+
: undefined)
|
|
1416
|
+
: undefined;
|
|
1417
|
+
})) ?? resolveParentOwned(execution));
|
|
1418
|
+
},
|
|
1419
|
+
planActive: (agent) => ctx.get("planMode", false)?.get(agent)?.active === true,
|
|
1420
|
+
async confirm(identity, detail, signal) {
|
|
1421
|
+
if (!userQuestions)
|
|
1422
|
+
return false;
|
|
1423
|
+
const id = `kioku-destructive-${crypto.randomUUID()}`;
|
|
1424
|
+
const answer = await userQuestions.ask({
|
|
1425
|
+
agent: identity.agent,
|
|
1426
|
+
signal,
|
|
1427
|
+
questions: [
|
|
1428
|
+
{
|
|
1429
|
+
id,
|
|
1430
|
+
header: "破壊的変更の確認",
|
|
1431
|
+
question: "この対象への変更を許可しますか?",
|
|
1432
|
+
detail,
|
|
1433
|
+
options: [{ label: "許可しない" }, { label: "許可する" }],
|
|
1434
|
+
},
|
|
1435
|
+
],
|
|
1436
|
+
});
|
|
1437
|
+
return (answer.answers?.[0]?.id === id &&
|
|
1438
|
+
answer.answers[0].selected?.[0] === "許可する");
|
|
1439
|
+
},
|
|
1440
|
+
})
|
|
1441
|
+
: undefined;
|
|
1442
|
+
const planDisposer = mountPlanTransition({
|
|
1443
|
+
on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options),
|
|
1444
|
+
}, ctx.get("planMode", false));
|
|
914
1445
|
const observationMount = observation.install({
|
|
915
|
-
ctx,
|
|
916
|
-
|
|
1446
|
+
ctx,
|
|
1447
|
+
ennoMemory,
|
|
1448
|
+
evolutionConfig,
|
|
1449
|
+
memoryFinalizer,
|
|
1450
|
+
currentSession,
|
|
1451
|
+
currentForAgentEvent,
|
|
1452
|
+
answerReview,
|
|
1453
|
+
markModelUnavailable: (agent) => routing.markModelUnavailable(agent),
|
|
917
1454
|
recordManualChange: (sessionId, pending) => routing.recordManualChange(sessionId, pending),
|
|
918
|
-
modelAuto,
|
|
1455
|
+
modelAuto,
|
|
1456
|
+
root,
|
|
1457
|
+
autoReview,
|
|
1458
|
+
reviewBinding,
|
|
1459
|
+
sessionMirror,
|
|
1460
|
+
executionSupport,
|
|
919
1461
|
kickBoundary: (sessionId, agent) => {
|
|
920
1462
|
if (agent && isGenericNativeChild(agent))
|
|
921
1463
|
return;
|
|
@@ -925,93 +1467,166 @@ export function createDshHostAdapter(ctx, options = {}) {
|
|
|
925
1467
|
if (!nativeAgent || !isGenericNativeChild(nativeAgent))
|
|
926
1468
|
boundaryWorker.kick(sessionId, agent);
|
|
927
1469
|
},
|
|
928
|
-
stateForRun,
|
|
1470
|
+
stateForRun,
|
|
1471
|
+
objectRecord,
|
|
1472
|
+
isHumanMessage,
|
|
1473
|
+
eventContinuationId,
|
|
929
1474
|
});
|
|
930
1475
|
const lifecycle = createLifecycle({
|
|
931
|
-
awaitingClarification: agent => demand?.awaitingClarification(agent) ?? false,
|
|
932
|
-
runtime,
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
1476
|
+
awaitingClarification: (agent) => demand?.awaitingClarification(agent) ?? false,
|
|
1477
|
+
runtime,
|
|
1478
|
+
sessions,
|
|
1479
|
+
sessionMirror,
|
|
1480
|
+
memoryFinalizer,
|
|
1481
|
+
autoReview,
|
|
1482
|
+
answerReview,
|
|
1483
|
+
ennoController,
|
|
1484
|
+
ennoMemory,
|
|
1485
|
+
executionSupport,
|
|
1486
|
+
gate,
|
|
1487
|
+
turnState,
|
|
1488
|
+
getSelection: (runId) => selections.get(runId),
|
|
1489
|
+
currentSession,
|
|
1490
|
+
currentForAgentEvent,
|
|
1491
|
+
stateForRun,
|
|
1492
|
+
deliverCompletionReport,
|
|
1493
|
+
reviewBinding,
|
|
1494
|
+
evolutionConfig,
|
|
1495
|
+
clearToolRun: toolHostModule.clearRun,
|
|
1496
|
+
sessionEventSource,
|
|
1497
|
+
onRunClosed: (runId, status, sessionId, authority) => lifecycleMemory.completed(runId, status, sessionId, authority),
|
|
937
1498
|
});
|
|
938
|
-
const { runLifecycle, resolveIdleClose, resolveSessionRunId, resolveSessionClose } = lifecycle;
|
|
1499
|
+
const { runLifecycle, resolveIdleClose, resolveSessionRunId, resolveSessionClose, } = lifecycle;
|
|
939
1500
|
retireSupersededRun = lifecycle.retireSupersededRun;
|
|
940
1501
|
const agenticReplayConfig = AgenticReplayConfig.parse(options.agenticReplay ?? {});
|
|
941
|
-
const agenticReplay = !agenticReplayConfig.enabled
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
1502
|
+
const agenticReplay = !agenticReplayConfig.enabled
|
|
1503
|
+
? undefined
|
|
1504
|
+
: createDshAgenticReplayHost(ctx, agenticReplayConfig, runtime, {
|
|
1505
|
+
session: (id) => sessions?.get(id),
|
|
1506
|
+
agent: (id) => agents?.get(id),
|
|
1507
|
+
logicalRun: resolveSessionRunId,
|
|
1508
|
+
...(userQuestions ? { questions: userQuestions } : {}),
|
|
1509
|
+
interactive: (agent) => !delegation.isChild(agent) && !deepPlanning.executor.isChild(agent),
|
|
1510
|
+
recordingRun: (agent) => deepPlanning.executor.recordingRun(agent),
|
|
1511
|
+
recordingParent: (agent) => deepPlanning.executor.recordingParent(agent),
|
|
1512
|
+
});
|
|
948
1513
|
let disposePromise;
|
|
949
1514
|
if (agenticReplay)
|
|
950
1515
|
lifecycleMemory.connectAgenticReplay(agenticReplay);
|
|
951
|
-
const efficiencyHost = createEfficiencyHost({
|
|
952
|
-
|
|
1516
|
+
const efficiencyHost = createEfficiencyHost({
|
|
1517
|
+
ctx,
|
|
1518
|
+
memoryFinalizer,
|
|
1519
|
+
agents,
|
|
1520
|
+
sessions,
|
|
1521
|
+
delegation,
|
|
1522
|
+
deepPlanning,
|
|
1523
|
+
currentSession,
|
|
1524
|
+
});
|
|
1525
|
+
efficiencyHost.configure({
|
|
1526
|
+
observe: efficiencyConfig.observe,
|
|
1527
|
+
inputMode: finalizationConfig.inputMode,
|
|
1528
|
+
});
|
|
953
1529
|
// Register last so deferred preparation precedes the existing memory/completion pre-execute checks.
|
|
954
1530
|
if (demand)
|
|
955
1531
|
demand.mount(ctx, tools, systemPrompt);
|
|
956
1532
|
// Observe the bound identity before inner pre-execute policies can refuse a tool.
|
|
957
|
-
executionSupport.mountPreExecution({
|
|
1533
|
+
executionSupport.mountPreExecution({
|
|
1534
|
+
on: (name, listener, options) => onNativeServiceEvent(ctx, name, listener, options),
|
|
1535
|
+
});
|
|
958
1536
|
const host = {
|
|
959
1537
|
...(demand ? { onDemandIntake: demand } : {}),
|
|
960
1538
|
...(taskWorkflow ? { taskWorkflow } : {}),
|
|
961
1539
|
bypassNativeIntake: isGenericNativeChild,
|
|
962
|
-
modelAuto: {
|
|
1540
|
+
modelAuto: {
|
|
1541
|
+
coordinator: modelAuto,
|
|
1542
|
+
validSession: (agentId, sessionId) => {
|
|
963
1543
|
const currentAgent = agents?.get(agentId);
|
|
964
1544
|
const currentNativeSession = sessions?.get(sessionId);
|
|
965
1545
|
// Web sessions can belong to a workspace other than DSH's launch directory.
|
|
966
|
-
return Boolean(currentAgent &&
|
|
967
|
-
|
|
1546
|
+
return Boolean(currentAgent &&
|
|
1547
|
+
currentNativeSession &&
|
|
1548
|
+
currentAgent.session === currentNativeSession);
|
|
1549
|
+
},
|
|
1550
|
+
},
|
|
968
1551
|
...(diffReview ? { diffReview } : {}),
|
|
969
1552
|
decisions,
|
|
970
1553
|
semanticCompaction,
|
|
971
1554
|
deepPlanning,
|
|
972
|
-
get efficiency() {
|
|
1555
|
+
get efficiency() {
|
|
1556
|
+
return efficiencyHost.efficiency;
|
|
1557
|
+
},
|
|
973
1558
|
configureEfficiency: efficiencyHost.configure,
|
|
974
|
-
get skillPrompts() {
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
1559
|
+
get skillPrompts() {
|
|
1560
|
+
return skillPrompts;
|
|
1561
|
+
},
|
|
1562
|
+
configureSkillPrompts(prompts) {
|
|
1563
|
+
skillPrompts = prompts;
|
|
1564
|
+
},
|
|
1565
|
+
configureEnnoMemory: (config) => ennoMemory.configure(config),
|
|
1566
|
+
configureToolExposure: (config) => {
|
|
1567
|
+
toolExposureConfig = ToolExposureConfig.parse(config);
|
|
1568
|
+
},
|
|
978
1569
|
modelToolDefinitionsChanged: routing.modelToolDefinitionsChanged,
|
|
979
|
-
memoryReview: createMemoryReviewHost({
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1570
|
+
memoryReview: createMemoryReviewHost({
|
|
1571
|
+
runtime,
|
|
1572
|
+
autoReview,
|
|
1573
|
+
root,
|
|
1574
|
+
currentSession,
|
|
1575
|
+
objectRecord,
|
|
1576
|
+
memoryFinalizer,
|
|
1577
|
+
sessionMirror,
|
|
1578
|
+
reviewBinding,
|
|
1579
|
+
}),
|
|
1580
|
+
memoryIndexReasoning: {
|
|
1581
|
+
configure: (config) => memoryFinalizer.configureMemoryIndexReasoning(config),
|
|
1582
|
+
command: (sessionId, raw) => memoryFinalizer.indexCommand(sessionId, raw),
|
|
1583
|
+
},
|
|
1584
|
+
memoryEvolution: createEvolutionHost({
|
|
1585
|
+
runtime,
|
|
1586
|
+
memoryFinalizer,
|
|
1587
|
+
evolutionConfig,
|
|
1588
|
+
}),
|
|
1589
|
+
autoGlobalization: {
|
|
1590
|
+
configure(enabled) {
|
|
1591
|
+
memoryFinalizer.configureAutoGlobalization(enabled);
|
|
1592
|
+
},
|
|
1593
|
+
},
|
|
984
1594
|
...(agenticReplay === undefined ? {} : { agenticReplay }),
|
|
985
1595
|
...(skills === undefined ? {} : { skills: skills }),
|
|
986
1596
|
...(systemPrompt === undefined ? {} : { systemPrompt }),
|
|
987
1597
|
runtime,
|
|
988
|
-
runtimeOwner: options.runtime ?
|
|
1598
|
+
runtimeOwner: options.runtime ? "external" : "host",
|
|
989
1599
|
...(userQuestions === undefined ? {} : { userQuestions }),
|
|
990
1600
|
...(commands === undefined ? {} : { commands: commands }),
|
|
991
1601
|
ponytailModes: modes,
|
|
992
|
-
...(tools === undefined
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
1602
|
+
...(tools === undefined
|
|
1603
|
+
? {}
|
|
1604
|
+
: {
|
|
1605
|
+
tools: {
|
|
1606
|
+
register: tools.register.bind(tools),
|
|
1607
|
+
guard: tools.guard.bind(tools),
|
|
1608
|
+
},
|
|
1609
|
+
toolHost,
|
|
1610
|
+
toolPolicy: policy,
|
|
1611
|
+
}),
|
|
997
1612
|
...(tools === undefined ? {} : { intakeGate: gate, mapPreStep }),
|
|
998
1613
|
memoryFinalizer,
|
|
999
|
-
memoryFinalizerOwner:
|
|
1614
|
+
memoryFinalizerOwner: "host",
|
|
1000
1615
|
sessionMirror,
|
|
1001
|
-
sessionMirrorOwner:
|
|
1616
|
+
sessionMirrorOwner: "host",
|
|
1002
1617
|
sessionExport,
|
|
1003
1618
|
checkpointSessionMirror: (session) => sessionMirror.checkpointAfterNativeFlush(session),
|
|
1004
1619
|
resolveSessionRunId,
|
|
1005
1620
|
boundaryWorker,
|
|
1006
|
-
boundaryWorkerOwner:
|
|
1621
|
+
boundaryWorkerOwner: "host",
|
|
1007
1622
|
lifecycle: runLifecycle,
|
|
1008
|
-
lifecycleOwner:
|
|
1623
|
+
lifecycleOwner: "host",
|
|
1009
1624
|
resolveIdleClose,
|
|
1010
1625
|
resolveSessionClose,
|
|
1011
1626
|
};
|
|
1012
1627
|
return {
|
|
1013
1628
|
host,
|
|
1014
|
-
dispose: () => disposePromise ??= (async () => {
|
|
1629
|
+
dispose: () => (disposePromise ??= (async () => {
|
|
1015
1630
|
demand?.stop();
|
|
1016
1631
|
await ownedDisposer?.();
|
|
1017
1632
|
planDisposer();
|
|
@@ -1046,7 +1661,7 @@ export function createDshHostAdapter(ctx, options = {}) {
|
|
|
1046
1661
|
catch (error) {
|
|
1047
1662
|
failures.push(error);
|
|
1048
1663
|
}
|
|
1049
|
-
const pausedSessions = new Set(turnState.sessionIds().filter(id => executionSupport.paused(id)));
|
|
1664
|
+
const pausedSessions = new Set(turnState.sessionIds().filter((id) => executionSupport.paused(id)));
|
|
1050
1665
|
ennoMemory.close();
|
|
1051
1666
|
executionSupport.dispose();
|
|
1052
1667
|
try {
|
|
@@ -1091,7 +1706,7 @@ export function createDshHostAdapter(ctx, options = {}) {
|
|
|
1091
1706
|
catch (error) {
|
|
1092
1707
|
failures.push(error);
|
|
1093
1708
|
}
|
|
1094
|
-
failures.push(...await lifecycle.closeRemainingRuns(pausedSessions));
|
|
1709
|
+
failures.push(...(await lifecycle.closeRemainingRuns(pausedSessions)));
|
|
1095
1710
|
try {
|
|
1096
1711
|
await runLifecycle.dispose();
|
|
1097
1712
|
}
|
|
@@ -1102,7 +1717,9 @@ export function createDshHostAdapter(ctx, options = {}) {
|
|
|
1102
1717
|
try {
|
|
1103
1718
|
await lifecycleMemory.whenIdle();
|
|
1104
1719
|
}
|
|
1105
|
-
catch {
|
|
1720
|
+
catch {
|
|
1721
|
+
/* optional observations cannot veto shutdown */
|
|
1722
|
+
}
|
|
1106
1723
|
try {
|
|
1107
1724
|
observationMount.disposeIdle();
|
|
1108
1725
|
await autoReview.dispose();
|
|
@@ -1162,14 +1779,18 @@ export function createDshHostAdapter(ctx, options = {}) {
|
|
|
1162
1779
|
if (failures.length === 1)
|
|
1163
1780
|
throw failures[0];
|
|
1164
1781
|
if (failures.length > 1)
|
|
1165
|
-
throw new AggregateError(failures,
|
|
1166
|
-
})(),
|
|
1782
|
+
throw new AggregateError(failures, "kiokuko-dsh adapter disposal failed");
|
|
1783
|
+
})()),
|
|
1167
1784
|
};
|
|
1168
1785
|
}
|
|
1169
1786
|
function stateForRun(database, item) {
|
|
1170
1787
|
if (!item.prepared.ennoOduno.applicable)
|
|
1171
1788
|
return item.prepared.ennoOduno;
|
|
1172
|
-
return stateForSnapshot(readEnnoSnapshot(database, {
|
|
1789
|
+
return stateForSnapshot(readEnnoSnapshot(database, {
|
|
1790
|
+
runId: item.runId,
|
|
1791
|
+
workspace: item.workspace,
|
|
1792
|
+
orchestrationId: item.orchestrationId,
|
|
1793
|
+
}));
|
|
1173
1794
|
}
|
|
1174
1795
|
export { KIOKUKO_DSH_HOST_SERVICE };
|
|
1175
1796
|
//# sourceMappingURL=host-adapter.js.map
|