@agentforge-io/core 2.0.24 → 2.1.1

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 (88) hide show
  1. package/dist/factory.js +56 -1
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.js +7 -1
  4. package/dist/services/agent-runner.service.js +57 -4
  5. package/dist/services/agent.service.d.ts +21 -1
  6. package/dist/services/agent.service.js +42 -8
  7. package/dist/services/orchestrator.service.d.ts +40 -1
  8. package/dist/services/orchestrator.service.js +220 -0
  9. package/dist/types/agent.types.d.ts +31 -6
  10. package/package.json +1 -1
  11. package/dist/adapters/billing/billing-adapter.interface.d.ts +0 -41
  12. package/dist/adapters/billing/billing-adapter.interface.js +0 -5
  13. package/dist/adapters/billing/stripe/stripe.adapter.d.ts +0 -30
  14. package/dist/adapters/billing/stripe/stripe.adapter.js +0 -122
  15. package/dist/adapters/email/email-adapter.interface.d.ts +0 -25
  16. package/dist/adapters/email/email-adapter.interface.js +0 -6
  17. package/dist/adapters/email/noop.adapter.d.ts +0 -10
  18. package/dist/adapters/email/noop.adapter.js +0 -15
  19. package/dist/adapters/email/resend.adapter.d.ts +0 -8
  20. package/dist/adapters/email/resend.adapter.js +0 -39
  21. package/dist/adapters/upload/noop.adapter.d.ts +0 -9
  22. package/dist/adapters/upload/noop.adapter.js +0 -14
  23. package/dist/adapters/upload/s3.adapter.d.ts +0 -38
  24. package/dist/adapters/upload/s3.adapter.js +0 -69
  25. package/dist/adapters/upload/upload-adapter.interface.d.ts +0 -37
  26. package/dist/adapters/upload/upload-adapter.interface.js +0 -15
  27. package/dist/billing/index.d.ts +0 -12
  28. package/dist/billing/index.js +0 -28
  29. package/dist/domain/agent.d.ts +0 -59
  30. package/dist/domain/agent.js +0 -2
  31. package/dist/domain/api-key.d.ts +0 -28
  32. package/dist/domain/api-key.js +0 -2
  33. package/dist/domain/auth-identity.d.ts +0 -10
  34. package/dist/domain/auth-identity.js +0 -2
  35. package/dist/domain/email-token.d.ts +0 -11
  36. package/dist/domain/email-token.js +0 -2
  37. package/dist/domain/external-user.d.ts +0 -23
  38. package/dist/domain/external-user.js +0 -2
  39. package/dist/domain/plan.d.ts +0 -20
  40. package/dist/domain/plan.js +0 -2
  41. package/dist/domain/platform-secret.d.ts +0 -24
  42. package/dist/domain/platform-secret.js +0 -8
  43. package/dist/domain/refresh-token.d.ts +0 -15
  44. package/dist/domain/refresh-token.js +0 -2
  45. package/dist/domain/subscription.d.ts +0 -21
  46. package/dist/domain/subscription.js +0 -2
  47. package/dist/domain/tenant.d.ts +0 -21
  48. package/dist/domain/tenant.js +0 -2
  49. package/dist/domain/usage-record.d.ts +0 -15
  50. package/dist/domain/usage-record.js +0 -2
  51. package/dist/domain/user.d.ts +0 -43
  52. package/dist/domain/user.js +0 -2
  53. package/dist/services/agent-config.service.d.ts +0 -45
  54. package/dist/services/agent-config.service.js +0 -114
  55. package/dist/services/api-key.service.d.ts +0 -41
  56. package/dist/services/api-key.service.js +0 -80
  57. package/dist/services/auth.service.d.ts +0 -133
  58. package/dist/services/auth.service.js +0 -411
  59. package/dist/services/billing.service.d.ts +0 -67
  60. package/dist/services/billing.service.js +0 -254
  61. package/dist/services/email-templates.d.ts +0 -18
  62. package/dist/services/email-templates.js +0 -39
  63. package/dist/services/email.service.d.ts +0 -26
  64. package/dist/services/email.service.js +0 -42
  65. package/dist/services/errors.d.ts +0 -7
  66. package/dist/services/errors.js +0 -27
  67. package/dist/services/oauth.service.d.ts +0 -73
  68. package/dist/services/oauth.service.js +0 -174
  69. package/dist/services/plan.service.d.ts +0 -54
  70. package/dist/services/plan.service.js +0 -120
  71. package/dist/services/refresh-token.service.d.ts +0 -38
  72. package/dist/services/refresh-token.service.js +0 -73
  73. package/dist/services/secrets/crypto.d.ts +0 -37
  74. package/dist/services/secrets/crypto.js +0 -110
  75. package/dist/services/secrets/known-keys.d.ts +0 -38
  76. package/dist/services/secrets/known-keys.js +0 -50
  77. package/dist/services/secrets.service.d.ts +0 -91
  78. package/dist/services/secrets.service.js +0 -193
  79. package/dist/services/tenant-billing.service.d.ts +0 -121
  80. package/dist/services/tenant-billing.service.js +0 -290
  81. package/dist/services/tenant.service.d.ts +0 -54
  82. package/dist/services/tenant.service.js +0 -96
  83. package/dist/services/upload.service.d.ts +0 -37
  84. package/dist/services/upload.service.js +0 -84
  85. package/dist/services/usage.service.d.ts +0 -34
  86. package/dist/services/usage.service.js +0 -108
  87. package/dist/types/billing.types.d.ts +0 -82
  88. package/dist/types/billing.types.js +0 -3
@@ -165,29 +165,54 @@ export interface ApprovalCopyBundle {
165
165
  blockedBody: string;
166
166
  expiresPrefix: string;
167
167
  }
168
- export type StreamChunk = {
168
+ /**
169
+ * Per-chunk identity. When a Team orchestrator delegates a turn to a
170
+ * member, the streaming chunks coming out of the member carry the
171
+ * member's `agentId` here so the chat client can render a bubble with
172
+ * the member's avatar and name. Optional everywhere — when absent the
173
+ * client falls back to the session's primary agent identity (the
174
+ * default, non-team behaviour).
175
+ *
176
+ * The orchestrator's OWN chunks (the routing wrappers it speaks as
177
+ * itself) carry no `actingAgentId` so the client renders them as the
178
+ * team / orchestrator identity. The boundary between members is marked
179
+ * by `delegation_start` and `delegation_result`.
180
+ */
181
+ export interface ActingAgentTag {
182
+ /** Id of the agent producing this chunk. When absent, treat the
183
+ * chunk as coming from the session's primary agent (legacy
184
+ * non-team behaviour). */
185
+ actingAgentId?: string;
186
+ }
187
+ export type StreamChunk = ({
169
188
  type: 'text_delta';
170
189
  delta: string;
171
- } | {
190
+ } & ActingAgentTag) | ({
172
191
  type: 'tool_use_start';
173
192
  toolName: string;
174
193
  toolUseId: string;
175
- } | {
194
+ } & ActingAgentTag) | ({
176
195
  type: 'tool_result';
177
196
  toolName: string;
178
197
  result: string;
179
- } | {
198
+ } & ActingAgentTag) | {
180
199
  type: 'delegation_start';
181
200
  subAgentId: string;
182
201
  task: string;
202
+ /** Display name of the sub-agent. Lets the client render the
203
+ * "Routing to <name>…" hint without a separate roster fetch. */
204
+ subAgentName?: string;
205
+ /** Optional avatar URL of the sub-agent — used by the chat client
206
+ * to swap the avatar column for the member's bubble. */
207
+ subAgentAvatarUrl?: string;
183
208
  } | {
184
209
  type: 'delegation_result';
185
210
  subAgentId: string;
186
211
  result: string;
187
- } | {
212
+ } | ({
188
213
  type: 'usage';
189
214
  usage: TokenUsage;
190
- } | {
215
+ } & ActingAgentTag) | {
191
216
  /**
192
217
  * Emitted by the runtime when a tool dispatch hit
193
218
  * `ToolApprovalGate.check() → { kind: 'approval' }`. The stream
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentforge-io/core",
3
- "version": "2.0.24",
3
+ "version": "2.1.1",
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
6
  "main": "dist/index.js",
@@ -1,41 +0,0 @@
1
- import type { CheckoutSession, CreateCheckoutParams, CreateCustomerParams, CreateSubscriptionParams, SubscriptionResult, WebhookEvent } from '../../types';
2
- /**
3
- * IBillingAdapter defines the contract for payment providers.
4
- * Implement this interface to support any payment gateway (Stripe, Paddle, LemonSqueezy, etc.)
5
- */
6
- export interface IBillingAdapter {
7
- /**
8
- * Create a Stripe Checkout (or equivalent) session for a subscription or one-time payment.
9
- */
10
- createCheckoutSession(params: CreateCheckoutParams): Promise<CheckoutSession>;
11
- /**
12
- * Programmatically create a subscription (without hosted checkout).
13
- */
14
- createSubscription(params: CreateSubscriptionParams): Promise<SubscriptionResult>;
15
- /**
16
- * Cancel a subscription (optionally at period end).
17
- */
18
- cancelSubscription(subscriptionId: string, atPeriodEnd?: boolean): Promise<void>;
19
- /**
20
- * Handle an incoming webhook from the payment provider.
21
- * Returns a normalized WebhookEvent.
22
- */
23
- handleWebhook(payload: Buffer, signature: string): Promise<WebhookEvent>;
24
- /**
25
- * Generate a customer portal URL where users can manage their subscription.
26
- */
27
- getPortalUrl(customerId: string, returnUrl: string): Promise<string>;
28
- /**
29
- * Create a customer record in the payment provider.
30
- * Returns the provider-specific customer ID.
31
- */
32
- createCustomer(params: CreateCustomerParams): Promise<string>;
33
- /**
34
- * Get the current subscription status from the provider.
35
- */
36
- getSubscription(subscriptionId: string): Promise<SubscriptionResult & {
37
- status: string;
38
- }>;
39
- }
40
- /** Token to inject the billing adapter via NestJS DI */
41
- export declare const BILLING_ADAPTER = "BILLING_ADAPTER";
@@ -1,5 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BILLING_ADAPTER = void 0;
4
- /** Token to inject the billing adapter via NestJS DI */
5
- exports.BILLING_ADAPTER = 'BILLING_ADAPTER';
@@ -1,30 +0,0 @@
1
- import Stripe from 'stripe';
2
- import type { IBillingAdapter } from '../billing-adapter.interface';
3
- import type { CheckoutSession, CreateCheckoutParams, CreateCustomerParams, CreateSubscriptionParams, PlanDefinition, StripeConfig, SubscriptionResult, WebhookEvent } from '../../../types';
4
- interface MiniLogger {
5
- debug?: (m: string) => void;
6
- warn?: (m: string) => void;
7
- log?: (m: string) => void;
8
- }
9
- /**
10
- * StripeAdapter implements IBillingAdapter using the Stripe API.
11
- * Handles subscriptions, pay-per-use checkouts, webhooks, and customer portal.
12
- */
13
- export declare class StripeAdapter implements IBillingAdapter {
14
- private readonly logger;
15
- private readonly stripe;
16
- private readonly plans;
17
- private readonly webhookSecret;
18
- constructor(config: StripeConfig, plans?: PlanDefinition[], logger?: MiniLogger);
19
- createCustomer(params: CreateCustomerParams): Promise<string>;
20
- createCheckoutSession(params: CreateCheckoutParams): Promise<CheckoutSession>;
21
- createSubscription(params: CreateSubscriptionParams): Promise<SubscriptionResult>;
22
- cancelSubscription(subscriptionId: string, atPeriodEnd?: boolean): Promise<void>;
23
- getSubscription(subscriptionId: string): Promise<SubscriptionResult & {
24
- status: string;
25
- }>;
26
- getPortalUrl(customerId: string, returnUrl: string): Promise<string>;
27
- handleWebhook(payload: Buffer, signature: string): Promise<WebhookEvent>;
28
- getStripeInstance(): Stripe;
29
- }
30
- export {};
@@ -1,122 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.StripeAdapter = void 0;
7
- const stripe_1 = __importDefault(require("stripe"));
8
- /**
9
- * StripeAdapter implements IBillingAdapter using the Stripe API.
10
- * Handles subscriptions, pay-per-use checkouts, webhooks, and customer portal.
11
- */
12
- class StripeAdapter {
13
- constructor(config, plans = [], logger) {
14
- this.logger = logger ?? {};
15
- this.stripe = new stripe_1.default(config.secretKey, {
16
- apiVersion: '2023-10-16',
17
- });
18
- this.plans = plans;
19
- this.webhookSecret = config.webhookSecret;
20
- }
21
- // ─── Customer ─────────────────────────────────────────────────────────────
22
- async createCustomer(params) {
23
- const customer = await this.stripe.customers.create({
24
- email: params.email,
25
- name: params.name,
26
- metadata: params.metadata ?? {},
27
- });
28
- this.logger.debug?.(`Created Stripe customer: ${customer.id}`);
29
- return customer.id;
30
- }
31
- // ─── Checkout ─────────────────────────────────────────────────────────────
32
- async createCheckoutSession(params) {
33
- // Prefer the caller-provided stripePriceId (DB-backed plans flow).
34
- // Fall back to looking it up in the static plan list passed to the
35
- // constructor (legacy / single-tenant flow).
36
- const fallbackPlan = this.plans.find((p) => p.id === params.planId);
37
- const stripePriceId = params.stripePriceId ?? fallbackPlan?.stripePriceId;
38
- const interval = fallbackPlan?.interval ?? 'month';
39
- if (!stripePriceId) {
40
- throw new Error(`Plan "${params.planId}" has no Stripe price ID configured`);
41
- }
42
- const session = await this.stripe.checkout.sessions.create({
43
- mode: interval ? 'subscription' : 'payment',
44
- payment_method_types: ['card'],
45
- line_items: [{ price: stripePriceId, quantity: 1 }],
46
- success_url: params.successUrl,
47
- cancel_url: params.cancelUrl,
48
- metadata: {
49
- userId: params.userId,
50
- planId: params.planId,
51
- ...params.metadata,
52
- },
53
- subscription_data: interval
54
- ? { metadata: { userId: params.userId, planId: params.planId } }
55
- : undefined,
56
- });
57
- return { sessionId: session.id, url: session.url };
58
- }
59
- // ─── Subscription ─────────────────────────────────────────────────────────
60
- async createSubscription(params) {
61
- const subscription = await this.stripe.subscriptions.create({
62
- customer: params.customerId,
63
- items: [{ price: params.priceId }],
64
- trial_period_days: params.trialDays,
65
- payment_behavior: 'default_incomplete',
66
- expand: ['latest_invoice.payment_intent'],
67
- });
68
- return {
69
- subscriptionId: subscription.id,
70
- status: subscription.status,
71
- currentPeriodEnd: new Date(subscription.current_period_end * 1000),
72
- };
73
- }
74
- async cancelSubscription(subscriptionId, atPeriodEnd = true) {
75
- if (atPeriodEnd) {
76
- await this.stripe.subscriptions.update(subscriptionId, {
77
- cancel_at_period_end: true,
78
- });
79
- }
80
- else {
81
- await this.stripe.subscriptions.cancel(subscriptionId);
82
- }
83
- this.logger.log?.(`Subscription ${subscriptionId} cancelled (atPeriodEnd=${atPeriodEnd})`);
84
- }
85
- async getSubscription(subscriptionId) {
86
- const sub = await this.stripe.subscriptions.retrieve(subscriptionId);
87
- return {
88
- subscriptionId: sub.id,
89
- status: sub.status,
90
- currentPeriodEnd: new Date(sub.current_period_end * 1000),
91
- };
92
- }
93
- // ─── Customer Portal ──────────────────────────────────────────────────────
94
- async getPortalUrl(customerId, returnUrl) {
95
- const session = await this.stripe.billingPortal.sessions.create({
96
- customer: customerId,
97
- return_url: returnUrl,
98
- });
99
- return session.url;
100
- }
101
- // ─── Webhooks ─────────────────────────────────────────────────────────────
102
- async handleWebhook(payload, signature) {
103
- let event;
104
- try {
105
- event = this.stripe.webhooks.constructEvent(payload, signature, this.webhookSecret);
106
- }
107
- catch (err) {
108
- throw new Error(`Stripe webhook verification failed: ${err}`);
109
- }
110
- this.logger.debug?.(`Stripe webhook received: ${event.type}`);
111
- // Normalize to a generic WebhookEvent
112
- return {
113
- type: event.type,
114
- data: event.data.object,
115
- };
116
- }
117
- // ─── Helpers ──────────────────────────────────────────────────────────────
118
- getStripeInstance() {
119
- return this.stripe;
120
- }
121
- }
122
- exports.StripeAdapter = StripeAdapter;
@@ -1,25 +0,0 @@
1
- /**
2
- * Transport-agnostic contract for sending email.
3
- *
4
- * Default implementation is Resend. Plug in SES/SendGrid/SMTP/Mailgun/etc.
5
- * via `auth.email.provider = 'custom'` + `customAdapter` in config, or by
6
- * overriding the EMAIL_ADAPTER provider in the consuming app's module.
7
- */
8
- export interface EmailAdapter {
9
- send(message: EmailMessage): Promise<EmailSendResult>;
10
- }
11
- export interface EmailMessage {
12
- to: string;
13
- subject: string;
14
- html?: string;
15
- text?: string;
16
- /** Override the default `from` for this single send. */
17
- from?: string;
18
- /** Tags / metadata for analytics — adapter may ignore. */
19
- tags?: Record<string, string>;
20
- }
21
- export interface EmailSendResult {
22
- /** Provider's message id, when available. */
23
- id?: string;
24
- }
25
- export declare const EMAIL_ADAPTER = "AGENTFORGE_EMAIL_ADAPTER";
@@ -1,6 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EMAIL_ADAPTER = void 0;
4
- // String token (not Symbol) so it survives duplicate package instances and
5
- // works as a NestJS string-based DI provider out of the box.
6
- exports.EMAIL_ADAPTER = 'AGENTFORGE_EMAIL_ADAPTER';
@@ -1,10 +0,0 @@
1
- import type { EmailAdapter, EmailMessage, EmailSendResult } from './email-adapter.interface';
2
- /**
3
- * Used when no email config is provided. Throws on send so callers (verify,
4
- * password-reset) fail loudly instead of silently dropping. AuthService wraps
5
- * the call in try/catch where appropriate (e.g. password-reset to preserve
6
- * the always-200 anti-enumeration guarantee).
7
- */
8
- export declare class NoopEmailAdapter implements EmailAdapter {
9
- send(_message: EmailMessage): Promise<EmailSendResult>;
10
- }
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NoopEmailAdapter = void 0;
4
- /**
5
- * Used when no email config is provided. Throws on send so callers (verify,
6
- * password-reset) fail loudly instead of silently dropping. AuthService wraps
7
- * the call in try/catch where appropriate (e.g. password-reset to preserve
8
- * the always-200 anti-enumeration guarantee).
9
- */
10
- class NoopEmailAdapter {
11
- async send(_message) {
12
- throw new Error('Email features are not configured. Pass an EmailAdapter (e.g. ResendAdapter) when creating AgentForge.');
13
- }
14
- }
15
- exports.NoopEmailAdapter = NoopEmailAdapter;
@@ -1,8 +0,0 @@
1
- import type { EmailAdapter, EmailMessage, EmailSendResult } from './email-adapter.interface';
2
- export declare class ResendAdapter implements EmailAdapter {
3
- private readonly apiKey;
4
- private readonly defaultFrom;
5
- private readonly client;
6
- constructor(apiKey: string, defaultFrom: string);
7
- send(message: EmailMessage): Promise<EmailSendResult>;
8
- }
@@ -1,39 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ResendAdapter = void 0;
4
- const resend_1 = require("resend");
5
- class ResendAdapter {
6
- constructor(apiKey, defaultFrom) {
7
- this.apiKey = apiKey;
8
- this.defaultFrom = defaultFrom;
9
- if (!apiKey)
10
- throw new Error('ResendAdapter: apiKey is required');
11
- if (!defaultFrom) {
12
- throw new Error('ResendAdapter: defaultFrom is required (e.g. "App <noreply@yourdomain.com>")');
13
- }
14
- this.client = new resend_1.Resend(apiKey);
15
- }
16
- async send(message) {
17
- const payload = {
18
- from: message.from ?? this.defaultFrom,
19
- to: [message.to],
20
- subject: message.subject,
21
- };
22
- if (message.html)
23
- payload.html = message.html;
24
- if (message.text)
25
- payload.text = message.text;
26
- if (message.tags) {
27
- payload.tags = Object.entries(message.tags).map(([name, value]) => ({ name, value }));
28
- }
29
- if (!payload.html && !payload.text) {
30
- throw new Error('ResendAdapter: html or text is required');
31
- }
32
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
33
- const { data, error } = await this.client.emails.send(payload);
34
- if (error)
35
- throw new Error(`Resend: ${error.message}`);
36
- return { id: data?.id };
37
- }
38
- }
39
- exports.ResendAdapter = ResendAdapter;
@@ -1,9 +0,0 @@
1
- import type { UploadAdapter } from './upload-adapter.interface';
2
- /**
3
- * Used when no upload adapter is wired. Any sign request throws so the
4
- * controller returns a clear 501 to the client instead of pretending to
5
- * generate a URL that nobody can PUT to.
6
- */
7
- export declare class NoopUploadAdapter implements UploadAdapter {
8
- signUpload(): Promise<never>;
9
- }
@@ -1,14 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NoopUploadAdapter = void 0;
4
- /**
5
- * Used when no upload adapter is wired. Any sign request throws so the
6
- * controller returns a clear 501 to the client instead of pretending to
7
- * generate a URL that nobody can PUT to.
8
- */
9
- class NoopUploadAdapter {
10
- async signUpload() {
11
- throw new Error('Uploads are not configured. Pass an UploadAdapter (e.g. S3UploadAdapter) when creating AgentForge.');
12
- }
13
- }
14
- exports.NoopUploadAdapter = NoopUploadAdapter;
@@ -1,38 +0,0 @@
1
- import type { SignUploadInput, SignedUploadTarget, UploadAdapter } from './upload-adapter.interface';
2
- export interface S3UploadAdapterOptions {
3
- region: string;
4
- bucket: string;
5
- /** AWS access key id. Omit when running on an EC2/EKS instance with an IAM
6
- * role — the SDK's default credential chain picks it up. */
7
- accessKeyId?: string;
8
- secretAccessKey?: string;
9
- /**
10
- * Public URL prefix the object will be reachable at. Required because we
11
- * don't assume CloudFront vs raw S3 vs custom domain. The adapter
12
- * concatenates `${publicUrlBase}/${key}` for `publicUrl`.
13
- * Examples:
14
- * "https://my-bucket.s3.us-east-1.amazonaws.com"
15
- * "https://cdn.example.com"
16
- */
17
- publicUrlBase: string;
18
- /** PUT URL TTL in seconds. Short by default so the upload window can't be
19
- * reused by a leaked URL hours later. */
20
- signedUrlTtlSeconds?: number;
21
- }
22
- /**
23
- * S3 (or S3-compatible — R2, Spaces, MinIO) signed-upload adapter. Uses the
24
- * official AWS SDK v3 so it talks to any provider that implements the S3 API.
25
- *
26
- * Read access model: the adapter assumes objects are world-readable once
27
- * uploaded (`publicUrlBase` is GETtable). If your bucket is private and you
28
- * need signed GETs at read-time too, fork this adapter — the interface is
29
- * intentionally minimal.
30
- */
31
- export declare class S3UploadAdapter implements UploadAdapter {
32
- private readonly client;
33
- private readonly bucket;
34
- private readonly publicUrlBase;
35
- private readonly ttl;
36
- constructor(opts: S3UploadAdapterOptions);
37
- signUpload(input: SignUploadInput): Promise<SignedUploadTarget>;
38
- }
@@ -1,69 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.S3UploadAdapter = void 0;
4
- const client_s3_1 = require("@aws-sdk/client-s3");
5
- const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
6
- /**
7
- * S3 (or S3-compatible — R2, Spaces, MinIO) signed-upload adapter. Uses the
8
- * official AWS SDK v3 so it talks to any provider that implements the S3 API.
9
- *
10
- * Read access model: the adapter assumes objects are world-readable once
11
- * uploaded (`publicUrlBase` is GETtable). If your bucket is private and you
12
- * need signed GETs at read-time too, fork this adapter — the interface is
13
- * intentionally minimal.
14
- */
15
- class S3UploadAdapter {
16
- constructor(opts) {
17
- if (!opts.bucket)
18
- throw new Error('S3UploadAdapter: bucket is required');
19
- if (!opts.region)
20
- throw new Error('S3UploadAdapter: region is required');
21
- if (!opts.publicUrlBase) {
22
- throw new Error('S3UploadAdapter: publicUrlBase is required');
23
- }
24
- this.bucket = opts.bucket;
25
- this.publicUrlBase = opts.publicUrlBase.replace(/\/+$/, '');
26
- this.ttl = opts.signedUrlTtlSeconds ?? 300;
27
- this.client = new client_s3_1.S3Client({
28
- region: opts.region,
29
- // Only override credentials when explicit keys were passed. Otherwise
30
- // let the SDK fall through to its standard provider chain (env vars,
31
- // shared credentials file, IAM role, etc.) — that's what production
32
- // deployments on AWS expect.
33
- ...(opts.accessKeyId && opts.secretAccessKey
34
- ? {
35
- credentials: {
36
- accessKeyId: opts.accessKeyId,
37
- secretAccessKey: opts.secretAccessKey,
38
- },
39
- }
40
- : {}),
41
- });
42
- }
43
- async signUpload(input) {
44
- if (!input.key)
45
- throw new Error('signUpload: key is required');
46
- if (!input.contentType)
47
- throw new Error('signUpload: contentType is required');
48
- const cmd = new client_s3_1.PutObjectCommand({
49
- Bucket: this.bucket,
50
- Key: input.key,
51
- ContentType: input.contentType,
52
- // ContentLength can't be locked into a presigned URL on plain S3 — the
53
- // SDK only includes signed headers, and the client controls the
54
- // Content-Length header. Enforce size at the app layer (callers
55
- // check the response Content-Length on a HEAD after upload, or trust
56
- // the size they already validated client-side).
57
- });
58
- const uploadUrl = await (0, s3_request_presigner_1.getSignedUrl)(this.client, cmd, {
59
- expiresIn: this.ttl,
60
- });
61
- return {
62
- uploadUrl,
63
- publicUrl: `${this.publicUrlBase}/${input.key}`,
64
- key: input.key,
65
- expiresInSeconds: this.ttl,
66
- };
67
- }
68
- }
69
- exports.S3UploadAdapter = S3UploadAdapter;
@@ -1,37 +0,0 @@
1
- /**
2
- * Provider-agnostic contract for object storage. The default adapter signs
3
- * S3 PUTs; consumers running on R2, Backblaze B2, or Supabase Storage can
4
- * write their own and pass it to `createAgentForge({ adapters: { upload } })`.
5
- *
6
- * Direct-upload flow (signed PUT) instead of streaming through our backend:
7
- * 1. Client asks us for a signed URL.
8
- * 2. We validate intent (MIME, size, scope), generate a key, sign the PUT.
9
- * 3. Client uploads the bytes straight to the storage provider.
10
- * 4. The persisted `publicUrl` is what other clients read later.
11
- */
12
- export interface SignedUploadTarget {
13
- /** Pre-authorized URL the client PUTs the file body to. Short-lived. */
14
- uploadUrl: string;
15
- /** The eventual GETtable URL once the upload finishes. */
16
- publicUrl: string;
17
- /** Object key inside the bucket — useful when callers want to associate
18
- * the upload with a domain entity for later cleanup. */
19
- key: string;
20
- /** Seconds until `uploadUrl` stops being honored by the provider. */
21
- expiresInSeconds: number;
22
- }
23
- export interface SignUploadInput {
24
- /** Object key path. Adapter is free to add randomness for collision safety. */
25
- key: string;
26
- /** Content-Type the client will declare on PUT. Adapters MUST require the
27
- * same value at PUT time so a different MIME can't be smuggled in. */
28
- contentType: string;
29
- /** Max content-length the signed URL will accept. Soft hint to the adapter
30
- * — providers that don't support content-length pre-sign should still
31
- * return the URL and rely on app-level validation. */
32
- maxSizeBytes?: number;
33
- }
34
- export interface UploadAdapter {
35
- signUpload(input: SignUploadInput): Promise<SignedUploadTarget>;
36
- }
37
- export declare const UPLOAD_ADAPTER = "AGENTFORGE_UPLOAD_ADAPTER";
@@ -1,15 +0,0 @@
1
- "use strict";
2
- /**
3
- * Provider-agnostic contract for object storage. The default adapter signs
4
- * S3 PUTs; consumers running on R2, Backblaze B2, or Supabase Storage can
5
- * write their own and pass it to `createAgentForge({ adapters: { upload } })`.
6
- *
7
- * Direct-upload flow (signed PUT) instead of streaming through our backend:
8
- * 1. Client asks us for a signed URL.
9
- * 2. We validate intent (MIME, size, scope), generate a key, sign the PUT.
10
- * 3. Client uploads the bytes straight to the storage provider.
11
- * 4. The persisted `publicUrl` is what other clients read later.
12
- */
13
- Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.UPLOAD_ADAPTER = void 0;
15
- exports.UPLOAD_ADAPTER = 'AGENTFORGE_UPLOAD_ADAPTER';
@@ -1,12 +0,0 @@
1
- export type { Plan, NewPlan, PlanPatch, UsageLimits, } from '../domain/plan';
2
- export type { Subscription, NewSubscription, SubscriptionPatch, } from '../domain/subscription';
3
- export type { SubscriptionStatus, PaymentStatus, UserSubscription, UsageSummary, UsageRecord, CheckoutResult, PortalResult, BillingOverviewResult, InvoiceRecord, } from '../types/billing.types';
4
- export type { BillingProvider, BillingModel, BillingConfig, StripeConfig, PlanDefinition, CreditsConfig, } from '../types/config.types';
5
- export type { PlanRepository, SubscriptionRepository, UsageRecordRepository, } from '../repositories';
6
- export type { IBillingAdapter } from '../adapters/billing/billing-adapter.interface';
7
- export { BILLING_ADAPTER } from '../adapters/billing/billing-adapter.interface';
8
- export { StripeAdapter } from '../adapters/billing/stripe/stripe.adapter';
9
- export { UsageService, type UsageServiceOptions } from '../services/usage.service';
10
- export { PlanService } from '../services/plan.service';
11
- export { BillingService } from '../services/billing.service';
12
- export { TenantBillingService } from '../services/tenant-billing.service';
@@ -1,28 +0,0 @@
1
- "use strict";
2
- // ─── @agentforge/core/billing — narrow surface for commercial code ─────────
3
- //
4
- // This sub-path exposes ONLY the billing/commercial slice of the core
5
- // library. Consumers that don't want to pull in the full AI surface (and
6
- // don't want their type-checker to suggest AI internals on autocomplete)
7
- // can import from here.
8
- //
9
- // Architecturally the files still live alongside the AI code in
10
- // `packages/core/src/`; this is a narrowed re-export, not a physical move.
11
- // The goal is to make the seam visible and lintable today, and to make a
12
- // later physical extraction (to `apps/server/modules/billing/`, or to a
13
- // separate `@agentforge/billing` package) a localized change.
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.TenantBillingService = exports.BillingService = exports.PlanService = exports.UsageService = exports.StripeAdapter = exports.BILLING_ADAPTER = void 0;
16
- var billing_adapter_interface_1 = require("../adapters/billing/billing-adapter.interface");
17
- Object.defineProperty(exports, "BILLING_ADAPTER", { enumerable: true, get: function () { return billing_adapter_interface_1.BILLING_ADAPTER; } });
18
- var stripe_adapter_1 = require("../adapters/billing/stripe/stripe.adapter");
19
- Object.defineProperty(exports, "StripeAdapter", { enumerable: true, get: function () { return stripe_adapter_1.StripeAdapter; } });
20
- // ─── Services ──────────────────────────────────────────────────────────────
21
- var usage_service_1 = require("../services/usage.service");
22
- Object.defineProperty(exports, "UsageService", { enumerable: true, get: function () { return usage_service_1.UsageService; } });
23
- var plan_service_1 = require("../services/plan.service");
24
- Object.defineProperty(exports, "PlanService", { enumerable: true, get: function () { return plan_service_1.PlanService; } });
25
- var billing_service_1 = require("../services/billing.service");
26
- Object.defineProperty(exports, "BillingService", { enumerable: true, get: function () { return billing_service_1.BillingService; } });
27
- var tenant_billing_service_1 = require("../services/tenant-billing.service");
28
- Object.defineProperty(exports, "TenantBillingService", { enumerable: true, get: function () { return tenant_billing_service_1.TenantBillingService; } });