@falkenslab/agent-kit 0.24.0 → 0.25.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.
Files changed (40) hide show
  1. package/README.md +2 -0
  2. package/dist/chat/chatController.d.ts +10 -0
  3. package/dist/chat/chatController.js +39 -1
  4. package/dist/chat/extensions.d.ts +9 -0
  5. package/dist/chat/extensions.js +13 -1
  6. package/dist/chat/runs.d.ts +3 -1
  7. package/dist/chat/runs.js +1 -1
  8. package/dist/core/extensionCatalog.d.ts +6 -1
  9. package/dist/core/extensionCatalog.js +10 -8
  10. package/dist/core/extensionOptions.d.ts +5 -0
  11. package/dist/core/extensionOptions.js +10 -0
  12. package/dist/core/extensions.d.ts +6 -0
  13. package/dist/core/externalExtensions.d.ts +24 -1
  14. package/dist/core/externalExtensions.js +78 -12
  15. package/dist/core/liveExtensions.d.ts +38 -0
  16. package/dist/core/liveExtensions.js +69 -0
  17. package/dist/core/marketplaces.d.ts +1 -0
  18. package/dist/core/messages/de.js +10 -1
  19. package/dist/core/messages/en.d.ts +14 -0
  20. package/dist/core/messages/en.js +10 -1
  21. package/dist/core/messages/es.js +10 -1
  22. package/dist/core/messages/fr.js +10 -1
  23. package/dist/core/npxPackages.d.ts +2 -2
  24. package/dist/core/runner.js +17 -0
  25. package/dist/core/session.d.ts +6 -2
  26. package/dist/core/session.js +5 -2
  27. package/dist/core/sessionFacts.d.ts +14 -0
  28. package/dist/extensions/awareness/catalog.d.ts +8 -0
  29. package/dist/extensions/awareness/catalog.js +92 -0
  30. package/dist/extensions/awareness/index.d.ts +3 -1
  31. package/dist/extensions/awareness/index.js +15 -6
  32. package/dist/extensions/awareness/labels.js +8 -5
  33. package/dist/extensions/awareness/tools.d.ts +2 -2
  34. package/dist/extensions/awareness/tools.js +4 -3
  35. package/dist/index.d.ts +3 -3
  36. package/dist/index.js +1 -1
  37. package/dist/tui/extensionCommand.js +11 -6
  38. package/extensions/awareness/skills/extensions/SKILL.md +56 -0
  39. package/package.json +1 -1
  40. package/schemas/marketplace-catalog.schema.json +6 -0
package/dist/index.js CHANGED
@@ -17,7 +17,7 @@ export { knowledge } from "./extensions/knowledge/index.js";
17
17
  export { memory } from "./extensions/memory/index.js";
18
18
  export { describeCapability, readExtensionManifest, } from "./core/extensions.js";
19
19
  export { checkRequirements } from "./core/extensionRequirements.js";
20
- export { addExtension, codeStoreDir, installTarget, scopePrivateDir, extensionDataDir, extensionOptionStates, setExtensionOptions, removeExtension, setExtensionEnabled, listInstalled, readExternalManifest, } from "./core/externalExtensions.js";
20
+ export { addExtension, codeStoreDir, installTarget, scopePrivateDir, extensionDataDir, extensionOptionStates, setExtensionOptions, removeExtension, setExtensionEnabled, listInstalled, readExternalManifest, isRemoteServer, remoteHosts, remoteServerName, } from "./core/externalExtensions.js";
21
21
  export { packageCacheDir } from "./core/npxPackages.js";
22
22
  export { addMarketplace, findPlugin, inspectMarketplace, installFromMarketplace, listMarketplaces, readMarketplaceManifest, removeMarketplace, resolvePluginSource, updateMarketplace, } from "./core/marketplaces.js";
23
23
  export { extensionCatalog, installExtension, restoreExtensions, updateExtension } from "./core/extensionCatalog.js";
@@ -2,7 +2,7 @@ import { stat } from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { createInterface } from "node:readline/promises";
4
4
  import { addMarketplace, findPlugin, inspectMarketplace, installFromMarketplace, removeMarketplace, updateMarketplace, } from "../core/marketplaces.js";
5
- import { addExtension, extensionOptionStates, installTarget, folderSize, isGitSource, listInstalled, removeExtension, setExtensionEnabled, setExtensionOptions, } from "../core/externalExtensions.js";
5
+ import { addExtension, extensionOptionStates, installTarget, folderSize, isGitSource, isRemoteServer, remoteHosts, listInstalled, removeExtension, setExtensionEnabled, setExtensionOptions, } from "../core/externalExtensions.js";
6
6
  import { describe, describeOptions } from "../chat/extensions.js";
7
7
  import { extensionCatalog, knownMarketplaces as catalogMarketplaces, restoreExtensions, updateExtension } from "../core/extensionCatalog.js";
8
8
  import { trustWorkspace } from "../core/workspaceTrust.js";
@@ -129,9 +129,12 @@ export async function runExtensionCommand(argv, options) {
129
129
  // Installed into the workspace by the person: trusted there as it is.
130
130
  const trusted = async (name) => void (scope === "project" && (await trustWorkspace(options.dirs, [name])));
131
131
  // What it needs and this computer lacks (#63): said, never installed.
132
- const lacking = (missing) => {
132
+ const lacking = (missing, remote = []) => {
133
133
  for (const line of missing)
134
134
  write(`It ${line}.`);
135
+ // Where what the agent sends goes (#61).
136
+ if (remote.length)
137
+ write(`It talks to ${remote.join(", ")}: what the agent sends there leaves this computer.`);
135
138
  };
136
139
  // A plugin of a marketplace, unless it's a folder here or a git URL.
137
140
  const isFolder = await stat(path.resolve(source)).then((found) => found.isDirectory(), () => false);
@@ -142,7 +145,7 @@ export async function runExtensionCommand(argv, options) {
142
145
  await trusted(result.name);
143
146
  await configure(result.name, dir);
144
147
  write(`Linked ${result.name} in the ${scope} scope: it runs from ${path.resolve(source)}, whose files aren't checked. A rebuild takes effect when its server starts again (a new session, or \`/extensions disable\` and \`enable\` in the chat).`);
145
- lacking(result.missing);
148
+ lacking(result.missing, result.remote);
146
149
  return true;
147
150
  }
148
151
  if (!isFolder && !isGitSource(source) && /^[A-Za-z0-9][\w.-]*(@[A-Za-z0-9][\w.-]*)?$/.test(source)) {
@@ -158,7 +161,7 @@ export async function runExtensionCommand(argv, options) {
158
161
  await trusted(result.name);
159
162
  await configure(result.name, dir);
160
163
  write(`${result.replaced ? "Reinstalled" : "Installed"} ${result.name} from ${result.marketplace} in the ${scope} scope (${dir})${result.commit ? `, at ${result.commit.slice(0, 12)}` : ""}. It's enabled: it runs from the next session.`);
161
- lacking(result.missing);
164
+ lacking(result.missing, result.remote);
162
165
  return true;
163
166
  }
164
167
  const subdir = value("path");
@@ -166,7 +169,7 @@ export async function runExtensionCommand(argv, options) {
166
169
  await trusted(result.name);
167
170
  await configure(result.name, dir);
168
171
  write(`${result.replaced ? "Reinstalled" : "Installed"} ${result.name} in the ${scope} scope (${dir})${result.commit ? `, at ${result.commit.slice(0, 12)}` : ""}. It's enabled: it runs from the next session.`);
169
- lacking(result.missing);
172
+ lacking(result.missing, result.remote);
170
173
  return true;
171
174
  }
172
175
  case "remove":
@@ -434,7 +437,9 @@ async function info(extension) {
434
437
  ...field("Options", Object.entries(manifest.userConfig)
435
438
  .map(([key, option]) => `${key} (${[option.title, option.required && "required", option.sensitive && "secret"].filter(Boolean).join(", ")})`)
436
439
  .join(", ") || undefined),
437
- ...field("Variables", Object.values(manifest.servers).flatMap((server) => Object.keys(server.env ?? {})).join(", ") || undefined),
440
+ ...field("Variables", Object.values(manifest.servers).flatMap((server) => (isRemoteServer(server) ? [] : Object.keys(server.env ?? {}))).join(", ") || undefined),
441
+ // Where what the agent sends goes (#61): a remote server's host.
442
+ ...field("Talks to", remoteHosts(manifest).join(", ") || undefined),
438
443
  ...field("Installed", `${extension.scope} scope, ${extension.lock.enabled ? "enabled" : "disabled"}, on ${extension.lock.installed}, from ${describe(extension).split(" from ")[1]}`),
439
444
  ...field("Data", (await stat(extension.dataDir).catch(() => null))?.isDirectory() ? `${extension.dataDir} (${formatSize(await folderSize(extension.dataDir))})` : undefined),
440
445
  ...field("README", (await stat(readme).catch(() => null))?.isFile() ? readme : undefined),
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: extensions
3
+ description: Helping the person with this agent's extensions - what each installed one lets you do, setting its options, why one is off, what the catalogs offer for a task, signing in to a remote one, installing, updating and removing, adding a catalog. Load it whenever the person asks about extensions, or when you're about to suggest one.
4
+ ---
5
+
6
+ # Helping with extensions
7
+
8
+ Extensions add what you can do: tools, skills and the know-how to use them (a Moodle classroom, a weather forecast, a lab). What's installed and what the catalogs offer come from `extensions_catalog`, read anew each time: never answer from memory. Answer in the language you reply in, briefly, with the exact command; commands are typed as written here. Without `extensions_catalog` among your tools, this agent has no folder for extensions and can't install any: say so, and suggest nothing.
9
+
10
+ ## What you never do
11
+
12
+ - Install, enable, disable, configure or remove an extension yourself: the person does, with the commands below. You suggest and explain.
13
+ - Ask for a secret (a token, a password) in the chat: what's typed there is kept in its history. Secrets are set in the agent's settings or from a terminal (`<agent> extension config <name> <key>`, which asks without showing it).
14
+ - Suggest an extension the catalog didn't return, or one the person already declined in this conversation.
15
+
16
+ ## Suggesting one
17
+
18
+ When the task needs what an extension does and it isn't installed, or it's off: one sentence with what it adds, what it needs (a program, a site, an account) and how to install it, then go on with what you can do without it.
19
+
20
+ > The **weather** extension would give me today's forecast for your city; install it with `/extensions install weather@falkenslab` and tell me your city. Meanwhile, here's what I can plan without it…
21
+
22
+ An extension that talks to a remote service sends what you give it there: say so when the person's data is involved.
23
+
24
+ ## Commands in the chat
25
+
26
+ | Command | What it does |
27
+ | --- | --- |
28
+ | `/extensions` | What's running, what's off and why, what's installed |
29
+ | `/extensions search <words>` | What the catalogs offer |
30
+ | `/extensions install <name>@<marketplace>` | Installs one (one from a catalog that isn't the agent's own asks for confirmation) |
31
+ | `/extensions reload` | Opens the session again with what's installed now, keeping the conversation |
32
+ | `/extensions update [name]` | Updates one, or every one with a newer version |
33
+ | `/extensions remove <name>` | Uninstalls one (`--delete-data` deletes its data too) |
34
+ | `/extensions enable <name>` | Turns one on |
35
+ | `/extensions disable <name>` | Turns one off, keeping it installed |
36
+ | `/extensions config <name> [key=value…]` | Its options, and setting the ones that aren't secret |
37
+ | `/extensions sign-in <name>` | Signs in to its remote service: gives the link to open |
38
+ | `/extensions sign-out <name>` | Signs out of its remote service |
39
+ | `/extensions trust` | Lets the workspace's extensions run |
40
+
41
+ A new catalog (a marketplace) is added from a terminal: `<agent> extension marketplace add <owner/repo>`.
42
+
43
+ ## Why one is off
44
+
45
+ `extensions_catalog` and `/extensions` give the reason; explain it and its remedy in plain words:
46
+
47
+ - **An option without a value** (its site, its account): `/extensions config <name> <key>=<value>`, or the settings for a secret.
48
+ - **A program missing on the computer** (Docker, ffmpeg): what it is, and the install command for this system the reason gives. The extension never installs it.
49
+ - **It needs signing in**: `/extensions sign-in <name>`, then open the link.
50
+ - **It requires another extension's capability**: install or enable the one that provides it.
51
+ - **Its files changed** or **its workspace isn't trusted**: reinstall it, or `/extensions trust`.
52
+ - **This agent's kit version is outside its range**: an update of the agent or of the extension.
53
+
54
+ ## What's new
55
+
56
+ `extensions_catalog` with `refresh: true` fetches the catalogs again and says what's new: extensions added since the last copy, and newer versions of installed ones (`/extensions update`). Without network it answers from the copies on this computer and says how old they are.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@falkenslab/agent-kit",
3
- "version": "0.24.0",
3
+ "version": "0.25.0",
4
4
  "description": "Library for building an agent on top of the Claude Agent SDK",
5
5
  "author": "Francisco Vargas Ruiz",
6
6
  "license": "MIT",
@@ -80,6 +80,12 @@
80
80
  "type": "array",
81
81
  "items": { "$ref": "https://falkenslab.github.io/agent-kit/schemas/agent-kit-metadata.schema.json#/$defs/requirement" }
82
82
  },
83
+ "remote": {
84
+ "description": "The hosts its remote MCP servers talk to (type http or sse in its .mcp.json): what an agent sends there leaves the computer. Only when it has some.",
85
+ "type": "array",
86
+ "uniqueItems": true,
87
+ "items": { "type": "string", "minLength": 1 }
88
+ },
83
89
  "logo": { "description": "A URL anyone can load.", "$ref": "#/$defs/url" },
84
90
  "banner": { "description": "A URL anyone can load.", "$ref": "#/$defs/url" }
85
91
  }