@amalgm/agents 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/PURPOSE.md +25 -24
  2. package/README.md +21 -47
  3. package/dist/agents.d.ts +4 -26
  4. package/dist/agents.js +4 -87
  5. package/dist/bin/mcp.js +1 -1
  6. package/dist/cli/help.d.ts +1 -1
  7. package/dist/cli/help.js +2 -13
  8. package/dist/cli/open.d.ts +1 -1
  9. package/dist/cli/open.js +1 -5
  10. package/dist/cli/run.js +3 -8
  11. package/dist/errors.d.ts +1 -1
  12. package/dist/errors.js +0 -2
  13. package/dist/http/server.js +1 -7
  14. package/dist/index.d.ts +0 -2
  15. package/dist/index.js +0 -2
  16. package/dist/mcp/agent-tools.js +1 -1
  17. package/dist/mcp/tools.js +1 -2
  18. package/dist/rows.d.ts +1 -4
  19. package/dist/rows.js +0 -39
  20. package/dist/schema.js +53 -101
  21. package/dist/types.d.ts +0 -106
  22. package/docs/ARCHITECTURE.md +21 -33
  23. package/docs/CLI.md +3 -43
  24. package/docs/DATA_MODEL.md +7 -46
  25. package/docs/DEFINITIONS.md +4 -4
  26. package/docs/ENGINE_INTEGRATION.md +9 -71
  27. package/docs/MCP.md +3 -19
  28. package/docs/REST.md +14 -97
  29. package/docs/SDK.md +12 -61
  30. package/docs/SECURITY.md +6 -35
  31. package/docs/SHELL_INTEGRATION.md +29 -0
  32. package/examples/basic.ts +8 -22
  33. package/package.json +2 -2
  34. package/skills/amalgm-agents/SKILL.md +231 -20
  35. package/skills/amalgm-agents/agents/openai.yaml +2 -2
  36. package/dist/cli/session-commands.d.ts +0 -4
  37. package/dist/cli/session-commands.js +0 -54
  38. package/dist/drivers.d.ts +0 -4
  39. package/dist/drivers.js +0 -25
  40. package/dist/event-store.d.ts +0 -13
  41. package/dist/event-store.js +0 -50
  42. package/dist/http/session-routes.d.ts +0 -2
  43. package/dist/http/session-routes.js +0 -67
  44. package/dist/http/stream.d.ts +0 -3
  45. package/dist/http/stream.js +0 -30
  46. package/dist/mcp/session-tools.d.ts +0 -3
  47. package/dist/mcp/session-tools.js +0 -81
  48. package/dist/messages.d.ts +0 -3
  49. package/dist/messages.js +0 -56
  50. package/dist/runtime.d.ts +0 -29
  51. package/dist/runtime.js +0 -176
  52. package/dist/session-store.d.ts +0 -15
  53. package/dist/session-store.js +0 -83
  54. package/dist/turn-store.d.ts +0 -31
  55. package/dist/turn-store.js +0 -164
  56. package/docs/DRIVERS.md +0 -72
@@ -1,31 +0,0 @@
1
- import type Database from 'better-sqlite3';
2
- import type { EventStore } from './event-store.js';
3
- import type { SessionStore } from './session-store.js';
4
- import type { AgentFailure, AgentMessage, AgentTurn, JsonObject } from './types.js';
5
- export declare class TurnStore {
6
- private readonly database;
7
- private readonly sessions;
8
- private readonly events;
9
- private readonly now;
10
- constructor(database: Database.Database, sessions: SessionStore, events: EventStore, now: () => string);
11
- reserve(sessionId: string, input: AgentMessage, key?: string): {
12
- turn: AgentTurn;
13
- duplicate: boolean;
14
- };
15
- markRunning(id: string): AgentTurn;
16
- requestCancellation(id: string): AgentTurn;
17
- complete(id: string, result: JsonObject): AgentTurn;
18
- fail(id: string, failure: AgentFailure): AgentTurn;
19
- cancel(id: string): AgentTurn;
20
- interrupt(id: string, failure: AgentFailure): AgentTurn;
21
- get(id: string): AgentTurn | null;
22
- require(id: string): AgentTurn;
23
- list(sessionId: string): AgentTurn[];
24
- active(sessionId: string): AgentTurn | null;
25
- history(sessionId: string, beforeTurnId?: string): AgentMessage[];
26
- recoverInterrupted(): number;
27
- private byKey;
28
- private transition;
29
- private terminal;
30
- private touch;
31
- }
@@ -1,164 +0,0 @@
1
- import { AgentError } from './errors.js';
2
- import { newId, optionalKey, randomKey, requireId } from './ids.js';
3
- import { isObject } from './json.js';
4
- import { turnFromRow } from './rows.js';
5
- const ACTIVE_SQL = `status IN ('queued', 'running', 'cancelling')`;
6
- const TERMINAL = new Set(['completed', 'failed', 'cancelled', 'interrupted']);
7
- export class TurnStore {
8
- database;
9
- sessions;
10
- events;
11
- now;
12
- constructor(database, sessions, events, now) {
13
- this.database = database;
14
- this.sessions = sessions;
15
- this.events = events;
16
- this.now = now;
17
- }
18
- reserve(sessionId, input, key) {
19
- const session = this.sessions.require(sessionId);
20
- if (session.status !== 'active')
21
- throw new AgentError('conflict', 'Session is archived.');
22
- const idempotencyKey = optionalKey(key) || randomKey('turn-key');
23
- const existing = this.byKey(session.id, idempotencyKey);
24
- if (existing)
25
- return { turn: existing, duplicate: true };
26
- if (this.active(session.id))
27
- throw new AgentError('conflict', 'Session already has an active turn.');
28
- const id = newId('turn');
29
- const timestamp = this.now();
30
- let event;
31
- try {
32
- this.database.transaction(() => {
33
- this.database.prepare(`
34
- INSERT INTO turns (id, session_id, idempotency_key, status, input_json, created_at)
35
- VALUES (?, ?, ?, 'queued', ?, ?)
36
- `).run(id, session.id, idempotencyKey, JSON.stringify(input), timestamp);
37
- event = this.events.write(session.id, id, 'turn.input', { message: input });
38
- this.touch(session.id, timestamp);
39
- })();
40
- }
41
- catch (error) {
42
- const racedDuplicate = this.byKey(session.id, idempotencyKey);
43
- if (racedDuplicate)
44
- return { turn: racedDuplicate, duplicate: true };
45
- if (isUniqueConstraint(error)) {
46
- throw new AgentError('conflict', 'Session already has an active turn.');
47
- }
48
- throw error;
49
- }
50
- if (event)
51
- this.events.announce(event);
52
- return { turn: this.require(id), duplicate: false };
53
- }
54
- markRunning(id) {
55
- return this.transition(id, 'running', 'turn.running', true);
56
- }
57
- requestCancellation(id) {
58
- return this.transition(id, 'cancelling', 'turn.cancelling');
59
- }
60
- complete(id, result) {
61
- return this.terminal(id, 'completed', result, null, 'turn.completed');
62
- }
63
- fail(id, failure) {
64
- return this.terminal(id, 'failed', null, failure, 'turn.failed');
65
- }
66
- cancel(id) {
67
- return this.terminal(id, 'cancelled', null, null, 'turn.cancelled');
68
- }
69
- interrupt(id, failure) {
70
- return this.terminal(id, 'interrupted', null, failure, 'turn.interrupted');
71
- }
72
- get(id) {
73
- const row = this.database.prepare('SELECT * FROM turns WHERE id = ?').get(requireId(id, 'turn id'));
74
- return row ? turnFromRow(row) : null;
75
- }
76
- require(id) {
77
- const turn = this.get(id);
78
- if (!turn)
79
- throw new AgentError('not_found', `Turn not found: ${id}`);
80
- return turn;
81
- }
82
- list(sessionId) {
83
- this.sessions.require(sessionId);
84
- return this.database.prepare('SELECT * FROM turns WHERE session_id = ? ORDER BY created_at ASC')
85
- .all(sessionId).map(turnFromRow);
86
- }
87
- active(sessionId) {
88
- const row = this.database.prepare(`
89
- SELECT * FROM turns WHERE session_id = ? AND ${ACTIVE_SQL} ORDER BY created_at DESC LIMIT 1
90
- `).get(sessionId);
91
- return row ? turnFromRow(row) : null;
92
- }
93
- history(sessionId, beforeTurnId) {
94
- const messages = [];
95
- for (const turn of this.list(sessionId)) {
96
- if (turn.id === beforeTurnId)
97
- break;
98
- messages.push(turn.input);
99
- for (const event of this.events.forTurn(turn.id)) {
100
- const message = isObject(event.data.message) ? event.data.message : null;
101
- if (event.type === 'message' && message)
102
- messages.push(message);
103
- }
104
- }
105
- return messages;
106
- }
107
- recoverInterrupted() {
108
- const rows = this.database.prepare(`SELECT * FROM turns WHERE ${ACTIVE_SQL}`).all();
109
- for (const row of rows) {
110
- this.interrupt(turnFromRow(row).id, {
111
- code: 'process_restarted',
112
- message: 'The owning process restarted before the driver settled.',
113
- details: {},
114
- });
115
- }
116
- return rows.length;
117
- }
118
- byKey(sessionId, key) {
119
- const row = this.database.prepare('SELECT * FROM turns WHERE session_id = ? AND idempotency_key = ?')
120
- .get(sessionId, key);
121
- return row ? turnFromRow(row) : null;
122
- }
123
- transition(id, status, type, started = false) {
124
- const turn = this.require(id);
125
- const timestamp = this.now();
126
- let event;
127
- this.database.transaction(() => {
128
- this.database.prepare(`UPDATE turns SET status = ?, started_at = COALESCE(started_at, ?) WHERE id = ?`)
129
- .run(status, started ? timestamp : turn.startedAt, turn.id);
130
- event = this.events.write(turn.sessionId, turn.id, type, {});
131
- this.touch(turn.sessionId, timestamp);
132
- })();
133
- if (event)
134
- this.events.announce(event);
135
- return this.require(turn.id);
136
- }
137
- terminal(id, status, result, error, type) {
138
- const turn = this.require(id);
139
- if (TERMINAL.has(turn.status))
140
- return turn;
141
- const timestamp = this.now();
142
- let event;
143
- this.database.transaction(() => {
144
- this.database.prepare(`
145
- UPDATE turns SET status = ?, result_json = ?, error_json = ?, completed_at = ? WHERE id = ?
146
- `).run(status, result && JSON.stringify(result), error && JSON.stringify(error), timestamp, turn.id);
147
- const data = error ? { error: error } : {};
148
- event = this.events.write(turn.sessionId, turn.id, type, data);
149
- this.touch(turn.sessionId, timestamp);
150
- })();
151
- if (event)
152
- this.events.announce(event);
153
- return this.require(turn.id);
154
- }
155
- touch(sessionId, timestamp) {
156
- this.database.prepare('UPDATE sessions SET updated_at = ? WHERE id = ?').run(timestamp, sessionId);
157
- }
158
- }
159
- function isUniqueConstraint(error) {
160
- return Boolean(error
161
- && typeof error === 'object'
162
- && 'code' in error
163
- && String(error.code).startsWith('SQLITE_CONSTRAINT'));
164
- }
package/docs/DRIVERS.md DELETED
@@ -1,72 +0,0 @@
1
- # Agent drivers
2
-
3
- Drivers connect durable Agents state to a native or hosted runtime. They are
4
- registered by the embedding process and selected by `definition.driver.id`.
5
-
6
- ```ts
7
- import { defineDriver } from '@amalgm/agents';
8
-
9
- export default defineDriver({
10
- id: 'my-runtime',
11
- async run(request, context) {
12
- context.signal.throwIfAborted();
13
- context.emit({ type: 'text.delta', data: { text: 'Working…' } });
14
-
15
- return {
16
- driverSessionId: request.driverSessionId ?? 'native-session-id',
17
- message: {
18
- role: 'assistant',
19
- parts: [{ type: 'text', text: 'Done.' }],
20
- },
21
- metadata: { provider: 'example' },
22
- };
23
- },
24
- });
25
- ```
26
-
27
- ## Request
28
-
29
- `DriverRunRequest` includes:
30
-
31
- - the immutable `AgentRevision`;
32
- - the durable session and current turn;
33
- - ordered completed history before this turn;
34
- - the accepted input; and
35
- - the opaque `driverSessionId` returned by an earlier turn.
36
-
37
- Drivers do not receive a database handle. They resolve Toolbox actions,
38
- credentials, skills, files, and native processes through dependencies supplied
39
- by their host.
40
-
41
- ## Events and results
42
-
43
- Call `context.emit` for streaming or structured observations. The event is
44
- committed before the call returns. Use type `message` with an assistant
45
- `AgentMessage` for a durable output message; other event names are driver-owned
46
- and their data must be JSON.
47
-
48
- A final returned `message` is appended once before turn completion. Returned
49
- `driverSessionId` replaces the prior opaque value for future continuation.
50
-
51
- ## Cancellation and limits
52
-
53
- Drivers must observe `context.signal` and stop their underlying process or
54
- request. The service records cancellation intent before aborting the signal.
55
- Input and event sizes are bounded. A driver that emits invalid or oversized
56
- data fails the turn explicitly.
57
-
58
- The in-process boundary cannot forcibly kill an uncooperative driver. Process
59
- drivers should own their child process and terminate it when signalled.
60
-
61
- ## Loading drivers in CLIs
62
-
63
- Compile driver modules to JavaScript and export either an `AgentDriver`, a
64
- `driver` value, or a zero-argument factory:
65
-
66
- ```bash
67
- AMALGM_AGENT_DRIVERS=./dist/codex-driver.js amalgm-agents-rest
68
- amalgm-agents --drivers ./dist/codex-driver.js talk reviewer "Review this"
69
- ```
70
-
71
- Multiple modules are comma-separated. Secret values belong in the host's
72
- credential resolver, not in agent definitions or driver module arguments.