@cogenta/agents 0.1.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/define.d.ts +9 -0
- package/dist/agents/define.d.ts.map +1 -0
- package/dist/agents/define.js +25 -0
- package/dist/agents/define.js.map +1 -0
- package/dist/agents/registry.d.ts +29 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/registry.js +50 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/agents/types.d.ts +36 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +2 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/audit/types.d.ts +23 -0
- package/dist/audit/types.d.ts.map +1 -0
- package/dist/audit/types.js +2 -0
- package/dist/audit/types.js.map +1 -0
- package/dist/audit/with-audit.d.ts +34 -0
- package/dist/audit/with-audit.d.ts.map +1 -0
- package/dist/audit/with-audit.js +65 -0
- package/dist/audit/with-audit.js.map +1 -0
- package/dist/autonomy/approval-queue.d.ts +13 -0
- package/dist/autonomy/approval-queue.d.ts.map +1 -0
- package/dist/autonomy/approval-queue.js +56 -0
- package/dist/autonomy/approval-queue.js.map +1 -0
- package/dist/autonomy/types.d.ts +36 -0
- package/dist/autonomy/types.d.ts.map +1 -0
- package/dist/autonomy/types.js +2 -0
- package/dist/autonomy/types.js.map +1 -0
- package/dist/autonomy/with-autonomy.d.ts +25 -0
- package/dist/autonomy/with-autonomy.d.ts.map +1 -0
- package/dist/autonomy/with-autonomy.js +77 -0
- package/dist/autonomy/with-autonomy.js.map +1 -0
- package/dist/budget/kill-switch.d.ts +14 -0
- package/dist/budget/kill-switch.d.ts.map +1 -0
- package/dist/budget/kill-switch.js +20 -0
- package/dist/budget/kill-switch.js.map +1 -0
- package/dist/budget/tracker.d.ts +15 -0
- package/dist/budget/tracker.d.ts.map +1 -0
- package/dist/budget/tracker.js +68 -0
- package/dist/budget/tracker.js.map +1 -0
- package/dist/budget/types.d.ts +35 -0
- package/dist/budget/types.d.ts.map +1 -0
- package/dist/budget/types.js +2 -0
- package/dist/budget/types.js.map +1 -0
- package/dist/eval/assert-threshold.d.ts +15 -0
- package/dist/eval/assert-threshold.d.ts.map +1 -0
- package/dist/eval/assert-threshold.js +27 -0
- package/dist/eval/assert-threshold.js.map +1 -0
- package/dist/eval/compare-prompt-versions.d.ts +17 -0
- package/dist/eval/compare-prompt-versions.d.ts.map +1 -0
- package/dist/eval/compare-prompt-versions.js +20 -0
- package/dist/eval/compare-prompt-versions.js.map +1 -0
- package/dist/eval/run-suite.d.ts +4 -0
- package/dist/eval/run-suite.d.ts.map +1 -0
- package/dist/eval/run-suite.js +18 -0
- package/dist/eval/run-suite.js.map +1 -0
- package/dist/eval/scorers.d.ts +13 -0
- package/dist/eval/scorers.d.ts.map +1 -0
- package/dist/eval/scorers.js +33 -0
- package/dist/eval/scorers.js.map +1 -0
- package/dist/eval/types.d.ts +27 -0
- package/dist/eval/types.d.ts.map +1 -0
- package/dist/eval/types.js +2 -0
- package/dist/eval/types.js.map +1 -0
- package/dist/identity/constitution.d.ts +17 -0
- package/dist/identity/constitution.d.ts.map +1 -0
- package/dist/identity/constitution.js +33 -0
- package/dist/identity/constitution.js.map +1 -0
- package/dist/identity/context.d.ts +49 -0
- package/dist/identity/context.d.ts.map +1 -0
- package/dist/identity/context.js +67 -0
- package/dist/identity/context.js.map +1 -0
- package/dist/index.d.ts +99 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/file-store.d.ts +6 -0
- package/dist/memory/file-store.d.ts.map +1 -0
- package/dist/memory/file-store.js +94 -0
- package/dist/memory/file-store.js.map +1 -0
- package/dist/memory/from-approval.d.ts +20 -0
- package/dist/memory/from-approval.d.ts.map +1 -0
- package/dist/memory/from-approval.js +38 -0
- package/dist/memory/from-approval.js.map +1 -0
- package/dist/memory/memory-store.d.ts +4 -0
- package/dist/memory/memory-store.d.ts.map +1 -0
- package/dist/memory/memory-store.js +55 -0
- package/dist/memory/memory-store.js.map +1 -0
- package/dist/memory/types.d.ts +67 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +2 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/privacy/assert-provider-allowed.d.ts +10 -0
- package/dist/privacy/assert-provider-allowed.d.ts.map +1 -0
- package/dist/privacy/assert-provider-allowed.js +20 -0
- package/dist/privacy/assert-provider-allowed.js.map +1 -0
- package/dist/privacy/redact-fields.d.ts +11 -0
- package/dist/privacy/redact-fields.d.ts.map +1 -0
- package/dist/privacy/redact-fields.js +26 -0
- package/dist/privacy/redact-fields.js.map +1 -0
- package/dist/privacy/redact-text.d.ts +4 -0
- package/dist/privacy/redact-text.d.ts.map +1 -0
- package/dist/privacy/redact-text.js +26 -0
- package/dist/privacy/redact-text.js.map +1 -0
- package/dist/privacy/types.d.ts +23 -0
- package/dist/privacy/types.d.ts.map +1 -0
- package/dist/privacy/types.js +2 -0
- package/dist/privacy/types.js.map +1 -0
- package/dist/providers/anthropic.d.ts +57 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +130 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/google.d.ts +63 -0
- package/dist/providers/google.d.ts.map +1 -0
- package/dist/providers/google.js +144 -0
- package/dist/providers/google.js.map +1 -0
- package/dist/providers/openai.d.ts +56 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +143 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/registry.d.ts +31 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +35 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/providers/types.d.ts +63 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +10 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/rag/chunking/chunk-document.d.ts +13 -0
- package/dist/rag/chunking/chunk-document.d.ts.map +1 -0
- package/dist/rag/chunking/chunk-document.js +51 -0
- package/dist/rag/chunking/chunk-document.js.map +1 -0
- package/dist/rag/chunking/incremental.d.ts +19 -0
- package/dist/rag/chunking/incremental.d.ts.map +1 -0
- package/dist/rag/chunking/incremental.js +24 -0
- package/dist/rag/chunking/incremental.js.map +1 -0
- package/dist/rag/chunking/types.d.ts +34 -0
- package/dist/rag/chunking/types.d.ts.map +1 -0
- package/dist/rag/chunking/types.js +2 -0
- package/dist/rag/chunking/types.js.map +1 -0
- package/dist/rag/embeddings/hashing-provider.d.ts +22 -0
- package/dist/rag/embeddings/hashing-provider.d.ts.map +1 -0
- package/dist/rag/embeddings/hashing-provider.js +53 -0
- package/dist/rag/embeddings/hashing-provider.js.map +1 -0
- package/dist/rag/embeddings/types.d.ts +16 -0
- package/dist/rag/embeddings/types.d.ts.map +1 -0
- package/dist/rag/embeddings/types.js +2 -0
- package/dist/rag/embeddings/types.js.map +1 -0
- package/dist/rag/index/bm25.d.ts +4 -0
- package/dist/rag/index/bm25.d.ts.map +1 -0
- package/dist/rag/index/bm25.js +38 -0
- package/dist/rag/index/bm25.js.map +1 -0
- package/dist/rag/index/memory-index.d.ts +12 -0
- package/dist/rag/index/memory-index.d.ts.map +1 -0
- package/dist/rag/index/memory-index.js +44 -0
- package/dist/rag/index/memory-index.js.map +1 -0
- package/dist/rag/index/rrf.d.ts +9 -0
- package/dist/rag/index/rrf.d.ts.map +1 -0
- package/dist/rag/index/rrf.js +20 -0
- package/dist/rag/index/rrf.js.map +1 -0
- package/dist/rag/index/types.d.ts +48 -0
- package/dist/rag/index/types.d.ts.map +1 -0
- package/dist/rag/index/types.js +2 -0
- package/dist/rag/index/types.js.map +1 -0
- package/dist/rag/index/vector-rank.d.ts +4 -0
- package/dist/rag/index/vector-rank.d.ts.map +1 -0
- package/dist/rag/index/vector-rank.js +27 -0
- package/dist/rag/index/vector-rank.js.map +1 -0
- package/dist/reversibility/diff.d.ts +17 -0
- package/dist/reversibility/diff.d.ts.map +1 -0
- package/dist/reversibility/diff.js +39 -0
- package/dist/reversibility/diff.js.map +1 -0
- package/dist/reversibility/receipt-store.d.ts +9 -0
- package/dist/reversibility/receipt-store.d.ts.map +1 -0
- package/dist/reversibility/receipt-store.js +34 -0
- package/dist/reversibility/receipt-store.js.map +1 -0
- package/dist/reversibility/revert.d.ts +18 -0
- package/dist/reversibility/revert.d.ts.map +1 -0
- package/dist/reversibility/revert.js +38 -0
- package/dist/reversibility/revert.js.map +1 -0
- package/dist/reversibility/types.d.ts +25 -0
- package/dist/reversibility/types.d.ts.map +1 -0
- package/dist/reversibility/types.js +2 -0
- package/dist/reversibility/types.js.map +1 -0
- package/dist/reversibility/with-receipts.d.ts +19 -0
- package/dist/reversibility/with-receipts.d.ts.map +1 -0
- package/dist/reversibility/with-receipts.js +35 -0
- package/dist/reversibility/with-receipts.js.map +1 -0
- package/dist/runtime/loop.d.ts +11 -0
- package/dist/runtime/loop.d.ts.map +1 -0
- package/dist/runtime/loop.js +116 -0
- package/dist/runtime/loop.js.map +1 -0
- package/dist/runtime/repetition.d.ts +16 -0
- package/dist/runtime/repetition.d.ts.map +1 -0
- package/dist/runtime/repetition.js +38 -0
- package/dist/runtime/repetition.js.map +1 -0
- package/dist/runtime/retry.d.ts +22 -0
- package/dist/runtime/retry.d.ts.map +1 -0
- package/dist/runtime/retry.js +69 -0
- package/dist/runtime/retry.js.map +1 -0
- package/dist/runtime/types.d.ts +78 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +2 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/sandbox/types.d.ts +20 -0
- package/dist/sandbox/types.d.ts.map +1 -0
- package/dist/sandbox/types.js +2 -0
- package/dist/sandbox/types.js.map +1 -0
- package/dist/sandbox/with-sandbox.d.ts +26 -0
- package/dist/sandbox/with-sandbox.d.ts.map +1 -0
- package/dist/sandbox/with-sandbox.js +41 -0
- package/dist/sandbox/with-sandbox.js.map +1 -0
- package/dist/skills/file-store.d.ts +13 -0
- package/dist/skills/file-store.d.ts.map +1 -0
- package/dist/skills/file-store.js +73 -0
- package/dist/skills/file-store.js.map +1 -0
- package/dist/skills/frontmatter.d.ts +11 -0
- package/dist/skills/frontmatter.d.ts.map +1 -0
- package/dist/skills/frontmatter.js +46 -0
- package/dist/skills/frontmatter.js.map +1 -0
- package/dist/skills/types.d.ts +19 -0
- package/dist/skills/types.d.ts.map +1 -0
- package/dist/skills/types.js +2 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/skin/generate.d.ts +22 -0
- package/dist/skin/generate.d.ts.map +1 -0
- package/dist/skin/generate.js +144 -0
- package/dist/skin/generate.js.map +1 -0
- package/dist/subagents/run-subagent.d.ts +10 -0
- package/dist/subagents/run-subagent.d.ts.map +1 -0
- package/dist/subagents/run-subagent.js +24 -0
- package/dist/subagents/run-subagent.js.map +1 -0
- package/dist/subagents/types.d.ts +13 -0
- package/dist/subagents/types.d.ts.map +1 -0
- package/dist/subagents/types.js +2 -0
- package/dist/subagents/types.js.map +1 -0
- package/dist/subagents/validate.d.ts +8 -0
- package/dist/subagents/validate.d.ts.map +1 -0
- package/dist/subagents/validate.js +32 -0
- package/dist/subagents/validate.js.map +1 -0
- package/dist/tools/core/agent-delegate.d.ts +34 -0
- package/dist/tools/core/agent-delegate.d.ts.map +1 -0
- package/dist/tools/core/agent-delegate.js +41 -0
- package/dist/tools/core/agent-delegate.js.map +1 -0
- package/dist/tools/core/content.d.ts +81 -0
- package/dist/tools/core/content.d.ts.map +1 -0
- package/dist/tools/core/content.js +121 -0
- package/dist/tools/core/content.js.map +1 -0
- package/dist/tools/core/http-fetch.d.ts +33 -0
- package/dist/tools/core/http-fetch.d.ts.map +1 -0
- package/dist/tools/core/http-fetch.js +63 -0
- package/dist/tools/core/http-fetch.js.map +1 -0
- package/dist/tools/core/media.d.ts +38 -0
- package/dist/tools/core/media.d.ts.map +1 -0
- package/dist/tools/core/media.js +93 -0
- package/dist/tools/core/media.js.map +1 -0
- package/dist/tools/core/site-config.d.ts +19 -0
- package/dist/tools/core/site-config.d.ts.map +1 -0
- package/dist/tools/core/site-config.js +37 -0
- package/dist/tools/core/site-config.js.map +1 -0
- package/dist/tools/define.d.ts +12 -0
- package/dist/tools/define.d.ts.map +1 -0
- package/dist/tools/define.js +28 -0
- package/dist/tools/define.js.map +1 -0
- package/dist/tools/manifest.d.ts +19 -0
- package/dist/tools/manifest.d.ts.map +1 -0
- package/dist/tools/manifest.js +70 -0
- package/dist/tools/manifest.js.map +1 -0
- package/dist/tools/registry.d.ts +8 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +20 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +51 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/trace/capture.d.ts +19 -0
- package/dist/trace/capture.d.ts.map +1 -0
- package/dist/trace/capture.js +31 -0
- package/dist/trace/capture.js.map +1 -0
- package/dist/trace/file-store.d.ts +12 -0
- package/dist/trace/file-store.d.ts.map +1 -0
- package/dist/trace/file-store.js +78 -0
- package/dist/trace/file-store.js.map +1 -0
- package/dist/trace/memory-store.d.ts +9 -0
- package/dist/trace/memory-store.d.ts.map +1 -0
- package/dist/trace/memory-store.js +36 -0
- package/dist/trace/memory-store.js.map +1 -0
- package/dist/trace/types.d.ts +37 -0
- package/dist/trace/types.d.ts.map +1 -0
- package/dist/trace/types.js +2 -0
- package/dist/trace/types.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { assertProviderAllowed } from '../privacy/assert-provider-allowed.js';
|
|
2
|
+
import { RepetitionGuard } from './repetition.js';
|
|
3
|
+
import { retryModelCall, withTimeout } from './retry.js';
|
|
4
|
+
const DEFAULT_MAX_STEPS = 25;
|
|
5
|
+
const DEFAULT_MAX_ATTEMPTS = 3;
|
|
6
|
+
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
7
|
+
const DEFAULT_MAX_REPEATS = 2;
|
|
8
|
+
function addUsage(a, b) {
|
|
9
|
+
return {
|
|
10
|
+
inputTokens: a.inputTokens + b.inputTokens,
|
|
11
|
+
outputTokens: a.outputTokens + b.outputTokens,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function toolByName(tools) {
|
|
15
|
+
return new Map(tools.map((tool) => [tool.spec.name, tool]));
|
|
16
|
+
}
|
|
17
|
+
async function runTool(tool, call, signal) {
|
|
18
|
+
if (tool === undefined) {
|
|
19
|
+
return { call, ok: false, error: `No tool named "${call.name}" is available in this run.` };
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const result = await tool.execute(call.input, { signal });
|
|
23
|
+
return { call, ok: true, output: result === undefined ? '' : JSON.stringify(result) };
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
return { call, ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* L4 task 2: one model call, tool dispatch, repeat — with the three guards
|
|
31
|
+
* the lot's own "pièges connus" call out by name: a step ceiling, repetition
|
|
32
|
+
* detection, and per-call cost (usage) measured from the first line rather
|
|
33
|
+
* than discovered later. Permission checking (task 4) and budgets (task 8)
|
|
34
|
+
* wrap this from the outside; this loop only knows how to hold a
|
|
35
|
+
* conversation with a model and the tools it was handed.
|
|
36
|
+
*/
|
|
37
|
+
export async function runAgentLoop(input) {
|
|
38
|
+
const maxSteps = input.maxSteps ?? DEFAULT_MAX_STEPS;
|
|
39
|
+
const maxAttempts = input.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
|
|
40
|
+
const timeoutMs = input.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
41
|
+
const now = input.now ?? Date.now;
|
|
42
|
+
const tools = input.tools ?? [];
|
|
43
|
+
const toolIndex = toolByName(tools);
|
|
44
|
+
const toolSpecs = tools.length === 0 ? undefined : tools.map((tool) => tool.spec);
|
|
45
|
+
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
|
+
const runStartedAt = now();
|
|
51
|
+
for (let step = 0; step < maxSteps; step++) {
|
|
52
|
+
if (input.privacyPolicy !== undefined) {
|
|
53
|
+
assertProviderAllowed(input.client, input.privacyPolicy);
|
|
54
|
+
}
|
|
55
|
+
if (input.signal?.aborted === true) {
|
|
56
|
+
return { messages, steps, finalText, stopReason: 'cancelled', usage: totalUsage };
|
|
57
|
+
}
|
|
58
|
+
if (input.killSwitch?.isActive() === true) {
|
|
59
|
+
return { messages, steps, finalText, stopReason: 'killed', usage: totalUsage };
|
|
60
|
+
}
|
|
61
|
+
if (input.maxRunDurationMs !== undefined && now() - runStartedAt >= input.maxRunDurationMs) {
|
|
62
|
+
return { messages, steps, finalText, stopReason: 'max_duration', usage: totalUsage };
|
|
63
|
+
}
|
|
64
|
+
if (input.budget !== undefined) {
|
|
65
|
+
const check = input.budget.checkCall();
|
|
66
|
+
if (!check.allowed) {
|
|
67
|
+
if (check.reason !== undefined)
|
|
68
|
+
input.onBudgetExceeded?.(check.reason);
|
|
69
|
+
return { messages, steps, finalText, stopReason: 'budget_exceeded', usage: totalUsage };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const response = await retryModelCall(() => withTimeout((signal) => input.client.chat({
|
|
73
|
+
model: input.client.model,
|
|
74
|
+
...(input.system === undefined ? {} : { system: input.system }),
|
|
75
|
+
messages: [...messages],
|
|
76
|
+
...(toolSpecs === undefined ? {} : { tools: toolSpecs }),
|
|
77
|
+
maxTokens: input.maxTokens,
|
|
78
|
+
...(input.temperature === undefined ? {} : { temperature: input.temperature }),
|
|
79
|
+
}, { signal }), timeoutMs, input.signal), { maxAttempts });
|
|
80
|
+
totalUsage = addUsage(totalUsage, response.usage);
|
|
81
|
+
input.budget?.recordCall(response.usage);
|
|
82
|
+
const assistantMessage = {
|
|
83
|
+
role: 'assistant',
|
|
84
|
+
...(response.content === null ? {} : { content: response.content }),
|
|
85
|
+
...(response.toolCalls.length === 0 ? {} : { toolCalls: response.toolCalls }),
|
|
86
|
+
};
|
|
87
|
+
messages.push(assistantMessage);
|
|
88
|
+
if (response.content !== null)
|
|
89
|
+
finalText = response.content;
|
|
90
|
+
if (response.toolCalls.length === 0) {
|
|
91
|
+
steps.push({ response: assistantMessage, usage: response.usage, toolOutcomes: [] });
|
|
92
|
+
const stopReason = response.stopReason === 'max_tokens' ? 'max_tokens' : 'end_turn';
|
|
93
|
+
return { messages, steps, finalText, stopReason, usage: totalUsage };
|
|
94
|
+
}
|
|
95
|
+
if (response.toolCalls.some((call) => repetitionGuard.wouldRepeat(call))) {
|
|
96
|
+
steps.push({ response: assistantMessage, usage: response.usage, toolOutcomes: [] });
|
|
97
|
+
return { messages, steps, finalText, stopReason: 'repetition_detected', usage: totalUsage };
|
|
98
|
+
}
|
|
99
|
+
for (const call of response.toolCalls)
|
|
100
|
+
repetitionGuard.record(call);
|
|
101
|
+
const toolOutcomes = [];
|
|
102
|
+
for (const call of response.toolCalls) {
|
|
103
|
+
const outcome = await runTool(toolIndex.get(call.name), call, input.signal ?? new AbortController().signal);
|
|
104
|
+
toolOutcomes.push(outcome);
|
|
105
|
+
messages.push({
|
|
106
|
+
role: 'tool',
|
|
107
|
+
toolCallId: call.id,
|
|
108
|
+
toolName: call.name,
|
|
109
|
+
content: outcome.ok ? (outcome.output ?? '') : `Error: ${outcome.error ?? 'unknown error'}`,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
steps.push({ response: assistantMessage, usage: response.usage, toolOutcomes });
|
|
113
|
+
}
|
|
114
|
+
return { messages, steps, finalText, stopReason: 'max_steps', usage: totalUsage };
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=loop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/runtime/loop.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ProviderToolCall } from '../providers/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Guards against the "infinite loop" failure mode L4's own pitfalls call out:
|
|
4
|
+
* an agent that calls the same tool with the same input over and over,
|
|
5
|
+
* getting nowhere. Keys on name + a stable stringify of the input (sorted
|
|
6
|
+
* keys, so `{a:1,b:2}` and `{b:2,a:1}` count as the same call).
|
|
7
|
+
*/
|
|
8
|
+
export declare class RepetitionGuard {
|
|
9
|
+
private readonly seen;
|
|
10
|
+
private readonly maxRepeats;
|
|
11
|
+
constructor(maxRepeats?: number);
|
|
12
|
+
/** True once `call` has already been made `maxRepeats` times before this one. */
|
|
13
|
+
wouldRepeat(call: ProviderToolCall): boolean;
|
|
14
|
+
record(call: ProviderToolCall): void;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=repetition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repetition.d.ts","sourceRoot":"","sources":["../../src/runtime/repetition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAE7D;;;;;GAKG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4B;IACjD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;IAEnC,YAAY,UAAU,SAAI,EAEzB;IAED,iFAAiF;IACjF,WAAW,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAE3C;IAED,MAAM,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAGnC;CACF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guards against the "infinite loop" failure mode L4's own pitfalls call out:
|
|
3
|
+
* an agent that calls the same tool with the same input over and over,
|
|
4
|
+
* getting nowhere. Keys on name + a stable stringify of the input (sorted
|
|
5
|
+
* keys, so `{a:1,b:2}` and `{b:2,a:1}` count as the same call).
|
|
6
|
+
*/
|
|
7
|
+
export class RepetitionGuard {
|
|
8
|
+
seen = new Map();
|
|
9
|
+
maxRepeats;
|
|
10
|
+
constructor(maxRepeats = 2) {
|
|
11
|
+
this.maxRepeats = maxRepeats;
|
|
12
|
+
}
|
|
13
|
+
/** True once `call` has already been made `maxRepeats` times before this one. */
|
|
14
|
+
wouldRepeat(call) {
|
|
15
|
+
return (this.seen.get(signatureOf(call)) ?? 0) >= this.maxRepeats;
|
|
16
|
+
}
|
|
17
|
+
record(call) {
|
|
18
|
+
const key = signatureOf(call);
|
|
19
|
+
this.seen.set(key, (this.seen.get(key) ?? 0) + 1);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function signatureOf(call) {
|
|
23
|
+
return `${call.name}:${stableStringify(call.input)}`;
|
|
24
|
+
}
|
|
25
|
+
function stableStringify(value) {
|
|
26
|
+
return JSON.stringify(sortKeysDeep(value));
|
|
27
|
+
}
|
|
28
|
+
function sortKeysDeep(value) {
|
|
29
|
+
if (Array.isArray(value))
|
|
30
|
+
return value.map(sortKeysDeep);
|
|
31
|
+
if (value !== null && typeof value === 'object') {
|
|
32
|
+
return Object.fromEntries(Object.entries(value)
|
|
33
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
34
|
+
.map(([key, entryValue]) => [key, sortKeysDeep(entryValue)]));
|
|
35
|
+
}
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=repetition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repetition.js","sourceRoot":"","sources":["../../src/runtime/repetition.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,OAAO,eAAe;IACT,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAA;IAChC,UAAU,CAAQ;IAEnC,YAAY,UAAU,GAAG,CAAC;QACxB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;IAED,iFAAiF;IACjF,WAAW,CAAC,IAAsB;QAChC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,UAAU,CAAA;IACnE,CAAC;IAED,MAAM,CAAC,IAAsB;QAC3B,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,CAAA;QAC7B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACnD,CAAC;CACF;AAED,SAAS,WAAW,CAAC,IAAsB;IACzC,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAA;AACtD,CAAC;AAED,SAAS,eAAe,CAAC,KAAwC;IAC/D,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAA;AAC5C,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;IACxD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC;aAC7C,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;aACtC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAC/D,CAAA;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface RetryOptions {
|
|
2
|
+
readonly maxAttempts: number;
|
|
3
|
+
/** Exponential backoff, 250ms base — injectable so tests never actually sleep. */
|
|
4
|
+
readonly delayMs?: (attempt: number) => number;
|
|
5
|
+
readonly sleep?: (ms: number) => Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Retries only what a retry can plausibly fix: a dropped connection, a rate
|
|
9
|
+
* limit, a timeout. `PROVIDER_RESPONSE_INVALID` (a malformed vendor payload)
|
|
10
|
+
* and everything else is not retried — a second identical request against
|
|
11
|
+
* the same malformed state just wastes a call and a budget unit.
|
|
12
|
+
*/
|
|
13
|
+
export declare function retryModelCall<T>(fn: () => Promise<T>, options: RetryOptions): Promise<T>;
|
|
14
|
+
/**
|
|
15
|
+
* Races a model call against a timeout, distinguishing three outcomes: the
|
|
16
|
+
* call resolved, it was cancelled by `parentSignal` (the run's own
|
|
17
|
+
* cancellation, handled by the loop, not thrown as a timeout), or it timed
|
|
18
|
+
* out (thrown as `PROVIDER_TIMEOUT`, which `retryModelCall` treats as
|
|
19
|
+
* retryable).
|
|
20
|
+
*/
|
|
21
|
+
export declare function withTimeout<T>(fn: (signal: AbortSignal) => Promise<T>, timeoutMs: number, parentSignal?: AbortSignal): Promise<T>;
|
|
22
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/runtime/retry.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,kFAAkF;IAClF,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAA;IAC9C,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/C;AAMD;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,CAAC,CAAC,CAkB/F;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,CAAC,EACjC,EAAE,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EACvC,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,WAAW,GACzB,OAAO,CAAC,CAAC,CAAC,CAyBZ"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
2
|
+
const RETRYABLE_CODES = new Set([
|
|
3
|
+
'PROVIDER_REQUEST_FAILED',
|
|
4
|
+
'PROVIDER_RATE_LIMITED',
|
|
5
|
+
'PROVIDER_TIMEOUT',
|
|
6
|
+
]);
|
|
7
|
+
const DEFAULT_DELAY = (attempt) => 250 * 2 ** attempt;
|
|
8
|
+
const DEFAULT_SLEEP = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
9
|
+
/**
|
|
10
|
+
* Retries only what a retry can plausibly fix: a dropped connection, a rate
|
|
11
|
+
* limit, a timeout. `PROVIDER_RESPONSE_INVALID` (a malformed vendor payload)
|
|
12
|
+
* and everything else is not retried — a second identical request against
|
|
13
|
+
* the same malformed state just wastes a call and a budget unit.
|
|
14
|
+
*/
|
|
15
|
+
export async function retryModelCall(fn, options) {
|
|
16
|
+
const delayMs = options.delayMs ?? DEFAULT_DELAY;
|
|
17
|
+
const sleep = options.sleep ?? DEFAULT_SLEEP;
|
|
18
|
+
let lastError;
|
|
19
|
+
for (let attempt = 0; attempt < options.maxAttempts; attempt++) {
|
|
20
|
+
try {
|
|
21
|
+
return await fn();
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
lastError = error;
|
|
25
|
+
const retryable = error instanceof CogentaError && RETRYABLE_CODES.has(error.code);
|
|
26
|
+
if (!retryable || attempt === options.maxAttempts - 1)
|
|
27
|
+
throw error;
|
|
28
|
+
await sleep(delayMs(attempt));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Unreachable when maxAttempts >= 1 (the loop above always returns or throws),
|
|
32
|
+
// kept only so the function has a total return type.
|
|
33
|
+
throw lastError;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Races a model call against a timeout, distinguishing three outcomes: the
|
|
37
|
+
* call resolved, it was cancelled by `parentSignal` (the run's own
|
|
38
|
+
* cancellation, handled by the loop, not thrown as a timeout), or it timed
|
|
39
|
+
* out (thrown as `PROVIDER_TIMEOUT`, which `retryModelCall` treats as
|
|
40
|
+
* retryable).
|
|
41
|
+
*/
|
|
42
|
+
export async function withTimeout(fn, timeoutMs, parentSignal) {
|
|
43
|
+
const controller = new AbortController();
|
|
44
|
+
let timedOut = false;
|
|
45
|
+
const onParentAbort = () => controller.abort();
|
|
46
|
+
parentSignal?.addEventListener('abort', onParentAbort);
|
|
47
|
+
const timer = setTimeout(() => {
|
|
48
|
+
timedOut = true;
|
|
49
|
+
controller.abort();
|
|
50
|
+
}, timeoutMs);
|
|
51
|
+
try {
|
|
52
|
+
return await fn(controller.signal);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (timedOut) {
|
|
56
|
+
throw new CogentaError({
|
|
57
|
+
code: 'PROVIDER_TIMEOUT',
|
|
58
|
+
message: `The model call did not respond within ${timeoutMs}ms.`,
|
|
59
|
+
hint: 'Increase timeoutMs for this agent, or check the provider status page.',
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
clearTimeout(timer);
|
|
66
|
+
parentSignal?.removeEventListener('abort', onParentAbort);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/runtime/retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAE5C,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,yBAAyB;IACzB,uBAAuB;IACvB,kBAAkB;CACnB,CAAC,CAAA;AASF,MAAM,aAAa,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,GAAG,GAAG,CAAC,IAAI,OAAO,CAAA;AACrE,MAAM,aAAa,GAAG,CAAC,EAAU,EAAiB,EAAE,CAClD,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;AAEnD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAI,EAAoB,EAAE,OAAqB;IACjF,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,aAAa,CAAA;IAChD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa,CAAA;IAC5C,IAAI,SAAkB,CAAA;IAEtB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QAC/D,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAA;QACnB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAK,CAAA;YACjB,MAAM,SAAS,GAAG,KAAK,YAAY,YAAY,IAAI,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YAClF,IAAI,CAAC,SAAS,IAAI,OAAO,KAAK,OAAO,CAAC,WAAW,GAAG,CAAC;gBAAE,MAAM,KAAK,CAAA;YAClE,MAAM,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;QAC/B,CAAC;IACH,CAAC;IACD,+EAA+E;IAC/E,qDAAqD;IACrD,MAAM,SAAS,CAAA;AACjB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,EAAuC,EACvC,SAAiB,EACjB,YAA0B;IAE1B,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;IACxC,IAAI,QAAQ,GAAG,KAAK,CAAA;IACpB,MAAM,aAAa,GAAG,GAAS,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAA;IACpD,YAAY,EAAE,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAA;IACtD,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;QAC5B,QAAQ,GAAG,IAAI,CAAA;QACf,UAAU,CAAC,KAAK,EAAE,CAAA;IACpB,CAAC,EAAE,SAAS,CAAC,CAAA;IAEb,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,IAAI,YAAY,CAAC;gBACrB,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,yCAAyC,SAAS,KAAK;gBAChE,IAAI,EAAE,uEAAuE;aAC9E,CAAC,CAAA;QACJ,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAA;QACnB,YAAY,EAAE,mBAAmB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { BudgetExceededReason, BudgetTracker, KillSwitch } from '../budget/types.js';
|
|
2
|
+
import type { NoDataLeavesPolicy } from '../privacy/types.js';
|
|
3
|
+
import type { ChatMessage, ProviderClient, ProviderToolCall, ProviderToolSpec, TokenUsage } from '../providers/types.js';
|
|
4
|
+
export interface ToolExecutionContext {
|
|
5
|
+
/** The run's cancellation signal — a tool that makes its own HTTP calls should thread this through. */
|
|
6
|
+
readonly signal: AbortSignal;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A tool the loop can actually call. `sideEffects`/`reversible` are optional
|
|
10
|
+
* because a bare `ExecutableTool` (hand-built in a test, or from a source
|
|
11
|
+
* that never declared them) should not silently claim safety it did not
|
|
12
|
+
* declare — `withAutonomy` (task 9) treats an unset `sideEffects` as "assume
|
|
13
|
+
* side-effecting" for exactly that reason.
|
|
14
|
+
*/
|
|
15
|
+
export interface ExecutableTool {
|
|
16
|
+
readonly spec: ProviderToolSpec;
|
|
17
|
+
readonly sideEffects?: boolean;
|
|
18
|
+
readonly reversible?: boolean;
|
|
19
|
+
execute(input: Readonly<Record<string, unknown>>, ctx: ToolExecutionContext): Promise<unknown>;
|
|
20
|
+
/** Undoes one past call, given the receipt (that call's own output) — present exactly when `reversible` is `true` (task 10). */
|
|
21
|
+
revert?(receipt: unknown, ctx: ToolExecutionContext): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export interface ToolCallOutcome {
|
|
24
|
+
readonly call: ProviderToolCall;
|
|
25
|
+
readonly ok: boolean;
|
|
26
|
+
/** The tool's return value, serialised to a string for the model — present when `ok`. */
|
|
27
|
+
readonly output?: string;
|
|
28
|
+
/** A human-readable failure reason, fed back to the model as the tool result — present when not `ok`. */
|
|
29
|
+
readonly error?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface StepRecord {
|
|
32
|
+
readonly response: ChatMessage;
|
|
33
|
+
readonly usage: TokenUsage;
|
|
34
|
+
readonly toolOutcomes: readonly ToolCallOutcome[];
|
|
35
|
+
}
|
|
36
|
+
export type RunStopReason = 'end_turn' | 'max_tokens' | 'max_steps' | 'repetition_detected' | 'cancelled' | 'budget_exceeded' | 'max_duration' | 'killed'
|
|
37
|
+
/** The run threw instead of returning — e.g. a model call's retries were exhausted (task 11: this is how `runSubagent` reports a sub-agent's crash as data instead of an exception, so it cannot propagate into the parent's own loop). */
|
|
38
|
+
| 'errored';
|
|
39
|
+
export interface RunResult {
|
|
40
|
+
readonly messages: readonly ChatMessage[];
|
|
41
|
+
readonly steps: readonly StepRecord[];
|
|
42
|
+
/** The last assistant turn's text — `null` if the run stopped before producing one. */
|
|
43
|
+
readonly finalText: string | null;
|
|
44
|
+
readonly stopReason: RunStopReason;
|
|
45
|
+
readonly usage: TokenUsage;
|
|
46
|
+
/** Set only when `stopReason` is `'errored'` — the caught error's message. */
|
|
47
|
+
readonly error?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface RunAgentLoopInput {
|
|
50
|
+
readonly client: ProviderClient;
|
|
51
|
+
readonly messages: readonly ChatMessage[];
|
|
52
|
+
readonly system?: string;
|
|
53
|
+
readonly tools?: readonly ExecutableTool[];
|
|
54
|
+
readonly maxTokens: number;
|
|
55
|
+
readonly temperature?: number;
|
|
56
|
+
/** Hard ceiling on model-call turns — the "infinite loop" backstop (default 25). */
|
|
57
|
+
readonly maxSteps?: number;
|
|
58
|
+
/** Per model call, including retries (default 3). */
|
|
59
|
+
readonly maxAttempts?: number;
|
|
60
|
+
/** Per model call attempt (default 60_000ms). */
|
|
61
|
+
readonly timeoutMs?: number;
|
|
62
|
+
/** How many times an identical tool call (name + input) may repeat before the run stops (default 2). */
|
|
63
|
+
readonly maxRepeats?: number;
|
|
64
|
+
readonly signal?: AbortSignal;
|
|
65
|
+
/** Checked before every model call; a call that would exceed it never happens ("arrêt propre et alerte, jamais dégradation silencieuse"). */
|
|
66
|
+
readonly budget?: BudgetTracker;
|
|
67
|
+
/** Checked before every model call — an explicit, human-flipped stop, independent of budgets. */
|
|
68
|
+
readonly killSwitch?: KillSwitch;
|
|
69
|
+
/** The alert half of a budget stop — called once, with which limit tripped, right before the run returns. */
|
|
70
|
+
readonly onBudgetExceeded?: (reason: BudgetExceededReason) => void;
|
|
71
|
+
/** Wall-clock ceiling for the whole run — "durée maximale par run", the fourth budget dimension the lot's design section names, checked independently of `BudgetTracker` since it belongs to one run, not to the agent's calendar-bucketed totals. */
|
|
72
|
+
readonly maxRunDurationMs?: number;
|
|
73
|
+
/** Clock the loop measures `maxRunDurationMs` against — injectable for tests, defaults to `Date.now`. */
|
|
74
|
+
readonly now?: () => number;
|
|
75
|
+
/** "Mode « rien ne sort »" (task 21) — checked before every model call; an out-of-allowlist provider throws instead of returning a stop reason, since a privacy leak is a configuration error, not a run outcome to record. */
|
|
76
|
+
readonly privacyPolicy?: NoDataLeavesPolicy;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { DiffEntry } from '../reversibility/diff.js';
|
|
2
|
+
/**
|
|
3
|
+
* "Un agent peut être exécuté contre une copie du site, en lecture réelle et
|
|
4
|
+
* écriture simulée, avec production des diffs qu'il aurait appliqués."
|
|
5
|
+
*/
|
|
6
|
+
export interface SandboxCallResult {
|
|
7
|
+
/**
|
|
8
|
+
* `true` when the write genuinely ran, against the copy, and was
|
|
9
|
+
* immediately undone via the tool's own `revert()` — a real dry run, not
|
|
10
|
+
* a guess. `false` when the tool has no `revert()`: there is no safe way
|
|
11
|
+
* to undo it on the copy, so it was never called at all, not even once.
|
|
12
|
+
*/
|
|
13
|
+
readonly simulated: boolean;
|
|
14
|
+
/** The tool's own output from the reverted call — present only when `simulated` is `true`. */
|
|
15
|
+
readonly wouldHaveApplied?: unknown;
|
|
16
|
+
/** `diffValues(before, after)` around the reverted call — present only when both a `snapshot()` was supplied and `simulated` is `true`. */
|
|
17
|
+
readonly diff?: readonly DiffEntry[];
|
|
18
|
+
readonly note: string;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sandbox/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAEzD;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,8FAA8F;IAC9F,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;IACnC,2IAA2I;IAC3I,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sandbox/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ExecutableTool } from '../runtime/types.js';
|
|
2
|
+
export interface WithSandboxOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Reads whatever state a diff should be computed over (e.g. the copied
|
|
5
|
+
* site's data) — called once before and once after a reverted write. No
|
|
6
|
+
* generic "read the current state" exists in this runtime (same limit
|
|
7
|
+
* `diffValues` itself documents), so without this the sandbox still
|
|
8
|
+
* simulates the write safely, it just cannot report a `diff`, only
|
|
9
|
+
* `wouldHaveApplied`.
|
|
10
|
+
*/
|
|
11
|
+
readonly snapshot?: () => Promise<unknown>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A read tool (`sideEffects` not `true`) is unchanged — "lecture réelle".
|
|
15
|
+
* A side-effecting, reversible tool is genuinely called against the copy and
|
|
16
|
+
* immediately reverted — "écriture simulée": the copy ends the call in the
|
|
17
|
+
* same state it started in, but what the call produced (and, with
|
|
18
|
+
* `snapshot`, a real before/after diff) is captured and returned instead of
|
|
19
|
+
* the tool's own output. A side-effecting tool with no `revert()` is never
|
|
20
|
+
* called at all — there is no safe way to undo it on the copy, so refusing
|
|
21
|
+
* is the only sandbox-safe answer. "C'est le prérequis à toute activation en
|
|
22
|
+
* autonomie" (task 9's `autonomous` level).
|
|
23
|
+
*/
|
|
24
|
+
export declare function withSandbox(tool: ExecutableTool, options?: WithSandboxOptions): ExecutableTool;
|
|
25
|
+
export declare function withSandboxForManifest(tools: readonly ExecutableTool[], options?: WithSandboxOptions): readonly ExecutableTool[];
|
|
26
|
+
//# sourceMappingURL=with-sandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-sandbox.d.ts","sourceRoot":"","sources":["../../src/sandbox/with-sandbox.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAwB,MAAM,qBAAqB,CAAA;AAG/E,MAAM,WAAW,kBAAkB;IACjC;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;CAC3C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,cAAc,EACpB,OAAO,GAAE,kBAAuB,GAC/B,cAAc,CA6BhB;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,OAAO,CAAC,EAAE,kBAAkB,GAC3B,SAAS,cAAc,EAAE,CAE3B"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { diffValues } from '../reversibility/diff.js';
|
|
2
|
+
/**
|
|
3
|
+
* A read tool (`sideEffects` not `true`) is unchanged — "lecture réelle".
|
|
4
|
+
* A side-effecting, reversible tool is genuinely called against the copy and
|
|
5
|
+
* immediately reverted — "écriture simulée": the copy ends the call in the
|
|
6
|
+
* same state it started in, but what the call produced (and, with
|
|
7
|
+
* `snapshot`, a real before/after diff) is captured and returned instead of
|
|
8
|
+
* the tool's own output. A side-effecting tool with no `revert()` is never
|
|
9
|
+
* called at all — there is no safe way to undo it on the copy, so refusing
|
|
10
|
+
* is the only sandbox-safe answer. "C'est le prérequis à toute activation en
|
|
11
|
+
* autonomie" (task 9's `autonomous` level).
|
|
12
|
+
*/
|
|
13
|
+
export function withSandbox(tool, options = {}) {
|
|
14
|
+
if (tool.sideEffects !== true)
|
|
15
|
+
return tool;
|
|
16
|
+
return {
|
|
17
|
+
...tool,
|
|
18
|
+
async execute(input, ctx) {
|
|
19
|
+
if (tool.revert === undefined) {
|
|
20
|
+
return {
|
|
21
|
+
simulated: false,
|
|
22
|
+
note: `"${tool.spec.name}" has no revert() — refusing to run it even once, since the sandbox could not undo it on the copied site.`,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const before = await options.snapshot?.();
|
|
26
|
+
const output = await tool.execute(input, ctx);
|
|
27
|
+
const after = await options.snapshot?.();
|
|
28
|
+
await tool.revert(output, ctx);
|
|
29
|
+
return {
|
|
30
|
+
simulated: true,
|
|
31
|
+
wouldHaveApplied: output,
|
|
32
|
+
note: `"${tool.spec.name}" ran against the copy and was immediately reverted — a simulated write.`,
|
|
33
|
+
...(before === undefined || after === undefined ? {} : { diff: diffValues(before, after) }),
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function withSandboxForManifest(tools, options) {
|
|
39
|
+
return tools.map((tool) => withSandbox(tool, options));
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=with-sandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-sandbox.js","sourceRoot":"","sources":["../../src/sandbox/with-sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAgBrD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CACzB,IAAoB,EACpB,OAAO,GAAuB,EAAE;IAEhC,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAE1C,OAAO;QACL,GAAG,IAAI;QACP,KAAK,CAAC,OAAO,CACX,KAAwC,EACxC,GAAyB;YAEzB,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC9B,OAAO;oBACL,SAAS,EAAE,KAAK;oBAChB,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,2GAA2G;iBACpI,CAAA;YACH,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAA;YACzC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;YAC7C,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAA;YACxC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;YAE9B,OAAO;gBACL,SAAS,EAAE,IAAI;gBACf,gBAAgB,EAAE,MAAM;gBACxB,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,0EAA0E;gBAClG,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;aAC5F,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,KAAgC,EAChC,OAA4B;IAE5B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAA;AACxD,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SkillStore } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* A skill is a folder — `<dir>/<name>/SKILL.md` plus whatever resource files
|
|
4
|
+
* sit alongside it — under `options.dir`. No external service (R1): this is
|
|
5
|
+
* the whole store, the same "real but local" tier the trace/media file
|
|
6
|
+
* stores already use. `list()` only reads each `SKILL.md`'s frontmatter, so
|
|
7
|
+
* scanning many skills stays cheap; the (potentially large) instructions
|
|
8
|
+
* body and resource file names are read only by `load()`, on demand.
|
|
9
|
+
*/
|
|
10
|
+
export declare function createFileSkillStore(options: {
|
|
11
|
+
readonly dir: string;
|
|
12
|
+
}): SkillStore;
|
|
13
|
+
//# sourceMappingURL=file-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-store.d.ts","sourceRoot":"","sources":["../../src/skills/file-store.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAwB,UAAU,EAAE,MAAM,YAAY,CAAA;AAIlE;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CA+DlF"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { cp, mkdir, readdir, readFile } from 'node:fs/promises';
|
|
2
|
+
import { join, relative } from 'node:path';
|
|
3
|
+
import { CogentaError } from '@cogenta/core';
|
|
4
|
+
import { parseSkillFile } from './frontmatter.js';
|
|
5
|
+
const SKILL_FILE = 'SKILL.md';
|
|
6
|
+
/**
|
|
7
|
+
* A skill is a folder — `<dir>/<name>/SKILL.md` plus whatever resource files
|
|
8
|
+
* sit alongside it — under `options.dir`. No external service (R1): this is
|
|
9
|
+
* the whole store, the same "real but local" tier the trace/media file
|
|
10
|
+
* stores already use. `list()` only reads each `SKILL.md`'s frontmatter, so
|
|
11
|
+
* scanning many skills stays cheap; the (potentially large) instructions
|
|
12
|
+
* body and resource file names are read only by `load()`, on demand.
|
|
13
|
+
*/
|
|
14
|
+
export function createFileSkillStore(options) {
|
|
15
|
+
const ready = mkdir(options.dir, { recursive: true });
|
|
16
|
+
async function readSkillFile(name) {
|
|
17
|
+
const path = join(options.dir, name, SKILL_FILE);
|
|
18
|
+
let raw;
|
|
19
|
+
try {
|
|
20
|
+
raw = await readFile(path, 'utf8');
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (error.code === 'ENOENT') {
|
|
24
|
+
throw new CogentaError({
|
|
25
|
+
code: 'SKILL_UNKNOWN',
|
|
26
|
+
message: `No skill named "${name}" (expected "${path}").`,
|
|
27
|
+
hint: 'Install the skill first, or check the name against `list()`.',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
return parseSkillFile(path, raw);
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
async list() {
|
|
36
|
+
await ready;
|
|
37
|
+
const entries = await readdir(options.dir, { withFileTypes: true }).catch(() => []);
|
|
38
|
+
const skills = [];
|
|
39
|
+
for (const entry of entries) {
|
|
40
|
+
if (!entry.isDirectory())
|
|
41
|
+
continue;
|
|
42
|
+
try {
|
|
43
|
+
const { metadata } = await readSkillFile(entry.name);
|
|
44
|
+
skills.push(metadata);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// A folder without a valid SKILL.md is not a skill — skip it rather than fail the whole listing.
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return skills;
|
|
51
|
+
},
|
|
52
|
+
async load(name) {
|
|
53
|
+
await ready;
|
|
54
|
+
const { metadata, instructions } = await readSkillFile(name);
|
|
55
|
+
const skillDir = join(options.dir, name);
|
|
56
|
+
const allFiles = await readdir(skillDir, { withFileTypes: true, recursive: true });
|
|
57
|
+
const resources = allFiles
|
|
58
|
+
.filter((entry) => entry.isFile())
|
|
59
|
+
.map((entry) => relative(skillDir, join(entry.parentPath, entry.name)))
|
|
60
|
+
.filter((path) => path !== SKILL_FILE);
|
|
61
|
+
const skill = { ...metadata, instructions, dir: skillDir, resources };
|
|
62
|
+
return skill;
|
|
63
|
+
},
|
|
64
|
+
async install(sourceDir) {
|
|
65
|
+
await ready;
|
|
66
|
+
const raw = await readFile(join(sourceDir, SKILL_FILE), 'utf8');
|
|
67
|
+
const { metadata } = parseSkillFile(join(sourceDir, SKILL_FILE), raw);
|
|
68
|
+
await cp(sourceDir, join(options.dir, metadata.name), { recursive: true });
|
|
69
|
+
return metadata;
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=file-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-store.js","sourceRoot":"","sources":["../../src/skills/file-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SkillMetadata } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Deliberately not a YAML parser (R9: no new dependency for three flat
|
|
4
|
+
* string fields) — `---\nkey: value\n---\nbody`, one `key: value` per line,
|
|
5
|
+
* nothing nested.
|
|
6
|
+
*/
|
|
7
|
+
export declare function parseSkillFile(path: string, raw: string): {
|
|
8
|
+
readonly metadata: SkillMetadata;
|
|
9
|
+
readonly instructions: string;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=frontmatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/skills/frontmatter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAI/C;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,GACV;IAAE,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAsCrE"}
|