kiokuko-dsh 0.2.4 → 0.2.5
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/dsh/agenticreplay-event-mapper.d.ts +7 -0
- package/dist/dsh/agenticreplay-event-mapper.d.ts.map +1 -1
- package/dist/dsh/agenticreplay-event-mapper.js +52 -13
- package/dist/dsh/agenticreplay-event-mapper.js.map +1 -1
- package/dist/dsh/agenticreplay-hooks.d.ts.map +1 -1
- package/dist/dsh/agenticreplay-hooks.js +10 -1
- package/dist/dsh/agenticreplay-hooks.js.map +1 -1
- package/dist/dsh/agenticreplay-recorder.d.ts +5 -0
- package/dist/dsh/agenticreplay-recorder.d.ts.map +1 -1
- package/dist/dsh/agenticreplay-recorder.js +193 -20
- package/dist/dsh/agenticreplay-recorder.js.map +1 -1
- package/dist/dsh/answer-context.d.ts +8 -6
- package/dist/dsh/answer-context.d.ts.map +1 -1
- package/dist/dsh/answer-context.js +85 -21
- package/dist/dsh/answer-context.js.map +1 -1
- package/dist/dsh/coding-workflow/contracts.d.ts +5 -0
- package/dist/dsh/coding-workflow/contracts.d.ts.map +1 -1
- package/dist/dsh/coding-workflow/contracts.js +20 -3
- package/dist/dsh/coding-workflow/contracts.js.map +1 -1
- package/dist/dsh/coding-workflow/host.d.ts +4 -1
- package/dist/dsh/coding-workflow/host.d.ts.map +1 -1
- package/dist/dsh/coding-workflow/host.js +72 -44
- package/dist/dsh/coding-workflow/host.js.map +1 -1
- package/dist/dsh/coding-workflow/intent.d.ts +8 -0
- package/dist/dsh/coding-workflow/intent.d.ts.map +1 -1
- package/dist/dsh/coding-workflow/intent.js +33 -2
- package/dist/dsh/coding-workflow/intent.js.map +1 -1
- package/dist/dsh/coding-workflow/service.d.ts +214 -0
- package/dist/dsh/coding-workflow/service.d.ts.map +1 -1
- package/dist/dsh/coding-workflow/service.js +86 -6
- package/dist/dsh/coding-workflow/service.js.map +1 -1
- package/dist/dsh/coding-workflow/store.d.ts.map +1 -1
- package/dist/dsh/coding-workflow/store.js +10 -1
- package/dist/dsh/coding-workflow/store.js.map +1 -1
- package/dist/dsh/core/host.d.ts.map +1 -1
- package/dist/dsh/core/host.js +288 -48
- package/dist/dsh/core/host.js.map +1 -1
- package/dist/dsh/core/tasks.d.ts +7 -0
- package/dist/dsh/core/tasks.d.ts.map +1 -1
- package/dist/dsh/core/tasks.js +59 -8
- package/dist/dsh/core/tasks.js.map +1 -1
- package/dist/dsh/decisions/contracts.d.ts +3 -2
- package/dist/dsh/decisions/contracts.d.ts.map +1 -1
- package/dist/dsh/decisions/contracts.js +1 -1
- package/dist/dsh/decisions/contracts.js.map +1 -1
- package/dist/dsh/decisions/request-intent.d.ts +121 -0
- package/dist/dsh/decisions/request-intent.d.ts.map +1 -0
- package/dist/dsh/decisions/request-intent.js +260 -0
- package/dist/dsh/decisions/request-intent.js.map +1 -0
- package/dist/dsh/decisions/service.d.ts +5 -1
- package/dist/dsh/decisions/service.d.ts.map +1 -1
- package/dist/dsh/decisions/service.js +2 -1
- package/dist/dsh/decisions/service.js.map +1 -1
- package/dist/dsh/execution-support.d.ts +2 -0
- package/dist/dsh/execution-support.d.ts.map +1 -1
- package/dist/dsh/execution-support.js +36 -8
- package/dist/dsh/execution-support.js.map +1 -1
- package/dist/dsh/host-adapter/admission.d.ts +4 -1
- package/dist/dsh/host-adapter/admission.d.ts.map +1 -1
- package/dist/dsh/host-adapter/admission.js +294 -12
- package/dist/dsh/host-adapter/admission.js.map +1 -1
- package/dist/dsh/host-adapter/routing.d.ts +2 -1
- package/dist/dsh/host-adapter/routing.d.ts.map +1 -1
- package/dist/dsh/host-adapter/routing.js +32 -18
- package/dist/dsh/host-adapter/routing.js.map +1 -1
- package/dist/dsh/host-adapter/turn-state.d.ts +6 -0
- package/dist/dsh/host-adapter/turn-state.d.ts.map +1 -1
- package/dist/dsh/host-adapter/turn-state.js +19 -1
- package/dist/dsh/host-adapter/turn-state.js.map +1 -1
- package/dist/dsh/host-adapter.d.ts.map +1 -1
- package/dist/dsh/host-adapter.js +71 -8
- package/dist/dsh/host-adapter.js.map +1 -1
- package/dist/dsh/intake-clarification.d.ts +2 -2
- package/dist/dsh/intake-clarification.d.ts.map +1 -1
- package/dist/dsh/intake-clarification.js +13 -4
- package/dist/dsh/intake-clarification.js.map +1 -1
- package/dist/dsh/intake-gate.d.ts +5 -0
- package/dist/dsh/intake-gate.d.ts.map +1 -1
- package/dist/dsh/intake-gate.js +19 -5
- package/dist/dsh/intake-gate.js.map +1 -1
- package/dist/dsh/lisp/candidate.d.ts +1 -1
- package/dist/dsh/lisp/surface.d.ts +1 -1
- package/dist/dsh/memory-owner.d.ts +24 -0
- package/dist/dsh/memory-owner.d.ts.map +1 -0
- package/dist/dsh/memory-owner.js +35 -0
- package/dist/dsh/memory-owner.js.map +1 -0
- package/dist/dsh/memory-request-fence.d.ts +37 -0
- package/dist/dsh/memory-request-fence.d.ts.map +1 -0
- package/dist/dsh/memory-request-fence.js +48 -0
- package/dist/dsh/memory-request-fence.js.map +1 -0
- package/dist/dsh/message-sources.d.ts.map +1 -1
- package/dist/dsh/message-sources.js +2 -1
- package/dist/dsh/message-sources.js.map +1 -1
- package/dist/dsh/models/profiles.d.ts +23 -0
- package/dist/dsh/models/profiles.d.ts.map +1 -1
- package/dist/dsh/models/profiles.js +30 -1
- package/dist/dsh/models/profiles.js.map +1 -1
- package/dist/dsh/models/service.d.ts +9 -0
- package/dist/dsh/models/service.d.ts.map +1 -1
- package/dist/dsh/models/service.js +52 -13
- package/dist/dsh/models/service.js.map +1 -1
- package/dist/dsh/on-demand-intake.d.ts +71 -5
- package/dist/dsh/on-demand-intake.d.ts.map +1 -1
- package/dist/dsh/on-demand-intake.js +299 -70
- package/dist/dsh/on-demand-intake.js.map +1 -1
- package/dist/dsh/owned-execution.d.ts +3 -0
- package/dist/dsh/owned-execution.d.ts.map +1 -1
- package/dist/dsh/owned-execution.js +7 -0
- package/dist/dsh/owned-execution.js.map +1 -1
- package/dist/dsh/request-memory.d.ts +2 -0
- package/dist/dsh/request-memory.d.ts.map +1 -1
- package/dist/dsh/request-memory.js +33 -2
- package/dist/dsh/request-memory.js.map +1 -1
- package/dist/dsh/setup.d.ts +2 -2
- package/dist/dsh/setup.d.ts.map +1 -1
- package/dist/dsh/setup.js +37 -14
- package/dist/dsh/setup.js.map +1 -1
- package/dist/dsh/skill-prompts.json +1 -1
- package/dist/dsh/standard-skills.d.ts +2 -1
- package/dist/dsh/standard-skills.d.ts.map +1 -1
- package/dist/dsh/standard-skills.js +2 -1
- package/dist/dsh/standard-skills.js.map +1 -1
- package/dist/dsh/task-intake.d.ts +6 -0
- package/dist/dsh/task-intake.d.ts.map +1 -1
- package/dist/dsh/task-intake.js +7 -2
- package/dist/dsh/task-intake.js.map +1 -1
- 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/docs/coding-workflow.md +3 -1
- package/docs/dsh-plugin.md +28 -5
- package/docs/on-demand-intake.md +13 -7
- package/package.json +3 -2
- package/skills/japanese-translation-for-oss-models/SKILL.md +5 -3
|
@@ -3,6 +3,7 @@ import { bindMemoryApplication, memoryRetrievalStatus } from '../../memory/appli
|
|
|
3
3
|
import { createMemoryReuseRuntime } from '../memory-reuse.js';
|
|
4
4
|
import { dshTurnRequestId } from '../intake-profile-resolver.js';
|
|
5
5
|
import { classifyTaskForIntake, selectInstalledSkills } from '../decisions/workflows.js';
|
|
6
|
+
import { classifyRequestIntent, createRequestIntentContext, rebindRequestIntentDecision, requestIntentMessageRefs, requestIntentReferenceIds, requestIntentTaskType } from '../decisions/request-intent.js';
|
|
6
7
|
import { ANSWER_REVIEW_FORM, hasHumanInput } from '../answer-review/contracts.js';
|
|
7
8
|
import { refreshContinuedTaskContext } from '../task-intake.js';
|
|
8
9
|
import { saveSessionNotice } from '../plugin-records.js';
|
|
@@ -28,8 +29,12 @@ import { ENNO_APPLICABLE_TASK_TYPES } from '../../enno-oduno/types.js';
|
|
|
28
29
|
import { supersedeBoundaryJobsAtOrBeforeRevisionInTransaction, supersedeOutboxAtOrBeforeRevisionInTransaction } from '../turn-process.js';
|
|
29
30
|
import { unexecutedRunInput } from '../input-claim.js';
|
|
30
31
|
import { resetLoopGuardForUserInTransaction } from '../loop-guard.js';
|
|
31
|
-
import { codingContinuation } from '../coding-workflow/intent.js';
|
|
32
32
|
import { readCodingWorkflow } from '../coding-workflow/store.js';
|
|
33
|
+
import { markCodingScopeChange } from '../coding-workflow/service.js';
|
|
34
|
+
import { readExecutionFrame } from '../execution-frame.js';
|
|
35
|
+
import { assertMemoryOwner, createMemoryOwner, memoryOwnerKind } from '../memory-owner.js';
|
|
36
|
+
import { findSecret } from '../../memory/secrets.js';
|
|
37
|
+
import { executionClarification, isContinuationReference } from '../intake-clarification.js';
|
|
33
38
|
export function createAdmission({ native, skills, tools, userQuestions, sessions, agents, deepPlanning, modelCatalog, modelCompatibility, modelRoutes, now, runtime, decisions, answerReview, delegation, executionSupport, ennoMemory, memoryFinalizer, autoReview, sessionMirror, akinatorMemoryConfig, memoryRetrievalConfig, completionMode, turnState, getSelection, setSelection, refreshEnnoMemory, executionBinding, captureInitialInput, contextMessages, resolveIdleClose, retireSupersededRun, cancelBoundarySession, isSelectionBlocked, closeTurn, readStateForRun, capabilityCatalog, sessionEventSource, objectRecord, isHumanMessage, textFromMessages, pluginContinuationId, isLoopRecoveryMessage, }) {
|
|
34
39
|
const currentSession = turnState.currentSession;
|
|
35
40
|
const currentForAgentEvent = turnState.currentForAgentEvent;
|
|
@@ -45,6 +50,16 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
45
50
|
}).profileHints.taskType;
|
|
46
51
|
return incomingType !== null && !ENNO_APPLICABLE_TASK_TYPES.includes(incomingType);
|
|
47
52
|
}
|
|
53
|
+
function eventTurn(event) {
|
|
54
|
+
const data = typeof event.data === 'object' && event.data !== null && !Array.isArray(event.data)
|
|
55
|
+
? event.data : undefined;
|
|
56
|
+
return Number.isSafeInteger(data?.turn) ? data.turn : undefined;
|
|
57
|
+
}
|
|
58
|
+
function continuesCodingScope(event) {
|
|
59
|
+
const intent = event.requestIntent;
|
|
60
|
+
return !!intent && (intent.relation === 'same_scope_continuation' || intent.relation === 'scope_change')
|
|
61
|
+
&& intent.action !== 'answer' && intent.action !== 'unknown';
|
|
62
|
+
}
|
|
48
63
|
let prepareGeneration = 0;
|
|
49
64
|
const continuedTurns = new Map();
|
|
50
65
|
const resumedTurns = new Map();
|
|
@@ -83,7 +98,11 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
83
98
|
},
|
|
84
99
|
});
|
|
85
100
|
}
|
|
86
|
-
if (result.admitted && result.prepared.run.status === 'active'
|
|
101
|
+
if (result.admitted && event.requestIntent?.relation !== 'scope_change' && result.prepared.run.status === 'active'
|
|
102
|
+
&& result.prepared.memoryOwner?.kind === 'execution'
|
|
103
|
+
&& currentSession(event.sessionId)?.prepareGeneration === generation && !delegation.isChild(event.nativeAgent ?? {})) {
|
|
104
|
+
assertMemoryOwner(result.prepared.memoryOwner, { agentId: event.agent.id, sessionId: event.sessionId, turn: event.turn,
|
|
105
|
+
requestDigest: canonicalContentHash(event.task), runId: result.prepared.run.runId }, 'execution');
|
|
87
106
|
await runtime.withDatabase(db => {
|
|
88
107
|
if (currentSession(event.sessionId)?.prepareGeneration !== generation)
|
|
89
108
|
return;
|
|
@@ -100,6 +119,18 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
100
119
|
catch { /* Unsupported or unavailable review source must not veto a native request. */ }
|
|
101
120
|
}
|
|
102
121
|
};
|
|
122
|
+
async function hasPendingExecutionDiscussion(sessionId, cwd) {
|
|
123
|
+
return runtime.withDatabase(async (db) => {
|
|
124
|
+
const project = await resolveProjectWorkspaceReadOnly(db, cwd, { allowDirectory: true });
|
|
125
|
+
if (!project)
|
|
126
|
+
return false;
|
|
127
|
+
const activeRuns = db.prepare(`SELECT run_id FROM ledger_runs
|
|
128
|
+
WHERE workspace=? AND dsh_session_id=? AND status='active'`).all(project.workspace, sessionId);
|
|
129
|
+
if (activeRuns.length !== 1)
|
|
130
|
+
return false;
|
|
131
|
+
return readExecutionSelection(db, activeRuns[0].run_id)?.value.discussion !== undefined;
|
|
132
|
+
});
|
|
133
|
+
}
|
|
103
134
|
const refreshContinuedWorkLease = async (item, expected) => {
|
|
104
135
|
const expectedWorkUnitId = expected.nextAction === 'execute_work_unit'
|
|
105
136
|
? expected.directive?.workUnit?.id
|
|
@@ -200,7 +231,8 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
200
231
|
// context deliveries that finish out of order.
|
|
201
232
|
const generation = ++prepareGeneration;
|
|
202
233
|
const prior = currentForAgentEvent(event.agent.id, event.sessionId, undefined, event.nativeSession, event.nativeAgent);
|
|
203
|
-
if (prior && prior.turn === event.turn && !prior.closed && prior.task !== event.task && hasHumanInput(event.nativeMessages ?? [])
|
|
234
|
+
if (prior && prior.turn === event.turn && !prior.closed && prior.task !== event.task && hasHumanInput(event.nativeMessages ?? [])
|
|
235
|
+
&& event.requestIntent?.relation === 'new') {
|
|
204
236
|
const choice = getSelection(prior.runId);
|
|
205
237
|
if (choice?.value.status === 'ready')
|
|
206
238
|
this.supersededChoices.set(`${event.sessionId}\u0000${event.turn}`, choice);
|
|
@@ -223,11 +255,33 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
223
255
|
profileHints: event.profileHints ?? null,
|
|
224
256
|
...(event.deferTaskTypeInference ? { deferTaskTypeInference: true } : {}),
|
|
225
257
|
evidence: event.evidence ?? null,
|
|
258
|
+
requestIntent: event.requestIntent ?? null,
|
|
259
|
+
requestIntentContextDigest: event.requestIntentContext ? canonicalContentHash(event.requestIntentContext) : null,
|
|
260
|
+
memoryOwner: event.memoryOwner ?? null,
|
|
226
261
|
skillDiscoveryMode: event.skillDiscoveryMode ?? null,
|
|
227
262
|
catalogDigest: event.capabilities.digest,
|
|
228
263
|
});
|
|
264
|
+
const unresolvedBinding = canonicalContentHash({ sessionId: event.sessionId, agentId: event.agent.id,
|
|
265
|
+
turn: event.turn, sourceStartSeq: event.sourceStartSeq ?? null, task: event.task, cwd: event.cwd,
|
|
266
|
+
evidence: event.evidence ?? null, context: event.requestIntentContext ?? null, catalogDigest: event.capabilities.digest,
|
|
267
|
+
skillDiscoveryMode: event.skillDiscoveryMode ?? null });
|
|
229
268
|
const cached = continuedTurns.get(cacheKey) ?? resumedTurns.get(cacheKey);
|
|
230
269
|
if (cached !== undefined) {
|
|
270
|
+
if (cached.fingerprint !== fingerprint && 'unresolvedBinding' in cached && cached.unresolvedBinding === unresolvedBinding
|
|
271
|
+
&& cached.nativeAgent === event.nativeAgent && cached.nativeSession === event.nativeSession
|
|
272
|
+
&& event.requestIntentContext && event.requestIntent
|
|
273
|
+
&& continuesCodingScope(event) && rebindRequestIntentDecision(event.requestIntent, event.requestIntentContext)) {
|
|
274
|
+
// A host-owned confirmation may resume before optional interpretation.
|
|
275
|
+
// Resolve that exact unresolved input once; changing resolved input still conflicts.
|
|
276
|
+
const kind = memoryOwnerKind(event.requestIntent, event.profileHints?.taskType);
|
|
277
|
+
const prepared = { ...cached.result.prepared,
|
|
278
|
+
memoryOwner: createMemoryOwner(kind, { agentId: event.agent.id, sessionId: event.sessionId, turn: event.turn,
|
|
279
|
+
requestDigest: canonicalContentHash(event.task), runId: cached.result.prepared.run.runId }) };
|
|
280
|
+
const resolved = await this.choose(event, { ...cached.result, prepared });
|
|
281
|
+
continuedTurns.set(cacheKey, { fingerprint, result: resolved, ...(event.nativeAgent ? { nativeAgent: event.nativeAgent } : {}), ...(event.nativeSession ? { nativeSession: event.nativeSession } : {}) });
|
|
282
|
+
await bindAndRecord(event, resolved, generation);
|
|
283
|
+
return resolved;
|
|
284
|
+
}
|
|
231
285
|
if (cached.fingerprint !== fingerprint
|
|
232
286
|
|| cached.nativeAgent !== event.nativeAgent
|
|
233
287
|
|| cached.nativeSession !== event.nativeSession) {
|
|
@@ -247,12 +301,36 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
247
301
|
if (!hasHumanInput(reviewMessages) && reviewMessages.some(message => objectRecord(objectRecord(message)?.source)?.form === ANSWER_REVIEW_FORM)) {
|
|
248
302
|
if (!previous || !event.nativeAgent || !await answerReview.accept(event.nativeAgent, reviewMessages, event.turn, event.capabilities.digest))
|
|
249
303
|
throw new Error('Unbound answer review continuation');
|
|
250
|
-
|
|
304
|
+
// Only the coordinator's exact reserved message may carry this owner
|
|
305
|
+
// into another native turn; the request and run remain unchanged.
|
|
306
|
+
const owner = previous.prepared.memoryOwner;
|
|
307
|
+
const prepared = owner ? { ...previous.prepared,
|
|
308
|
+
memoryOwner: createMemoryOwner(owner.kind, { ...owner, turn: event.turn }) } : previous.prepared;
|
|
309
|
+
const continued = { admitted: true, prepared, catalog: previous.catalog };
|
|
251
310
|
continuedTurns.set(cacheKey, { fingerprint, result: continued, nativeAgent: event.nativeAgent, ...(event.nativeSession === undefined ? {} : { nativeSession: event.nativeSession }) });
|
|
252
311
|
await bindAndRecord(event, continued, generation);
|
|
253
312
|
return continued;
|
|
254
313
|
}
|
|
255
314
|
if (previous !== undefined && previous.turn === event.turn && !previous.closed) {
|
|
315
|
+
if (previous.task !== event.task && hasHumanInput(event.nativeMessages ?? [])) {
|
|
316
|
+
if (!continuesCodingScope(event))
|
|
317
|
+
return { admitted: false, prepared: previous.prepared, catalog: event.capabilities };
|
|
318
|
+
const workflow = await runtime.withDatabase(db => readCodingWorkflow(db, previous.runId));
|
|
319
|
+
const scopeChanging = !!workflow && event.requestIntent?.relation === 'scope_change';
|
|
320
|
+
if (scopeChanging && event.requestIntent) {
|
|
321
|
+
const evidenceRefs = event.requestIntentContext ? requestIntentReferenceIds(event.requestIntentContext) : [];
|
|
322
|
+
await runtime.withDatabase(db => markCodingScopeChange(db, { runId: previous.runId, sessionId: previous.sessionId, repositoryRoot: previous.repositoryRoot }, `request-intent:${event.sessionId}:${event.turn}:${event.requestIntent.evidence.requestDigest}`, event.requestIntent.evidence.requestDigest, evidenceRefs));
|
|
323
|
+
}
|
|
324
|
+
const ownerKind = event.memoryOwner ?? memoryOwnerKind(event.requestIntent, event.profileHints?.taskType ?? previous.prepared.intake.profile.taskType);
|
|
325
|
+
const prepared = { ...previous.prepared,
|
|
326
|
+
...(scopeChanging ? { context: null, memoryPolicy: { memoryReasoningRequired: false, contextWithheld: false, withheldReason: null, deliveryEmpty: true } } : {}),
|
|
327
|
+
memoryOwner: createMemoryOwner(ownerKind, { agentId: event.agent.id, sessionId: event.sessionId, turn: event.turn,
|
|
328
|
+
requestDigest: canonicalContentHash(event.task), runId: previous.runId }) };
|
|
329
|
+
const selected = await this.choose(event, { admitted: !event.signal.aborted, prepared, catalog: event.capabilities });
|
|
330
|
+
if (selected.admitted)
|
|
331
|
+
await bindAndRecord(event, selected, generation);
|
|
332
|
+
return selected;
|
|
333
|
+
}
|
|
256
334
|
// Model routing prepares before native pre-step. Reuse that exact
|
|
257
335
|
// intake result instead of treating its newly active run as a cold
|
|
258
336
|
// resume (which deliberately starts without historical context).
|
|
@@ -304,7 +382,7 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
304
382
|
// Child results and other generated turns continue the admitted Goal.
|
|
305
383
|
// Only a new human request can replace it without an explicit continuation.
|
|
306
384
|
const resumeCoding = coding && !['completed', 'cancelled', 'superseded'].includes(coding.state)
|
|
307
|
-
&& (!hasHumanInput(event.nativeMessages ?? []) ||
|
|
385
|
+
&& (!hasHumanInput(event.nativeMessages ?? []) || continuesCodingScope(event));
|
|
308
386
|
const continuePrevious = resumeCoding || selection && (selection.status !== 'ready' || selection.mode === 'normal' && previous.failed)
|
|
309
387
|
? true : previousWasChat
|
|
310
388
|
? event.profileHints?.taskType === 'chat'
|
|
@@ -315,6 +393,12 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
315
393
|
&& (previousState.nextAction !== 'complete' || executionSupport.paused(previous.sessionId));
|
|
316
394
|
if (continuePrevious) {
|
|
317
395
|
this.assertCatalog(previous.catalog, event.capabilities);
|
|
396
|
+
const intent = event.requestIntent;
|
|
397
|
+
const scopeChanging = !!coding && intent?.relation === 'scope_change' && intent.action !== 'answer' && intent.action !== 'unknown';
|
|
398
|
+
if (scopeChanging && intent) {
|
|
399
|
+
const evidenceRefs = event.requestIntentContext ? requestIntentReferenceIds(event.requestIntentContext) : [];
|
|
400
|
+
await runtime.withDatabase(db => markCodingScopeChange(db, { runId: previous.runId, sessionId: previous.sessionId, repositoryRoot: previous.repositoryRoot }, `request-intent:${event.sessionId}:${event.turn}:${intent.evidence.requestDigest}`, intent.evidence.requestDigest, evidenceRefs));
|
|
401
|
+
}
|
|
318
402
|
const refreshedWork = await refreshContinuedWorkLease(previous, previousState);
|
|
319
403
|
if (refreshedWork !== undefined) {
|
|
320
404
|
previous.prepared = { ...previous.prepared, ennoOduno: refreshedWork.state };
|
|
@@ -322,7 +406,10 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
322
406
|
turnState.applyPolicy(previous.runId, next);
|
|
323
407
|
}
|
|
324
408
|
let continuedMemory;
|
|
325
|
-
if (
|
|
409
|
+
if (scopeChanging)
|
|
410
|
+
continuedMemory = { context: null,
|
|
411
|
+
memoryPolicy: { memoryReasoningRequired: false, contextWithheld: false, withheldReason: null, deliveryEmpty: true } };
|
|
412
|
+
else if (!ennoMemory.ownsActiveRefresh(previous.prepared.ennoOduno)) {
|
|
326
413
|
const captured = previous.prepared, started = performance.now();
|
|
327
414
|
const inboxIdentity = () => canonicalContentHash([...(event.nativeAgent?.inbox?.nextStep ?? []), ...(event.nativeAgent?.inbox?.nextTurn ?? [])].filter(isHumanMessage));
|
|
328
415
|
const pendingInput = inboxIdentity();
|
|
@@ -349,10 +436,15 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
349
436
|
/* Optional retrieval failure retains the previous delivery, whose state is validated before injection. */
|
|
350
437
|
}
|
|
351
438
|
}
|
|
352
|
-
const
|
|
439
|
+
const ownerKind = event.memoryOwner ?? memoryOwnerKind(intent, event.profileHints?.taskType ?? previous.prepared.intake.profile.taskType);
|
|
440
|
+
const continuedPrepared = { ...previous.prepared, ...(continuedMemory ?? {}),
|
|
441
|
+
memoryOwner: createMemoryOwner(ownerKind, { agentId: event.agent.id, sessionId: event.sessionId, turn: event.turn,
|
|
442
|
+
requestDigest: canonicalContentHash(event.task), runId: previous.runId }) };
|
|
443
|
+
const continued = await this.choose(event, { admitted: !event.signal.aborted, prepared: continuedPrepared, catalog: event.capabilities });
|
|
353
444
|
if (continued.admitted) {
|
|
354
445
|
continuedTurns.set(cacheKey, {
|
|
355
446
|
fingerprint,
|
|
447
|
+
...(event.requestIntent?.relation === 'unknown' || event.requestIntent?.action === 'unknown' ? { unresolvedBinding } : {}),
|
|
356
448
|
result: continued,
|
|
357
449
|
...(event.profileHints === undefined ? {} : { profileHints: event.profileHints }),
|
|
358
450
|
...(event.nativeAgent === undefined ? {} : { nativeAgent: event.nativeAgent }),
|
|
@@ -538,6 +630,49 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
538
630
|
}
|
|
539
631
|
}
|
|
540
632
|
const gate = new CapturingGate(runtime, userQuestions === undefined ? undefined : createDshIntakeAnswerer(userQuestions), (context) => capabilityCatalog(skills, tools, context), true, akinatorMemoryConfig, decisions, completionMode, memoryRetrievalConfig);
|
|
633
|
+
const refreshMemoryOwner = async (item, signal) => {
|
|
634
|
+
const prepared = item.prepared;
|
|
635
|
+
const owner = prepared.memoryOwner;
|
|
636
|
+
if (!owner || owner.kind !== 'execution')
|
|
637
|
+
throw new KiokukoError('CONFLICT', 'memory_owner_unavailable');
|
|
638
|
+
const ownerIdentity = { agentId: item.agentId, sessionId: item.sessionId, turn: item.turn,
|
|
639
|
+
requestDigest: canonicalContentHash(item.task), runId: item.runId };
|
|
640
|
+
assertMemoryOwner(owner, ownerIdentity, 'execution');
|
|
641
|
+
const started = performance.now();
|
|
642
|
+
const refreshed = await runtime.withDatabase(async (database, embedding) => {
|
|
643
|
+
const assertCurrent = () => {
|
|
644
|
+
signal.throwIfAborted();
|
|
645
|
+
if (currentSession(item.sessionId) !== item || item.prepared !== prepared || item.closed || item.failed
|
|
646
|
+
|| item.nativeAgent === undefined || agents?.get(item.nativeAgent.id) !== item.nativeAgent
|
|
647
|
+
|| item.nativeSession === undefined || sessions?.get(item.sessionId) !== item.nativeSession) {
|
|
648
|
+
throw new KiokukoError('CONFLICT', 'memory_owner_changed');
|
|
649
|
+
}
|
|
650
|
+
assertMemoryOwner(owner, ownerIdentity, 'execution');
|
|
651
|
+
if (performance.now() - started > 1000 + (decisions.memoryReuse.mode === 'auto' ? decisions.memoryReuse.budgetMs : 0)) {
|
|
652
|
+
throw new KiokukoError('CONFLICT', 'memory_owner_rebuild_deadline');
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
if (embedding.mode === 'required')
|
|
656
|
+
throw new KiokukoError('SERVICE_UNAVAILABLE', 'required_embedding_unavailable');
|
|
657
|
+
const capabilities = [...item.catalog.skills, ...item.catalog.tools];
|
|
658
|
+
const memoryReuse = await createMemoryReuseRuntime(decisions, `run:${item.runId}`, signal);
|
|
659
|
+
return refreshContinuedTaskContext({ database, memoryReuse, memoryRetrieval: memoryRetrievalConfig, prepared,
|
|
660
|
+
task: item.memoryInput ?? item.task, capabilities, assertCurrent,
|
|
661
|
+
validateCapabilities: async () => {
|
|
662
|
+
const fresh = await capabilityCatalog(skills, tools, { agent: { id: item.agentId },
|
|
663
|
+
...(item.nativeAgent ? { nativeAgent: item.nativeAgent } : {}), cwd: item.cwd, signal });
|
|
664
|
+
gate.assertCatalog(item.catalog, fresh);
|
|
665
|
+
assertCurrent();
|
|
666
|
+
} });
|
|
667
|
+
});
|
|
668
|
+
signal.throwIfAborted();
|
|
669
|
+
if (currentSession(item.sessionId) !== item || item.prepared !== prepared)
|
|
670
|
+
throw new KiokukoError('CONFLICT', 'memory_owner_changed');
|
|
671
|
+
item.prepared = { ...prepared, ...refreshed };
|
|
672
|
+
await runtime.withDatabase(database => bindMemoryApplication(database, {
|
|
673
|
+
runId: item.runId, workspace: item.workspace, sessionId: item.sessionId, repositoryRoot: item.repositoryRoot,
|
|
674
|
+
}, item.prepared.intake.profile, item.prepared.context, memoryRetrievalStatus(database, item.workspace, item.prepared.context, item.prepared.memoryPolicy.contextWithheld)));
|
|
675
|
+
};
|
|
541
676
|
resumeExistingRun = async (event) => runtime.withDatabase(async (database) => {
|
|
542
677
|
const project = await resolveProjectWorkspaceReadOnly(database, event.cwd, { allowDirectory: true });
|
|
543
678
|
if (project === undefined)
|
|
@@ -554,7 +689,7 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
554
689
|
OR (ec.run_id IS NULL AND (json_extract(es.state_json, '$.paused') = 1 OR xs.run_id IS NOT NULL)))
|
|
555
690
|
AND (cw.run_id IS NULL OR (? = 1 AND json_extract(cw.snapshot_json, '$.state') NOT IN ('completed', 'cancelled', 'superseded')))
|
|
556
691
|
ORDER BY lr.created_at, lr.run_id LIMIT 2
|
|
557
|
-
`).all(project.workspace, event.sessionId, project.repositoryRoot,
|
|
692
|
+
`).all(project.workspace, event.sessionId, project.repositoryRoot, continuesCodingScope(event) ? 1 : 0);
|
|
558
693
|
if (candidates.length === 0)
|
|
559
694
|
return undefined;
|
|
560
695
|
if (candidates.length !== 1)
|
|
@@ -601,6 +736,10 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
601
736
|
});
|
|
602
737
|
const canonicalCwd = realpathSync(event.cwd);
|
|
603
738
|
const prepared = {
|
|
739
|
+
memoryOwner: createMemoryOwner(event.memoryOwner ?? memoryOwnerKind(event.requestIntent, intake.profile.taskType), {
|
|
740
|
+
agentId: event.agent.id, sessionId: event.sessionId, turn: event.turn,
|
|
741
|
+
requestDigest: canonicalContentHash(event.task), runId,
|
|
742
|
+
}),
|
|
604
743
|
project,
|
|
605
744
|
executionContext: {
|
|
606
745
|
canonicalCwd,
|
|
@@ -631,7 +770,97 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
631
770
|
turnState.stageLease(runId, decision.executionLease);
|
|
632
771
|
return { admitted: !event.signal.aborted, prepared, catalog: event.capabilities };
|
|
633
772
|
});
|
|
634
|
-
const
|
|
773
|
+
const requestIntentContextFor = async (input, sessionId, nativeSession, previous, task) => {
|
|
774
|
+
const human = input.messages.filter(isHumanMessage);
|
|
775
|
+
if (!human.length || !task.trim())
|
|
776
|
+
return undefined;
|
|
777
|
+
const sessionHeader = objectRecord(objectRecord(nativeSession)?.header);
|
|
778
|
+
const cwd = typeof sessionHeader?.cwd === 'string' ? sessionHeader.cwd : undefined;
|
|
779
|
+
if (!cwd)
|
|
780
|
+
return undefined;
|
|
781
|
+
const messageRefs = requestIntentMessageRefs(human, task);
|
|
782
|
+
let activeGoal;
|
|
783
|
+
let proposals = [];
|
|
784
|
+
const sameOwner = previous && previous.sessionId === sessionId && previous.nativeAgent === input.agent && previous.nativeSession === nativeSession;
|
|
785
|
+
const persistedRun = sameOwner ? undefined : await runtime.withDatabase(async (database) => {
|
|
786
|
+
const project = await resolveProjectWorkspaceReadOnly(database, cwd, { allowDirectory: true });
|
|
787
|
+
if (!project)
|
|
788
|
+
return undefined;
|
|
789
|
+
const candidates = database.prepare(`SELECT lr.run_id AS runId,
|
|
790
|
+
ec.orchestration_session_id AS orchestrationId
|
|
791
|
+
FROM ledger_runs AS lr
|
|
792
|
+
LEFT JOIN dsh_coding_workflows AS cw ON cw.run_id = lr.run_id
|
|
793
|
+
LEFT JOIN enno_contracts AS ec ON ec.run_id = lr.run_id
|
|
794
|
+
WHERE lr.workspace = ? AND lr.dsh_session_id = ? AND lr.status = 'active'
|
|
795
|
+
AND ((json_extract(cw.snapshot_json, '$.repositoryRoot') = ?
|
|
796
|
+
AND json_extract(cw.snapshot_json, '$.sessionId') = ?
|
|
797
|
+
AND json_extract(cw.snapshot_json, '$.state') NOT IN ('completed', 'cancelled', 'superseded'))
|
|
798
|
+
OR (ec.repository_root = ? AND ec.status NOT IN ('completed', 'cancelled', 'blocked')))
|
|
799
|
+
ORDER BY lr.created_at, lr.run_id LIMIT 2`)
|
|
800
|
+
.all(project.workspace, sessionId, project.repositoryRoot, sessionId, project.repositoryRoot);
|
|
801
|
+
if (candidates.length > 1)
|
|
802
|
+
throw new KiokukoError('CONFLICT', 'Multiple active tasks match this session; refusing to guess');
|
|
803
|
+
return candidates[0] === undefined ? undefined : { ...candidates[0], workspace: project.workspace };
|
|
804
|
+
});
|
|
805
|
+
const runId = sameOwner ? previous.runId : persistedRun?.runId;
|
|
806
|
+
if (runId) {
|
|
807
|
+
const state = await runtime.withDatabase(database => {
|
|
808
|
+
const workflow = readCodingWorkflow(database, runId);
|
|
809
|
+
const definition = workflow?.definition;
|
|
810
|
+
const frame = readExecutionFrame(database, runId);
|
|
811
|
+
const enno = !workflow && persistedRun?.runId === runId && persistedRun.orchestrationId !== null
|
|
812
|
+
? readEnnoSnapshot(database, { runId, workspace: persistedRun.workspace, orchestrationId: persistedRun.orchestrationId })
|
|
813
|
+
: undefined;
|
|
814
|
+
const active = definition ? {
|
|
815
|
+
runId, workflowRevision: workflow.revision, goalId: definition.goal.goalId,
|
|
816
|
+
goalRevision: definition.goal.revision, scopeRevision: workflow.scopeVersion, ideal: definition.goal.ideal,
|
|
817
|
+
target: definition.goal.target, outOfScope: [...definition.goal.outOfScope], constraints: [...definition.goal.constraints],
|
|
818
|
+
} : workflow ? { runId, workflowRevision: workflow.revision, scopeRevision: workflow.scopeVersion, outOfScope: [], constraints: [] }
|
|
819
|
+
: enno ? {
|
|
820
|
+
runId, workflowRevision: enno.revision, goalRevision: enno.revision, scopeRevision: enno.revision,
|
|
821
|
+
ideal: enno.ideal?.objective ?? enno.handoff.objective,
|
|
822
|
+
...(enno.handoff.target === null ? {} : { target: enno.handoff.target }),
|
|
823
|
+
outOfScope: [...enno.contract.exclusions], constraints: [...enno.handoff.constraints],
|
|
824
|
+
}
|
|
825
|
+
: sameOwner && previous.prepared.ennoOduno.applicable ? {
|
|
826
|
+
runId,
|
|
827
|
+
...(previous.prepared.ennoOduno.contractRevision === null ? {} : {
|
|
828
|
+
workflowRevision: previous.prepared.ennoOduno.contractRevision,
|
|
829
|
+
goalRevision: previous.prepared.ennoOduno.contractRevision,
|
|
830
|
+
scopeRevision: previous.prepared.ennoOduno.contractRevision,
|
|
831
|
+
}),
|
|
832
|
+
...(previous.prepared.ennoOduno.directive?.objective ? { ideal: previous.prepared.ennoOduno.directive.objective } : {}),
|
|
833
|
+
...(previous.prepared.intake.profile.target ? { target: previous.prepared.intake.profile.target } : {}),
|
|
834
|
+
outOfScope: [],
|
|
835
|
+
constraints: previous.prepared.intake.profile.constraints ? [previous.prepared.intake.profile.constraints] : [],
|
|
836
|
+
} : undefined;
|
|
837
|
+
const candidates = (frame?.conditions ?? []).filter(condition => condition.approval === 'proposed').slice(0, 7)
|
|
838
|
+
.map(condition => ({ id: `condition-${canonicalContentHash([runId, frame.revision, condition.field, condition.text, condition.planRevision])}`,
|
|
839
|
+
revision: condition.planRevision ?? frame.revision, digest: canonicalContentHash(condition),
|
|
840
|
+
text: `${condition.field}: ${condition.text}`, field: condition.field }));
|
|
841
|
+
return { active, candidates };
|
|
842
|
+
});
|
|
843
|
+
activeGoal = state.active;
|
|
844
|
+
proposals = state.candidates;
|
|
845
|
+
}
|
|
846
|
+
const eventSource = sessionEventSource(nativeSession);
|
|
847
|
+
const precedingAssistant = [...eventSource.snapshotEvents()].reverse().find(event => event.type === 'assistant/message'
|
|
848
|
+
&& (eventTurn(event) ?? Number.MAX_SAFE_INTEGER) < input.turn);
|
|
849
|
+
if (precedingAssistant && proposals.length < 8) {
|
|
850
|
+
const data = objectRecord(precedingAssistant.data);
|
|
851
|
+
const message = objectRecord(data?.message) ?? data;
|
|
852
|
+
const content = Array.isArray(message?.content) ? message.content : [];
|
|
853
|
+
const text = content.filter((block) => objectRecord(block)?.type === 'text')
|
|
854
|
+
.map((block) => objectRecord(block)?.text).filter((value) => typeof value === 'string').join('\n').trim();
|
|
855
|
+
const messageId = typeof message?.id === 'string' ? message.id : `seq:${precedingAssistant.seq}`;
|
|
856
|
+
if (message?.role === 'assistant' && text && text.length <= 8192 && findSecret(text) === undefined) {
|
|
857
|
+
proposals = [...proposals, { id: `assistant-${canonicalContentHash([sessionId, messageId])}`, revision: null,
|
|
858
|
+
digest: canonicalContentHash(text), text }];
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
return createRequestIntentContext({ task, messageRefs, ...(activeGoal ? { activeGoal } : {}), proposals: proposals.slice(0, 8) });
|
|
862
|
+
};
|
|
863
|
+
const mapPreStep = async (payload, advisoryType, suppliedIntent, interpretationOnly = false) => {
|
|
635
864
|
const nativeSession = payload.agent.session;
|
|
636
865
|
const registered = nativeSession === undefined && payload.agent.sessionId === undefined
|
|
637
866
|
? sessions?.get(payload.agent.id)
|
|
@@ -668,7 +897,8 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
668
897
|
// model, while any supplied step-local user text still replaces this
|
|
669
898
|
// fallback and is recorded as the continuation instruction.
|
|
670
899
|
const reviewing = !hasHumanInput(payload.messages) && payload.messages.some(message => objectRecord(objectRecord(message)?.source)?.form === ANSWER_REVIEW_FORM);
|
|
671
|
-
const
|
|
900
|
+
const intentTask = hasHumanInput(payload.messages) ? textFromMessages(payload.messages.filter(isHumanMessage), '') : '';
|
|
901
|
+
const task = intentTask.trim() ? intentTask : bound?.task ?? (reviewing && previous ? previous.task : textFromMessages(payload.messages, previous?.task));
|
|
672
902
|
let profile = (() => {
|
|
673
903
|
if (bound !== undefined)
|
|
674
904
|
return bound.profileHints;
|
|
@@ -683,20 +913,62 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
683
913
|
return inferred === null || previousType === 'chat' && inferred === 'chat' ? { taskType: previousType } : undefined;
|
|
684
914
|
})();
|
|
685
915
|
let deferTaskTypeInference = bound?.deferTaskTypeInference ?? (reviewing ? previous?.deferTaskTypeInference : false) ?? false;
|
|
686
|
-
|
|
916
|
+
let requestIntentContext;
|
|
917
|
+
let requestIntent;
|
|
918
|
+
const activeRecord = bound ?? previous;
|
|
919
|
+
if (!reviewing && hasHumanInput(payload.messages) && !delegation.isChild(payload.agent) && intentTask.trim()) {
|
|
920
|
+
requestIntentContext = await requestIntentContextFor(payload, sessionId, boundSession, activeRecord, intentTask);
|
|
687
921
|
const requestId = dshTurnRequestId({ dshSessionId: sessionId, turn: payload.turn });
|
|
922
|
+
const establishedConversation = profile?.taskType === 'chat' && !requestIntentContext?.activeGoal;
|
|
923
|
+
if (requestIntentContext && !establishedConversation) {
|
|
924
|
+
requestIntent = await classifyRequestIntent(decisions, requestId, requestIntentContext, payload.signal);
|
|
925
|
+
}
|
|
688
926
|
const configuration = await decisions?.bind(requestId, payload.signal);
|
|
689
927
|
// This profile is inherited from a previous turn, not a current user choice.
|
|
690
928
|
// Let Laya assess new work, but retain the user's chat choice for an
|
|
691
929
|
// ambiguous continuation instead of asking the same classification again.
|
|
692
930
|
const explicit = advisoryType ?? (configuration?.provider === 'laya-coreml' && profile?.taskType !== 'chat' ? undefined : profile?.taskType);
|
|
693
|
-
const classification = await classifyTaskForIntake(decisions, requestId,
|
|
931
|
+
const classification = await classifyTaskForIntake(decisions, requestId, intentTask, explicit, payload.signal);
|
|
694
932
|
deferTaskTypeInference = classification.deferInference;
|
|
695
933
|
if (classification.taskType)
|
|
696
934
|
profile = { ...profile, taskType: classification.taskType };
|
|
697
935
|
else if (deferTaskTypeInference && profile)
|
|
698
936
|
profile = { ...profile, taskType: null };
|
|
699
937
|
}
|
|
938
|
+
else if (activeRecord) {
|
|
939
|
+
requestIntent = activeRecord.requestIntent;
|
|
940
|
+
requestIntentContext = activeRecord.requestIntentContext;
|
|
941
|
+
}
|
|
942
|
+
if (suppliedIntent) {
|
|
943
|
+
if (!requestIntentContext)
|
|
944
|
+
throw new KiokukoError('CONFLICT', 'request_intent_context_unavailable');
|
|
945
|
+
const rebound = rebindRequestIntentDecision(suppliedIntent, requestIntentContext);
|
|
946
|
+
if (!rebound)
|
|
947
|
+
throw new KiokukoError('CONFLICT', 'request_intent_evidence_stale');
|
|
948
|
+
if (requestIntent?.source === 'decision-provider' && requestIntent.relation !== 'unknown' && requestIntent.action !== 'unknown'
|
|
949
|
+
&& (requestIntent.relation !== rebound.relation || requestIntent.action !== rebound.action)) {
|
|
950
|
+
throw new KiokukoError('CONFLICT', 'request_intent_provider_conflict');
|
|
951
|
+
}
|
|
952
|
+
requestIntent = requestIntent?.source === 'decision-provider' && requestIntent.relation !== 'unknown' && requestIntent.action !== 'unknown'
|
|
953
|
+
? { ...requestIntent, evidence: rebound.evidence } : rebound;
|
|
954
|
+
}
|
|
955
|
+
const pendingDiscussion = isContinuationReference(intentTask)
|
|
956
|
+
&& await hasPendingExecutionDiscussion(sessionId, cwd);
|
|
957
|
+
const establishedConversation = profile?.taskType === 'chat' && !requestIntentContext?.activeGoal;
|
|
958
|
+
if (!interpretationOnly && intentTask.trim() && !pendingDiscussion && !establishedConversation) {
|
|
959
|
+
const clarification = executionClarification(intentTask, requestIntent, requestIntentContext);
|
|
960
|
+
if (clarification)
|
|
961
|
+
throw new KiokukoError('VALIDATION_ERROR', clarification);
|
|
962
|
+
}
|
|
963
|
+
const legacyTaskType = advisoryType !== undefined && advisoryType !== 'chat'
|
|
964
|
+
&& !requestIntentContext?.activeGoal && (requestIntentContext?.proposals.length ?? 0) === 0;
|
|
965
|
+
if (requestIntent?.source === 'unresolved' && legacyTaskType)
|
|
966
|
+
requestIntent = undefined;
|
|
967
|
+
if (requestIntent?.source !== 'unresolved') {
|
|
968
|
+
const intentType = requestIntentTaskType(requestIntent, profile?.taskType ?? advisoryType);
|
|
969
|
+
if (intentType !== undefined)
|
|
970
|
+
profile = { ...profile, taskType: intentType };
|
|
971
|
+
}
|
|
700
972
|
// Coding Lisp choice belongs to the admitted Goal, after all criteria exist.
|
|
701
973
|
// Task intake never starts Lisp or interrupts an explanation with a mode question.
|
|
702
974
|
const catalog = await capabilityCatalog(skills, tools, {
|
|
@@ -715,6 +987,9 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
715
987
|
cwd,
|
|
716
988
|
...(profile === undefined ? {} : { profileHints: profile }),
|
|
717
989
|
...(deferTaskTypeInference ? { deferTaskTypeInference: true } : {}),
|
|
990
|
+
...(requestIntent === undefined ? {} : { requestIntent }),
|
|
991
|
+
...(requestIntentContext === undefined ? {} : { requestIntentContext }),
|
|
992
|
+
memoryOwner: memoryOwnerKind(requestIntent, profile?.taskType),
|
|
718
993
|
capabilities: catalog,
|
|
719
994
|
signal: payload.signal,
|
|
720
995
|
};
|
|
@@ -722,6 +997,13 @@ export function createAdmission({ native, skills, tools, userQuestions, sessions
|
|
|
722
997
|
return {
|
|
723
998
|
gate,
|
|
724
999
|
mapPreStep,
|
|
1000
|
+
interpret: async (payload) => {
|
|
1001
|
+
const event = await mapPreStep(payload, undefined, undefined, true);
|
|
1002
|
+
if (!event.requestIntentContext || !event.requestIntent)
|
|
1003
|
+
return undefined;
|
|
1004
|
+
return { context: event.requestIntentContext, decision: event.requestIntent };
|
|
1005
|
+
},
|
|
1006
|
+
refreshMemoryOwner,
|
|
725
1007
|
clear: () => { continuedTurns.clear(); resumedTurns.clear(); },
|
|
726
1008
|
};
|
|
727
1009
|
}
|