@almadar/integrations 2.41.0 → 2.42.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.
@@ -1,4 +1,4 @@
1
- import { LogMeta } from '@almadar/core';
1
+ import { LogMeta, ServiceHostPorts } from '@almadar/core';
2
2
 
3
3
  /**
4
4
  * Core types for Almadar integrations
@@ -138,6 +138,8 @@ interface IntegrationCallContext {
138
138
  principal?: string;
139
139
  /** The caller's roster role, from the same identity entity-ACL enforces against. */
140
140
  role?: string;
141
+ /** The running app, lent for this call as the caller (`llm call-tools`). */
142
+ host?: ServiceHostPorts;
141
143
  }
142
144
  /**
143
145
  * Factory for creating and managing integration instances
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { e as IntegrationLogger, c as IntegrationErrorCode, a as IntegrationConfig, B as BaseIntegration, d as IntegrationFactory, g as IntegrationParams, h as IntegrationResult, I as IntegrationCallContext } from './BaseIntegration-CWdas-N_.js';
2
- export { b as IntegrationError, f as IntegrationParamValue, U as UnknownActionError, V as ValidationError, i as ValidationResult, j as getIntegrationFactory, r as resetIntegrationFactory, v as validateParams } from './BaseIntegration-CWdas-N_.js';
3
- import { e as CredentialStore, d as CredentialPersistence, H as HookDeclaration } from './store-DG5OGiuQ.js';
4
- export { A as ArxivActions, C as CLIActions, a as CREDENTIAL_ENTITY_TYPE, b as CREDENTIAL_MASTER_KEY_ENV, c as CredentialEntry, D as DatabaseActions, f as DatabaseDriver, g as DatabaseQueryParamValue, h as DatabaseQueryParams, i as DatabaseQueryResult, j as DatabaseRow, k as DeepAgentActions, l as DockerActions, E as EmailActions, G as GitHubActions, I as IconifyActions, m as IntegrationActionName, n as IntegrationContracts, o as IntegrationName, L as LLMIntegrationActions, M as MLActions, O as OAuthActions, p as OtelActions, Q as QueueActions, R as RedisActions, S as StorageActions, q as StripeActions, T as TwilioActions, W as WebhookActions, r as WikimediaActions, Y as YouTubeActions, s as allCredentialEnvVars, t as declaredCredentialEnvVars, u as serviceHooks } from './store-DG5OGiuQ.js';
5
- import { LogMeta, EntityRow, EventPayload } from '@almadar/core';
1
+ import { e as IntegrationLogger, c as IntegrationErrorCode, a as IntegrationConfig, B as BaseIntegration, d as IntegrationFactory, g as IntegrationParams, h as IntegrationResult, I as IntegrationCallContext } from './BaseIntegration-D_iNTesu.js';
2
+ export { b as IntegrationError, f as IntegrationParamValue, U as UnknownActionError, V as ValidationError, i as ValidationResult, j as getIntegrationFactory, r as resetIntegrationFactory, v as validateParams } from './BaseIntegration-D_iNTesu.js';
3
+ import { e as CredentialStore, d as CredentialPersistence, H as HookDeclaration } from './store-DcennSSh.js';
4
+ export { A as ArxivActions, C as CLIActions, a as CREDENTIAL_ENTITY_TYPE, b as CREDENTIAL_MASTER_KEY_ENV, c as CredentialEntry, D as DatabaseActions, f as DatabaseDriver, g as DatabaseQueryParamValue, h as DatabaseQueryParams, i as DatabaseQueryResult, j as DatabaseRow, k as DeepAgentActions, l as DockerActions, E as EmailActions, G as GitHubActions, I as IconifyActions, m as IntegrationActionName, n as IntegrationContracts, o as IntegrationName, L as LLMIntegrationActions, M as MLActions, O as OAuthActions, p as OtelActions, Q as QueueActions, R as RedisActions, S as StorageActions, q as StripeActions, T as TwilioActions, W as WebhookActions, r as WikimediaActions, Y as YouTubeActions, s as allCredentialEnvVars, t as declaredCredentialEnvVars, u as serviceHooks } from './store-DcennSSh.js';
5
+ import { LogMeta, EntityRow, EventPayload, ServiceHostPorts } from '@almadar/core';
6
+ import { AgentChatMessage, AgentTool, AgentStep, ToolCallingClient } from '@almadar/llm';
6
7
  export { GitHubIntegration } from './integrations/github/index.js';
7
8
 
8
9
  /**
@@ -620,16 +621,6 @@ declare class EsignIntegration extends BaseIntegration {
620
621
  private downloadDocument;
621
622
  }
622
623
 
623
- /**
624
- * LLM integration using @almadar/llm
625
- *
626
- * Provides 5 actions:
627
- * - generate: Generate text content from a prompt
628
- * - classify: Classify text into predefined categories
629
- * - extract: Extract structured data from text using a schema
630
- * - summarize: Summarize long text content
631
- * - embed: Generate embeddings for an array of texts
632
- */
633
624
  declare class LLMIntegration extends BaseIntegration {
634
625
  private client;
635
626
  private embeddings;
@@ -648,14 +639,41 @@ declare class LLMIntegration extends BaseIntegration {
648
639
  * `EMBEDDING_PROVIDER` / `EMBEDDING_MODEL` / `EMBEDDING_API_KEY`.
649
640
  */
650
641
  private getEmbeddings;
651
- execute(action: string, params: IntegrationParams): Promise<IntegrationResult>;
642
+ execute(action: string, params: IntegrationParams, context?: IntegrationCallContext): Promise<IntegrationResult>;
652
643
  private generate;
653
644
  private classify;
654
645
  private extract;
655
646
  private summarize;
647
+ private callTools;
656
648
  private embed;
657
649
  }
658
650
 
651
+ /**
652
+ * `llm call-tools`: the model operates the running app AS THE CALLER through the
653
+ * host's ports. Each allowlisted input is one tool (its declared payload is the
654
+ * schema, its `@description` the text); each allowlisted entity is one read tool.
655
+ * Every tool call is an ordinary dispatch on the host (guards, policies and
656
+ * listens all apply) whose response goes back to the model, until it replies.
657
+ */
658
+
659
+ interface ToolLoopRequest {
660
+ messages: readonly AgentChatMessage[];
661
+ tools: readonly AgentTool[];
662
+ instructions?: string;
663
+ maxSteps?: number;
664
+ }
665
+ interface ToolLoopResult {
666
+ reply: string;
667
+ steps: AgentStep[];
668
+ usage: {
669
+ promptTokens: number;
670
+ completionTokens: number;
671
+ totalTokens: number;
672
+ modelCalls: number;
673
+ };
674
+ }
675
+ declare function runToolLoop(client: ToolCallingClient, host: ServiceHostPorts, request: ToolLoopRequest): Promise<ToolLoopResult>;
676
+
659
677
  declare class MLIntegration extends BaseIntegration {
660
678
  private readonly eventsUrl;
661
679
  private readonly timeoutMs;
@@ -1085,4 +1103,4 @@ declare class RiggerIntegration extends BaseIntegration {
1085
1103
  private generate;
1086
1104
  }
1087
1105
 
1088
- export { AccountingIntegration, type AlmadarCheckoutSession, type AlmadarCustomer, type AlmadarInvoiceFailure, type AlmadarInvoicePayment, type AlmadarPortalSession, type AlmadarStripeEvent, type AlmadarStripeEventOk, type AlmadarSubscription, type AlmadarSubscriptionStatus, type AlmadarTier, ArxivIntegration, type ArxivResult, BankingIntegration, BaseIntegration, CLIIntegration, CREDENTIALS_FILE_ENV, CalendarIntegration, type CancelSubscriptionInput, ConsoleLogger, type CreateCheckoutInput, type CreateCustomerInput, type CreatePortalInput, CredentialPersistence, CredentialStore, CredentialsIntegration, DatabaseIntegration, DeepAgentIntegration, DockerIntegration, DriveIntegration, EmailIntegration, EsignIntegration, FileCredentialPersistence, HookDeclaration, type HookProviderInput, type HookProviderResult, IconifyIntegration, InMemoryPendingGrantStore, IntegrationCallContext, IntegrationConfig, type IntegrationConstructor, IntegrationErrorCode, IntegrationFactory, IntegrationLogger, IntegrationParams, IntegrationResult, LLMIntegration, MLIntegration, MetaAdsIntegration, type OAuthAuthorizeInput, OAuthGrantNotFoundError, OAuthIntegration, type OAuthProvider, OAuthSubjectMismatchError, type OAuthTokenInput, type OAuthTokenResult, OtelIntegration, type PendingAuthorization, type PendingGrantStore, PushIntegration, QueueIntegration, RedisIntegration, type RegisteredHookProvider, type RetryConfig, RiggerIntegration, type SqlGuardResult, StorageIntegration, StripeIntegration, type StripePriceMap, TwilioIntegration, type UpdateSubscriptionInput, type VerifyAndParseInput, WebhookIntegration, WikimediaIntegration, YouTubeIntegration, allHookDeclarations, assertReadOnlySelect, getActiveFactory, getInstalledCredentialStore, getIntegration, getRegisteredIntegrations, googleCalendarHookProvider, installActiveFactory, installCredentialStore, installPendingGrantStore, isKnownIntegration, parseCalendarPushNotification, registerIntegration, registeredHookProviders, resolveCredentialRef, runWithCredentialScope, uninstallCredentialStore, verifyAndParseStripeEvent, withRetry };
1106
+ export { AccountingIntegration, type AlmadarCheckoutSession, type AlmadarCustomer, type AlmadarInvoiceFailure, type AlmadarInvoicePayment, type AlmadarPortalSession, type AlmadarStripeEvent, type AlmadarStripeEventOk, type AlmadarSubscription, type AlmadarSubscriptionStatus, type AlmadarTier, ArxivIntegration, type ArxivResult, BankingIntegration, BaseIntegration, CLIIntegration, CREDENTIALS_FILE_ENV, CalendarIntegration, type CancelSubscriptionInput, ConsoleLogger, type CreateCheckoutInput, type CreateCustomerInput, type CreatePortalInput, CredentialPersistence, CredentialStore, CredentialsIntegration, DatabaseIntegration, DeepAgentIntegration, DockerIntegration, DriveIntegration, EmailIntegration, EsignIntegration, FileCredentialPersistence, HookDeclaration, type HookProviderInput, type HookProviderResult, IconifyIntegration, InMemoryPendingGrantStore, IntegrationCallContext, IntegrationConfig, type IntegrationConstructor, IntegrationErrorCode, IntegrationFactory, IntegrationLogger, IntegrationParams, IntegrationResult, LLMIntegration, MLIntegration, MetaAdsIntegration, type OAuthAuthorizeInput, OAuthGrantNotFoundError, OAuthIntegration, type OAuthProvider, OAuthSubjectMismatchError, type OAuthTokenInput, type OAuthTokenResult, OtelIntegration, type PendingAuthorization, type PendingGrantStore, PushIntegration, QueueIntegration, RedisIntegration, type RegisteredHookProvider, type RetryConfig, RiggerIntegration, type SqlGuardResult, StorageIntegration, StripeIntegration, type StripePriceMap, type ToolLoopRequest, type ToolLoopResult, TwilioIntegration, type UpdateSubscriptionInput, type VerifyAndParseInput, WebhookIntegration, WikimediaIntegration, YouTubeIntegration, allHookDeclarations, assertReadOnlySelect, getActiveFactory, getInstalledCredentialStore, getIntegration, getRegisteredIntegrations, googleCalendarHookProvider, installActiveFactory, installCredentialStore, installPendingGrantStore, isKnownIntegration, parseCalendarPushNotification, registerIntegration, registeredHookProviders, resolveCredentialRef, runToolLoop, runWithCredentialScope, uninstallCredentialStore, verifyAndParseStripeEvent, withRetry };
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ import webpush from 'web-push';
13
13
  import { Readable } from 'stream';
14
14
  import { getAvailableProvider, LLMClient, EmbeddingClient } from '@almadar/llm';
15
15
  import { z } from 'zod';
16
+ import { findInputByAddress, payloadSchemaToJsonSchema, EventPayloadSchema } from '@almadar/core';
16
17
  import { execSync, spawn } from 'child_process';
17
18
  import { tmpdir } from 'os';
18
19
  import * as oidc from 'openid-client';
@@ -2458,6 +2459,123 @@ var EsignIntegration = class extends BaseIntegration {
2458
2459
  }
2459
2460
  };
2460
2461
  registerIntegration("esign", EsignIntegration);
2462
+ var DEFAULT_MAX_STEPS = 8;
2463
+ var TOOL_NAME = /^[a-zA-Z0-9_-]{1,64}$/;
2464
+ function toolName(raw) {
2465
+ if (!TOOL_NAME.test(raw)) {
2466
+ throw new Error(`call-tools: tool name '${raw}' is not a valid tool name (letters, digits, _ and -, at most 64)`);
2467
+ }
2468
+ return raw;
2469
+ }
2470
+ function buildTools(host, tools) {
2471
+ const inputs = host.inputs();
2472
+ const out = /* @__PURE__ */ new Map();
2473
+ for (const tool of tools) {
2474
+ if (tool.event !== void 0) {
2475
+ const input = findInputByAddress(inputs, tool.event, host.caller);
2476
+ if (!input) throw new Error(`call-tools: '${tool.event}' is not a declared external input`);
2477
+ const name = toolName(tool.event.split(".").join("__"));
2478
+ out.set(name, {
2479
+ def: {
2480
+ type: "function",
2481
+ function: { name, description: input.description ?? tool.event, parameters: payloadSchemaToJsonSchema(input.payloadSchema) }
2482
+ },
2483
+ target: { kind: "input", address: tool.event, input }
2484
+ });
2485
+ } else if (tool.read !== void 0) {
2486
+ const name = toolName(`read__${tool.read}`);
2487
+ out.set(name, {
2488
+ def: {
2489
+ type: "function",
2490
+ function: { name, description: `Read the ${tool.read} rows you may see`, parameters: { type: "object", properties: {} } }
2491
+ },
2492
+ target: { kind: "read", entity: tool.read }
2493
+ });
2494
+ }
2495
+ }
2496
+ return out;
2497
+ }
2498
+ function dispatchFailure(response) {
2499
+ if (response.rejections && response.rejections.length > 0) return response.rejections.map((r) => r.code).join(", ");
2500
+ if (response.guardFailed !== void 0) return `guard failed: ${response.guardFailed}`;
2501
+ if (!response.success) return response.error ?? "dispatch failed";
2502
+ const failed = (response.effectResults ?? []).find((r) => !r.success);
2503
+ if (failed) return failed.error ?? `${failed.effect} failed`;
2504
+ if (!response.transitioned) return "no transition";
2505
+ return void 0;
2506
+ }
2507
+ function parseArgs(args) {
2508
+ let value;
2509
+ try {
2510
+ value = JSON.parse(args === "" ? "{}" : args);
2511
+ } catch {
2512
+ value = void 0;
2513
+ }
2514
+ return EventPayloadSchema.safeParse(value);
2515
+ }
2516
+ async function runToolLoop(client, host, request) {
2517
+ const tools = buildTools(host, request.tools);
2518
+ const defs = [...tools.values()].map((t) => t.def);
2519
+ const maxSteps = request.maxSteps ?? DEFAULT_MAX_STEPS;
2520
+ const conversation = [
2521
+ ...request.instructions !== void 0 ? [{ role: "system", content: request.instructions }] : [],
2522
+ ...request.messages.map((m) => ({ role: m.role, content: m.content }))
2523
+ ];
2524
+ const steps = [];
2525
+ const usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0, modelCalls: 0 };
2526
+ while (usage.modelCalls < maxSteps) {
2527
+ const turn = await client.callWithTools({ messages: conversation, tools: defs });
2528
+ usage.modelCalls += 1;
2529
+ if (turn.usage) {
2530
+ usage.promptTokens += turn.usage.promptTokens;
2531
+ usage.completionTokens += turn.usage.completionTokens;
2532
+ usage.totalTokens += turn.usage.totalTokens;
2533
+ }
2534
+ conversation.push(turn.message);
2535
+ const calls = turn.message.tool_calls ?? [];
2536
+ if (calls.length === 0) return { reply: turn.message.content ?? "", steps, usage };
2537
+ for (const call of calls) {
2538
+ const args = call.function.arguments;
2539
+ const tool = tools.get(call.function.name);
2540
+ let content;
2541
+ if (!tool) {
2542
+ steps.push({ kind: "invalid", target: call.function.name, args, ok: false, detail: "not an allowed tool" });
2543
+ content = JSON.stringify({ error: `'${call.function.name}' is not one of your tools` });
2544
+ } else if (tool.target.kind === "read") {
2545
+ const rows = await host.read(tool.target.entity);
2546
+ steps.push({ kind: "read", target: tool.target.entity, args, ok: true });
2547
+ content = JSON.stringify({ rows });
2548
+ } else {
2549
+ const parsed = parseArgs(args);
2550
+ if (!parsed.success) {
2551
+ steps.push({ kind: "input", target: tool.target.address, args, ok: false, detail: "arguments are not a JSON object" });
2552
+ content = JSON.stringify({ error: "arguments must be a JSON object" });
2553
+ } else {
2554
+ const { input } = tool.target;
2555
+ const response = await host.dispatchInput(input.orbital, {
2556
+ targetTrait: input.trait,
2557
+ event: input.event,
2558
+ payload: parsed.data
2559
+ });
2560
+ const detail = dispatchFailure(response);
2561
+ steps.push({ kind: "input", target: tool.target.address, args, ok: detail === void 0, ...detail !== void 0 ? { detail } : {} });
2562
+ content = JSON.stringify(response);
2563
+ }
2564
+ }
2565
+ conversation.push({ role: "tool", content, tool_call_id: call.id });
2566
+ }
2567
+ }
2568
+ throw new Error(`call-tools: no reply after ${maxSteps} model calls`);
2569
+ }
2570
+
2571
+ // src/integrations/llm/index.ts
2572
+ var CallToolsParamsSchema = z.object({
2573
+ messages: z.array(z.object({ role: z.enum(["user", "assistant"]), content: z.string() })),
2574
+ tools: z.array(z.object({ event: z.string().optional(), read: z.string().optional() })),
2575
+ instructions: z.string().optional(),
2576
+ maxSteps: z.number().int().positive().optional(),
2577
+ model: z.string().optional()
2578
+ });
2461
2579
  var LLMIntegration = class extends BaseIntegration {
2462
2580
  constructor(config) {
2463
2581
  super(config);
@@ -2498,7 +2616,7 @@ var LLMIntegration = class extends BaseIntegration {
2498
2616
  }
2499
2617
  return this.embeddings;
2500
2618
  }
2501
- async execute(action, params) {
2619
+ async execute(action, params, context) {
2502
2620
  const validation = this.validateParams(action, params);
2503
2621
  if (!validation.valid) return this.validationFailure(action, validation.errors);
2504
2622
  const startTime = Date.now();
@@ -2520,6 +2638,10 @@ var LLMIntegration = class extends BaseIntegration {
2520
2638
  case "embed":
2521
2639
  data = await this.executeWithRetry(() => this.embed(params));
2522
2640
  break;
2641
+ // Never retried: a retry would re-fire inputs the first attempt already fired.
2642
+ case "call-tools":
2643
+ data = await this.callTools(params, context);
2644
+ break;
2523
2645
  default:
2524
2646
  throw new UnknownActionError(this.config.name, action);
2525
2647
  }
@@ -2610,6 +2732,14 @@ Return ONLY valid JSON matching the schema.`,
2610
2732
  });
2611
2733
  return result;
2612
2734
  }
2735
+ async callTools(params, context) {
2736
+ if (!context?.host) {
2737
+ throw new Error("llm.call-tools needs host ports: run it from a host that lends the running app (call-service on a server)");
2738
+ }
2739
+ const request = CallToolsParamsSchema.parse(params);
2740
+ const client = request.model !== void 0 ? new LLMClient({ provider: this.provider, model: request.model }) : this.getClient();
2741
+ return runToolLoop(client, context.host, request);
2742
+ }
2613
2743
  async embed(params) {
2614
2744
  const { texts } = params;
2615
2745
  if (!Array.isArray(texts)) {
@@ -5837,6 +5967,6 @@ var RiggerIntegration = class extends BaseIntegration {
5837
5967
  };
5838
5968
  registerIntegration("rigger", RiggerIntegration);
5839
5969
 
5840
- export { AccountingIntegration, ArxivIntegration, BankingIntegration, BaseIntegration, CLIIntegration, CREDENTIALS_FILE_ENV, CREDENTIAL_ENTITY_TYPE, CREDENTIAL_MASTER_KEY_ENV, CalendarIntegration, ConsoleLogger, CredentialStore, CredentialsIntegration, DatabaseIntegration, DeepAgentIntegration, DockerIntegration, DriveIntegration, EmailIntegration, EsignIntegration, FileCredentialPersistence, GitHubIntegration, IconifyIntegration, InMemoryPendingGrantStore, IntegrationError, IntegrationFactory, LLMIntegration, MLIntegration, MetaAdsIntegration, OAuthGrantNotFoundError, OAuthIntegration, OAuthSubjectMismatchError, OtelIntegration, PushIntegration, QueueIntegration, RedisIntegration, RiggerIntegration, StorageIntegration, StripeIntegration, TwilioIntegration, UnknownActionError, WebhookIntegration, WikimediaIntegration, YouTubeIntegration, allCredentialEnvVars, allHookDeclarations, assertReadOnlySelect, declaredCredentialEnvVars, getActiveFactory, getInstalledCredentialStore, getIntegration, getIntegrationFactory, getRegisteredIntegrations, googleCalendarHookProvider, installActiveFactory, installCredentialStore, installPendingGrantStore, isKnownIntegration, parseCalendarPushNotification, registerIntegration, registeredHookProviders, resetIntegrationFactory, resolveCredentialRef, runWithCredentialScope, serviceHooks, uninstallCredentialStore, validateParams, verifyAndParseStripeEvent, withRetry };
5970
+ export { AccountingIntegration, ArxivIntegration, BankingIntegration, BaseIntegration, CLIIntegration, CREDENTIALS_FILE_ENV, CREDENTIAL_ENTITY_TYPE, CREDENTIAL_MASTER_KEY_ENV, CalendarIntegration, ConsoleLogger, CredentialStore, CredentialsIntegration, DatabaseIntegration, DeepAgentIntegration, DockerIntegration, DriveIntegration, EmailIntegration, EsignIntegration, FileCredentialPersistence, GitHubIntegration, IconifyIntegration, InMemoryPendingGrantStore, IntegrationError, IntegrationFactory, LLMIntegration, MLIntegration, MetaAdsIntegration, OAuthGrantNotFoundError, OAuthIntegration, OAuthSubjectMismatchError, OtelIntegration, PushIntegration, QueueIntegration, RedisIntegration, RiggerIntegration, StorageIntegration, StripeIntegration, TwilioIntegration, UnknownActionError, WebhookIntegration, WikimediaIntegration, YouTubeIntegration, allCredentialEnvVars, allHookDeclarations, assertReadOnlySelect, declaredCredentialEnvVars, getActiveFactory, getInstalledCredentialStore, getIntegration, getIntegrationFactory, getRegisteredIntegrations, googleCalendarHookProvider, installActiveFactory, installCredentialStore, installPendingGrantStore, isKnownIntegration, parseCalendarPushNotification, registerIntegration, registeredHookProviders, resetIntegrationFactory, resolveCredentialRef, runToolLoop, runWithCredentialScope, serviceHooks, uninstallCredentialStore, validateParams, verifyAndParseStripeEvent, withRetry };
5841
5971
  //# sourceMappingURL=index.js.map
5842
5972
  //# sourceMappingURL=index.js.map