@cat-factory/worker 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.
Files changed (58) hide show
  1. package/LICENSE +21 -21
  2. package/dist/infrastructure/config/agents.d.ts.map +1 -1
  3. package/dist/infrastructure/config/agents.js +10 -0
  4. package/dist/infrastructure/config/agents.js.map +1 -1
  5. package/dist/infrastructure/container.d.ts.map +1 -1
  6. package/dist/infrastructure/container.js +36 -2
  7. package/dist/infrastructure/container.js.map +1 -1
  8. package/dist/infrastructure/repositories/D1BootstrapJobRepository.js +4 -4
  9. package/dist/infrastructure/repositories/D1ModelDefaultsRepository.js +1 -1
  10. package/dist/infrastructure/repositories/D1PipelineScheduleRepository.js +25 -25
  11. package/dist/infrastructure/repositories/D1RepoProjectionRepository.js +6 -6
  12. package/dist/infrastructure/repositories/D1ServiceRepository.js +1 -1
  13. package/dist/infrastructure/repositories/D1TrackerSettingsRepository.d.ts.map +1 -1
  14. package/dist/infrastructure/repositories/D1TrackerSettingsRepository.js +12 -6
  15. package/dist/infrastructure/repositories/D1TrackerSettingsRepository.js.map +1 -1
  16. package/dist/infrastructure/repositories/D1WorkspaceMountRepository.js +8 -8
  17. package/migrations/0005_issue_tracker_writeback.sql +11 -0
  18. package/package.json +18 -13
  19. package/dist/infrastructure/ai/CloudflareModelProvider.d.ts +0 -23
  20. package/dist/infrastructure/ai/CloudflareModelProvider.d.ts.map +0 -1
  21. package/dist/infrastructure/ai/CloudflareModelProvider.js +0 -62
  22. package/dist/infrastructure/ai/CloudflareModelProvider.js.map +0 -1
  23. package/dist/infrastructure/ai/ContainerRepoScanner.d.ts +0 -39
  24. package/dist/infrastructure/ai/ContainerRepoScanner.d.ts.map +0 -1
  25. package/dist/infrastructure/ai/ContainerRepoScanner.js +0 -115
  26. package/dist/infrastructure/ai/ContainerRepoScanner.js.map +0 -1
  27. package/dist/infrastructure/documents/ConfluenceProvider.d.ts +0 -29
  28. package/dist/infrastructure/documents/ConfluenceProvider.d.ts.map +0 -1
  29. package/dist/infrastructure/documents/ConfluenceProvider.js +0 -179
  30. package/dist/infrastructure/documents/ConfluenceProvider.js.map +0 -1
  31. package/dist/infrastructure/documents/GitHubDocsProvider.d.ts +0 -42
  32. package/dist/infrastructure/documents/GitHubDocsProvider.d.ts.map +0 -1
  33. package/dist/infrastructure/documents/GitHubDocsProvider.js +0 -85
  34. package/dist/infrastructure/documents/GitHubDocsProvider.js.map +0 -1
  35. package/dist/infrastructure/documents/NotionProvider.d.ts +0 -32
  36. package/dist/infrastructure/documents/NotionProvider.d.ts.map +0 -1
  37. package/dist/infrastructure/documents/NotionProvider.js +0 -220
  38. package/dist/infrastructure/documents/NotionProvider.js.map +0 -1
  39. package/dist/infrastructure/environments/HttpEnvironmentProvider.d.ts +0 -27
  40. package/dist/infrastructure/environments/HttpEnvironmentProvider.d.ts.map +0 -1
  41. package/dist/infrastructure/environments/HttpEnvironmentProvider.js +0 -314
  42. package/dist/infrastructure/environments/HttpEnvironmentProvider.js.map +0 -1
  43. package/dist/infrastructure/events/InAppNotificationChannel.d.ts +0 -19
  44. package/dist/infrastructure/events/InAppNotificationChannel.d.ts.map +0 -1
  45. package/dist/infrastructure/events/InAppNotificationChannel.js +0 -22
  46. package/dist/infrastructure/events/InAppNotificationChannel.js.map +0 -1
  47. package/dist/infrastructure/repositories/D1RepoBlueprintRepository.d.ts +0 -20
  48. package/dist/infrastructure/repositories/D1RepoBlueprintRepository.d.ts.map +0 -1
  49. package/dist/infrastructure/repositories/D1RepoBlueprintRepository.js +0 -64
  50. package/dist/infrastructure/repositories/D1RepoBlueprintRepository.js.map +0 -1
  51. package/dist/infrastructure/tasks/GitHubIssuesProvider.d.ts +0 -50
  52. package/dist/infrastructure/tasks/GitHubIssuesProvider.d.ts.map +0 -1
  53. package/dist/infrastructure/tasks/GitHubIssuesProvider.js +0 -91
  54. package/dist/infrastructure/tasks/GitHubIssuesProvider.js.map +0 -1
  55. package/dist/infrastructure/tasks/JiraProvider.d.ts +0 -29
  56. package/dist/infrastructure/tasks/JiraProvider.d.ts.map +0 -1
  57. package/dist/infrastructure/tasks/JiraProvider.js +0 -109
  58. package/dist/infrastructure/tasks/JiraProvider.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,11 @@
1
1
  {
2
2
  "name": "@cat-factory/worker",
3
- "version": "0.6.0",
3
+ "version": "0.7.3",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/kibertoad/cat-factory.git",
7
+ "directory": "backend/runtimes/cloudflare"
8
+ },
4
9
  "description": "Reusable Cloudflare Worker library (Hono + D1) exposing the Agent Architecture Board core: the `createApp()` Hono factory, the default fetch/scheduled/queue handler, and the Durable Object + Workflow classes. Deployments (see deploy/backend) supply the wrangler.toml + config and re-export these.",
5
10
  "files": [
6
11
  "dist",
@@ -34,17 +39,17 @@
34
39
  "pino": "^9.14.0",
35
40
  "valibot": "^1.4.1",
36
41
  "workers-ai-provider": "^3.2.0",
37
- "@cat-factory/agents": "0.6.0",
38
- "@cat-factory/consensus": "0.6.0",
39
- "@cat-factory/observability-langfuse": "0.6.0",
40
- "@cat-factory/server": "0.6.0",
41
- "@cat-factory/contracts": "0.6.0",
42
- "@cat-factory/integrations": "0.6.0",
43
- "@cat-factory/orchestration": "0.6.0",
44
- "@cat-factory/kernel": "0.6.0",
45
- "@cat-factory/spend": "0.6.0",
46
- "@cat-factory/prompt-fragments": "0.6.0",
47
- "@cat-factory/provider-cloudflare": "0.6.0"
42
+ "@cat-factory/agents": "0.7.3",
43
+ "@cat-factory/consensus": "0.7.3",
44
+ "@cat-factory/contracts": "0.7.2",
45
+ "@cat-factory/integrations": "0.7.3",
46
+ "@cat-factory/kernel": "0.7.3",
47
+ "@cat-factory/observability-langfuse": "0.7.3",
48
+ "@cat-factory/orchestration": "0.7.3",
49
+ "@cat-factory/prompt-fragments": "0.7.2",
50
+ "@cat-factory/provider-cloudflare": "0.7.3",
51
+ "@cat-factory/server": "0.7.3",
52
+ "@cat-factory/spend": "0.7.3"
48
53
  },
49
54
  "devDependencies": {
50
55
  "@cloudflare/vitest-pool-workers": "^0.16.17",
@@ -52,7 +57,7 @@
52
57
  "typescript": "7.0.1-rc",
53
58
  "vitest": "^4.1.9",
54
59
  "wrangler": "^4.102.0",
55
- "@cat-factory/conformance": "0.6.0"
60
+ "@cat-factory/conformance": "0.7.3"
56
61
  },
57
62
  "scripts": {
58
63
  "build": "tsc -b tsconfig.build.json",
@@ -1,23 +0,0 @@
1
- import { type ProviderRegistry } from '@cat-factory/agents';
2
- import type { ModelProvider, ModelRef } from '@cat-factory/kernel';
3
- import type { LanguageModel } from 'ai';
4
- import type { Env } from '../env';
5
- /**
6
- * Resolves a provider-agnostic {@link ModelRef} into a concrete Vercel AI SDK model.
7
- * This is the Worker's binding of the LLM seam: the core asks for
8
- * `{ provider: 'openai', model: 'gpt-4o-mini' }` and gets back something `generateText`
9
- * can call, while API keys and the Workers AI binding stay here.
10
- *
11
- * It is just the Worker's composition of the shared AI provisioning facade
12
- * ({@link CompositeModelProvider}): the base registry above plus any `extraRegistries`
13
- * an installation mixes in — e.g. `bedrockRegistry()` from `@cat-factory/provider-bedrock`.
14
- */
15
- export declare class CloudflareModelProvider implements ModelProvider {
16
- private readonly composite;
17
- constructor({ env, extraRegistries }: {
18
- env: Env;
19
- extraRegistries?: ProviderRegistry[];
20
- });
21
- resolve(ref: ModelRef): LanguageModel;
22
- }
23
- //# sourceMappingURL=CloudflareModelProvider.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CloudflareModelProvider.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/ai/CloudflareModelProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,EAItB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AAEvC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAA;AAgDjC;;;;;;;;;GASG;AACH,qBAAa,uBAAwB,YAAW,aAAa;IAC3D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAElD,YAAY,EAAE,GAAG,EAAE,eAAoB,EAAE,EAAE;QAAE,GAAG,EAAE,GAAG,CAAC;QAAC,eAAe,CAAC,EAAE,gBAAgB,EAAE,CAAA;KAAE,EAE5F;IAED,OAAO,CAAC,GAAG,EAAE,QAAQ,GAAG,aAAa,CAEpC;CACF"}
@@ -1,62 +0,0 @@
1
- import { CompositeModelProvider, anthropicResolver, openAiCompatibleResolver, openAiResolver, } from '@cat-factory/agents';
2
- import { createWorkersAI } from 'workers-ai-provider';
3
- import { baseUrlFor } from './providerEndpoints';
4
- // DashScope (Alibaba), DeepSeek and Moonshot (Kimi) all expose OpenAI-compatible
5
- // chat APIs, so they resolve through the openai-compatible provider with just a
6
- // base URL and a key (see ./providerEndpoints for the shared base URLs).
7
- // DashScope's international endpoint is used (the mainland host differs).
8
- /**
9
- * Build the Worker's base provider registry. `workers-ai` is the Cloudflare flavour
10
- * (resolved via the in-process `AI` binding); `openai`/`anthropic` and the
11
- * OpenAI-compatible vendors (`qwen`/`deepseek`/`moonshot`) are keyed from `env`. A
12
- * provider is registered ONLY when its credential/binding is present, so an unconfigured
13
- * provider resolves to a clear "Unsupported model provider" error (from
14
- * {@link CompositeModelProvider}) rather than failing deep in the vendor SDK — matching the
15
- * Node facade exactly (the conditional `baseProviderRegistry`), so the two runtimes don't
16
- * diverge on a missing key.
17
- */
18
- function workerBaseRegistry(env) {
19
- const compatible = (provider, apiKey) => apiKey
20
- ? openAiCompatibleResolver({ name: provider, apiKey, baseURL: baseUrlFor(provider, env) })
21
- : undefined;
22
- return {
23
- openai: env.OPENAI_API_KEY ? openAiResolver({ apiKey: env.OPENAI_API_KEY }) : undefined,
24
- anthropic: env.ANTHROPIC_API_KEY
25
- ? anthropicResolver({ apiKey: env.ANTHROPIC_API_KEY })
26
- : undefined,
27
- qwen: compatible('qwen', env.QWEN_API_KEY),
28
- deepseek: compatible('deepseek', env.DEEPSEEK_API_KEY),
29
- moonshot: compatible('moonshot', env.MOONSHOT_API_KEY),
30
- 'workers-ai': env.AI
31
- ? (ref) => {
32
- const binding = env.AI;
33
- if (!binding)
34
- throw new Error('Workers AI binding (AI) is not configured');
35
- // workers-ai-provider@3 implements the same provider spec as `ai` v6
36
- // (`@ai-sdk/provider` v3), so the model is a real LanguageModel — no cast.
37
- const workersai = createWorkersAI({ binding });
38
- return workersai(ref.model);
39
- }
40
- : undefined,
41
- };
42
- }
43
- /**
44
- * Resolves a provider-agnostic {@link ModelRef} into a concrete Vercel AI SDK model.
45
- * This is the Worker's binding of the LLM seam: the core asks for
46
- * `{ provider: 'openai', model: 'gpt-4o-mini' }` and gets back something `generateText`
47
- * can call, while API keys and the Workers AI binding stay here.
48
- *
49
- * It is just the Worker's composition of the shared AI provisioning facade
50
- * ({@link CompositeModelProvider}): the base registry above plus any `extraRegistries`
51
- * an installation mixes in — e.g. `bedrockRegistry()` from `@cat-factory/provider-bedrock`.
52
- */
53
- export class CloudflareModelProvider {
54
- composite;
55
- constructor({ env, extraRegistries = [] }) {
56
- this.composite = new CompositeModelProvider(workerBaseRegistry(env), ...extraRegistries);
57
- }
58
- resolve(ref) {
59
- return this.composite.resolve(ref);
60
- }
61
- }
62
- //# sourceMappingURL=CloudflareModelProvider.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CloudflareModelProvider.js","sourceRoot":"","sources":["../../../src/infrastructure/ai/CloudflareModelProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EAGtB,iBAAiB,EACjB,wBAAwB,EACxB,cAAc,GACf,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAErD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAEhD,iFAAiF;AACjF,gFAAgF;AAChF,yEAAyE;AACzE,0EAA0E;AAE1E;;;;;;;;;GASG;AACH,SAAS,kBAAkB,CAAC,GAAQ;IAClC,MAAM,UAAU,GAAG,CACjB,QAA0C,EAC1C,MAA0B,EACC,EAAE,CAC7B,MAAM;QACJ,CAAC,CAAC,wBAAwB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAE,EAAE,CAAC;QAC3F,CAAC,CAAC,SAAS,CAAA;IAEf,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;QACvF,SAAS,EAAE,GAAG,CAAC,iBAAiB;YAC9B,CAAC,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,iBAAiB,EAAE,CAAC;YACtD,CAAC,CAAC,SAAS;QACb,IAAI,EAAE,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,YAAY,CAAC;QAC1C,QAAQ,EAAE,UAAU,CAAC,UAAU,EAAE,GAAG,CAAC,gBAAgB,CAAC;QACtD,QAAQ,EAAE,UAAU,CAAC,UAAU,EAAE,GAAG,CAAC,gBAAgB,CAAC;QACtD,YAAY,EAAE,GAAG,CAAC,EAAE;YAClB,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE;gBACN,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,CAAA;gBACtB,IAAI,CAAC,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;gBAC1E,qEAAqE;gBACrE,2EAA2E;gBAC3E,MAAM,SAAS,GAAG,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;gBAC9C,OAAO,SAAS,CAAC,GAAG,CAAC,KAAwC,CAAC,CAAA;YAChE,CAAC;YACH,CAAC,CAAC,SAAS;KACd,CAAA;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,OAAO,uBAAuB;IACjB,SAAS,CAAwB;IAElD,YAAY,EAAE,GAAG,EAAE,eAAe,GAAG,EAAE,EAAsD;QAC3F,IAAI,CAAC,SAAS,GAAG,IAAI,sBAAsB,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,GAAG,eAAe,CAAC,CAAA;IAC1F,CAAC;IAED,OAAO,CAAC,GAAa;QACnB,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACpC,CAAC;CACF"}
@@ -1,39 +0,0 @@
1
- import { type GitHubInstallationRepository, type ModelRef, type RepoScanner, type ScanRepoRequest, type ScannedBlueprint } from '@cat-factory/kernel';
2
- import type { DurableObjectNamespace } from '@cloudflare/workers-types';
3
- import type { ExecutionContainer } from '../containers/ExecutionContainer';
4
- import type { ContainerSessionService } from '../containers/ContainerSessionService';
5
- export interface ContainerRepoScannerDependencies {
6
- /** The Durable Object namespace backing the per-run container instances. */
7
- container: DurableObjectNamespace<ExecutionContainer>;
8
- /** Resolve which GitHub installation a workspace's repos live under. */
9
- installationRepository: GitHubInstallationRepository;
10
- /** Mints a short-lived GitHub installation token for the read-only clone. */
11
- mintInstallationToken: (installationId: number) => Promise<string>;
12
- /** Mints the signed, model-locked LLM-proxy session token the container uses. */
13
- sessionService: ContainerSessionService;
14
- /** Model the scanner agent runs with (must be proxyable). */
15
- model: ModelRef;
16
- /** Public base URL of the Worker's OpenAI-compatible LLM proxy, including `/v1`. */
17
- proxyBaseUrl: string;
18
- /** GitHub REST base for resolving the repo (Enterprise / api.github.com). */
19
- githubApiBase?: string;
20
- /** Web base for building the repo clone URL (defaults to github.com). */
21
- webBaseUrl?: string;
22
- }
23
- /**
24
- * A {@link RepoScanner} that performs the side-effecting half of a "scan
25
- * repository" run: it spins up a per-run Cloudflare Container that clones the
26
- * repository read-only, has the scanner agent decompose it into the canonical
27
- * service → modules blueprint (with codebase references), and returns
28
- * that structure. The agent's JSON is coerced into a well-formed tree here.
29
- *
30
- * Secrets never reach the container image: the per-run GitHub installation token
31
- * and the model-locked LLM-proxy session token are minted here and handed over in
32
- * the dispatch body, exactly as the implementation executor and bootstrapper do.
33
- */
34
- export declare class ContainerRepoScanner implements RepoScanner {
35
- private readonly deps;
36
- constructor(deps: ContainerRepoScannerDependencies);
37
- scan(request: ScanRepoRequest): Promise<ScannedBlueprint>;
38
- }
39
- //# sourceMappingURL=ContainerRepoScanner.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ContainerRepoScanner.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/ai/ContainerRepoScanner.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,4BAA4B,EACjC,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AACvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AAC1E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAA;AAOpF,MAAM,WAAW,gCAAgC;IAC/C,4EAA4E;IAC5E,SAAS,EAAE,sBAAsB,CAAC,kBAAkB,CAAC,CAAA;IACrD,wEAAwE;IACxE,sBAAsB,EAAE,4BAA4B,CAAA;IACpD,6EAA6E;IAC7E,qBAAqB,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAClE,iFAAiF;IACjF,cAAc,EAAE,uBAAuB,CAAA;IACvC,6DAA6D;IAC7D,KAAK,EAAE,QAAQ,CAAA;IACf,oFAAoF;IACpF,YAAY,EAAE,MAAM,CAAA;IACpB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AA6BD;;;;;;;;;;GAUG;AACH,qBAAa,oBAAqB,YAAW,WAAW;IAC1C,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,gCAAgC,EAAI;IAEjE,IAAI,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8D9D;CACF"}
@@ -1,115 +0,0 @@
1
- import {} from '@cat-factory/kernel';
2
- import { boardScanLogic } from '@cat-factory/orchestration';
3
- // Unlike `/run`, scan/bootstrap stay synchronous request/response. This caps how
4
- // long the Worker will wait so a wedged container can't block the caller forever;
5
- // the harness's shared git timeouts bound the underlying git operations too.
6
- const CONTAINER_SYNC_TIMEOUT_MS = 30 * 60_000;
7
- /** The role prompt the scanner agent runs under inside the container. */
8
- const SCAN_SYSTEM_PROMPT = 'You are a Domain-Driven Design architect mapping an existing repository. You have ' +
9
- 'a fresh, read-only clone. Decompose it into ONE top-level service and the modules ' +
10
- 'inside it, where each module is a DOMAIN — a cohesive area of the BUSINESS, in the ' +
11
- 'language of the problem space (a DDD bounded context / aggregate / subdomain). ' +
12
- 'Name modules after business concepts, not technical layers. ' +
13
- 'A module MUST represent a business capability or domain model (e.g. Billing, ' +
14
- 'Catalog, Ordering, Identity), NOT a technical layer or shape: "api", "routes", ' +
15
- '"controllers", "utils", "helpers", "lib", "common", "config", "types", "models", ' +
16
- '"db" and the like are NOT domains and MUST NOT be modules. ' +
17
- 'Group the genuinely non-business, technical/cross-cutting plumbing (persistence ' +
18
- 'wiring, HTTP/transport, logging, configuration, auth middleware, build/deploy, ' +
19
- 'shared utilities) into a SINGLE module named "infrastructure" rather than ' +
20
- 'scattering it into many technical modules. ' +
21
- 'Prefer organising code by domain (the ubiquitous language) over organising by ' +
22
- 'file type. Anchor every node to the codebase with explicit repo-relative ' +
23
- 'file/directory references. Keep names short and descriptive. ' +
24
- 'Respond with ONLY a JSON object of shape {"type","name","summary","references":[],' +
25
- '"modules":[{"name","summary","references":[]}]} — no prose, no code fences.';
26
- /**
27
- * A {@link RepoScanner} that performs the side-effecting half of a "scan
28
- * repository" run: it spins up a per-run Cloudflare Container that clones the
29
- * repository read-only, has the scanner agent decompose it into the canonical
30
- * service → modules blueprint (with codebase references), and returns
31
- * that structure. The agent's JSON is coerced into a well-formed tree here.
32
- *
33
- * Secrets never reach the container image: the per-run GitHub installation token
34
- * and the model-locked LLM-proxy session token are minted here and handed over in
35
- * the dispatch body, exactly as the implementation executor and bootstrapper do.
36
- */
37
- export class ContainerRepoScanner {
38
- deps;
39
- constructor(deps) {
40
- this.deps = deps;
41
- }
42
- async scan(request) {
43
- const installation = await this.deps.installationRepository.getByWorkspace(request.workspaceId);
44
- if (!installation || installation.deletedAt) {
45
- throw new Error(`Workspace '${request.workspaceId}' is not connected to GitHub`);
46
- }
47
- if (!isProxyableProvider(this.deps.model.provider)) {
48
- throw new Error(`Repository scanning needs a model the LLM proxy can serve ` +
49
- `(Workers AI, or a direct OpenAI-compatible provider); ` +
50
- `'${this.deps.model.provider}' is not supported.`);
51
- }
52
- const ghToken = await this.deps.mintInstallationToken(installation.installationId);
53
- const sessionToken = await this.deps.sessionService.mint({
54
- workspaceId: request.workspaceId,
55
- executionId: `scan-${request.repo.owner}-${request.repo.name}`,
56
- agentKind: 'architect',
57
- provider: this.deps.model.provider,
58
- model: this.deps.model.model,
59
- });
60
- const webBase = (this.deps.webBaseUrl ?? 'https://github.com').replace(/\/+$/, '');
61
- const cloneUrl = `${webBase}/${request.repo.owner}/${request.repo.name}.git`;
62
- const body = {
63
- systemPrompt: SCAN_SYSTEM_PROMPT,
64
- instructions: request.instructions || 'Map the repository into the blueprint structure.',
65
- model: this.deps.model.model,
66
- proxyBaseUrl: this.deps.proxyBaseUrl,
67
- sessionToken,
68
- ghToken,
69
- repo: {
70
- owner: request.repo.owner,
71
- name: request.repo.name,
72
- cloneUrl,
73
- },
74
- ...(this.deps.githubApiBase ? { githubApiBase: this.deps.githubApiBase } : {}),
75
- };
76
- // One container instance per repo scan (keyed by owner/name), mirroring the
77
- // per-run implementation and bootstrap containers.
78
- const key = `scan-${request.repo.owner}/${request.repo.name}`;
79
- const stub = this.deps.container.get(this.deps.container.idFromName(key));
80
- const res = await stub.fetch('http://container/scan', {
81
- method: 'POST',
82
- headers: { 'content-type': 'application/json' },
83
- body: JSON.stringify(body),
84
- signal: AbortSignal.timeout(CONTAINER_SYNC_TIMEOUT_MS),
85
- });
86
- if (!res.ok) {
87
- throw new Error(`Scan container failed (HTTP ${res.status}): ${await safeText(res)}`);
88
- }
89
- const result = (await res.json());
90
- if (result.error)
91
- throw new Error(`Scan failed: ${result.error}`);
92
- const service = boardScanLogic.coerceService(result.service, request.repo.name);
93
- if (!service) {
94
- throw new Error('Scan produced no usable blueprint');
95
- }
96
- return { source: 'llm', service };
97
- }
98
- }
99
- /** Providers the LLM proxy can serve (mirrors ContainerAgentExecutor). */
100
- function isProxyableProvider(provider) {
101
- return (provider === 'workers-ai' ||
102
- provider === 'qwen' ||
103
- provider === 'deepseek' ||
104
- provider === 'moonshot' ||
105
- provider === 'openai');
106
- }
107
- async function safeText(res) {
108
- try {
109
- return (await res.text()).slice(0, 500);
110
- }
111
- catch {
112
- return '(no body)';
113
- }
114
- }
115
- //# sourceMappingURL=ContainerRepoScanner.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ContainerRepoScanner.js","sourceRoot":"","sources":["../../../src/infrastructure/ai/ContainerRepoScanner.ts"],"names":[],"mappings":"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"}
@@ -1,29 +0,0 @@
1
- import { type DocumentContent, type DocumentCredentials, type DocumentSearchResult, type DocumentSourceProvider, type NormalizedConnection } from '@cat-factory/kernel';
2
- /** Carries the HTTP status so callers can surface a meaningful error. */
3
- export declare class ConfluenceApiError extends Error {
4
- readonly status: number;
5
- constructor(status: number, message: string);
6
- }
7
- export declare class ConfluenceProvider implements DocumentSourceProvider {
8
- readonly kind: 'confluence';
9
- readonly descriptor: {
10
- source: "confluence" | "github" | "notion";
11
- label: string;
12
- icon: string;
13
- credentialFields: {
14
- key: string;
15
- label: string;
16
- help?: string | undefined;
17
- placeholder?: string | undefined;
18
- secret?: boolean | undefined;
19
- }[];
20
- refLabel: string;
21
- refPlaceholder: string;
22
- searchable?: boolean | undefined;
23
- };
24
- normalizeConnection(input: DocumentCredentials): NormalizedConnection;
25
- parseRef(input: string): string | null;
26
- fetchDocument(credentials: DocumentCredentials, externalId: string): Promise<DocumentContent>;
27
- search(credentials: DocumentCredentials, query: string): Promise<DocumentSearchResult[]>;
28
- }
29
- //# sourceMappingURL=ConfluenceProvider.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ConfluenceProvider.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/documents/ConfluenceProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAA;AAgB5B,yEAAyE;AACzE,qBAAa,kBAAmB,SAAQ,KAAK;IAEzC,QAAQ,CAAC,MAAM,EAAE,MAAM;IADzB,YACW,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EAIhB;CACF;AA+ED,qBAAa,kBAAmB,YAAW,sBAAsB;IAC/D,QAAQ,CAAC,IAAI,EAAG,YAAY,CAAS;IACrC,QAAQ,CAAC,UAAU;;;;;;;;;;;;;;MAAwB;IAE3C,mBAAmB,CAAC,KAAK,EAAE,mBAAmB,GAAG,oBAAoB,CAepE;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAErC;IAEK,aAAa,CACjB,WAAW,EAAE,mBAAmB,EAChC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,eAAe,CAAC,CAiD1B;IAEK,MAAM,CAAC,WAAW,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAkC7F;CACF"}
@@ -1,179 +0,0 @@
1
- import { ValidationError, } from '@cat-factory/kernel';
2
- import { CONFLUENCE_DESCRIPTOR, confluenceLogic } from '@cat-factory/integrations';
3
- // ConfluenceProvider: the document-source provider for Confluence Cloud. It
4
- // authenticates with HTTP Basic (account email + API token), fetches a page in
5
- // storage format, and converts the body to the Markdown the planner consumes.
6
- // All Confluence-specific *pure* logic (ref parsing, base-URL SSRF guard,
7
- // XHTML → Markdown) lives in `@cat-factory/integrations` so it is unit-testable; this
8
- // class is the thin `fetch` shell around it. No SDK — fetch + `btoa` suffice.
9
- const USER_AGENT = 'cat-factory';
10
- /** Bound the redirect chain so a permitted first hop can't walk us anywhere. */
11
- const MAX_REDIRECTS = 5;
12
- /** Hard cap on the bytes read off any response body, to protect the isolate. */
13
- const MAX_RESPONSE_BYTES = 5_000_000;
14
- /** Carries the HTTP status so callers can surface a meaningful error. */
15
- export class ConfluenceApiError extends Error {
16
- status;
17
- constructor(status, message) {
18
- super(message);
19
- this.status = status;
20
- this.name = 'ConfluenceApiError';
21
- }
22
- }
23
- /**
24
- * `fetch` with redirects followed by hand so the SSRF guard runs against EVERY
25
- * hop. With the default `redirect: 'follow'` the permitted site could 302 to an
26
- * internal target (or downgrade https→http) and the runtime would follow it
27
- * unchecked, leaking the Basic-auth token. We force `redirect: 'manual'`,
28
- * re-resolve the `Location` against the current URL, and re-run the same
29
- * `assertSafe` guard (https-only + host blocklist) before following.
30
- */
31
- async function safeFetch(url, init, assertSafe) {
32
- let current = url;
33
- for (let hop = 0;; hop++) {
34
- assertSafe(current);
35
- const res = await fetch(current, { ...init, redirect: 'manual' });
36
- if (res.status >= 300 && res.status < 400) {
37
- const location = res.headers.get('location');
38
- if (!location)
39
- return res;
40
- if (hop >= MAX_REDIRECTS) {
41
- throw new ConfluenceApiError(502, 'Confluence returned too many redirects');
42
- }
43
- current = new URL(location, current).toString();
44
- continue;
45
- }
46
- return res;
47
- }
48
- }
49
- /**
50
- * Read a response body with a running byte cap so a hostile/huge response can't
51
- * OOM the isolate. Checks the declared Content-Length first, then enforces the
52
- * cap while streaming.
53
- */
54
- async function readCappedText(res, maxBytes) {
55
- const declared = res.headers.get('content-length');
56
- if (declared && Number(declared) > maxBytes) {
57
- throw new ConfluenceApiError(502, 'Confluence response too large');
58
- }
59
- const body = res.body;
60
- if (!body)
61
- return '';
62
- const reader = body.getReader();
63
- const chunks = [];
64
- let total = 0;
65
- try {
66
- for (;;) {
67
- const { done, value } = await reader.read();
68
- if (done)
69
- break;
70
- if (!value)
71
- continue;
72
- total += value.byteLength;
73
- if (total > maxBytes) {
74
- await reader.cancel();
75
- throw new ConfluenceApiError(502, 'Confluence response too large');
76
- }
77
- chunks.push(value);
78
- }
79
- }
80
- finally {
81
- reader.releaseLock();
82
- }
83
- const merged = new Uint8Array(total);
84
- let offset = 0;
85
- for (const c of chunks) {
86
- merged.set(c, offset);
87
- offset += c.byteLength;
88
- }
89
- return new TextDecoder().decode(merged);
90
- }
91
- export class ConfluenceProvider {
92
- kind = 'confluence';
93
- descriptor = CONFLUENCE_DESCRIPTOR;
94
- normalizeConnection(input) {
95
- const baseUrlRaw = input.baseUrl?.trim();
96
- const accountEmail = input.accountEmail?.trim();
97
- const apiToken = input.apiToken?.trim();
98
- if (!baseUrlRaw || !accountEmail || !apiToken) {
99
- throw new ValidationError('Confluence requires a site URL, account email and API token');
100
- }
101
- const baseUrl = confluenceLogic.normalizeBaseUrl(baseUrlRaw);
102
- // Guard against SSRF: the stored base URL is later fetched with the
103
- // workspace's credentials, so it must be a public https host.
104
- confluenceLogic.assertSafeConfluenceBaseUrl(baseUrl);
105
- return {
106
- credentials: { baseUrl, accountEmail, apiToken },
107
- label: baseUrl,
108
- };
109
- }
110
- parseRef(input) {
111
- return confluenceLogic.parseConfluenceRef(input);
112
- }
113
- async fetchDocument(credentials, externalId) {
114
- const base = credentials.baseUrl.replace(/\/+$/, '');
115
- const url = `${base}/wiki/rest/api/content/${encodeURIComponent(externalId)}?expand=body.storage,version`;
116
- const auth = btoa(`${credentials.accountEmail}:${credentials.apiToken}`);
117
- const res = await safeFetch(url, {
118
- method: 'GET',
119
- headers: {
120
- authorization: `Basic ${auth}`,
121
- accept: 'application/json',
122
- 'user-agent': USER_AGENT,
123
- },
124
- }, (u) => confluenceLogic.assertSafeConfluenceBaseUrl(u));
125
- if (!res.ok) {
126
- const text = await readCappedText(res, MAX_RESPONSE_BYTES).catch(() => '');
127
- throw new ConfluenceApiError(res.status, `Confluence GET ${url} → ${res.status}: ${text.slice(0, 300)}`);
128
- }
129
- const text = await readCappedText(res, MAX_RESPONSE_BYTES);
130
- const json = (() => {
131
- try {
132
- return JSON.parse(text);
133
- }
134
- catch {
135
- return null;
136
- }
137
- })();
138
- if (!json || !json.id) {
139
- throw new ConfluenceApiError(502, `Confluence returned an unexpected body for page ${externalId}`);
140
- }
141
- const linkBase = json._links?.base ?? `${base}/wiki`;
142
- const webui = json._links?.webui ?? '';
143
- return {
144
- externalId: json.id,
145
- title: json.title ?? '(untitled)',
146
- url: `${linkBase}${webui}`,
147
- body: confluenceLogic.confluenceStorageToMarkdown(json.body?.storage?.value ?? ''),
148
- };
149
- }
150
- async search(credentials, query) {
151
- const base = credentials.baseUrl.replace(/\/+$/, '');
152
- const cql = encodeURIComponent(confluenceLogic.buildConfluenceSearchCql(query));
153
- const url = `${base}/wiki/rest/api/content/search?cql=${cql}&limit=20`;
154
- const auth = btoa(`${credentials.accountEmail}:${credentials.apiToken}`);
155
- const res = await safeFetch(url, {
156
- method: 'GET',
157
- headers: {
158
- authorization: `Basic ${auth}`,
159
- accept: 'application/json',
160
- 'user-agent': USER_AGENT,
161
- },
162
- }, (u) => confluenceLogic.assertSafeConfluenceBaseUrl(u));
163
- if (!res.ok) {
164
- const text = await readCappedText(res, MAX_RESPONSE_BYTES).catch(() => '');
165
- throw new ConfluenceApiError(res.status, `Confluence search ${url} → ${res.status}: ${text.slice(0, 300)}`);
166
- }
167
- const text = await readCappedText(res, MAX_RESPONSE_BYTES);
168
- const json = (() => {
169
- try {
170
- return JSON.parse(text);
171
- }
172
- catch {
173
- return null;
174
- }
175
- })();
176
- return confluenceLogic.parseConfluenceSearchResults(json, base);
177
- }
178
- }
179
- //# sourceMappingURL=ConfluenceProvider.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ConfluenceProvider.js","sourceRoot":"","sources":["../../../src/infrastructure/documents/ConfluenceProvider.ts"],"names":[],"mappings":"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"}
@@ -1,42 +0,0 @@
1
- import { type DocumentContent, type DocumentCredentials, type DocumentSearchResult, type DocumentSourceProvider, type GitHubClient, type GitHubInstallationRepository, type NormalizedConnection } from '@cat-factory/kernel';
2
- export interface GitHubDocsProviderDependencies {
3
- githubClient: GitHubClient;
4
- /** Resolves which installation owns a given repo owner (by account login). */
5
- installations: GitHubInstallationRepository;
6
- }
7
- export declare class GitHubDocsProvider implements DocumentSourceProvider {
8
- private readonly deps;
9
- readonly kind: 'github';
10
- readonly descriptor: {
11
- source: "confluence" | "github" | "notion";
12
- label: string;
13
- icon: string;
14
- credentialFields: {
15
- key: string;
16
- label: string;
17
- help?: string | undefined;
18
- placeholder?: string | undefined;
19
- secret?: boolean | undefined;
20
- }[];
21
- refLabel: string;
22
- refPlaceholder: string;
23
- searchable?: boolean | undefined;
24
- };
25
- constructor(deps: GitHubDocsProviderDependencies);
26
- /**
27
- * GitHub docs piggyback on the installed GitHub App, so there is nothing to
28
- * validate or persist — the connection is a marker. Any supplied fields are
29
- * ignored (the connect form has none).
30
- */
31
- normalizeConnection(_input: DocumentCredentials): NormalizedConnection;
32
- parseRef(input: string): string | null;
33
- fetchDocument(_credentials: DocumentCredentials, externalId: string): Promise<DocumentContent>;
34
- search(_credentials: DocumentCredentials, query: string, workspaceId: string): Promise<DocumentSearchResult[]>;
35
- /**
36
- * Find the GitHub App installation whose account owns `owner`. The
37
- * installation token for that account is what can read the repo's contents,
38
- * regardless of which workspace triggered the import.
39
- */
40
- private resolveInstallationId;
41
- }
42
- //# sourceMappingURL=GitHubDocsProvider.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"GitHubDocsProvider.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/documents/GitHubDocsProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,YAAY,EACjB,KAAK,4BAA4B,EACjC,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAA;AAc5B,MAAM,WAAW,8BAA8B;IAC7C,YAAY,EAAE,YAAY,CAAA;IAC1B,8EAA8E;IAC9E,aAAa,EAAE,4BAA4B,CAAA;CAC5C;AAED,qBAAa,kBAAmB,YAAW,sBAAsB;IAInD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAS;IACjC,QAAQ,CAAC,UAAU;;;;;;;;;;;;;;MAAyB;IAE5C,YAA6B,IAAI,EAAE,8BAA8B,EAAI;IAErE;;;;OAIG;IACH,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,oBAAoB,CAErE;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAErC;IAEK,aAAa,CACjB,YAAY,EAAE,mBAAmB,EACjC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,eAAe,CAAC,CAoB1B;IAEK,MAAM,CACV,YAAY,EAAE,mBAAmB,EACjC,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAkCjC;IAED;;;;OAIG;YACW,qBAAqB;CAUpC"}