@almadar/integrations 2.42.0 → 2.43.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,5 +1,5 @@
1
- import { g as IntegrationParams, I as IntegrationCallContext, d as IntegrationFactory } from '../BaseIntegration-D_iNTesu.js';
2
- import { o as IntegrationName, m as IntegrationActionName, n as IntegrationContracts, e as CredentialStore } from '../store-DcennSSh.js';
1
+ import { g as IntegrationParams, I as IntegrationCallContext, d as IntegrationFactory } from '../BaseIntegration-Dgwn1ZR6.js';
2
+ import { o as IntegrationName, m as IntegrationActionName, n as IntegrationContracts, e as CredentialStore } from '../store-DP3gfEfJ.js';
3
3
  import '@almadar/core';
4
4
  import '@almadar/llm';
5
5
 
@@ -13,7 +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
+ import { findInputByAddress, payloadSchemaToJsonSchema, traceActivityPayload, EventPayloadSchema } from '@almadar/core';
17
17
  import { execSync, spawn } from 'child_process';
18
18
  import { tmpdir } from 'os';
19
19
  import * as oidc from 'openid-client';
@@ -410,6 +410,8 @@ var IntegrationFactory = class {
410
410
  constructor() {
411
411
  this.instances = /* @__PURE__ */ new Map();
412
412
  this.configs = /* @__PURE__ */ new Map();
413
+ /** Names whose app-wide instance was registered directly (mock infrastructure). */
414
+ this.registered = /* @__PURE__ */ new Set();
413
415
  }
414
416
  /**
415
417
  * Configure an integration (doesn't instantiate yet). A `principal` scopes
@@ -424,7 +426,8 @@ var IntegrationFactory = class {
424
426
  * back to the app-wide config when no per-principal config exists.
425
427
  */
426
428
  get(name, principal) {
427
- const key = instanceKey(name, principal);
429
+ const registered = this.registered.has(name) && !this.configs.has(instanceKey(name, principal));
430
+ const key = registered ? name : instanceKey(name, principal);
428
431
  const cached = this.instances.get(key);
429
432
  if (cached) {
430
433
  return cached;
@@ -468,6 +471,7 @@ var IntegrationFactory = class {
468
471
  * Register an integration instance directly (used by mock infrastructure)
469
472
  */
470
473
  registerInstance(name, instance, principal) {
474
+ if (principal === void 0) this.registered.add(name);
471
475
  this.instances.set(instanceKey(name, principal), instance);
472
476
  }
473
477
  /**
@@ -478,8 +482,10 @@ var IntegrationFactory = class {
478
482
  invalidate(name) {
479
483
  if (name === void 0) {
480
484
  this.instances.clear();
485
+ this.registered.clear();
481
486
  return;
482
487
  }
488
+ this.registered.delete(name);
483
489
  for (const key of this.instances.keys()) {
484
490
  if (key === name || key.startsWith(`${name}\0`)) {
485
491
  this.instances.delete(key);
@@ -491,6 +497,7 @@ var IntegrationFactory = class {
491
497
  */
492
498
  clear() {
493
499
  this.instances.clear();
500
+ this.registered.clear();
494
501
  }
495
502
  /**
496
503
  * Clear all instances and configs
@@ -498,6 +505,7 @@ var IntegrationFactory = class {
498
505
  reset() {
499
506
  this.instances.clear();
500
507
  this.configs.clear();
508
+ this.registered.clear();
501
509
  }
502
510
  };
503
511
  var installedStore = null;
@@ -2028,7 +2036,7 @@ function parseArgs(args) {
2028
2036
  }
2029
2037
  return EventPayloadSchema.safeParse(value);
2030
2038
  }
2031
- async function runToolLoop(client, host, request) {
2039
+ async function runToolLoop(client, host, request, model, now = Date.now) {
2032
2040
  const tools = buildTools(host, request.tools);
2033
2041
  const defs = [...tools.values()].map((t) => t.def);
2034
2042
  const maxSteps = request.maxSteps ?? DEFAULT_MAX_STEPS;
@@ -2036,10 +2044,17 @@ async function runToolLoop(client, host, request) {
2036
2044
  ...request.instructions !== void 0 ? [{ role: "system", content: request.instructions }] : [],
2037
2045
  ...request.messages.map((m) => ({ role: m.role, content: m.content }))
2038
2046
  ];
2047
+ const userPrompt = [...request.messages].reverse().find((m) => m.role === "user")?.content ?? "";
2039
2048
  const steps = [];
2049
+ const record = (activity) => {
2050
+ steps.push(activity);
2051
+ host.message(traceActivityPayload(activity));
2052
+ };
2040
2053
  const usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0, modelCalls: 0 };
2041
2054
  while (usage.modelCalls < maxSteps) {
2055
+ const started = now();
2042
2056
  const turn = await client.callWithTools({ messages: conversation, tools: defs });
2057
+ const ended = now();
2043
2058
  usage.modelCalls += 1;
2044
2059
  if (turn.usage) {
2045
2060
  usage.promptTokens += turn.usage.promptTokens;
@@ -2048,23 +2063,41 @@ async function runToolLoop(client, host, request) {
2048
2063
  }
2049
2064
  conversation.push(turn.message);
2050
2065
  const calls = turn.message.tool_calls ?? [];
2066
+ record({
2067
+ type: "llm_response",
2068
+ content: turn.message.content ?? "",
2069
+ llm: {
2070
+ service: "llm",
2071
+ provider: model.provider,
2072
+ model: model.model,
2073
+ systemPrompt: request.instructions ?? "",
2074
+ userPrompt,
2075
+ ...calls.length > 0 ? { toolCallsJson: JSON.stringify(calls) } : {},
2076
+ durationMs: ended - started,
2077
+ ...turn.usage ? { promptTokens: turn.usage.promptTokens, completionTokens: turn.usage.completionTokens } : {}
2078
+ },
2079
+ timestamp: ended
2080
+ });
2051
2081
  if (calls.length === 0) return { reply: turn.message.content ?? "", steps, usage };
2052
2082
  for (const call of calls) {
2053
2083
  const args = call.function.arguments;
2054
2084
  const tool = tools.get(call.function.name);
2085
+ const kind = tool === void 0 ? "invalid" : tool.target.kind;
2086
+ const label = tool === void 0 ? call.function.name : tool.target.kind === "input" ? tool.target.address : tool.target.entity;
2087
+ record({ type: "tool_call", tool: label, kind, argsText: args, timestamp: now() });
2055
2088
  let content;
2056
2089
  if (!tool) {
2057
- steps.push({ kind: "invalid", target: call.function.name, args, ok: false, detail: "not an allowed tool" });
2058
2090
  content = JSON.stringify({ error: `'${call.function.name}' is not one of your tools` });
2091
+ record({ type: "tool_result", tool: label, kind, success: false, detail: "not an allowed tool", resultText: content, timestamp: now() });
2059
2092
  } else if (tool.target.kind === "read") {
2060
2093
  const rows = await host.read(tool.target.entity);
2061
- steps.push({ kind: "read", target: tool.target.entity, args, ok: true });
2062
2094
  content = JSON.stringify({ rows });
2095
+ record({ type: "tool_result", tool: label, kind, success: true, rows: rows.length, resultText: content, timestamp: now() });
2063
2096
  } else {
2064
2097
  const parsed = parseArgs(args);
2065
2098
  if (!parsed.success) {
2066
- steps.push({ kind: "input", target: tool.target.address, args, ok: false, detail: "arguments are not a JSON object" });
2067
2099
  content = JSON.stringify({ error: "arguments must be a JSON object" });
2100
+ record({ type: "tool_result", tool: label, kind, success: false, detail: "arguments are not a JSON object", resultText: content, timestamp: now() });
2068
2101
  } else {
2069
2102
  const { input } = tool.target;
2070
2103
  const response = await host.dispatchInput(input.orbital, {
@@ -2073,8 +2106,8 @@ async function runToolLoop(client, host, request) {
2073
2106
  payload: parsed.data
2074
2107
  });
2075
2108
  const detail = dispatchFailure(response);
2076
- steps.push({ kind: "input", target: tool.target.address, args, ok: detail === void 0, ...detail !== void 0 ? { detail } : {} });
2077
2109
  content = JSON.stringify(response);
2110
+ record({ type: "tool_result", tool: label, kind, success: detail === void 0, ...detail !== void 0 ? { detail } : {}, resultText: content, timestamp: now() });
2078
2111
  }
2079
2112
  }
2080
2113
  conversation.push({ role: "tool", content, tool_call_id: call.id });
@@ -2253,7 +2286,7 @@ Return ONLY valid JSON matching the schema.`,
2253
2286
  }
2254
2287
  const request = CallToolsParamsSchema.parse(params);
2255
2288
  const client = request.model !== void 0 ? new LLMClient({ provider: this.provider, model: request.model }) : this.getClient();
2256
- return runToolLoop(client, context.host, request);
2289
+ return runToolLoop(client, context.host, request, { provider: client.getProvider(), model: client.getModelName() });
2257
2290
  }
2258
2291
  async embed(params) {
2259
2292
  const { texts } = params;