@agentforge-io/core 3.4.0 → 4.0.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.
- package/dist/domain/conversation.d.ts +11 -0
- package/dist/repositories/in-memory.d.ts +1 -0
- package/dist/repositories/in-memory.js +10 -0
- package/dist/repositories/index.d.ts +5 -0
- package/dist/services/conversation.service.d.ts +15 -0
- package/dist/services/conversation.service.js +41 -0
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.js +2 -1
- package/package.json +2 -1
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import type { ConversationStatus, MessageRole, ToolCallRecord, TokenUsage } from '../types/agent.types';
|
|
2
2
|
export interface Conversation {
|
|
3
3
|
id: string;
|
|
4
|
+
/** Short, URL-friendly public handle (nanoid). Preferred over `id`
|
|
5
|
+
* for links, deep-link params (`?c=`/`?conv=`) and SDK resume — it's
|
|
6
|
+
* shorter and doesn't leak the internal UUID. Generated on create.
|
|
7
|
+
* Optional in the type so persistence adapters that predate the
|
|
8
|
+
* column (older @agentforge-io/typeorm builds) still satisfy the
|
|
9
|
+
* contract during the rollout — once every adapter ships the column
|
|
10
|
+
* this can be tightened to required. */
|
|
11
|
+
code?: string;
|
|
4
12
|
userId: string;
|
|
5
13
|
agentId: string;
|
|
6
14
|
title?: string;
|
|
@@ -50,6 +58,9 @@ export type NewMessage = Omit<Message, 'id' | 'createdAt'>;
|
|
|
50
58
|
*/
|
|
51
59
|
export interface ConversationListItem {
|
|
52
60
|
id: string;
|
|
61
|
+
/** Short public handle — see `Conversation.code`. Optional during the
|
|
62
|
+
* rollout (older typeorm builds don't select it yet). */
|
|
63
|
+
code?: string;
|
|
53
64
|
userId: string;
|
|
54
65
|
agentId: string;
|
|
55
66
|
status: ConversationStatus;
|
|
@@ -5,6 +5,7 @@ export declare class InMemoryConversationRepository implements ConversationRepos
|
|
|
5
5
|
private byId;
|
|
6
6
|
create(c: NewConversation): Promise<Conversation>;
|
|
7
7
|
findById(id: string): Promise<Conversation | null>;
|
|
8
|
+
findByCode(code: string): Promise<Conversation | null>;
|
|
8
9
|
findByIdForUser(id: string, userId: string): Promise<Conversation | null>;
|
|
9
10
|
listForUser(userId: string, opts?: {
|
|
10
11
|
status?: ConversationStatus;
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.InMemoryMessageRepository = exports.InMemoryConversationRepository = void 0;
|
|
7
7
|
exports.createInMemoryRepositories = createInMemoryRepositories;
|
|
8
8
|
const crypto_1 = require("crypto");
|
|
9
|
+
const conversation_service_1 = require("../services/conversation.service");
|
|
9
10
|
class InMemoryConversationRepository {
|
|
10
11
|
constructor() {
|
|
11
12
|
this.byId = new Map();
|
|
@@ -14,6 +15,7 @@ class InMemoryConversationRepository {
|
|
|
14
15
|
const now = new Date();
|
|
15
16
|
const full = {
|
|
16
17
|
id: (0, crypto_1.randomUUID)(),
|
|
18
|
+
code: (0, conversation_service_1.generateConversationCode)(),
|
|
17
19
|
status: 'active',
|
|
18
20
|
totalInputTokens: 0,
|
|
19
21
|
totalOutputTokens: 0,
|
|
@@ -28,6 +30,13 @@ class InMemoryConversationRepository {
|
|
|
28
30
|
async findById(id) {
|
|
29
31
|
return this.byId.get(id) ?? null;
|
|
30
32
|
}
|
|
33
|
+
async findByCode(code) {
|
|
34
|
+
for (const c of this.byId.values()) {
|
|
35
|
+
if (c.code === code)
|
|
36
|
+
return c;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
31
40
|
async findByIdForUser(id, userId) {
|
|
32
41
|
const c = this.byId.get(id);
|
|
33
42
|
return c && c.userId === userId ? c : null;
|
|
@@ -54,6 +63,7 @@ class InMemoryConversationRepository {
|
|
|
54
63
|
return {
|
|
55
64
|
items: all.slice(start, end).map((c) => ({
|
|
56
65
|
id: c.id,
|
|
66
|
+
code: c.code,
|
|
57
67
|
userId: c.userId,
|
|
58
68
|
agentId: c.agentId,
|
|
59
69
|
status: c.status,
|
|
@@ -11,6 +11,11 @@ export declare const CONNECTOR_AUTH_REPOSITORY = "AGENTFORGE_CONNECTOR_AUTH_REPO
|
|
|
11
11
|
export interface ConversationRepository {
|
|
12
12
|
create(conv: NewConversation): Promise<Conversation>;
|
|
13
13
|
findById(id: string): Promise<Conversation | null>;
|
|
14
|
+
/** Look a conversation up by its short public `code` (nanoid).
|
|
15
|
+
* Optional during rollout — adapters that predate the column don't
|
|
16
|
+
* implement it yet; callers must feature-detect (see
|
|
17
|
+
* `ConversationService.getByCode`). */
|
|
18
|
+
findByCode?(code: string): Promise<Conversation | null>;
|
|
14
19
|
/** Same as findById but also enforces ownership — used in user-scoped routes. */
|
|
15
20
|
findByIdForUser(id: string, userId: string): Promise<Conversation | null>;
|
|
16
21
|
/**
|
|
@@ -6,6 +6,13 @@ export declare class ConversationNotFoundError extends Error {
|
|
|
6
6
|
code: string;
|
|
7
7
|
constructor(id: string);
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Generate a short, URL-friendly conversation `code` (nanoid-style).
|
|
11
|
+
* 31^12 ≈ 7.6e17 combinations — collisions are negligible; the unique
|
|
12
|
+
* index on the column is the backstop. Uses `crypto.randomBytes` so we
|
|
13
|
+
* don't add a nanoid dependency to the shared packages.
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateConversationCode(length?: number): string;
|
|
9
16
|
export declare class ConversationService {
|
|
10
17
|
private readonly convRepo;
|
|
11
18
|
private readonly msgRepo;
|
|
@@ -16,6 +23,14 @@ export declare class ConversationService {
|
|
|
16
23
|
title?: string;
|
|
17
24
|
metadata?: Record<string, unknown>;
|
|
18
25
|
}): Promise<Conversation>;
|
|
26
|
+
/** Resolve a conversation by its short public `code`. Returns `null`
|
|
27
|
+
* when no conversation carries that code, or when the wired repo
|
|
28
|
+
* adapter predates the column (no `findByCode`). */
|
|
29
|
+
findByCode(code: string): Promise<Conversation | null>;
|
|
30
|
+
/** Resolve a conversation by `code`, enforcing ownership. Throws
|
|
31
|
+
* `ConversationNotFoundError` (ambiguous on purpose) when the code is
|
|
32
|
+
* unknown OR belongs to another user — same contract as `loadOwned`. */
|
|
33
|
+
getByCode(code: string, userId: string): Promise<Conversation>;
|
|
19
34
|
addMessage(params: {
|
|
20
35
|
conversationId: string;
|
|
21
36
|
userId: string;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ConversationService = exports.ConversationNotFoundError = void 0;
|
|
4
|
+
exports.generateConversationCode = generateConversationCode;
|
|
5
|
+
const crypto_1 = require("crypto");
|
|
4
6
|
class ConversationNotFoundError extends Error {
|
|
5
7
|
constructor(id) {
|
|
6
8
|
super(`Conversation "${id}" not found`);
|
|
@@ -9,6 +11,24 @@ class ConversationNotFoundError extends Error {
|
|
|
9
11
|
}
|
|
10
12
|
}
|
|
11
13
|
exports.ConversationNotFoundError = ConversationNotFoundError;
|
|
14
|
+
/** Alphabet for conversation codes. Lowercase + digits, minus the
|
|
15
|
+
* ambiguous glyphs (0/o/1/l/i) so a code stays readable when shared. */
|
|
16
|
+
const CODE_ALPHABET = 'abcdefghjkmnpqrstuvwxyz23456789';
|
|
17
|
+
const CODE_LENGTH = 12;
|
|
18
|
+
/**
|
|
19
|
+
* Generate a short, URL-friendly conversation `code` (nanoid-style).
|
|
20
|
+
* 31^12 ≈ 7.6e17 combinations — collisions are negligible; the unique
|
|
21
|
+
* index on the column is the backstop. Uses `crypto.randomBytes` so we
|
|
22
|
+
* don't add a nanoid dependency to the shared packages.
|
|
23
|
+
*/
|
|
24
|
+
function generateConversationCode(length = CODE_LENGTH) {
|
|
25
|
+
const bytes = (0, crypto_1.randomBytes)(length);
|
|
26
|
+
let out = '';
|
|
27
|
+
for (let i = 0; i < length; i++) {
|
|
28
|
+
out += CODE_ALPHABET[bytes[i] % CODE_ALPHABET.length];
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
12
32
|
class ConversationService {
|
|
13
33
|
constructor(convRepo, msgRepo) {
|
|
14
34
|
this.convRepo = convRepo;
|
|
@@ -20,12 +40,33 @@ class ConversationService {
|
|
|
20
40
|
agentId: params.agentId,
|
|
21
41
|
title: params.title,
|
|
22
42
|
metadata: params.metadata,
|
|
43
|
+
code: generateConversationCode(),
|
|
23
44
|
status: 'active',
|
|
24
45
|
totalInputTokens: 0,
|
|
25
46
|
totalOutputTokens: 0,
|
|
26
47
|
messageCount: 0,
|
|
27
48
|
});
|
|
28
49
|
}
|
|
50
|
+
/** Resolve a conversation by its short public `code`. Returns `null`
|
|
51
|
+
* when no conversation carries that code, or when the wired repo
|
|
52
|
+
* adapter predates the column (no `findByCode`). */
|
|
53
|
+
async findByCode(code) {
|
|
54
|
+
if (!this.convRepo.findByCode)
|
|
55
|
+
return null;
|
|
56
|
+
return this.convRepo.findByCode(code);
|
|
57
|
+
}
|
|
58
|
+
/** Resolve a conversation by `code`, enforcing ownership. Throws
|
|
59
|
+
* `ConversationNotFoundError` (ambiguous on purpose) when the code is
|
|
60
|
+
* unknown OR belongs to another user — same contract as `loadOwned`. */
|
|
61
|
+
async getByCode(code, userId) {
|
|
62
|
+
const conv = this.convRepo.findByCode
|
|
63
|
+
? await this.convRepo.findByCode(code)
|
|
64
|
+
: null;
|
|
65
|
+
if (!conv || conv.userId !== userId) {
|
|
66
|
+
throw new ConversationNotFoundError(code);
|
|
67
|
+
}
|
|
68
|
+
return conv;
|
|
69
|
+
}
|
|
29
70
|
async addMessage(params) {
|
|
30
71
|
// Coerce empty/whitespace-only content to a sentinel so we don't
|
|
31
72
|
// poison the history with rows that getAnthropicMessages would
|
package/dist/services/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { AgentRunnerService } from './agent-runner.service';
|
|
|
3
3
|
export { ToolApprovalRequired, ToolBlockedError, isToolApprovalRequired, isToolBlockedError, type ToolApprovalGate, type ToolApprovalCheckArgs, type ToolApprovalDecision, } from './tool-approval-gate';
|
|
4
4
|
export { PreparedStreamService, PreparedStreamError, } from './prepared-stream.service';
|
|
5
5
|
export { InMemoryPreparedStreamStore } from './in-memory-prepared-stream.store';
|
|
6
|
-
export { ConversationService, ConversationNotFoundError, } from './conversation.service';
|
|
6
|
+
export { ConversationService, ConversationNotFoundError, generateConversationCode, } from './conversation.service';
|
|
7
7
|
export { AgentService, AgentForbiddenError, type AgentNotFoundError, } from './agent.service';
|
|
8
8
|
export { ApprovalCopywriterService, type ApprovalCopyBundle as ApprovalCopywriterBundle, type ApprovalCopywriterInput, } from './approval-copywriter.service';
|
|
9
9
|
export { OrchestratorService, OrchestratorError, type OrchestratorServiceOptions, } from './orchestrator.service';
|
package/dist/services/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.InMemoryAuthorizeStateStore = exports.ConnectorError = exports.ConnectorRegistryService = exports.OAuth2Service = exports.McpServerError = exports.McpServerService = exports.McpClientError = exports.McpClientService = exports.ChatTokenError = exports.ChatTokenService = exports.AgentJobWorker = exports.OrchestratorError = exports.OrchestratorService = exports.ApprovalCopywriterService = exports.AgentForbiddenError = exports.AgentService = exports.ConversationNotFoundError = exports.ConversationService = exports.InMemoryPreparedStreamStore = exports.PreparedStreamError = exports.PreparedStreamService = exports.isToolBlockedError = exports.isToolApprovalRequired = exports.ToolBlockedError = exports.ToolApprovalRequired = exports.AgentRunnerService = exports.ToolRegistryService = void 0;
|
|
3
|
+
exports.InMemoryAuthorizeStateStore = exports.ConnectorError = exports.ConnectorRegistryService = exports.OAuth2Service = exports.McpServerError = exports.McpServerService = exports.McpClientError = exports.McpClientService = exports.ChatTokenError = exports.ChatTokenService = exports.AgentJobWorker = exports.OrchestratorError = exports.OrchestratorService = exports.ApprovalCopywriterService = exports.AgentForbiddenError = exports.AgentService = exports.generateConversationCode = exports.ConversationNotFoundError = exports.ConversationService = exports.InMemoryPreparedStreamStore = exports.PreparedStreamError = exports.PreparedStreamService = exports.isToolBlockedError = exports.isToolApprovalRequired = exports.ToolBlockedError = exports.ToolApprovalRequired = exports.AgentRunnerService = exports.ToolRegistryService = void 0;
|
|
4
4
|
// Public service surface of @agentforge-io/core. AI runtime only — auth,
|
|
5
5
|
// identity, billing, infra, etc. have all moved to the host server.
|
|
6
6
|
var tool_registry_service_1 = require("./tool-registry.service");
|
|
@@ -24,6 +24,7 @@ Object.defineProperty(exports, "InMemoryPreparedStreamStore", { enumerable: true
|
|
|
24
24
|
var conversation_service_1 = require("./conversation.service");
|
|
25
25
|
Object.defineProperty(exports, "ConversationService", { enumerable: true, get: function () { return conversation_service_1.ConversationService; } });
|
|
26
26
|
Object.defineProperty(exports, "ConversationNotFoundError", { enumerable: true, get: function () { return conversation_service_1.ConversationNotFoundError; } });
|
|
27
|
+
Object.defineProperty(exports, "generateConversationCode", { enumerable: true, get: function () { return conversation_service_1.generateConversationCode; } });
|
|
27
28
|
var agent_service_1 = require("./agent.service");
|
|
28
29
|
Object.defineProperty(exports, "AgentService", { enumerable: true, get: function () { return agent_service_1.AgentService; } });
|
|
29
30
|
Object.defineProperty(exports, "AgentForbiddenError", { enumerable: true, get: function () { return agent_service_1.AgentForbiddenError; } });
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentforge-io/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.2",
|
|
4
4
|
"description": "Framework-free AI runtime SDK. Owns: agent loop (Anthropic), conversations, tools, streaming, agent-job queue, SdkHooks. Identity, billing, infra (email/uploads/secrets) live in the host's modules — not here.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"type": "commonjs",
|
|
6
7
|
"main": "dist/index.js",
|
|
7
8
|
"types": "dist/index.d.ts",
|
|
8
9
|
"exports": {
|