@animalabs/agent-framework 0.6.2 → 0.6.4
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/src/agent.d.ts +3 -1
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +7 -2
- package/dist/src/agent.js.map +1 -1
- package/dist/src/framework.d.ts +60 -1
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +261 -20
- package/dist/src/framework.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/modules/discord/index.d.ts +1 -0
- package/dist/src/modules/discord/index.d.ts.map +1 -1
- package/dist/src/modules/discord/index.js +4 -1
- package/dist/src/modules/discord/index.js.map +1 -1
- package/dist/src/modules/discord/types.d.ts +2 -0
- package/dist/src/modules/discord/types.d.ts.map +1 -1
- package/dist/src/modules/health/index.d.ts +2 -0
- package/dist/src/modules/health/index.d.ts.map +1 -1
- package/dist/src/modules/health/index.js +15 -4
- package/dist/src/modules/health/index.js.map +1 -1
- package/dist/src/timezone.d.ts +14 -0
- package/dist/src/timezone.d.ts.map +1 -0
- package/dist/src/timezone.js +74 -0
- package/dist/src/timezone.js.map +1 -0
- package/dist/src/types/agent.d.ts +5 -2
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +46 -0
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +9 -0
- package/dist/src/types/trace.d.ts.map +1 -1
- package/dist/test/agent-cache-ttl.test.js +18 -2
- package/dist/test/agent-cache-ttl.test.js.map +1 -1
- package/dist/test/health-snapshot.test.d.ts +2 -0
- package/dist/test/health-snapshot.test.d.ts.map +1 -0
- package/dist/test/health-snapshot.test.js +74 -0
- package/dist/test/health-snapshot.test.js.map +1 -0
- package/dist/test/inference-failure-observability.test.js +5 -0
- package/dist/test/inference-failure-observability.test.js.map +1 -1
- package/dist/test/maintenance-timer.test.d.ts +2 -0
- package/dist/test/maintenance-timer.test.d.ts.map +1 -0
- package/dist/test/maintenance-timer.test.js +114 -0
- package/dist/test/maintenance-timer.test.js.map +1 -0
- package/dist/test/ops-alert.test.d.ts +2 -0
- package/dist/test/ops-alert.test.d.ts.map +1 -0
- package/dist/test/ops-alert.test.js +152 -0
- package/dist/test/ops-alert.test.js.map +1 -0
- package/dist/test/timezone.test.d.ts +2 -0
- package/dist/test/timezone.test.d.ts.map +1 -0
- package/dist/test/timezone.test.js +18 -0
- package/dist/test/timezone.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/agent.ts +8 -3
- package/src/framework.ts +307 -22
- package/src/index.ts +1 -0
- package/src/modules/discord/index.ts +4 -1
- package/src/modules/discord/types.ts +3 -0
- package/src/modules/health/index.ts +20 -4
- package/src/timezone.ts +90 -0
- package/src/types/agent.ts +6 -2
- package/src/types/framework.ts +51 -0
- package/src/types/trace.ts +16 -0
package/src/timezone.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent-visible wall-clock formatting.
|
|
3
|
+
*
|
|
4
|
+
* Persistence and protocol timestamps should remain epoch milliseconds or UTC
|
|
5
|
+
* ISO strings. These helpers are only for presentation boundaries where a
|
|
6
|
+
* timestamp is rendered into an agent's context or a tool result.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export function isValidTimeZone(timeZone: string): boolean {
|
|
10
|
+
try {
|
|
11
|
+
new Intl.DateTimeFormat('en-US', { timeZone }).format(new Date(0));
|
|
12
|
+
return true;
|
|
13
|
+
} catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function resolveTimeZone(configured?: string): string {
|
|
19
|
+
const candidate = configured?.trim()
|
|
20
|
+
|| process.env.AGENT_TIMEZONE?.trim()
|
|
21
|
+
|| Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
22
|
+
|| 'UTC';
|
|
23
|
+
if (!isValidTimeZone(candidate)) {
|
|
24
|
+
throw new Error(`Invalid IANA time zone: ${JSON.stringify(candidate)}`);
|
|
25
|
+
}
|
|
26
|
+
return candidate;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type ZonedParts = {
|
|
30
|
+
year: string;
|
|
31
|
+
month: string;
|
|
32
|
+
day: string;
|
|
33
|
+
hour: string;
|
|
34
|
+
minute: string;
|
|
35
|
+
second: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
function zonedParts(date: Date, timeZone: string): ZonedParts {
|
|
39
|
+
const parts = new Intl.DateTimeFormat('en-CA', {
|
|
40
|
+
timeZone,
|
|
41
|
+
year: 'numeric',
|
|
42
|
+
month: '2-digit',
|
|
43
|
+
day: '2-digit',
|
|
44
|
+
hour: '2-digit',
|
|
45
|
+
minute: '2-digit',
|
|
46
|
+
second: '2-digit',
|
|
47
|
+
hourCycle: 'h23',
|
|
48
|
+
}).formatToParts(date);
|
|
49
|
+
const get = (type: Intl.DateTimeFormatPartTypes): string =>
|
|
50
|
+
parts.find((part) => part.type === type)?.value ?? '';
|
|
51
|
+
return {
|
|
52
|
+
year: get('year'),
|
|
53
|
+
month: get('month'),
|
|
54
|
+
day: get('day'),
|
|
55
|
+
hour: get('hour'),
|
|
56
|
+
minute: get('minute'),
|
|
57
|
+
second: get('second'),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** RFC3339-style local time with an explicit numeric offset and IANA zone. */
|
|
62
|
+
export function formatZonedDateTime(value: Date | number | string, timeZone: string): string {
|
|
63
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
64
|
+
if (Number.isNaN(date.getTime())) throw new Error(`Invalid date: ${String(value)}`);
|
|
65
|
+
const zone = resolveTimeZone(timeZone);
|
|
66
|
+
const p = zonedParts(date, zone);
|
|
67
|
+
|
|
68
|
+
// Reinterpret the displayed wall-clock components as UTC to recover the
|
|
69
|
+
// offset that applied at this exact instant (including DST transitions).
|
|
70
|
+
const displayedAsUtc = Date.UTC(
|
|
71
|
+
Number(p.year), Number(p.month) - 1, Number(p.day),
|
|
72
|
+
Number(p.hour), Number(p.minute), Number(p.second),
|
|
73
|
+
);
|
|
74
|
+
const instantAtWholeSecond = Math.floor(date.getTime() / 1000) * 1000;
|
|
75
|
+
const offsetMinutes = Math.round((displayedAsUtc - instantAtWholeSecond) / 60_000);
|
|
76
|
+
const sign = offsetMinutes < 0 ? '-' : '+';
|
|
77
|
+
const absoluteOffset = Math.abs(offsetMinutes);
|
|
78
|
+
const offset = `${sign}${String(Math.floor(absoluteOffset / 60)).padStart(2, '0')}:${String(absoluteOffset % 60).padStart(2, '0')}`;
|
|
79
|
+
const millis = String(date.getUTCMilliseconds()).padStart(3, '0');
|
|
80
|
+
|
|
81
|
+
return `${p.year}-${p.month}-${p.day}T${p.hour}:${p.minute}:${p.second}.${millis}${offset} [${zone}]`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Compact wall-clock time for provenance headers. */
|
|
85
|
+
export function formatZonedTime(value: Date | number | string, timeZone: string): string {
|
|
86
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
87
|
+
if (Number.isNaN(date.getTime())) throw new Error(`Invalid date: ${String(value)}`);
|
|
88
|
+
const p = zonedParts(date, resolveTimeZone(timeZone));
|
|
89
|
+
return `${p.hour}:${p.minute}`;
|
|
90
|
+
}
|
package/src/types/agent.ts
CHANGED
|
@@ -48,7 +48,7 @@ export interface AgentConfig {
|
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
50
|
* Prompt-cache TTL forwarded to the provider (Anthropic `cache_control.ttl`).
|
|
51
|
-
* '5m'
|
|
51
|
+
* '5m' or '1h'. Defaults to '1h'.
|
|
52
52
|
*
|
|
53
53
|
* Why you'd set '1h': for persistent agents whose conversational cadence is
|
|
54
54
|
* slower than 5 minutes, the default TTL expires between turns and the full
|
|
@@ -57,10 +57,14 @@ export interface AgentConfig {
|
|
|
57
57
|
* chatty-but-not-rapid agent pays the write premium over and over. With '1h'
|
|
58
58
|
* the write happens once per idle-hour and subsequent turns hit cache reads;
|
|
59
59
|
* in practice cache writes can dominate spend for slow-cadence agents.
|
|
60
|
-
*
|
|
60
|
+
* Set '5m' explicitly for high-frequency loops with sub-5-minute cadence,
|
|
61
61
|
* where the cheaper write premium wins.
|
|
62
62
|
*/
|
|
63
63
|
cacheTtl?: '5m' | '1h';
|
|
64
|
+
|
|
65
|
+
/** Provider-specific request parameters (for example Responses reasoning
|
|
66
|
+
* and server-side compaction settings). */
|
|
67
|
+
providerParams?: Record<string, unknown>;
|
|
64
68
|
/**
|
|
65
69
|
* Extended thinking config. When `enabled: true`, the agent runs with
|
|
66
70
|
* Anthropic's native extended thinking; responses include `thinking` blocks
|
package/src/types/framework.ts
CHANGED
|
@@ -32,6 +32,13 @@ export interface ProcessLoggingConfig {
|
|
|
32
32
|
* Configuration for the agent framework.
|
|
33
33
|
*/
|
|
34
34
|
export interface FrameworkConfig {
|
|
35
|
+
/**
|
|
36
|
+
* IANA zone used only when rendering wall-clock times for the agent.
|
|
37
|
+
* Stored/protocol timestamps remain epoch/UTC. Defaults to AGENT_TIMEZONE,
|
|
38
|
+
* then the process zone.
|
|
39
|
+
*/
|
|
40
|
+
timeZone?: string;
|
|
41
|
+
|
|
35
42
|
/** Path to Chronicle store */
|
|
36
43
|
storePath?: string;
|
|
37
44
|
|
|
@@ -56,6 +63,13 @@ export interface FrameworkConfig {
|
|
|
56
63
|
/** Interval for periodic store sync in milliseconds (default: 1000ms, 0 to disable) */
|
|
57
64
|
syncIntervalMs?: number;
|
|
58
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Interval for queued context-maintenance polling in milliseconds
|
|
68
|
+
* (default: 5000ms, 0 to disable). Each pass refreshes the agent's live tool
|
|
69
|
+
* definitions, then advances pending compression/indexing work.
|
|
70
|
+
*/
|
|
71
|
+
maintenanceIntervalMs?: number;
|
|
72
|
+
|
|
59
73
|
/** Process logging configuration (default: disabled) */
|
|
60
74
|
processLogging?: ProcessLoggingConfig;
|
|
61
75
|
|
|
@@ -92,6 +106,43 @@ export interface FrameworkConfig {
|
|
|
92
106
|
conversations?: ConversationRouterConfig;
|
|
93
107
|
}
|
|
94
108
|
|
|
109
|
+
/** One agent's outcome within a periodic context-maintenance pass. */
|
|
110
|
+
export interface ContextMaintenanceAgentRun {
|
|
111
|
+
agentName: string;
|
|
112
|
+
startedAt: number;
|
|
113
|
+
finishedAt?: number;
|
|
114
|
+
ticks: number;
|
|
115
|
+
readyBefore: boolean;
|
|
116
|
+
readyAfter?: boolean;
|
|
117
|
+
pendingBefore?: string;
|
|
118
|
+
pendingAfter?: string;
|
|
119
|
+
progressBefore?: Record<string, unknown>;
|
|
120
|
+
progressAfter?: Record<string, unknown>;
|
|
121
|
+
error?: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** A bounded periodic context-maintenance pass. */
|
|
125
|
+
export interface ContextMaintenanceRun {
|
|
126
|
+
id: number;
|
|
127
|
+
startedAt: number;
|
|
128
|
+
finishedAt?: number;
|
|
129
|
+
agents: ContextMaintenanceAgentRun[];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Debug-safe maintenance state. Contains counts and errors, never messages. */
|
|
133
|
+
export interface ContextMaintenanceSnapshot {
|
|
134
|
+
intervalMs: number;
|
|
135
|
+
ticksPerPass: number;
|
|
136
|
+
current: ContextMaintenanceRun | null;
|
|
137
|
+
history: ContextMaintenanceRun[];
|
|
138
|
+
agents: Array<{
|
|
139
|
+
agentName: string;
|
|
140
|
+
ready: boolean;
|
|
141
|
+
pending?: string;
|
|
142
|
+
progress?: Record<string, unknown>;
|
|
143
|
+
}>;
|
|
144
|
+
}
|
|
145
|
+
|
|
95
146
|
/**
|
|
96
147
|
* Policy for deciding when to run inference.
|
|
97
148
|
*/
|
package/src/types/trace.ts
CHANGED
|
@@ -321,6 +321,22 @@ export type TraceEvent =
|
|
|
321
321
|
hadState: boolean;
|
|
322
322
|
/** True when the dropped response carried a server-managed `checkpoint`. */
|
|
323
323
|
hadCheckpoint: boolean;
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
// Ops / fleet observability. Everything the framework's opsAlert() escalates
|
|
327
|
+
// (refusals, hard-down, MCPL unreachable, …) mirrored onto the trace bus so
|
|
328
|
+
// authorized observers see alerts on the same wire as the rest of the
|
|
329
|
+
// agent's internal life. Discord (CONNECTOME_OPS_WEBHOOK) is one sink of
|
|
330
|
+
// this stream, not a separate system. See connectome docs/observability.md.
|
|
331
|
+
| (TraceEventBase & {
|
|
332
|
+
type: 'ops:alert';
|
|
333
|
+
/** Alert kind — open set: 'refusal' | 'hard-down' | 'mcpl-down' | … */
|
|
334
|
+
kind: string;
|
|
335
|
+
/** Agent name, or a server/component id for non-agent alerts (e.g. mcpl-down). */
|
|
336
|
+
agentName: string;
|
|
337
|
+
message: string;
|
|
338
|
+
/** Kind-specific structured payload (mirrors the failures.log record). */
|
|
339
|
+
data?: Record<string, unknown>;
|
|
324
340
|
});
|
|
325
341
|
|
|
326
342
|
/**
|