@shawnstack/quickforge 1.3.20 → 1.3.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +348 -348
- package/dist/assets/{anthropic-Bj3HAZgj.js → anthropic-CDKnv1FQ.js} +1 -1
- package/dist/assets/{azure-openai-responses-IdZZrSrI.js → azure-openai-responses-BnUwVl-8.js} +1 -1
- package/dist/assets/{google-Brt_lS1J.js → google-DOEyCDZy.js} +1 -1
- package/dist/assets/{google-vertex-B6HsoZ34.js → google-vertex-BPPf3car.js} +1 -1
- package/dist/assets/{icons-BHkxP7oT.js → icons-WD3UkVNM.js} +1 -1
- package/dist/assets/{index-D0CVLdX_.js → index-CjTN0qaQ.js} +586 -554
- package/dist/assets/index-eeLjaV06.css +3 -0
- package/dist/assets/{mistral-CenXqwPz.js → mistral-Ber29mja.js} +1 -1
- package/dist/assets/{openai-codex-responses-D9ffGwbj.js → openai-codex-responses-D8gq8a3l.js} +1 -1
- package/dist/assets/{openai-completions-eWdeSGBG.js → openai-completions-CATWPFBp.js} +1 -1
- package/dist/assets/{openai-responses-Cavpmjeu.js → openai-responses-DxcB6Ksu.js} +1 -1
- package/dist/assets/{openai-responses-shared-DF3ZGaUx.js → openai-responses-shared-a_PAPxTO.js} +1 -1
- package/dist/assets/{react-vendor-CmyL2roG.js → react-vendor-BcQaTQ90.js} +1 -1
- package/dist/index.html +4 -4
- package/node_modules/@aws-sdk/client-bedrock-runtime/dist-cjs/index.js +1 -0
- package/node_modules/@aws-sdk/client-bedrock-runtime/dist-es/models/enums.js +1 -0
- package/node_modules/@aws-sdk/client-bedrock-runtime/package.json +11 -11
- package/node_modules/@aws-sdk/core/package.json +3 -3
- package/node_modules/@aws-sdk/credential-provider-env/package.json +3 -3
- package/node_modules/@aws-sdk/credential-provider-http/package.json +5 -5
- package/node_modules/@aws-sdk/credential-provider-ini/package.json +11 -11
- package/node_modules/@aws-sdk/credential-provider-login/package.json +4 -4
- package/node_modules/@aws-sdk/credential-provider-node/package.json +9 -9
- package/node_modules/@aws-sdk/credential-provider-process/package.json +3 -3
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/LICENSE +201 -0
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/README.md +62 -0
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-cjs/index.js +156 -0
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/constants.js +2 -0
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/fromEnvSigningName.js +16 -0
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/fromSso.js +80 -0
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/fromStatic.js +8 -0
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/getNewSsoOidcToken.js +11 -0
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/getSsoOidcClient.js +10 -0
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/index.js +4 -0
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/nodeProvider.js +5 -0
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/validateTokenExpiry.js +7 -0
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/validateTokenKey.js +7 -0
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/dist-es/writeSSOTokenToFile.js +8 -0
- package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/package.json +69 -0
- package/node_modules/@aws-sdk/credential-provider-sso/package.json +5 -5
- package/node_modules/@aws-sdk/credential-provider-web-identity/package.json +4 -4
- package/node_modules/@aws-sdk/eventstream-handler-node/package.json +2 -2
- package/node_modules/@aws-sdk/middleware-eventstream/package.json +2 -2
- package/node_modules/@aws-sdk/middleware-websocket/package.json +5 -5
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/cognito-identity/index.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/signin/index.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso/index.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso-oidc/index.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sts/index.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/package.json +6 -6
- package/node_modules/@aws-sdk/signature-v4-multi-region/package.json +2 -2
- package/node_modules/@aws-sdk/token-providers/package.json +4 -4
- package/node_modules/@nodable/entities/package.json +1 -1
- package/node_modules/@nodable/entities/src/EntityDecoder.js +1 -1
- package/node_modules/@nodable/entities/src/entities.js +0 -18
- package/node_modules/@smithy/core/dist-cjs/index.js +3 -4
- package/node_modules/@smithy/core/dist-cjs/submodules/client/index.js +3 -11
- package/node_modules/@smithy/core/dist-cjs/submodules/config/index.browser.js +2 -2
- package/node_modules/@smithy/core/dist-cjs/submodules/config/index.js +2 -2
- package/node_modules/@smithy/core/dist-cjs/submodules/config/index.native.js +2 -2
- package/node_modules/@smithy/core/dist-cjs/submodules/endpoints/index.browser.js +9 -40
- package/node_modules/@smithy/core/dist-cjs/submodules/endpoints/index.js +9 -40
- package/node_modules/@smithy/core/dist-cjs/submodules/protocols/index.js +12 -142
- package/node_modules/@smithy/core/dist-cjs/submodules/schema/index.js +7 -9
- package/node_modules/@smithy/core/dist-cjs/submodules/serde/index.browser.js +2 -2
- package/node_modules/@smithy/core/dist-cjs/submodules/serde/index.js +2 -2
- package/node_modules/@smithy/core/dist-cjs/submodules/serde/index.native.js +2 -2
- package/node_modules/@smithy/core/dist-cjs/submodules/transport/index.js +184 -0
- package/node_modules/@smithy/core/dist-es/index.js +6 -6
- package/node_modules/@smithy/core/dist-es/submodules/client/index.js +2 -2
- package/node_modules/@smithy/core/dist-es/submodules/config/config-resolver/regionConfig/checkRegion.js +1 -1
- package/node_modules/@smithy/core/dist-es/submodules/endpoints/index.browser.js +2 -2
- package/node_modules/@smithy/core/dist-es/submodules/endpoints/index.js +2 -2
- package/node_modules/@smithy/core/dist-es/submodules/endpoints/middleware-endpoint/adaptors/toEndpointV1.js +1 -1
- package/node_modules/@smithy/core/dist-es/submodules/endpoints/middleware-endpoint/resolveEndpointConfig.js +1 -1
- package/node_modules/@smithy/core/dist-es/submodules/endpoints/util-endpoints/lib/index.js +1 -1
- package/node_modules/@smithy/core/dist-es/submodules/protocols/HttpBindingProtocol.js +1 -1
- package/node_modules/@smithy/core/dist-es/submodules/protocols/HttpProtocol.js +1 -2
- package/node_modules/@smithy/core/dist-es/submodules/protocols/RpcProtocol.js +1 -1
- package/node_modules/@smithy/core/dist-es/submodules/protocols/index.js +5 -5
- package/node_modules/@smithy/core/dist-es/submodules/protocols/middleware-content-length/contentLengthMiddleware.js +1 -1
- package/node_modules/@smithy/core/dist-es/submodules/protocols/requestBuilder.js +1 -1
- package/node_modules/@smithy/core/dist-es/submodules/schema/middleware/schemaDeserializationMiddleware.js +3 -4
- package/node_modules/@smithy/core/dist-es/submodules/schema/middleware/schemaSerializationMiddleware.js +1 -2
- package/node_modules/@smithy/core/dist-es/submodules/serde/middleware-serde/deserializerMiddleware.js +1 -1
- package/node_modules/@smithy/core/dist-es/submodules/transport/index.js +9 -0
- package/node_modules/@smithy/core/dist-es/submodules/{protocols/url-parser → transport}/parseUrl.js +1 -1
- package/node_modules/@smithy/core/dist-es/submodules/{endpoints → transport}/toEndpointV1.js +1 -1
- package/node_modules/@smithy/core/package.json +19 -10
- package/node_modules/@smithy/core/transport.js +5 -0
- package/node_modules/@smithy/credential-provider-imds/dist-cjs/index.js +14 -13
- package/node_modules/@smithy/credential-provider-imds/dist-es/fromContainerMetadata.js +14 -13
- package/node_modules/@smithy/credential-provider-imds/package.json +2 -2
- package/node_modules/@smithy/fetch-http-handler/package.json +2 -2
- package/node_modules/@smithy/node-http-handler/package.json +2 -2
- package/node_modules/@smithy/signature-v4/package.json +2 -2
- package/node_modules/eventsource-parser/README.md +31 -0
- package/node_modules/eventsource-parser/dist/index.cjs +21 -10
- package/node_modules/eventsource-parser/dist/index.js +21 -10
- package/node_modules/eventsource-parser/dist/stream.cjs +4 -3
- package/node_modules/eventsource-parser/dist/stream.js +4 -3
- package/node_modules/eventsource-parser/package.json +8 -8
- package/node_modules/hasown/CHANGELOG.md +7 -0
- package/node_modules/hasown/package.json +4 -5
- package/node_modules/protobufjs/dist/light/protobuf.js +7 -5
- package/node_modules/protobufjs/dist/light/protobuf.min.js +3 -3
- package/node_modules/protobufjs/dist/minimal/protobuf.js +3 -3
- package/node_modules/protobufjs/dist/minimal/protobuf.min.js +3 -3
- package/node_modules/protobufjs/dist/protobuf.js +7 -5
- package/node_modules/protobufjs/dist/protobuf.min.js +3 -3
- package/node_modules/protobufjs/package.json +1 -1
- package/node_modules/protobufjs/src/converter.js +4 -2
- package/node_modules/protobufjs/src/roots.js +1 -1
- package/node_modules/typebox/build/type/script/mapping.mjs +15 -8
- package/node_modules/typebox/build/type/script/parser.mjs +2 -1
- package/node_modules/typebox/package.json +29 -29
- package/package.json +1 -1
- package/server/agent-manager.mjs +63 -25
- package/server/agent-profiles.mjs +191 -0
- package/server/auto-compaction.mjs +20 -0
- package/server/index.mjs +32 -8
- package/server/mcp/registry.mjs +13 -2
- package/server/routes/agent-profiles.mjs +172 -0
- package/server/routes/lan-access.mjs +20 -0
- package/server/routes/scheduled-tasks.mjs +161 -47
- package/server/routes/shared-conversation.mjs +14 -0
- package/server/routes/storage.mjs +10 -0
- package/server/routes/terminal.mjs +13 -3
- package/server/session-utils.mjs +2 -2
- package/server/storage.mjs +3 -4
- package/server/system-prompt.mjs +10 -5
- package/server/terminal/terminal-manager.mjs +9 -1
- package/server/tools/definitions.mjs +2 -7
- package/server/utils/response.mjs +4 -0
- package/dist/assets/index-D0W9hAl_.css +0 -3
- package/node_modules/@smithy/core/dist-cjs/getSmithyContext.js +0 -6
- package/node_modules/@smithy/core/dist-cjs/middleware-http-auth-scheme/getHttpAuthSchemeEndpointRuleSetPlugin.js +0 -21
- package/node_modules/@smithy/core/dist-cjs/middleware-http-auth-scheme/getHttpAuthSchemePlugin.js +0 -21
- package/node_modules/@smithy/core/dist-cjs/middleware-http-auth-scheme/httpAuthSchemeMiddleware.js +0 -46
- package/node_modules/@smithy/core/dist-cjs/middleware-http-auth-scheme/index.js +0 -6
- package/node_modules/@smithy/core/dist-cjs/middleware-http-auth-scheme/resolveAuthOptions.js +0 -24
- package/node_modules/@smithy/core/dist-cjs/middleware-http-signing/getHttpSigningMiddleware.js +0 -19
- package/node_modules/@smithy/core/dist-cjs/middleware-http-signing/httpSigningMiddleware.js +0 -27
- package/node_modules/@smithy/core/dist-cjs/middleware-http-signing/index.js +0 -5
- package/node_modules/@smithy/core/dist-cjs/normalizeProvider.js +0 -10
- package/node_modules/@smithy/core/dist-cjs/pagination/createPaginator.js +0 -44
- package/node_modules/@smithy/core/dist-cjs/request-builder/requestBuilder.js +0 -5
- package/node_modules/@smithy/core/dist-cjs/setFeature.js +0 -14
- package/node_modules/@smithy/core/dist-cjs/util-identity-and-auth/DefaultIdentityProviderConfig.js +0 -18
- package/node_modules/@smithy/core/dist-cjs/util-identity-and-auth/httpAuthSchemes/httpApiKeyAuth.js +0 -38
- package/node_modules/@smithy/core/dist-cjs/util-identity-and-auth/httpAuthSchemes/httpBearerAuth.js +0 -15
- package/node_modules/@smithy/core/dist-cjs/util-identity-and-auth/httpAuthSchemes/index.js +0 -6
- package/node_modules/@smithy/core/dist-cjs/util-identity-and-auth/httpAuthSchemes/noAuth.js +0 -9
- package/node_modules/@smithy/core/dist-cjs/util-identity-and-auth/index.js +0 -6
- package/node_modules/@smithy/core/dist-cjs/util-identity-and-auth/memoizeIdentityProvider.js +0 -61
- package/node_modules/@smithy/core/dist-es/request-builder/requestBuilder.js +0 -1
- package/node_modules/@smithy/core/dist-es/submodules/client/util-middleware/getSmithyContext.js +0 -2
- package/node_modules/@smithy/core/dist-es/submodules/event-streams/eventstream-codec/TestVectors.fixture.js +0 -146
- package/node_modules/@smithy/core/dist-es/submodules/event-streams/eventstream-codec/vectorTypes.fixture.js +0 -1
- package/node_modules/@smithy/credential-provider-imds/dist-es/remoteProvider/index.js +0 -2
- package/node_modules/@smithy/node-http-handler/dist-es/readable.mock.js +0 -21
- package/node_modules/@smithy/node-http-handler/dist-es/server.mock.js +0 -88
- package/node_modules/@smithy/node-http-handler/dist-es/stream-collector/readable.mock.js +0 -21
- package/node_modules/@smithy/signature-v4/dist-es/suite.fixture.js +0 -399
- /package/node_modules/@smithy/core/dist-es/{middleware-http-auth-scheme → legacy-root-exports/middleware-http-auth-scheme}/getHttpAuthSchemeEndpointRuleSetPlugin.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{middleware-http-auth-scheme → legacy-root-exports/middleware-http-auth-scheme}/getHttpAuthSchemePlugin.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{middleware-http-auth-scheme → legacy-root-exports/middleware-http-auth-scheme}/httpAuthSchemeMiddleware.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{middleware-http-auth-scheme → legacy-root-exports/middleware-http-auth-scheme}/index.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{middleware-http-auth-scheme → legacy-root-exports/middleware-http-auth-scheme}/resolveAuthOptions.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{middleware-http-signing → legacy-root-exports/middleware-http-signing}/getHttpSigningMiddleware.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{middleware-http-signing → legacy-root-exports/middleware-http-signing}/httpSigningMiddleware.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{middleware-http-signing → legacy-root-exports/middleware-http-signing}/index.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{pagination → legacy-root-exports/pagination}/createPaginator.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{util-identity-and-auth → legacy-root-exports/util-identity-and-auth}/DefaultIdentityProviderConfig.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{util-identity-and-auth → legacy-root-exports/util-identity-and-auth}/httpAuthSchemes/httpApiKeyAuth.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{util-identity-and-auth → legacy-root-exports/util-identity-and-auth}/httpAuthSchemes/httpBearerAuth.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{util-identity-and-auth → legacy-root-exports/util-identity-and-auth}/httpAuthSchemes/index.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{util-identity-and-auth → legacy-root-exports/util-identity-and-auth}/httpAuthSchemes/noAuth.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{util-identity-and-auth → legacy-root-exports/util-identity-and-auth}/index.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{util-identity-and-auth → legacy-root-exports/util-identity-and-auth}/memoizeIdentityProvider.js +0 -0
- /package/node_modules/@smithy/core/dist-es/{getSmithyContext.js → submodules/transport/getSmithyContext.js} +0 -0
- /package/node_modules/@smithy/core/dist-es/submodules/{protocols/protocol-http → transport}/httpRequest.js +0 -0
- /package/node_modules/@smithy/core/dist-es/submodules/{protocols/protocol-http → transport}/httpResponse.js +0 -0
- /package/node_modules/@smithy/core/dist-es/submodules/{endpoints/util-endpoints/lib → transport}/isValidHostLabel.js +0 -0
- /package/node_modules/@smithy/core/dist-es/submodules/{protocols/protocol-http → transport}/isValidHostname.js +0 -0
- /package/node_modules/@smithy/core/dist-es/submodules/{client/util-middleware → transport}/normalizeProvider.js +0 -0
- /package/node_modules/@smithy/core/dist-es/submodules/{protocols/querystring-parser → transport}/parseQueryString.js +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typebox",
|
|
3
3
|
"description": "Json Schema Type Builder with Static Type Resolution for TypeScript",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.39",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
7
7
|
"jsonschema"
|
|
@@ -16,22 +16,6 @@
|
|
|
16
16
|
"types": "./build/index.d.mts",
|
|
17
17
|
"module": "./build/index.mjs",
|
|
18
18
|
"exports": {
|
|
19
|
-
"./guard": {
|
|
20
|
-
"import": "./build/guard/index.mjs",
|
|
21
|
-
"default": "./build/guard/index.mjs"
|
|
22
|
-
},
|
|
23
|
-
"./error": {
|
|
24
|
-
"import": "./build/error/index.mjs",
|
|
25
|
-
"default": "./build/error/index.mjs"
|
|
26
|
-
},
|
|
27
|
-
"./compile": {
|
|
28
|
-
"import": "./build/compile/index.mjs",
|
|
29
|
-
"default": "./build/compile/index.mjs"
|
|
30
|
-
},
|
|
31
|
-
"./system": {
|
|
32
|
-
"import": "./build/system/index.mjs",
|
|
33
|
-
"default": "./build/system/index.mjs"
|
|
34
|
-
},
|
|
35
19
|
"./format": {
|
|
36
20
|
"import": "./build/format/index.mjs",
|
|
37
21
|
"default": "./build/format/index.mjs"
|
|
@@ -44,10 +28,26 @@
|
|
|
44
28
|
"import": "./build/schema/index.mjs",
|
|
45
29
|
"default": "./build/schema/index.mjs"
|
|
46
30
|
},
|
|
31
|
+
"./compile": {
|
|
32
|
+
"import": "./build/compile/index.mjs",
|
|
33
|
+
"default": "./build/compile/index.mjs"
|
|
34
|
+
},
|
|
47
35
|
"./value": {
|
|
48
36
|
"import": "./build/value/index.mjs",
|
|
49
37
|
"default": "./build/value/index.mjs"
|
|
50
38
|
},
|
|
39
|
+
"./guard": {
|
|
40
|
+
"import": "./build/guard/index.mjs",
|
|
41
|
+
"default": "./build/guard/index.mjs"
|
|
42
|
+
},
|
|
43
|
+
"./system": {
|
|
44
|
+
"import": "./build/system/index.mjs",
|
|
45
|
+
"default": "./build/system/index.mjs"
|
|
46
|
+
},
|
|
47
|
+
"./error": {
|
|
48
|
+
"import": "./build/error/index.mjs",
|
|
49
|
+
"default": "./build/error/index.mjs"
|
|
50
|
+
},
|
|
51
51
|
".": {
|
|
52
52
|
"import": "./build/index.mjs",
|
|
53
53
|
"default": "./build/index.mjs"
|
|
@@ -55,18 +55,6 @@
|
|
|
55
55
|
},
|
|
56
56
|
"typesVersions": {
|
|
57
57
|
"*": {
|
|
58
|
-
"guard": [
|
|
59
|
-
"./build/guard/index.d.mts"
|
|
60
|
-
],
|
|
61
|
-
"error": [
|
|
62
|
-
"./build/error/index.d.mts"
|
|
63
|
-
],
|
|
64
|
-
"compile": [
|
|
65
|
-
"./build/compile/index.d.mts"
|
|
66
|
-
],
|
|
67
|
-
"system": [
|
|
68
|
-
"./build/system/index.d.mts"
|
|
69
|
-
],
|
|
70
58
|
"format": [
|
|
71
59
|
"./build/format/index.d.mts"
|
|
72
60
|
],
|
|
@@ -76,9 +64,21 @@
|
|
|
76
64
|
"schema": [
|
|
77
65
|
"./build/schema/index.d.mts"
|
|
78
66
|
],
|
|
67
|
+
"compile": [
|
|
68
|
+
"./build/compile/index.d.mts"
|
|
69
|
+
],
|
|
79
70
|
"value": [
|
|
80
71
|
"./build/value/index.d.mts"
|
|
81
72
|
],
|
|
73
|
+
"guard": [
|
|
74
|
+
"./build/guard/index.d.mts"
|
|
75
|
+
],
|
|
76
|
+
"system": [
|
|
77
|
+
"./build/system/index.d.mts"
|
|
78
|
+
],
|
|
79
|
+
"error": [
|
|
80
|
+
"./build/error/index.d.mts"
|
|
81
|
+
],
|
|
82
82
|
".": [
|
|
83
83
|
"./build/index.d.mts"
|
|
84
84
|
]
|
package/package.json
CHANGED
package/server/agent-manager.mjs
CHANGED
|
@@ -8,8 +8,8 @@ import { callMcpTool, createMcpToolDefinitions, isMcpToolName } from './mcp/regi
|
|
|
8
8
|
import {
|
|
9
9
|
composeSubagentSystemPrompt,
|
|
10
10
|
formatSubagentTask,
|
|
11
|
-
getSubagentDefinition,
|
|
12
11
|
} from './subagents.mjs'
|
|
12
|
+
import { agentProfileSnapshot, getAgentProfile } from './agent-profiles.mjs'
|
|
13
13
|
import { projectContextFromId, readProjectConfig } from './project-config.mjs'
|
|
14
14
|
import { readStore, atomicUpdate, readSessionValue, writeSessionValue, deleteSessionValue } from './storage.mjs'
|
|
15
15
|
import { logger } from './utils/logger.mjs'
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
} from './conversation-compaction.mjs'
|
|
23
23
|
import {
|
|
24
24
|
buildAutoCompactLoopMessages,
|
|
25
|
+
estimateSessionContextUsage,
|
|
25
26
|
maybeAutoCompactSession,
|
|
26
27
|
} from './auto-compaction.mjs'
|
|
27
28
|
import {
|
|
@@ -366,8 +367,12 @@ function estimateTokenReduction(originalChars, finalChars) {
|
|
|
366
367
|
}
|
|
367
368
|
|
|
368
369
|
function emitSessionEvent(session, event) {
|
|
369
|
-
|
|
370
|
-
|
|
370
|
+
const enrichedEvent = (event?.type === 'message_end' || event?.type === 'agent_end' || event?.type === 'messages_replaced' || event?.type === 'auto_compact_completed')
|
|
371
|
+
&& event.contextUsage === undefined
|
|
372
|
+
? { ...event, contextUsage: getSessionContextUsage(session) }
|
|
373
|
+
: event
|
|
374
|
+
session.eventBus.emit('agent_event', enrichedEvent)
|
|
375
|
+
agentEvents.emit('agent_event', { sessionId: session.sessionId, ...enrichedEvent })
|
|
371
376
|
}
|
|
372
377
|
|
|
373
378
|
function addToolTimingToEvent(session, event) {
|
|
@@ -681,12 +686,13 @@ function lastAssistantText(messages) {
|
|
|
681
686
|
}
|
|
682
687
|
|
|
683
688
|
async function runSubagent(parentSession, params, parentSignal, onUpdate) {
|
|
684
|
-
const
|
|
685
|
-
if (!
|
|
686
|
-
const error = new Error(`Unknown subagent: ${params?.subagent || ''}`)
|
|
689
|
+
const profile = await getAgentProfile(params?.subagent)
|
|
690
|
+
if (!profile || !profile.enabledAsSubagent) {
|
|
691
|
+
const error = new Error(`Unknown or disabled subagent: ${params?.subagent || ''}`)
|
|
687
692
|
error.statusCode = 400
|
|
688
693
|
throw error
|
|
689
694
|
}
|
|
695
|
+
const definition = profile
|
|
690
696
|
|
|
691
697
|
const task = String(params?.task || '').trim()
|
|
692
698
|
if (!task) {
|
|
@@ -774,7 +780,7 @@ async function runSubagent(parentSession, params, parentSignal, onUpdate) {
|
|
|
774
780
|
const toolName = context.toolCall?.name
|
|
775
781
|
toolCalls += 1
|
|
776
782
|
emitSubagentTrace()
|
|
777
|
-
if (toolCalls > Number(definition.maxToolCalls ||
|
|
783
|
+
if (toolCalls > Number(definition.maxToolCalls || 300)) {
|
|
778
784
|
return { block: true, reason: `Subagent ${definition.name} exceeded its tool-call budget.` }
|
|
779
785
|
}
|
|
780
786
|
if (!definition.allowedTools.includes(toolName)) {
|
|
@@ -954,6 +960,7 @@ export async function createAgent(sessionId, config = {}) {
|
|
|
954
960
|
createdAt = new Date().toISOString(),
|
|
955
961
|
lastModified = null,
|
|
956
962
|
contextCompaction = null,
|
|
963
|
+
agentProfile = null,
|
|
957
964
|
} = config
|
|
958
965
|
|
|
959
966
|
// Resolve project context for tool calls
|
|
@@ -975,7 +982,8 @@ export async function createAgent(sessionId, config = {}) {
|
|
|
975
982
|
globalSkillNames: projectConfig.globalSkills,
|
|
976
983
|
projectSkillNames: configuredProject?.skills,
|
|
977
984
|
}
|
|
978
|
-
const
|
|
985
|
+
const profileSystemPrompt = agentProfile?.systemPrompt ? `\n\n<agent_profile_instructions>\nAgent Profile: ${agentProfile.label || agentProfile.name}\n${agentProfile.systemPrompt}\n</agent_profile_instructions>` : ''
|
|
986
|
+
const resolvedSystemPrompt = systemPrompt ?? `${await buildSystemPrompt(projectId)}${profileSystemPrompt}`
|
|
979
987
|
|
|
980
988
|
// Resolve model
|
|
981
989
|
let resolvedModel = model
|
|
@@ -991,16 +999,25 @@ export async function createAgent(sessionId, config = {}) {
|
|
|
991
999
|
}
|
|
992
1000
|
|
|
993
1001
|
// Build skills tools for enabled skills, plus workspace tools when a project is available.
|
|
1002
|
+
const profileToolNames = Array.isArray(agentProfile?.allowedTools) ? agentProfile.allowedTools : null
|
|
994
1003
|
const tools = await createServerTools(
|
|
995
1004
|
projectId,
|
|
996
1005
|
projectContext,
|
|
997
1006
|
skillsContext,
|
|
998
1007
|
!!(projectId && projectContext),
|
|
999
1008
|
(toolName) => {
|
|
1009
|
+
if (profileToolNames && !profileToolNames.includes(toolName)) return `Agent profile ${agentProfile.name} is not allowed to use ${toolName}.`
|
|
1000
1010
|
const session = agentSessions.get(sessionId)
|
|
1001
1011
|
return session ? createCommandToolPermissions(session)(toolName) : null
|
|
1002
1012
|
},
|
|
1003
|
-
|
|
1013
|
+
agentProfile
|
|
1014
|
+
? {
|
|
1015
|
+
allowedToolNames: profileToolNames,
|
|
1016
|
+
includeSubagentTool: false,
|
|
1017
|
+
includeMcpTools: false,
|
|
1018
|
+
parentSessionId: sessionId,
|
|
1019
|
+
}
|
|
1020
|
+
: { parentSessionId: sessionId },
|
|
1004
1021
|
)
|
|
1005
1022
|
|
|
1006
1023
|
// Resolve API key
|
|
@@ -1013,6 +1030,7 @@ export async function createAgent(sessionId, config = {}) {
|
|
|
1013
1030
|
}
|
|
1014
1031
|
}
|
|
1015
1032
|
|
|
1033
|
+
let session
|
|
1016
1034
|
const agent = new Agent({
|
|
1017
1035
|
initialState: {
|
|
1018
1036
|
systemPrompt: resolvedSystemPrompt,
|
|
@@ -1035,6 +1053,7 @@ export async function createAgent(sessionId, config = {}) {
|
|
|
1035
1053
|
const isSkillTool = toolName === 'activate_skill' || toolName === 'read_skill_resource'
|
|
1036
1054
|
if (isSkillTool) return undefined
|
|
1037
1055
|
const currentSession = agentSessions.get(sessionId)
|
|
1056
|
+
if (profileToolNames && !profileToolNames.includes(toolName)) return { block: true, reason: `Agent profile ${agentProfile.name} is not allowed to use ${toolName}.` }
|
|
1038
1057
|
if (toolName === 'run_subagent') return undefined
|
|
1039
1058
|
if (isMcpToolName(toolName)) {
|
|
1040
1059
|
if (!currentSession?.yoloMode) return createApprovalPromise(currentSession, toolCallId, toolName, context.args)
|
|
@@ -1055,7 +1074,7 @@ export async function createAgent(sessionId, config = {}) {
|
|
|
1055
1074
|
const eventBus = new EventEmitter()
|
|
1056
1075
|
eventBus.setMaxListeners(100)
|
|
1057
1076
|
|
|
1058
|
-
|
|
1077
|
+
session = {
|
|
1059
1078
|
sessionId,
|
|
1060
1079
|
agent,
|
|
1061
1080
|
projectContext,
|
|
@@ -1081,6 +1100,7 @@ export async function createAgent(sessionId, config = {}) {
|
|
|
1081
1100
|
toolTimings: new Map(),
|
|
1082
1101
|
getApiKey,
|
|
1083
1102
|
contextCompaction,
|
|
1103
|
+
agentProfile: agentProfile ? agentProfileSnapshot(agentProfile) : null,
|
|
1084
1104
|
lastTransformedContextMessages: null,
|
|
1085
1105
|
autoCompacting: false,
|
|
1086
1106
|
lastAutoCompactAt: null,
|
|
@@ -1102,8 +1122,7 @@ export async function createAgent(sessionId, config = {}) {
|
|
|
1102
1122
|
: timedEvent
|
|
1103
1123
|
|
|
1104
1124
|
// Forward all events to the session event bus and the global bus.
|
|
1105
|
-
|
|
1106
|
-
agentEvents.emit('agent_event', { sessionId, ...forwardEvent })
|
|
1125
|
+
emitSessionEvent(session, forwardEvent)
|
|
1107
1126
|
|
|
1108
1127
|
// Track status
|
|
1109
1128
|
if (event.type === 'agent_start') {
|
|
@@ -1263,7 +1282,10 @@ async function persistSession(session) {
|
|
|
1263
1282
|
try {
|
|
1264
1283
|
await writeSessionValue(sessionId, sessionData)
|
|
1265
1284
|
await atomicUpdate('sessions-metadata', (data) => {
|
|
1266
|
-
data[sessionId] =
|
|
1285
|
+
data[sessionId] = {
|
|
1286
|
+
...metadata,
|
|
1287
|
+
pinnedAt: data[sessionId]?.pinnedAt,
|
|
1288
|
+
}
|
|
1267
1289
|
return data
|
|
1268
1290
|
})
|
|
1269
1291
|
} catch (err) {
|
|
@@ -1320,6 +1342,8 @@ export async function rollbackSessionMessages(sessionId, rollbackMessageIndex) {
|
|
|
1320
1342
|
reason: 'rollback',
|
|
1321
1343
|
rollbackIndex,
|
|
1322
1344
|
messages: session.agent.state.messages,
|
|
1345
|
+
contextCompaction: session.contextCompaction,
|
|
1346
|
+
contextUsage: getSessionContextUsage(session),
|
|
1323
1347
|
}
|
|
1324
1348
|
emitSessionEvent(session, replacedEvent)
|
|
1325
1349
|
emitSessionEvent(session, { type: 'message_end', messages: session.agent.state.messages })
|
|
@@ -1340,8 +1364,9 @@ export async function replaceSessionMessages(sessionId, messages) {
|
|
|
1340
1364
|
session.finishedAt = new Date().toISOString()
|
|
1341
1365
|
await persistSession(session)
|
|
1342
1366
|
const nextMessages = session.agent.state.messages
|
|
1343
|
-
|
|
1344
|
-
emitSessionEvent(session, { type: '
|
|
1367
|
+
const contextUsage = getSessionContextUsage(session)
|
|
1368
|
+
emitSessionEvent(session, { type: 'message_end', messages: nextMessages, contextUsage })
|
|
1369
|
+
emitSessionEvent(session, { type: 'agent_end', messages: nextMessages, contextUsage })
|
|
1345
1370
|
return getSessionState(sessionId)
|
|
1346
1371
|
}
|
|
1347
1372
|
|
|
@@ -1375,10 +1400,8 @@ export async function runPrompt(sessionId, message) {
|
|
|
1375
1400
|
]
|
|
1376
1401
|
await persistSession(session)
|
|
1377
1402
|
const messages = session.agent.state.messages
|
|
1378
|
-
session
|
|
1379
|
-
session
|
|
1380
|
-
agentEvents.emit('agent_event', { sessionId, type: 'message_end', messages })
|
|
1381
|
-
agentEvents.emit('agent_event', { sessionId, type: 'agent_end', messages })
|
|
1403
|
+
emitSessionEvent(session, { type: 'message_end', messages })
|
|
1404
|
+
emitSessionEvent(session, { type: 'agent_end', messages })
|
|
1382
1405
|
return { sessionId, status: session.status }
|
|
1383
1406
|
}
|
|
1384
1407
|
|
|
@@ -1403,8 +1426,7 @@ export async function runPrompt(sessionId, message) {
|
|
|
1403
1426
|
if (aiTitle && aiTitle !== 'New chat') {
|
|
1404
1427
|
session.title = aiTitle
|
|
1405
1428
|
await persistSession(session)
|
|
1406
|
-
session
|
|
1407
|
-
agentEvents.emit('agent_event', { sessionId, type: 'title_updated', title: aiTitle })
|
|
1429
|
+
emitSessionEvent(session, { type: 'title_updated', title: aiTitle })
|
|
1408
1430
|
}
|
|
1409
1431
|
}).catch((err) => {
|
|
1410
1432
|
logger.warn(`Title generation failed for session ${sessionId}:`, err.message || err, { sessionId })
|
|
@@ -1422,8 +1444,7 @@ export async function runPrompt(sessionId, message) {
|
|
|
1422
1444
|
type: 'error',
|
|
1423
1445
|
error: err.message || 'Unknown error',
|
|
1424
1446
|
}
|
|
1425
|
-
session
|
|
1426
|
-
agentEvents.emit('agent_event', { sessionId, ...event })
|
|
1447
|
+
emitSessionEvent(session, event)
|
|
1427
1448
|
}).finally(() => {
|
|
1428
1449
|
session.activeCommandName = null
|
|
1429
1450
|
session.activeCommandPermissions = null
|
|
@@ -1468,8 +1489,7 @@ export async function abortRun(sessionId) {
|
|
|
1468
1489
|
type: 'agent_end',
|
|
1469
1490
|
messages: session.agent.state.messages,
|
|
1470
1491
|
}
|
|
1471
|
-
session
|
|
1472
|
-
agentEvents.emit('agent_event', { sessionId, ...event })
|
|
1492
|
+
emitSessionEvent(session, event)
|
|
1473
1493
|
}
|
|
1474
1494
|
|
|
1475
1495
|
return { sessionId, aborted: true }
|
|
@@ -1509,6 +1529,15 @@ export function followUpAgent(sessionId, message) {
|
|
|
1509
1529
|
return { sessionId, followUp: true }
|
|
1510
1530
|
}
|
|
1511
1531
|
|
|
1532
|
+
function getSessionContextUsage(session) {
|
|
1533
|
+
try {
|
|
1534
|
+
return estimateSessionContextUsage(session)
|
|
1535
|
+
} catch (error) {
|
|
1536
|
+
logger.warn(`Failed to estimate context usage for session ${session?.sessionId}:`, error?.message || error, { sessionId: session?.sessionId })
|
|
1537
|
+
return null
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1512
1541
|
/**
|
|
1513
1542
|
* Get the current state of a session (for page refresh recovery).
|
|
1514
1543
|
*/
|
|
@@ -1533,6 +1562,7 @@ export function getSessionState(sessionId) {
|
|
|
1533
1562
|
tools: session.agent.state.tools,
|
|
1534
1563
|
messages: session.agent.state.messages,
|
|
1535
1564
|
contextCompaction: session.contextCompaction,
|
|
1565
|
+
contextUsage: getSessionContextUsage(session),
|
|
1536
1566
|
isStreaming: session.agent.state.isStreaming,
|
|
1537
1567
|
errorMessage: session.agent.state.errorMessage,
|
|
1538
1568
|
}
|
|
@@ -1591,6 +1621,14 @@ export async function destroyAgent(sessionId) {
|
|
|
1591
1621
|
// ignore
|
|
1592
1622
|
}
|
|
1593
1623
|
|
|
1624
|
+
// Clean up any pending approvals for this session before removing it.
|
|
1625
|
+
for (const [toolCallId, approval] of pendingApprovals) {
|
|
1626
|
+
if (approval.sessionId === sessionId) approval.reject(new Error('Session destroyed'))
|
|
1627
|
+
}
|
|
1628
|
+
for (const [approvalId, approval] of pendingAutoCompactApprovals) {
|
|
1629
|
+
if (approval.sessionId === sessionId) approval.reject(new Error('Session destroyed'))
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1594
1632
|
// Final persist (empty sessions are cleaned up by persistSession)
|
|
1595
1633
|
try {
|
|
1596
1634
|
await persistSession(session)
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto'
|
|
2
|
+
import { readStore, atomicUpdate } from './storage.mjs'
|
|
3
|
+
import { subagentDefinitions } from './subagents.mjs'
|
|
4
|
+
import { workspaceTools } from './tools/definitions.mjs'
|
|
5
|
+
|
|
6
|
+
const STORE = 'custom-agents'
|
|
7
|
+
const RESERVED_NAMES = new Set(subagentDefinitions.map((definition) => definition.name))
|
|
8
|
+
export const AGENT_PROFILE_TOOL_NAMES = ['read_file', 'grep_files', 'write_file', 'edit_file', 'run_command']
|
|
9
|
+
const allowedToolNames = new Set(AGENT_PROFILE_TOOL_NAMES)
|
|
10
|
+
const nameRegex = /^[a-z][a-z0-9_-]{1,39}$/
|
|
11
|
+
const DEFAULT_MAX_RUNTIME_MS = 30 * 60 * 1000
|
|
12
|
+
const DEFAULT_MAX_TOOL_CALLS = 300
|
|
13
|
+
|
|
14
|
+
function requestError(message, statusCode = 400) {
|
|
15
|
+
const error = new Error(message)
|
|
16
|
+
error.statusCode = statusCode
|
|
17
|
+
return error
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function uniqueStrings(value) {
|
|
21
|
+
if (!Array.isArray(value)) return []
|
|
22
|
+
const result = []
|
|
23
|
+
const seen = new Set()
|
|
24
|
+
for (const item of value) {
|
|
25
|
+
const text = String(item || '').trim()
|
|
26
|
+
if (!text || seen.has(text)) continue
|
|
27
|
+
seen.add(text)
|
|
28
|
+
result.push(text)
|
|
29
|
+
}
|
|
30
|
+
return result
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function normalizeOptionalPositiveInteger(value, fallback, max) {
|
|
34
|
+
if (value === undefined || value === null || value === '') return fallback
|
|
35
|
+
const parsed = Number(value)
|
|
36
|
+
if (!Number.isInteger(parsed) || parsed <= 0) throw requestError('maxToolCalls must be a positive integer')
|
|
37
|
+
return Math.min(parsed, max)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function normalizeOptionalRuntime(value, fallback) {
|
|
41
|
+
if (value === undefined || value === null || value === '') return fallback
|
|
42
|
+
const parsed = Number(value)
|
|
43
|
+
if (!Number.isFinite(parsed) || parsed <= 0) throw requestError('maxRuntimeMs must be a positive number')
|
|
44
|
+
return Math.min(Math.max(Math.round(parsed), 1000), DEFAULT_MAX_RUNTIME_MS)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function builtinProfileFromSubagent(definition) {
|
|
48
|
+
return {
|
|
49
|
+
id: definition.name,
|
|
50
|
+
name: definition.name,
|
|
51
|
+
label: definition.label || definition.name,
|
|
52
|
+
description: definition.description || '',
|
|
53
|
+
systemPrompt: definition.systemPrompt || '',
|
|
54
|
+
allowedTools: [...definition.allowedTools],
|
|
55
|
+
maxRuntimeMs: definition.maxRuntimeMs || DEFAULT_MAX_RUNTIME_MS,
|
|
56
|
+
maxToolCalls: definition.maxToolCalls || DEFAULT_MAX_TOOL_CALLS,
|
|
57
|
+
enabledAsSubagent: true,
|
|
58
|
+
builtin: true,
|
|
59
|
+
createdAt: 'builtin',
|
|
60
|
+
updatedAt: 'builtin',
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function listBuiltinAgentProfiles() {
|
|
65
|
+
return subagentDefinitions.map(builtinProfileFromSubagent)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function normalizeProfileInput(input, existing = null, { creating = false } = {}) {
|
|
69
|
+
const now = new Date().toISOString()
|
|
70
|
+
const name = String(input?.name ?? existing?.name ?? '').trim().toLowerCase()
|
|
71
|
+
if (!nameRegex.test(name)) throw requestError('name must start with a letter and contain only lowercase letters, numbers, underscores, or hyphens')
|
|
72
|
+
if (creating && RESERVED_NAMES.has(name)) throw requestError(`Agent name is reserved: ${name}`, 409)
|
|
73
|
+
if (!creating && existing?.builtin) throw requestError('Built-in agents cannot be modified', 403)
|
|
74
|
+
|
|
75
|
+
const label = String(input?.label ?? existing?.label ?? name).trim().slice(0, 80)
|
|
76
|
+
if (!label) throw requestError('label is required')
|
|
77
|
+
|
|
78
|
+
const allowedTools = uniqueStrings(input?.allowedTools ?? existing?.allowedTools ?? ['read_file', 'grep_files'])
|
|
79
|
+
if (allowedTools.length === 0) throw requestError('allowedTools must contain at least one tool')
|
|
80
|
+
for (const toolName of allowedTools) {
|
|
81
|
+
if (!allowedToolNames.has(toolName)) throw requestError(`Unsupported tool for custom agent: ${toolName}`)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
id: existing?.id || `agent-${randomUUID()}`,
|
|
86
|
+
name,
|
|
87
|
+
label,
|
|
88
|
+
description: String(input?.description ?? existing?.description ?? '').trim().slice(0, 500),
|
|
89
|
+
systemPrompt: String(input?.systemPrompt ?? existing?.systemPrompt ?? '').trim(),
|
|
90
|
+
allowedTools,
|
|
91
|
+
maxRuntimeMs: normalizeOptionalRuntime(input?.maxRuntimeMs ?? existing?.maxRuntimeMs, DEFAULT_MAX_RUNTIME_MS),
|
|
92
|
+
maxToolCalls: normalizeOptionalPositiveInteger(input?.maxToolCalls ?? existing?.maxToolCalls, DEFAULT_MAX_TOOL_CALLS, 300),
|
|
93
|
+
enabledAsSubagent: input?.enabledAsSubagent === undefined ? Boolean(existing?.enabledAsSubagent ?? true) : input.enabledAsSubagent === true,
|
|
94
|
+
builtin: false,
|
|
95
|
+
createdAt: existing?.createdAt || now,
|
|
96
|
+
updatedAt: now,
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function readCustomAgentMap() {
|
|
101
|
+
const data = await readStore(STORE)
|
|
102
|
+
return data && typeof data === 'object' ? data : {}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export async function listAgentProfiles(options = {}) {
|
|
106
|
+
const custom = Object.values(await readCustomAgentMap())
|
|
107
|
+
const profiles = [...listBuiltinAgentProfiles(), ...custom]
|
|
108
|
+
return options.includeDisabled ? profiles : profiles.filter((profile) => profile.enabledAsSubagent || profile.builtin || profile.enabledAsSubagent === false)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export async function listSubagentProfiles() {
|
|
112
|
+
return (await listAgentProfiles({ includeDisabled: true })).filter((profile) => profile.enabledAsSubagent)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export async function getAgentProfile(idOrName) {
|
|
116
|
+
const key = String(idOrName || '').trim().toLowerCase()
|
|
117
|
+
if (!key) return null
|
|
118
|
+
return (await listAgentProfiles({ includeDisabled: true })).find((profile) => profile.id === key || profile.name === key) || null
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export async function createCustomAgentProfile(input) {
|
|
122
|
+
let created = null
|
|
123
|
+
await atomicUpdate(STORE, (data) => {
|
|
124
|
+
const map = data && typeof data === 'object' ? data : {}
|
|
125
|
+
const profile = normalizeProfileInput(input, null, { creating: true })
|
|
126
|
+
if (Object.values(map).some((item) => item?.name === profile.name)) throw requestError(`Agent name already exists: ${profile.name}`, 409)
|
|
127
|
+
created = profile
|
|
128
|
+
map[profile.id] = profile
|
|
129
|
+
return map
|
|
130
|
+
})
|
|
131
|
+
return created
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export async function updateCustomAgentProfile(id, patch) {
|
|
135
|
+
let updated = null
|
|
136
|
+
await atomicUpdate(STORE, (data) => {
|
|
137
|
+
const map = data && typeof data === 'object' ? data : {}
|
|
138
|
+
const current = map[id]
|
|
139
|
+
if (!current) throw requestError('Agent not found', 404)
|
|
140
|
+
const next = normalizeProfileInput(patch, current)
|
|
141
|
+
if (RESERVED_NAMES.has(next.name)) throw requestError(`Agent name is reserved: ${next.name}`, 409)
|
|
142
|
+
if (Object.values(map).some((item) => item?.id !== id && item?.name === next.name)) throw requestError(`Agent name already exists: ${next.name}`, 409)
|
|
143
|
+
updated = next
|
|
144
|
+
map[id] = next
|
|
145
|
+
return map
|
|
146
|
+
})
|
|
147
|
+
return updated
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export async function deleteCustomAgentProfile(id) {
|
|
151
|
+
await atomicUpdate(STORE, (data) => {
|
|
152
|
+
const map = data && typeof data === 'object' ? data : {}
|
|
153
|
+
if (!map[id]) throw requestError('Agent not found', 404)
|
|
154
|
+
delete map[id]
|
|
155
|
+
return map
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function agentProfileSnapshot(profile) {
|
|
160
|
+
if (!profile) return null
|
|
161
|
+
return {
|
|
162
|
+
id: profile.id,
|
|
163
|
+
name: profile.name,
|
|
164
|
+
label: profile.label,
|
|
165
|
+
description: profile.description,
|
|
166
|
+
systemPrompt: profile.systemPrompt,
|
|
167
|
+
allowedTools: [...profile.allowedTools],
|
|
168
|
+
maxRuntimeMs: profile.maxRuntimeMs,
|
|
169
|
+
maxToolCalls: profile.maxToolCalls,
|
|
170
|
+
builtin: profile.builtin === true,
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function listAvailableAgentTools() {
|
|
175
|
+
const labels = {
|
|
176
|
+
read_file: 'Read file',
|
|
177
|
+
grep_files: 'Search files',
|
|
178
|
+
write_file: 'Write file',
|
|
179
|
+
edit_file: 'Edit file',
|
|
180
|
+
run_command: 'Run command',
|
|
181
|
+
}
|
|
182
|
+
const risks = new Set(['write_file', 'edit_file', 'run_command'])
|
|
183
|
+
return workspaceTools
|
|
184
|
+
.filter((tool) => allowedToolNames.has(tool.name))
|
|
185
|
+
.map((tool) => ({
|
|
186
|
+
name: tool.name,
|
|
187
|
+
label: tool.label || labels[tool.name] || tool.name,
|
|
188
|
+
description: tool.description || '',
|
|
189
|
+
riskLevel: risks.has(tool.name) ? 'dangerous' : 'safe',
|
|
190
|
+
}))
|
|
191
|
+
}
|
|
@@ -215,6 +215,24 @@ export function buildAutoCompactLoopMessages(session, messages) {
|
|
|
215
215
|
return [summaryMessage, ...source.slice(compactedUpToIndex)]
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
export function estimateSessionContextUsage(session, messages = session?.agent?.state?.messages ?? []) {
|
|
219
|
+
if (!session?.agent?.state) return null
|
|
220
|
+
const sourceMessages = Array.isArray(messages) ? messages : []
|
|
221
|
+
const contextWindow = Number(session.model?.contextWindow) || 0
|
|
222
|
+
if (sourceMessages.length === 0) {
|
|
223
|
+
return { inputTokens: 0, estimatedInputTokens: 0, knownInputTokens: 0, reservedOutputTokens: 0, totalTokens: 0, contextWindow, percent: 0 }
|
|
224
|
+
}
|
|
225
|
+
const loopMessages = buildAutoCompactLoopMessages(session, sourceMessages)
|
|
226
|
+
const knownInputTokens = latestKnownInputTokens(sourceMessages, latestCompactTimestampMs(session))
|
|
227
|
+
return estimateContextUsage({
|
|
228
|
+
systemPrompt: session.agent.state.systemPrompt,
|
|
229
|
+
messages: loopMessages,
|
|
230
|
+
tools: session.agent.state.tools,
|
|
231
|
+
model: session.model,
|
|
232
|
+
knownInputTokens,
|
|
233
|
+
})
|
|
234
|
+
}
|
|
235
|
+
|
|
218
236
|
export async function maybeAutoCompactSession({ session, messages, signal, emitSessionEvent, persistSession, logger, confirmAutoCompact }) {
|
|
219
237
|
if (!session || session.autoCompacting) return { compacted: false }
|
|
220
238
|
const settings = await readAutoCompactSettings()
|
|
@@ -300,12 +318,14 @@ export async function maybeAutoCompactSession({ session, messages, signal, emitS
|
|
|
300
318
|
usage,
|
|
301
319
|
thresholdPercent: settings.thresholdPercent,
|
|
302
320
|
contextCompaction: session.contextCompaction,
|
|
321
|
+
contextUsage: estimateSessionContextUsage(session, messages),
|
|
303
322
|
})
|
|
304
323
|
emitSessionEvent(session, {
|
|
305
324
|
type: 'messages_replaced',
|
|
306
325
|
reason: 'auto_compact',
|
|
307
326
|
messages,
|
|
308
327
|
contextCompaction: session.contextCompaction,
|
|
328
|
+
contextUsage: estimateSessionContextUsage(session, messages),
|
|
309
329
|
})
|
|
310
330
|
return { compacted: true, usage }
|
|
311
331
|
} catch (error) {
|
package/server/index.mjs
CHANGED
|
@@ -16,6 +16,7 @@ import { handleToolApi, handleGetTools } from './routes/tools.mjs'
|
|
|
16
16
|
import { handleInstructionsApi } from './routes/instructions.mjs'
|
|
17
17
|
import { handleSkillsApi } from './routes/skills.mjs'
|
|
18
18
|
import { handleAgentApi } from './routes/agent.mjs'
|
|
19
|
+
import { handleAgentProfilesApi } from './routes/agent-profiles.mjs'
|
|
19
20
|
import { handleScheduledTasksApi, startScheduledTaskRunner, stopScheduledTaskRunner } from './routes/scheduled-tasks.mjs'
|
|
20
21
|
import { handleBackupApi } from './routes/backup.mjs'
|
|
21
22
|
import { handleSystemApi } from './routes/system.mjs'
|
|
@@ -208,6 +209,12 @@ async function handleApi(req, res, url) {
|
|
|
208
209
|
return
|
|
209
210
|
}
|
|
210
211
|
|
|
212
|
+
// Agent profiles
|
|
213
|
+
if (pathname === '/api/agent-profiles' || pathname.startsWith('/api/agent-profiles/')) {
|
|
214
|
+
await handleAgentProfilesApi(req, res, url)
|
|
215
|
+
return
|
|
216
|
+
}
|
|
217
|
+
|
|
211
218
|
// Skills
|
|
212
219
|
if (pathname === '/api/skills' || pathname.startsWith('/api/skills/')) {
|
|
213
220
|
await handleSkillsApi(req, res, url)
|
|
@@ -319,6 +326,10 @@ function startVite() {
|
|
|
319
326
|
shell: false,
|
|
320
327
|
env: { ...process.env, QUICKFORGE_SERVER_PORT: String(port) },
|
|
321
328
|
})
|
|
329
|
+
viteChild.on('error', (error) => {
|
|
330
|
+
logger.error('Failed to start Vite dev server:', error)
|
|
331
|
+
process.exitCode = 1
|
|
332
|
+
})
|
|
322
333
|
viteChild.on('exit', (code) => {
|
|
323
334
|
if (code && code !== 0) process.exitCode = code
|
|
324
335
|
})
|
|
@@ -485,10 +496,17 @@ const server = createServer(async (req, res) => {
|
|
|
485
496
|
}
|
|
486
497
|
})
|
|
487
498
|
|
|
499
|
+
function writeAndDestroySocket(socket, statusLine) {
|
|
500
|
+
socket.on('error', () => {})
|
|
501
|
+
if (!socket.destroyed) {
|
|
502
|
+
try { socket.write(`${statusLine}\r\n\r\n`) } catch { /* ignore */ }
|
|
503
|
+
}
|
|
504
|
+
socket.destroy()
|
|
505
|
+
}
|
|
506
|
+
|
|
488
507
|
server.on('upgrade', (req, socket, head) => {
|
|
489
508
|
if (!isAllowedHostHeader(req.headers.host)) {
|
|
490
|
-
socket
|
|
491
|
-
socket.destroy()
|
|
509
|
+
writeAndDestroySocket(socket, 'HTTP/1.1 403 Forbidden')
|
|
492
510
|
return
|
|
493
511
|
}
|
|
494
512
|
|
|
@@ -500,11 +518,9 @@ server.on('upgrade', (req, socket, head) => {
|
|
|
500
518
|
})
|
|
501
519
|
return
|
|
502
520
|
}
|
|
503
|
-
socket
|
|
504
|
-
socket.destroy()
|
|
521
|
+
writeAndDestroySocket(socket, 'HTTP/1.1 404 Not Found')
|
|
505
522
|
} catch {
|
|
506
|
-
socket
|
|
507
|
-
socket.destroy()
|
|
523
|
+
writeAndDestroySocket(socket, 'HTTP/1.1 400 Bad Request')
|
|
508
524
|
}
|
|
509
525
|
})
|
|
510
526
|
|
|
@@ -546,5 +562,13 @@ async function gracefulShutdown(signal) {
|
|
|
546
562
|
process.exit(0)
|
|
547
563
|
}
|
|
548
564
|
|
|
549
|
-
|
|
550
|
-
|
|
565
|
+
function handleShutdownSignal(signal) {
|
|
566
|
+
void gracefulShutdown(signal).catch((error) => {
|
|
567
|
+
logger.error('Graceful shutdown failed:', error)
|
|
568
|
+
flushLogger()
|
|
569
|
+
process.exit(1)
|
|
570
|
+
})
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
process.on('SIGINT', handleShutdownSignal)
|
|
574
|
+
process.on('SIGTERM', handleShutdownSignal)
|