@stigmer/server 3.38.2 → 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/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/pipeline/__tests__/blind-not-found.test.ts +0 -3
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pins the store-fault contract the artifact load by id shares: a typed
|
|
3
|
+
* ResourceNotFoundError answers NotFound with the domain's pinned Go copy
|
|
4
|
+
* (`Artifact not found: <id>`), and any other store failure is an
|
|
5
|
+
* infrastructure fault answered as a sanitized Internal, never a NotFound
|
|
6
|
+
* that tells a client a run's output does not exist (stigmer/stigmer#1345).
|
|
7
|
+
*
|
|
8
|
+
* The surfaces: the three direct handlers that load through
|
|
9
|
+
* loadArtifactOrNotFound, delete, getDownloadUrl and getContent, each
|
|
10
|
+
* reached through the registered handler on an in-process router. All three
|
|
11
|
+
* load before they authorize (stigmer#224), and a fault answered as Internal
|
|
12
|
+
* says nothing about whether the artifact exists. The composed suites reach
|
|
13
|
+
* only a real store, which cannot fail selectively, so each surface runs here
|
|
14
|
+
* against a store whose read throws. Artifact storage is untouchable: a load
|
|
15
|
+
* that fails must stop the call before any blob read or URL mint.
|
|
16
|
+
*
|
|
17
|
+
* Out of scope: the NotFound copy itself (wire contract, pinned by the
|
|
18
|
+
* artifact conformance suite) and create's best-effort org derivation
|
|
19
|
+
* (stigmer/stigmer#1369).
|
|
20
|
+
*/
|
|
21
|
+
import type { Client, ConnectError } from "@connectrpc/connect";
|
|
22
|
+
import { Code, createClient, createRouterTransport } from "@connectrpc/connect";
|
|
23
|
+
import { describe, expect, it } from "vitest";
|
|
24
|
+
|
|
25
|
+
import { ArtifactCommandController } from "@stigmer/protos/ai/stigmer/agentic/artifact/v1/command_pb";
|
|
26
|
+
import { ArtifactQueryController } from "@stigmer/protos/ai/stigmer/agentic/artifact/v1/query_pb";
|
|
27
|
+
|
|
28
|
+
import { createLogger } from "../../../boot/logger.js";
|
|
29
|
+
import { createVerifierChainInterceptor } from "../../../pipeline/interceptors/auth.js";
|
|
30
|
+
import {
|
|
31
|
+
errorOf,
|
|
32
|
+
failingStore,
|
|
33
|
+
untouchable,
|
|
34
|
+
} from "../../../pipeline/__tests__/support.js";
|
|
35
|
+
import { newPermissiveSingleTeamAuthorizer } from "../../../pipeline/steps/authorize.js";
|
|
36
|
+
import { ResourceNotFoundError } from "../../../store/interface.js";
|
|
37
|
+
import type { Store } from "../../../store/interface.js";
|
|
38
|
+
|
|
39
|
+
import { registerArtifactServices } from "../controller.js";
|
|
40
|
+
|
|
41
|
+
const silentLogger = createLogger({
|
|
42
|
+
level: "error",
|
|
43
|
+
pretty: false,
|
|
44
|
+
write: () => {},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const ARTIFACT_ID = "art_storefault";
|
|
48
|
+
|
|
49
|
+
const NOT_FOUND_COPY = `Artifact not found: ${ARTIFACT_ID}`;
|
|
50
|
+
const LOAD_FAULT_COPY = "failed to load artifact";
|
|
51
|
+
|
|
52
|
+
const MISSING = (): Error =>
|
|
53
|
+
new ResourceNotFoundError(`artifact/${ARTIFACT_ID}`);
|
|
54
|
+
const LOCKED = (): Error => new Error("SQLITE_BUSY: database is locked");
|
|
55
|
+
|
|
56
|
+
interface ArtifactClients {
|
|
57
|
+
readonly command: Client<typeof ArtifactCommandController>;
|
|
58
|
+
readonly query: Client<typeof ArtifactQueryController>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The registered handlers on an in-process router (`artifact.test.ts`'s
|
|
63
|
+
* harness): the verifier chain stamps the trusted-local caller, each handler
|
|
64
|
+
* checks its id, and the load is the first read of the store.
|
|
65
|
+
*/
|
|
66
|
+
function artifactClients(store: Store): ArtifactClients {
|
|
67
|
+
const transport = createRouterTransport(
|
|
68
|
+
(router) => {
|
|
69
|
+
registerArtifactServices(router, {
|
|
70
|
+
store,
|
|
71
|
+
artifactStorage: untouchable("artifactStorage"),
|
|
72
|
+
logger: silentLogger,
|
|
73
|
+
authorizer: newPermissiveSingleTeamAuthorizer(),
|
|
74
|
+
});
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
router: {
|
|
78
|
+
interceptors: [createVerifierChainInterceptor([], [], silentLogger)],
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
);
|
|
82
|
+
return {
|
|
83
|
+
command: createClient(ArtifactCommandController, transport),
|
|
84
|
+
query: createClient(ArtifactQueryController, transport),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const SURFACES: ReadonlyArray<
|
|
89
|
+
readonly [string, (clients: ArtifactClients) => Promise<unknown>]
|
|
90
|
+
> = [
|
|
91
|
+
["delete", ({ command }) => command.delete({ value: ARTIFACT_ID })],
|
|
92
|
+
[
|
|
93
|
+
"getDownloadUrl",
|
|
94
|
+
({ query }) => query.getDownloadUrl({ value: ARTIFACT_ID }),
|
|
95
|
+
],
|
|
96
|
+
["getContent", ({ query }) => query.getContent({ artifactId: ARTIFACT_ID })],
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
describe.each(SURFACES)("%s — loadArtifactOrNotFound", (_name, call) => {
|
|
100
|
+
function surfaceError(store: Store): Promise<ConnectError> {
|
|
101
|
+
return errorOf(() => call(artifactClients(store)));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
it("a missing artifact answers NotFound with the domain's copy", async () => {
|
|
105
|
+
const error = await surfaceError(failingStore(MISSING()));
|
|
106
|
+
|
|
107
|
+
expect(error.code).toBe(Code.NotFound);
|
|
108
|
+
expect(error.rawMessage).toBe(NOT_FOUND_COPY);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("any other store failure answers a sanitized Internal", async () => {
|
|
112
|
+
const error = await surfaceError(failingStore(LOCKED()));
|
|
113
|
+
|
|
114
|
+
expect(error.code).toBe(Code.Internal);
|
|
115
|
+
expect(error.rawMessage).toBe(LOAD_FAULT_COPY);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* storage_state transition rather than the hard-delete pipeline; only
|
|
10
10
|
* get/listByExecution ride pipelines. Proven by
|
|
11
11
|
* artifact.conformance.test.ts (CONFORMANCE_TARGET=local, incl. the
|
|
12
|
-
* file-server lane)
|
|
12
|
+
* file-server lane), __tests__/artifact.test.ts and
|
|
13
|
+
* __tests__/store-faults.test.ts.
|
|
13
14
|
*
|
|
14
15
|
* Go tolerates a nil ArtifactStorage (two-phase wiring) and answers
|
|
15
16
|
* Internal "artifact storage not configured"; the TS composition root
|
|
@@ -79,6 +80,7 @@ import {
|
|
|
79
80
|
newLoadTargetStep,
|
|
80
81
|
} from "../../pipeline/steps/load-target.js";
|
|
81
82
|
import { newValidateProtoStep } from "../../pipeline/steps/validation.js";
|
|
83
|
+
import { ResourceNotFoundError } from "../../store/interface.js";
|
|
82
84
|
import type { Store } from "../../store/interface.js";
|
|
83
85
|
import type { ListIndexRow } from "../../store/list-index.js";
|
|
84
86
|
import { artifactListIndex } from "./list-index.js";
|
|
@@ -649,7 +651,7 @@ async function getContent(
|
|
|
649
651
|
});
|
|
650
652
|
}
|
|
651
653
|
|
|
652
|
-
/** Load by id
|
|
654
|
+
/** Load by id: a missing artifact answers the byte-pinned Go NotFound copy, a store fault Internal. */
|
|
653
655
|
async function loadArtifactOrNotFound(
|
|
654
656
|
deps: ArtifactControllerDeps,
|
|
655
657
|
artifactId: string,
|
|
@@ -660,10 +662,14 @@ async function loadArtifactOrNotFound(
|
|
|
660
662
|
artifactId,
|
|
661
663
|
ArtifactSchema,
|
|
662
664
|
);
|
|
663
|
-
} catch {
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
665
|
+
} catch (error) {
|
|
666
|
+
if (error instanceof ResourceNotFoundError) {
|
|
667
|
+
throw new ConnectError(
|
|
668
|
+
artifactNotFoundMessage(artifactId),
|
|
669
|
+
Code.NotFound,
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
throw internalError(error, "failed to load artifact");
|
|
667
673
|
}
|
|
668
674
|
}
|
|
669
675
|
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pins the store-fault contract every environment load by id shares: a typed
|
|
3
|
+
* ResourceNotFoundError answers NotFound with the domain's pinned copy
|
|
4
|
+
* (`environment not found: <id>`), and any other store failure is an
|
|
5
|
+
* infrastructure fault answered as a sanitized Internal, never a NotFound
|
|
6
|
+
* that tells a client the environment does not exist
|
|
7
|
+
* (stigmer/stigmer#1345).
|
|
8
|
+
*
|
|
9
|
+
* The surfaces: updateVisibility (its own load step) and the three RPCs that
|
|
10
|
+
* share LoadEnvironmentByID, updateVariables, removeVariables and
|
|
11
|
+
* getSecretValue, each reached through the registered handler on an
|
|
12
|
+
* in-process router. The composed suites reach only a real store, which
|
|
13
|
+
* cannot fail selectively, so each surface runs here against a store whose
|
|
14
|
+
* read throws. The secret service is untouchable: a load that fails must stop
|
|
15
|
+
* the call before any decrypt or encrypt.
|
|
16
|
+
*
|
|
17
|
+
* Out of scope: the NotFound copy itself (wire contract, pinned by
|
|
18
|
+
* environment.test.ts and the environment conformance suite) and the
|
|
19
|
+
* personal-environment resolver's fold of a failed secret read into a
|
|
20
|
+
* missing key (stigmer/stigmer#1360).
|
|
21
|
+
*/
|
|
22
|
+
import type { Client, ConnectError } from "@connectrpc/connect";
|
|
23
|
+
import { Code, createClient, createRouterTransport } from "@connectrpc/connect";
|
|
24
|
+
import { describe, expect, it } from "vitest";
|
|
25
|
+
|
|
26
|
+
import { EnvironmentCommandController } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/command_pb";
|
|
27
|
+
import { EnvironmentQueryController } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/query_pb";
|
|
28
|
+
import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
|
|
29
|
+
|
|
30
|
+
import { createLogger } from "../../../boot/logger.js";
|
|
31
|
+
import { createApiResourceInterceptor } from "../../../pipeline/interceptors/apiresource.js";
|
|
32
|
+
import { createVerifierChainInterceptor } from "../../../pipeline/interceptors/auth.js";
|
|
33
|
+
import {
|
|
34
|
+
errorOf,
|
|
35
|
+
failingStore,
|
|
36
|
+
untouchable,
|
|
37
|
+
} from "../../../pipeline/__tests__/support.js";
|
|
38
|
+
import { newPermissiveSingleTeamAuthorizer } from "../../../pipeline/steps/authorize.js";
|
|
39
|
+
import { ResourceNotFoundError } from "../../../store/interface.js";
|
|
40
|
+
import type { Store } from "../../../store/interface.js";
|
|
41
|
+
|
|
42
|
+
import { registerEnvironmentServices } from "../controller.js";
|
|
43
|
+
|
|
44
|
+
const silentLogger = createLogger({
|
|
45
|
+
level: "error",
|
|
46
|
+
pretty: false,
|
|
47
|
+
write: () => {},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const ENVIRONMENT_ID = "env_storefault";
|
|
51
|
+
|
|
52
|
+
const NOT_FOUND_COPY = `environment not found: ${ENVIRONMENT_ID}`;
|
|
53
|
+
const LOAD_FAULT_COPY = "failed to load environment";
|
|
54
|
+
|
|
55
|
+
const MISSING = (): Error =>
|
|
56
|
+
new ResourceNotFoundError(`environment/${ENVIRONMENT_ID}`);
|
|
57
|
+
const LOCKED = (): Error => new Error("SQLITE_BUSY: database is locked");
|
|
58
|
+
|
|
59
|
+
interface EnvironmentClients {
|
|
60
|
+
readonly command: Client<typeof EnvironmentCommandController>;
|
|
61
|
+
readonly query: Client<typeof EnvironmentQueryController>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The registered handlers on an in-process router: the verifier chain stamps
|
|
66
|
+
* the trusted-local caller and the apiresource interceptor the kind both
|
|
67
|
+
* loads read, then Authorize and ValidateProto run and the load is the first
|
|
68
|
+
* step that reads the store.
|
|
69
|
+
*/
|
|
70
|
+
function environmentClients(store: Store): EnvironmentClients {
|
|
71
|
+
const transport = createRouterTransport(
|
|
72
|
+
(router) => {
|
|
73
|
+
registerEnvironmentServices(router, {
|
|
74
|
+
store,
|
|
75
|
+
logger: silentLogger,
|
|
76
|
+
authorizer: newPermissiveSingleTeamAuthorizer(),
|
|
77
|
+
authorizationLifecycle: undefined,
|
|
78
|
+
secretService: untouchable("secretService"),
|
|
79
|
+
listReadScope: undefined,
|
|
80
|
+
});
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
router: {
|
|
84
|
+
interceptors: [
|
|
85
|
+
createVerifierChainInterceptor([], [], silentLogger),
|
|
86
|
+
createApiResourceInterceptor(),
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
);
|
|
91
|
+
return {
|
|
92
|
+
command: createClient(EnvironmentCommandController, transport),
|
|
93
|
+
query: createClient(EnvironmentQueryController, transport),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Each surface with an input valid enough to pass ValidateProto. */
|
|
98
|
+
const SURFACES: ReadonlyArray<
|
|
99
|
+
readonly [string, (clients: EnvironmentClients) => Promise<unknown>]
|
|
100
|
+
> = [
|
|
101
|
+
[
|
|
102
|
+
"updateVisibility — LoadEnvironmentForVisibilityUpdate",
|
|
103
|
+
({ command }) =>
|
|
104
|
+
command.updateVisibility({
|
|
105
|
+
resourceId: ENVIRONMENT_ID,
|
|
106
|
+
visibility: ApiResourceVisibility.visibility_private,
|
|
107
|
+
}),
|
|
108
|
+
],
|
|
109
|
+
[
|
|
110
|
+
"updateVariables — LoadEnvironmentByID",
|
|
111
|
+
({ command }) =>
|
|
112
|
+
command.updateVariables({
|
|
113
|
+
environmentId: ENVIRONMENT_ID,
|
|
114
|
+
variables: { API_KEY: { value: "v", isSecret: false } },
|
|
115
|
+
}),
|
|
116
|
+
],
|
|
117
|
+
[
|
|
118
|
+
"removeVariables — LoadEnvironmentByID",
|
|
119
|
+
({ command }) =>
|
|
120
|
+
command.removeVariables({
|
|
121
|
+
environmentId: ENVIRONMENT_ID,
|
|
122
|
+
keys: ["API_KEY"],
|
|
123
|
+
}),
|
|
124
|
+
],
|
|
125
|
+
[
|
|
126
|
+
"getSecretValue — LoadEnvironmentByID",
|
|
127
|
+
({ query }) =>
|
|
128
|
+
query.getSecretValue({ environmentId: ENVIRONMENT_ID, key: "API_KEY" }),
|
|
129
|
+
],
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
describe.each(SURFACES)("%s", (_name, call) => {
|
|
133
|
+
function surfaceError(store: Store): Promise<ConnectError> {
|
|
134
|
+
return errorOf(() => call(environmentClients(store)));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
it("a missing environment answers NotFound with the domain's copy", async () => {
|
|
138
|
+
const error = await surfaceError(failingStore(MISSING()));
|
|
139
|
+
|
|
140
|
+
expect(error.code).toBe(Code.NotFound);
|
|
141
|
+
expect(error.rawMessage).toBe(NOT_FOUND_COPY);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("any other store failure answers a sanitized Internal", async () => {
|
|
145
|
+
const error = await surfaceError(failingStore(LOCKED()));
|
|
146
|
+
|
|
147
|
+
expect(error.code).toBe(Code.Internal);
|
|
148
|
+
expect(error.rawMessage).toBe(LOAD_FAULT_COPY);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* design: limited blast radius, per-key audit, the industry "reveal" UX).
|
|
9
9
|
*
|
|
10
10
|
* Pipeline per RPC mirrors the Go step chains character-for-character.
|
|
11
|
-
* Proven by environment.conformance.test.ts (CONFORMANCE_TARGET=local)
|
|
12
|
-
* and __tests__/
|
|
11
|
+
* Proven by environment.conformance.test.ts (CONFORMANCE_TARGET=local),
|
|
12
|
+
* __tests__/environment.test.ts and __tests__/store-faults.test.ts.
|
|
13
13
|
*
|
|
14
14
|
* Versus Stigmer Cloud, OSS excludes the Authorize, CreateIamPolicies,
|
|
15
15
|
* FGA-tuple, and Publish steps (no multi-tenant auth, IAM/FGA, or event
|
|
@@ -421,7 +421,7 @@ async function updateVisibility(
|
|
|
421
421
|
return env;
|
|
422
422
|
}
|
|
423
423
|
|
|
424
|
-
/** Loads the environment by resource_id;
|
|
424
|
+
/** Loads the environment by resource_id; a missing one answers NotFound, a store fault Internal. */
|
|
425
425
|
function newLoadEnvironmentForVisibilityUpdateStep(
|
|
426
426
|
store: Store,
|
|
427
427
|
): PipelineStep<UpdateVisibilityDesc> {
|
|
@@ -436,8 +436,11 @@ function newLoadEnvironmentForVisibilityUpdateStep(
|
|
|
436
436
|
input.resourceId,
|
|
437
437
|
EnvironmentSchema,
|
|
438
438
|
);
|
|
439
|
-
} catch {
|
|
440
|
-
|
|
439
|
+
} catch (error) {
|
|
440
|
+
if (error instanceof ResourceNotFoundError) {
|
|
441
|
+
throw notFoundError("environment", input.resourceId);
|
|
442
|
+
}
|
|
443
|
+
throw internalError(error, "failed to load environment");
|
|
441
444
|
}
|
|
442
445
|
ctx.set(UPDATE_VISIBILITY_ENVIRONMENT_KEY, env);
|
|
443
446
|
},
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
* by design and must not hit the forgery rejection.
|
|
16
16
|
* 3. Redaction (redact.ts) runs AFTER Persist, outside the pipeline.
|
|
17
17
|
*
|
|
18
|
-
* Proven by environment.conformance.test.ts (CONFORMANCE_TARGET=local)
|
|
19
|
-
* and __tests__/
|
|
18
|
+
* Proven by environment.conformance.test.ts (CONFORMANCE_TARGET=local),
|
|
19
|
+
* __tests__/environment.test.ts and __tests__/store-faults.test.ts.
|
|
20
20
|
*/
|
|
21
21
|
import { create } from "@bufbuild/protobuf";
|
|
22
22
|
import type { DescMessage } from "@bufbuild/protobuf";
|
|
@@ -51,6 +51,7 @@ import { findResourceByLabelAndOrg } from "../../pipeline/steps/helpers.js";
|
|
|
51
51
|
import { EXISTING_RESOURCE_KEY } from "../../pipeline/steps/load-existing.js";
|
|
52
52
|
import { TARGET_RESOURCE_KEY } from "../../pipeline/steps/load-target.js";
|
|
53
53
|
import { destroySecretBackingState } from "../../pipeline/steps/secret-cleanup.js";
|
|
54
|
+
import { ResourceNotFoundError } from "../../store/interface.js";
|
|
54
55
|
import type { Store } from "../../store/interface.js";
|
|
55
56
|
import {
|
|
56
57
|
PERSONAL_LABEL_KEY,
|
|
@@ -273,7 +274,8 @@ export function newEnforcePersonalUniquenessStep(
|
|
|
273
274
|
* environment_id field (the standard LoadTarget expects a `value` id
|
|
274
275
|
* field, but EnvironmentSecretValueInput / Update-/RemoveEnvironment-
|
|
275
276
|
* VariablesRequest carry `environment_id`). Stores under
|
|
276
|
-
* TARGET_RESOURCE_KEY.
|
|
277
|
+
* TARGET_RESOURCE_KEY. A missing environment answers NotFound, a store
|
|
278
|
+
* fault Internal.
|
|
277
279
|
*/
|
|
278
280
|
export function newLoadEnvironmentByIdStep<Desc extends DescMessage>(
|
|
279
281
|
store: Store,
|
|
@@ -294,10 +296,11 @@ export function newLoadEnvironmentByIdStep<Desc extends DescMessage>(
|
|
|
294
296
|
environmentId,
|
|
295
297
|
EnvironmentSchema,
|
|
296
298
|
);
|
|
297
|
-
} catch {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
299
|
+
} catch (error) {
|
|
300
|
+
if (error instanceof ResourceNotFoundError) {
|
|
301
|
+
throw notFoundError("environment", environmentId);
|
|
302
|
+
}
|
|
303
|
+
throw internalError(error, "failed to load environment");
|
|
301
304
|
}
|
|
302
305
|
|
|
303
306
|
ctx.set(TARGET_RESOURCE_KEY, env);
|
|
@@ -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,
|
|
@@ -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],
|