mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-08-28 08:35:57 +00:00
feat: add pure ssh2 remote operations
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import type { PermissionsService } from "@gotgenes/pi-permission-system";
|
||||
import {
|
||||
formatSshPermissionInput,
|
||||
installSshPermissionIntegration,
|
||||
type SshPermissionConnection,
|
||||
} from "../permission-integration.ts";
|
||||
|
||||
function makeService() {
|
||||
const formatters = new Map<string, (input: Record<string, unknown>) => string | undefined>();
|
||||
const extractors = new Map<string, (input: Record<string, unknown>) => string | undefined>();
|
||||
const service = {
|
||||
registerToolInputFormatter(name: string, formatter: (input: Record<string, unknown>) => string | undefined) {
|
||||
formatters.set(name, formatter);
|
||||
return () => formatters.delete(name);
|
||||
},
|
||||
registerToolAccessExtractor(name: string, extractor: (input: Record<string, unknown>) => string | undefined) {
|
||||
extractors.set(name, extractor);
|
||||
return () => extractors.delete(name);
|
||||
},
|
||||
} as unknown as PermissionsService;
|
||||
return { service, formatters, extractors };
|
||||
}
|
||||
|
||||
function makePi() {
|
||||
const hooks = new Map<string, Array<() => void>>();
|
||||
const eventHooks = new Map<string, Array<() => void>>();
|
||||
const add = (map: Map<string, Array<() => void>>, name: string, handler: () => void) => {
|
||||
map.set(name, [...(map.get(name) ?? []), handler]);
|
||||
};
|
||||
return {
|
||||
api: {
|
||||
on: (name: string, handler: () => void) => add(hooks, name, handler),
|
||||
events: { on: (name: string, handler: () => void) => add(eventHooks, name, handler) },
|
||||
},
|
||||
emit: (name: string) => hooks.get(name)?.forEach((handler) => handler()),
|
||||
emitEvent: (name: string) => eventHooks.get(name)?.forEach((handler) => handler()),
|
||||
};
|
||||
}
|
||||
|
||||
const connection: SshPermissionConnection = {
|
||||
remote: "packaging-server",
|
||||
port: 2222,
|
||||
remoteCwd: "/srv/build",
|
||||
};
|
||||
|
||||
test("formats the SSH target and bounded operation details", () => {
|
||||
assert.equal(
|
||||
formatSshPermissionInput("ssh_read", { path: "src/main.ts", offset: 5, limit: 20 }, connection),
|
||||
"SSH target 'packaging-server:2222' in remote cwd '/srv/build'; read remote path 'src/main.ts', offset 5, limit 20",
|
||||
);
|
||||
assert.equal(
|
||||
formatSshPermissionInput("ssh_write", { path: "dist/a.txt", content: "one\ntwo" }, connection),
|
||||
"SSH target 'packaging-server:2222' in remote cwd '/srv/build'; write remote path 'dist/a.txt' (2 lines, 7 characters)",
|
||||
);
|
||||
assert.equal(
|
||||
formatSshPermissionInput("ssh_grep", { pattern: "TODO", path: "src", include: "*.ts", limit: 25 }, connection),
|
||||
"SSH target 'packaging-server:2222' in remote cwd '/srv/build'; search remote file contents under 'src', for 'TODO', limit 25, file glob '*.ts'",
|
||||
);
|
||||
});
|
||||
|
||||
test("registers previews and disables local path extraction for remote file tools", () => {
|
||||
const { service, formatters, extractors } = makeService();
|
||||
const pi = makePi();
|
||||
const dispose = installSshPermissionIntegration(
|
||||
pi.api as never,
|
||||
() => connection,
|
||||
{ getPermissionsService: () => service, permissionsReadyChannel: "permissions:ready" },
|
||||
);
|
||||
|
||||
assert.deepEqual([...formatters.keys()], ["ssh_read", "ssh_write", "ssh_edit", "ssh_find", "ssh_grep", "ssh_bash"]);
|
||||
assert.deepEqual([...extractors.keys()], ["ssh_read", "ssh_write", "ssh_edit", "ssh_find", "ssh_grep"]);
|
||||
assert.equal(extractors.get("ssh_read")?.({ path: "/remote/secret" }), undefined);
|
||||
assert.equal(extractors.get("ssh_grep")?.({ path: "/remote/src" }), undefined);
|
||||
assert.match(formatters.get("ssh_bash")?.({ command: "git push" }) ?? "", /packaging-server:2222/);
|
||||
|
||||
dispose();
|
||||
assert.equal(formatters.size, 0);
|
||||
assert.equal(extractors.size, 0);
|
||||
});
|
||||
|
||||
test("registers when the permission service becomes ready and cleans up on shutdown", () => {
|
||||
const { service, formatters, extractors } = makeService();
|
||||
const pi = makePi();
|
||||
let published: PermissionsService | undefined;
|
||||
installSshPermissionIntegration(pi.api as never, () => connection, {
|
||||
getPermissionsService: () => published,
|
||||
permissionsReadyChannel: "permissions:ready",
|
||||
});
|
||||
assert.equal(formatters.size, 0);
|
||||
|
||||
published = service;
|
||||
pi.emitEvent("permissions:ready");
|
||||
assert.equal(formatters.size, 6);
|
||||
assert.equal(extractors.size, 5);
|
||||
|
||||
pi.emit("session_shutdown");
|
||||
assert.equal(formatters.size, 0);
|
||||
assert.equal(extractors.size, 0);
|
||||
});
|
||||
Reference in New Issue
Block a user