Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add autocomplete component #496

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion extensions/gnome-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"lint:fix": "eslint --fix src build-scripts && prettier --write src build-scripts types"
},
"devDependencies": {
"@eslint/js": "^9.18.0",
"@eslint/js": "^9.16.0",
"eslint": "9.18.0",
"globals": "^15.14.0",
"typescript": "^5.7.3",
Expand Down
4 changes: 2 additions & 2 deletions extensions/gnome-legacy-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
"private": true,
"type": "module",
"devDependencies": {
"@eslint/js": "^9.18.0",
"@eslint/js": "^9.16.0",
"@gi.ts/cli": "^1.5.10",
"@gi.ts/lib": "^1.5.13",
"eslint": "^9.18.0",
"eslint": "^9.16.0",
"globals": "^15.14.0"
},
"scripts": {
Expand Down
6 changes: 3 additions & 3 deletions extensions/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@
}
},
"devDependencies": {
"@eslint/js": "^9.18.0",
"@eslint/js": "^9.16.0",
"@types/glob": "^8.1.0",
"@types/mocha": "^10.0.10",
"@types/node": "^22.10.6",
"@types/node": "^22.10.5",
"@types/vscode": "~1.80.0",
"@vscode/test-electron": "^2.4.1",
"@vscode/vsce": "^2.32.0",
"eslint": "^9.18.0",
"eslint": "^9.16.0",
"glob": "^11.0.1",
"globals": "^15.14.0",
"mocha": "^10.8.2",
Expand Down
7 changes: 5 additions & 2 deletions packages/api-bindings-wrappers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
"clean": "rm -rf dist"
},
"dependencies": {
"@aws/amazon-q-developer-cli-api-bindings": "workspace:~",
"@aws/amazon-q-developer-cli-api-bindings": "workspace:^",
"@aws/amazon-q-developer-cli-ipc-client-core": "workspace:^",
"@aws/amazon-q-developer-cli-proto": "workspace:^",
"@bufbuild/protobuf": "2.2.3",
"loglevel": "^1.9.2"
},
"devDependencies": {
Expand All @@ -32,7 +35,7 @@
"@amzn/types": "workspace:^",
"@aws/amazon-q-developer-cli-shared": "workspace:^",
"@withfig/autocomplete-types": "^1.31.0",
"eslint": "^9.18.0",
"eslint": "^9.16.0",
"prettier": "^3.4.2",
"typescript": "^5.7.3"
}
Expand Down
39 changes: 28 additions & 11 deletions packages/api-bindings-wrappers/src/executeCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@
* vitest is not able to mock it (because of esm restrictions).
*/
import { withTimeout } from "@aws/amazon-q-developer-cli-shared/utils";
import { Process } from "@aws/amazon-q-developer-cli-api-bindings";
import logger from "loglevel";
import { IpcClient } from "../../ipc-client-core/dist/index.js";
import {
DurationSchema,
EnvironmentVariableSchema,
} from "@aws/amazon-q-developer-cli-proto/fig_common";
import { RunProcessRequestSchema } from "@aws/amazon-q-developer-cli-proto/remote";
import { create } from "@bufbuild/protobuf";

export const cleanOutput = (output: string) =>
output
Expand All @@ -17,23 +23,34 @@ export const cleanOutput = (output: string) =>
.replace(/\n+$/, ""); // strips new lines from end of output

export const executeCommandTimeout = async (
ipcClient: IpcClient,
input: Fig.ExecuteCommandInput,
timeout = window.fig.constants?.os === "windows" ? 20000 : 5000,
timeout = window?.fig?.constants?.os === "windows" ? 20000 : 5000,
): Promise<Fig.ExecuteCommandOutput> => {
const command = [input.command, ...input.args].join(" ");
const command = [input.command, ...(input.args ?? [])].join(" ");
try {
logger.info(`About to run shell command '${command}'`);
const start = performance.now();
const result = await withTimeout(
Math.max(timeout, input.timeout ?? 0),
Process.run({
executable: input.command,
args: input.args,
environment: input.env,
workingDirectory: input.cwd,
terminalSessionId: window.globalTerminalSessionId,
timeout: input.timeout,
}),
ipcClient.runProcess(
window.globalTerminalSessionId ?? "",
create(RunProcessRequestSchema, {
executable: input.command,
arguments: input.args,
env: Object.entries(input.env ?? {}).map(([key, value]) => {
return create(EnvironmentVariableSchema, {
key,
value,
});
}),
workingDirectory: input.cwd,
timeout: create(DurationSchema, {
secs: BigInt(Math.floor(timeout / 1000)),
nanos: (timeout % 1000) * 1000000,
}),
}),
),
);
const end = performance.now();
logger.info(`Result of shell command '${command}'`, {
Expand Down
178 changes: 91 additions & 87 deletions packages/api-bindings-wrappers/src/executeCommandWrappers.ts
Original file line number Diff line number Diff line change
@@ -1,102 +1,106 @@
import { Process } from "@aws/amazon-q-developer-cli-api-bindings";
import { withTimeout } from "@aws/amazon-q-developer-cli-shared/utils";
import { createErrorInstance } from "@aws/amazon-q-developer-cli-shared/errors";
import logger from "loglevel";
import { cleanOutput, executeCommandTimeout } from "./executeCommand.js";
import { fread } from "./fs.js";
// import { Process } from "@aws/amazon-q-developer-cli-api-bindings";
// import { withTimeout } from "@aws/amazon-q-developer-cli-shared/utils";
// import { createErrorInstance } from "@aws/amazon-q-developer-cli-shared/errors";
// import logger from "loglevel";
// import { cleanOutput, executeCommandTimeout } from "./executeCommand.js";
// import { fread } from "./fs.js";

export const LoginShellError = createErrorInstance("LoginShellError");
import { IpcClient } from "../../ipc-client-core/dist/index.js";
import { executeCommandTimeout } from "./executeCommand.js";

const DONE_SOURCING_OSC = "\u001b]697;DoneSourcing\u0007";
// export const LoginShellError = createErrorInstance("LoginShellError");

let etcShells: Promise<string[]> | undefined;
// const DONE_SOURCING_OSC = "\u001b]697;DoneSourcing\u0007";

const getShellExecutable = async (shellName: string) => {
if (!etcShells) {
etcShells = fread("/etc/shells").then((shells) =>
shells
.split("\n")
.map((line) => line.trim())
.filter((line) => line && !line.startsWith("#")),
);
}
// let etcShells: Promise<string[]> | undefined;

try {
return (
(await etcShells).find((shell) => shell.includes(shellName)) ??
(
await executeCommandTimeout({
command: "/usr/bin/which",
args: [shellName],
})
).stdout
);
} catch (_) {
return undefined;
}
};
// const getShellExecutable = async (shellName: string) => {
// if (!etcShells) {
// etcShells = fread("/etc/shells").then((shells) =>
// shells
// .split("\n")
// .map((line) => line.trim())
// .filter((line) => line && !line.startsWith("#")),
// );
// }

// try {
// return (
// (await etcShells).find((shell) => shell.includes(shellName)) ??
// (
// await executeCommandTimeout({
// command: "/usr/bin/which",
// args: [shellName],
// })
// ).stdout
// );
// } catch (_) {
// return undefined;
// }
// };

export const executeLoginShell = async ({
command,
executable,
shell,
timeout,
command: _command,
executable: _executable,
shell: _shell,
timeout: _timeout,
}: {
command: string;
executable?: string;
shell?: string;
timeout?: number;
}): Promise<string> => {
let exe = executable;
if (!exe) {
if (!shell) {
throw new LoginShellError("Must pass shell or executable");
}
exe = await getShellExecutable(shell);
if (!exe) {
throw new LoginShellError(`Could not find executable for ${shell}`);
}
}
const flags = window.fig.constants?.os === "linux" ? "-lc" : "-lic";

const process = Process.run({
executable: exe,
args: [flags, command],
terminalSessionId: window.globalTerminalSessionId,
timeout,
});

try {
logger.info(`About to run login shell command '${command}'`, {
separateProcess: Boolean(window.f.Process),
shell: exe,
});
const start = performance.now();
const result = await withTimeout(
timeout ?? 5000,
process.then((output) => {
if (output.exitCode !== 0) {
logger.warn(
`Command ${command} exited with exit code ${output.exitCode}: ${output.stderr}`,
);
}
return cleanOutput(output.stdout);
}),
);
const idx =
result.lastIndexOf(DONE_SOURCING_OSC) + DONE_SOURCING_OSC.length;
const trimmed = result.slice(idx);
const end = performance.now();
logger.info(`Result of login shell command '${command}'`, {
result: trimmed,
time: end - start,
});
return trimmed;
} catch (err) {
logger.error(`Error running login shell command '${command}'`, { err });
throw err;
}
throw new Error("Not implemented");
// let exe = executable;
// if (!exe) {
// if (!shell) {
// throw new LoginShellError("Must pass shell or executable");
// }
// exe = await getShellExecutable(shell);
// if (!exe) {
// throw new LoginShellError(`Could not find executable for ${shell}`);
// }
// }
// const flags = window?.fig?.constants?.os === "linux" ? "-lc" : "-lic";
// const process = Process.run({
// executable: exe,
// args: [flags, command],
// terminalSessionId: window.globalTerminalSessionId,
// timeout,
// });
// try {
// logger.info(`About to run login shell command '${command}'`, {
// separateProcess: Boolean(window.f.Process),
// shell: exe,
// });
// const start = performance.now();
// const result = await withTimeout(
// timeout ?? 5000,
// process.then((output) => {
// if (output.exitCode !== 0) {
// logger.warn(
// `Command ${command} exited with exit code ${output.exitCode}: ${output.stderr}`,
// );
// }
// return cleanOutput(output.stdout);
// }),
// );
// const idx =
// result.lastIndexOf(DONE_SOURCING_OSC) + DONE_SOURCING_OSC.length;
// const trimmed = result.slice(idx);
// const end = performance.now();
// logger.info(`Result of login shell command '${command}'`, {
// result: trimmed,
// time: end - start,
// });
// return trimmed;
// } catch (err) {
// logger.error(`Error running login shell command '${command}'`, { err });
// throw err;
// }
};

export const executeCommand: Fig.ExecuteCommandFunction = (args) =>
executeCommandTimeout(args);
export const executeCommand: (
ipcClient: IpcClient,
) => Fig.ExecuteCommandFunction = (ipcClient) => (args) =>
executeCommandTimeout(ipcClient, args);
7 changes: 2 additions & 5 deletions packages/api-bindings/codegen/generate-requests.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { file_fig as file } from "@aws/amazon-q-developer-cli-proto/fig";
import packageJson from "@aws/amazon-q-developer-cli-proto/package.json";
import { CodeBlockWriter, IndentationText, Project } from "ts-morph";
import { readFileSync } from "node:fs";
import { join, dirname } from "node:path";
Expand Down Expand Up @@ -124,8 +125,6 @@ const [requestsWithMatchingResponses, otherRequests] = requestTypes

const endpoint = normalize(request);

console.log(endpoint, requestTypes);

if (responseTypes.indexOf(`${endpoint}Response`) !== -1) {
return [matchingResponse.concat([request]), other];
}
Expand All @@ -136,9 +135,7 @@ const [requestsWithMatchingResponses, otherRequests] = requestTypes

console.log(requestsWithMatchingResponses, otherRequests);

const protoVersion = JSON.parse(
readFileSync(join(__dirname, "../../../proto/package.json"), "utf8"),
).version;
const protoVersion = packageJson.version;

const sourceFile = project.createSourceFile(
join(__dirname, "../src/requests.ts"),
Expand Down
4 changes: 2 additions & 2 deletions packages/api-bindings/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
"@amzn/eslint-config": "workspace:^",
"@amzn/tsconfig": "workspace:^",
"@tsconfig/recommended": "^1.0.8",
"@types/node": "^22.10.6",
"@types/node": "^22.10.5",
"@typescript/analyze-trace": "^0.10.1",
"eslint": "^9.18.0",
"eslint": "^9.16.0",
"lint-staged": "^15.3.0",
"prettier": "^3.4.2",
"ts-morph": "^25.0.0",
Expand Down
1 change: 0 additions & 1 deletion packages/api-bindings/src/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export function page(
name: string,
properties: Record<string, Property>,
) {
// See more: https://segment.com/docs/connections/spec/page/
const props = properties;
props.title = document.title;
props.path = window.location.pathname;
Expand Down
9 changes: 6 additions & 3 deletions packages/autocomplete-parser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@
"clean": "rm -rf dist"
},
"dependencies": {
"@aws/amazon-q-developer-cli-api-bindings-wrappers": "workspace:^",
"@aws/amazon-q-developer-cli-api-bindings": "workspace:^",
"@aws/amazon-q-developer-cli-api-bindings-wrappers": "workspace:^",
"@aws/amazon-q-developer-cli-ipc-client-core": "workspace:^",
"@aws/amazon-q-developer-cli-proto": "workspace:^",
"@aws/amazon-q-developer-cli-shell-parser": "workspace:^",
"@bufbuild/protobuf": "2.2.3",
"@fig/autocomplete-generators": "^2.4.0",
"@fig/autocomplete-helpers": "^2.0.0",
"@fig/autocomplete-helpers": "^1.0.7",
"@fig/autocomplete-shared": "^1.1.2",
"loglevel": "^1.9.2",
"semver": "^7.6.3",
Expand All @@ -38,7 +41,7 @@
"@aws/amazon-q-developer-cli-shared": "workspace:^",
"@types/semver": "^7.5.8",
"@withfig/autocomplete-types": "^1.31.0",
"eslint": "^9.18.0",
"eslint": "^9.16.0",
"typescript": "^5.7.3",
"vitest": "^2.1.8"
}
Expand Down
Loading
Loading