@sema-agent/client-core 0.85.0 → 0.85.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/README.md +5 -5
- package/dist/adapter/activeRunSelfHeal.d.ts +3 -0
- package/dist/adapter/activeRunSelfHeal.js +149 -17
- package/dist/hitl/armedGateRegistry.d.ts +1 -0
- package/dist/hitl/armedGateRegistry.js +1 -1
- package/dist/hitl/planReviewWire.js +14 -3
- package/dist/host.d.ts +1 -1
- package/dist/host.js +11 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/request/taskRequest.d.ts +2 -0
- package/dist/request/taskRequest.js +12 -0
- package/dist/subagent/subagentOwnerAbsence.js +2 -5
- package/docs/INTEGRATION-CLIENTS.md +198 -14
- package/package.json +1 -1
|
@@ -79,11 +79,105 @@ export function readCancelRequested(body) {
|
|
|
79
79
|
const v = body.cancelRequested;
|
|
80
80
|
return typeof v === 'boolean' ? v : undefined;
|
|
81
81
|
}
|
|
82
|
+
const REOPEN_VERDICT_KEYS = [
|
|
83
|
+
'reopened',
|
|
84
|
+
'firstSight',
|
|
85
|
+
'presented',
|
|
86
|
+
'decidedWithoutCard',
|
|
87
|
+
'pendingRowGone',
|
|
88
|
+
'_sema_decisionInFlight',
|
|
89
|
+
'dismissedByUser',
|
|
90
|
+
'_sema_noPresentationSurface',
|
|
91
|
+
];
|
|
92
|
+
function snapshotReopenVerdict(raw) {
|
|
93
|
+
if (raw === null || raw === undefined)
|
|
94
|
+
return { reopened: false };
|
|
95
|
+
if (typeof raw !== 'object' && typeof raw !== 'function')
|
|
96
|
+
return raw;
|
|
97
|
+
const src = raw;
|
|
98
|
+
let nullProto = false;
|
|
99
|
+
try {
|
|
100
|
+
nullProto = Object.getPrototypeOf(raw) === null;
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
nullProto = false;
|
|
104
|
+
}
|
|
105
|
+
const snap = nullProto ? Object.create(null) : {};
|
|
106
|
+
const put = (k, v) => {
|
|
107
|
+
Object.defineProperty(snap, k, { value: v, enumerable: true, writable: true, configurable: true });
|
|
108
|
+
};
|
|
109
|
+
let own = [];
|
|
110
|
+
try {
|
|
111
|
+
own = Reflect.ownKeys(raw);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
own = [];
|
|
115
|
+
}
|
|
116
|
+
const copied = new Set();
|
|
117
|
+
for (const k of own) {
|
|
118
|
+
let enumerable = false;
|
|
119
|
+
try {
|
|
120
|
+
enumerable = Object.prototype.propertyIsEnumerable.call(raw, k);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
enumerable = false;
|
|
124
|
+
}
|
|
125
|
+
if (!enumerable)
|
|
126
|
+
continue;
|
|
127
|
+
let v;
|
|
128
|
+
let readable = true;
|
|
129
|
+
try {
|
|
130
|
+
v = src[k];
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
readable = false;
|
|
134
|
+
}
|
|
135
|
+
if (!readable)
|
|
136
|
+
continue;
|
|
137
|
+
put(k, v);
|
|
138
|
+
copied.add(k);
|
|
139
|
+
}
|
|
140
|
+
for (const k of REOPEN_VERDICT_KEYS) {
|
|
141
|
+
if (copied.has(k))
|
|
142
|
+
continue;
|
|
143
|
+
let v;
|
|
144
|
+
let readable = true;
|
|
145
|
+
try {
|
|
146
|
+
v = src[k];
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
readable = false;
|
|
150
|
+
}
|
|
151
|
+
if (readable && v !== undefined)
|
|
152
|
+
put(k, v);
|
|
153
|
+
}
|
|
154
|
+
return snap;
|
|
155
|
+
}
|
|
82
156
|
function reopenRefusedForDecisionInFlight(verdict) {
|
|
83
|
-
|
|
157
|
+
try {
|
|
158
|
+
return verdict !== null && verdict.reopened === false && verdict._sema_decisionInFlight === true;
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
84
163
|
}
|
|
85
164
|
function reopenRefusedForUserDismissal(verdict) {
|
|
86
|
-
|
|
165
|
+
try {
|
|
166
|
+
return verdict !== null && verdict.reopened === false && verdict.dismissedByUser === true;
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function reopenRefusedForNoPresentationSurface(verdict) {
|
|
173
|
+
try {
|
|
174
|
+
return (verdict !== null &&
|
|
175
|
+
verdict.reopened === false &&
|
|
176
|
+
verdict._sema_noPresentationSurface === true);
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
87
181
|
}
|
|
88
182
|
function planReviewReopenTriggerFor(origin) {
|
|
89
183
|
if (origin === 'user')
|
|
@@ -93,7 +187,31 @@ function planReviewReopenTriggerFor(origin) {
|
|
|
93
187
|
return undefined;
|
|
94
188
|
}
|
|
95
189
|
function reopenDelivered(verdict) {
|
|
96
|
-
|
|
190
|
+
let reopened;
|
|
191
|
+
let presented;
|
|
192
|
+
try {
|
|
193
|
+
reopened = verdict.reopened;
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
if (reopened !== true)
|
|
199
|
+
return false;
|
|
200
|
+
try {
|
|
201
|
+
presented = verdict.presented;
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
presented = undefined;
|
|
205
|
+
}
|
|
206
|
+
return presented !== false;
|
|
207
|
+
}
|
|
208
|
+
function reopenedOfOutcome(outcome) {
|
|
209
|
+
try {
|
|
210
|
+
return outcome.reopened ?? null;
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
97
215
|
}
|
|
98
216
|
export function atMostOnceFailureClass(e) {
|
|
99
217
|
const status = e?.status;
|
|
@@ -299,7 +417,7 @@ async function planVerdict(taskId, deps) {
|
|
|
299
417
|
try {
|
|
300
418
|
const trigger = planReviewReopenTriggerFor(deps?.submissionOrigin);
|
|
301
419
|
const verdict = trigger === undefined ? deps?.reopenPlanReview?.(taskId) : deps?.reopenPlanReview?.(taskId, { trigger });
|
|
302
|
-
return (await verdict)
|
|
420
|
+
return snapshotReopenVerdict(await verdict);
|
|
303
421
|
}
|
|
304
422
|
catch {
|
|
305
423
|
return { reopened: false };
|
|
@@ -307,7 +425,7 @@ async function planVerdict(taskId, deps) {
|
|
|
307
425
|
}
|
|
308
426
|
async function askVerdict(taskId, deps) {
|
|
309
427
|
try {
|
|
310
|
-
return (await deps?.reopenAskPark?.(taskId))
|
|
428
|
+
return snapshotReopenVerdict(await deps?.reopenAskPark?.(taskId));
|
|
311
429
|
}
|
|
312
430
|
catch {
|
|
313
431
|
return { reopened: false };
|
|
@@ -324,6 +442,7 @@ async function planReviewArm(taskId, signal, deps) {
|
|
|
324
442
|
...(reopenRefusedForDecisionInFlight(verdict) ? { decisionInFlight: true } : {}),
|
|
325
443
|
...(verdict.pendingRowGone === true ? { pendingRowGone: true } : {}),
|
|
326
444
|
...(reopenRefusedForUserDismissal(verdict) ? { dismissedByUser: true } : {}),
|
|
445
|
+
...(reopenRefusedForNoPresentationSurface(verdict) ? { noPresentationSurface: true } : {}),
|
|
327
446
|
};
|
|
328
447
|
}
|
|
329
448
|
async function askParkArm(taskId, signal, runs, deps) {
|
|
@@ -364,6 +483,7 @@ async function askParkArm(taskId, signal, runs, deps) {
|
|
|
364
483
|
decidePath: signal.pendingGate?.decidePath ?? null,
|
|
365
484
|
...(inFlight ? { decisionInFlight: true } : {}),
|
|
366
485
|
...(verdict.pendingRowGone === true ? { pendingRowGone: true } : {}),
|
|
486
|
+
...(reopenRefusedForNoPresentationSurface(verdict) ? { noPresentationSurface: true } : {}),
|
|
367
487
|
};
|
|
368
488
|
}
|
|
369
489
|
async function probeRunStatusOnce(taskId, durable, durableGet, deps) {
|
|
@@ -655,6 +775,7 @@ export function activeRunSelfHealRow(outcome, signal, copy, origin, follow) {
|
|
|
655
775
|
}
|
|
656
776
|
const INJECTED_LEAD = 'A follow-up message sema sent on its own (not one you typed)';
|
|
657
777
|
const USER_CLOSED_CARD_NOT_PUT_BACK = 'sema does not put a card you closed back on screen by itself';
|
|
778
|
+
const NO_CARD_VIEW_ATTACHED = 'this session has no view attached that can show decision cards';
|
|
658
779
|
function injectedSubmissionRow(outcome, following = false) {
|
|
659
780
|
const lead = INJECTED_LEAD;
|
|
660
781
|
const id = 'taskId' in outcome && outcome.taskId ? ` (id ${outcome.taskId})` : '';
|
|
@@ -677,17 +798,19 @@ function injectedSubmissionRow(outcome, following = false) {
|
|
|
677
798
|
}
|
|
678
799
|
if (outcome.kind === 'running-steered' && outcome.delivery === 'queued') {
|
|
679
800
|
const queuedOn = `${lead} is queued on an earlier reply${id} that is paused waiting for a decision`;
|
|
680
|
-
|
|
801
|
+
const reopened = reopenedOfOutcome(outcome);
|
|
802
|
+
if (reopened !== null && reopenDelivered(reopened)) {
|
|
681
803
|
return `${queuedOn}; sema has shown that decision card, and the message is picked up once you answer it.`;
|
|
682
804
|
}
|
|
683
|
-
if (reopenRefusedForDecisionInFlight(
|
|
805
|
+
if (reopenRefusedForDecisionInFlight(reopened)) {
|
|
684
806
|
return `${queuedOn}; your answer to it is still on its way, and the message is picked up once that answer is applied.`;
|
|
685
807
|
}
|
|
686
|
-
if (reopenRefusedForUserDismissal(
|
|
808
|
+
if (reopenRefusedForUserDismissal(reopened)) {
|
|
687
809
|
return (`${queuedOn}; you closed that card yourself, so sema did not put it back on screen — send a message to bring it ` +
|
|
688
810
|
`back, and the message is picked up once that decision is made.`);
|
|
689
811
|
}
|
|
690
|
-
|
|
812
|
+
const noView = reopenRefusedForNoPresentationSurface(reopened) ? ` (${NO_CARD_VIEW_ATTACHED})` : '';
|
|
813
|
+
return `${queuedOn} sema could not show here${noView}; the message is picked up only once that decision is made.`;
|
|
691
814
|
}
|
|
692
815
|
if (outcome.kind === 'running-steered' && outcome.delivery === 'parked_for_wake') {
|
|
693
816
|
return (`${lead} has not reached the model: the earlier reply${id} had already finished, so the message was set aside on it ` +
|
|
@@ -710,9 +833,13 @@ function injectedSubmissionRow(outcome, following = false) {
|
|
|
710
833
|
`sema is following that reply and will show whatever it asks for next; nothing for you to do now.`
|
|
711
834
|
: `${lead} was passed to the reply already in progress${id} instead of starting a new one — ` +
|
|
712
835
|
`watch that reply for what it does with it.`;
|
|
713
|
-
case 'not-delivered':
|
|
836
|
+
case 'not-delivered': {
|
|
837
|
+
const noView = (outcome.kind === 'ask-reopen-failed' || outcome.kind === 'plan-review-reopen-failed') && outcome.noPresentationSurface === true
|
|
838
|
+
? ` (${NO_CARD_VIEW_ATTACHED})`
|
|
839
|
+
: '';
|
|
714
840
|
return (`${lead} was not delivered: this session was still busy with an earlier reply${id}, and there was no open card ` +
|
|
715
|
-
`you could answer to free it. sema did not retry, so the model has not seen it.`);
|
|
841
|
+
`you could answer to free it${noView}. sema did not retry, so the model has not seen it.`);
|
|
842
|
+
}
|
|
716
843
|
}
|
|
717
844
|
}
|
|
718
845
|
function decisionInFlightRow(parkedOn) {
|
|
@@ -780,8 +907,9 @@ function activeRunSelfHealBaseRow(outcome, signal, wayOut, following = false, ke
|
|
|
780
907
|
const viaEngine = engineDecide && outcome.decidePath
|
|
781
908
|
? ` You can also decide it on the engine directly: POST ${outcome.decidePath}.`
|
|
782
909
|
: '';
|
|
910
|
+
const noView = outcome.noPresentationSurface === true ? `: ${NO_CARD_VIEW_ATTACHED}` : '';
|
|
783
911
|
return (`The previous turn is parked waiting for your decision (run ${outcome.taskId}) and sema could ` +
|
|
784
|
-
`not reopen that card here. It did NOT cancel the run — that would have decided it for you. ` +
|
|
912
|
+
`not reopen that card here${noView}. It did NOT cancel the run — that would have decided it for you. ` +
|
|
785
913
|
(keepSessionWayOut !== null
|
|
786
914
|
? `Your message was NOT sent. To keep this conversation, ${keepSessionWayOut}: the card comes back when the session resumes, if it is still waiting. Or ${wayOut} if you no longer want it.${viaEngine}`
|
|
787
915
|
: `Your message was NOT sent; ${wayOut} if you no longer want it.${viaEngine}`));
|
|
@@ -797,8 +925,9 @@ function activeRunSelfHealBaseRow(outcome, signal, wayOut, following = false, ke
|
|
|
797
925
|
const viaEngine = engineDecide && outcome.decidePath
|
|
798
926
|
? ` You can also decide it on the engine directly: POST ${outcome.decidePath}.`
|
|
799
927
|
: '';
|
|
928
|
+
const noView = outcome.noPresentationSurface === true ? `: ${NO_CARD_VIEW_ATTACHED}` : '';
|
|
800
929
|
return (`The previous turn is parked waiting for a plan review (run ${outcome.taskId}) and sema could not ` +
|
|
801
|
-
`reopen that approval card. It did NOT cancel the run — that would have discarded the plan for ` +
|
|
930
|
+
`reopen that approval card${noView}. It did NOT cancel the run — that would have discarded the plan for ` +
|
|
802
931
|
(keepSessionWayOut !== null
|
|
803
932
|
? `you. Your message was NOT sent. To keep this conversation, ${keepSessionWayOut}: the card comes back when the session resumes, if it is still waiting. Or ${wayOut} if you no longer want that plan.${viaEngine}`
|
|
804
933
|
: `you. Your message was NOT sent; ${wayOut} if you no longer want that plan.${viaEngine}`));
|
|
@@ -816,15 +945,18 @@ function activeRunSelfHealBaseRow(outcome, signal, wayOut, following = false, ke
|
|
|
816
945
|
}
|
|
817
946
|
if (outcome.delivery === 'queued') {
|
|
818
947
|
const parked = outcome.status ? `parked (status ${outcome.status})` : 'parked';
|
|
819
|
-
const
|
|
948
|
+
const reopened = reopenedOfOutcome(outcome);
|
|
949
|
+
const next = reopened !== null && reopenDelivered(reopened)
|
|
820
950
|
? `sema has surfaced that decision card — answering it is what lets that run resume and pick your message up.`
|
|
821
|
-
: reopenRefusedForDecisionInFlight(
|
|
951
|
+
: reopenRefusedForDecisionInFlight(reopened)
|
|
822
952
|
? `Your answer to that decision is still on its way to the engine, so sema did not show the card again; ` +
|
|
823
953
|
`that run moves on once the engine applies it.`
|
|
824
|
-
: reopenRefusedForUserDismissal(
|
|
954
|
+
: reopenRefusedForUserDismissal(reopened)
|
|
825
955
|
? `You closed that decision card yourself, so sema did not put it back on screen; nothing will resume that ` +
|
|
826
956
|
`run until that decision is made — send a message to bring the card back.`
|
|
827
|
-
: `sema could not surface that decision card here
|
|
957
|
+
: `sema could not surface that decision card here` +
|
|
958
|
+
(reopenRefusedForNoPresentationSurface(reopened) ? ` (${NO_CARD_VIEW_ATTACHED})` : '') +
|
|
959
|
+
`, so nothing will resume that run until that decision is made; ` +
|
|
828
960
|
`${wayOut} if you no longer want it.`;
|
|
829
961
|
return (`${handle} is not actually working right now: the engine reports it ${parked} on a decision it needs ` +
|
|
830
962
|
`from you, so it queued your message on that park instead of running it. ${next} ${textOnly} ` +
|
|
@@ -9,6 +9,7 @@ export declare function gateArmedWaitMs(): number;
|
|
|
9
9
|
export declare function waitForGateArmed(keys: readonly string[], timeoutMs: number): Promise<boolean>;
|
|
10
10
|
export declare function waitForGateArmedFor(sessionKey: string, keys: readonly string[], timeoutMs: number): Promise<boolean>;
|
|
11
11
|
export declare function registerArmedGateFromQuestionId(questionId: unknown): void;
|
|
12
|
+
export declare function registerArmedGateFromQuestionIdFor(sessionKey: string, questionId: unknown): void;
|
|
12
13
|
export declare function planReviewArmedKey(taskId: string): string;
|
|
13
14
|
export declare function planReviewArmedKeyFor(sessionKey: string, taskId: string): string;
|
|
14
15
|
export declare function notePlanReviewAnswered(questionId: unknown): void;
|
|
@@ -120,7 +120,7 @@ function armedKeyForQuestionIdFor(sessionKey, questionId) {
|
|
|
120
120
|
export function registerArmedGateFromQuestionId(questionId) {
|
|
121
121
|
registerArmedGateFromQuestionIdFor(DEFAULT_SESSION_KEY, questionId);
|
|
122
122
|
}
|
|
123
|
-
function registerArmedGateFromQuestionIdFor(sessionKey, questionId) {
|
|
123
|
+
export function registerArmedGateFromQuestionIdFor(sessionKey, questionId) {
|
|
124
124
|
if (typeof questionId !== 'string' || questionId.length === 0)
|
|
125
125
|
return;
|
|
126
126
|
if (questionId.startsWith(PLAN_REVIEW_QUESTION_ID_PREFIX) && !questionId.includes(REOPEN_ID_TAIL)) {
|
|
@@ -827,6 +827,12 @@ function mintPlanReviewReopenCard(taskId, opts, sessionKey, receiptMs) {
|
|
|
827
827
|
revokePlanReviewUserDismissal(sessionKey, taskId, markBefore);
|
|
828
828
|
return { reopened: true, firstSight };
|
|
829
829
|
}
|
|
830
|
+
function noPresentationSurfaceVerdict(taskId, sessionKey) {
|
|
831
|
+
const verdict = { reopened: false, _sema_noPresentationSurface: true };
|
|
832
|
+
hostLog('debug', `planReviewWire: reopen for task ${taskId} refused — nothing is subscribed to question frames for session ` +
|
|
833
|
+
`${JSON.stringify(sessionKey)} (onQuestionFrameFor), so the card has nowhere to render`);
|
|
834
|
+
return verdict;
|
|
835
|
+
}
|
|
830
836
|
async function reopenAfterDismissalCheck(taskId, opts, sessionKey, receiptMs, mark, recheckReadStart) {
|
|
831
837
|
const refusedByUser = { reopened: false, dismissedByUser: true };
|
|
832
838
|
try {
|
|
@@ -863,6 +869,11 @@ async function reopenAfterDismissalCheck(taskId, opts, sessionKey, receiptMs, ma
|
|
|
863
869
|
hostLog('debug', `planReviewWire: reopen for task ${taskId} not minted — the dismissal record changed while it was being checked (stale evaluation)`);
|
|
864
870
|
return await staleDismissalVerdict(current, sessionKey, taskId, receiptMs);
|
|
865
871
|
}
|
|
872
|
+
if (!hasQuestionOverlayFor(sessionKey)) {
|
|
873
|
+
if (fresh)
|
|
874
|
+
dropDismissalEntry(sessionKey, taskId, mark);
|
|
875
|
+
return noPresentationSurfaceVerdict(taskId, sessionKey);
|
|
876
|
+
}
|
|
866
877
|
if (!fresh) {
|
|
867
878
|
hostLog('debug', `planReviewWire: automatic reopen for task ${taskId} refused — the user closed this gate's card (no newer gate instance proven)`);
|
|
868
879
|
return refusedByUser;
|
|
@@ -878,8 +889,7 @@ async function reopenAfterDismissalCheck(taskId, opts, sessionKey, receiptMs, ma
|
|
|
878
889
|
putDismissalEntry(sessionKey, taskId, reopening);
|
|
879
890
|
let verdict = { reopened: false };
|
|
880
891
|
try {
|
|
881
|
-
|
|
882
|
-
verdict = await mintPlanReviewReopen(taskId, opts, sessionKey, receiptMs);
|
|
892
|
+
verdict = await mintPlanReviewReopen(taskId, opts, sessionKey, receiptMs);
|
|
883
893
|
}
|
|
884
894
|
finally {
|
|
885
895
|
const presented = verdict.reopened === true;
|
|
@@ -937,7 +947,8 @@ export function reopenPlanReviewCard(taskId, opts) {
|
|
|
937
947
|
const recheckReadStart = readStart === undefined ? guardStartedAt : Math.min(readStart, guardStartedAt);
|
|
938
948
|
const sessionKey = opts?.sessionKey ?? DEFAULT_SESSION_KEY;
|
|
939
949
|
if (!hasQuestionOverlayFor(sessionKey)) {
|
|
940
|
-
|
|
950
|
+
const noSurface = noPresentationSurfaceVerdict(taskId, sessionKey);
|
|
951
|
+
return receiptMs === undefined ? noSurface : Promise.resolve(noSurface);
|
|
941
952
|
}
|
|
942
953
|
if (sessionKey !== DEFAULT_SESSION_KEY && opts?.deliverDecision === undefined && opts?.wire === undefined) {
|
|
943
954
|
hostLog('error', `planReviewWire: plan_review 卡未重开 —— sessionKey=${JSON.stringify(sessionKey)} 是非默认槽,` +
|
package/dist/host.d.ts
CHANGED
|
@@ -56,7 +56,7 @@ export interface HostPorts {
|
|
|
56
56
|
}
|
|
57
57
|
export declare function installHost(ports: HostPorts): () => void;
|
|
58
58
|
export declare function installHostFor(sessionKey: string, ports: Omit<HostPorts, 'queue'>): () => void;
|
|
59
|
-
export declare function hostLog(level: AdapterLogLevel, msg: string, data?: unknown):
|
|
59
|
+
export declare function hostLog(level: AdapterLogLevel, msg: string, data?: unknown): boolean;
|
|
60
60
|
export declare function hostProbe(channel: string, line: string): void;
|
|
61
61
|
export declare function hostSettings(): SettingsPort | undefined;
|
|
62
62
|
export declare function hostSettingsFor(sessionKey: string): SettingsPort | undefined;
|
package/dist/host.js
CHANGED
|
@@ -46,11 +46,20 @@ export function installHostFor(sessionKey, ports) {
|
|
|
46
46
|
slot.state = prev;
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
|
+
function callDiagnosticPort(call) {
|
|
50
|
+
try {
|
|
51
|
+
call();
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
49
58
|
export function hostLog(level, msg, data) {
|
|
50
|
-
hostSlot(DEFAULT_SESSION_KEY).state.log?.(level, msg, data);
|
|
59
|
+
return callDiagnosticPort(() => hostSlot(DEFAULT_SESSION_KEY).state.log?.(level, msg, data));
|
|
51
60
|
}
|
|
52
61
|
export function hostProbe(channel, line) {
|
|
53
|
-
hostSlot(DEFAULT_SESSION_KEY).state.probe?.(channel, line);
|
|
62
|
+
callDiagnosticPort(() => hostSlot(DEFAULT_SESSION_KEY).state.probe?.(channel, line));
|
|
54
63
|
}
|
|
55
64
|
export function hostSettings() {
|
|
56
65
|
return hostSettingsFor(DEFAULT_SESSION_KEY);
|
package/dist/index.d.ts
CHANGED
|
@@ -169,7 +169,7 @@ export * from './coreValuePorts.js';
|
|
|
169
169
|
export * from './hitl/askGateWire.js';
|
|
170
170
|
export * from './hitl/planReviewWire.js';
|
|
171
171
|
export { PLAN_REVIEW_QUESTION_ID_PREFIX, REOPEN_ID_TAIL, approvalCallKey, askGateQuestionId, planReviewQuestionId, liveFrameCallKey, armedKeyFromQuestionId, } from './hitl/gateIdentity.js';
|
|
172
|
-
export { _resetArmedGateRegistryForTest, _setGateArmedWaitMsForTest, clearArmedGate, gateArmedWaitMs, notePlanReviewAnswered, onGateArmed, planReviewArmedKey, registerArmedGate, registerArmedGateFor, registerArmedGateFromQuestionId, waitForGateArmed, wasGateArmed, wasGateArmedFor, } from './hitl/armedGateRegistry.js';
|
|
172
|
+
export { _resetArmedGateRegistryForTest, _setGateArmedWaitMsForTest, clearArmedGate, gateArmedWaitMs, notePlanReviewAnswered, onGateArmed, planReviewArmedKey, registerArmedGate, registerArmedGateFor, registerArmedGateFromQuestionId, registerArmedGateFromQuestionIdFor, waitForGateArmed, wasGateArmed, wasGateArmedFor, } from './hitl/armedGateRegistry.js';
|
|
173
173
|
export * from './hitl/parkOwnership.js';
|
|
174
174
|
export * from './hitl/parkRowBirthWait.js';
|
|
175
175
|
export * from './hitl/approvalDecisionNoteAudit.js';
|
package/dist/index.js
CHANGED
|
@@ -155,7 +155,7 @@ export * from './coreValuePorts.js';
|
|
|
155
155
|
export * from './hitl/askGateWire.js';
|
|
156
156
|
export * from './hitl/planReviewWire.js';
|
|
157
157
|
export { PLAN_REVIEW_QUESTION_ID_PREFIX, REOPEN_ID_TAIL, approvalCallKey, askGateQuestionId, planReviewQuestionId, liveFrameCallKey, armedKeyFromQuestionId, } from './hitl/gateIdentity.js';
|
|
158
|
-
export { _resetArmedGateRegistryForTest, _setGateArmedWaitMsForTest, clearArmedGate, gateArmedWaitMs, notePlanReviewAnswered, onGateArmed, planReviewArmedKey, registerArmedGate, registerArmedGateFor, registerArmedGateFromQuestionId, waitForGateArmed, wasGateArmed, wasGateArmedFor, } from './hitl/armedGateRegistry.js';
|
|
158
|
+
export { _resetArmedGateRegistryForTest, _setGateArmedWaitMsForTest, clearArmedGate, gateArmedWaitMs, notePlanReviewAnswered, onGateArmed, planReviewArmedKey, registerArmedGate, registerArmedGateFor, registerArmedGateFromQuestionId, registerArmedGateFromQuestionIdFor, waitForGateArmed, wasGateArmed, wasGateArmedFor, } from './hitl/armedGateRegistry.js';
|
|
159
159
|
export * from './hitl/parkOwnership.js';
|
|
160
160
|
export * from './hitl/parkRowBirthWait.js';
|
|
161
161
|
export * from './hitl/approvalDecisionNoteAudit.js';
|
|
@@ -71,6 +71,8 @@ export interface TaskRequestOmission {
|
|
|
71
71
|
readonly cause: TaskRequestOmissionCause;
|
|
72
72
|
}
|
|
73
73
|
export declare function taskRequestOmissionCauseDetail(cause: unknown): string;
|
|
74
|
+
export declare const TASK_REQUEST_OMISSION_CAUSE_NOTICES: Readonly<Record<TaskRequestOmissionCause, string>>;
|
|
75
|
+
export declare function taskRequestOmissionCauseNotice(cause: unknown): string;
|
|
74
76
|
export interface TaskRequestAssembly {
|
|
75
77
|
readonly request: TaskRequestLike;
|
|
76
78
|
readonly omitted: readonly TaskRequestOmission[];
|
|
@@ -75,6 +75,18 @@ export function taskRequestOmissionCauseDetail(cause) {
|
|
|
75
75
|
const word = typeof cause === 'string' && cause.length > 0 ? cause : '(none)';
|
|
76
76
|
return `a cause this build does not know (${word}) — this build does not know this cause: receipt causes come from this build's own frozen vocabulary, so a word outside it was not produced here; check whatever supplied it`;
|
|
77
77
|
}
|
|
78
|
+
export const TASK_REQUEST_OMISSION_CAUSE_NOTICES = Object.freeze({
|
|
79
|
+
upstream_absent: 'Not sent with this request: this version has no way to send this setting in any request, so giving it or leaving it out makes no difference to what is sent.',
|
|
80
|
+
other_channel: 'Not sent from here: that part of the request belongs to a separate step, so what goes out for it, if anything, is decided there rather than by the value given here.',
|
|
81
|
+
off_lane: 'Not sent with this request: this kind of request does not carry this setting, so giving it or leaving it out makes no difference to what this request sends.',
|
|
82
|
+
not_live: 'Not sent with this request: the request was marked as not going to a live engine (for example an offline or test run), and this setting is only sent on requests that go to one.',
|
|
83
|
+
});
|
|
84
|
+
const TASK_REQUEST_OMISSION_UNKNOWN_CAUSE_NOTICE = 'Not sent with this request, for a reason this version does not recognize.';
|
|
85
|
+
export function taskRequestOmissionCauseNotice(cause) {
|
|
86
|
+
return typeof cause === 'string' && Object.hasOwn(TASK_REQUEST_OMISSION_CAUSE_NOTICES, cause)
|
|
87
|
+
? TASK_REQUEST_OMISSION_CAUSE_NOTICES[cause]
|
|
88
|
+
: TASK_REQUEST_OMISSION_UNKNOWN_CAUSE_NOTICE;
|
|
89
|
+
}
|
|
78
90
|
const row = (field) => ({ via: 'matrix', field });
|
|
79
91
|
const INPUT_KEY_ROUTES = {
|
|
80
92
|
objective: { via: 'always' },
|
|
@@ -11,12 +11,9 @@ export function noteBgOwnerAbsence(leg, taskId) {
|
|
|
11
11
|
noted.delete(oldest);
|
|
12
12
|
}
|
|
13
13
|
noted.add(key);
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
catch {
|
|
14
|
+
const delivered = hostLog('warn', `[subagent-owner] ${leg}: no host-run mapping for ${taskId} — not connecting (owner ledger absent ⇒ honest absence; active-run fallback removed per [4000] Q3)`);
|
|
15
|
+
if (!delivered)
|
|
18
16
|
noted.delete(key);
|
|
19
|
-
}
|
|
20
17
|
}
|
|
21
18
|
export function __resetBgOwnerAbsenceForTests() {
|
|
22
19
|
noted.clear();
|