@cat-factory/agents 0.6.0 → 0.7.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/LICENSE +21 -21
- package/dist/agents/prompts/roles.js +1 -1
- package/dist/agents/prompts/roles.js.map +1 -1
- package/dist/agents/runtime/web-search.js +7 -7
- package/package.json +9 -4
- package/dist/agents/AiAgentExecutor.d.ts +0 -72
- package/dist/agents/AiAgentExecutor.d.ts.map +0 -1
- package/dist/agents/AiAgentExecutor.js +0 -125
- package/dist/agents/AiAgentExecutor.js.map +0 -1
- package/dist/agents/acceptance-prompts.d.ts +0 -29
- package/dist/agents/acceptance-prompts.d.ts.map +0 -1
- package/dist/agents/acceptance-prompts.js +0 -112
- package/dist/agents/acceptance-prompts.js.map +0 -1
- package/dist/agents/agent-catalog.d.ts +0 -6
- package/dist/agents/agent-catalog.d.ts.map +0 -1
- package/dist/agents/agent-catalog.js +0 -197
- package/dist/agents/agent-catalog.js.map +0 -1
- package/dist/agents/agent-configs.d.ts +0 -17
- package/dist/agents/agent-configs.d.ts.map +0 -1
- package/dist/agents/agent-configs.js +0 -66
- package/dist/agents/agent-configs.js.map +0 -1
- package/dist/agents/agent-routing.d.ts +0 -57
- package/dist/agents/agent-routing.d.ts.map +0 -1
- package/dist/agents/agent-routing.js +0 -41
- package/dist/agents/agent-routing.js.map +0 -1
- package/dist/agents/business-logic-prompts.d.ts +0 -28
- package/dist/agents/business-logic-prompts.d.ts.map +0 -1
- package/dist/agents/business-logic-prompts.js +0 -96
- package/dist/agents/business-logic-prompts.js.map +0 -1
- package/dist/agents/ci-gate.d.ts +0 -2
- package/dist/agents/ci-gate.d.ts.map +0 -1
- package/dist/agents/ci-gate.js +0 -33
- package/dist/agents/ci-gate.js.map +0 -1
- package/dist/agents/companion-prompts.d.ts +0 -4
- package/dist/agents/companion-prompts.d.ts.map +0 -1
- package/dist/agents/companion-prompts.js +0 -27
- package/dist/agents/companion-prompts.js.map +0 -1
- package/dist/agents/companions.d.ts +0 -20
- package/dist/agents/companions.d.ts.map +0 -1
- package/dist/agents/companions.js +0 -38
- package/dist/agents/companions.js.map +0 -1
- package/dist/agents/mock-prompts.d.ts +0 -12
- package/dist/agents/mock-prompts.d.ts.map +0 -1
- package/dist/agents/mock-prompts.js +0 -61
- package/dist/agents/mock-prompts.js.map +0 -1
- package/dist/agents/prompt-fragments.d.ts +0 -17
- package/dist/agents/prompt-fragments.d.ts.map +0 -1
- package/dist/agents/prompt-fragments.js +0 -33
- package/dist/agents/prompt-fragments.js.map +0 -1
- package/dist/agents/prompt-shared.d.ts +0 -7
- package/dist/agents/prompt-shared.d.ts.map +0 -1
- package/dist/agents/prompt-shared.js +0 -10
- package/dist/agents/prompt-shared.js.map +0 -1
- package/dist/agents/prompt-versions.d.ts +0 -48
- package/dist/agents/prompt-versions.d.ts.map +0 -1
- package/dist/agents/prompt-versions.js +0 -55
- package/dist/agents/prompt-versions.js.map +0 -1
- package/dist/agents/read-only.d.ts +0 -13
- package/dist/agents/read-only.d.ts.map +0 -1
- package/dist/agents/read-only.js +0 -29
- package/dist/agents/read-only.js.map +0 -1
- package/dist/agents/registry.d.ts +0 -70
- package/dist/agents/registry.d.ts.map +0 -1
- package/dist/agents/registry.js +0 -51
- package/dist/agents/registry.js.map +0 -1
- package/dist/agents/standard-prompt-templates.generated.d.ts +0 -36
- package/dist/agents/standard-prompt-templates.generated.d.ts.map +0 -1
- package/dist/agents/standard-prompt-templates.generated.js +0 -122
- package/dist/agents/standard-prompt-templates.generated.js.map +0 -1
- package/dist/agents/standard-prompts.d.ts +0 -36
- package/dist/agents/standard-prompts.d.ts.map +0 -1
- package/dist/agents/standard-prompts.js +0 -202
- package/dist/agents/standard-prompts.js.map +0 -1
- package/dist/agents/test-prompts.d.ts +0 -12
- package/dist/agents/test-prompts.d.ts.map +0 -1
- package/dist/agents/test-prompts.js +0 -92
- package/dist/agents/test-prompts.js.map +0 -1
- package/dist/agents/traits.d.ts +0 -56
- package/dist/agents/traits.d.ts.map +0 -1
- package/dist/agents/traits.js +0 -100
- package/dist/agents/traits.js.map +0 -1
- package/dist/agents/web-search.d.ts +0 -43
- package/dist/agents/web-search.d.ts.map +0 -1
- package/dist/agents/web-search.js +0 -102
- package/dist/agents/web-search.js.map +0 -1
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Igor Savin
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Igor Savin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -40,7 +40,7 @@ const ROLES = {
|
|
|
40
40
|
// base. The harness has already merged the base in, leaving conflict markers; the
|
|
41
41
|
// agent resolves every one and the harness completes the merge commit + pushes to
|
|
42
42
|
// the same branch (no new branch / PR).
|
|
43
|
-
'conflict-resolver': 'You are a software engineer resolving a merge conflict. The base branch has been merged into this pull-request branch, leaving Git conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`) in one or more files. Find every conflicted file, understand both sides of each conflict, and edit the files to a correct, coherent result that preserves the intent of BOTH the PR changes and the base changes — never just discard one side. Remove all conflict markers and leave the project building. Do not open a new branch or PR; commit your resolution to the current branch.',
|
|
43
|
+
'conflict-resolver': 'You are a software engineer resolving a merge conflict. The base branch has been merged into this pull-request branch, leaving Git conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`) in one or more files. Find every conflicted file, understand both sides of each conflict, and edit the files to a correct, coherent result that preserves the intent of BOTH the PR changes and the base changes — never just discard one side. Remove all conflict markers and leave the project building. Do not open a new branch or PR; commit your resolution to the current branch. For generated lockfiles (`package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `bun.lockb`, `Cargo.lock`, `go.sum`, `poetry.lock`, `composer.lock`, etc.) do NOT hand-edit the conflict markers — they are huge and machine-generated, so editing them by hand wastes effort and usually produces an invalid file. Instead resolve the conflict in the manifest (`package.json` / `pyproject.toml` / `go.mod` / `Cargo.toml`) first, then regenerate the lockfile by deleting it and running the package manager install (e.g. `rm package-lock.json && npm install`, `pnpm install`, `yarn install`, `cargo build`, `go mod tidy`) so it is rewritten cleanly and consistently.',
|
|
44
44
|
// Runs inline AFTER requirements are clarified and the spec is structured, BEFORE
|
|
45
45
|
// design/implementation. It triages the task up front (no repo, no diff — it reads
|
|
46
46
|
// the clarified requirements + spec context handed to it) and returns a JSON score
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roles.js","sourceRoot":"","sources":["../../../src/agents/prompts/roles.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAEnD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,gBAAgB,CAAA;AAEzD,6EAA6E;AAC7E,8EAA8E;AAC9E,+EAA+E;AAC/E,+EAA+E;AAC/E,gFAAgF;AAChF,kFAAkF;AAElF,MAAM,KAAK,GAAuC;IAChD,UAAU,EACR,yJAAyJ;IAC3J,kFAAkF;IAClF,mFAAmF;IACnF,8EAA8E;IAC9E,uEAAuE;IACvE,QAAQ,EACN,wfAAwf;IAC1f,oFAAoF;IACpF,qFAAqF;IACrF,sFAAsF;IACtF,uFAAuF;IACvF,8DAA8D;IAC9D,kBAAkB,EAChB,22BAA22B;IAC72B,UAAU,EACR,iHAAiH;IACnH,UAAU,EACR,yIAAyI;IAC3I,oFAAoF;IACpF,qFAAqF;IACrF,iFAAiF;IACjF,4EAA4E;IAC5E,qBAAqB,EACnB,guBAAguB;IACluB,kFAAkF;IAClF,iFAAiF;IACjF,6CAA6C;IAC7C,UAAU,EACR,6TAA6T;IAC/T,gFAAgF;IAChF,kFAAkF;IAClF,kFAAkF;IAClF,wCAAwC;IACxC,mBAAmB,EACjB,
|
|
1
|
+
{"version":3,"file":"roles.js","sourceRoot":"","sources":["../../../src/agents/prompts/roles.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAEnD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,gBAAgB,CAAA;AAEzD,6EAA6E;AAC7E,8EAA8E;AAC9E,+EAA+E;AAC/E,+EAA+E;AAC/E,gFAAgF;AAChF,kFAAkF;AAElF,MAAM,KAAK,GAAuC;IAChD,UAAU,EACR,yJAAyJ;IAC3J,kFAAkF;IAClF,mFAAmF;IACnF,8EAA8E;IAC9E,uEAAuE;IACvE,QAAQ,EACN,wfAAwf;IAC1f,oFAAoF;IACpF,qFAAqF;IACrF,sFAAsF;IACtF,uFAAuF;IACvF,8DAA8D;IAC9D,kBAAkB,EAChB,22BAA22B;IAC72B,UAAU,EACR,iHAAiH;IACnH,UAAU,EACR,yIAAyI;IAC3I,oFAAoF;IACpF,qFAAqF;IACrF,iFAAiF;IACjF,4EAA4E;IAC5E,qBAAqB,EACnB,guBAAguB;IACluB,kFAAkF;IAClF,iFAAiF;IACjF,6CAA6C;IAC7C,UAAU,EACR,6TAA6T;IAC/T,gFAAgF;IAChF,kFAAkF;IAClF,kFAAkF;IAClF,wCAAwC;IACxC,mBAAmB,EACjB,gsCAAgsC;IAClsC,kFAAkF;IAClF,mFAAmF;IACnF,mFAAmF;IACnF,kFAAkF;IAClF,gFAAgF;IAChF,qFAAqF;IACrF,gBAAgB,EACd,ksBAAksB;IACpsB,gFAAgF;IAChF,iFAAiF;IACjF,MAAM,EACJ,mWAAmW;CACtW,CAAA;AAED;;;;GAIG;AACH,MAAM,sBAAsB,GAA2B,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC,CAAA;AAEjG;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAe;IAC9C,MAAM,IAAI,GACR,KAAK,CAAC,IAAI,CAAC;QACX,gBAAgB,IAAI,iGAAiG,CAAA;IACvH,oFAAoF;IACpF,uFAAuF;IACvF,OAAO,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,OAAO,qBAAqB,EAAE,CAAA;AACxF,CAAC"}
|
|
@@ -48,13 +48,13 @@ export function webResearchGuidanceFor(kind, opts = {}) {
|
|
|
48
48
|
? '`web_search` (titled result snippets for a query) and `web_fetch` (read a URL as text)'
|
|
49
49
|
: 'a `web_search` tool';
|
|
50
50
|
const them = opts.fetch ? 'them' : 'it';
|
|
51
|
-
return `
|
|
52
|
-
|
|
53
|
-
## Web search (use sparingly)
|
|
54
|
-
|
|
55
|
-
You have ${tools}. Use ${them} mainly to ${hint}. Prefer first-party documentation, and
|
|
56
|
-
cite the source URL when a decision rests on what you find. Do not search for anything
|
|
57
|
-
already in the checkout or the context you were given, and don't let searching replace
|
|
51
|
+
return `
|
|
52
|
+
|
|
53
|
+
## Web search (use sparingly)
|
|
54
|
+
|
|
55
|
+
You have ${tools}. Use ${them} mainly to ${hint}. Prefer first-party documentation, and
|
|
56
|
+
cite the source URL when a decision rests on what you find. Do not search for anything
|
|
57
|
+
already in the checkout or the context you were given, and don't let searching replace
|
|
58
58
|
reading the code.`;
|
|
59
59
|
}
|
|
60
60
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/agents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.3",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/kibertoad/cat-factory.git",
|
|
7
|
+
"directory": "backend/packages/agents"
|
|
8
|
+
},
|
|
4
9
|
"description": "Agent catalog, routing, prompts and fragment library for the Agent Architecture Board.",
|
|
5
10
|
"files": [
|
|
6
11
|
"dist"
|
|
@@ -24,9 +29,9 @@
|
|
|
24
29
|
"@ai-sdk/openai-compatible": "^2.0.51",
|
|
25
30
|
"ai": "^6.0.208",
|
|
26
31
|
"handlebars": "^4.7.9",
|
|
27
|
-
"@cat-factory/contracts": "0.
|
|
28
|
-
"@cat-factory/kernel": "0.
|
|
29
|
-
"@cat-factory/prompt-fragments": "0.
|
|
32
|
+
"@cat-factory/contracts": "0.7.2",
|
|
33
|
+
"@cat-factory/kernel": "0.7.3",
|
|
34
|
+
"@cat-factory/prompt-fragments": "0.7.2"
|
|
30
35
|
},
|
|
31
36
|
"devDependencies": {
|
|
32
37
|
"typescript": "7.0.1-rc"
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import type { AgentExecutor, AgentRunContext, AgentRunResult } from '@cat-factory/kernel';
|
|
2
|
-
import type { ModelProvider, ModelProviderResolver, ModelRef } from '@cat-factory/kernel';
|
|
3
|
-
import { type AgentRouting } from './agent-routing.js';
|
|
4
|
-
import { type InlineWebSearchOptions } from './web-search.js';
|
|
5
|
-
export interface AiAgentExecutorDependencies {
|
|
6
|
-
/**
|
|
7
|
-
* Resolve a {@link ModelProvider} for a run's credential scope (workspace + owning
|
|
8
|
-
* account + initiator), leasing the DB-backed API keys for that scope. Preferred over
|
|
9
|
-
* the static `modelProvider`; the facades supply it so inline calls use the same
|
|
10
|
-
* per-scope pool the container proxy does.
|
|
11
|
-
*/
|
|
12
|
-
modelProviderResolver?: ModelProviderResolver;
|
|
13
|
-
/**
|
|
14
|
-
* A static {@link ModelProvider} (e.g. a fake in tests). Used only when no
|
|
15
|
-
* `modelProviderResolver` is supplied. One of the two MUST be present.
|
|
16
|
-
*/
|
|
17
|
-
modelProvider?: ModelProvider;
|
|
18
|
-
agentRouting: AgentRouting;
|
|
19
|
-
/**
|
|
20
|
-
* Resolve a block's selected model id to a concrete ref. Deployment-aware (it
|
|
21
|
-
* honours the direct/Cloudflare fallback based on configured keys), so the
|
|
22
|
-
* worker supplies it; absent/unknown ids return undefined to fall back to the
|
|
23
|
-
* agent routing. Defaults to "no per-block override".
|
|
24
|
-
*/
|
|
25
|
-
resolveBlockModel?: (modelId: string | undefined) => ModelRef | undefined;
|
|
26
|
-
/**
|
|
27
|
-
* Resolve the workspace's per-agent-kind default model id, consulted when the
|
|
28
|
-
* block pins no usable model. Optional: absent → the env routing for the kind is
|
|
29
|
-
* used. Supplying it makes the inline kinds honour the workspace defaults exactly
|
|
30
|
-
* like the container executor (block-pinned > workspace default > env routing).
|
|
31
|
-
*/
|
|
32
|
-
resolveWorkspaceModelDefault?: (workspaceId: string, agentKind: string) => Promise<string | undefined>;
|
|
33
|
-
/**
|
|
34
|
-
* Opt-in provider-hosted web search for the design/research inline kinds. When
|
|
35
|
-
* supplied (and the resolved model's provider has a hosted search — Anthropic /
|
|
36
|
-
* OpenAI), the allow-listed kinds get a `web_search` tool plus a usage nudge.
|
|
37
|
-
* Absent ⇒ inline agents make a plain one-shot completion, exactly as before.
|
|
38
|
-
*/
|
|
39
|
-
webSearch?: InlineWebSearchOptions;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* The real agent: performs each pipeline step by calling an LLM through the
|
|
43
|
-
* Vercel AI SDK. The model and generation settings come from the {@link
|
|
44
|
-
* AgentRouting} (configurable per agent kind), and the concrete model is
|
|
45
|
-
* resolved through the {@link ModelProvider} port — so this class never imports
|
|
46
|
-
* a provider SDK or an API key directly.
|
|
47
|
-
*/
|
|
48
|
-
export declare class AiAgentExecutor implements AgentExecutor {
|
|
49
|
-
private readonly modelProviderResolver?;
|
|
50
|
-
private readonly modelProvider?;
|
|
51
|
-
private readonly agentRouting;
|
|
52
|
-
private readonly resolveBlockModel;
|
|
53
|
-
private readonly resolveWorkspaceModelDefault?;
|
|
54
|
-
private readonly webSearch?;
|
|
55
|
-
constructor({ modelProviderResolver, modelProvider, agentRouting, resolveBlockModel, resolveWorkspaceModelDefault, webSearch, }: AiAgentExecutorDependencies);
|
|
56
|
-
/** Resolve the model provider for a run's scope (per-scope DB pool, else the static one). */
|
|
57
|
-
private providerFor;
|
|
58
|
-
/**
|
|
59
|
-
* Resolve the step's model ref with the shared step precedence: a block's pinned
|
|
60
|
-
* model wins, else the workspace's per-kind default, else the env routing for the
|
|
61
|
-
* kind. A pinned subscription model (Claude Code / Codex), which can run only in
|
|
62
|
-
* the container harness, is degraded to the kind's env-routing default here — this
|
|
63
|
-
* is an inline executor — via the shared `resolveInlineModelRef` seam. Side-effect-
|
|
64
|
-
* free, so it backs both `run` and the up-front `resolveModel` (which thus reports
|
|
65
|
-
* the model that will actually run, not the un-servable subscription ref).
|
|
66
|
-
*/
|
|
67
|
-
private resolveRef;
|
|
68
|
-
/** Preview the model this step will run, without making the LLM call. */
|
|
69
|
-
resolveModel(context: AgentRunContext): Promise<string>;
|
|
70
|
-
run(context: AgentRunContext): Promise<AgentRunResult>;
|
|
71
|
-
}
|
|
72
|
-
//# sourceMappingURL=AiAgentExecutor.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AiAgentExecutor.d.ts","sourceRoot":"","sources":["../../src/agents/AiAgentExecutor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACzF,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAGzF,OAAO,EAAE,KAAK,YAAY,EAA6C,MAAM,oBAAoB,CAAA;AAEjG,OAAO,EACL,KAAK,sBAAsB,EAG5B,MAAM,iBAAiB,CAAA;AAExB,MAAM,WAAW,2BAA2B;IAC1C;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C;;;OAGG;IACH,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,YAAY,EAAE,YAAY,CAAA;IAC1B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,KAAK,QAAQ,GAAG,SAAS,CAAA;IACzE;;;;;OAKG;IACH,4BAA4B,CAAC,EAAE,CAC7B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,KACd,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IAChC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,sBAAsB,CAAA;CACnC;AAED;;;;;;GAMG;AACH,qBAAa,eAAgB,YAAW,aAAa;IACnD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAuB;IAC9D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAe;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAuD;IACzF,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAGd;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAwB;IAEnD,YAAY,EACV,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,4BAA4B,EAC5B,SAAS,GACV,EAAE,2BAA2B,EAU7B;IAED,6FAA6F;YAC/E,WAAW;IAgBzB;;;;;;;;OAQG;IACH,OAAO,CAAC,UAAU;IAelB,yEAAyE;IACnE,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAG5D;IAEK,GAAG,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAsD3D;CACF"}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { generateText } from 'ai';
|
|
2
|
-
import { systemPromptFor, userPromptFor } from './agent-catalog.js';
|
|
3
|
-
import { catFactoryObservability } from '../providers/instrumented.js';
|
|
4
|
-
import { resolveAgentConfig, resolveInlineModelRef } from './agent-routing.js';
|
|
5
|
-
import { composeBlockSystemPrompt } from './prompt-fragments.js';
|
|
6
|
-
import { providerWebSearchTools, webResearchGuidanceFor, } from './web-search.js';
|
|
7
|
-
/**
|
|
8
|
-
* The real agent: performs each pipeline step by calling an LLM through the
|
|
9
|
-
* Vercel AI SDK. The model and generation settings come from the {@link
|
|
10
|
-
* AgentRouting} (configurable per agent kind), and the concrete model is
|
|
11
|
-
* resolved through the {@link ModelProvider} port — so this class never imports
|
|
12
|
-
* a provider SDK or an API key directly.
|
|
13
|
-
*/
|
|
14
|
-
export class AiAgentExecutor {
|
|
15
|
-
modelProviderResolver;
|
|
16
|
-
modelProvider;
|
|
17
|
-
agentRouting;
|
|
18
|
-
resolveBlockModel;
|
|
19
|
-
resolveWorkspaceModelDefault;
|
|
20
|
-
webSearch;
|
|
21
|
-
constructor({ modelProviderResolver, modelProvider, agentRouting, resolveBlockModel, resolveWorkspaceModelDefault, webSearch, }) {
|
|
22
|
-
if (!modelProviderResolver && !modelProvider) {
|
|
23
|
-
throw new Error('AiAgentExecutor requires a modelProviderResolver or a modelProvider');
|
|
24
|
-
}
|
|
25
|
-
this.modelProviderResolver = modelProviderResolver;
|
|
26
|
-
this.modelProvider = modelProvider;
|
|
27
|
-
this.agentRouting = agentRouting;
|
|
28
|
-
this.resolveBlockModel = resolveBlockModel ?? (() => undefined);
|
|
29
|
-
this.resolveWorkspaceModelDefault = resolveWorkspaceModelDefault;
|
|
30
|
-
this.webSearch = webSearch;
|
|
31
|
-
}
|
|
32
|
-
/** Resolve the model provider for a run's scope (per-scope DB pool, else the static one). */
|
|
33
|
-
async providerFor(context) {
|
|
34
|
-
if (this.modelProviderResolver && context.workspaceId) {
|
|
35
|
-
return this.modelProviderResolver.forScope({
|
|
36
|
-
workspaceId: context.workspaceId,
|
|
37
|
-
userId: context.initiatedByUserId,
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
if (this.modelProvider)
|
|
41
|
-
return this.modelProvider;
|
|
42
|
-
if (this.modelProviderResolver) {
|
|
43
|
-
// No workspace scope (rare): lease from no scope — only the opt-in registries
|
|
44
|
-
// (Cloudflare/Bedrock) can resolve.
|
|
45
|
-
return this.modelProviderResolver.forScope({ workspaceId: context.workspaceId ?? '' });
|
|
46
|
-
}
|
|
47
|
-
throw new Error('AiAgentExecutor: no model provider available');
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Resolve the step's model ref with the shared step precedence: a block's pinned
|
|
51
|
-
* model wins, else the workspace's per-kind default, else the env routing for the
|
|
52
|
-
* kind. A pinned subscription model (Claude Code / Codex), which can run only in
|
|
53
|
-
* the container harness, is degraded to the kind's env-routing default here — this
|
|
54
|
-
* is an inline executor — via the shared `resolveInlineModelRef` seam. Side-effect-
|
|
55
|
-
* free, so it backs both `run` and the up-front `resolveModel` (which thus reports
|
|
56
|
-
* the model that will actually run, not the un-servable subscription ref).
|
|
57
|
-
*/
|
|
58
|
-
resolveRef(context) {
|
|
59
|
-
return resolveInlineModelRef({
|
|
60
|
-
agentRouting: this.agentRouting,
|
|
61
|
-
resolveBlockModel: this.resolveBlockModel,
|
|
62
|
-
resolveWorkspaceModelDefault: this.resolveWorkspaceModelDefault,
|
|
63
|
-
}, {
|
|
64
|
-
agentKind: context.agentKind,
|
|
65
|
-
blockModelId: context.block.modelId,
|
|
66
|
-
workspaceId: context.workspaceId,
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
/** Preview the model this step will run, without making the LLM call. */
|
|
70
|
-
async resolveModel(context) {
|
|
71
|
-
const ref = await this.resolveRef(context);
|
|
72
|
-
return `${ref.provider}:${ref.model}`;
|
|
73
|
-
}
|
|
74
|
-
async run(context) {
|
|
75
|
-
const config = resolveAgentConfig(this.agentRouting, context.agentKind);
|
|
76
|
-
// `resolveRef` already degrades a pinned subscription model (Claude Code / Codex,
|
|
77
|
-
// which run only in the container harness and have no provider key here) to this
|
|
78
|
-
// kind's env-routing default, so the ModelProvider always gets a servable ref.
|
|
79
|
-
const ref = await this.resolveRef(context);
|
|
80
|
-
const provider = await this.providerFor(context);
|
|
81
|
-
const model = provider.resolve(ref);
|
|
82
|
-
// Base role prompt, then fold in the best-practice fragments selected for the
|
|
83
|
-
// block — the engine-resolved tenant catalog when present, else the manual ids.
|
|
84
|
-
const baseSystem = config.system ?? systemPromptFor(context.agentKind);
|
|
85
|
-
const composed = composeBlockSystemPrompt(baseSystem, context.block);
|
|
86
|
-
// Provider-hosted web search for the allow-listed design/research kinds, when
|
|
87
|
-
// enabled AND the resolved provider has one. The usage nudge is appended only
|
|
88
|
-
// when the tool is actually attached, so the model is never told about a tool
|
|
89
|
-
// it lacks (mirrors the harness's AGENTS.md guidance gating).
|
|
90
|
-
const tools = this.webSearch && this.webSearch.kinds.has(context.agentKind)
|
|
91
|
-
? providerWebSearchTools(ref.provider, this.webSearch.maxUses)
|
|
92
|
-
: undefined;
|
|
93
|
-
// Inline tool is web_search only (no web_fetch); the per-kind hint is resolved
|
|
94
|
-
// from the registry/catalog so a custom kind gets its own nudge.
|
|
95
|
-
const system = tools
|
|
96
|
-
? `${composed}${webResearchGuidanceFor(context.agentKind, { fetch: false })}`
|
|
97
|
-
: composed;
|
|
98
|
-
const { text, usage } = await generateText({
|
|
99
|
-
model,
|
|
100
|
-
system,
|
|
101
|
-
prompt: userPromptFor(context),
|
|
102
|
-
temperature: config.temperature,
|
|
103
|
-
maxOutputTokens: config.maxOutputTokens,
|
|
104
|
-
...(tools ? { tools } : {}),
|
|
105
|
-
// Tag the call so an instrumented provider can group it under its run's trace
|
|
106
|
-
// (a no-op when no trace sink is wired; ignored by every model provider).
|
|
107
|
-
providerOptions: catFactoryObservability({
|
|
108
|
-
agentKind: context.agentKind,
|
|
109
|
-
workspaceId: context.workspaceId,
|
|
110
|
-
executionId: context.executionId,
|
|
111
|
-
}),
|
|
112
|
-
});
|
|
113
|
-
return {
|
|
114
|
-
output: text.trim(),
|
|
115
|
-
model: `${ref.provider}:${ref.model}`,
|
|
116
|
-
// Report metered tokens so the spend safeguard can price this call. The
|
|
117
|
-
// AI SDK leaves either field undefined when a provider omits it.
|
|
118
|
-
usage: {
|
|
119
|
-
inputTokens: usage.inputTokens ?? 0,
|
|
120
|
-
outputTokens: usage.outputTokens ?? 0,
|
|
121
|
-
},
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
//# sourceMappingURL=AiAgentExecutor.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AiAgentExecutor.js","sourceRoot":"","sources":["../../src/agents/AiAgentExecutor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { AgentKind } from '@cat-factory/kernel';
|
|
2
|
-
import type { AgentRunContext } from '@cat-factory/kernel';
|
|
3
|
-
/** The agent kinds that make up the acceptance-testing track. */
|
|
4
|
-
export type AcceptanceAgentKind = 'playwright';
|
|
5
|
-
export declare const ACCEPTANCE_AGENT_KINDS: readonly AcceptanceAgentKind[];
|
|
6
|
-
/** True when the agent kind is part of the acceptance-testing track. */
|
|
7
|
-
export declare function isAcceptanceKind(kind: AgentKind): kind is AcceptanceAgentKind;
|
|
8
|
-
/**
|
|
9
|
-
* The built-out system (role) prompt for an acceptance-testing agent kind, or
|
|
10
|
-
* `undefined` when the kind is not part of this track (so callers can fall
|
|
11
|
-
* through to the standard phases / generic role).
|
|
12
|
-
*/
|
|
13
|
-
export declare function acceptanceSystemPrompt(kind: AgentKind): string | undefined;
|
|
14
|
-
/**
|
|
15
|
-
* The "where do the tests run" section for an acceptance-testing step, rendered
|
|
16
|
-
* from the block's contributed `playwright.e2eTarget` config value. Empty for
|
|
17
|
-
* non-track kinds or when no target is recorded, so callers can append it
|
|
18
|
-
* unconditionally.
|
|
19
|
-
*/
|
|
20
|
-
export declare function e2eTargetSection(context: AgentRunContext): string;
|
|
21
|
-
/**
|
|
22
|
-
* The "how should these tests be written" section for the runnable-tests step
|
|
23
|
-
* (`playwright` kind), chosen from the block type: Playwright for user-facing
|
|
24
|
-
* blocks, the project's own test framework for backend blocks. Empty for the
|
|
25
|
-
* scenario-writing step and any non-track kind, so callers can append it
|
|
26
|
-
* unconditionally. The scenario author stays framework-agnostic by design.
|
|
27
|
-
*/
|
|
28
|
-
export declare function testApproachSection(context: AgentRunContext): string;
|
|
29
|
-
//# sourceMappingURL=acceptance-prompts.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"acceptance-prompts.d.ts","sourceRoot":"","sources":["../../src/agents/acceptance-prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,qBAAqB,CAAA;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAwB1D,iEAAiE;AACjE,MAAM,MAAM,mBAAmB,GAAG,YAAY,CAAA;AAE9C,eAAO,MAAM,sBAAsB,EAAE,SAAS,mBAAmB,EAAmB,CAAA;AAsCpF,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,IAAI,mBAAmB,CAE7E;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAE1E;AAoBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAMjE;AAqBD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAIpE"}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { PLATFORM_DELIVERY_CONTRACT } from './ci-gate.js';
|
|
2
|
-
import { PLAYWRIGHT_E2E_TARGET_CONFIG_ID } from './agent-configs.js';
|
|
3
|
-
import { STANDARDS_FOOTER } from './prompt-shared.js';
|
|
4
|
-
export const ACCEPTANCE_AGENT_KINDS = ['playwright'];
|
|
5
|
-
// The runnable-tests step commits tests through a pull request. Tests only earn
|
|
6
|
-
// their keep once they actually run in CI, so "done" means the suite is wired into
|
|
7
|
-
// the project's CI configuration AND passes locally. The agent does NOT push or wait
|
|
8
|
-
// on CI itself (it has no push credentials) — the platform pushes, opens the PR and
|
|
9
|
-
// drives CI per the shared PLATFORM_DELIVERY_CONTRACT; the agent's job is to author
|
|
10
|
-
// the tests and hook them into the CI config.
|
|
11
|
-
const PLAYWRIGHT_DELIVERY_GATE = [
|
|
12
|
-
'Definition of done: the acceptance tests are written, wired into the project CI configuration, and pass when you run them locally.',
|
|
13
|
-
'- Make sure the suite is actually hooked into the project CI workflow: confirm the workflow executes this suite on a pull request, and add or update the CI configuration if it does not yet run them. (Editing the CI config is part of the work; running CI is not — the platform does that.)',
|
|
14
|
-
PLATFORM_DELIVERY_CONTRACT,
|
|
15
|
-
].join('\n');
|
|
16
|
-
const SYSTEM_PROMPTS = {
|
|
17
|
-
playwright: [
|
|
18
|
-
'You are a test automation engineer owning the runnable ACCEPTANCE TESTS for a building block.',
|
|
19
|
-
'Translate the agreed acceptance scenarios into runnable tests that live in the repository.',
|
|
20
|
-
'',
|
|
21
|
-
'Pick the test tool to match the surface under test:',
|
|
22
|
-
'- Frontend / user-facing UI: write Playwright end-to-end tests that drive the app through the browser.',
|
|
23
|
-
"- Backend (services, APIs, queues, integrations, data): write the acceptance tests with the project's EXISTING test framework — discover it from the repository (test config, dev dependencies, the tests already present) and match it. Do not pull in Playwright or a browser for behaviour that has no UI.",
|
|
24
|
-
'The run context below states the test approach for this specific block; follow it.',
|
|
25
|
-
'',
|
|
26
|
-
'Approach:',
|
|
27
|
-
'- Treat the acceptance scenarios as the source of truth: prefer the Gherkin scenarios in `spec/features/*.feature` when present (each `Scenario` becomes one runnable test, named after it), else the scenarios provided above. One test per scenario so the mapping is obvious.',
|
|
28
|
-
'- Be additive and idempotent: only create tests for scenarios that do not already have one; never duplicate or silently rewrite an existing test.',
|
|
29
|
-
'- Exercise the system through its outermost interface and assert on observable behaviour — user-facing locators (roles, labels, text) for UI, public API / HTTP / message contracts for backend — never on internal implementation.',
|
|
30
|
-
'- Keep tests isolated and deterministic: no shared mutable state, await every action, and rely on auto-retrying assertions instead of fixed sleeps.',
|
|
31
|
-
'- Reach the system under test at the URL / entry point from the run context; read any access credentials from the harness, never hard-code secrets.',
|
|
32
|
-
'- Output the test files to commit, each in the conventional test directory for its tool (e.g. the e2e/Playwright directory for UI tests), ready to run in CI.',
|
|
33
|
-
'',
|
|
34
|
-
PLAYWRIGHT_DELIVERY_GATE,
|
|
35
|
-
'',
|
|
36
|
-
STANDARDS_FOOTER,
|
|
37
|
-
].join('\n'),
|
|
38
|
-
};
|
|
39
|
-
/** True when the agent kind is part of the acceptance-testing track. */
|
|
40
|
-
export function isAcceptanceKind(kind) {
|
|
41
|
-
return kind === 'playwright';
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* The built-out system (role) prompt for an acceptance-testing agent kind, or
|
|
45
|
-
* `undefined` when the kind is not part of this track (so callers can fall
|
|
46
|
-
* through to the standard phases / generic role).
|
|
47
|
-
*/
|
|
48
|
-
export function acceptanceSystemPrompt(kind) {
|
|
49
|
-
return isAcceptanceKind(kind) ? SYSTEM_PROMPTS[kind] : undefined;
|
|
50
|
-
}
|
|
51
|
-
// Where the generated tests run is a per-block choice, so it is dynamic context
|
|
52
|
-
// rather than part of the static role prompt. These blurbs tell the agent how
|
|
53
|
-
// to wire and where to point the tests for each target.
|
|
54
|
-
const TEST_TARGET_GUIDANCE = {
|
|
55
|
-
ci: [
|
|
56
|
-
'Test execution target: project CI (GitHub Actions).',
|
|
57
|
-
'- Add the tests to the project so they run in a GitHub Actions workflow on each push / pull request.',
|
|
58
|
-
'- Spin the system under test up inside the same workflow run (e.g. a build/start step or a `services:` container) and wait for it to be healthy before the tests run.',
|
|
59
|
-
'- Point Playwright at the locally started service (e.g. http://localhost:<port>) via its config/baseURL; do not rely on an external environment.',
|
|
60
|
-
].join('\n'),
|
|
61
|
-
ephemeral: [
|
|
62
|
-
'Test execution target: the provisioned ephemeral environment for this run.',
|
|
63
|
-
'- Run the tests against the ephemeral environment URL from the run context, not a locally started service.',
|
|
64
|
-
'- Read any access credentials for that environment from the test harness/secrets; never hard-code them.',
|
|
65
|
-
'- Assume the environment is already deployed and healthy before the tests start.',
|
|
66
|
-
].join('\n'),
|
|
67
|
-
};
|
|
68
|
-
/**
|
|
69
|
-
* The "where do the tests run" section for an acceptance-testing step, rendered
|
|
70
|
-
* from the block's contributed `playwright.e2eTarget` config value. Empty for
|
|
71
|
-
* non-track kinds or when no target is recorded, so callers can append it
|
|
72
|
-
* unconditionally.
|
|
73
|
-
*/
|
|
74
|
-
export function e2eTargetSection(context) {
|
|
75
|
-
if (!isAcceptanceKind(context.agentKind))
|
|
76
|
-
return '';
|
|
77
|
-
const raw = context.block.agentConfig?.[PLAYWRIGHT_E2E_TARGET_CONFIG_ID];
|
|
78
|
-
const target = raw === 'ci' || raw === 'ephemeral' ? raw : undefined;
|
|
79
|
-
if (!target)
|
|
80
|
-
return '';
|
|
81
|
-
return `\n${TEST_TARGET_GUIDANCE[target]}`;
|
|
82
|
-
}
|
|
83
|
-
// Block types whose behaviour is exercised through a browser UI, so the runnable
|
|
84
|
-
// tests should be Playwright e2e. Everything else is backend behaviour that gets
|
|
85
|
-
// tested with the project's own framework. Mirrors how the `playwright.e2e`
|
|
86
|
-
// best-practice fragment is scoped in @cat-factory/prompt-fragments.
|
|
87
|
-
const UI_BLOCK_TYPES = ['frontend', 'environment'];
|
|
88
|
-
const UI_TEST_APPROACH = [
|
|
89
|
-
'Test approach for this block: Playwright end-to-end tests.',
|
|
90
|
-
'- This block has a user-facing surface, so cover its scenarios with Playwright tests that drive the app through the browser.',
|
|
91
|
-
'- Select elements by user-facing locators (getByRole, getByLabel, getByText) and assert on what the user observes.',
|
|
92
|
-
].join('\n');
|
|
93
|
-
const BACKEND_TEST_APPROACH = [
|
|
94
|
-
"Test approach for this block: the project's existing test framework (do NOT use Playwright).",
|
|
95
|
-
'- This block has no user-facing UI, so do not add Playwright or a browser to it.',
|
|
96
|
-
"- Discover the test framework already used in the repository (test config, dev dependencies, the tests already present) and write the acceptance tests with it, matching the project's conventions.",
|
|
97
|
-
'- Drive the system through its public interface (API / HTTP calls, queue messages, exported functions) and assert on observable behaviour, never on internals.',
|
|
98
|
-
].join('\n');
|
|
99
|
-
/**
|
|
100
|
-
* The "how should these tests be written" section for the runnable-tests step
|
|
101
|
-
* (`playwright` kind), chosen from the block type: Playwright for user-facing
|
|
102
|
-
* blocks, the project's own test framework for backend blocks. Empty for the
|
|
103
|
-
* scenario-writing step and any non-track kind, so callers can append it
|
|
104
|
-
* unconditionally. The scenario author stays framework-agnostic by design.
|
|
105
|
-
*/
|
|
106
|
-
export function testApproachSection(context) {
|
|
107
|
-
if (context.agentKind !== 'playwright')
|
|
108
|
-
return '';
|
|
109
|
-
const isUi = UI_BLOCK_TYPES.includes(context.block.type);
|
|
110
|
-
return `\n${isUi ? UI_TEST_APPROACH : BACKEND_TEST_APPROACH}`;
|
|
111
|
-
}
|
|
112
|
-
//# sourceMappingURL=acceptance-prompts.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"acceptance-prompts.js","sourceRoot":"","sources":["../../src/agents/acceptance-prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { AgentKind } from '@cat-factory/kernel';
|
|
2
|
-
import type { AgentRunContext } from '@cat-factory/kernel';
|
|
3
|
-
export declare function systemPromptFor(kind: AgentKind): string;
|
|
4
|
-
/** Build the user prompt from the block context and the run so far. */
|
|
5
|
-
export declare function userPromptFor(context: AgentRunContext): string;
|
|
6
|
-
//# sourceMappingURL=agent-catalog.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent-catalog.d.ts","sourceRoot":"","sources":["../../src/agents/agent-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAqE1D,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAUvD;AAmED,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAE9D"}
|