@fleetagent/pi-coding-agent 0.0.10 → 0.0.12

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 (116) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/cli/args.d.ts +3 -2
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +20 -8
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/core/agent-session.d.ts +10 -2
  7. package/dist/core/agent-session.d.ts.map +1 -1
  8. package/dist/core/agent-session.js +75 -14
  9. package/dist/core/agent-session.js.map +1 -1
  10. package/dist/core/bash-executor.d.ts +2 -0
  11. package/dist/core/bash-executor.d.ts.map +1 -1
  12. package/dist/core/bash-executor.js +1 -0
  13. package/dist/core/bash-executor.js.map +1 -1
  14. package/dist/core/extensions/index.d.ts +1 -1
  15. package/dist/core/extensions/index.d.ts.map +1 -1
  16. package/dist/core/extensions/index.js.map +1 -1
  17. package/dist/core/extensions/loader.d.ts.map +1 -1
  18. package/dist/core/extensions/loader.js +86 -0
  19. package/dist/core/extensions/loader.js.map +1 -1
  20. package/dist/core/extensions/runner.d.ts +3 -0
  21. package/dist/core/extensions/runner.d.ts.map +1 -1
  22. package/dist/core/extensions/runner.js +27 -0
  23. package/dist/core/extensions/runner.js.map +1 -1
  24. package/dist/core/extensions/types.d.ts +55 -2
  25. package/dist/core/extensions/types.d.ts.map +1 -1
  26. package/dist/core/extensions/types.js.map +1 -1
  27. package/dist/core/pi-agent.d.ts.map +1 -1
  28. package/dist/core/pi-agent.js +1 -0
  29. package/dist/core/pi-agent.js.map +1 -1
  30. package/dist/core/prompt-templates.d.ts +5 -0
  31. package/dist/core/prompt-templates.d.ts.map +1 -1
  32. package/dist/core/prompt-templates.js +115 -0
  33. package/dist/core/prompt-templates.js.map +1 -1
  34. package/dist/core/resource-loader.d.ts +15 -0
  35. package/dist/core/resource-loader.d.ts.map +1 -1
  36. package/dist/core/resource-loader.js +355 -40
  37. package/dist/core/resource-loader.js.map +1 -1
  38. package/dist/core/rules.d.ts +6 -0
  39. package/dist/core/rules.d.ts.map +1 -1
  40. package/dist/core/rules.js +231 -10
  41. package/dist/core/rules.js.map +1 -1
  42. package/dist/core/skills.d.ts +6 -0
  43. package/dist/core/skills.d.ts.map +1 -1
  44. package/dist/core/skills.js +231 -10
  45. package/dist/core/skills.js.map +1 -1
  46. package/dist/core/slash-commands.d.ts.map +1 -1
  47. package/dist/core/slash-commands.js +1 -1
  48. package/dist/core/slash-commands.js.map +1 -1
  49. package/dist/core/source-info.d.ts +2 -0
  50. package/dist/core/source-info.d.ts.map +1 -1
  51. package/dist/core/source-info.js +6 -0
  52. package/dist/core/source-info.js.map +1 -1
  53. package/dist/core/tools/bash.d.ts.map +1 -1
  54. package/dist/core/tools/bash.js +11 -8
  55. package/dist/core/tools/bash.js.map +1 -1
  56. package/dist/core/tools/edit.d.ts.map +1 -1
  57. package/dist/core/tools/edit.js +5 -5
  58. package/dist/core/tools/edit.js.map +1 -1
  59. package/dist/core/tools/find.d.ts.map +1 -1
  60. package/dist/core/tools/find.js +2 -2
  61. package/dist/core/tools/find.js.map +1 -1
  62. package/dist/core/tools/grep.d.ts.map +1 -1
  63. package/dist/core/tools/grep.js +2 -2
  64. package/dist/core/tools/grep.js.map +1 -1
  65. package/dist/core/tools/index.d.ts +1 -1
  66. package/dist/core/tools/index.d.ts.map +1 -1
  67. package/dist/core/tools/index.js +1 -1
  68. package/dist/core/tools/index.js.map +1 -1
  69. package/dist/core/tools/ls.d.ts.map +1 -1
  70. package/dist/core/tools/ls.js +2 -2
  71. package/dist/core/tools/ls.js.map +1 -1
  72. package/dist/core/tools/operations.d.ts +49 -4
  73. package/dist/core/tools/operations.d.ts.map +1 -1
  74. package/dist/core/tools/operations.js +340 -4
  75. package/dist/core/tools/operations.js.map +1 -1
  76. package/dist/core/tools/read.d.ts +2 -0
  77. package/dist/core/tools/read.d.ts.map +1 -1
  78. package/dist/core/tools/read.js +14 -6
  79. package/dist/core/tools/read.js.map +1 -1
  80. package/dist/core/tools/render-utils.d.ts +9 -0
  81. package/dist/core/tools/render-utils.d.ts.map +1 -1
  82. package/dist/core/tools/render-utils.js +16 -0
  83. package/dist/core/tools/render-utils.js.map +1 -1
  84. package/dist/core/tools/write.d.ts.map +1 -1
  85. package/dist/core/tools/write.js +3 -2
  86. package/dist/core/tools/write.js.map +1 -1
  87. package/dist/index.d.ts +2 -2
  88. package/dist/index.d.ts.map +1 -1
  89. package/dist/index.js +1 -1
  90. package/dist/index.js.map +1 -1
  91. package/dist/main.d.ts.map +1 -1
  92. package/dist/main.js +36 -19
  93. package/dist/main.js.map +1 -1
  94. package/dist/modes/interactive/interactive-mode.d.ts +3 -1
  95. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  96. package/dist/modes/interactive/interactive-mode.js +61 -28
  97. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  98. package/dist/modes/rpc/rpc-client.d.ts +11 -4
  99. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  100. package/dist/modes/rpc/rpc-client.js +6 -6
  101. package/dist/modes/rpc/rpc-client.js.map +1 -1
  102. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  103. package/dist/modes/rpc/rpc-mode.js +11 -7
  104. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  105. package/dist/modes/rpc/rpc-types.d.ts +10 -4
  106. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  107. package/dist/modes/rpc/rpc-types.js.map +1 -1
  108. package/docs/extensions.md +83 -4
  109. package/docs/rpc.md +31 -0
  110. package/docs/usage.md +5 -0
  111. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  112. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  113. package/examples/extensions/sandbox/package.json +1 -1
  114. package/examples/extensions/with-deps/package.json +1 -1
  115. package/npm-shrinkwrap.json +12 -12
  116. package/package.json +4 -4
@@ -11,6 +11,7 @@ import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities,
11
11
  import { spawn, spawnSync } from "child_process";
12
12
  import { APP_NAME, APP_TITLE, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, getShareViewerUrl, PACKAGE_NAME, VERSION, } from "../../config.js";
13
13
  import { parseSkillBlock } from "../../core/agent-session.js";
14
+ import { executeBashWithOperations } from "../../core/bash-executor.js";
14
15
  import { FooterDataProvider } from "../../core/footer-data-provider.js";
15
16
  import { KeybindingsManager } from "../../core/keybindings.js";
16
17
  import { createCompactionSummaryMessage } from "../../core/messages.js";
@@ -21,6 +22,7 @@ import { BUILT_IN_PROVIDER_DISPLAY_NAMES } from "../../core/provider-display-nam
21
22
  import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
22
23
  import { LocalSessionManager } from "../../core/session-manager.js";
23
24
  import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
25
+ import { getSourceBackendIcon } from "../../core/source-info.js";
24
26
  import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
25
27
  import { getChangelogPath, getNewEntries, parseChangelog } from "../../utils/changelog.js";
26
28
  import { copyToClipboard } from "../../utils/clipboard.js";
@@ -265,7 +267,8 @@ export class InteractiveMode {
265
267
  if (!sourceTag) {
266
268
  return description;
267
269
  }
268
- return description ? `[${sourceTag}] ${description}` : `[${sourceTag}]`;
270
+ const backendIcon = getSourceBackendIcon(sourceInfo);
271
+ return description ? `[${backendIcon} ${sourceTag}] ${description}` : `[${backendIcon} ${sourceTag}]`;
269
272
  }
270
273
  getBuiltInCommandConflictDiagnostics(extensionRunner) {
271
274
  const builtinNames = new Set(BUILTIN_SLASH_COMMANDS.map((command) => command.name));
@@ -914,7 +917,8 @@ export class InteractiveMode {
914
917
  if (sourceInfo) {
915
918
  const shortPath = this.getShortPath(p, sourceInfo);
916
919
  const { label, scopeLabel } = this.getDisplaySourceInfo(sourceInfo);
917
- const labelText = scopeLabel ? `${label} (${scopeLabel})` : label;
920
+ const backendIcon = getSourceBackendIcon(sourceInfo);
921
+ const labelText = scopeLabel ? `${backendIcon} ${label} (${scopeLabel})` : `${backendIcon} ${label}`;
918
922
  return `${labelText} ${shortPath}`;
919
923
  }
920
924
  return this.formatDisplayPath(p);
@@ -1017,8 +1021,10 @@ export class InteractiveMode {
1017
1021
  const contextFiles = this.session.resourceLoader.getAgentsFiles().agentsFiles;
1018
1022
  if (contextFiles.length > 0) {
1019
1023
  this.chatContainer.addChild(new Spacer(1));
1024
+ const contextBackendInfo = this.session.getToolBackendInfo?.();
1025
+ const contextBackendIcon = contextBackendInfo?.type === "ssh" || contextBackendInfo?.type === "remote" ? "☁" : "🖥";
1020
1026
  const contextList = contextFiles
1021
- .map((f) => theme.fg("dim", ` ${this.formatDisplayPath(f.path)}`))
1027
+ .map((f) => theme.fg("dim", ` ${f.path.startsWith(getAgentDir()) ? "🖥" : contextBackendIcon} ${this.formatDisplayPath(f.path)}`))
1022
1028
  .join("\n");
1023
1029
  const contextCompactList = formatCompactList(contextFiles.map((contextFile) => this.formatContextPath(contextFile.path)), { sort: false });
1024
1030
  addLoadedSection("Context", contextCompactList, contextList);
@@ -1027,20 +1033,20 @@ export class InteractiveMode {
1027
1033
  if (skills.length > 0) {
1028
1034
  const groups = this.buildScopeGroups(skills.map((skill) => ({ path: skill.filePath, sourceInfo: skill.sourceInfo })));
1029
1035
  const skillList = this.formatScopeGroups(groups, {
1030
- formatPath: (item) => this.formatDisplayPath(item.path),
1031
- formatPackagePath: (item) => this.getShortPath(item.path, item.sourceInfo),
1036
+ formatPath: (item) => `${getSourceBackendIcon(item.sourceInfo)} ${this.formatDisplayPath(item.path)}`,
1037
+ formatPackagePath: (item) => `${getSourceBackendIcon(item.sourceInfo)} ${this.getShortPath(item.path, item.sourceInfo)}`,
1032
1038
  });
1033
- const skillCompactList = formatCompactList(skills.map((skill) => skill.name));
1039
+ const skillCompactList = formatCompactList(skills.map((skill) => `${getSourceBackendIcon(skill.sourceInfo)} ${skill.name}`));
1034
1040
  addLoadedSection("Skills", skillCompactList, skillList);
1035
1041
  }
1036
1042
  const rules = rulesResult.rules;
1037
1043
  if (rules.length > 0) {
1038
1044
  const groups = this.buildScopeGroups(rules.map((rule) => ({ path: rule.filePath, sourceInfo: rule.sourceInfo })));
1039
1045
  const ruleList = this.formatScopeGroups(groups, {
1040
- formatPath: (item) => this.formatDisplayPath(item.path),
1041
- formatPackagePath: (item) => this.getShortPath(item.path, item.sourceInfo),
1046
+ formatPath: (item) => `${getSourceBackendIcon(item.sourceInfo)} ${this.formatDisplayPath(item.path)}`,
1047
+ formatPackagePath: (item) => `${getSourceBackendIcon(item.sourceInfo)} ${this.getShortPath(item.path, item.sourceInfo)}`,
1042
1048
  });
1043
- const ruleCompactList = formatCompactList(rules.map((rule) => rule.name));
1049
+ const ruleCompactList = formatCompactList(rules.map((rule) => `${getSourceBackendIcon(rule.sourceInfo)} ${rule.name}`));
1044
1050
  addLoadedSection("Rules", ruleCompactList, ruleList);
1045
1051
  }
1046
1052
  const templates = this.session.promptTemplates;
@@ -1050,14 +1056,14 @@ export class InteractiveMode {
1050
1056
  const templateList = this.formatScopeGroups(groups, {
1051
1057
  formatPath: (item) => {
1052
1058
  const template = templateByPath.get(item.path);
1053
- return template ? `/${template.name}` : this.formatDisplayPath(item.path);
1059
+ return `${getSourceBackendIcon(item.sourceInfo)} ${template ? `/${template.name}` : this.formatDisplayPath(item.path)}`;
1054
1060
  },
1055
1061
  formatPackagePath: (item) => {
1056
1062
  const template = templateByPath.get(item.path);
1057
- return template ? `/${template.name}` : this.formatDisplayPath(item.path);
1063
+ return `${getSourceBackendIcon(item.sourceInfo)} ${template ? `/${template.name}` : this.formatDisplayPath(item.path)}`;
1058
1064
  },
1059
1065
  });
1060
- const promptCompactList = formatCompactList(templates.map((template) => `/${template.name}`));
1066
+ const promptCompactList = formatCompactList(templates.map((template) => `${getSourceBackendIcon(template.sourceInfo)} /${template.name}`));
1061
1067
  addLoadedSection("Prompts", promptCompactList, templateList);
1062
1068
  }
1063
1069
  if (extensions.length > 0) {
@@ -1277,6 +1283,12 @@ export class InteractiveMode {
1277
1283
  ui: this.createExtensionUIContext(),
1278
1284
  hasUI: true,
1279
1285
  cwd: this.activeSession.getCwd(),
1286
+ toolOperations: this.session.getToolOperations(),
1287
+ getToolBackendInfo: () => this.session.getToolBackendInfo(),
1288
+ execToolBackend: (command, options) => {
1289
+ const operations = this.session.getToolOperations();
1290
+ return executeBashWithOperations(command, options?.cwd ?? operations.cwd, operations, options);
1291
+ },
1280
1292
  session: this.activeSession,
1281
1293
  modelRegistry: this.session.modelRegistry,
1282
1294
  model: this.session.model,
@@ -1330,10 +1342,12 @@ export class InteractiveMode {
1330
1342
  if (info.type === "local") {
1331
1343
  return theme.fg("dim", `tools: local ${info.cwd}`);
1332
1344
  }
1333
- if (info.configured) {
1334
- return theme.fg("accent", `tools: ssh ${info.remote}:${info.cwd}`);
1345
+ if (info.type === "remote") {
1346
+ return info.configured
1347
+ ? theme.fg("accent", `tools: remote ${info.url} ${info.cwd}`)
1348
+ : theme.fg("warning", `tools: remote not configured ${info.cwd}`);
1335
1349
  }
1336
- return theme.fg("warning", `tools: ssh not configured ${info.cwd}`);
1350
+ return theme.fg("accent", `tools: ssh ${info.remote}:${info.cwd}`);
1337
1351
  }
1338
1352
  updateToolBackendStatus() {
1339
1353
  this.setExtensionStatus("toolBackend", this.formatToolBackendStatus(this.session.getToolBackendInfo()));
@@ -2051,9 +2065,9 @@ export class InteractiveMode {
2051
2065
  this.editor.setText("");
2052
2066
  return;
2053
2067
  }
2054
- if (text === "/ssh-sandbox" || text.startsWith("/ssh-sandbox ")) {
2068
+ if (text === "/remote" || text.startsWith("/remote ")) {
2055
2069
  this.editor.setText("");
2056
- await this.handleSshSandboxCommand(text);
2070
+ await this.handleRemoteCommand(text);
2057
2071
  return;
2058
2072
  }
2059
2073
  if (text === "/changelog") {
@@ -4383,40 +4397,59 @@ export class InteractiveMode {
4383
4397
  this.chatContainer.addChild(new Text(theme.fg("dim", `Session name set: ${name}`), 1, 0));
4384
4398
  this.ui.requestRender();
4385
4399
  }
4386
- async handleSshSandboxCommand(text) {
4387
- const args = text.replace(/^\/ssh-sandbox\s*/, "").trim();
4400
+ async reloadResourcesAfterBackendChange() {
4401
+ await this.session.reload();
4402
+ this.setupAutocompleteProvider();
4403
+ this.showLoadedResources({ force: true, showDiagnosticsWhenQuiet: true });
4404
+ }
4405
+ async handleRemoteCommand(text) {
4406
+ const args = text.replace(/^\/remote\s*/, "").trim();
4388
4407
  if (!args || args === "status") {
4389
4408
  this.showStatus(this.formatToolBackendStatus(this.session.getToolBackendInfo()));
4390
4409
  return;
4391
4410
  }
4392
4411
  if (args === "clear") {
4393
4412
  try {
4394
- this.session.clearSshSandbox();
4413
+ this.session.clearRemoteSandbox();
4414
+ await this.reloadResourcesAfterBackendChange();
4395
4415
  this.updateToolBackendStatus();
4396
- this.showStatus("SSH sandbox cleared");
4416
+ this.showStatus("Remote backend cleared");
4397
4417
  }
4398
4418
  catch (error) {
4399
4419
  this.showError(error instanceof Error ? error.message : String(error));
4400
4420
  }
4401
4421
  return;
4402
4422
  }
4403
- const [targetArg, cwdArg] = args.split(/\s+/, 2);
4423
+ const [kind, targetArg, cwdArg] = args.split(/\s+/, 3);
4424
+ if (kind !== "ssh" && kind !== "daemon") {
4425
+ this.showWarning("Usage: /remote <ssh|daemon> <url> [path]");
4426
+ return;
4427
+ }
4404
4428
  if (!targetArg) {
4405
- this.showWarning("Usage: /ssh-sandbox <user@host[:/path]> [path]");
4429
+ this.showWarning(kind === "ssh" ? "Usage: /remote ssh <user@host[:/path]> [path]" : "Usage: /remote daemon <ws://url>");
4406
4430
  return;
4407
4431
  }
4408
- const separatorIndex = targetArg.indexOf(":");
4409
- const remote = separatorIndex === -1 ? targetArg : targetArg.slice(0, separatorIndex);
4410
- const cwd = cwdArg ?? (separatorIndex === -1 ? undefined : targetArg.slice(separatorIndex + 1));
4411
4432
  try {
4412
- const info = await this.session.configureSshSandbox({ remote, cwd });
4433
+ const info = kind === "ssh"
4434
+ ? await this.session.configureRemoteSandbox({
4435
+ type: "ssh",
4436
+ ...this.parseSshRemoteTarget(targetArg, cwdArg),
4437
+ })
4438
+ : await this.session.configureRemoteSandbox({ type: "daemon", url: targetArg });
4439
+ await this.reloadResourcesAfterBackendChange();
4413
4440
  this.updateToolBackendStatus();
4414
4441
  this.showStatus(this.formatToolBackendStatus(info));
4415
4442
  }
4416
4443
  catch (error) {
4417
- this.showError(`Failed to configure SSH sandbox: ${error instanceof Error ? error.message : String(error)}`);
4444
+ this.showError(`Failed to configure remote backend: ${error instanceof Error ? error.message : String(error)}`);
4418
4445
  }
4419
4446
  }
4447
+ parseSshRemoteTarget(targetArg, cwdArg) {
4448
+ const separatorIndex = targetArg.indexOf(":");
4449
+ const remote = separatorIndex === -1 ? targetArg : targetArg.slice(0, separatorIndex);
4450
+ const cwd = cwdArg ?? (separatorIndex === -1 ? undefined : targetArg.slice(separatorIndex + 1));
4451
+ return { remote, cwd };
4452
+ }
4420
4453
  handleSessionCommand() {
4421
4454
  const stats = this.session.getSessionStats();
4422
4455
  const sessionName = this.activeSession.getSessionName();