@stigmer/server 3.38.1 → 3.38.3
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/domain/agentexecution/controller.js +7 -3
- package/dist/domain/agentexecution/controller.js.map +1 -1
- package/dist/domain/agentexecution/update-status.d.ts +9 -2
- package/dist/domain/agentexecution/update-status.d.ts.map +1 -1
- package/dist/domain/agentexecution/update-status.js +28 -5
- package/dist/domain/agentexecution/update-status.js.map +1 -1
- package/dist/domain/agentexecution/validate-thinking-mode.d.ts +31 -21
- package/dist/domain/agentexecution/validate-thinking-mode.d.ts.map +1 -1
- package/dist/domain/agentexecution/validate-thinking-mode.js +61 -18
- package/dist/domain/agentexecution/validate-thinking-mode.js.map +1 -1
- package/dist/domain/artifact/controller.d.ts.map +1 -1
- package/dist/domain/artifact/controller.js +9 -6
- package/dist/domain/artifact/controller.js.map +1 -1
- package/dist/domain/environment/controller.d.ts +2 -2
- package/dist/domain/environment/controller.js +7 -3
- package/dist/domain/environment/controller.js.map +1 -1
- package/dist/domain/environment/steps.d.ts +2 -1
- package/dist/domain/environment/steps.d.ts.map +1 -1
- package/dist/domain/environment/steps.js +10 -7
- package/dist/domain/environment/steps.js.map +1 -1
- package/dist/domain/workflow/registry/data/model-registry.json +23 -14
- package/dist/domain/workflow/registry/model-registry-store.d.ts +14 -3
- package/dist/domain/workflow/registry/model-registry-store.d.ts.map +1 -1
- package/dist/domain/workflow/registry/model-registry-store.js +14 -3
- package/dist/domain/workflow/registry/model-registry-store.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pipeline/errors.d.ts +12 -13
- package/dist/pipeline/errors.d.ts.map +1 -1
- package/dist/pipeline/errors.js +29 -3
- package/dist/pipeline/errors.js.map +1 -1
- package/package.json +6 -6
- package/src/domain/agentexecution/__tests__/run-gate.test.ts +42 -1
- package/src/domain/agentexecution/__tests__/update-status.test.ts +58 -2
- package/src/domain/agentexecution/__tests__/validate-thinking-mode.test.ts +209 -61
- package/src/domain/agentexecution/controller.ts +7 -3
- package/src/domain/agentexecution/update-status.ts +43 -3
- package/src/domain/agentexecution/validate-thinking-mode.ts +102 -47
- package/src/domain/artifact/__tests__/store-faults.test.ts +117 -0
- package/src/domain/artifact/controller.ts +12 -6
- package/src/domain/environment/__tests__/store-faults.test.ts +150 -0
- package/src/domain/environment/controller.ts +8 -5
- package/src/domain/environment/steps.ts +10 -7
- package/src/domain/workflow/registry/data/model-registry.json +23 -14
- package/src/domain/workflow/registry/model-registry-store.ts +16 -3
- package/src/index.ts +2 -0
- package/src/pipeline/__tests__/blind-not-found.test.ts +0 -3
- package/src/pipeline/__tests__/errors.test.ts +72 -0
- package/src/pipeline/errors.ts +42 -3
|
@@ -963,7 +963,8 @@
|
|
|
963
963
|
"vision" : true,
|
|
964
964
|
"streaming" : true,
|
|
965
965
|
"thinking" : false,
|
|
966
|
-
"adaptiveThinking" : true
|
|
966
|
+
"adaptiveThinking" : true,
|
|
967
|
+
"thinkingRequired" : true
|
|
967
968
|
}
|
|
968
969
|
}, {
|
|
969
970
|
"id" : "claude-haiku-4.5",
|
|
@@ -995,8 +996,9 @@
|
|
|
995
996
|
"toolUse" : true,
|
|
996
997
|
"vision" : true,
|
|
997
998
|
"streaming" : true,
|
|
998
|
-
"thinking" :
|
|
999
|
-
"adaptiveThinking" : false
|
|
999
|
+
"thinking" : true,
|
|
1000
|
+
"adaptiveThinking" : false,
|
|
1001
|
+
"thinkingRequired" : false
|
|
1000
1002
|
}
|
|
1001
1003
|
}, {
|
|
1002
1004
|
"id" : "claude-opus-4.5",
|
|
@@ -1017,7 +1019,7 @@
|
|
|
1017
1019
|
"effectiveAt" : "2026-05-03T00:00:00Z"
|
|
1018
1020
|
},
|
|
1019
1021
|
"contextWindowTokens" : 200000,
|
|
1020
|
-
"maxOutputTokens" :
|
|
1022
|
+
"maxOutputTokens" : 64000,
|
|
1021
1023
|
"tokenCounterMethod" : "anthropic_native",
|
|
1022
1024
|
"summarization" : {
|
|
1023
1025
|
"triggerThreshold" : 180000,
|
|
@@ -1029,7 +1031,8 @@
|
|
|
1029
1031
|
"vision" : true,
|
|
1030
1032
|
"streaming" : true,
|
|
1031
1033
|
"thinking" : true,
|
|
1032
|
-
"adaptiveThinking" : false
|
|
1034
|
+
"adaptiveThinking" : false,
|
|
1035
|
+
"thinkingRequired" : false
|
|
1033
1036
|
}
|
|
1034
1037
|
}, {
|
|
1035
1038
|
"id" : "claude-opus-4.6",
|
|
@@ -1050,7 +1053,7 @@
|
|
|
1050
1053
|
"effectiveAt" : "2026-05-03T00:00:00Z"
|
|
1051
1054
|
},
|
|
1052
1055
|
"contextWindowTokens" : 200000,
|
|
1053
|
-
"maxOutputTokens" :
|
|
1056
|
+
"maxOutputTokens" : 128000,
|
|
1054
1057
|
"tokenCounterMethod" : "anthropic_native",
|
|
1055
1058
|
"summarization" : {
|
|
1056
1059
|
"triggerThreshold" : 180000,
|
|
@@ -1062,7 +1065,8 @@
|
|
|
1062
1065
|
"vision" : true,
|
|
1063
1066
|
"streaming" : true,
|
|
1064
1067
|
"thinking" : false,
|
|
1065
|
-
"adaptiveThinking" : true
|
|
1068
|
+
"adaptiveThinking" : true,
|
|
1069
|
+
"thinkingRequired" : false
|
|
1066
1070
|
}
|
|
1067
1071
|
}, {
|
|
1068
1072
|
"id" : "claude-opus-4.7",
|
|
@@ -1096,7 +1100,8 @@
|
|
|
1096
1100
|
"vision" : true,
|
|
1097
1101
|
"streaming" : true,
|
|
1098
1102
|
"thinking" : false,
|
|
1099
|
-
"adaptiveThinking" : true
|
|
1103
|
+
"adaptiveThinking" : true,
|
|
1104
|
+
"thinkingRequired" : false
|
|
1100
1105
|
}
|
|
1101
1106
|
}, {
|
|
1102
1107
|
"id" : "claude-opus-4.8",
|
|
@@ -1130,7 +1135,8 @@
|
|
|
1130
1135
|
"vision" : true,
|
|
1131
1136
|
"streaming" : true,
|
|
1132
1137
|
"thinking" : false,
|
|
1133
|
-
"adaptiveThinking" : true
|
|
1138
|
+
"adaptiveThinking" : true,
|
|
1139
|
+
"thinkingRequired" : false
|
|
1134
1140
|
}
|
|
1135
1141
|
}, {
|
|
1136
1142
|
"id" : "claude-sonnet-4.5",
|
|
@@ -1151,7 +1157,7 @@
|
|
|
1151
1157
|
"effectiveAt" : "2026-05-03T00:00:00Z"
|
|
1152
1158
|
},
|
|
1153
1159
|
"contextWindowTokens" : 200000,
|
|
1154
|
-
"maxOutputTokens" :
|
|
1160
|
+
"maxOutputTokens" : 64000,
|
|
1155
1161
|
"tokenCounterMethod" : "anthropic_native",
|
|
1156
1162
|
"summarization" : {
|
|
1157
1163
|
"triggerThreshold" : 180000,
|
|
@@ -1163,7 +1169,8 @@
|
|
|
1163
1169
|
"vision" : true,
|
|
1164
1170
|
"streaming" : true,
|
|
1165
1171
|
"thinking" : true,
|
|
1166
|
-
"adaptiveThinking" : false
|
|
1172
|
+
"adaptiveThinking" : false,
|
|
1173
|
+
"thinkingRequired" : false
|
|
1167
1174
|
}
|
|
1168
1175
|
}, {
|
|
1169
1176
|
"id" : "claude-sonnet-4.6",
|
|
@@ -1195,8 +1202,9 @@
|
|
|
1195
1202
|
"toolUse" : true,
|
|
1196
1203
|
"vision" : true,
|
|
1197
1204
|
"streaming" : true,
|
|
1198
|
-
"thinking" :
|
|
1199
|
-
"adaptiveThinking" :
|
|
1205
|
+
"thinking" : false,
|
|
1206
|
+
"adaptiveThinking" : true,
|
|
1207
|
+
"thinkingRequired" : false
|
|
1200
1208
|
}
|
|
1201
1209
|
}, {
|
|
1202
1210
|
"id" : "claude-sonnet-5",
|
|
@@ -1230,7 +1238,8 @@
|
|
|
1230
1238
|
"vision" : true,
|
|
1231
1239
|
"streaming" : true,
|
|
1232
1240
|
"thinking" : false,
|
|
1233
|
-
"adaptiveThinking" : true
|
|
1241
|
+
"adaptiveThinking" : true,
|
|
1242
|
+
"thinkingRequired" : false
|
|
1234
1243
|
}
|
|
1235
1244
|
} ]
|
|
1236
1245
|
}
|
|
@@ -63,6 +63,19 @@ export const FAST_VARIANT_KEY = "fast";
|
|
|
63
63
|
*/
|
|
64
64
|
export const THINKING_CAPABILITY_KEY = "thinking";
|
|
65
65
|
|
|
66
|
+
/**
|
|
67
|
+
* The registry capability key of adaptive thinking, the second form that
|
|
68
|
+
* makes THINKING_MODE_ENABLED selectable (stigmer/stigmer#1280).
|
|
69
|
+
*/
|
|
70
|
+
export const ADAPTIVE_THINKING_CAPABILITY_KEY = "adaptiveThinking";
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* The registry capability key naming a model that always thinks and refuses
|
|
74
|
+
* a request to turn thinking off: an explicit THINKING_MODE_DISABLED is
|
|
75
|
+
* refused for it at create.
|
|
76
|
+
*/
|
|
77
|
+
export const THINKING_REQUIRED_CAPABILITY_KEY = "thinkingRequired";
|
|
78
|
+
|
|
66
79
|
export interface ModelRegistryStoreOptions {
|
|
67
80
|
/** Bundled build-time snapshot; MUST pass the sanity gate at boot. */
|
|
68
81
|
bundledDocument: string;
|
|
@@ -202,9 +215,9 @@ export class ModelRegistryStore implements ModelCatalogProvider {
|
|
|
202
215
|
* "thinking") true under the given harness. Capability flags are
|
|
203
216
|
* harness-scoped facts (they describe what works through that serving
|
|
204
217
|
* path), so there is no any-harness form: THINKING_MODE_ENABLED validates
|
|
205
|
-
* against the
|
|
206
|
-
*
|
|
207
|
-
*
|
|
218
|
+
* against the entry of the harness the execution runs on (oss#772,
|
|
219
|
+
* stigmer/stigmer#1280), because an id with an entry on both harnesses
|
|
220
|
+
* can declare different capabilities on each.
|
|
208
221
|
*/
|
|
209
222
|
hasCapabilityForHarness(
|
|
210
223
|
harness: string,
|
package/src/index.ts
CHANGED
|
@@ -293,12 +293,14 @@ export { RequestContext } from "./pipeline/request-context.js";
|
|
|
293
293
|
export {
|
|
294
294
|
abortedError,
|
|
295
295
|
alreadyExistsError,
|
|
296
|
+
ERROR_REASON_DOMAIN,
|
|
296
297
|
failedPreconditionError,
|
|
297
298
|
internalError,
|
|
298
299
|
invalidArgumentError,
|
|
299
300
|
notFoundError,
|
|
300
301
|
unavailableError,
|
|
301
302
|
} from "./pipeline/errors.js";
|
|
303
|
+
export type { RefusalReason } from "./pipeline/errors.js";
|
|
302
304
|
// The shared slug derivation (C2 Stage 3): extension-registered resource
|
|
303
305
|
// kinds derive slugs with the SAME generator both editions pin
|
|
304
306
|
// (ApiRequestResourceSlugGenerator parity) — the semantics live exactly
|
|
@@ -41,9 +41,6 @@ const PENDING: ReadonlyMap<string, number> = new Map([
|
|
|
41
41
|
["domain/agentchannel/controller.ts", 1],
|
|
42
42
|
["domain/agentinstance/controller.ts", 1],
|
|
43
43
|
["domain/agentshare/controller.ts", 1],
|
|
44
|
-
["domain/artifact/controller.ts", 1],
|
|
45
|
-
["domain/environment/controller.ts", 1],
|
|
46
|
-
["domain/environment/steps.ts", 1],
|
|
47
44
|
["domain/plugin/controller.ts", 1],
|
|
48
45
|
["domain/skill/controller.ts", 1],
|
|
49
46
|
["domain/workflow/controller.ts", 1],
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The structured-refusal seam on failedPreconditionError: a reason rides
|
|
3
|
+
* as a google.rpc.ErrorInfo detail beside the byte-pinned message, and
|
|
4
|
+
* reaches a client over a real Connect call. The SDK's getErrorReason
|
|
5
|
+
* reads the detail the same way the round trip below does, so a refusal
|
|
6
|
+
* this helper builds is one a console can branch on.
|
|
7
|
+
*/
|
|
8
|
+
import { create } from "@bufbuild/protobuf";
|
|
9
|
+
import {
|
|
10
|
+
Code,
|
|
11
|
+
ConnectError,
|
|
12
|
+
createClient,
|
|
13
|
+
createRouterTransport,
|
|
14
|
+
} from "@connectrpc/connect";
|
|
15
|
+
import { ErrorInfoSchema } from "@stigmer/protos/google/rpc/error_details_pb";
|
|
16
|
+
import { Health, HealthCheckRequestSchema } from "@stigmer/protos/grpc/health/v1/health_pb";
|
|
17
|
+
import { describe, expect, it } from "vitest";
|
|
18
|
+
|
|
19
|
+
import { ERROR_REASON_DOMAIN, failedPreconditionError } from "../errors.js";
|
|
20
|
+
|
|
21
|
+
describe("failedPreconditionError", () => {
|
|
22
|
+
it("carries no detail without a reason", () => {
|
|
23
|
+
const error = failedPreconditionError("Add a payment method first.");
|
|
24
|
+
|
|
25
|
+
expect(error.code).toBe(Code.FailedPrecondition);
|
|
26
|
+
expect(error.rawMessage).toBe("Add a payment method first.");
|
|
27
|
+
expect(error.findDetails(ErrorInfoSchema)).toEqual([]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("attaches the reason as an ErrorInfo detail and leaves the message as written", () => {
|
|
31
|
+
const error = failedPreconditionError("Teams need the Team plan or above.", {
|
|
32
|
+
reason: "PLAN_UPGRADE_REQUIRED",
|
|
33
|
+
metadata: { feature: "teams", org_id: "org_1" },
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(error.rawMessage).toBe("Teams need the Team plan or above.");
|
|
37
|
+
const [info] = error.findDetails(ErrorInfoSchema);
|
|
38
|
+
expect(info?.reason).toBe("PLAN_UPGRADE_REQUIRED");
|
|
39
|
+
expect(info?.domain).toBe(ERROR_REASON_DOMAIN);
|
|
40
|
+
expect(info?.metadata).toEqual({ feature: "teams", org_id: "org_1" });
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("delivers the detail to a client across a Connect call", async () => {
|
|
44
|
+
const transport = createRouterTransport((router) => {
|
|
45
|
+
router.service(Health, {
|
|
46
|
+
check: () => {
|
|
47
|
+
throw failedPreconditionError("A saved payment method is required.", {
|
|
48
|
+
reason: "PAYMENT_METHOD_REQUIRED",
|
|
49
|
+
metadata: { org_id: "org_2" },
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
list: () => ({ statuses: {} }),
|
|
53
|
+
watch: async function* () {},
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
const client = createClient(Health, transport);
|
|
57
|
+
|
|
58
|
+
const caught = await client.check(create(HealthCheckRequestSchema)).then(
|
|
59
|
+
() => undefined,
|
|
60
|
+
(error: unknown) => error,
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
expect(caught).toBeInstanceOf(ConnectError);
|
|
64
|
+
const error = caught as ConnectError;
|
|
65
|
+
expect(error.code).toBe(Code.FailedPrecondition);
|
|
66
|
+
expect(error.rawMessage).toBe("A saved payment method is required.");
|
|
67
|
+
const [info] = error.findDetails(ErrorInfoSchema);
|
|
68
|
+
expect(info?.reason).toBe("PAYMENT_METHOD_REQUIRED");
|
|
69
|
+
expect(info?.domain).toBe(ERROR_REASON_DOMAIN);
|
|
70
|
+
expect(info?.metadata).toEqual({ org_id: "org_2" });
|
|
71
|
+
});
|
|
72
|
+
});
|
package/src/pipeline/errors.ts
CHANGED
|
@@ -9,8 +9,31 @@
|
|
|
9
9
|
* text can carry storage-engine detail or filesystem paths, and on an
|
|
10
10
|
* anonymous surface that is information disclosure. The cause rides
|
|
11
11
|
* ConnectError.cause for server-side logs; it never crosses the wire.
|
|
12
|
+
*
|
|
13
|
+
* A refusal a client should branch on, rather than parse its copy, also
|
|
14
|
+
* carries a google.rpc.ErrorInfo detail (domain "stigmer.ai"), the
|
|
15
|
+
* platform's structured-refusal contract that the SDK's getErrorReason
|
|
16
|
+
* reads. Its reasons are documented on the refusing RPC's proto comment.
|
|
17
|
+
* The detail rides beside the message and never changes it, so the copy
|
|
18
|
+
* stays byte-pinned. A detail survives the pipeline and the transport
|
|
19
|
+
* boundary; only the visitor sanitizer, which rewrites an anonymous
|
|
20
|
+
* caller's error, drops it (interceptors/error-boundary.ts).
|
|
12
21
|
*/
|
|
22
|
+
import { create } from "@bufbuild/protobuf";
|
|
13
23
|
import { Code, ConnectError } from "@connectrpc/connect";
|
|
24
|
+
import { ErrorInfoSchema } from "@stigmer/protos/google/rpc/error_details_pb";
|
|
25
|
+
|
|
26
|
+
/** The domain every structured refusal reason is issued under. */
|
|
27
|
+
export const ERROR_REASON_DOMAIN = "stigmer.ai";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* A machine-readable refusal reason: an UPPER_SNAKE code and the facts a
|
|
31
|
+
* client needs to act on it, both documented on the refusing RPC.
|
|
32
|
+
*/
|
|
33
|
+
export interface RefusalReason {
|
|
34
|
+
readonly reason: string;
|
|
35
|
+
readonly metadata?: Readonly<Record<string, string>>;
|
|
36
|
+
}
|
|
14
37
|
|
|
15
38
|
/** Go NotFoundError: "%s not found: %s". */
|
|
16
39
|
export function notFoundError(resource: string, id: string): ConnectError {
|
|
@@ -32,10 +55,26 @@ export function alreadyExistsError(resource: string, id: string): ConnectError {
|
|
|
32
55
|
|
|
33
56
|
/**
|
|
34
57
|
* Go FailedPreconditionError — the system is not in a state required for
|
|
35
|
-
* the operation (vs AlreadyExists, which tells the caller to stop).
|
|
58
|
+
* the operation (vs AlreadyExists, which tells the caller to stop). With a
|
|
59
|
+
* reason, the refusal also carries it as an ErrorInfo detail.
|
|
36
60
|
*/
|
|
37
|
-
export function failedPreconditionError(
|
|
38
|
-
|
|
61
|
+
export function failedPreconditionError(
|
|
62
|
+
message: string,
|
|
63
|
+
reason?: RefusalReason,
|
|
64
|
+
): ConnectError {
|
|
65
|
+
if (reason === undefined) {
|
|
66
|
+
return new ConnectError(message, Code.FailedPrecondition);
|
|
67
|
+
}
|
|
68
|
+
return new ConnectError(message, Code.FailedPrecondition, undefined, [
|
|
69
|
+
{
|
|
70
|
+
desc: ErrorInfoSchema,
|
|
71
|
+
value: create(ErrorInfoSchema, {
|
|
72
|
+
reason: reason.reason,
|
|
73
|
+
domain: ERROR_REASON_DOMAIN,
|
|
74
|
+
metadata: { ...reason.metadata },
|
|
75
|
+
}),
|
|
76
|
+
},
|
|
77
|
+
]);
|
|
39
78
|
}
|
|
40
79
|
|
|
41
80
|
/** Go AbortedError — retryable conflict (e.g. an in-flight dedupe claim). */
|