@dsh-enhanced/assistant-delivery 0.1.47 → 0.1.49
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/README.md +36 -18
- package/lib/agent-runtime.d.ts +17 -1
- package/lib/agent-runtime.d.ts.map +1 -1
- package/lib/agent-runtime.js +52 -39
- package/lib/agent-runtime.js.map +1 -1
- package/lib/feedback-command.d.ts +2 -0
- package/lib/feedback-command.d.ts.map +1 -1
- package/lib/feedback-command.js +15 -0
- package/lib/feedback-command.js.map +1 -1
- package/lib/foreground-observation.d.ts +13 -0
- package/lib/foreground-observation.d.ts.map +1 -1
- package/lib/foreground-observation.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/native-web-owner.js +3 -3
- package/lib/native-web-owner.js.map +1 -1
- package/lib/operator-snapshot.d.ts +1 -2
- package/lib/operator-snapshot.d.ts.map +1 -1
- package/lib/operator-snapshot.js +8 -3
- package/lib/operator-snapshot.js.map +1 -1
- package/lib/service.d.ts +54 -2
- package/lib/service.d.ts.map +1 -1
- package/lib/service.js +350 -26
- package/lib/service.js.map +1 -1
- package/lib/session-lease-runtime.js +1 -1
- package/lib/session-lease-runtime.js.map +1 -1
- package/lib/sqlite.d.ts +1 -1
- package/lib/sqlite.d.ts.map +1 -1
- package/lib/sqlite.js +113 -2
- package/lib/sqlite.js.map +1 -1
- package/lib/store.d.ts +105 -11
- package/lib/store.d.ts.map +1 -1
- package/lib/store.js +490 -13
- package/lib/store.js.map +1 -1
- package/lib/types.d.ts +70 -0
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +52 -47
package/lib/service.js
CHANGED
|
@@ -4,16 +4,16 @@ import { createHash, randomUUID } from 'node:crypto';
|
|
|
4
4
|
import { Context, Service } from '@deepseek-ai/cordis';
|
|
5
5
|
import Schema from '@deepseek-ai/schemastery';
|
|
6
6
|
import { acceptanceCanonicalJson, goalDefinitionSituation } from '@dsh-enhanced/task-acceptance-contract';
|
|
7
|
-
import { approvalReviewerOf,
|
|
7
|
+
import { approvalReviewerOf, } from '@dsh-enhanced/assistant-policy';
|
|
8
8
|
// Cross-package wire literal, kept locally so this bundle can load without the
|
|
9
9
|
// optional assistant-evaluation peer installed (a value import would defeat
|
|
10
10
|
// peerDependenciesMeta.optional at module link time). Must stay identical to
|
|
11
11
|
// TRUSTED_EVALUATION_PRODUCER_PROTOCOL in assistant-evaluation.
|
|
12
12
|
const TRUSTED_EVALUATION_PRODUCER_PROTOCOL = 'assistant-evaluation/trusted-producer/v1';
|
|
13
|
-
import { ASSISTANT_GROWTH_CONTRACT_VERSION, growthObjectDigest, validateResolvedWorkflowAutomationTemplate, validateWorkflowAutomationTemplate, validateWorkflowScope, validateWorkflowTraceProjectionReceipt, workflowArgumentShapeDigest, } from '@dsh-enhanced/assistant-growth-contract';
|
|
13
|
+
import { ASSISTANT_GROWTH_CONTRACT_VERSION, growthObjectDigest, isSourceOwnerContinuation, validateResolvedWorkflowAutomationTemplate, validateWorkflowAutomationTemplate, validateWorkflowScope, validateWorkflowTraceProjectionReceipt, workflowArgumentShapeDigest, } from '@dsh-enhanced/assistant-growth-contract';
|
|
14
14
|
import { DeliveryAdapterRegistry, DeliveryCoordinator, InboundCoordinator, } from './coordinator.js';
|
|
15
15
|
import { DeliveryStore, DeliveryStoreError, } from './store.js';
|
|
16
|
-
import { DshDeliveryRuntime } from './agent-runtime.js';
|
|
16
|
+
import { DshDeliveryRuntime, redactOwnerLearningReply } from './agent-runtime.js';
|
|
17
17
|
import { DeliverySessionLeases } from './session-lease-runtime.js';
|
|
18
18
|
import { NativeWebOwner } from './native-web-owner.js';
|
|
19
19
|
import { validateOwnerGoalOutcomeFeedbackLocator, validateOwnerGoalOutcomeFeedbackProof, } from './goal-wake-types.js';
|
|
@@ -24,7 +24,7 @@ import { bindingMatchesOwnerRoute, canonicalBackgroundSourceId as canonicalHostB
|
|
|
24
24
|
import { isExactDeliveryCommand, parseDeliveryCommand } from './session-commands.js';
|
|
25
25
|
import { deliveryT1PreferenceKeys, deliveryT1PreferenceValues } from './learning-command.js';
|
|
26
26
|
import { assertReplyReplayAllowed, blockAgentRepliesForReplay as createReplyReplayBlock, } from './reply-replay.js';
|
|
27
|
-
import { feedbackSignalInput, parseFeedbackCommand, classifyNaturalPreferenceDirective, observedResponseLanguage, } from './feedback-command.js';
|
|
27
|
+
import { feedbackSignalInput, parseFeedbackCommand, parseNaturalObjectiveFeedback, classifyNaturalPreferenceDirective, observedResponseLanguage, } from './feedback-command.js';
|
|
28
28
|
import { DELIVERY_PREFERENCE_PROJECTION_PROTOCOL, TRUSTED_DELIVERY_PRESENTATION_PRODUCER_PROTOCOL, } from './types.js';
|
|
29
29
|
const trustedDeliveryPreferenceProducers = new WeakSet();
|
|
30
30
|
const deliveryPreferenceProducerProbe = Symbol('assistant-delivery.preference-producer-probe');
|
|
@@ -491,7 +491,7 @@ function exactToolApprovalCall(events, openTurn, callId, toolName) {
|
|
|
491
491
|
callId, event.data.name, event.data.arguments],
|
|
492
492
|
});
|
|
493
493
|
}
|
|
494
|
-
if (event.type === 'tool/
|
|
494
|
+
if (event.type === 'tool/ptc-dispatch-start' && String(event.data.subCallId) === callId) {
|
|
495
495
|
const rootCallId = String(event.data.rootCallId);
|
|
496
496
|
const parentCallId = String(event.data.parentCallId);
|
|
497
497
|
const argumentsJson = serializeCodeDispatchArguments(event.data.arguments);
|
|
@@ -503,14 +503,14 @@ function exactToolApprovalCall(events, openTurn, callId, toolName) {
|
|
|
503
503
|
seq: event.seq,
|
|
504
504
|
name: event.data.name,
|
|
505
505
|
arguments: argumentsJson,
|
|
506
|
-
hashIdentity: ['tool/
|
|
506
|
+
hashIdentity: ['tool/ptc-dispatch-start', event.seq, rootCallId, parentCallId,
|
|
507
507
|
callId, event.data.name, argumentsJson],
|
|
508
508
|
});
|
|
509
509
|
}
|
|
510
510
|
if (event.type === 'tool/result'
|
|
511
511
|
&& String(event.data.message.source.callId) === callId)
|
|
512
512
|
settled = true;
|
|
513
|
-
if (event.type === 'tool/
|
|
513
|
+
if (event.type === 'tool/ptc-dispatch'
|
|
514
514
|
&& String(event.data.subCallId) === callId)
|
|
515
515
|
settled = true;
|
|
516
516
|
}
|
|
@@ -560,6 +560,7 @@ export class AssistantDeliveryService extends Service {
|
|
|
560
560
|
modelSelectionFlight;
|
|
561
561
|
presentationFlight;
|
|
562
562
|
workflowTraceFlight;
|
|
563
|
+
naturalObjectiveFlight;
|
|
563
564
|
preferenceProjectionFlight;
|
|
564
565
|
inboundAdmissionRecoveryFlight;
|
|
565
566
|
inboundAdmissionRecoveryAfterSequence = 0;
|
|
@@ -696,6 +697,7 @@ export class AssistantDeliveryService extends Service {
|
|
|
696
697
|
dispatchPreferenceFeedback: events => this.dispatchPreferenceFeedback(events),
|
|
697
698
|
replyCompletedPreferenceTurn: (agent, binding, envelope, reply) => this.replyCompletedPreferenceTurn(agent, binding, envelope, reply),
|
|
698
699
|
dispatchObjectiveFeedback: (binding, envelope, objectiveStatus) => this.dispatchObjectiveFeedback(binding, envelope, objectiveStatus),
|
|
700
|
+
dispatchNaturalObjectiveFeedback: (binding, envelope) => this.dispatchNaturalObjectiveFeedback(binding, envelope),
|
|
699
701
|
dispatchWorkflowCommand: (binding, envelope, command) => this.dispatchWorkflowCommand(binding, envelope, command),
|
|
700
702
|
dispatchLearningCommand: (binding, envelope, action, preferenceKey) => this.dispatchLearningCommand(binding, envelope, action, preferenceKey),
|
|
701
703
|
authorizePermissionReply: (binding, envelope) => this.authorizePermissionReply(binding, envelope),
|
|
@@ -728,7 +730,8 @@ export class AssistantDeliveryService extends Service {
|
|
|
728
730
|
// A plain approval/request listener can be starved by an earlier remote
|
|
729
731
|
// waterfall (notably a Web-enabled Host with a headless Lark conversation).
|
|
730
732
|
ctx.inject(['approval', 'assistantPolicy'], approvalCtx => approvalCtx.effect(() => {
|
|
731
|
-
if (typeof approvalCtx.assistantPolicy.registerHumanApprovalAnswerer !== 'function'
|
|
733
|
+
if (typeof approvalCtx.assistantPolicy.registerHumanApprovalAnswerer !== 'function'
|
|
734
|
+
|| typeof approvalCtx.assistantPolicy.isAutoReviewEscalation !== 'function') {
|
|
732
735
|
throw new Error('assistant-delivery: upgrade assistant-policy with Delivery; human approval routing is unavailable');
|
|
733
736
|
}
|
|
734
737
|
return approvalCtx.assistantPolicy.registerHumanApprovalAnswerer((request, next) => this.requestToolApproval(approvalCtx, request, next));
|
|
@@ -1843,6 +1846,83 @@ export class AssistantDeliveryService extends Service {
|
|
|
1843
1846
|
runtime.ctx.effect(() => () => access.dispose(), 'assistant-delivery.native-web-runtime');
|
|
1844
1847
|
return access;
|
|
1845
1848
|
};
|
|
1849
|
+
/** Host-only proof of a single live native tool call in the exact claimed owner Inbox. */
|
|
1850
|
+
inspectOwnerForegroundToolCall(input) {
|
|
1851
|
+
if (!input || typeof input !== 'object'
|
|
1852
|
+
|| typeof input.authorityId !== 'string' || input.authorityId.length === 0
|
|
1853
|
+
|| typeof input.callId !== 'string' || input.callId.length === 0
|
|
1854
|
+
|| typeof input.toolName !== 'string' || input.toolName.length === 0
|
|
1855
|
+
|| typeof input.argumentsJson !== 'string'
|
|
1856
|
+
|| Buffer.byteLength(input.authorityId) > toolApprovalIdentityBytes
|
|
1857
|
+
|| Buffer.byteLength(input.callId) > toolApprovalIdentityBytes
|
|
1858
|
+
|| Buffer.byteLength(input.toolName) > toolApprovalIdentityBytes
|
|
1859
|
+
|| Buffer.byteLength(input.argumentsJson) > toolApprovalArgumentBytes)
|
|
1860
|
+
return undefined;
|
|
1861
|
+
const route = this.validateOwnerAgentForRoute(input.agent, input.authorityId);
|
|
1862
|
+
if (route === undefined)
|
|
1863
|
+
return undefined;
|
|
1864
|
+
const turn = this.currentPreferenceTurn(input.agent);
|
|
1865
|
+
if (turn === undefined || turn.principalId !== route.principalId
|
|
1866
|
+
|| turn.principalLineage.principalRecordId !== route.principalRecordId
|
|
1867
|
+
|| turn.principalLineage.principalVersion !== route.principalVersion
|
|
1868
|
+
|| turn.scope.workspace !== route.workspace || turn.scope.preset !== route.agentPreset
|
|
1869
|
+
|| turn.bindingVersion !== route.bindingVersion
|
|
1870
|
+
|| turn.sessionId !== String(input.agent.session.id))
|
|
1871
|
+
return undefined;
|
|
1872
|
+
const task = this.deliveryStore.inspectPendingForegroundToolTask({
|
|
1873
|
+
inboxId: turn.sourceInboxId, sessionId: turn.sessionId, scope: turn.scope,
|
|
1874
|
+
owner: turn.principalLineage,
|
|
1875
|
+
binding: { id: turn.bindingId, version: turn.bindingVersion, generation: route.generation },
|
|
1876
|
+
});
|
|
1877
|
+
if (task === undefined)
|
|
1878
|
+
return undefined;
|
|
1879
|
+
const events = input.agent.session.snapshotEvents();
|
|
1880
|
+
const openTurn = events.findLast(event => event.type === 'turn/start' || event.type === 'turn/end');
|
|
1881
|
+
if (openTurn?.type !== 'turn/start' || openTurn.data.turn !== turn.turn)
|
|
1882
|
+
return undefined;
|
|
1883
|
+
const nativeCalls = events.filter((event) => event.type === 'tool/call' && event.seq > openTurn.seq
|
|
1884
|
+
&& event.data.turn === turn.turn && String(event.data.callId) === input.callId);
|
|
1885
|
+
const unresolved = nativeCalls.filter(call => !events.some(event => event.type === 'tool/result'
|
|
1886
|
+
&& event.seq > call.seq && String(event.data.message.source.callId) === String(call.data.callId)));
|
|
1887
|
+
if (unresolved.length !== 1)
|
|
1888
|
+
return undefined;
|
|
1889
|
+
const call = unresolved[0];
|
|
1890
|
+
const currentStep = events.findLast(event => (event.type === 'step/start' || event.type === 'step/end')
|
|
1891
|
+
&& event.data.turn === turn.turn);
|
|
1892
|
+
if (String(call.data.callId) !== input.callId || call.data.name !== input.toolName
|
|
1893
|
+
|| !Number.isSafeInteger(call.seq) || !Number.isSafeInteger(call.data.step)
|
|
1894
|
+
|| typeof call.data.arguments !== 'string'
|
|
1895
|
+
|| Buffer.byteLength(call.data.arguments) > toolApprovalArgumentBytes
|
|
1896
|
+
|| events.some(event => event !== call && ((event.type === 'tool/call'
|
|
1897
|
+
&& String(event.data.callId) === input.callId)
|
|
1898
|
+
|| (event.type === 'tool/ptc-dispatch-start' && String(event.data.subCallId) === input.callId)))
|
|
1899
|
+
|| currentStep?.type !== 'step/start' || currentStep.seq <= openTurn.seq
|
|
1900
|
+
|| currentStep.seq >= call.seq || currentStep.data.step !== call.data.step
|
|
1901
|
+
|| events.filter(event => event.type === 'step/start' && event.data.turn === turn.turn
|
|
1902
|
+
&& event.data.step === call.data.step).length !== 1)
|
|
1903
|
+
return undefined;
|
|
1904
|
+
let normalizedArguments;
|
|
1905
|
+
try {
|
|
1906
|
+
const parsed = JSON.parse(call.data.arguments);
|
|
1907
|
+
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
1908
|
+
return undefined;
|
|
1909
|
+
normalizedArguments = JSON.stringify(parsed);
|
|
1910
|
+
}
|
|
1911
|
+
catch {
|
|
1912
|
+
return undefined;
|
|
1913
|
+
}
|
|
1914
|
+
const argumentsDigest = createHash('sha256').update(normalizedArguments).digest('hex');
|
|
1915
|
+
if (argumentsDigest !== createHash('sha256').update(input.argumentsJson).digest('hex'))
|
|
1916
|
+
return undefined;
|
|
1917
|
+
const eventDigest = createHash('sha256').update(JSON.stringify(['tool/call', call.seq,
|
|
1918
|
+
call.data.turn, call.data.step, input.callId, input.toolName, call.data.arguments])).digest('hex');
|
|
1919
|
+
if (this.deliveryStore.inspectPendingForegroundToolTask({ inboxId: task.inboxId,
|
|
1920
|
+
sessionId: task.sessionId, scope: task.scope, owner: task.owner, binding: task.binding }) === undefined)
|
|
1921
|
+
return undefined;
|
|
1922
|
+
return Object.freeze({ protocol: 'assistant-delivery/foreground-tool-call/v1', task,
|
|
1923
|
+
turn: turn.turn, call: Object.freeze({ id: input.callId, toolName: input.toolName,
|
|
1924
|
+
eventSeq: call.seq, eventDigest, argumentsDigest }) });
|
|
1925
|
+
}
|
|
1846
1926
|
currentPreferenceTurn(agent) {
|
|
1847
1927
|
this.assertActive();
|
|
1848
1928
|
const attestation = this.preferenceTurns.get(agent);
|
|
@@ -1973,6 +2053,7 @@ export class AssistantDeliveryService extends Service {
|
|
|
1973
2053
|
}
|
|
1974
2054
|
const token = Symbol('assistant-delivery.trusted-evaluation');
|
|
1975
2055
|
this.evaluationSink = Object.freeze({ token, registration });
|
|
2056
|
+
void this.drainNaturalObjectiveIntents();
|
|
1976
2057
|
let active = true;
|
|
1977
2058
|
return () => {
|
|
1978
2059
|
if (!active)
|
|
@@ -2437,13 +2518,14 @@ export class AssistantDeliveryService extends Service {
|
|
|
2437
2518
|
context: { initiator: 'external' },
|
|
2438
2519
|
}).effect === 'allow';
|
|
2439
2520
|
}
|
|
2440
|
-
isOwnerFeedbackController(binding, envelope) {
|
|
2521
|
+
isOwnerFeedbackController(binding, envelope, allowProcessedNatural = false) {
|
|
2441
2522
|
if (!this.isInboundAuthorized(binding, envelope))
|
|
2442
2523
|
return false;
|
|
2443
2524
|
const principal = this.deliveryStore.getPrincipal(binding.principal);
|
|
2444
2525
|
const inbox = this.deliveryStore.getInboxByProviderEvent(envelope.channel, envelope.account, envelope.eventId);
|
|
2445
2526
|
if (principal?.status !== 'active' || principal.role !== 'owner'
|
|
2446
|
-
|| inbox?.status !== 'claimed'
|
|
2527
|
+
|| (inbox?.status !== 'claimed' && !(allowProcessedNatural && (inbox?.status === 'processed' || inbox?.status === 'dead_letter')
|
|
2528
|
+
&& inbox.envelope.kind === 'text' && this.deliveryStore.getNaturalObjectiveIntent(inbox.id)?.envelopeHash === inbox.envelopeHash))
|
|
2447
2529
|
|| inbox.bindingId !== binding.id
|
|
2448
2530
|
|| JSON.stringify(inbox.envelope) !== JSON.stringify(envelope)) {
|
|
2449
2531
|
return false;
|
|
@@ -2828,17 +2910,112 @@ export class AssistantDeliveryService extends Service {
|
|
|
2828
2910
|
* Evolution re-proves the immutable production run; the later Inbox is a
|
|
2829
2911
|
* separate evidence reference, never copied as prose.
|
|
2830
2912
|
*/
|
|
2913
|
+
async dispatchNaturalObjectiveFeedback(binding, envelope) {
|
|
2914
|
+
const selection = envelope.kind === 'text' && (envelope.attachments?.length ?? 0) === 0
|
|
2915
|
+
? parseNaturalObjectiveFeedback(envelope.text) : undefined;
|
|
2916
|
+
if (selection === undefined || !this.isOwnerFeedbackController(binding, envelope))
|
|
2917
|
+
return;
|
|
2918
|
+
const replyTarget = envelope.metadata?.replyToProviderMessageId;
|
|
2919
|
+
if (typeof replyTarget !== 'string')
|
|
2920
|
+
return;
|
|
2921
|
+
const inbox = this.deliveryStore.getInboxByProviderEvent(envelope.channel, envelope.account, envelope.eventId);
|
|
2922
|
+
const target = this.deliveryStore.getOutboxByProviderMessage(envelope.channel, envelope.account, replyTarget);
|
|
2923
|
+
const sourceEventId = target?.intent.replyToEventId;
|
|
2924
|
+
const source = sourceEventId === undefined ? undefined
|
|
2925
|
+
: this.deliveryStore.getInboxByProviderEvent(envelope.channel, envelope.account, sourceEventId);
|
|
2926
|
+
const lineage = this.ownerLineageForBinding(binding);
|
|
2927
|
+
if (inbox === undefined || target === undefined || source === undefined || lineage === undefined)
|
|
2928
|
+
return;
|
|
2929
|
+
if (!this.deliveryStore.isVerifiedForegroundObjectiveTarget(binding, source.id, target.id))
|
|
2930
|
+
return;
|
|
2931
|
+
const scope = { workspace: binding.workspace, preset: binding.agentPreset };
|
|
2932
|
+
const execution = this.deliveryStore.inspectForegroundExecutionForOwner({ inboxId: source.id,
|
|
2933
|
+
scope, owner: lineage, bindingId: binding.id, bindingVersion: binding.version,
|
|
2934
|
+
bindingGeneration: binding.generation })
|
|
2935
|
+
?? this.deliveryStore.inspectForegroundAcceptedExecutionForOwner({ inboxId: source.id,
|
|
2936
|
+
scope, owner: lineage, bindingId: binding.id });
|
|
2937
|
+
if (execution?.status !== 'succeeded' || !execution.quiescent)
|
|
2938
|
+
return;
|
|
2939
|
+
try {
|
|
2940
|
+
this.deliveryStore.prepareNaturalObjectiveIntent({ binding, feedbackInboxId: inbox.id,
|
|
2941
|
+
sourceInboxId: source.id, sourceOutboxId: target.id, selection });
|
|
2942
|
+
}
|
|
2943
|
+
catch (error) {
|
|
2944
|
+
if (error instanceof DeliveryStoreError)
|
|
2945
|
+
return;
|
|
2946
|
+
throw error;
|
|
2947
|
+
}
|
|
2948
|
+
void this.drainNaturalObjectiveIntents().catch(() => { });
|
|
2949
|
+
}
|
|
2950
|
+
drainNaturalObjectiveIntents() {
|
|
2951
|
+
if (this.naturalObjectiveFlight !== undefined)
|
|
2952
|
+
return this.naturalObjectiveFlight;
|
|
2953
|
+
const flight = this.runNaturalObjectiveIntents()
|
|
2954
|
+
.finally(() => { if (this.naturalObjectiveFlight === flight)
|
|
2955
|
+
this.naturalObjectiveFlight = undefined; });
|
|
2956
|
+
this.naturalObjectiveFlight = flight;
|
|
2957
|
+
return flight;
|
|
2958
|
+
}
|
|
2959
|
+
async runNaturalObjectiveIntents() {
|
|
2960
|
+
let afterAdmissionSequence = 0;
|
|
2961
|
+
while (true) {
|
|
2962
|
+
const page = this.deliveryStore.listPendingNaturalObjectiveIntents(100, afterAdmissionSequence);
|
|
2963
|
+
if (page.length === 0)
|
|
2964
|
+
return;
|
|
2965
|
+
for (const intent of page) {
|
|
2966
|
+
afterAdmissionSequence = intent.admissionSequence;
|
|
2967
|
+
if (!this.active || this.evaluationSink === undefined)
|
|
2968
|
+
return;
|
|
2969
|
+
if (this.evaluationSink.registration.ownerRevisionProtocol !== 'owner-objective-revision/v2'
|
|
2970
|
+
|| typeof this.evaluationSink.registration.inspect !== 'function')
|
|
2971
|
+
return;
|
|
2972
|
+
const inbox = this.deliveryStore.getInbox(intent.inboxId);
|
|
2973
|
+
const binding = this.deliveryStore.getBinding(intent.bindingId);
|
|
2974
|
+
if (inbox === undefined || binding === undefined)
|
|
2975
|
+
continue;
|
|
2976
|
+
let frozen = intent;
|
|
2977
|
+
if (frozen.status === 'awaiting-evaluation') {
|
|
2978
|
+
const inspected = await this.dispatchObjectiveFeedback(binding, inbox.envelope, { kind: 'objective-status' });
|
|
2979
|
+
if (inspected === 'invalid-target' || inspected === 'conflict') {
|
|
2980
|
+
this.deliveryStore.settleNaturalObjectiveIntent(intent.inboxId, 'conflict');
|
|
2981
|
+
continue;
|
|
2982
|
+
}
|
|
2983
|
+
if (inspected === 'unavailable' || inspected === 'unknown')
|
|
2984
|
+
continue;
|
|
2985
|
+
const current = typeof inspected === 'object' ? inspected : undefined;
|
|
2986
|
+
frozen = this.deliveryStore.freezeNaturalObjectiveIntent(intent.inboxId, current) ?? intent;
|
|
2987
|
+
if (frozen.status === 'awaiting-evaluation')
|
|
2988
|
+
continue;
|
|
2989
|
+
}
|
|
2990
|
+
if (frozen.status !== 'frozen' || frozen.command === undefined)
|
|
2991
|
+
continue;
|
|
2992
|
+
const result = await this.dispatchObjectiveFeedback(binding, inbox.envelope, frozen.command);
|
|
2993
|
+
if (typeof result === 'object') {
|
|
2994
|
+
this.deliveryStore.settleNaturalObjectiveIntent(intent.inboxId, 'projected', result);
|
|
2995
|
+
}
|
|
2996
|
+
else if (result === 'conflict' || result === 'invalid-target') {
|
|
2997
|
+
this.deliveryStore.settleNaturalObjectiveIntent(intent.inboxId, 'conflict');
|
|
2998
|
+
}
|
|
2999
|
+
else if (result === 'unavailable' || result === 'unknown')
|
|
3000
|
+
continue;
|
|
3001
|
+
}
|
|
3002
|
+
if (page.length < 100)
|
|
3003
|
+
return;
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
2831
3006
|
async dispatchObjectiveFeedback(binding, envelope, command) {
|
|
2832
3007
|
const parsed = typeof command === 'string' ? { kind: 'objective', objectiveStatus: command } : command;
|
|
2833
3008
|
const objectiveStatus = parsed.kind === 'objective-status' ? 'achieved' : parsed.objectiveStatus;
|
|
2834
3009
|
const replyTarget = envelope.metadata?.replyToProviderMessageId;
|
|
2835
3010
|
if (typeof replyTarget !== 'string')
|
|
2836
3011
|
return 'invalid-target';
|
|
2837
|
-
if (!this.isOwnerFeedbackController(binding, envelope))
|
|
2838
|
-
return 'invalid-target';
|
|
2839
3012
|
const inbox = this.deliveryStore.getInboxByProviderEvent(envelope.channel, envelope.account, envelope.eventId);
|
|
3013
|
+
const naturalIntent = inbox === undefined ? undefined : this.deliveryStore.getNaturalObjectiveIntent(inbox.id);
|
|
3014
|
+
if (!this.isOwnerFeedbackController(binding, envelope, naturalIntent !== undefined))
|
|
3015
|
+
return 'invalid-target';
|
|
2840
3016
|
const target = this.deliveryStore.getOutboxByProviderMessage(envelope.channel, envelope.account, replyTarget);
|
|
2841
|
-
if (inbox?.status !== 'claimed'
|
|
3017
|
+
if ((inbox?.status !== 'claimed' && !(naturalIntent !== undefined
|
|
3018
|
+
&& (inbox?.status === 'processed' || inbox?.status === 'dead_letter'))) || inbox.bindingId !== binding.id
|
|
2842
3019
|
|| target === undefined || target.providerMessageId !== replyTarget
|
|
2843
3020
|
|| target.intent.bindingId !== binding.id
|
|
2844
3021
|
|| JSON.stringify(target.intent.target.conversation) !== JSON.stringify(binding.conversation)
|
|
@@ -2846,9 +3023,22 @@ export class AssistantDeliveryService extends Service {
|
|
|
2846
3023
|
return 'invalid-target';
|
|
2847
3024
|
}
|
|
2848
3025
|
const hostCommand = parseDeliveryCommand(inbox.envelope);
|
|
2849
|
-
|
|
2850
|
-
|
|
3026
|
+
const typedMatches = hostCommand?.name === 'feedback'
|
|
3027
|
+
&& JSON.stringify(parseFeedbackCommand(hostCommand.rawInput)) === JSON.stringify(parsed);
|
|
3028
|
+
const naturalMatches = naturalIntent !== undefined && inbox.envelope.kind === 'text'
|
|
3029
|
+
&& naturalIntent.envelopeHash === inbox.envelopeHash
|
|
3030
|
+
&& naturalIntent.sourceOutboxId === target.id
|
|
3031
|
+
&& parseNaturalObjectiveFeedback(inbox.envelope.text) === naturalIntent.selection
|
|
3032
|
+
&& (parsed.kind === 'objective-status' || (naturalIntent.status === 'frozen'
|
|
3033
|
+
&& JSON.stringify(naturalIntent.command) === JSON.stringify(parsed)));
|
|
3034
|
+
if ((inbox.envelope.attachments?.length ?? 0) !== 0 || (!typedMatches && !naturalMatches))
|
|
2851
3035
|
return 'invalid-target';
|
|
3036
|
+
if (naturalIntent === undefined && parsed.kind !== 'objective-status'
|
|
3037
|
+
&& this.deliveryStore.hasEarlierPendingNaturalObjectiveIntent(target.id, inbox.admissionCursor.sequence)) {
|
|
3038
|
+
await this.drainNaturalObjectiveIntents();
|
|
3039
|
+
if (this.deliveryStore.hasEarlierPendingNaturalObjectiveIntent(target.id, inbox.admissionCursor.sequence))
|
|
3040
|
+
return 'unknown';
|
|
3041
|
+
}
|
|
2852
3042
|
const metadata = target.intent.metadata;
|
|
2853
3043
|
let goalOutcomeTarget;
|
|
2854
3044
|
try {
|
|
@@ -2874,6 +3064,8 @@ export class AssistantDeliveryService extends Service {
|
|
|
2874
3064
|
const sourceInbox = this.deliveryStore.getInboxByProviderEvent(envelope.channel, envelope.account, sourceEventId);
|
|
2875
3065
|
if (sourceInbox === undefined)
|
|
2876
3066
|
return 'invalid-target';
|
|
3067
|
+
if (!this.deliveryStore.isVerifiedForegroundObjectiveTarget(binding, sourceInbox.id, target.id))
|
|
3068
|
+
return 'invalid-target';
|
|
2877
3069
|
const lineage = this.ownerLineageForBinding(binding);
|
|
2878
3070
|
const accepted = lineage === undefined ? null : this.deliveryStore.inspectForegroundAcceptedExecutionForOwner({
|
|
2879
3071
|
inboxId: sourceInbox.id,
|
|
@@ -2892,7 +3084,7 @@ export class AssistantDeliveryService extends Service {
|
|
|
2892
3084
|
&& (execution.status !== 'succeeded' || !execution.quiescent)))
|
|
2893
3085
|
return 'invalid-target';
|
|
2894
3086
|
const canonicalForeground = foreground !== null || accepted !== null;
|
|
2895
|
-
const projectForegroundOwner =
|
|
3087
|
+
const projectForegroundOwner = (inspectOnly) => {
|
|
2896
3088
|
const sink = this.evaluationSink;
|
|
2897
3089
|
if (sink === undefined || lineage === undefined)
|
|
2898
3090
|
return undefined;
|
|
@@ -2921,10 +3113,10 @@ export class AssistantDeliveryService extends Service {
|
|
|
2921
3113
|
return undefined;
|
|
2922
3114
|
if (inspectOnly)
|
|
2923
3115
|
return sink.registration.inspect?.(capabilityReceipt);
|
|
2924
|
-
const receipt =
|
|
3116
|
+
const receipt = sink.registration.append({
|
|
2925
3117
|
capabilityReceipt, runId: sourceInbox.id, outboxId: target.id, chatId: binding.conversation.chat,
|
|
2926
3118
|
principalId: externalPrincipalId(binding.principal), bindingId: binding.id, idempotencyKey: claims.idempotencyKey,
|
|
2927
|
-
})
|
|
3119
|
+
});
|
|
2928
3120
|
return typeof receipt === 'object' && receipt !== null
|
|
2929
3121
|
&& typeof receipt.ownerFeedbackState === 'object'
|
|
2930
3122
|
? receipt.ownerFeedbackState
|
|
@@ -2934,12 +3126,15 @@ export class AssistantDeliveryService extends Service {
|
|
|
2934
3126
|
if (!canonicalForeground)
|
|
2935
3127
|
return this.deliveryStore.verifiedWorkflowObjectiveState(target.id, lineage) ?? 'recorded';
|
|
2936
3128
|
try {
|
|
2937
|
-
|
|
3129
|
+
const inspected = projectForegroundOwner(true);
|
|
3130
|
+
return inspected ?? (naturalIntent !== undefined && this.evaluationSink !== undefined ? 'recorded' : 'unavailable');
|
|
2938
3131
|
}
|
|
2939
3132
|
catch {
|
|
2940
3133
|
return 'unknown';
|
|
2941
3134
|
}
|
|
2942
3135
|
}
|
|
3136
|
+
if (naturalIntent !== undefined && !canonicalForeground)
|
|
3137
|
+
return 'invalid-target';
|
|
2943
3138
|
if (canonicalForeground && this.evaluationSink === undefined)
|
|
2944
3139
|
return 'unavailable';
|
|
2945
3140
|
try {
|
|
@@ -2947,7 +3142,7 @@ export class AssistantDeliveryService extends Service {
|
|
|
2947
3142
|
// is unavailable, never acknowledge a Delivery-only success; a replay
|
|
2948
3143
|
// can safely repeat the opaque command and then repair local workflow
|
|
2949
3144
|
// evidence after the canonical owner revision is durable.
|
|
2950
|
-
const canonical = canonicalForeground ?
|
|
3145
|
+
const canonical = canonicalForeground ? projectForegroundOwner(false) : undefined;
|
|
2951
3146
|
if (canonicalForeground && canonical === undefined)
|
|
2952
3147
|
return 'unavailable';
|
|
2953
3148
|
const result = this.deliveryStore.commitVerifiedWorkflowTraceFeedback({
|
|
@@ -2958,7 +3153,7 @@ export class AssistantDeliveryService extends Service {
|
|
|
2958
3153
|
objectiveStatus,
|
|
2959
3154
|
...(parsed.kind === 'objective-revision' ? { command: parsed } : {}),
|
|
2960
3155
|
});
|
|
2961
|
-
|
|
3156
|
+
void this.drainWorkflowTraces().catch(() => { });
|
|
2962
3157
|
return canonical ?? result.ownerFeedbackState ?? 'recorded';
|
|
2963
3158
|
}
|
|
2964
3159
|
catch (error) {
|
|
@@ -2974,7 +3169,7 @@ export class AssistantDeliveryService extends Service {
|
|
|
2974
3169
|
if (typeof error === 'object' && error !== null && 'code' in error
|
|
2975
3170
|
&& ['idempotency-conflict', 'version-conflict'].includes(String(error.code)))
|
|
2976
3171
|
return 'conflict';
|
|
2977
|
-
return '
|
|
3172
|
+
return 'unknown';
|
|
2978
3173
|
}
|
|
2979
3174
|
}
|
|
2980
3175
|
const automationId = metadata?.['dsh.learning.automationId'];
|
|
@@ -3264,7 +3459,7 @@ export class AssistantDeliveryService extends Service {
|
|
|
3264
3459
|
const reviewer = approvalReviewerOf(events);
|
|
3265
3460
|
const reviewRoute = reviewer === 'user'
|
|
3266
3461
|
? 'user'
|
|
3267
|
-
: reviewer === 'auto-review' && isAutoReviewEscalation(request)
|
|
3462
|
+
: reviewer === 'auto-review' && ctx.assistantPolicy.isAutoReviewEscalation(request)
|
|
3268
3463
|
? 'auto-escalation'
|
|
3269
3464
|
: undefined;
|
|
3270
3465
|
const sessionId = String(agent.session.id);
|
|
@@ -3407,7 +3602,7 @@ export class AssistantDeliveryService extends Service {
|
|
|
3407
3602
|
}
|
|
3408
3603
|
const reviewRoute = reviewer === 'user'
|
|
3409
3604
|
? 'user'
|
|
3410
|
-
: reviewer === 'auto-review' && isAutoReviewEscalation(request)
|
|
3605
|
+
: reviewer === 'auto-review' && ctx.assistantPolicy.isAutoReviewEscalation(request)
|
|
3411
3606
|
? 'auto-escalation'
|
|
3412
3607
|
: undefined;
|
|
3413
3608
|
if (reviewRoute === undefined)
|
|
@@ -3974,6 +4169,94 @@ export class AssistantDeliveryService extends Service {
|
|
|
3974
4169
|
generation: resolved.snapshot.generation,
|
|
3975
4170
|
});
|
|
3976
4171
|
}
|
|
4172
|
+
/** Host-only proof that the live caller Agent belongs to the current owner route. */
|
|
4173
|
+
validateOwnerAgentForRoute(agent, authorityId) {
|
|
4174
|
+
if (!this.active || typeof agent !== 'object' || agent === null || agent.session === undefined)
|
|
4175
|
+
return undefined;
|
|
4176
|
+
const agents = this.context.get('agents');
|
|
4177
|
+
const sessions = this.context.get('sessions');
|
|
4178
|
+
if (agents === undefined || sessions === undefined)
|
|
4179
|
+
return undefined;
|
|
4180
|
+
const sessionId = String(agent.session.id);
|
|
4181
|
+
const liveCaller = () => String(agent.id) === sessionId
|
|
4182
|
+
&& agents.get(agent.id) === agent
|
|
4183
|
+
&& sessions.get(agent.id) === agent.session;
|
|
4184
|
+
if (!liveCaller())
|
|
4185
|
+
return undefined;
|
|
4186
|
+
const matches = (attestation, route, receipt) => attestation.sessionId === sessionId
|
|
4187
|
+
&& attestation.bindingId === route.binding.id
|
|
4188
|
+
&& attestation.bindingVersion === route.binding.version
|
|
4189
|
+
&& attestation.bindingGeneration === route.binding.generation
|
|
4190
|
+
&& route.binding.sessionId === sessionId
|
|
4191
|
+
&& route.snapshot.bindingId === attestation.bindingId
|
|
4192
|
+
&& route.snapshot.bindingVersion === attestation.bindingVersion
|
|
4193
|
+
&& route.snapshot.generation === attestation.bindingGeneration
|
|
4194
|
+
&& attestation.principalId === receipt.principalId
|
|
4195
|
+
&& attestation.principalLineage.principalRecordId === receipt.principalRecordId
|
|
4196
|
+
&& attestation.principalLineage.principalVersion === receipt.principalVersion
|
|
4197
|
+
&& attestation.scope.workspace === receipt.workspace
|
|
4198
|
+
&& attestation.scope.preset === receipt.agentPreset
|
|
4199
|
+
&& agent.session.header.cwd === receipt.workspace
|
|
4200
|
+
&& agent.session.header.agentPreset === receipt.agentPreset
|
|
4201
|
+
&& route.authorityId === receipt.authorityId
|
|
4202
|
+
&& route.snapshot.authorityHash === receipt.authorityHash
|
|
4203
|
+
&& route.snapshot.bindingVersion === receipt.bindingVersion
|
|
4204
|
+
&& route.snapshot.generation === receipt.generation;
|
|
4205
|
+
try {
|
|
4206
|
+
const first = this.preferencePrincipalForAgent(agent);
|
|
4207
|
+
if (first === undefined)
|
|
4208
|
+
return undefined;
|
|
4209
|
+
const route = this.resolveOwnerRoute(authorityId);
|
|
4210
|
+
const receipt = this.validateOwnerRoute({
|
|
4211
|
+
authorityId: route.authorityId,
|
|
4212
|
+
principalId: first.principalId,
|
|
4213
|
+
workspace: first.scope.workspace,
|
|
4214
|
+
agentPreset: first.scope.preset,
|
|
4215
|
+
});
|
|
4216
|
+
if (!matches(first, route, receipt))
|
|
4217
|
+
return undefined;
|
|
4218
|
+
const current = this.preferencePrincipalForAgent(agent);
|
|
4219
|
+
const currentRoute = this.resolveOwnerRoute(authorityId);
|
|
4220
|
+
return current !== undefined && liveCaller() && matches(current, currentRoute, receipt)
|
|
4221
|
+
? receipt
|
|
4222
|
+
: undefined;
|
|
4223
|
+
}
|
|
4224
|
+
catch (error) {
|
|
4225
|
+
if (error instanceof AssistantDeliveryError && error.code === 'missing-binding')
|
|
4226
|
+
return undefined;
|
|
4227
|
+
throw error;
|
|
4228
|
+
}
|
|
4229
|
+
}
|
|
4230
|
+
/** Host-only durable ordinary-turn metadata; never registered as a model tool. */
|
|
4231
|
+
listOwnerForegroundTaskSources(input) {
|
|
4232
|
+
this.assertActive();
|
|
4233
|
+
this.validateOwnerRoute(input);
|
|
4234
|
+
return this.deliveryStore.listOwnerForegroundTaskSources(input, this.ownerRoutes.get(input.authorityId));
|
|
4235
|
+
}
|
|
4236
|
+
/** Host-only exact terminal source metadata, including before reply Outbox exists. */
|
|
4237
|
+
inspectOwnerForegroundTaskSource(input) {
|
|
4238
|
+
this.assertActive();
|
|
4239
|
+
this.validateOwnerRoute(input);
|
|
4240
|
+
return this.deliveryStore.inspectOwnerForegroundTaskSource(input, this.ownerRoutes.get(input.authorityId));
|
|
4241
|
+
}
|
|
4242
|
+
/** Read one exact completed source under the current owner fence. */
|
|
4243
|
+
readOwnerForegroundTaskSource(input) {
|
|
4244
|
+
this.assertActive();
|
|
4245
|
+
this.validateOwnerRoute(input);
|
|
4246
|
+
return this.deliveryStore.readOwnerForegroundTaskSource(input, this.ownerRoutes.get(input.authorityId));
|
|
4247
|
+
}
|
|
4248
|
+
/** Hold Delivery's owner/source writer fence across synchronous downstream adoption. */
|
|
4249
|
+
withOwnerForegroundTaskSourceFence(input, callback) {
|
|
4250
|
+
this.assertActive();
|
|
4251
|
+
this.validateOwnerRoute(input);
|
|
4252
|
+
return this.deliveryStore.withOwnerForegroundTaskSourceFence(input, this.ownerRoutes.get(input.authorityId), callback);
|
|
4253
|
+
}
|
|
4254
|
+
/** Hold one owner/source writer fence for a bounded, ordered batch of sources. */
|
|
4255
|
+
withOwnerForegroundTaskSourcesFence(input, callback) {
|
|
4256
|
+
this.assertActive();
|
|
4257
|
+
this.validateOwnerRoute(input);
|
|
4258
|
+
return this.deliveryStore.withOwnerForegroundTaskSourcesFence(input, this.ownerRoutes.get(input.authorityId), callback);
|
|
4259
|
+
}
|
|
3977
4260
|
/** Host-only snapshot of the model selected for this owner's external conversation. */
|
|
3978
4261
|
inspectOwnerModelSelection(input) {
|
|
3979
4262
|
this.validateOwnerRoute(input);
|
|
@@ -4037,6 +4320,19 @@ export class AssistantDeliveryService extends Service {
|
|
|
4037
4320
|
owner: { principalRecordId: owner.principalRecordId, principalVersion: owner.principalVersion } }) ?? accepted;
|
|
4038
4321
|
if (execution === null)
|
|
4039
4322
|
return undefined;
|
|
4323
|
+
// /new retires the conversation binding. Read the version from the actual
|
|
4324
|
+
// execution row, never the retired binding's incremented version or the
|
|
4325
|
+
// new Session's generation. The Store also fences the current owner route.
|
|
4326
|
+
const original = this.deliveryStore.inspectOwnerForegroundTaskSource({ ...routeInput,
|
|
4327
|
+
inboxId: inbox.id, expectedOwner: { authorityHash: owner.authorityHash,
|
|
4328
|
+
principalRecordId: owner.principalRecordId, principalVersion: owner.principalVersion } }, this.ownerRoutes.get(owner.authorityId));
|
|
4329
|
+
if (original === undefined || original.binding.id !== binding.id
|
|
4330
|
+
|| original.binding.sessionId !== binding.sessionId)
|
|
4331
|
+
return undefined;
|
|
4332
|
+
const sourceOwner = Object.freeze({ ...owner, bindingVersion: original.binding.version,
|
|
4333
|
+
generation: original.binding.generation });
|
|
4334
|
+
if (!isSourceOwnerContinuation(owner, sourceOwner))
|
|
4335
|
+
return undefined;
|
|
4040
4336
|
const verifierComponent = (component) => accepted !== null && component.source.kind === 'evaluator' && component.source.id === 'assistant-verifier'
|
|
4041
4337
|
&& component.evaluator.id === 'assistant-verifier' && component.evaluator.version === '1'
|
|
4042
4338
|
&& component.evidence.some(ref => ref.kind === 'foreground-turn' && ref.ref === inbox.id)
|
|
@@ -4048,6 +4344,8 @@ export class AssistantDeliveryService extends Service {
|
|
|
4048
4344
|
return undefined;
|
|
4049
4345
|
let judgement = 'unresolved';
|
|
4050
4346
|
let ownerRevision;
|
|
4347
|
+
let feedback;
|
|
4348
|
+
let feedbackOutboxId;
|
|
4051
4349
|
const objective = canonical.objective;
|
|
4052
4350
|
if (objective?.source.kind === 'user-feedback') {
|
|
4053
4351
|
if (objective.source.id !== 'assistant-delivery/typed-owner-feedback')
|
|
@@ -4068,7 +4366,10 @@ export class AssistantDeliveryService extends Service {
|
|
|
4068
4366
|
|| !['accepted', 'delivered', 'read'].includes(outbox.status))
|
|
4069
4367
|
return undefined;
|
|
4070
4368
|
judgement = 'owner-feedback';
|
|
4369
|
+
feedbackOutboxId = outbox.id;
|
|
4071
4370
|
ownerRevision = Object.freeze({ version: revision.version, action: revision.action });
|
|
4371
|
+
if (revision.operationId !== undefined)
|
|
4372
|
+
feedback = this.deliveryStore.findNaturalObjectiveFeedbackByOperation(outbox.id, revision.operationId, { principalRecordId: owner.principalRecordId, principalVersion: owner.principalVersion });
|
|
4072
4373
|
}
|
|
4073
4374
|
else if (objective !== undefined) {
|
|
4074
4375
|
if (!verifierComponent(objective))
|
|
@@ -4080,16 +4381,36 @@ export class AssistantDeliveryService extends Service {
|
|
|
4080
4381
|
// may turn a completed ordinary conversation into a learning source.
|
|
4081
4382
|
if (accepted === null && judgement !== 'owner-feedback')
|
|
4082
4383
|
return undefined;
|
|
4384
|
+
const content = feedbackOutboxId === undefined ? undefined : this.readOwnerForegroundTaskSource({
|
|
4385
|
+
...routeInput, inboxId: inbox.id, expectedSourceDigest: original.sourceDigest,
|
|
4386
|
+
expectedOwner: { authorityHash: owner.authorityHash,
|
|
4387
|
+
principalRecordId: owner.principalRecordId, principalVersion: owner.principalVersion },
|
|
4388
|
+
maxReplyBytes: 16_384,
|
|
4389
|
+
});
|
|
4390
|
+
if (content !== undefined && content.reply.outboxId !== feedbackOutboxId)
|
|
4391
|
+
return undefined;
|
|
4392
|
+
const reply = content?.reply === undefined ? undefined : (() => {
|
|
4393
|
+
// A partial prefix could cut a credential below the filter's minimum
|
|
4394
|
+
// token length. Publish no raw prefix when the reader hit its hard cap.
|
|
4395
|
+
const visible = content.reply.truncated
|
|
4396
|
+
? { text: '[TRUNCATED REPLY]', truncated: true, redacted: true }
|
|
4397
|
+
: redactOwnerLearningReply(content.reply.text, 4096);
|
|
4398
|
+
return Object.freeze({ text: visible.text, truncated: content.reply.truncated || visible.truncated,
|
|
4399
|
+
redacted: visible.redacted, outboxId: content.reply.outboxId,
|
|
4400
|
+
intentDigest: content.reply.intentDigest, fullTextDigest: content.reply.fullTextDigest });
|
|
4401
|
+
})();
|
|
4083
4402
|
// Fence cross-ledger reads before handing any task text to the consumer.
|
|
4084
4403
|
if (!evaluation.isTrustedTaskLearningProjectionReceipt(canonical)
|
|
4085
4404
|
|| acceptanceCanonicalJson(owner) !== acceptanceCanonicalJson(this.validateOwnerRoute(routeInput)))
|
|
4086
4405
|
return undefined;
|
|
4087
4406
|
const objectiveText = inbox.envelope.text;
|
|
4088
|
-
return Object.freeze({ protocol: 'assistant-delivery/owner-foreground-learning/v1', owner, canonical, judgement,
|
|
4407
|
+
return Object.freeze({ protocol: 'assistant-delivery/owner-foreground-learning/v1', owner: sourceOwner, canonical, judgement,
|
|
4089
4408
|
...(ownerRevision === undefined ? {} : { ownerRevision }),
|
|
4409
|
+
...(feedback === undefined ? {} : { feedback }),
|
|
4090
4410
|
source: Object.freeze({ sessionId: binding.sessionId, inboxId: inbox.id,
|
|
4091
4411
|
objective: objectiveText.slice(0, 4096), truncated: objectiveText.length > 4096, quiescent: execution.quiescent,
|
|
4092
|
-
modelSelectionState: execution.modelSelectionState, ...(execution.modelSelection === undefined ? {} : { modelSelection: execution.modelSelection })
|
|
4412
|
+
modelSelectionState: execution.modelSelectionState, ...(execution.modelSelection === undefined ? {} : { modelSelection: execution.modelSelection }),
|
|
4413
|
+
...(reply === undefined ? {} : { reply }) }) });
|
|
4093
4414
|
}
|
|
4094
4415
|
/**
|
|
4095
4416
|
* Enqueue against a stable Host-owned route rather than a session binding.
|
|
@@ -4366,6 +4687,7 @@ export class AssistantDeliveryService extends Service {
|
|
|
4366
4687
|
await this.outbound.tick();
|
|
4367
4688
|
await this.drainDeliveryPresentations();
|
|
4368
4689
|
await this.drainPreferenceProjections();
|
|
4690
|
+
await this.drainNaturalObjectiveIntents();
|
|
4369
4691
|
await this.drainWorkflowTraces();
|
|
4370
4692
|
}
|
|
4371
4693
|
async whenIdle() {
|
|
@@ -4376,6 +4698,7 @@ export class AssistantDeliveryService extends Service {
|
|
|
4376
4698
|
this.modelSelectionFlight,
|
|
4377
4699
|
this.presentationFlight,
|
|
4378
4700
|
this.preferenceProjectionFlight,
|
|
4701
|
+
this.naturalObjectiveFlight,
|
|
4379
4702
|
this.workflowTraceFlight,
|
|
4380
4703
|
this.inboundAdmissionRecoveryFlight,
|
|
4381
4704
|
]);
|
|
@@ -4628,6 +4951,7 @@ export class AssistantDeliveryService extends Service {
|
|
|
4628
4951
|
this.modelSelectionFlight,
|
|
4629
4952
|
this.presentationFlight,
|
|
4630
4953
|
this.preferenceProjectionFlight,
|
|
4954
|
+
this.naturalObjectiveFlight,
|
|
4631
4955
|
this.workflowTraceFlight,
|
|
4632
4956
|
]);
|
|
4633
4957
|
}
|