@axiom-lattice/core 6.3.1 → 6.3.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/index.mjs CHANGED
@@ -40174,6 +40174,33 @@ function clearEncryptionKeyCache() {
40174
40174
  cachedKey = null;
40175
40175
  keyValidated = false;
40176
40176
  }
40177
+ function encryptConfigFields(config, fields) {
40178
+ if (!fields?.length) return config;
40179
+ const out = { ...config };
40180
+ for (const field of fields) {
40181
+ const value = out[field];
40182
+ if (typeof value === "string" && value.length > 0) {
40183
+ out[field] = encrypt(value);
40184
+ }
40185
+ }
40186
+ return out;
40187
+ }
40188
+ function decryptConfigFields(config, fields) {
40189
+ if (!fields?.length) return config;
40190
+ const out = { ...config };
40191
+ for (const field of fields) {
40192
+ const value = out[field];
40193
+ if (typeof value === "string" && value.length > 0) {
40194
+ try {
40195
+ out[field] = decrypt(value);
40196
+ } catch (error) {
40197
+ console.error(`Failed to decrypt connection field "${field}":`, error);
40198
+ throw new Error("Failed to decrypt connection configuration");
40199
+ }
40200
+ }
40201
+ }
40202
+ return out;
40203
+ }
40177
40204
 
40178
40205
  // src/util/safeUpstreamUrl.ts
40179
40206
  var UnsafeUpstreamUrlError = class extends Error {
@@ -43707,7 +43734,7 @@ function createTaskMiddleware(options = {}) {
43707
43734
  error: "Task changed before activity could be recorded."
43708
43735
  });
43709
43736
  markMutation();
43710
- return JSON.stringify({ success: true, data: activity });
43737
+ return JSON.stringify({ success: true, data: activity, task: existing });
43711
43738
  }
43712
43739
  case "update": {
43713
43740
  taskUpdateDebug("update:enter", {
@@ -46198,6 +46225,12 @@ import { createMiddleware as createMiddleware27, tool as tool67 } from "langchai
46198
46225
  import { z as z73 } from "zod";
46199
46226
  import { AgentType as AgentType10 } from "@axiom-lattice/protocols";
46200
46227
 
46228
+ // src/connection/connectionSecretFields.ts
46229
+ function connectionSecretFields(plugin) {
46230
+ const fields = plugin?.connection?.fields ?? [];
46231
+ return fields.filter((field) => field.type === "password" || field.widget === "password").map((field) => field.key);
46232
+ }
46233
+
46201
46234
  // src/middlewares/sandboxPluginsSkills.ts
46202
46235
  var PLUGIN_JSON_TEMPLATE = `{
46203
46236
  "schemaVersion": 1,
@@ -46861,11 +46894,25 @@ Use the \`manage_plugin\` tool. The loop:
46861
46894
 
46862
46895
  1. \`action: "validate"\` with \`{ type, manifest, handlers }\` \u2014 dry-run, no writes, returns diagnostics.
46863
46896
  2. \`action: "create"\` or \`"update"\` \u2014 writes files, bumps version, reloads.
46864
- 3. \`action: "test"\` to exercise a handler without an LLM:
46897
+ 3. If the plugin has \`connection.fields\` and a tool reads credentials: a **human**
46898
+ must configure a connection of this plugin type. You cannot create credentials.
46899
+ Call \`list_connections { type }\` first \u2014 if none exist, use \`ask_user_to_clarify\`
46900
+ to state explicitly that only the human can configure the connector, ask them to
46901
+ add it (Console \u2192 Connections) and to give you the connection key. Do not claim
46902
+ the tool works until a real \`connectionKey\` test passes.
46903
+ 4. \`action: "test"\` to exercise a handler without an LLM:
46865
46904
  - Tool: \`{ type, target: { kind: "tool", name, input, connectionKey? } }\`
46866
46905
  - Connection: \`{ type, target: { kind: "connection-test" } }\` or \`{ kind: "connection-discover" }\`
46867
46906
  Returns \`{ ok, result, exitCode, durationMs, stdout, stderr }\`.
46868
- 4. \`action: "reload"\` if you edited files directly.
46907
+ For credentialed tools, pass the real \`connectionKey\`. Without one, the handler
46908
+ receives an empty connection \u2014 that only checks plumbing, NOT functional success.
46909
+ 5. \`action: "reload"\` if you edited files directly.
46910
+
46911
+ ## Secrets
46912
+ - \`list_connections\` returns identifiers only (\`key\`/\`name\`/\`description\`), never config or secrets.
46913
+ - \`test\` output is redacted: real connection secret values are replaced with
46914
+ \`[redacted]\`. Never rely on echoing credentials to verify a handler \u2014 assert on
46915
+ functional output instead.
46869
46916
 
46870
46917
  ## Common failures
46871
46918
  | Symptom | Cause |
@@ -46875,9 +46922,12 @@ Use the \`manage_plugin\` tool. The loop:
46875
46922
  | TOOL_SCHEMA | unsupported JSON Schema keyword |
46876
46923
  | non-zero exit | handler threw; read stdout/stderr from \`test\` |
46877
46924
  | old behaviour after edit | version/hash unchanged \u2014 bump \`version\` or call \`reload\` |
46925
+ | empty connection in handler | no \`connectionKey\` passed, or no connection configured for this type |
46878
46926
 
46879
46927
  Fall back to \`execute_code\`/\`shell\` to run \`node handlers/x.js\` manually with
46880
- \`PLUGIN_INPUT\` set if you need to reproduce.
46928
+ \`PLUGIN_INPUT\` and a synthetic \`PLUGIN_CONNECTION_FILE\` to reproduce logic bugs.
46929
+ A synthetic fixture only verifies plumbing \u2014 a real upstream call requires a real
46930
+ \`connectionKey\` configured by a human.
46881
46931
  `,
46882
46932
  resources: {}
46883
46933
  }
@@ -46908,8 +46958,13 @@ implemented", "UI added", "validated/tested via manage_plugin"). As you work,
46908
46958
  update each Task's status to reflect reality. Never use \`write_todos\`.
46909
46959
 
46910
46960
  Author with the \`manage_plugin\` tool: validate, then create/update, then test.
46911
- Use \`shell_exec\` (the tool provided by the \`code_eval\` middleware) to run
46912
- \`node handlers/x.js\` for manual checks when reproducing a failure.`;
46961
+ If a tool needs credentials, a human must configure the connection \u2014 use
46962
+ \`list_connections\` to check, and \`ask_user_to_clarify\` to ask the human to add
46963
+ the connector and give you its key. Only after a real \`connectionKey\` test
46964
+ passes may you call the tool verified; without it, report functionality as
46965
+ unverified (missing credentials), not as passing. Use \`shell_exec\` (the tool
46966
+ provided by the \`code_eval\` middleware) to run \`node handlers/x.js\` for manual
46967
+ checks when reproducing a failure.`;
46913
46968
 
46914
46969
  // src/middlewares/sandboxPluginsMiddleware.ts
46915
46970
  var PLUGIN_BUILDER_SKILLS = [...Object.keys(SANDBOX_PLUGIN_SKILLS), "task-tracking"];
@@ -46917,6 +46972,37 @@ function tenantIdFrom(exeConfig) {
46917
46972
  const c = exeConfig;
46918
46973
  return c?.configurable?.runConfig?.tenantId ?? "default";
46919
46974
  }
46975
+ function collectSecretValues(connection, fields) {
46976
+ if (!connection) return [];
46977
+ const values = [];
46978
+ for (const field of fields) {
46979
+ const value = connection[field];
46980
+ if (typeof value === "string" && value.length > 0) values.push(value);
46981
+ }
46982
+ return values;
46983
+ }
46984
+ function errorText(err) {
46985
+ return err instanceof Error ? err.message : String(err);
46986
+ }
46987
+ function redactString(value, secrets) {
46988
+ let out = value;
46989
+ for (const secret of secrets) out = out.split(secret).join("[redacted]");
46990
+ return out;
46991
+ }
46992
+ function redactSecretValues(payload, secrets) {
46993
+ if (secrets.length === 0) return payload;
46994
+ const walk = (node) => {
46995
+ if (typeof node === "string") return redactString(node, secrets);
46996
+ if (Array.isArray(node)) return node.map(walk);
46997
+ if (node !== null && typeof node === "object") {
46998
+ const out = {};
46999
+ for (const [key5, value] of Object.entries(node)) out[key5] = walk(value);
47000
+ return out;
47001
+ }
47002
+ return node;
47003
+ };
47004
+ return walk(payload);
47005
+ }
46920
47006
  var managePluginSchema = z73.object({
46921
47007
  action: z73.enum(["list", "get", "validate", "create", "update", "delete", "reload", "test"]),
46922
47008
  type: z73.string().optional(),
@@ -46948,6 +47034,10 @@ var sandboxPluginsPlugin = {
46948
47034
  description: "Author and manage tenant plugins in the shared sandbox: clarify goal, inputs/outputs, credentials, and whether a UI is needed; then write the manifest and JS handlers, add an optional HTML MCP App UI, and validate/test with the manage_plugin tool.",
46949
47035
  type: AgentType10.DEEP_AGENT,
46950
47036
  prompt: PLUGIN_BUILDER_PROMPT,
47037
+ // Read-only discovery of connection identifiers (metadata only — never
47038
+ // config/secrets) so the builder can confirm a human configured a
47039
+ // connector and pass its key to `manage_plugin test`.
47040
+ tools: ["list_connections"],
46951
47041
  middleware: [
46952
47042
  {
46953
47043
  id: "sandbox-plugins",
@@ -47083,8 +47173,19 @@ var sandboxPluginsPlugin = {
47083
47173
  input.target.connectionKey ? { connections: [input.target.connectionKey] } : { connectAll: true },
47084
47174
  { tenantId: tenantId2 }
47085
47175
  );
47086
- const result2 = await plugin.connection?.test?.(connection ?? {});
47087
- return JSON.stringify(result2 ?? { ok: false, message: "no test handler" });
47176
+ const secrets2 = collectSecretValues(connection, connectionSecretFields(plugin));
47177
+ try {
47178
+ const result = await plugin.connection?.test?.(connection ?? {});
47179
+ return JSON.stringify(redactSecretValues(
47180
+ result ?? { ok: false, message: "no test handler" },
47181
+ secrets2
47182
+ ));
47183
+ } catch (err) {
47184
+ return JSON.stringify(redactSecretValues(
47185
+ { ok: false, message: errorText(err) },
47186
+ secrets2
47187
+ ));
47188
+ }
47088
47189
  }
47089
47190
  if (input.target.kind === "connection-discover") {
47090
47191
  const { connection } = await resolveSandboxPluginConnections(
@@ -47092,8 +47193,16 @@ var sandboxPluginsPlugin = {
47092
47193
  input.target.connectionKey ? { connections: [input.target.connectionKey] } : { connectAll: true },
47093
47194
  { tenantId: tenantId2 }
47094
47195
  );
47095
- const result2 = await plugin.connection?.discover?.(connection ?? {});
47096
- return JSON.stringify(result2 ?? []);
47196
+ const secrets2 = collectSecretValues(connection, connectionSecretFields(plugin));
47197
+ try {
47198
+ const result = await plugin.connection?.discover?.(connection ?? {});
47199
+ return JSON.stringify(redactSecretValues(result ?? [], secrets2));
47200
+ } catch (err) {
47201
+ return JSON.stringify(redactSecretValues(
47202
+ { error: errorText(err) },
47203
+ secrets2
47204
+ ));
47205
+ }
47097
47206
  }
47098
47207
  const executor = catalog2.getExecutor();
47099
47208
  const manifestContent = await catalog2.readPluginFile(tenantId2, input.type, "plugin.json");
@@ -47111,19 +47220,24 @@ var sandboxPluginsPlugin = {
47111
47220
  { connections: [input.target.connectionKey] },
47112
47221
  { tenantId: tenantId2 }
47113
47222
  ) : {};
47114
- const result = await executor.invoke({
47115
- manifest: parsedManifest,
47116
- handler: toolDef.handler,
47117
- input: input.target.input ?? null,
47118
- connection: resolved.connection,
47119
- connections: resolved.connections,
47120
- context: { tenantId: tenantId2, pluginType: input.type, tool: toolDef.name },
47121
- runConfig: {
47122
- tenantId: tenantId2,
47123
- assistantId: typeof runCfg.assistant_id === "string" ? runCfg.assistant_id : void 0
47124
- }
47125
- });
47126
- return JSON.stringify(result);
47223
+ const secrets = collectSecretValues(resolved.connection, connectionSecretFields(plugin));
47224
+ try {
47225
+ const result = await executor.invoke({
47226
+ manifest: parsedManifest,
47227
+ handler: toolDef.handler,
47228
+ input: input.target.input ?? null,
47229
+ connection: resolved.connection,
47230
+ connections: resolved.connections,
47231
+ context: { tenantId: tenantId2, pluginType: input.type, tool: toolDef.name },
47232
+ runConfig: {
47233
+ tenantId: tenantId2,
47234
+ assistantId: typeof runCfg.assistant_id === "string" ? runCfg.assistant_id : void 0
47235
+ }
47236
+ });
47237
+ return JSON.stringify(redactSecretValues(result, secrets));
47238
+ } catch (err) {
47239
+ return JSON.stringify(redactSecretValues({ ok: false, error: errorText(err) }, secrets));
47240
+ }
47127
47241
  }
47128
47242
  default:
47129
47243
  return `unsupported action: ${input.action}`;
@@ -47786,6 +47900,7 @@ export {
47786
47900
  configurePluginCatalogSync,
47787
47901
  configureStores,
47788
47902
  connectAllChannels,
47903
+ connectionSecretFields,
47789
47904
  convertToConnection,
47790
47905
  createAgentNode,
47791
47906
  createAgentTeam,
@@ -47826,11 +47941,13 @@ export {
47826
47941
  createUnknownToolHandlerMiddleware,
47827
47942
  createWidgetMiddleware,
47828
47943
  decrypt,
47944
+ decryptConfigFields,
47829
47945
  describeCronExpression,
47830
47946
  documentLearningPlugin,
47831
47947
  documentParserPlugin,
47832
47948
  embeddingsLatticeManager,
47833
47949
  encrypt,
47950
+ encryptConfigFields,
47834
47951
  ensureBuiltinAgentsForTenant,
47835
47952
  ensurePluginSkillInSandbox,
47836
47953
  evaluateLatticeCaseWithLogs,