@apart-tech/intelligence-core 1.12.1 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/ability.d.ts +1 -1
- package/dist/auth/ability.d.ts.map +1 -1
- package/dist/auth/ability.js +4 -0
- package/dist/auth/ability.js.map +1 -1
- package/dist/auth/ability.test.js +12 -1
- package/dist/auth/ability.test.js.map +1 -1
- package/dist/db/tenant.d.ts.map +1 -1
- package/dist/db/tenant.js +2 -0
- package/dist/db/tenant.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/services/document-service.d.ts +91 -0
- package/dist/services/document-service.d.ts.map +1 -0
- package/dist/services/document-service.js +273 -0
- package/dist/services/document-service.js.map +1 -0
- package/dist/services/document-service.test.d.ts +2 -0
- package/dist/services/document-service.test.d.ts.map +1 -0
- package/dist/services/document-service.test.js +289 -0
- package/dist/services/document-service.test.js.map +1 -0
- package/dist/services/ocr-service.d.ts +21 -0
- package/dist/services/ocr-service.d.ts.map +1 -0
- package/dist/services/ocr-service.js +61 -0
- package/dist/services/ocr-service.js.map +1 -0
- package/dist/services/ocr-service.test.d.ts +2 -0
- package/dist/services/ocr-service.test.d.ts.map +1 -0
- package/dist/services/ocr-service.test.js +66 -0
- package/dist/services/ocr-service.test.js.map +1 -0
- package/dist/services/org-agent-type-service.d.ts +18 -0
- package/dist/services/org-agent-type-service.d.ts.map +1 -1
- package/dist/services/org-agent-type-service.js +25 -0
- package/dist/services/org-agent-type-service.js.map +1 -1
- package/dist/services/org-agent-type-service.test.d.ts +2 -0
- package/dist/services/org-agent-type-service.test.d.ts.map +1 -0
- package/dist/services/org-agent-type-service.test.js +168 -0
- package/dist/services/org-agent-type-service.test.js.map +1 -0
- package/package.json +1 -1
- package/prisma/schema.prisma +35 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OCR text extraction via the AIShield proxy (Mistral OCR model).
|
|
3
|
+
*
|
|
4
|
+
* Calls the OpenAI-compatible chat completions endpoint at AIShield,
|
|
5
|
+
* passing a signed GCS document URL as a `document_url` content part.
|
|
6
|
+
* The model returns extracted text as structured markdown.
|
|
7
|
+
*/
|
|
8
|
+
const OCR_PROMPT = `Extract all text content from this document. Format the output as clean markdown:
|
|
9
|
+
- Preserve document structure with headings (#, ##, ###).
|
|
10
|
+
- Render tables as markdown tables.
|
|
11
|
+
- Separate pages with --- (horizontal rule).
|
|
12
|
+
- Do not add any commentary — output only the extracted text.`;
|
|
13
|
+
export class OcrService {
|
|
14
|
+
baseUrl;
|
|
15
|
+
apiKey;
|
|
16
|
+
model;
|
|
17
|
+
constructor(baseUrl, apiKey, model = "mistral-ocr-latest") {
|
|
18
|
+
this.baseUrl = baseUrl;
|
|
19
|
+
this.apiKey = apiKey;
|
|
20
|
+
this.model = model;
|
|
21
|
+
}
|
|
22
|
+
async extractText(documentUrl, organizationId) {
|
|
23
|
+
const body = {
|
|
24
|
+
model: this.model,
|
|
25
|
+
messages: [
|
|
26
|
+
{
|
|
27
|
+
role: "user",
|
|
28
|
+
content: [
|
|
29
|
+
{ type: "text", text: OCR_PROMPT },
|
|
30
|
+
{ type: "document_url", document_url: documentUrl },
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
const response = await fetch(`${this.baseUrl}/v1/chat/completions`, {
|
|
36
|
+
method: "POST",
|
|
37
|
+
headers: {
|
|
38
|
+
"Content-Type": "application/json",
|
|
39
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
40
|
+
Organisation: organizationId,
|
|
41
|
+
},
|
|
42
|
+
body: JSON.stringify(body),
|
|
43
|
+
});
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
const errorBody = await response.text().catch(() => "");
|
|
46
|
+
throw new Error(`OCR request failed (${response.status}): ${errorBody}`);
|
|
47
|
+
}
|
|
48
|
+
const result = await response.json();
|
|
49
|
+
const text = result.choices?.[0]?.message?.content;
|
|
50
|
+
if (text === undefined || text === null) {
|
|
51
|
+
throw new Error("OCR response missing choices[0].message.content");
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
text,
|
|
55
|
+
tokensIn: result.usage?.prompt_tokens ?? 0,
|
|
56
|
+
tokensOut: result.usage?.completion_tokens ?? 0,
|
|
57
|
+
model: result.model ?? this.model,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=ocr-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ocr-service.js","sourceRoot":"","sources":["../../src/services/ocr-service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,MAAM,UAAU,GAAG;;;;8DAI2C,CAAC;AAE/D,MAAM,OAAO,UAAU;IAEX;IACA;IACA;IAHV,YACU,OAAe,EACf,MAAc,EACd,QAAgB,oBAAoB;QAFpC,YAAO,GAAP,OAAO,CAAQ;QACf,WAAM,GAAN,MAAM,CAAQ;QACd,UAAK,GAAL,KAAK,CAA+B;IAC3C,CAAC;IAEJ,KAAK,CAAC,WAAW,CACf,WAAmB,EACnB,cAAsB;QAEtB,MAAM,IAAI,GAAG;YACX,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE;wBACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE;wBAClC,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE;qBACpD;iBACF;aACF;SACF,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,sBAAsB,EAAE;YAClE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;gBACtC,YAAY,EAAE,cAAc;aAC7B;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YACxD,MAAM,IAAI,KAAK,CACb,uBAAuB,QAAQ,CAAC,MAAM,MAAM,SAAS,EAAE,CACxD,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAIjC,CAAC;QAEF,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC;QACnD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,CAAC;QAED,OAAO;YACL,IAAI;YACJ,QAAQ,EAAE,MAAM,CAAC,KAAK,EAAE,aAAa,IAAI,CAAC;YAC1C,SAAS,EAAE,MAAM,CAAC,KAAK,EAAE,iBAAiB,IAAI,CAAC;YAC/C,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK;SAClC,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ocr-service.test.d.ts","sourceRoot":"","sources":["../../src/services/ocr-service.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { describe, expect, it, vi, afterEach, beforeEach } from "vitest";
|
|
2
|
+
import { OcrService } from "./ocr-service.js";
|
|
3
|
+
describe("OcrService", () => {
|
|
4
|
+
const BASE_URL = "https://aishield.apart.tech";
|
|
5
|
+
const API_KEY = "test-api-key";
|
|
6
|
+
const MODEL = "mistral-ocr-latest";
|
|
7
|
+
const ORG_ID = "org-123";
|
|
8
|
+
const DOC_URL = "https://storage.googleapis.com/bucket/doc.pdf?X-Goog-Signature=...";
|
|
9
|
+
let service;
|
|
10
|
+
const mockFetch = vi.fn();
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
service = new OcrService(BASE_URL, API_KEY, MODEL);
|
|
13
|
+
mockFetch.mockReset();
|
|
14
|
+
vi.stubGlobal("fetch", mockFetch);
|
|
15
|
+
});
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
vi.restoreAllMocks();
|
|
18
|
+
});
|
|
19
|
+
it("sends correct request format and parses response", async () => {
|
|
20
|
+
mockFetch.mockResolvedValueOnce(new Response(JSON.stringify({
|
|
21
|
+
choices: [{ message: { content: "# Title\n\nExtracted text" } }],
|
|
22
|
+
usage: { prompt_tokens: 100, completion_tokens: 50 },
|
|
23
|
+
model: "mistral-ocr-latest",
|
|
24
|
+
}), { status: 200 }));
|
|
25
|
+
const result = await service.extractText(DOC_URL, ORG_ID);
|
|
26
|
+
expect(result.text).toBe("# Title\n\nExtracted text");
|
|
27
|
+
expect(result.tokensIn).toBe(100);
|
|
28
|
+
expect(result.tokensOut).toBe(50);
|
|
29
|
+
expect(result.model).toBe("mistral-ocr-latest");
|
|
30
|
+
expect(mockFetch).toHaveBeenCalledOnce();
|
|
31
|
+
const [url, opts] = mockFetch.mock.calls[0];
|
|
32
|
+
expect(url).toBe(`${BASE_URL}/v1/chat/completions`);
|
|
33
|
+
expect(opts.method).toBe("POST");
|
|
34
|
+
const headers = opts.headers;
|
|
35
|
+
expect(headers["Authorization"]).toBe(`Bearer ${API_KEY}`);
|
|
36
|
+
expect(headers["Organisation"]).toBe(ORG_ID);
|
|
37
|
+
expect(headers["Content-Type"]).toBe("application/json");
|
|
38
|
+
const body = JSON.parse(opts.body);
|
|
39
|
+
expect(body.model).toBe(MODEL);
|
|
40
|
+
expect(body.messages[0].content).toHaveLength(2);
|
|
41
|
+
expect(body.messages[0].content[0].type).toBe("text");
|
|
42
|
+
expect(body.messages[0].content[1].type).toBe("document_url");
|
|
43
|
+
expect(body.messages[0].content[1].document_url).toBe(DOC_URL);
|
|
44
|
+
});
|
|
45
|
+
it("throws on non-200 response", async () => {
|
|
46
|
+
mockFetch.mockResolvedValueOnce(new Response("Rate limited", { status: 429 }));
|
|
47
|
+
await expect(service.extractText(DOC_URL, ORG_ID)).rejects.toThrow("OCR request failed (429): Rate limited");
|
|
48
|
+
});
|
|
49
|
+
it("throws when response missing content", async () => {
|
|
50
|
+
mockFetch.mockResolvedValueOnce(new Response(JSON.stringify({ choices: [{ message: {} }], usage: {} }), { status: 200 }));
|
|
51
|
+
await expect(service.extractText(DOC_URL, ORG_ID)).rejects.toThrow("OCR response missing choices[0].message.content");
|
|
52
|
+
});
|
|
53
|
+
it("handles missing usage gracefully", async () => {
|
|
54
|
+
mockFetch.mockResolvedValueOnce(new Response(JSON.stringify({
|
|
55
|
+
choices: [{ message: { content: "text" } }],
|
|
56
|
+
}), { status: 200 }));
|
|
57
|
+
const result = await service.extractText(DOC_URL, ORG_ID);
|
|
58
|
+
expect(result.tokensIn).toBe(0);
|
|
59
|
+
expect(result.tokensOut).toBe(0);
|
|
60
|
+
});
|
|
61
|
+
it("handles network error", async () => {
|
|
62
|
+
mockFetch.mockRejectedValueOnce(new Error("Network error"));
|
|
63
|
+
await expect(service.extractText(DOC_URL, ORG_ID)).rejects.toThrow("Network error");
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=ocr-service.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ocr-service.test.js","sourceRoot":"","sources":["../../src/services/ocr-service.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,6 +21,18 @@ export interface OrgAgentTypeRecord {
|
|
|
21
21
|
* anything that is not an array as "no rules" (deny-by-default).
|
|
22
22
|
*/
|
|
23
23
|
intrinsicPolicy: unknown;
|
|
24
|
+
/** Secret names that must be registered on the invoking user before the
|
|
25
|
+
* type can run. Empty = no required secrets. See spec
|
|
26
|
+
* docs/superpowers/specs/2026-04-24-custom-agent-type-secret-mapping.md. */
|
|
27
|
+
requiredSecrets: string[];
|
|
28
|
+
/** Mapping of secret name → sandbox env var name. The orchestrator reads
|
|
29
|
+
* the user's `AgentSecrets` and injects each declared key under the
|
|
30
|
+
* env var name given here. Empty = no env vars injected. */
|
|
31
|
+
secretEnvMapping: Record<string, string>;
|
|
32
|
+
/** Opt-in to dynamic secret shapes. Today the only meaningful value is
|
|
33
|
+
* `"databases"`, which expands into paired `DATABASE_URL_<NAME>` /
|
|
34
|
+
* `DATABASE_TYPE_<NAME>` env vars per database connection. */
|
|
35
|
+
dynamicSecrets: string[];
|
|
24
36
|
createdBy: string;
|
|
25
37
|
createdAt: Date;
|
|
26
38
|
updatedAt: Date;
|
|
@@ -32,6 +44,9 @@ export interface CreateOrgAgentTypeInput {
|
|
|
32
44
|
prompt: string;
|
|
33
45
|
defaultTimeoutMinutes?: number;
|
|
34
46
|
isBuiltinOverride?: boolean;
|
|
47
|
+
requiredSecrets?: string[];
|
|
48
|
+
secretEnvMapping?: Record<string, string>;
|
|
49
|
+
dynamicSecrets?: string[];
|
|
35
50
|
createdBy: string;
|
|
36
51
|
}
|
|
37
52
|
export interface UpdateOrgAgentTypeInput {
|
|
@@ -39,6 +54,9 @@ export interface UpdateOrgAgentTypeInput {
|
|
|
39
54
|
description?: string;
|
|
40
55
|
prompt?: string;
|
|
41
56
|
defaultTimeoutMinutes?: number;
|
|
57
|
+
requiredSecrets?: string[];
|
|
58
|
+
secretEnvMapping?: Record<string, string>;
|
|
59
|
+
dynamicSecrets?: string[];
|
|
42
60
|
}
|
|
43
61
|
export declare class OrgAgentTypeService {
|
|
44
62
|
private db;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"org-agent-type-service.d.ts","sourceRoot":"","sources":["../../src/services/org-agent-type-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,qBAAqB,EAAE,MAAM,CAAC;IAC9B,iBAAiB,EAAE,OAAO,CAAC;IAC3B;;;;;;;OAOG;IACH,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qBAAqB,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"org-agent-type-service.d.ts","sourceRoot":"","sources":["../../src/services/org-agent-type-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,qBAAqB,EAAE,MAAM,CAAC;IAC9B,iBAAiB,EAAE,OAAO,CAAC;IAC3B;;;;;;;OAOG;IACH,eAAe,EAAE,OAAO,CAAC;IACzB;;iFAE6E;IAC7E,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B;;iEAE6D;IAC7D,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC;;mEAE+D;IAC/D,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAgCD,qBAAa,mBAAmB;IAClB,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,YAAY;IAE9B,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAQ3D,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAOnF,MAAM,CACV,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,uBAAuB,EAC9B,YAAY,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC,kBAAkB,CAAC;IA0CxB,MAAM,CACV,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,kBAAkB,CAAC;IAiBxB,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAUrE"}
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
const SLUG_REGEX = /^[a-z][a-z0-9-]*$/;
|
|
2
|
+
function normalizeSecretEnvMapping(raw) {
|
|
3
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
4
|
+
return {};
|
|
5
|
+
const out = {};
|
|
6
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
7
|
+
if (typeof v === "string")
|
|
8
|
+
out[k] = v;
|
|
9
|
+
}
|
|
10
|
+
return out;
|
|
11
|
+
}
|
|
2
12
|
function toRecord(row) {
|
|
3
13
|
return {
|
|
4
14
|
id: row.id,
|
|
@@ -9,6 +19,9 @@ function toRecord(row) {
|
|
|
9
19
|
defaultTimeoutMinutes: row.defaultTimeoutMinutes,
|
|
10
20
|
isBuiltinOverride: row.isBuiltinOverride,
|
|
11
21
|
intrinsicPolicy: row.intrinsicPolicy,
|
|
22
|
+
requiredSecrets: Array.isArray(row.requiredSecrets) ? row.requiredSecrets : [],
|
|
23
|
+
secretEnvMapping: normalizeSecretEnvMapping(row.secretEnvMapping),
|
|
24
|
+
dynamicSecrets: Array.isArray(row.dynamicSecrets) ? row.dynamicSecrets : [],
|
|
12
25
|
createdBy: row.createdBy,
|
|
13
26
|
createdAt: row.createdAt,
|
|
14
27
|
updatedAt: row.updatedAt,
|
|
@@ -54,6 +67,9 @@ export class OrgAgentTypeService {
|
|
|
54
67
|
defaultTimeoutMinutes: input.defaultTimeoutMinutes ?? 15,
|
|
55
68
|
isBuiltinOverride: isOverride,
|
|
56
69
|
createdBy: input.createdBy,
|
|
70
|
+
requiredSecrets: input.requiredSecrets ?? [],
|
|
71
|
+
secretEnvMapping: input.secretEnvMapping ?? {},
|
|
72
|
+
dynamicSecrets: input.dynamicSecrets ?? [],
|
|
57
73
|
},
|
|
58
74
|
update: {
|
|
59
75
|
label: input.label,
|
|
@@ -61,6 +77,9 @@ export class OrgAgentTypeService {
|
|
|
61
77
|
prompt: input.prompt,
|
|
62
78
|
defaultTimeoutMinutes: input.defaultTimeoutMinutes ?? 15,
|
|
63
79
|
updatedAt: new Date(),
|
|
80
|
+
...(input.requiredSecrets !== undefined ? { requiredSecrets: input.requiredSecrets } : {}),
|
|
81
|
+
...(input.secretEnvMapping !== undefined ? { secretEnvMapping: input.secretEnvMapping } : {}),
|
|
82
|
+
...(input.dynamicSecrets !== undefined ? { dynamicSecrets: input.dynamicSecrets } : {}),
|
|
64
83
|
},
|
|
65
84
|
});
|
|
66
85
|
return toRecord(row);
|
|
@@ -75,6 +94,12 @@ export class OrgAgentTypeService {
|
|
|
75
94
|
data.prompt = input.prompt;
|
|
76
95
|
if (input.defaultTimeoutMinutes !== undefined)
|
|
77
96
|
data.defaultTimeoutMinutes = input.defaultTimeoutMinutes;
|
|
97
|
+
if (input.requiredSecrets !== undefined)
|
|
98
|
+
data.requiredSecrets = input.requiredSecrets;
|
|
99
|
+
if (input.secretEnvMapping !== undefined)
|
|
100
|
+
data.secretEnvMapping = input.secretEnvMapping;
|
|
101
|
+
if (input.dynamicSecrets !== undefined)
|
|
102
|
+
data.dynamicSecrets = input.dynamicSecrets;
|
|
78
103
|
const row = await this.db.orgAgentType.update({
|
|
79
104
|
where: { organizationId_slug: { organizationId, slug } },
|
|
80
105
|
data,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"org-agent-type-service.js","sourceRoot":"","sources":["../../src/services/org-agent-type-service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"org-agent-type-service.js","sourceRoot":"","sources":["../../src/services/org-agent-type-service.ts"],"names":[],"mappings":"AAgEA,MAAM,UAAU,GAAG,mBAAmB,CAAC;AAEvC,SAAS,yBAAyB,CAAC,GAAY;IAC7C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACrE,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAA8B,CAAC,EAAE,CAAC;QACpE,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,QAAQ,CAAC,GAAQ;IACxB,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,qBAAqB,EAAE,GAAG,CAAC,qBAAqB;QAChD,iBAAiB,EAAE,GAAG,CAAC,iBAAiB;QACxC,eAAe,EAAE,GAAG,CAAC,eAAe;QACpC,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE;QAC9E,gBAAgB,EAAE,yBAAyB,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACjE,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE;QAC3E,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,SAAS,EAAE,GAAG,CAAC,SAAS;KACzB,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,mBAAmB;IACV;IAApB,YAAoB,EAAgB;QAAhB,OAAE,GAAF,EAAE,CAAc;IAAG,CAAC;IAExC,KAAK,CAAC,IAAI,CAAC,cAAsB;QAC/B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC;YAC/C,KAAK,EAAE,EAAE,cAAc,EAAE;YACzB,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;SACzB,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,cAAsB,EAAE,IAAY;QAClD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC;YAChD,KAAK,EAAE,EAAE,mBAAmB,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE;SACzD,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,MAAM,CACV,cAAsB,EACtB,KAA8B,EAC9B,YAAsB;QAEtB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YACpF,MAAM,IAAI,KAAK,CAAC,wFAAwF,CAAC,CAAC;QAC5G,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,iBAAiB,IAAI,KAAK,CAAC;QACpD,IAAI,UAAU,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,oBAAoB,KAAK,CAAC,IAAI,8BAA8B,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,CAAC,UAAU,IAAI,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,SAAS,KAAK,CAAC,IAAI,+EAA+E,CAAC,CAAC;QACtH,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC;YAC5C,KAAK,EAAE,EAAE,mBAAmB,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE;YACpE,MAAM,EAAE;gBACN,cAAc;gBACd,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,EAAE;gBACpC,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,qBAAqB,EAAE,KAAK,CAAC,qBAAqB,IAAI,EAAE;gBACxD,iBAAiB,EAAE,UAAU;gBAC7B,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,eAAe,EAAE,KAAK,CAAC,eAAe,IAAI,EAAE;gBAC5C,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,IAAI,EAAE;gBAC9C,cAAc,EAAE,KAAK,CAAC,cAAc,IAAI,EAAE;aAC3C;YACD,MAAM,EAAE;gBACN,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,EAAE;gBACpC,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,qBAAqB,EAAE,KAAK,CAAC,qBAAqB,IAAI,EAAE;gBACxD,SAAS,EAAE,IAAI,IAAI,EAAE;gBACrB,GAAG,CAAC,KAAK,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1F,GAAG,CAAC,KAAK,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7F,GAAG,CAAC,KAAK,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACxF;SACF,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,MAAM,CACV,cAAsB,EACtB,IAAY,EACZ,KAA8B;QAE9B,MAAM,IAAI,GAAwB,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;QAC5D,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QACxD,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;YAAE,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QAC1E,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC3D,IAAI,KAAK,CAAC,qBAAqB,KAAK,SAAS;YAAE,IAAI,CAAC,qBAAqB,GAAG,KAAK,CAAC,qBAAqB,CAAC;QACxG,IAAI,KAAK,CAAC,eAAe,KAAK,SAAS;YAAE,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;QACtF,IAAI,KAAK,CAAC,gBAAgB,KAAK,SAAS;YAAE,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,CAAC;QACzF,IAAI,KAAK,CAAC,cAAc,KAAK,SAAS;YAAE,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC;QAEnF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC;YAC5C,KAAK,EAAE,EAAE,mBAAmB,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE;YACxD,IAAI;SACL,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,cAAsB,EAAE,IAAY;QAC/C,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC;gBAChC,KAAK,EAAE,EAAE,mBAAmB,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE;aACzD,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"org-agent-type-service.test.d.ts","sourceRoot":"","sources":["../../src/services/org-agent-type-service.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// Unit tests for the builder-declared secret surface added 2026-04-24:
|
|
2
|
+
// custom agent types carry `requiredSecrets`, `secretEnvMapping`, and
|
|
3
|
+
// `dynamicSecrets` on the row so `resolveAgentType` in the orchestrator
|
|
4
|
+
// can read them and inject env vars. Previously these were hardcoded
|
|
5
|
+
// empty in the custom branch; the Prisma model didn't have the columns
|
|
6
|
+
// at all. See docs/superpowers/specs/2026-04-24-custom-agent-type-secret-mapping.md.
|
|
7
|
+
import { describe, expect, it, vi } from "vitest";
|
|
8
|
+
import { OrgAgentTypeService } from "./org-agent-type-service.js";
|
|
9
|
+
// Minimal Prisma mock — just the orgAgentType delegate shape the service
|
|
10
|
+
// reaches for. Stores rows in-memory so upsert/update/findUnique behave
|
|
11
|
+
// like a tiny key-value store keyed by (organizationId, slug).
|
|
12
|
+
function makeMockDb() {
|
|
13
|
+
const store = new Map();
|
|
14
|
+
const key = (orgId, slug) => `${orgId}:${slug}`;
|
|
15
|
+
return {
|
|
16
|
+
orgAgentType: {
|
|
17
|
+
upsert: vi.fn(async ({ where, create, update }) => {
|
|
18
|
+
const k = key(where.organizationId_slug.organizationId, where.organizationId_slug.slug);
|
|
19
|
+
const existing = store.get(k);
|
|
20
|
+
if (existing) {
|
|
21
|
+
const merged = { ...existing, ...update };
|
|
22
|
+
store.set(k, merged);
|
|
23
|
+
return merged;
|
|
24
|
+
}
|
|
25
|
+
const row = {
|
|
26
|
+
id: `id-${store.size}`,
|
|
27
|
+
intrinsicPolicy: {},
|
|
28
|
+
requiredSecrets: [],
|
|
29
|
+
secretEnvMapping: {},
|
|
30
|
+
dynamicSecrets: [],
|
|
31
|
+
createdAt: new Date(),
|
|
32
|
+
updatedAt: new Date(),
|
|
33
|
+
...create,
|
|
34
|
+
};
|
|
35
|
+
store.set(k, row);
|
|
36
|
+
return row;
|
|
37
|
+
}),
|
|
38
|
+
update: vi.fn(async ({ where, data }) => {
|
|
39
|
+
const k = key(where.organizationId_slug.organizationId, where.organizationId_slug.slug);
|
|
40
|
+
const existing = store.get(k);
|
|
41
|
+
if (!existing)
|
|
42
|
+
throw new Error("Not found");
|
|
43
|
+
const merged = { ...existing, ...data };
|
|
44
|
+
store.set(k, merged);
|
|
45
|
+
return merged;
|
|
46
|
+
}),
|
|
47
|
+
findUnique: vi.fn(async ({ where }) => {
|
|
48
|
+
const k = key(where.organizationId_slug.organizationId, where.organizationId_slug.slug);
|
|
49
|
+
return store.get(k) ?? null;
|
|
50
|
+
}),
|
|
51
|
+
findMany: vi.fn(async ({ where }) => {
|
|
52
|
+
return [...store.values()].filter((r) => r.organizationId === where.organizationId);
|
|
53
|
+
}),
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const ORG = "org-1";
|
|
58
|
+
const BUILTIN_SLUGS = ["researcher", "planner", "developer", "reviewer", "brainstormer", "data"];
|
|
59
|
+
describe("OrgAgentTypeService — secret surface round-trip", () => {
|
|
60
|
+
it("persists requiredSecrets, secretEnvMapping, and dynamicSecrets on create", async () => {
|
|
61
|
+
const db = makeMockDb();
|
|
62
|
+
const svc = new OrgAgentTypeService(db);
|
|
63
|
+
const created = await svc.create(ORG, {
|
|
64
|
+
slug: "sg-mailer",
|
|
65
|
+
label: "SendGrid mailer",
|
|
66
|
+
prompt: "You are a mailer.",
|
|
67
|
+
requiredSecrets: ["sendgridApiKey"],
|
|
68
|
+
secretEnvMapping: { sendgridApiKey: "SENDGRID_API_KEY" },
|
|
69
|
+
dynamicSecrets: [],
|
|
70
|
+
createdBy: "alice@example.com",
|
|
71
|
+
}, BUILTIN_SLUGS);
|
|
72
|
+
expect(created.requiredSecrets).toEqual(["sendgridApiKey"]);
|
|
73
|
+
expect(created.secretEnvMapping).toEqual({ sendgridApiKey: "SENDGRID_API_KEY" });
|
|
74
|
+
expect(created.dynamicSecrets).toEqual([]);
|
|
75
|
+
});
|
|
76
|
+
it("round-trips the secret surface through getBySlug", async () => {
|
|
77
|
+
const db = makeMockDb();
|
|
78
|
+
const svc = new OrgAgentTypeService(db);
|
|
79
|
+
await svc.create(ORG, {
|
|
80
|
+
slug: "multi-tool",
|
|
81
|
+
label: "Multi",
|
|
82
|
+
prompt: "…",
|
|
83
|
+
requiredSecrets: ["slackToken", "notionApiKey"],
|
|
84
|
+
secretEnvMapping: { slackToken: "SLACK_BOT_TOKEN", notionApiKey: "NOTION_API_KEY" },
|
|
85
|
+
dynamicSecrets: ["databases"],
|
|
86
|
+
createdBy: "alice@example.com",
|
|
87
|
+
}, BUILTIN_SLUGS);
|
|
88
|
+
const got = await svc.getBySlug(ORG, "multi-tool");
|
|
89
|
+
expect(got).not.toBeNull();
|
|
90
|
+
expect(got.requiredSecrets).toEqual(["slackToken", "notionApiKey"]);
|
|
91
|
+
expect(got.secretEnvMapping).toEqual({
|
|
92
|
+
slackToken: "SLACK_BOT_TOKEN",
|
|
93
|
+
notionApiKey: "NOTION_API_KEY",
|
|
94
|
+
});
|
|
95
|
+
expect(got.dynamicSecrets).toEqual(["databases"]);
|
|
96
|
+
});
|
|
97
|
+
it("defaults to empty arrays / object when no secret fields are provided", async () => {
|
|
98
|
+
const db = makeMockDb();
|
|
99
|
+
const svc = new OrgAgentTypeService(db);
|
|
100
|
+
const created = await svc.create(ORG, {
|
|
101
|
+
slug: "plain",
|
|
102
|
+
label: "Plain",
|
|
103
|
+
prompt: "…",
|
|
104
|
+
createdBy: "alice@example.com",
|
|
105
|
+
}, BUILTIN_SLUGS);
|
|
106
|
+
expect(created.requiredSecrets).toEqual([]);
|
|
107
|
+
expect(created.secretEnvMapping).toEqual({});
|
|
108
|
+
expect(created.dynamicSecrets).toEqual([]);
|
|
109
|
+
});
|
|
110
|
+
it("update merges secret fields without clobbering unspecified ones", async () => {
|
|
111
|
+
const db = makeMockDb();
|
|
112
|
+
const svc = new OrgAgentTypeService(db);
|
|
113
|
+
await svc.create(ORG, {
|
|
114
|
+
slug: "evolving",
|
|
115
|
+
label: "Evolving",
|
|
116
|
+
prompt: "v1",
|
|
117
|
+
requiredSecrets: ["keyA"],
|
|
118
|
+
secretEnvMapping: { keyA: "KEY_A" },
|
|
119
|
+
createdBy: "alice@example.com",
|
|
120
|
+
}, BUILTIN_SLUGS);
|
|
121
|
+
// Updating only the prompt must leave the secret surface intact.
|
|
122
|
+
await svc.update(ORG, "evolving", { prompt: "v2" });
|
|
123
|
+
const afterPromptUpdate = await svc.getBySlug(ORG, "evolving");
|
|
124
|
+
expect(afterPromptUpdate.prompt).toBe("v2");
|
|
125
|
+
expect(afterPromptUpdate.requiredSecrets).toEqual(["keyA"]);
|
|
126
|
+
expect(afterPromptUpdate.secretEnvMapping).toEqual({ keyA: "KEY_A" });
|
|
127
|
+
// Updating only the secret mapping must leave the prompt intact.
|
|
128
|
+
await svc.update(ORG, "evolving", {
|
|
129
|
+
secretEnvMapping: { keyA: "KEY_A", keyB: "KEY_B" },
|
|
130
|
+
requiredSecrets: ["keyA", "keyB"],
|
|
131
|
+
});
|
|
132
|
+
const afterMappingUpdate = await svc.getBySlug(ORG, "evolving");
|
|
133
|
+
expect(afterMappingUpdate.prompt).toBe("v2");
|
|
134
|
+
expect(afterMappingUpdate.requiredSecrets).toEqual(["keyA", "keyB"]);
|
|
135
|
+
expect(afterMappingUpdate.secretEnvMapping).toEqual({ keyA: "KEY_A", keyB: "KEY_B" });
|
|
136
|
+
});
|
|
137
|
+
it("toRecord survives a legacy row with no secret columns (empty defaults)", async () => {
|
|
138
|
+
// Simulates a pre-migration row where the columns literally don't
|
|
139
|
+
// exist on the object. toRecord's guards should surface them as
|
|
140
|
+
// empty rather than `undefined` leaking out to callers.
|
|
141
|
+
const db = makeMockDb();
|
|
142
|
+
// Hand-insert a row that skips the new fields to simulate pre-migration data.
|
|
143
|
+
db.orgAgentType.upsert({
|
|
144
|
+
where: { organizationId_slug: { organizationId: ORG, slug: "legacy" } },
|
|
145
|
+
create: {
|
|
146
|
+
organizationId: ORG,
|
|
147
|
+
slug: "legacy",
|
|
148
|
+
label: "Legacy",
|
|
149
|
+
description: "",
|
|
150
|
+
prompt: "…",
|
|
151
|
+
defaultTimeoutMinutes: 15,
|
|
152
|
+
isBuiltinOverride: false,
|
|
153
|
+
createdBy: "cli",
|
|
154
|
+
},
|
|
155
|
+
update: {},
|
|
156
|
+
});
|
|
157
|
+
// Remove the defaulted fields to really simulate a legacy row.
|
|
158
|
+
const raw = db.orgAgentType.findUnique.getMockImplementation?.();
|
|
159
|
+
void raw;
|
|
160
|
+
const svc = new OrgAgentTypeService(db);
|
|
161
|
+
const got = await svc.getBySlug(ORG, "legacy");
|
|
162
|
+
expect(got).not.toBeNull();
|
|
163
|
+
expect(got.requiredSecrets).toEqual([]);
|
|
164
|
+
expect(got.secretEnvMapping).toEqual({});
|
|
165
|
+
expect(got.dynamicSecrets).toEqual([]);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
//# sourceMappingURL=org-agent-type-service.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"org-agent-type-service.test.js","sourceRoot":"","sources":["../../src/services/org-agent-type-service.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/prisma/schema.prisma
CHANGED
|
@@ -39,6 +39,7 @@ model Organization {
|
|
|
39
39
|
nodeTags NodeTag[]
|
|
40
40
|
nodeChunks NodeChunk[]
|
|
41
41
|
piiQueryLogs PiiQueryLog[]
|
|
42
|
+
documents Document[]
|
|
42
43
|
|
|
43
44
|
@@map("organizations")
|
|
44
45
|
}
|
|
@@ -313,6 +314,12 @@ model OrgAgentType {
|
|
|
313
314
|
toolCatalogue String[] @default([]) @map("tool_catalogue")
|
|
314
315
|
requiresCiba Boolean @default(false) @map("requires_ciba")
|
|
315
316
|
createdByUserId String? @map("created_by_user_id") @db.Uuid
|
|
317
|
+
// Builder-declared secret surface. Empty defaults preserve existing
|
|
318
|
+
// custom-type behavior (no secrets injected). See spec
|
|
319
|
+
// docs/superpowers/specs/2026-04-24-custom-agent-type-secret-mapping.md.
|
|
320
|
+
requiredSecrets String[] @default([]) @map("required_secrets")
|
|
321
|
+
secretEnvMapping Json @default("{}") @map("secret_env_mapping")
|
|
322
|
+
dynamicSecrets String[] @default([]) @map("dynamic_secrets")
|
|
316
323
|
|
|
317
324
|
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
318
325
|
createdByUser User? @relation("OrgAgentTypeCreatedBy", fields: [createdByUserId], references: [id], onDelete: SetNull)
|
|
@@ -608,3 +615,31 @@ model NodeTagAudit {
|
|
|
608
615
|
@@index([orgId, createdAt], map: "idx_tag_audit_org_time")
|
|
609
616
|
@@map("node_tag_audit")
|
|
610
617
|
}
|
|
618
|
+
|
|
619
|
+
// ── Document Archive ────────────────────────────────────────────────────────
|
|
620
|
+
|
|
621
|
+
model Document {
|
|
622
|
+
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
|
623
|
+
organizationId String @map("organization_id") @db.Uuid
|
|
624
|
+
fileName String @map("file_name") @db.VarChar(500)
|
|
625
|
+
mimeType String @map("mime_type") @db.VarChar(100)
|
|
626
|
+
fileSizeBytes Int @map("file_size_bytes")
|
|
627
|
+
storagePath String @map("storage_path") @db.VarChar(1000)
|
|
628
|
+
contentHash String? @map("content_hash") @db.VarChar(64)
|
|
629
|
+
status String @default("uploading") @db.VarChar(20)
|
|
630
|
+
ocrModel String? @map("ocr_model") @db.VarChar(100)
|
|
631
|
+
ocrTokensIn Int? @map("ocr_tokens_in")
|
|
632
|
+
ocrTokensOut Int? @map("ocr_tokens_out")
|
|
633
|
+
pageCount Int? @map("page_count")
|
|
634
|
+
nodeId String? @map("node_id") @db.Uuid
|
|
635
|
+
errorMessage String? @map("error_message")
|
|
636
|
+
createdBy String @map("created_by") @db.VarChar(255)
|
|
637
|
+
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz
|
|
638
|
+
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz
|
|
639
|
+
|
|
640
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
641
|
+
|
|
642
|
+
@@index([organizationId, contentHash], map: "idx_documents_org_hash")
|
|
643
|
+
@@index([organizationId, status], map: "idx_documents_org_status")
|
|
644
|
+
@@map("documents")
|
|
645
|
+
}
|