@cogenta/agents 0.2.1 → 0.5.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/agents/builtins.d.ts +51 -0
- package/dist/agents/builtins.d.ts.map +1 -0
- package/dist/agents/builtins.js +190 -0
- package/dist/agents/builtins.js.map +1 -0
- package/dist/agents/orchestrator.d.ts +98 -0
- package/dist/agents/orchestrator.d.ts.map +1 -0
- package/dist/agents/orchestrator.js +286 -0
- package/dist/agents/orchestrator.js.map +1 -0
- package/dist/agents/store.d.ts +71 -0
- package/dist/agents/store.d.ts.map +1 -0
- package/dist/agents/store.js +211 -0
- package/dist/agents/store.js.map +1 -0
- package/dist/agents/types.d.ts +10 -0
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/assist/agent-identity.d.ts +44 -0
- package/dist/assist/agent-identity.d.ts.map +1 -0
- package/dist/assist/agent-identity.js +136 -0
- package/dist/assist/agent-identity.js.map +1 -0
- package/dist/assist/chat.d.ts +2 -0
- package/dist/assist/chat.d.ts.map +1 -1
- package/dist/assist/chat.js +14 -5
- package/dist/assist/chat.js.map +1 -1
- package/dist/assist/classify.d.ts +3 -2
- package/dist/assist/classify.d.ts.map +1 -1
- package/dist/assist/classify.js +30 -11
- package/dist/assist/classify.js.map +1 -1
- package/dist/assist/faq.d.ts +3 -2
- package/dist/assist/faq.d.ts.map +1 -1
- package/dist/assist/faq.js +31 -13
- package/dist/assist/faq.js.map +1 -1
- package/dist/assist/runtime.d.ts +8 -2
- package/dist/assist/runtime.d.ts.map +1 -1
- package/dist/assist/runtime.js +2 -2
- package/dist/assist/runtime.js.map +1 -1
- package/dist/assist/toolset.d.ts +10 -0
- package/dist/assist/toolset.d.ts.map +1 -1
- package/dist/assist/toolset.js +36 -8
- package/dist/assist/toolset.js.map +1 -1
- package/dist/assist/usage.d.ts +58 -0
- package/dist/assist/usage.d.ts.map +1 -0
- package/dist/assist/usage.js +53 -0
- package/dist/assist/usage.js.map +1 -0
- package/dist/assist/writing.d.ts +10 -9
- package/dist/assist/writing.d.ts.map +1 -1
- package/dist/assist/writing.js +126 -58
- package/dist/assist/writing.js.map +1 -1
- package/dist/audit/with-audit.d.ts +13 -0
- package/dist/audit/with-audit.d.ts.map +1 -1
- package/dist/audit/with-audit.js +6 -0
- package/dist/audit/with-audit.js.map +1 -1
- package/dist/autonomy/levels.d.ts +37 -0
- package/dist/autonomy/levels.d.ts.map +1 -0
- package/dist/autonomy/levels.js +51 -0
- package/dist/autonomy/levels.js.map +1 -0
- package/dist/conversations/store.d.ts +62 -0
- package/dist/conversations/store.d.ts.map +1 -0
- package/dist/conversations/store.js +0 -0
- package/dist/conversations/store.js.map +1 -0
- package/dist/identity/context.d.ts +8 -0
- package/dist/identity/context.d.ts.map +1 -1
- package/dist/identity/context.js +19 -4
- package/dist/identity/context.js.map +1 -1
- package/dist/identity/markdown.d.ts +38 -0
- package/dist/identity/markdown.d.ts.map +1 -0
- package/dist/identity/markdown.js +85 -0
- package/dist/identity/markdown.js.map +1 -0
- package/dist/index.d.ts +62 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -3
- package/dist/index.js.map +1 -1
- package/dist/progress/job-store.d.ts +41 -0
- package/dist/progress/job-store.d.ts.map +1 -0
- package/dist/progress/job-store.js +44 -0
- package/dist/progress/job-store.js.map +1 -0
- package/dist/progress/types.d.ts +21 -0
- package/dist/progress/types.d.ts.map +1 -0
- package/dist/progress/types.js +3 -0
- package/dist/progress/types.js.map +1 -0
- package/dist/prompts/render.d.ts +23 -0
- package/dist/prompts/render.d.ts.map +1 -0
- package/dist/prompts/render.js +35 -0
- package/dist/prompts/render.js.map +1 -0
- package/dist/prompts/seeds.d.ts +34 -0
- package/dist/prompts/seeds.d.ts.map +1 -0
- package/dist/prompts/seeds.js +166 -0
- package/dist/prompts/seeds.js.map +1 -0
- package/dist/prompts/store.d.ts +8 -0
- package/dist/prompts/store.d.ts.map +1 -0
- package/dist/prompts/store.js +153 -0
- package/dist/prompts/store.js.map +1 -0
- package/dist/prompts/types.d.ts +51 -0
- package/dist/prompts/types.d.ts.map +1 -0
- package/dist/prompts/types.js +24 -0
- package/dist/prompts/types.js.map +1 -0
- package/dist/providers/anthropic.d.ts +26 -3
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +60 -12
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/catalog.d.ts +41 -0
- package/dist/providers/catalog.d.ts.map +1 -0
- package/dist/providers/catalog.js +85 -0
- package/dist/providers/catalog.js.map +1 -0
- package/dist/providers/content-parts.d.ts +12 -0
- package/dist/providers/content-parts.d.ts.map +1 -0
- package/dist/providers/content-parts.js +18 -0
- package/dist/providers/content-parts.js.map +1 -0
- package/dist/providers/defaults.d.ts +44 -0
- package/dist/providers/defaults.d.ts.map +1 -0
- package/dist/providers/defaults.js +72 -0
- package/dist/providers/defaults.js.map +1 -0
- package/dist/providers/google.d.ts +20 -3
- package/dist/providers/google.d.ts.map +1 -1
- package/dist/providers/google.js +53 -12
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/openai.d.ts +36 -4
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +113 -21
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/registry.d.ts +38 -21
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/registry.js +64 -8
- package/dist/providers/registry.js.map +1 -1
- package/dist/providers/request-signal.d.ts +18 -0
- package/dist/providers/request-signal.d.ts.map +1 -0
- package/dist/providers/request-signal.js +21 -0
- package/dist/providers/request-signal.js.map +1 -0
- package/dist/providers/resolve.d.ts +13 -0
- package/dist/providers/resolve.d.ts.map +1 -0
- package/dist/providers/resolve.js +30 -0
- package/dist/providers/resolve.js.map +1 -0
- package/dist/providers/store.d.ts +70 -0
- package/dist/providers/store.d.ts.map +1 -0
- package/dist/providers/store.js +308 -0
- package/dist/providers/store.js.map +1 -0
- package/dist/providers/tool-names.d.ts +9 -0
- package/dist/providers/tool-names.d.ts.map +1 -0
- package/dist/providers/tool-names.js +56 -0
- package/dist/providers/tool-names.js.map +1 -0
- package/dist/providers/types.d.ts +87 -3
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/rag/reference-documents/ingest.d.ts +22 -0
- package/dist/rag/reference-documents/ingest.d.ts.map +1 -0
- package/dist/rag/reference-documents/ingest.js +69 -0
- package/dist/rag/reference-documents/ingest.js.map +1 -0
- package/dist/rag/reference-documents/store.d.ts +23 -0
- package/dist/rag/reference-documents/store.d.ts.map +1 -0
- package/dist/rag/reference-documents/store.js +140 -0
- package/dist/rag/reference-documents/store.js.map +1 -0
- package/dist/rag/reference-documents/types.d.ts +52 -0
- package/dist/rag/reference-documents/types.d.ts.map +1 -0
- package/dist/rag/reference-documents/types.js +32 -0
- package/dist/rag/reference-documents/types.js.map +1 -0
- package/dist/runtime/loop.d.ts +29 -7
- package/dist/runtime/loop.d.ts.map +1 -1
- package/dist/runtime/loop.js +209 -44
- package/dist/runtime/loop.js.map +1 -1
- package/dist/runtime/retry.d.ts +2 -0
- package/dist/runtime/retry.d.ts.map +1 -1
- package/dist/runtime/retry.js +1 -0
- package/dist/runtime/retry.js.map +1 -1
- package/dist/runtime/types.d.ts +14 -3
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/site-plan/analyse-brief.d.ts +8 -0
- package/dist/site-plan/analyse-brief.d.ts.map +1 -1
- package/dist/site-plan/analyse-brief.js +17 -8
- package/dist/site-plan/analyse-brief.js.map +1 -1
- package/dist/site-plan/approval.d.ts +2 -2
- package/dist/site-plan/approval.d.ts.map +1 -1
- package/dist/site-plan/approval.js +34 -4
- package/dist/site-plan/approval.js.map +1 -1
- package/dist/site-plan/content-model.d.ts +14 -0
- package/dist/site-plan/content-model.d.ts.map +1 -1
- package/dist/site-plan/content-model.js +51 -9
- package/dist/site-plan/content-model.js.map +1 -1
- package/dist/site-plan/demo-content.d.ts.map +1 -1
- package/dist/site-plan/demo-content.js +1 -4
- package/dist/site-plan/demo-content.js.map +1 -1
- package/dist/site-plan/propose-plan.d.ts +10 -0
- package/dist/site-plan/propose-plan.d.ts.map +1 -1
- package/dist/site-plan/propose-plan.js +25 -1
- package/dist/site-plan/propose-plan.js.map +1 -1
- package/dist/site-plan/site-context.d.ts +81 -0
- package/dist/site-plan/site-context.d.ts.map +1 -0
- package/dist/site-plan/site-context.js +76 -0
- package/dist/site-plan/site-context.js.map +1 -0
- package/dist/site-plan/skin-candidates.d.ts +13 -1
- package/dist/site-plan/skin-candidates.d.ts.map +1 -1
- package/dist/site-plan/skin-candidates.js +15 -0
- package/dist/site-plan/skin-candidates.js.map +1 -1
- package/dist/site-plan/structural-gaps.d.ts +32 -0
- package/dist/site-plan/structural-gaps.d.ts.map +1 -0
- package/dist/site-plan/structural-gaps.js +77 -0
- package/dist/site-plan/structural-gaps.js.map +1 -0
- package/dist/site-plan/types.d.ts +7 -0
- package/dist/site-plan/types.d.ts.map +1 -1
- package/dist/skills/frontmatter.d.ts +19 -1
- package/dist/skills/frontmatter.d.ts.map +1 -1
- package/dist/skills/frontmatter.js +29 -5
- package/dist/skills/frontmatter.js.map +1 -1
- package/dist/skills/library.d.ts +133 -0
- package/dist/skills/library.d.ts.map +1 -0
- package/dist/skills/library.js +332 -0
- package/dist/skills/library.js.map +1 -0
- package/dist/skills/types.d.ts +8 -1
- package/dist/skills/types.d.ts.map +1 -1
- package/dist/skin/generate.d.ts +22 -1
- package/dist/skin/generate.d.ts.map +1 -1
- package/dist/skin/generate.js +60 -5
- package/dist/skin/generate.js.map +1 -1
- package/dist/theme-creator/propose-theme.d.ts +83 -0
- package/dist/theme-creator/propose-theme.d.ts.map +1 -0
- package/dist/theme-creator/propose-theme.js +234 -0
- package/dist/theme-creator/propose-theme.js.map +1 -0
- package/dist/tools/core/agent-delegate.d.ts +8 -5
- package/dist/tools/core/agent-delegate.d.ts.map +1 -1
- package/dist/tools/core/agent-delegate.js +16 -6
- package/dist/tools/core/agent-delegate.js.map +1 -1
- package/dist/tools/core/content-browse.d.ts +74 -0
- package/dist/tools/core/content-browse.d.ts.map +1 -0
- package/dist/tools/core/content-browse.js +63 -0
- package/dist/tools/core/content-browse.js.map +1 -0
- package/dist/tools/core/content-schema.d.ts +86 -0
- package/dist/tools/core/content-schema.d.ts.map +1 -0
- package/dist/tools/core/content-schema.js +83 -0
- package/dist/tools/core/content-schema.js.map +1 -0
- package/dist/tools/core/deps-scan.d.ts +25 -0
- package/dist/tools/core/deps-scan.d.ts.map +1 -0
- package/dist/tools/core/deps-scan.js +85 -0
- package/dist/tools/core/deps-scan.js.map +1 -0
- package/dist/tools/core/media.d.ts +18 -2
- package/dist/tools/core/media.d.ts.map +1 -1
- package/dist/tools/core/media.js +8 -2
- package/dist/tools/core/media.js.map +1 -1
- package/dist/tools/core/not-found-log.d.ts +44 -0
- package/dist/tools/core/not-found-log.d.ts.map +1 -0
- package/dist/tools/core/not-found-log.js +32 -0
- package/dist/tools/core/not-found-log.js.map +1 -0
- package/dist/tools/core/redirects.d.ts +51 -0
- package/dist/tools/core/redirects.d.ts.map +1 -0
- package/dist/tools/core/redirects.js +50 -0
- package/dist/tools/core/redirects.js.map +1 -0
- package/package.json +6 -4
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type DatabaseHandle } from '@cogenta/core';
|
|
2
|
+
import type { DocumentFormat } from '../../documents/extract-text.js';
|
|
3
|
+
import type { ReferenceDocumentRecord } from './types.js';
|
|
4
|
+
export interface CreateReferenceDocumentInput {
|
|
5
|
+
readonly siteId: string;
|
|
6
|
+
readonly filename: string;
|
|
7
|
+
readonly format: DocumentFormat;
|
|
8
|
+
readonly characters: number;
|
|
9
|
+
readonly warnings: readonly string[];
|
|
10
|
+
readonly uploadedBy: string | null;
|
|
11
|
+
}
|
|
12
|
+
export interface ReferenceDocumentStore {
|
|
13
|
+
ensureTable(): Promise<void>;
|
|
14
|
+
list(siteId: string): Promise<readonly ReferenceDocumentRecord[]>;
|
|
15
|
+
get(siteId: string, id: string): Promise<ReferenceDocumentRecord | null>;
|
|
16
|
+
/** Inserted with `status: 'pending'` — indexing (embedding + vector upsert) happens after, and reports back via `markIndexed`/`markError`. */
|
|
17
|
+
create(input: CreateReferenceDocumentInput): Promise<ReferenceDocumentRecord>;
|
|
18
|
+
markIndexed(siteId: string, id: string, chunkCount: number, at: string): Promise<void>;
|
|
19
|
+
markError(siteId: string, id: string, message: string): Promise<void>;
|
|
20
|
+
remove(siteId: string, id: string): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
export declare function createReferenceDocumentStore(db: DatabaseHandle, now?: () => number): ReferenceDocumentStore;
|
|
23
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/rag/reference-documents/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,cAAc,EAMpB,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAA;AACrE,OAAO,KAAK,EAAE,uBAAuB,EAA2B,MAAM,YAAY,CAAA;AAqElF,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CACnC;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,uBAAuB,EAAE,CAAC,CAAA;IACjE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAA;IACxE,8IAA8I;IAC9I,MAAM,CAAC,KAAK,EAAE,4BAA4B,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAA;IAC7E,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtF,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAClD;AAWD,wBAAgB,4BAA4B,CAC1C,EAAE,EAAE,cAAc,EAClB,GAAG,GAAE,MAAM,MAAiB,GAC3B,sBAAsB,CAwFxB"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { CogentaError, identifier, newId, sql, unsafeRaw, } from '@cogenta/core';
|
|
2
|
+
/**
|
|
3
|
+
* Metadata for every reference document a site has uploaded — L22 task 4's
|
|
4
|
+
* "état clair de ce qui est indexé/en cours/en erreur". The vector store
|
|
5
|
+
* (`VectorStore`) holds the embedded chunks; this table holds the one row
|
|
6
|
+
* per upload that the admin screen actually renders a list from, because a
|
|
7
|
+
* `VectorStore` has no notion of "a document", only of chunks that happen to
|
|
8
|
+
* share an `entryId`.
|
|
9
|
+
*
|
|
10
|
+
* Column helpers are written out by hand rather than imported from
|
|
11
|
+
* `@cogenta/schema`'s `store/columns.ts`: that module is not part of
|
|
12
|
+
* `@cogenta/schema`'s public `exports` map (only `.` is), and `@cogenta/agents`
|
|
13
|
+
* may not deep-import another package's `src/`. Three columns' worth of
|
|
14
|
+
* per-dialect typing is not worth widening that package's public surface for.
|
|
15
|
+
*/
|
|
16
|
+
const REFERENCE_DOCUMENTS_TABLE = 'cogenta_reference_documents';
|
|
17
|
+
function textColumn(dialect, length) {
|
|
18
|
+
return unsafeRaw(dialect === 'sqlite' ? 'text' : `varchar(${length})`);
|
|
19
|
+
}
|
|
20
|
+
function idColumn(dialect) {
|
|
21
|
+
if (dialect === 'postgres')
|
|
22
|
+
return unsafeRaw('uuid');
|
|
23
|
+
if (dialect === 'mysql')
|
|
24
|
+
return unsafeRaw('char(36)');
|
|
25
|
+
return unsafeRaw('text');
|
|
26
|
+
}
|
|
27
|
+
function timestampColumn(dialect) {
|
|
28
|
+
return textColumn(dialect, 32);
|
|
29
|
+
}
|
|
30
|
+
function integerColumn() {
|
|
31
|
+
return unsafeRaw('integer');
|
|
32
|
+
}
|
|
33
|
+
function toRecord(row) {
|
|
34
|
+
return {
|
|
35
|
+
id: row.id,
|
|
36
|
+
siteId: row.site_id,
|
|
37
|
+
filename: row.filename,
|
|
38
|
+
format: row.format,
|
|
39
|
+
characters: Number(row.characters),
|
|
40
|
+
chunkCount: Number(row.chunk_count),
|
|
41
|
+
status: row.status,
|
|
42
|
+
errorMessage: row.error_message,
|
|
43
|
+
warnings: JSON.parse(row.warnings),
|
|
44
|
+
uploadedAt: row.uploaded_at,
|
|
45
|
+
uploadedBy: row.uploaded_by,
|
|
46
|
+
indexedAt: row.indexed_at,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function notFound(id) {
|
|
50
|
+
return new CogentaError({
|
|
51
|
+
code: 'ASSIST_DOCUMENT_NOT_FOUND',
|
|
52
|
+
message: `No reference document "${id}" exists on this site.`,
|
|
53
|
+
hint: 'Check the id against GET /api/assistant/documents — it may already have been removed.',
|
|
54
|
+
details: { id },
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
export function createReferenceDocumentStore(db, now = Date.now) {
|
|
58
|
+
const d = db.dialect;
|
|
59
|
+
const table = identifier(REFERENCE_DOCUMENTS_TABLE, d);
|
|
60
|
+
return {
|
|
61
|
+
async ensureTable() {
|
|
62
|
+
await db.query(sql `
|
|
63
|
+
create table if not exists ${table} (
|
|
64
|
+
id ${idColumn(d)} not null primary key,
|
|
65
|
+
site_id ${textColumn(d, 500)} not null,
|
|
66
|
+
filename ${textColumn(d, 300)} not null,
|
|
67
|
+
format ${textColumn(d, 16)} not null,
|
|
68
|
+
characters ${integerColumn()} not null,
|
|
69
|
+
chunk_count ${integerColumn()} not null,
|
|
70
|
+
status ${textColumn(d, 16)} not null,
|
|
71
|
+
error_message ${textColumn(d, 2000)},
|
|
72
|
+
warnings ${textColumn(d, 4000)} not null,
|
|
73
|
+
uploaded_at ${timestampColumn(d)} not null,
|
|
74
|
+
uploaded_by ${idColumn(d)},
|
|
75
|
+
indexed_at ${timestampColumn(d)}
|
|
76
|
+
)`);
|
|
77
|
+
},
|
|
78
|
+
async list(siteId) {
|
|
79
|
+
// `id` (UUIDv7) breaks a tie on `uploaded_at` in the same direction —
|
|
80
|
+
// two uploads landing in the same millisecond still sort newest first,
|
|
81
|
+
// deterministically, rather than by whatever order SQLite feels like.
|
|
82
|
+
const result = await db.query(sql `
|
|
83
|
+
select * from ${table} where site_id = ${siteId} order by uploaded_at desc, id desc`);
|
|
84
|
+
return result.rows.map(toRecord);
|
|
85
|
+
},
|
|
86
|
+
async get(siteId, id) {
|
|
87
|
+
const result = await db.query(sql `
|
|
88
|
+
select * from ${table} where site_id = ${siteId} and id = ${id}`);
|
|
89
|
+
const row = result.rows[0];
|
|
90
|
+
return row === undefined ? null : toRecord(row);
|
|
91
|
+
},
|
|
92
|
+
async create(input) {
|
|
93
|
+
const id = newId(now);
|
|
94
|
+
const uploadedAt = new Date(now()).toISOString();
|
|
95
|
+
await db.query(sql `
|
|
96
|
+
insert into ${table}
|
|
97
|
+
(id, site_id, filename, format, characters, chunk_count, status,
|
|
98
|
+
error_message, warnings, uploaded_at, uploaded_by, indexed_at)
|
|
99
|
+
values (
|
|
100
|
+
${id}, ${input.siteId}, ${input.filename}, ${input.format}, ${input.characters}, 0,
|
|
101
|
+
${'pending'}, ${null}, ${JSON.stringify([...input.warnings])}, ${uploadedAt},
|
|
102
|
+
${input.uploadedBy}, ${null}
|
|
103
|
+
)`);
|
|
104
|
+
return {
|
|
105
|
+
id,
|
|
106
|
+
siteId: input.siteId,
|
|
107
|
+
filename: input.filename,
|
|
108
|
+
format: input.format,
|
|
109
|
+
characters: input.characters,
|
|
110
|
+
chunkCount: 0,
|
|
111
|
+
status: 'pending',
|
|
112
|
+
errorMessage: null,
|
|
113
|
+
warnings: input.warnings,
|
|
114
|
+
uploadedAt,
|
|
115
|
+
uploadedBy: input.uploadedBy,
|
|
116
|
+
indexedAt: null,
|
|
117
|
+
};
|
|
118
|
+
},
|
|
119
|
+
async markIndexed(siteId, id, chunkCount, at) {
|
|
120
|
+
await db.query(sql `
|
|
121
|
+
update ${table}
|
|
122
|
+
set status = ${'indexed'}, chunk_count = ${chunkCount}, error_message = ${null}, indexed_at = ${at}
|
|
123
|
+
where site_id = ${siteId} and id = ${id}`);
|
|
124
|
+
},
|
|
125
|
+
async markError(siteId, id, message) {
|
|
126
|
+
await db.query(sql `
|
|
127
|
+
update ${table}
|
|
128
|
+
set status = ${'error'}, error_message = ${message}
|
|
129
|
+
where site_id = ${siteId} and id = ${id}`);
|
|
130
|
+
},
|
|
131
|
+
async remove(siteId, id) {
|
|
132
|
+
const existing = await db.query(sql `
|
|
133
|
+
select id from ${table} where site_id = ${siteId} and id = ${id}`);
|
|
134
|
+
if (existing.rows.length === 0)
|
|
135
|
+
throw notFound(id);
|
|
136
|
+
await db.query(sql `delete from ${table} where site_id = ${siteId} and id = ${id}`);
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/rag/reference-documents/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { DocumentFormat } from '../../documents/extract-text.js';
|
|
2
|
+
/**
|
|
3
|
+
* L22 task 4 — "un flux d'upload de documents additionnels", wired onto the
|
|
4
|
+
* existing extraction → chunking → vectorisation pipeline (L19/L18) rather
|
|
5
|
+
* than a second one.
|
|
6
|
+
*
|
|
7
|
+
* A reference document is not content: it has no collection, no locale
|
|
8
|
+
* variants, no draft/published lifecycle. It still needs a home in the
|
|
9
|
+
* vector index so `assist.chat` can retrieve it — `VectorRecord` requires a
|
|
10
|
+
* `collection`/`entryId`/`locale`/`status` (task 5's `VectorScope`), so this
|
|
11
|
+
* pseudo-collection name is the answer to "what collection is a reference
|
|
12
|
+
* document in?".
|
|
13
|
+
*
|
|
14
|
+
* `^_` can never collide with a real collection name:
|
|
15
|
+
* `defineCollection`'s own `COLLECTION_NAME_PATTERN` is
|
|
16
|
+
* `/^[a-z][a-z0-9_]*$/`, which requires a *letter* first. Starting with an
|
|
17
|
+
* underscore is therefore a name no `defineCollection` call can ever
|
|
18
|
+
* produce, on any site, without needing a registry or a reserved-word list
|
|
19
|
+
* kept in sync by hand.
|
|
20
|
+
*/
|
|
21
|
+
export declare const REFERENCE_DOCUMENT_COLLECTION = "_reference_documents";
|
|
22
|
+
/** `locale` a reference document's chunks are stored under — it has no translations, so one sentinel value stands in for "not localised". */
|
|
23
|
+
export declare const REFERENCE_DOCUMENT_LOCALE = "und";
|
|
24
|
+
/**
|
|
25
|
+
* `status` a reference document's chunks are stored under. Reusing the
|
|
26
|
+
* content lifecycle's own `'published'` value (rather than inventing a new
|
|
27
|
+
* one) is what lets `assist.chat`'s hard-coded `status: 'published'` filter
|
|
28
|
+
* retrieve it with no change to that tool — a reference document is exactly
|
|
29
|
+
* as quotable as a published entry, the moment it finishes indexing.
|
|
30
|
+
*/
|
|
31
|
+
export declare const REFERENCE_DOCUMENT_STATUS = "published";
|
|
32
|
+
export declare const REFERENCE_DOCUMENT_STATUSES: readonly ['pending', 'indexed', 'error'];
|
|
33
|
+
export type ReferenceDocumentStatus = (typeof REFERENCE_DOCUMENT_STATUSES)[number];
|
|
34
|
+
export interface ReferenceDocumentRecord {
|
|
35
|
+
readonly id: string;
|
|
36
|
+
readonly siteId: string;
|
|
37
|
+
readonly filename: string;
|
|
38
|
+
readonly format: DocumentFormat;
|
|
39
|
+
readonly characters: number;
|
|
40
|
+
/** Chunks actually embedded and stored. `0` until indexing finishes. */
|
|
41
|
+
readonly chunkCount: number;
|
|
42
|
+
readonly status: ReferenceDocumentStatus;
|
|
43
|
+
/** Set only when `status === 'error'`. */
|
|
44
|
+
readonly errorMessage: string | null;
|
|
45
|
+
/** `extractDocumentText`'s own warnings (e.g. "PDF page 4 has no text layer") — shown, never hidden. */
|
|
46
|
+
readonly warnings: readonly string[];
|
|
47
|
+
readonly uploadedAt: string;
|
|
48
|
+
readonly uploadedBy: string | null;
|
|
49
|
+
/** Set once indexing finishes successfully. */
|
|
50
|
+
readonly indexedAt: string | null;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/rag/reference-documents/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAA;AAErE;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,6BAA6B,yBAAyB,CAAA;AAEnE,6IAA6I;AAC7I,eAAO,MAAM,yBAAyB,QAAQ,CAAA;AAE9C;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,cAAc,CAAA;AAEpD,eAAO,MAAM,2BAA2B,YAAI,SAAS,EAAE,SAAS,EAAE,OAAO,CAAU,CAAA;AACnF,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAA;AAElF,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAA;IACxC,0CAA0C;IAC1C,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,wGAAwG;IACxG,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,+CAA+C;IAC/C,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAClC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L22 task 4 — "un flux d'upload de documents additionnels", wired onto the
|
|
3
|
+
* existing extraction → chunking → vectorisation pipeline (L19/L18) rather
|
|
4
|
+
* than a second one.
|
|
5
|
+
*
|
|
6
|
+
* A reference document is not content: it has no collection, no locale
|
|
7
|
+
* variants, no draft/published lifecycle. It still needs a home in the
|
|
8
|
+
* vector index so `assist.chat` can retrieve it — `VectorRecord` requires a
|
|
9
|
+
* `collection`/`entryId`/`locale`/`status` (task 5's `VectorScope`), so this
|
|
10
|
+
* pseudo-collection name is the answer to "what collection is a reference
|
|
11
|
+
* document in?".
|
|
12
|
+
*
|
|
13
|
+
* `^_` can never collide with a real collection name:
|
|
14
|
+
* `defineCollection`'s own `COLLECTION_NAME_PATTERN` is
|
|
15
|
+
* `/^[a-z][a-z0-9_]*$/`, which requires a *letter* first. Starting with an
|
|
16
|
+
* underscore is therefore a name no `defineCollection` call can ever
|
|
17
|
+
* produce, on any site, without needing a registry or a reserved-word list
|
|
18
|
+
* kept in sync by hand.
|
|
19
|
+
*/
|
|
20
|
+
export const REFERENCE_DOCUMENT_COLLECTION = '_reference_documents';
|
|
21
|
+
/** `locale` a reference document's chunks are stored under — it has no translations, so one sentinel value stands in for "not localised". */
|
|
22
|
+
export const REFERENCE_DOCUMENT_LOCALE = 'und';
|
|
23
|
+
/**
|
|
24
|
+
* `status` a reference document's chunks are stored under. Reusing the
|
|
25
|
+
* content lifecycle's own `'published'` value (rather than inventing a new
|
|
26
|
+
* one) is what lets `assist.chat`'s hard-coded `status: 'published'` filter
|
|
27
|
+
* retrieve it with no change to that tool — a reference document is exactly
|
|
28
|
+
* as quotable as a published entry, the moment it finishes indexing.
|
|
29
|
+
*/
|
|
30
|
+
export const REFERENCE_DOCUMENT_STATUS = 'published';
|
|
31
|
+
export const REFERENCE_DOCUMENT_STATUSES = ['pending', 'indexed', 'error'];
|
|
32
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/rag/reference-documents/types.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,sBAAsB,CAAA;AAEnE,6IAA6I;AAC7I,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,CAAA;AAE9C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,WAAW,CAAA;AAEpD,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAU,CAAA"}
|
package/dist/runtime/loop.d.ts
CHANGED
|
@@ -1,11 +1,33 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ProviderToolCall } from '../providers/types.js';
|
|
2
|
+
import type { ExecutableTool, RunAgentLoopInput, RunResult, ToolCallOutcome } from './types.js';
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* L24 task 1's whole point, made concrete: this function knows nothing about
|
|
5
|
+
* autonomy, approval, or audit. It is handed whatever `ExecutableTool` its
|
|
6
|
+
* caller built, and calls `.execute()` on it — nothing more. Contract C's R4
|
|
7
|
+
* ("un outil déclare ses permissions ; le runtime les vérifie — jamais un
|
|
8
|
+
* contrôle d'accès à l'intérieur d'un outil") extends unchanged to the graph
|
|
9
|
+
* era this way: the *tools* node below (the graph's own "inside a node" —
|
|
10
|
+
* see the task's own wording) is exactly this function wired to LangGraph,
|
|
11
|
+
* so it inherits the same "zero permission logic" property by construction.
|
|
12
|
+
* `packages/agents/test/runtime/loop.test.ts`'s "the graph node has no gate
|
|
13
|
+
* of its own" test calls this directly, once with a tool `withAutonomy`
|
|
14
|
+
* never touched (to show it *would* run unguarded) and once with the same
|
|
15
|
+
* tool wrapped (to show the run this package actually produces never can) —
|
|
16
|
+
* proving the gate lives in the tool object handed in, not in this function.
|
|
17
|
+
*/
|
|
18
|
+
export declare function runTool(tool: ExecutableTool | undefined, call: ProviderToolCall, signal: AbortSignal): Promise<ToolCallOutcome>;
|
|
19
|
+
/**
|
|
20
|
+
* L4 task 2, migrated to LangGraph.js (L24 task 1): one model call, tool
|
|
21
|
+
* dispatch, repeat — with the same three guards as before (a step ceiling,
|
|
22
|
+
* repetition detection, per-call cost measured from the first line), now run
|
|
23
|
+
* as a two-node `StateGraph` (`buildAgentGraph` above) instead of a `for`
|
|
24
|
+
* loop. The public contract — `RunAgentLoopInput` in, `RunResult` out — is
|
|
25
|
+
* unchanged, so every existing caller (`agents/orchestrator.ts`,
|
|
26
|
+
* `subagents/run-subagent.ts`, `tools/core/agent-delegate.ts`,
|
|
27
|
+
* `assist/runtime.ts`, `eval/run-suite.ts`) needed no change at all.
|
|
28
|
+
* Permission checking (task 4, now `withAutonomy`) and budgets (task 8)
|
|
29
|
+
* still wrap this from the outside; this module still only knows how to
|
|
30
|
+
* hold a conversation with a model and the tools it was handed.
|
|
9
31
|
*/
|
|
10
32
|
export declare function runAgentLoop(input: RunAgentLoopInput): Promise<RunResult>;
|
|
11
33
|
//# sourceMappingURL=loop.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/runtime/loop.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/runtime/loop.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAe,gBAAgB,EAAc,MAAM,uBAAuB,CAAA;AAGtF,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,SAAS,EAGT,eAAe,EAChB,MAAM,YAAY,CAAA;AAkBnB;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,OAAO,CAC3B,IAAI,EAAE,cAAc,GAAG,SAAS,EAChC,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,eAAe,CAAC,CAU1B;AAyND;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,CAAC,CAyC/E"}
|
package/dist/runtime/loop.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
2
|
+
import { Annotation, END, GraphRecursionError, START, StateGraph } from '@langchain/langgraph';
|
|
1
3
|
import { assertProviderAllowed } from '../privacy/assert-provider-allowed.js';
|
|
4
|
+
import { NOOP_PROGRESS } from '../progress/types.js';
|
|
2
5
|
import { RepetitionGuard } from './repetition.js';
|
|
3
6
|
import { retryModelCall, withTimeout } from './retry.js';
|
|
7
|
+
/** Tool-call step budget and repetition guard — orchestration policy, not a property of any one model, so these stay fixed defaults rather than admin-configurable per provider. */
|
|
4
8
|
const DEFAULT_MAX_STEPS = 25;
|
|
5
|
-
const DEFAULT_MAX_ATTEMPTS = 3;
|
|
6
|
-
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
7
9
|
const DEFAULT_MAX_REPEATS = 2;
|
|
10
|
+
const ZERO_USAGE = { inputTokens: 0, outputTokens: 0 };
|
|
8
11
|
function addUsage(a, b) {
|
|
9
12
|
return {
|
|
10
13
|
inputTokens: a.inputTokens + b.inputTokens,
|
|
@@ -14,7 +17,22 @@ function addUsage(a, b) {
|
|
|
14
17
|
function toolByName(tools) {
|
|
15
18
|
return new Map(tools.map((tool) => [tool.spec.name, tool]));
|
|
16
19
|
}
|
|
17
|
-
|
|
20
|
+
/**
|
|
21
|
+
* L24 task 1's whole point, made concrete: this function knows nothing about
|
|
22
|
+
* autonomy, approval, or audit. It is handed whatever `ExecutableTool` its
|
|
23
|
+
* caller built, and calls `.execute()` on it — nothing more. Contract C's R4
|
|
24
|
+
* ("un outil déclare ses permissions ; le runtime les vérifie — jamais un
|
|
25
|
+
* contrôle d'accès à l'intérieur d'un outil") extends unchanged to the graph
|
|
26
|
+
* era this way: the *tools* node below (the graph's own "inside a node" —
|
|
27
|
+
* see the task's own wording) is exactly this function wired to LangGraph,
|
|
28
|
+
* so it inherits the same "zero permission logic" property by construction.
|
|
29
|
+
* `packages/agents/test/runtime/loop.test.ts`'s "the graph node has no gate
|
|
30
|
+
* of its own" test calls this directly, once with a tool `withAutonomy`
|
|
31
|
+
* never touched (to show it *would* run unguarded) and once with the same
|
|
32
|
+
* tool wrapped (to show the run this package actually produces never can) —
|
|
33
|
+
* proving the gate lives in the tool object handed in, not in this function.
|
|
34
|
+
*/
|
|
35
|
+
export async function runTool(tool, call, signal) {
|
|
18
36
|
if (tool === undefined) {
|
|
19
37
|
return { call, ok: false, error: `No tool named "${call.name}" is available in this run.` };
|
|
20
38
|
}
|
|
@@ -27,90 +45,237 @@ async function runTool(tool, call, signal) {
|
|
|
27
45
|
}
|
|
28
46
|
}
|
|
29
47
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
48
|
+
* The graph's state. Every field uses LangGraph's default `LastValue`
|
|
49
|
+
* channel (no reducer) — a node's returned value simply replaces the
|
|
50
|
+
* previous one, the same "whole new value each time" style the pre-L24
|
|
51
|
+
* hand-written loop used for its local variables. `pending*` fields are the
|
|
52
|
+
* only thing carried from the `agent` node to the `tools` node — they hold
|
|
53
|
+
* exactly what the old loop kept on the stack between "got a response with
|
|
54
|
+
* tool calls" and "finished executing them".
|
|
36
55
|
*/
|
|
37
|
-
|
|
56
|
+
const AgentGraphState = Annotation.Root({
|
|
57
|
+
messages: Annotation(),
|
|
58
|
+
steps: Annotation(),
|
|
59
|
+
usage: Annotation(),
|
|
60
|
+
finalText: Annotation(),
|
|
61
|
+
stopReason: Annotation(),
|
|
62
|
+
stepIndex: Annotation(),
|
|
63
|
+
pendingAssistant: Annotation(),
|
|
64
|
+
pendingToolCalls: Annotation(),
|
|
65
|
+
pendingUsage: Annotation(),
|
|
66
|
+
});
|
|
67
|
+
/**
|
|
68
|
+
* Builds (and compiles) a fresh two-node graph for one `runAgentLoop` call:
|
|
69
|
+
* `agent` (one model turn — every guard the old loop checked before calling
|
|
70
|
+
* the model, then the call itself) and `tools` (executes whatever tool calls
|
|
71
|
+
* the `agent` node decided to make, via `runTool` above). `agent` is the only
|
|
72
|
+
* node with an edge back to itself (through `tools`), so "one iteration" of
|
|
73
|
+
* the old `for` loop is exactly one `agent → tools → agent` cycle here — the
|
|
74
|
+
* per-iteration guard order (privacy, signal, kill switch, duration, budget,
|
|
75
|
+
* then the model call) is preserved byte-for-byte because it is still one
|
|
76
|
+
* function, just called by LangGraph instead of by a `for`.
|
|
77
|
+
*
|
|
78
|
+
* Nothing here decides whether a tool call is *allowed* — that decision was
|
|
79
|
+
* already made (or not) before this function ever sees `input.tools`, by
|
|
80
|
+
* whoever built that array (`withAutonomyForManifest` in
|
|
81
|
+
* `agents/orchestrator.ts` for every real caller). The `tools` node below
|
|
82
|
+
* has no branch for "is this tool allowed" — it cannot have one, because it
|
|
83
|
+
* never sees a raw tool to begin with.
|
|
84
|
+
*/
|
|
85
|
+
function buildAgentGraph(input) {
|
|
38
86
|
const maxSteps = input.maxSteps ?? DEFAULT_MAX_STEPS;
|
|
39
|
-
const maxAttempts = input.maxAttempts ??
|
|
40
|
-
const timeoutMs = input.timeoutMs ??
|
|
87
|
+
const maxAttempts = input.maxAttempts ?? input.client.maxCorrectionAttempts;
|
|
88
|
+
const timeoutMs = input.timeoutMs ?? input.client.requestTimeoutMs;
|
|
41
89
|
const now = input.now ?? Date.now;
|
|
42
90
|
const tools = input.tools ?? [];
|
|
43
91
|
const toolIndex = toolByName(tools);
|
|
44
92
|
const toolSpecs = tools.length === 0 ? undefined : tools.map((tool) => tool.spec);
|
|
45
93
|
const repetitionGuard = new RepetitionGuard(input.maxRepeats ?? DEFAULT_MAX_REPEATS);
|
|
46
|
-
const messages = [...input.messages];
|
|
47
|
-
const steps = [];
|
|
48
|
-
let totalUsage = { inputTokens: 0, outputTokens: 0 };
|
|
49
|
-
let finalText = null;
|
|
50
94
|
const runStartedAt = now();
|
|
51
|
-
|
|
95
|
+
const progress = input.onProgress ?? NOOP_PROGRESS;
|
|
96
|
+
async function agentNode(state) {
|
|
52
97
|
if (input.privacyPolicy !== undefined) {
|
|
53
98
|
assertProviderAllowed(input.client, input.privacyPolicy);
|
|
54
99
|
}
|
|
55
|
-
if (input.signal?.aborted === true)
|
|
56
|
-
return {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return { messages, steps, finalText, stopReason: 'killed', usage: totalUsage };
|
|
60
|
-
}
|
|
100
|
+
if (input.signal?.aborted === true)
|
|
101
|
+
return { stopReason: 'cancelled' };
|
|
102
|
+
if (input.killSwitch?.isActive() === true)
|
|
103
|
+
return { stopReason: 'killed' };
|
|
61
104
|
if (input.maxRunDurationMs !== undefined && now() - runStartedAt >= input.maxRunDurationMs) {
|
|
62
|
-
return {
|
|
105
|
+
return { stopReason: 'max_duration' };
|
|
63
106
|
}
|
|
107
|
+
if (state.stepIndex >= maxSteps)
|
|
108
|
+
return { stopReason: 'max_steps' };
|
|
64
109
|
if (input.budget !== undefined) {
|
|
65
110
|
const check = input.budget.checkCall();
|
|
66
111
|
if (!check.allowed) {
|
|
67
112
|
if (check.reason !== undefined)
|
|
68
113
|
input.onBudgetExceeded?.(check.reason);
|
|
69
|
-
return {
|
|
114
|
+
return { stopReason: 'budget_exceeded' };
|
|
70
115
|
}
|
|
71
116
|
}
|
|
117
|
+
progress.report(state.stepIndex === 0 ? 'Thinking…' : `Thinking… (step ${state.stepIndex + 1})`);
|
|
72
118
|
const response = await retryModelCall(() => withTimeout((signal) => input.client.chat({
|
|
73
119
|
model: input.client.model,
|
|
74
120
|
...(input.system === undefined ? {} : { system: input.system }),
|
|
75
|
-
messages: [...messages],
|
|
121
|
+
messages: [...state.messages],
|
|
76
122
|
...(toolSpecs === undefined ? {} : { tools: toolSpecs }),
|
|
77
|
-
maxTokens: input.maxTokens,
|
|
123
|
+
...(input.maxTokens === undefined ? {} : { maxTokens: input.maxTokens }),
|
|
78
124
|
...(input.temperature === undefined ? {} : { temperature: input.temperature }),
|
|
79
|
-
}, { signal }), timeoutMs, input.signal), {
|
|
80
|
-
|
|
125
|
+
}, { signal }), timeoutMs, input.signal), {
|
|
126
|
+
maxAttempts,
|
|
127
|
+
onRetry: (attempt, error) => progress.report(`Retrying after a provider error (attempt ${attempt}/${maxAttempts}): ${error instanceof Error ? error.message : String(error)}`),
|
|
128
|
+
});
|
|
129
|
+
const usage = addUsage(state.usage, response.usage);
|
|
81
130
|
input.budget?.recordCall(response.usage);
|
|
82
131
|
const assistantMessage = {
|
|
83
132
|
role: 'assistant',
|
|
84
133
|
...(response.content === null ? {} : { content: response.content }),
|
|
85
134
|
...(response.toolCalls.length === 0 ? {} : { toolCalls: response.toolCalls }),
|
|
86
135
|
};
|
|
87
|
-
messages.
|
|
88
|
-
|
|
89
|
-
|
|
136
|
+
const messages = [...state.messages, assistantMessage];
|
|
137
|
+
const finalText = response.content !== null ? response.content : state.finalText;
|
|
138
|
+
const stepIndex = state.stepIndex + 1;
|
|
90
139
|
if (response.toolCalls.length === 0) {
|
|
91
|
-
steps.push({ response: assistantMessage, usage: response.usage, toolOutcomes: [] });
|
|
92
140
|
const stopReason = response.stopReason === 'max_tokens' ? 'max_tokens' : 'end_turn';
|
|
93
|
-
return {
|
|
141
|
+
return {
|
|
142
|
+
messages,
|
|
143
|
+
finalText,
|
|
144
|
+
usage,
|
|
145
|
+
stepIndex,
|
|
146
|
+
stopReason,
|
|
147
|
+
steps: [
|
|
148
|
+
...state.steps,
|
|
149
|
+
{ response: assistantMessage, usage: response.usage, toolOutcomes: [] },
|
|
150
|
+
],
|
|
151
|
+
};
|
|
94
152
|
}
|
|
95
153
|
if (response.toolCalls.some((call) => repetitionGuard.wouldRepeat(call))) {
|
|
96
|
-
|
|
97
|
-
|
|
154
|
+
return {
|
|
155
|
+
messages,
|
|
156
|
+
finalText,
|
|
157
|
+
usage,
|
|
158
|
+
stepIndex,
|
|
159
|
+
stopReason: 'repetition_detected',
|
|
160
|
+
steps: [
|
|
161
|
+
...state.steps,
|
|
162
|
+
{ response: assistantMessage, usage: response.usage, toolOutcomes: [] },
|
|
163
|
+
],
|
|
164
|
+
};
|
|
98
165
|
}
|
|
99
166
|
for (const call of response.toolCalls)
|
|
100
167
|
repetitionGuard.record(call);
|
|
168
|
+
return {
|
|
169
|
+
messages,
|
|
170
|
+
finalText,
|
|
171
|
+
usage,
|
|
172
|
+
stepIndex,
|
|
173
|
+
pendingAssistant: assistantMessage,
|
|
174
|
+
pendingToolCalls: response.toolCalls,
|
|
175
|
+
pendingUsage: response.usage,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
async function toolsNode(state) {
|
|
101
179
|
const toolOutcomes = [];
|
|
102
|
-
|
|
180
|
+
let messages = state.messages;
|
|
181
|
+
for (const call of state.pendingToolCalls) {
|
|
182
|
+
progress.report(`Calling tool "${call.name}"…`);
|
|
103
183
|
const outcome = await runTool(toolIndex.get(call.name), call, input.signal ?? new AbortController().signal);
|
|
184
|
+
progress.report(outcome.ok
|
|
185
|
+
? `Tool "${call.name}" finished.`
|
|
186
|
+
: `Tool "${call.name}" failed: ${outcome.error ?? 'unknown error'}`);
|
|
104
187
|
toolOutcomes.push(outcome);
|
|
105
|
-
messages
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
188
|
+
messages = [
|
|
189
|
+
...messages,
|
|
190
|
+
{
|
|
191
|
+
role: 'tool',
|
|
192
|
+
toolCallId: call.id,
|
|
193
|
+
toolName: call.name,
|
|
194
|
+
content: outcome.ok
|
|
195
|
+
? (outcome.output ?? '')
|
|
196
|
+
: `Error: ${outcome.error ?? 'unknown error'}`,
|
|
197
|
+
},
|
|
198
|
+
];
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
messages,
|
|
202
|
+
steps: [
|
|
203
|
+
...state.steps,
|
|
204
|
+
{
|
|
205
|
+
// Set on every path that reaches `tools` (see `agentNode` above) —
|
|
206
|
+
// non-null by construction, not by luck.
|
|
207
|
+
response: state.pendingAssistant,
|
|
208
|
+
usage: state.pendingUsage,
|
|
209
|
+
toolOutcomes,
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
pendingAssistant: null,
|
|
213
|
+
pendingToolCalls: [],
|
|
214
|
+
pendingUsage: null,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function routeAfterAgent(state) {
|
|
218
|
+
return state.stopReason !== null ? END : 'tools';
|
|
219
|
+
}
|
|
220
|
+
const graph = new StateGraph(AgentGraphState)
|
|
221
|
+
.addNode('agent', agentNode)
|
|
222
|
+
.addNode('tools', toolsNode)
|
|
223
|
+
.addEdge(START, 'agent')
|
|
224
|
+
.addConditionalEdges('agent', routeAfterAgent, { tools: 'tools', [END]: END })
|
|
225
|
+
.addEdge('tools', 'agent');
|
|
226
|
+
return { graph: graph.compile(), maxSteps };
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* L4 task 2, migrated to LangGraph.js (L24 task 1): one model call, tool
|
|
230
|
+
* dispatch, repeat — with the same three guards as before (a step ceiling,
|
|
231
|
+
* repetition detection, per-call cost measured from the first line), now run
|
|
232
|
+
* as a two-node `StateGraph` (`buildAgentGraph` above) instead of a `for`
|
|
233
|
+
* loop. The public contract — `RunAgentLoopInput` in, `RunResult` out — is
|
|
234
|
+
* unchanged, so every existing caller (`agents/orchestrator.ts`,
|
|
235
|
+
* `subagents/run-subagent.ts`, `tools/core/agent-delegate.ts`,
|
|
236
|
+
* `assist/runtime.ts`, `eval/run-suite.ts`) needed no change at all.
|
|
237
|
+
* Permission checking (task 4, now `withAutonomy`) and budgets (task 8)
|
|
238
|
+
* still wrap this from the outside; this module still only knows how to
|
|
239
|
+
* hold a conversation with a model and the tools it was handed.
|
|
240
|
+
*/
|
|
241
|
+
export async function runAgentLoop(input) {
|
|
242
|
+
const { graph, maxSteps } = buildAgentGraph(input);
|
|
243
|
+
const initialState = {
|
|
244
|
+
messages: [...input.messages],
|
|
245
|
+
steps: [],
|
|
246
|
+
usage: ZERO_USAGE,
|
|
247
|
+
finalText: null,
|
|
248
|
+
stopReason: null,
|
|
249
|
+
stepIndex: 0,
|
|
250
|
+
pendingAssistant: null,
|
|
251
|
+
pendingToolCalls: [],
|
|
252
|
+
pendingUsage: null,
|
|
253
|
+
};
|
|
254
|
+
let finalState;
|
|
255
|
+
try {
|
|
256
|
+
// Generous relative to `maxSteps`: each loop iteration is at most two
|
|
257
|
+
// graph super-steps (`agent`, then `tools`), and `agentNode`'s own
|
|
258
|
+
// `stepIndex >= maxSteps` check always produces a `max_steps` stop
|
|
259
|
+
// before this ceiling could ever bind. It exists as a backstop against a
|
|
260
|
+
// future bug in that check, not as the mechanism `max_steps` relies on.
|
|
261
|
+
finalState = await graph.invoke(initialState, { recursionLimit: maxSteps * 2 + 10 });
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
if (error instanceof GraphRecursionError) {
|
|
265
|
+
throw new CogentaError({
|
|
266
|
+
code: 'AGENT_LOOP_RECURSION_LIMIT',
|
|
267
|
+
message: 'The graph recursion ceiling was hit before its own max_steps check fired.',
|
|
268
|
+
hint: 'This indicates a bug in the agent graph, not a normal stop reason — please report it.',
|
|
110
269
|
});
|
|
111
270
|
}
|
|
112
|
-
|
|
271
|
+
throw error;
|
|
113
272
|
}
|
|
114
|
-
return {
|
|
273
|
+
return {
|
|
274
|
+
messages: finalState.messages,
|
|
275
|
+
steps: finalState.steps,
|
|
276
|
+
finalText: finalState.finalText,
|
|
277
|
+
stopReason: finalState.stopReason ?? 'max_steps',
|
|
278
|
+
usage: finalState.usage,
|
|
279
|
+
};
|
|
115
280
|
}
|
|
116
281
|
//# sourceMappingURL=loop.js.map
|