@particle-academy/agent-integrations 0.39.1 → 0.41.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 { ShareControls, AgentCursor, AgentActivityHighlight, AgentPanel } from './chunk-QYWPCRT2.js';
2
- import { createSessionDescriptor, attachSseRelay } from './chunk-JDCB2NMM.js';
1
+ import { ShareControls, AgentCursor, AgentActivityHighlight, AgentPanel } from './chunk-QDC7MXBH.js';
2
+ import { createSessionDescriptor, attachSseRelay } from './chunk-6TZ5IBRN.js';
3
3
  import { attachInProcess } from './chunk-AFUULW5E.js';
4
4
  import { registerWhiteboardBridge } from './chunk-2U5JB6ZA.js';
5
5
  import './chunk-CT3LRNH7.js';
package/dist/index.cjs CHANGED
@@ -2800,6 +2800,13 @@ function registerGitBridge(host, options) {
2800
2800
  // src/bridges/files.ts
2801
2801
  var DEFAULT_AGENT10 = { id: "agent", name: "Agent", color: "#a855f7" };
2802
2802
  var MAX_SNAPSHOT_DEPTH = 8;
2803
+ function invalidFolderName(name) {
2804
+ const trimmed = name.trim();
2805
+ if (trimmed === "") return "A folder name is required.";
2806
+ if (trimmed.includes("/") || trimmed.includes("\\")) return "A folder name may not contain a path separator.";
2807
+ if (trimmed === "." || trimmed === "..") return "That folder name is reserved.";
2808
+ return null;
2809
+ }
2803
2810
  function assertPathWithinRoot(root, path) {
2804
2811
  const segments = path.replace(/[\\/]+/g, "/").split("/");
2805
2812
  if (segments.includes("..")) {
@@ -2829,6 +2836,7 @@ var asPaths = (v) => {
2829
2836
  function registerFilesBridge(host, options) {
2830
2837
  const { adapter } = options;
2831
2838
  const agent = { ...DEFAULT_AGENT10, ...options.agent ?? {} };
2839
+ const pendingMode = options.pendingMode ?? true;
2832
2840
  const disposers = [];
2833
2841
  const guard = (path) => {
2834
2842
  if (options.root !== void 0) assertPathWithinRoot(options.root, path);
@@ -2995,6 +3003,42 @@ function registerFilesBridge(host, options) {
2995
3003
  },
2996
3004
  fTarget
2997
3005
  );
3006
+ if (adapter.createFolder) {
3007
+ reg(
3008
+ "files_create_folder",
3009
+ "Create a folder inside `parentPath`. Staged for human confirmation unless the host disabled pendingMode.",
3010
+ {
3011
+ parentPath: { type: "string", description: "Directory to create in; defaults to the current directory." },
3012
+ name: { type: "string", description: "The new folder's name. A leaf name \u2014 no separators." },
3013
+ confirm: { type: "boolean", description: "Acknowledge a staged write when the host wired no confirm hook." }
3014
+ },
3015
+ ["name"],
3016
+ async (args) => {
3017
+ const parentPath = guard(args.parentPath !== void 0 ? str3(args.parentPath) : adapter.getPath());
3018
+ const name = str3(args.name).trim();
3019
+ const invalid = invalidFolderName(name);
3020
+ if (invalid) return errorResult(invalid);
3021
+ const label = `${parentPath}/${name}`;
3022
+ if (pendingMode) {
3023
+ if (options.confirm) {
3024
+ const ok = await options.confirm({ action: "files_create_folder", path: label, label });
3025
+ if (!ok) return errorResult(`Declined: create folder ${label} (human did not confirm).`);
3026
+ } else if (args.confirm !== true) {
3027
+ return errorResult(
3028
+ `Staged: create folder ${label}. Re-call with confirm:true to proceed.`
3029
+ );
3030
+ }
3031
+ }
3032
+ try {
3033
+ await adapter.createFolder({ parentPath, name });
3034
+ } catch (e) {
3035
+ return errorResult(e instanceof Error ? e.message : String(e));
3036
+ }
3037
+ return textResult(`Created folder ${label}.`, { parentPath, name, path: label });
3038
+ },
3039
+ (args) => ({ kind: "directory", path: `${str3(args.parentPath)}/${str3(args.name)}`, label: str3(args.name) })
3040
+ );
3041
+ }
2998
3042
  reg(
2999
3043
  "files_request_snapshot",
3000
3044
  "Request a fresh snapshot subtree rooted at `path` (snapshot mode) \u2014 e.g. to pull a remote machine's current tree. Requires the host to wire requestSnapshot.",
@@ -4887,9 +4931,9 @@ var SseRelayTransport = class {
4887
4931
  this.peers.add(subscriberId);
4888
4932
  this.notifyPeers();
4889
4933
  fancyAutoCommon.emitActivity({
4890
- agentId: "agent",
4891
- agentName: "Agent",
4892
- agentColor: "#a855f7",
4934
+ agentId: this.opts.agent?.id ?? "agent",
4935
+ agentName: this.opts.agent?.name ?? "Agent",
4936
+ agentColor: this.opts.agent?.color ?? "#a855f7",
4893
4937
  action: "agent_connected",
4894
4938
  timestamp: Date.now(),
4895
4939
  target: { kind: "navigation", label: "Agent connected" },
@@ -4903,9 +4947,9 @@ var SseRelayTransport = class {
4903
4947
  this.notifyPeers();
4904
4948
  if (this.peers.size === 0) {
4905
4949
  fancyAutoCommon.emitActivity({
4906
- agentId: "agent",
4907
- agentName: "Agent",
4908
- agentColor: "#a855f7",
4950
+ agentId: this.opts.agent?.id ?? "agent",
4951
+ agentName: this.opts.agent?.name ?? "Agent",
4952
+ agentColor: this.opts.agent?.color ?? "#a855f7",
4909
4953
  action: "agent_disconnected",
4910
4954
  timestamp: Date.now(),
4911
4955
  target: { kind: "navigation", label: "Agent disconnected" },
@@ -4928,6 +4972,15 @@ function attachSseRelay(server, options) {
4928
4972
  transport.start();
4929
4973
  Promise.resolve().then(() => (init_registry(), registry_exports)).then(({ onActivity: onActivity2 }) => {
4930
4974
  const off = onActivity2((event) => {
4975
+ if (options.activityFilter) {
4976
+ let keep;
4977
+ try {
4978
+ keep = options.activityFilter(event);
4979
+ } catch {
4980
+ return;
4981
+ }
4982
+ if (!keep) return;
4983
+ }
4931
4984
  transport.send({
4932
4985
  jsonrpc: "2.0",
4933
4986
  method: "notifications/agent_activity",
@@ -4991,7 +5044,13 @@ function useCoBrowseSession(options) {
4991
5044
  if (!response.ok) {
4992
5045
  throw new Error(`Relay registration failed (${response.status})`);
4993
5046
  }
4994
- const relay = attachSseRelay(server, { baseUrl: relayBaseUrl, sessionId: descriptor.id, token: descriptor.token });
5047
+ const relay = attachSseRelay(server, {
5048
+ baseUrl: relayBaseUrl,
5049
+ sessionId: descriptor.id,
5050
+ token: descriptor.token,
5051
+ agent: options.agent,
5052
+ activityFilter: options.activityFilter
5053
+ });
4995
5054
  relay.onStateChange(setRelayState);
4996
5055
  relay.onPeersChange(setAgentCount);
4997
5056
  relayRef.current = relay;