@akagilnc/pi-workflow-roles 0.1.1883 → 0.1.1918
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/evidence-child-executor.js +153 -16
- package/dist/navigator-attendance.js +64 -29
- package/dist/public-cli/main.js +786 -373
- package/dist/reviewer-child-executor.js +1 -1
- package/dist/typed-provider-http.js +60 -0
- package/dist/upstream-error-testimony.js +19 -0
- package/package.json +1 -1
- package/scripts/build-package.mjs +2 -0
- package/src/evidence-child-executor.ts +177 -24
- package/src/factory-board.ts +60 -3
- package/src/navigator-attendance.ts +86 -33
- package/src/public-cli/cli.ts +96 -39
- package/src/public-cli/coder-run.ts +36 -11
- package/src/public-cli/collector-run.ts +8 -3
- package/src/public-cli/doctor-run.ts +1 -0
- package/src/public-cli/explicit-internal.ts +61 -19
- package/src/public-cli/fixer-run.ts +36 -11
- package/src/public-cli/invocation.ts +137 -101
- package/src/public-cli/judge-run.ts +39 -11
- package/src/public-cli/merger-run.ts +36 -11
- package/src/public-cli/reviewer-run.ts +35 -11
- package/src/public-cli/run-lifecycle.ts +89 -76
- package/src/public-cli/settlement.ts +256 -66
- package/src/reviewer-child-executor.ts +1 -1
- package/src/role-runtime.ts +18 -8
- package/src/ticket-frontmatter.ts +94 -0
- package/src/ticket-trajectory.ts +145 -5
- package/src/typed-provider-http.ts +99 -0
- package/src/upstream-error-testimony.ts +45 -0
|
@@ -11,6 +11,7 @@ import { AUDITOR_COMPLIANCE_FAILURE_ENTRY_TYPE, AUDITOR_PARENT_ATTEMPT_BINDING_E
|
|
|
11
11
|
import { wrapPackageOwnedToolDefinition } from "./package-owned-tool-idle.js";
|
|
12
12
|
import { createStreamIdleGuard, isStreamIdleTimeoutError } from "./stream-idle-guard.js";
|
|
13
13
|
import { createReceiptDeliveryPolicy, NO_RECEIPT_LIFECYCLE_ENTRY_TYPE, RECEIPT_DELIVERY_PROMPT } from "./receipt-delivery-policy.js";
|
|
14
|
+
import { hasUpstreamErrorTestimony, isNonSuccessHttpStatus, projectConfirmedRemotePayload, } from "./upstream-error-testimony.js";
|
|
14
15
|
// ── shared constants / types ──────────────────────────────────────────────
|
|
15
16
|
export const AUDITOR_TURN_LIMIT = 32;
|
|
16
17
|
export const DEFAULT_COMPLIANCE_IDLE_MAX_RETRIES = 2;
|
|
@@ -116,15 +117,23 @@ export async function createInheritedRuntime(options) {
|
|
|
116
117
|
void (async () => {
|
|
117
118
|
for (let attempt = 0;; attempt += 1) {
|
|
118
119
|
const idle = createStreamIdleGuard(options.signal === undefined ? {} : { parentSignal: options.signal });
|
|
120
|
+
// Typed HTTP status observed via onResponse — never inferred from prose.
|
|
121
|
+
let observedHttpStatus;
|
|
119
122
|
try {
|
|
120
123
|
const requestSignal = request?.signal;
|
|
121
124
|
const streamSignal = requestSignal === undefined
|
|
122
125
|
? idle.signal
|
|
123
126
|
: AbortSignal.any([idle.signal, requestSignal]);
|
|
127
|
+
const priorOnResponse = request?.onResponse;
|
|
124
128
|
const inheritedRequest = {
|
|
125
129
|
...(request ?? {}),
|
|
126
130
|
...(dispatch.auth.env === undefined ? {} : { env: dispatch.auth.env }),
|
|
127
131
|
signal: streamSignal,
|
|
132
|
+
onResponse: async (response, model) => {
|
|
133
|
+
if (typeof response?.status === "number")
|
|
134
|
+
observedHttpStatus = response.status;
|
|
135
|
+
await priorOnResponse?.(response, model);
|
|
136
|
+
},
|
|
128
137
|
};
|
|
129
138
|
if (options.runCompletion !== undefined) {
|
|
130
139
|
await new Promise((resolve) => setImmediate(resolve));
|
|
@@ -133,12 +142,12 @@ export async function createInheritedRuntime(options) {
|
|
|
133
142
|
const completed = await waitForStream(options.runCompletion(model, options.injectedSystemPrompt === undefined
|
|
134
143
|
? context
|
|
135
144
|
: { ...context, systemPrompt: options.injectedSystemPrompt }, inheritedRequest), streamSignal);
|
|
136
|
-
const response = {
|
|
145
|
+
const response = attachObservedHttpStatus({
|
|
137
146
|
...completed,
|
|
138
147
|
api: model.api,
|
|
139
148
|
provider: model.provider,
|
|
140
149
|
model: model.id,
|
|
141
|
-
};
|
|
150
|
+
}, observedHttpStatus);
|
|
142
151
|
if (response.stopReason === "error" || response.stopReason === "aborted") {
|
|
143
152
|
wrapped.push({ type: "error", reason: response.stopReason, error: response });
|
|
144
153
|
}
|
|
@@ -158,9 +167,9 @@ export async function createInheritedRuntime(options) {
|
|
|
158
167
|
break;
|
|
159
168
|
sawEvent = true;
|
|
160
169
|
idle.poke();
|
|
161
|
-
wrapped.push(next.value);
|
|
170
|
+
wrapped.push(enrichStreamEvent(next.value, observedHttpStatus));
|
|
162
171
|
}
|
|
163
|
-
const response = await waitForStream(source.result(), idle.signal);
|
|
172
|
+
const response = attachObservedHttpStatus(await waitForStream(source.result(), idle.signal), observedHttpStatus);
|
|
164
173
|
if (!sawEvent)
|
|
165
174
|
wrapped.end(response);
|
|
166
175
|
return;
|
|
@@ -190,6 +199,9 @@ export async function createInheritedRuntime(options) {
|
|
|
190
199
|
continue;
|
|
191
200
|
}
|
|
192
201
|
state.streamFailure = failure;
|
|
202
|
+
const projected = projectStructuredRemote(failure);
|
|
203
|
+
// Prefer structured fields on the thrown failure; fall back to onResponse observation.
|
|
204
|
+
const httpStatus = projected.httpStatus ?? numericHttpStatus(observedHttpStatus);
|
|
193
205
|
const response = {
|
|
194
206
|
role: "assistant",
|
|
195
207
|
content: [],
|
|
@@ -198,8 +210,14 @@ export async function createInheritedRuntime(options) {
|
|
|
198
210
|
model: model.id,
|
|
199
211
|
usage: emptyUsage(),
|
|
200
212
|
stopReason: "error",
|
|
213
|
+
// Preserve the held failure message bytes — do not rewrite.
|
|
201
214
|
errorMessage: failure instanceof Error ? failure.message : String(failure),
|
|
202
215
|
timestamp: Date.now(),
|
|
216
|
+
...(projected.diagnostics === undefined ? {} : { diagnostics: projected.diagnostics }),
|
|
217
|
+
...(httpStatus === undefined ? {} : { status: httpStatus, statusCode: httpStatus }),
|
|
218
|
+
...(projected.body === undefined ? {} : { body: projected.body }),
|
|
219
|
+
...(projected.code === undefined ? {} : { code: projected.code }),
|
|
220
|
+
...(projected.errno === undefined ? {} : { errno: projected.errno }),
|
|
203
221
|
};
|
|
204
222
|
wrapped.push({ type: "error", reason: "error", error: response });
|
|
205
223
|
wrapped.end(response);
|
|
@@ -270,6 +288,104 @@ export async function createInheritedRuntime(options) {
|
|
|
270
288
|
runtime.registerNativeProvider(provider);
|
|
271
289
|
return state;
|
|
272
290
|
}
|
|
291
|
+
function numericHttpStatus(value) {
|
|
292
|
+
return isNonSuccessHttpStatus(value) ? value : undefined;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Cause-chain reader over the shared upstream-testimony authority.
|
|
296
|
+
* Shape walking stays here; testimony + confirmed-remote payload rules are shared.
|
|
297
|
+
*/
|
|
298
|
+
function projectStructuredRemote(error) {
|
|
299
|
+
let httpStatus;
|
|
300
|
+
let diagnostics;
|
|
301
|
+
let body;
|
|
302
|
+
let code;
|
|
303
|
+
let errno;
|
|
304
|
+
let cursor = error;
|
|
305
|
+
const seen = new Set();
|
|
306
|
+
while (typeof cursor === "object" && cursor !== null && !seen.has(cursor)) {
|
|
307
|
+
seen.add(cursor);
|
|
308
|
+
const record = cursor;
|
|
309
|
+
const nodeStatus = numericHttpStatus(record.statusCode)
|
|
310
|
+
?? numericHttpStatus(record.status)
|
|
311
|
+
?? numericHttpStatus(record.httpStatus);
|
|
312
|
+
const nodeDiagnostics = Array.isArray(record.diagnostics) && record.diagnostics.length > 0
|
|
313
|
+
? record.diagnostics
|
|
314
|
+
: undefined;
|
|
315
|
+
const nodeHasTestimony = hasUpstreamErrorTestimony({
|
|
316
|
+
...(nodeStatus === undefined ? {} : { httpStatus: nodeStatus }),
|
|
317
|
+
...(nodeDiagnostics === undefined ? {} : { diagnostics: nodeDiagnostics }),
|
|
318
|
+
});
|
|
319
|
+
if (httpStatus === undefined && nodeStatus !== undefined)
|
|
320
|
+
httpStatus = nodeStatus;
|
|
321
|
+
if (diagnostics === undefined && nodeDiagnostics !== undefined)
|
|
322
|
+
diagnostics = nodeDiagnostics;
|
|
323
|
+
// Payload only from confirmed-remote nodes — never arbitrary local Error.code.
|
|
324
|
+
if (nodeHasTestimony) {
|
|
325
|
+
const payload = projectConfirmedRemotePayload(record);
|
|
326
|
+
if (body === undefined && payload.body !== undefined)
|
|
327
|
+
body = payload.body;
|
|
328
|
+
if (code === undefined && payload.code !== undefined)
|
|
329
|
+
code = payload.code;
|
|
330
|
+
if (errno === undefined && payload.errno !== undefined)
|
|
331
|
+
errno = payload.errno;
|
|
332
|
+
}
|
|
333
|
+
cursor = record.cause;
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
hasTestimony: hasUpstreamErrorTestimony({
|
|
337
|
+
...(httpStatus === undefined ? {} : { httpStatus }),
|
|
338
|
+
...(diagnostics === undefined ? {} : { diagnostics }),
|
|
339
|
+
}),
|
|
340
|
+
...(httpStatus === undefined ? {} : { httpStatus }),
|
|
341
|
+
...(diagnostics === undefined ? {} : { diagnostics }),
|
|
342
|
+
...(body === undefined ? {} : { body }),
|
|
343
|
+
...(code === undefined ? {} : { code }),
|
|
344
|
+
...(errno === undefined ? {} : { errno }),
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Attach a directly observed HTTP status onto an error/aborted assistant message.
|
|
349
|
+
* Does not invent status from errorMessage prose; skips when already held.
|
|
350
|
+
*/
|
|
351
|
+
function attachObservedHttpStatus(message, observedHttpStatus) {
|
|
352
|
+
if (observedHttpStatus === undefined)
|
|
353
|
+
return message;
|
|
354
|
+
if (message.stopReason !== "error" && message.stopReason !== "aborted")
|
|
355
|
+
return message;
|
|
356
|
+
if (numericHttpStatus(observedHttpStatus) === undefined)
|
|
357
|
+
return message;
|
|
358
|
+
if (projectStructuredRemote(message).httpStatus !== undefined)
|
|
359
|
+
return message;
|
|
360
|
+
return Object.assign(message, {
|
|
361
|
+
status: observedHttpStatus,
|
|
362
|
+
statusCode: observedHttpStatus,
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
function enrichStreamEvent(event, observedHttpStatus) {
|
|
366
|
+
if (observedHttpStatus === undefined || event === null || typeof event !== "object")
|
|
367
|
+
return event;
|
|
368
|
+
const record = event;
|
|
369
|
+
if (record.type === "error" && record.error !== null && typeof record.error === "object") {
|
|
370
|
+
return {
|
|
371
|
+
...record,
|
|
372
|
+
error: attachObservedHttpStatus(record.error, observedHttpStatus),
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
if (record.type === "done" && record.message !== null && typeof record.message === "object") {
|
|
376
|
+
return {
|
|
377
|
+
...record,
|
|
378
|
+
message: attachObservedHttpStatus(record.message, observedHttpStatus),
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
if (record.partial !== null && typeof record.partial === "object") {
|
|
382
|
+
return {
|
|
383
|
+
...record,
|
|
384
|
+
partial: attachObservedHttpStatus(record.partial, observedHttpStatus),
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
return event;
|
|
388
|
+
}
|
|
273
389
|
function classifiedError(error, evidenceChildFailure) {
|
|
274
390
|
const diagnostic = typeof error === "object" && error !== null && typeof error.errorMessage === "string"
|
|
275
391
|
? error.errorMessage
|
|
@@ -279,7 +395,9 @@ function classifiedError(error, evidenceChildFailure) {
|
|
|
279
395
|
: Object.assign(new Error(diagnostic, { cause: error }), { evidenceChildOriginal: error });
|
|
280
396
|
const classification = "evidenceChildFailure" in wrapped
|
|
281
397
|
? wrapped.evidenceChildFailure
|
|
282
|
-
: evidenceChildFailure
|
|
398
|
+
: evidenceChildFailure === "provider" && !projectStructuredRemote(error).hasTestimony
|
|
399
|
+
? "unknown"
|
|
400
|
+
: evidenceChildFailure;
|
|
283
401
|
return Object.assign(wrapped, { evidenceChildFailure: classification });
|
|
284
402
|
}
|
|
285
403
|
function emptyUsage() {
|
|
@@ -368,10 +486,14 @@ export async function executeEvidenceChild(workspace, prompt, context, options =
|
|
|
368
486
|
const lastAssistant = [...session.messages]
|
|
369
487
|
.reverse()
|
|
370
488
|
.find((message) => message.role === "assistant");
|
|
371
|
-
|
|
372
|
-
|
|
489
|
+
// error|aborted assistant stops share the upstream-testimony rule: provider only
|
|
490
|
+
// with direct HTTP/SDK testimony, otherwise existing unknown. child is reserved
|
|
491
|
+
// for real local child/report failures (no assistant / blank report / cleanup).
|
|
492
|
+
if (lastAssistant?.role === "assistant"
|
|
493
|
+
&& (lastAssistant.stopReason === "error" || lastAssistant.stopReason === "aborted")) {
|
|
494
|
+
throw classifiedError(new Error(lastAssistant.errorMessage ?? "", { cause: lastAssistant }), projectStructuredRemote(lastAssistant).hasTestimony ? "provider" : "unknown");
|
|
373
495
|
}
|
|
374
|
-
if (lastAssistant?.role !== "assistant"
|
|
496
|
+
if (lastAssistant?.role !== "assistant") {
|
|
375
497
|
throw classifiedError(new Error("Evidence child child terminated without a report", {
|
|
376
498
|
cause: lastAssistant ?? session.messages,
|
|
377
499
|
}), "child");
|
|
@@ -721,15 +843,30 @@ export async function executeAuditorChild(options) {
|
|
|
721
843
|
catch (retentionFailure) {
|
|
722
844
|
if (response.stopReason !== "error")
|
|
723
845
|
throw retentionFailure;
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
846
|
+
// Do not trim/rewrite the held errorMessage bytes.
|
|
847
|
+
const diagnostic = typeof response.errorMessage === "string" && response.errorMessage.trim() !== ""
|
|
848
|
+
? response.errorMessage
|
|
849
|
+
: undefined;
|
|
850
|
+
const projected = projectStructuredRemote(response);
|
|
851
|
+
const failure = new Error(diagnostic ?? "", { cause: retentionFailure });
|
|
852
|
+
if (projected.hasTestimony && (response.model || response.provider)) {
|
|
853
|
+
failure.name = response.model || response.provider || "Error";
|
|
854
|
+
failure.failureCode = response.provider || response.model;
|
|
855
|
+
}
|
|
856
|
+
failure.knownCause = projected.hasTestimony ? "provider" : "unrecognized";
|
|
728
857
|
const retentionError = retentionFailure instanceof Error ? retentionFailure : undefined;
|
|
729
858
|
const retentionCause = retentionError?.cause;
|
|
730
859
|
failure.details = {
|
|
731
|
-
...(
|
|
732
|
-
...(response.
|
|
860
|
+
...(diagnostic === undefined ? {} : { errorMessage: diagnostic }),
|
|
861
|
+
...(projected.hasTestimony && response.provider ? { provider: response.provider } : {}),
|
|
862
|
+
...(projected.hasTestimony && response.model ? { model: response.model } : {}),
|
|
863
|
+
...(response.api ? { api: response.api } : {}),
|
|
864
|
+
...(response.rawStopReason ? { rawStopReason: response.rawStopReason } : {}),
|
|
865
|
+
...(projected.httpStatus === undefined ? {} : { httpStatus: projected.httpStatus }),
|
|
866
|
+
...(projected.diagnostics === undefined ? {} : { diagnostics: projected.diagnostics }),
|
|
867
|
+
...(projected.body === undefined ? {} : { body: projected.body }),
|
|
868
|
+
...(projected.code === undefined ? {} : { code: projected.code }),
|
|
869
|
+
...(projected.errno === undefined ? {} : { errno: projected.errno }),
|
|
733
870
|
retentionFailure: {
|
|
734
871
|
name: retentionError?.name ?? typeof retentionFailure,
|
|
735
872
|
message: retentionError?.message ?? String(retentionFailure),
|
|
@@ -756,8 +893,8 @@ export async function executeAuditorChild(options) {
|
|
|
756
893
|
parent: binding.parent,
|
|
757
894
|
failure: {
|
|
758
895
|
cause: failure.knownCause,
|
|
759
|
-
identity: { name: failure.name, code: failure.failureCode },
|
|
760
|
-
diagnostic: failure.message,
|
|
896
|
+
...(failure.failureCode === undefined ? {} : { identity: { name: failure.name, code: failure.failureCode } }),
|
|
897
|
+
...(failure.message === "" ? {} : { diagnostic: failure.message }),
|
|
761
898
|
details: failure.details,
|
|
762
899
|
},
|
|
763
900
|
});
|
|
@@ -16,6 +16,12 @@ import { renderPublicAkRoleCommand } from "./public-command-renderer.js";
|
|
|
16
16
|
import { issueRoot, subjectPath } from "./work-subject-identity.js";
|
|
17
17
|
import { wrapPackageOwnedToolDefinition } from "./package-owned-tool-idle.js";
|
|
18
18
|
import { createReceiptDeliveryPolicy, NO_RECEIPT_LIFECYCLE_ENTRY_TYPE, RECEIPT_DELIVERY_PROMPT } from "./receipt-delivery-policy.js";
|
|
19
|
+
import { recordTypedProviderHttpStatus } from "./typed-provider-http.js";
|
|
20
|
+
import {
|
|
21
|
+
hasUpstreamErrorTestimony,
|
|
22
|
+
isNonSuccessHttpStatus,
|
|
23
|
+
projectConfirmedRemotePayload
|
|
24
|
+
} from "./upstream-error-testimony.js";
|
|
19
25
|
const NAVIGATOR_EVENT_TYPE = "ak-navigator-attendance";
|
|
20
26
|
const NAVIGATOR_PREPARE_TOOL_NAME = "ak_navigator_prepare";
|
|
21
27
|
const NAVIGATOR_DEFAULT_MODEL = "openai-codex/gpt-5.6-luna:max";
|
|
@@ -810,19 +816,26 @@ function createNativeNavigatorSessionFactory(defaultModelSettingPath = navigator
|
|
|
810
816
|
}
|
|
811
817
|
assignProviderFailure(navigatorProviderFailureFromStatus(status));
|
|
812
818
|
};
|
|
813
|
-
const
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
+
const projectHeldUpstream = (error) => {
|
|
820
|
+
if (!exactRecord(error)) return {};
|
|
821
|
+
const status = typeof error.statusCode === "number" ? error.statusCode : typeof error.status === "number" ? error.status : typeof error.httpStatus === "number" ? error.httpStatus : void 0;
|
|
822
|
+
const httpStatus = isNonSuccessHttpStatus(status) ? status : void 0;
|
|
823
|
+
const diagnostics = Array.isArray(error.diagnostics) && error.diagnostics.length > 0 ? error.diagnostics : void 0;
|
|
824
|
+
const testimony = hasUpstreamErrorTestimony({
|
|
825
|
+
...httpStatus === void 0 ? {} : { httpStatus },
|
|
826
|
+
...diagnostics === void 0 ? {} : { diagnostics }
|
|
827
|
+
});
|
|
828
|
+
return {
|
|
829
|
+
...httpStatus === void 0 ? {} : { statusCode: httpStatus, status: httpStatus },
|
|
830
|
+
...diagnostics === void 0 ? {} : { diagnostics },
|
|
831
|
+
...testimony ? projectConfirmedRemotePayload(error) : {}
|
|
832
|
+
};
|
|
819
833
|
};
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
return id;
|
|
834
|
+
const retainUpstreamMessage = (error) => {
|
|
835
|
+
if (!("navigatorFailure" in error)) return error;
|
|
836
|
+
const copy = { ...error };
|
|
837
|
+
delete copy.navigatorFailure;
|
|
838
|
+
return copy;
|
|
826
839
|
};
|
|
827
840
|
const setupFailureMessage = (error) => ({
|
|
828
841
|
role: "assistant",
|
|
@@ -833,22 +846,38 @@ function createNativeNavigatorSessionFactory(defaultModelSettingPath = navigator
|
|
|
833
846
|
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
|
|
834
847
|
stopReason: "error",
|
|
835
848
|
errorMessage: error instanceof Error ? error.message : String(error),
|
|
836
|
-
|
|
837
|
-
|
|
849
|
+
timestamp: Date.now(),
|
|
850
|
+
...projectHeldUpstream(error)
|
|
838
851
|
});
|
|
852
|
+
const persistNavigatorHttpObservation = async (status, model2) => {
|
|
853
|
+
const runDir = process.env.AK_ROLE_RUN_DIR;
|
|
854
|
+
if (typeof runDir !== "string" || runDir.trim() === "") return;
|
|
855
|
+
const provider2 = exactRecord(model2) && typeof model2.provider === "string" && model2.provider.trim() !== "" ? model2.provider : void 0;
|
|
856
|
+
if (provider2 === void 0) return;
|
|
857
|
+
await recordTypedProviderHttpStatus(runDir, { httpStatus: status, provider: provider2 });
|
|
858
|
+
};
|
|
839
859
|
const instrumentProvider = (sourceProvider) => {
|
|
840
|
-
const instrumentStreamOptions = (options) => {
|
|
860
|
+
const instrumentStreamOptions = (options, observedStatus) => {
|
|
841
861
|
const record = exactRecord(options) ? options : {};
|
|
842
862
|
const previous = typeof record.onResponse === "function" ? record.onResponse : void 0;
|
|
843
863
|
return {
|
|
844
864
|
...record,
|
|
845
865
|
onResponse: async (response, model2) => {
|
|
866
|
+
observedStatus.value = response.status;
|
|
846
867
|
classifyProviderResponseStatus(response.status);
|
|
868
|
+
await persistNavigatorHttpObservation(response.status, model2);
|
|
847
869
|
await previous?.(response, model2);
|
|
848
870
|
}
|
|
849
871
|
};
|
|
850
872
|
};
|
|
851
|
-
const
|
|
873
|
+
const withObservedStatus = (message, observedStatus) => {
|
|
874
|
+
if (observedStatus === void 0 || observedStatus >= 200 && observedStatus < 300) return message;
|
|
875
|
+
if (typeof message.statusCode === "number" || typeof message.status === "number" || typeof message.httpStatus === "number") {
|
|
876
|
+
return message;
|
|
877
|
+
}
|
|
878
|
+
return { ...message, statusCode: observedStatus, status: observedStatus };
|
|
879
|
+
};
|
|
880
|
+
const wrapProviderStream = (source, observedStatus) => {
|
|
852
881
|
const wrapped = createAssistantMessageEventStream();
|
|
853
882
|
void (async () => {
|
|
854
883
|
let result;
|
|
@@ -859,13 +888,13 @@ function createNativeNavigatorSessionFactory(defaultModelSettingPath = navigator
|
|
|
859
888
|
sawTerminal = true;
|
|
860
889
|
if (event.type === "done" && exactRecord(event.message)) {
|
|
861
890
|
assignProviderFailure(navigatorProviderFailureFromDiagnostics(event.message.diagnostics));
|
|
862
|
-
result =
|
|
891
|
+
result = withObservedStatus(retainUpstreamMessage(event.message), observedStatus.value);
|
|
863
892
|
wrapped.push({ ...event, message: result });
|
|
864
893
|
continue;
|
|
865
894
|
}
|
|
866
895
|
if (event.type === "error" && exactRecord(event.error)) {
|
|
867
896
|
classifyProviderStreamError(event.error);
|
|
868
|
-
result =
|
|
897
|
+
result = withObservedStatus(retainUpstreamMessage(event.error), observedStatus.value);
|
|
869
898
|
wrapped.push({ ...event, error: result });
|
|
870
899
|
continue;
|
|
871
900
|
}
|
|
@@ -874,21 +903,22 @@ function createNativeNavigatorSessionFactory(defaultModelSettingPath = navigator
|
|
|
874
903
|
}
|
|
875
904
|
if (sawTerminal) {
|
|
876
905
|
const terminal = await source.result();
|
|
877
|
-
if (result === void 0 && exactRecord(terminal))
|
|
878
|
-
|
|
906
|
+
if (result === void 0 && exactRecord(terminal)) {
|
|
907
|
+
result = withObservedStatus(retainUpstreamMessage(terminal), observedStatus.value);
|
|
908
|
+
} else if (result === void 0) result = terminal;
|
|
879
909
|
}
|
|
880
910
|
} catch (error) {
|
|
881
911
|
classifyProviderStreamError(error);
|
|
882
|
-
if (providerFailure === void 0) providerFailure = { source: "
|
|
912
|
+
if (providerFailure === void 0) providerFailure = { source: "unknown", cause: "unknown" };
|
|
883
913
|
if (!sawTerminal) {
|
|
884
|
-
const message = setupFailureMessage(error);
|
|
914
|
+
const message = withObservedStatus(setupFailureMessage(error), observedStatus.value);
|
|
885
915
|
wrapped.push({ type: "error", reason: "error", error: message });
|
|
886
916
|
result = message;
|
|
887
917
|
sawTerminal = true;
|
|
888
918
|
}
|
|
889
919
|
} finally {
|
|
890
920
|
if (!sawTerminal) {
|
|
891
|
-
if (providerFailure === void 0) providerFailure = { source: "
|
|
921
|
+
if (providerFailure === void 0) providerFailure = { source: "unknown", cause: "unknown" };
|
|
892
922
|
const message = setupFailureMessage(new Error("Navigator provider produced no response"));
|
|
893
923
|
wrapped.push({ type: "error", reason: "error", error: message });
|
|
894
924
|
result = message;
|
|
@@ -901,11 +931,12 @@ function createNativeNavigatorSessionFactory(defaultModelSettingPath = navigator
|
|
|
901
931
|
};
|
|
902
932
|
const invokeInstrumentedStream = (invoke) => {
|
|
903
933
|
providerFailure = void 0;
|
|
934
|
+
const observedStatus = {};
|
|
904
935
|
try {
|
|
905
|
-
return wrapProviderStream(invoke());
|
|
936
|
+
return wrapProviderStream(invoke(observedStatus), observedStatus);
|
|
906
937
|
} catch (error) {
|
|
907
938
|
classifyProviderStreamError(error);
|
|
908
|
-
if (providerFailure === void 0) providerFailure = { source: "
|
|
939
|
+
if (providerFailure === void 0) providerFailure = { source: "unknown", cause: "unknown" };
|
|
909
940
|
const wrapped = createAssistantMessageEventStream();
|
|
910
941
|
const message = setupFailureMessage(error);
|
|
911
942
|
queueMicrotask(() => {
|
|
@@ -918,12 +949,16 @@ function createNativeNavigatorSessionFactory(defaultModelSettingPath = navigator
|
|
|
918
949
|
return {
|
|
919
950
|
...sourceProvider,
|
|
920
951
|
stream(model2, streamContext, options) {
|
|
921
|
-
|
|
922
|
-
|
|
952
|
+
return invokeInstrumentedStream((observedStatus) => {
|
|
953
|
+
const instrumented = instrumentStreamOptions(options, observedStatus);
|
|
954
|
+
return sourceProvider.stream(model2, streamContext, instrumented);
|
|
955
|
+
});
|
|
923
956
|
},
|
|
924
957
|
streamSimple(model2, streamContext, options) {
|
|
925
|
-
|
|
926
|
-
|
|
958
|
+
return invokeInstrumentedStream((observedStatus) => {
|
|
959
|
+
const instrumented = instrumentStreamOptions(options, observedStatus);
|
|
960
|
+
return sourceProvider.streamSimple(model2, streamContext, instrumented);
|
|
961
|
+
});
|
|
927
962
|
}
|
|
928
963
|
};
|
|
929
964
|
};
|