naisys 1.0.1

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 (48) hide show
  1. package/.env.example +15 -0
  2. package/LICENSE.md +7 -0
  3. package/README.md +125 -0
  4. package/agents/example.yaml +34 -0
  5. package/dist/__tests__/utils/output.test.js +22 -0
  6. package/dist/__tests__/utils/output.test.js.map +1 -0
  7. package/dist/__tests__/utils/utilities.test.js +42 -0
  8. package/dist/__tests__/utils/utilities.test.js.map +1 -0
  9. package/dist/apps/llmail.js +350 -0
  10. package/dist/apps/llmail.js.map +1 -0
  11. package/dist/apps/llmynx.js +229 -0
  12. package/dist/apps/llmynx.js.map +1 -0
  13. package/dist/command/commandHandler.js +151 -0
  14. package/dist/command/commandHandler.js.map +1 -0
  15. package/dist/command/commandLoop.js +176 -0
  16. package/dist/command/commandLoop.js.map +1 -0
  17. package/dist/command/promptBuilder.js +133 -0
  18. package/dist/command/promptBuilder.js.map +1 -0
  19. package/dist/command/shellCommand.js +36 -0
  20. package/dist/command/shellCommand.js.map +1 -0
  21. package/dist/command/shellWrapper.js +179 -0
  22. package/dist/command/shellWrapper.js.map +1 -0
  23. package/dist/config.js +46 -0
  24. package/dist/config.js.map +1 -0
  25. package/dist/llm/contextManager.js +127 -0
  26. package/dist/llm/contextManager.js.map +1 -0
  27. package/dist/llm/costTracker.js +43 -0
  28. package/dist/llm/costTracker.js.map +1 -0
  29. package/dist/llm/llModels.js +52 -0
  30. package/dist/llm/llModels.js.map +1 -0
  31. package/dist/llm/llmDtos.js +8 -0
  32. package/dist/llm/llmDtos.js.map +1 -0
  33. package/dist/llm/llmService.js +113 -0
  34. package/dist/llm/llmService.js.map +1 -0
  35. package/dist/naisys.js +7 -0
  36. package/dist/naisys.js.map +1 -0
  37. package/dist/utils/dbUtils.js +37 -0
  38. package/dist/utils/dbUtils.js.map +1 -0
  39. package/dist/utils/inputMode.js +18 -0
  40. package/dist/utils/inputMode.js.map +1 -0
  41. package/dist/utils/logService.js +116 -0
  42. package/dist/utils/logService.js.map +1 -0
  43. package/dist/utils/output.js +38 -0
  44. package/dist/utils/output.js.map +1 -0
  45. package/dist/utils/utilities.js +40 -0
  46. package/dist/utils/utilities.js.map +1 -0
  47. package/naisys.sh +56 -0
  48. package/package.json +70 -0
@@ -0,0 +1,133 @@
1
+ import chalk from "chalk";
2
+ import * as events from "events";
3
+ import * as readline from "readline";
4
+ import * as llmail from "../apps/llmail.js";
5
+ import * as config from "../config.js";
6
+ import * as contextManager from "../llm/contextManager.js";
7
+ import * as inputMode from "../utils/inputMode.js";
8
+ import { InputMode } from "../utils/inputMode.js";
9
+ import * as output from "../utils/output.js";
10
+ import * as shellWrapper from "./shellWrapper.js";
11
+ // When actual output is entered by the user we want to cancel any auto-continue timers and/or wake on message
12
+ // We don't want to cancel if the user is entering a chords like ctrl+b then down arrow, when using tmux
13
+ // This is why we can't put the event listener on the standard process.stdin/keypress event.
14
+ // There is no 'data entered' output event so this monkey patch does that
15
+ const _writeEventName = "write";
16
+ const _outputEmitter = new events.EventEmitter();
17
+ const _originalWrite = process.stdout.write.bind(process.stdout);
18
+ process.stdout.write = (...args) => {
19
+ _outputEmitter.emit(_writeEventName, false, ...args);
20
+ return _originalWrite.apply(process.stdout, args);
21
+ };
22
+ const _readlineInterface = readline.createInterface({
23
+ input: process.stdin,
24
+ output: process.stdout,
25
+ });
26
+ // Happens when ctrl+c is pressed
27
+ let readlineInterfaceClosed = false;
28
+ _readlineInterface.on("close", () => {
29
+ readlineInterfaceClosed = true;
30
+ output.error("Readline interface closed");
31
+ });
32
+ export async function getPrompt(pauseSeconds, wakeOnMessage) {
33
+ const promptSuffix = inputMode.current == InputMode.Debug ? "#" : "$";
34
+ const tokenMax = config.tokenMax;
35
+ const usedTokens = contextManager.getTokenCount();
36
+ const tokenSuffix = ` [Tokens: ${usedTokens}/${tokenMax}]`;
37
+ let pause = "";
38
+ if (inputMode.current == InputMode.Debug) {
39
+ if (pauseSeconds) {
40
+ pause += ` [Paused: ${pauseSeconds}s]`;
41
+ }
42
+ if (wakeOnMessage) {
43
+ pause += " [WakeOnMsg]";
44
+ }
45
+ }
46
+ return `${await getUserHostPathPrompt()}${tokenSuffix}${pause}${promptSuffix} `;
47
+ }
48
+ export async function getUserHostPathPrompt() {
49
+ const currentPath = await shellWrapper.getCurrentPath();
50
+ return `${getUserHostPrompt()}:${currentPath}`;
51
+ }
52
+ export function getUserHostPrompt() {
53
+ const username = inputMode.current == InputMode.Debug ? "debug" : config.agent.username;
54
+ return `${username}@${config.hostname}`;
55
+ }
56
+ export function getInput(commandPrompt, pauseSeconds, wakeOnMessage) {
57
+ return new Promise((resolve) => {
58
+ const questionController = new AbortController();
59
+ let timeout;
60
+ let interval;
61
+ let timeoutCancelled = false;
62
+ if (readlineInterfaceClosed) {
63
+ output.error("Hanging because readline interface is closed.");
64
+ return;
65
+ }
66
+ /** Cancels waiting for user input */
67
+ function onStdinWrite_cancelTimers(questionAborted, buffer) {
68
+ // Don't allow console escape commands like \x1B[1G to cancel the timeout
69
+ if (timeoutCancelled || (buffer && !/^[a-zA-Z0-9 ]+$/.test(buffer))) {
70
+ return;
71
+ }
72
+ timeoutCancelled = true;
73
+ _outputEmitter.off(_writeEventName, onStdinWrite_cancelTimers);
74
+ clearTimeout(timeout);
75
+ clearInterval(interval);
76
+ timeout = undefined;
77
+ interval = undefined;
78
+ if (questionAborted) {
79
+ return;
80
+ }
81
+ // Else timeout interrupted by user input, clear out the timeout information from the prompt
82
+ // to prevent the user from thinking the timeout still applies
83
+ let pausePos = commandPrompt.indexOf("[Paused:");
84
+ pausePos =
85
+ pausePos == -1 ? commandPrompt.indexOf("[WakeOnMsg]") : pausePos;
86
+ if (pausePos > 0) {
87
+ // BUG: When the user hits delete, the prompt is reset to the original which is confusing as user will think timeout is still active
88
+ // Fix is probably to reset the entire the question when the timeout is interrupted
89
+ const charsBack = commandPrompt.length - pausePos - 1; // pluse 1 for the space after the #
90
+ readline.moveCursor(process.stdout, -charsBack, 0);
91
+ process.stdout.write("-".repeat(charsBack - 3));
92
+ readline.moveCursor(process.stdout, 3, 0);
93
+ }
94
+ }
95
+ _readlineInterface.question(chalk.greenBright(commandPrompt), { signal: questionController.signal }, (answer) => {
96
+ resolve(answer);
97
+ });
98
+ // If user starts typing in prompt, cancel any auto timeouts or wake on msg
99
+ _outputEmitter.on(_writeEventName, onStdinWrite_cancelTimers);
100
+ const abortQuestion = () => {
101
+ onStdinWrite_cancelTimers(true);
102
+ questionController.abort();
103
+ resolve("");
104
+ };
105
+ if (pauseSeconds) {
106
+ timeout = setTimeout(() => {
107
+ abortQuestion();
108
+ }, pauseSeconds * 1000);
109
+ }
110
+ if (wakeOnMessage) {
111
+ // Break timeout if new message is received
112
+ let firstError = true;
113
+ interval = setInterval(() => {
114
+ // setInterval does not support async/await, but that's okay as this call easily runs within the 3s interval
115
+ llmail
116
+ .getUnreadThreads()
117
+ .then((unreadThreadIds) => {
118
+ if (unreadThreadIds.length) {
119
+ abortQuestion();
120
+ }
121
+ })
122
+ // Catch and log errors, but don't break the interval on hopefully an intermittent error
123
+ .catch((e) => {
124
+ if (firstError) {
125
+ output.error(`Mail interval check error: ${e}`);
126
+ firstError = false;
127
+ }
128
+ });
129
+ }, 3000);
130
+ }
131
+ });
132
+ }
133
+ //# sourceMappingURL=promptBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promptBuilder.js","sourceRoot":"","sources":["../../src/command/promptBuilder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import * as contextManager from "../llm/contextManager.js";
2
+ import * as inputMode from "../utils/inputMode.js";
3
+ import { InputMode } from "../utils/inputMode.js";
4
+ import * as shellWrapper from "./shellWrapper.js";
5
+ export async function handleCommand(input) {
6
+ const cmdParams = input.split(" ");
7
+ const response = {
8
+ hasErrors: true,
9
+ };
10
+ // Route user to context friendly edit commands that can read/write the entire file in one go
11
+ if (["nano", "vi", "vim"].includes(cmdParams[0])) {
12
+ await contextManager.append(`${cmdParams[0]} not supported. Use 'cat' to view a file and 'cat > filename << EOF' to write a file`);
13
+ return response;
14
+ }
15
+ if (cmdParams[0] == "lynx" && cmdParams[1] != "--dump") {
16
+ await contextManager.append(`Interactive mode with lynx is not supported. Use --dump with lynx to view a website`);
17
+ return response;
18
+ }
19
+ if (cmdParams[0] == "exit") {
20
+ if (inputMode.current == InputMode.LLM) {
21
+ await contextManager.append("Use 'endsession' to end the session and clear the console log.");
22
+ }
23
+ else if (inputMode.current == InputMode.Debug) {
24
+ await shellWrapper.terminate();
25
+ response.terminate = true;
26
+ }
27
+ return response;
28
+ }
29
+ const output = await shellWrapper.executeCommand(input);
30
+ if (output.value) {
31
+ await contextManager.append(output.value);
32
+ }
33
+ response.hasErrors = output.hasErrors;
34
+ return response;
35
+ }
36
+ //# sourceMappingURL=shellCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shellCommand.js","sourceRoot":"","sources":["../../src/command/shellCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,cAAc,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,YAAY,MAAM,mBAAmB,CAAC;AAOlD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAa;IAEb,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,QAAQ,GAA+B;QAC3C,SAAS,EAAE,IAAI;KAChB,CAAC;IAEF,6FAA6F;IAC7F,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,MAAM,cAAc,CAAC,MAAM,CACzB,GAAG,SAAS,CAAC,CAAC,CAAC,sFAAsF,CACtG,CAAC;QAEF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,SAAS,CAAC,CAAC,CAAC,IAAI,MAAM,IAAI,SAAS,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,CAAC;QACvD,MAAM,cAAc,CAAC,MAAM,CACzB,qFAAqF,CACtF,CAAC;QAEF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,SAAS,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,GAAG,EAAE,CAAC;YACvC,MAAM,cAAc,CAAC,MAAM,CACzB,gEAAgE,CACjE,CAAC;QACJ,CAAC;aAAM,IAAI,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;YAChD,MAAM,YAAY,CAAC,SAAS,EAAE,CAAC;YAC/B,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC;QAC5B,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAExD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,QAAQ,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IAEtC,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,179 @@
1
+ import { spawn } from "child_process";
2
+ import * as fs from "fs";
3
+ import * as os from "os";
4
+ import * as config from "../config.js";
5
+ import * as output from "../utils/output.js";
6
+ import { naisysToHostPath } from "../utils/utilities.js";
7
+ var ShellEvent;
8
+ (function (ShellEvent) {
9
+ ShellEvent["Ouptput"] = "stdout";
10
+ ShellEvent["Error"] = "stderr";
11
+ ShellEvent["Exit"] = "exit";
12
+ })(ShellEvent || (ShellEvent = {}));
13
+ let _process;
14
+ //let _log = "";
15
+ let _commandOutput = "";
16
+ let _hasErrors = false;
17
+ let _currentPath;
18
+ let _resolveCurrentCommand;
19
+ let _currentCommandTimeout;
20
+ const _commandDelimiter = "__COMMAND_END_X7YUTT__";
21
+ async function ensureOpen() {
22
+ if (_process) {
23
+ return;
24
+ }
25
+ //_log = "";
26
+ resetCommand();
27
+ const spawnProcess = os.platform() === "win32" ? "wsl" : "bash";
28
+ _process = spawn(spawnProcess, [], { stdio: "pipe" });
29
+ _process.stdout.on("data", (data) => {
30
+ processOutput(data.toString(), ShellEvent.Ouptput);
31
+ });
32
+ _process.stderr.on("data", (data) => {
33
+ processOutput(data.toString(), ShellEvent.Error);
34
+ });
35
+ _process.on("close", (code) => {
36
+ processOutput(`${code}`, ShellEvent.Exit);
37
+ _process = undefined;
38
+ });
39
+ // Init users home dir on first run, on shell crash/rerun go back to the current path
40
+ if (!_currentPath) {
41
+ output.comment("NEW SHELL OPENED. PID: " + _process.pid);
42
+ commentIfNotEmpty(await executeCommand(`mkdir -p ${config.naisysFolder}/home/` + config.agent.username));
43
+ commentIfNotEmpty(await executeCommand(`cd ${config.naisysFolder}/home/` + config.agent.username));
44
+ }
45
+ else {
46
+ output.comment("SHELL RESTORED. PID: " + _process.pid);
47
+ commentIfNotEmpty(await executeCommand("cd " + _currentPath));
48
+ }
49
+ // Stop running commands if one fails
50
+ // Often the LLM will give us back all kinds of invalid commands, we want to break on the first one
51
+ // Unfortunately this also causes the shell to exit on failures, so we need to handle that
52
+ //commentIfNotEmpty(await executeCommand("set -e"));
53
+ }
54
+ /** Basically don't show anything in the console unless there is an error */
55
+ function commentIfNotEmpty(response) {
56
+ if (response.value) {
57
+ output.comment(response.value);
58
+ }
59
+ }
60
+ export function processOutput(dataStr, eventType) {
61
+ if (!_resolveCurrentCommand) {
62
+ output.comment(eventType + " without handler: " + dataStr);
63
+ return;
64
+ }
65
+ if (eventType === ShellEvent.Exit) {
66
+ output.error("SHELL EXITED. PID: " + (_process === null || _process === void 0 ? void 0 : _process.pid) + " CODE: " + dataStr);
67
+ }
68
+ else {
69
+ //_log += "OUTPUT: " + dataStr;
70
+ _commandOutput += dataStr;
71
+ }
72
+ if (eventType === ShellEvent.Error) {
73
+ _hasErrors = true;
74
+ //output += "stderr: ";
75
+ // parse out the line number from '-bash: line 999: '
76
+ /*if (dataStr.startsWith("-bash: line ")) {
77
+ output.error(dataStr);
78
+
79
+ const lineNum = dataStr.slice(11, dataStr.indexOf(": ", 11));
80
+ output.error(`Detected error on line ${lineNum} of output`);
81
+
82
+ // display the same line of _output
83
+ const logLines = _log.split("\n");
84
+ const lineIndex = parseInt(lineNum) - 1;
85
+ if (logLines.length > lineIndex) {
86
+ output.error(`Line ${lineIndex} in log: ` + logLines[lineIndex]);
87
+ }
88
+
89
+ // output all lines for debugging
90
+ for (let i = 0; i < logLines.length; i++) {
91
+ // if withing 10 lines of the error, show the line
92
+ //if (Math.abs(i - lineIndex) < 10) {
93
+ const lineStr = logLines[i].replace(/\n/g, "");
94
+ output.error(`${i}: ${lineStr}`);
95
+ //}
96
+ }
97
+ }*/
98
+ }
99
+ const delimiterIndex = _commandOutput.indexOf(_commandDelimiter);
100
+ if (delimiterIndex != -1 || eventType === ShellEvent.Exit) {
101
+ // trim everything after delimiter
102
+ _commandOutput = _commandOutput.slice(0, delimiterIndex);
103
+ const response = {
104
+ value: _commandOutput.trim(),
105
+ hasErrors: _hasErrors,
106
+ };
107
+ resetCommand();
108
+ _resolveCurrentCommand(response);
109
+ }
110
+ }
111
+ export async function executeCommand(command) {
112
+ /*if (command == "shelllog") {
113
+ _log.split("\n").forEach((line, i) => {
114
+ output.comment(`${i}. ${line}`);
115
+ });
116
+
117
+ return <CommandResponse>{
118
+ value: "",
119
+ hasErrors: false,
120
+ };
121
+ }*/
122
+ await ensureOpen();
123
+ if (_currentPath && command.trim().split("\n").length > 1) {
124
+ command = await runCommandFromScript(command);
125
+ }
126
+ return new Promise((resolve) => {
127
+ _resolveCurrentCommand = resolve;
128
+ const commandWithDelimiter = `${command.trim()}\necho "${_commandDelimiter} LINE:\${LINENO}"\n`;
129
+ //_log += "INPUT: " + commandWithDelimiter;
130
+ _process === null || _process === void 0 ? void 0 : _process.stdin.write(commandWithDelimiter);
131
+ // If no response after 5 seconds, kill and reset the shell, often hanging on some unescaped input
132
+ const timeoutSeconds = 5;
133
+ _currentCommandTimeout = setTimeout(() => {
134
+ if (_resolveCurrentCommand) {
135
+ _process === null || _process === void 0 ? void 0 : _process.kill();
136
+ output.error("SHELL TIMEMOUT/KILLED. PID: " + (_process === null || _process === void 0 ? void 0 : _process.pid));
137
+ resetProcess();
138
+ _resolveCurrentCommand({
139
+ value: `Error: Command timed out after ${timeoutSeconds} seconds.`,
140
+ hasErrors: true,
141
+ });
142
+ }
143
+ }, timeoutSeconds * 1000);
144
+ });
145
+ }
146
+ export async function getCurrentPath() {
147
+ await ensureOpen();
148
+ _currentPath = (await executeCommand("pwd")).value;
149
+ return _currentPath;
150
+ }
151
+ export async function terminate() {
152
+ /*const exitCode = */ await executeCommand("exit");
153
+ // For some reason showing the exit code clears the console
154
+ resetProcess();
155
+ }
156
+ function resetCommand() {
157
+ _commandOutput = "";
158
+ _hasErrors = false;
159
+ clearTimeout(_currentCommandTimeout);
160
+ }
161
+ function resetProcess() {
162
+ resetCommand();
163
+ _process === null || _process === void 0 ? void 0 : _process.removeAllListeners();
164
+ _process = undefined;
165
+ }
166
+ /** Wraps multi line commands in a script to make it easier to diagnose the source of errors based on line number
167
+ * May also help with common escaping errors */
168
+ function runCommandFromScript(command) {
169
+ const scriptPath = `${config.naisysFolder}/home/${config.agent.username}/.command.tmp.sh`;
170
+ // set -e causes the script to exit on any error
171
+ const scriptContent = `#!/bin/bash
172
+ set -e
173
+ cd ${_currentPath}
174
+ ${command.trim()}`;
175
+ // create/writewrite file
176
+ fs.writeFileSync(naisysToHostPath(scriptPath), scriptContent);
177
+ return `bash ${scriptPath}`;
178
+ }
179
+ //# sourceMappingURL=shellWrapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shellWrapper.js","sourceRoot":"","sources":["../../src/command/shellWrapper.ts"],"names":[],"mappings":"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"}
package/dist/config.js ADDED
@@ -0,0 +1,46 @@
1
+ import { program } from "commander";
2
+ import dotenv from "dotenv";
3
+ import * as fs from "fs";
4
+ import yaml from "js-yaml";
5
+ import { valueFromString } from "./utils/utilities.js";
6
+ program.argument("<agent-path>", "Path to agent configuration file").parse();
7
+ dotenv.config();
8
+ /** The system name that shows after the @ in the command prompt */
9
+ export const hostname = "naisys";
10
+ /** The number of tokens you want to limit a session to, independent of the LLM token max */
11
+ export const tokenMax = 4000;
12
+ /* .env is used for global configs across naisys, while agent configs for the specific agent */
13
+ export const naisysFolder = getEnv("NAISYS_FOLDER", true);
14
+ export const websiteFolder = getEnv("WEBSITE_FOLDER");
15
+ export const localLlmUrl = getEnv("LOCAL_LLM_URL");
16
+ export const localLlmName = getEnv("LOCAL_LLM_NAME");
17
+ export const openaiApiKey = getEnv("OPENAI_API_KEY");
18
+ export const googleApiKey = getEnv("GOOGLE_API_KEY");
19
+ export const agent = loadAgentConfig();
20
+ function getEnv(key, required) {
21
+ const value = process.env[key];
22
+ if (!value && required) {
23
+ throw `Config: Error, .env ${key} is not defined`;
24
+ }
25
+ return value;
26
+ }
27
+ function loadAgentConfig() {
28
+ const agentPath = program.args[0];
29
+ const checkAgentConfig = yaml.load(fs.readFileSync(agentPath, "utf8"));
30
+ // throw if any property is undefined
31
+ for (const key of [
32
+ "username",
33
+ "title",
34
+ "consoleModel",
35
+ "webModel",
36
+ "agentPrompt",
37
+ "spendLimitDollars",
38
+ // debugPauseSeconds and wakeOnMessage can be undefined
39
+ ]) {
40
+ if (!valueFromString(checkAgentConfig, key)) {
41
+ throw `Agent config: Error, ${key} is not defined`;
42
+ }
43
+ }
44
+ return checkAgentConfig;
45
+ }
46
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,CAAC,QAAQ,CAAC,cAAc,EAAE,kCAAkC,CAAC,CAAC,KAAK,EAAE,CAAC;AAE7E,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,mEAAmE;AACnE,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAAC;AAEjC,4FAA4F;AAC5F,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC;AAE7B,+FAA+F;AAE/F,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;AAC1D,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAEtD,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;AACnD,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAErD,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;AACrD,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAErD,MAAM,CAAC,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;AAEvC,SAAS,MAAM,CAAC,GAAW,EAAE,QAAkB;IAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK,IAAI,QAAQ,EAAE,CAAC;QACvB,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;IACpD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAcD,SAAS,eAAe;IACtB,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAElC,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAChC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CACpB,CAAC;IAEjB,qCAAqC;IACrC,KAAK,MAAM,GAAG,IAAI;QAChB,UAAU;QACV,OAAO;QACP,cAAc;QACd,UAAU;QACV,aAAa;QACb,mBAAmB;QACnB,uDAAuD;KACxD,EAAE,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,gBAAgB,EAAE,GAAG,CAAC,EAAE,CAAC;YAC5C,MAAM,wBAAwB,GAAG,iBAAiB,CAAC;QACrD,CAAC;IACH,CAAC;IAED,OAAO,gBAAgB,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,127 @@
1
+ import * as config from "../config.js";
2
+ import * as inputMode from "../utils/inputMode.js";
3
+ import { InputMode } from "../utils/inputMode.js";
4
+ import * as logService from "../utils/logService.js";
5
+ import * as output from "../utils/output.js";
6
+ import { OutputColor } from "../utils/output.js";
7
+ import * as utilities from "../utils/utilities.js";
8
+ import { valueFromString } from "../utils/utilities.js";
9
+ import { LlmRole } from "./llmDtos.js";
10
+ export var ContentSource;
11
+ (function (ContentSource) {
12
+ ContentSource["ConsolePrompt"] = "startPrompt";
13
+ ContentSource["LlmPromptResponse"] = "endPrompt";
14
+ ContentSource["Console"] = "console";
15
+ ContentSource["LLM"] = "llm";
16
+ })(ContentSource || (ContentSource = {}));
17
+ let _cachedSystemMessage = "";
18
+ export function getSystemMessage() {
19
+ if (_cachedSystemMessage) {
20
+ return _cachedSystemMessage;
21
+ }
22
+ // Fill out the templates in the agent prompt and stick it to the front of the system message
23
+ // A lot of the stipulations in here are to prevent common LLM mistakes
24
+ // Like we can't jump between standard and special commands in a single prompt, which the LLM will try to do if not warned
25
+ let agentPrompt = config.agent.agentPrompt;
26
+ agentPrompt = resolveTemplateVars(agentPrompt, "agent", config.agent);
27
+ agentPrompt = resolveTemplateVars(agentPrompt, "env", process.env);
28
+ const systemMessage = `${agentPrompt.trim()}
29
+
30
+ This is a command line interface presenting you with the next command prompt.
31
+ Make sure the read the command line rules in the MOTD carefully.
32
+ Don't try to guess the output of commands. Don't put commands in \`\`\` blocks.
33
+ For example when you run 'cat' or 'ls', don't write what you think the output will be. Let the system do that.
34
+ Your role is that of the user. The system will provide responses and next command prompt. Don't output your own command prompt.
35
+ Be careful when writing files through the command prompt with cat. Make sure to close and escape quotes properly.
36
+
37
+ NAISYS ${process.env.npm_package_version} Shell
38
+ Welcome back ${config.agent.username}!
39
+ MOTD:
40
+ Date: ${new Date().toLocaleString()}
41
+ Commands:
42
+ Standard Unix commands are available
43
+ vi and nano are not supported
44
+ Read/write entire files in a single command with cat
45
+ Do not input notes after the prompt. Only valid commands.
46
+ Special Commands: (Don't mix with standard commands on the same prompt)
47
+ llmail: A local mail system for communicating with your team
48
+ llmynx: A context optimized web browser. Enter 'llmynx help' to learn how to use it
49
+ comment <thought>: Any non-command output like thinking out loud, prefix with the 'comment' command
50
+ pause <seconds>: Pause for <seconds> or indeterminite if no argument is provided. Auto wake up on new mail message
51
+ endsession <note>: Ends this session, clears the console log and context.
52
+ The note should help you prevent from having to find your bearings in the next session.
53
+ The note should contain your next goal. Important things should you remember. Maybe a task list.
54
+ Try to keep the note around 400 tokens.
55
+ Tokens:
56
+ The console log can only hold a certain number of 'tokens' that is specified in the prompt
57
+ Make sure to call endsession before the limit is hit so you can continue your work with a fresh console`;
58
+ _cachedSystemMessage = systemMessage;
59
+ return systemMessage;
60
+ }
61
+ function resolveTemplateVars(templateString, allowedVarString, mappedVar) {
62
+ const pattern = new RegExp(`\\$\\{${allowedVarString}\\.([^}]+)\\}`, "g");
63
+ return templateString.replace(pattern, (match, key) => {
64
+ const value = valueFromString(mappedVar, key);
65
+ if (value === undefined) {
66
+ throw `Agent config: Error, ${key} is not defined`;
67
+ }
68
+ return value;
69
+ });
70
+ }
71
+ export let messages = [];
72
+ export async function append(text, source = ContentSource.Console) {
73
+ // Debug runs in a shadow mode where their activity is not recorded in the context
74
+ // Mark with a # to make it clear that it is not part of the context
75
+ if (inputMode.current === InputMode.Debug) {
76
+ output.comment(text);
77
+ return;
78
+ }
79
+ // Else otherwise we're running in LLM mode
80
+ const role = source == ContentSource.ConsolePrompt || source == ContentSource.Console
81
+ ? LlmRole.User
82
+ : source == ContentSource.LlmPromptResponse || source == ContentSource.LLM
83
+ ? LlmRole.Assistant
84
+ : undefined;
85
+ if (!role) {
86
+ throw new Error("Invalid source");
87
+ }
88
+ // If last message is the same role then combine - Googl API requires alterntating roles
89
+ // TODO: Maybe dont do this here, but in the google api call
90
+ let combined = false;
91
+ if (messages.length > 0) {
92
+ const lastMessage = messages[messages.length - 1];
93
+ if (lastMessage.role == role) {
94
+ lastMessage.content += `\n${text}`;
95
+ combined = true;
96
+ await logService.update(lastMessage, text);
97
+ }
98
+ }
99
+ if (!combined) {
100
+ const llmMessage = { role, content: text };
101
+ llmMessage.logId = await logService.write(llmMessage);
102
+ messages.push(llmMessage);
103
+ }
104
+ // Prompts are manually added to the console log
105
+ if (source != ContentSource.ConsolePrompt &&
106
+ source != ContentSource.LlmPromptResponse) {
107
+ output.write(text, source == "llm" ? OutputColor.llm : OutputColor.console);
108
+ }
109
+ }
110
+ export function clear() {
111
+ messages = [];
112
+ }
113
+ export function getTokenCount() {
114
+ const sytemMessageTokens = utilities.getTokenCount(getSystemMessage());
115
+ return messages.reduce((acc, message) => {
116
+ return acc + utilities.getTokenCount(message.content);
117
+ }, sytemMessageTokens);
118
+ }
119
+ export function printContext() {
120
+ output.comment("#####################");
121
+ // output.comment(content);
122
+ messages.forEach((message) => {
123
+ output.comment(`${message.role}: ${message.content}`);
124
+ });
125
+ output.comment("#####################");
126
+ }
127
+ //# sourceMappingURL=contextManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contextManager.js","sourceRoot":"","sources":["../../src/llm/contextManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAc,OAAO,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,CAAN,IAAY,aAKX;AALD,WAAY,aAAa;IACvB,8CAA6B,CAAA;IAC7B,gDAA+B,CAAA;IAC/B,oCAAmB,CAAA;IACnB,4BAAW,CAAA;AACb,CAAC,EALW,aAAa,KAAb,aAAa,QAKxB;AAED,IAAI,oBAAoB,GAAG,EAAE,CAAC;AAE9B,MAAM,UAAU,gBAAgB;IAC9B,IAAI,oBAAoB,EAAE,CAAC;QACzB,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED,6FAA6F;IAC7F,uEAAuE;IACvE,0HAA0H;IAC1H,IAAI,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC;IAC3C,WAAW,GAAG,mBAAmB,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACtE,WAAW,GAAG,mBAAmB,CAAC,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAEnE,MAAM,aAAa,GAAG,GAAG,WAAW,CAAC,IAAI,EAAE;;;;;;;;;SASpC,OAAO,CAAC,GAAG,CAAC,mBAAmB;eACzB,MAAM,CAAC,KAAK,CAAC,QAAQ;;QAE5B,IAAI,IAAI,EAAE,CAAC,cAAc,EAAE;;;;;;;;;;;;;;;;;0GAiBuE,CAAC;IAEzG,oBAAoB,GAAG,aAAa,CAAC;IACrC,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAS,mBAAmB,CAC1B,cAAsB,EACtB,gBAAwB,EACxB,SAAc;IAEd,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,SAAS,gBAAgB,eAAe,EAAE,GAAG,CAAC,CAAC;IAE1E,OAAO,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACpD,MAAM,KAAK,GAAG,eAAe,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC9C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,wBAAwB,GAAG,iBAAiB,CAAC;QACrD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,IAAI,QAAQ,GAAiB,EAAE,CAAC;AAEvC,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,IAAY,EACZ,SAAwB,aAAa,CAAC,OAAO;IAE7C,kFAAkF;IAClF,oEAAoE;IACpE,IAAI,SAAS,CAAC,OAAO,KAAK,SAAS,CAAC,KAAK,EAAE,CAAC;QAC1C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,2CAA2C;IAC3C,MAAM,IAAI,GACR,MAAM,IAAI,aAAa,CAAC,aAAa,IAAI,MAAM,IAAI,aAAa,CAAC,OAAO;QACtE,CAAC,CAAC,OAAO,CAAC,IAAI;QACd,CAAC,CAAC,MAAM,IAAI,aAAa,CAAC,iBAAiB,IAAI,MAAM,IAAI,aAAa,CAAC,GAAG;YACxE,CAAC,CAAC,OAAO,CAAC,SAAS;YACnB,CAAC,CAAC,SAAS,CAAC;IAElB,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACpC,CAAC;IAED,wFAAwF;IACxF,4DAA4D;IAC5D,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAElD,IAAI,WAAW,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;YAC7B,WAAW,CAAC,OAAO,IAAI,KAAK,IAAI,EAAE,CAAC;YACnC,QAAQ,GAAG,IAAI,CAAC;YAChB,MAAM,UAAU,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,UAAU,GAAe,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACvD,UAAU,CAAC,KAAK,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACtD,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5B,CAAC;IAED,gDAAgD;IAChD,IACE,MAAM,IAAI,aAAa,CAAC,aAAa;QACrC,MAAM,IAAI,aAAa,CAAC,iBAAiB,EACzC,CAAC;QACD,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,QAAQ,GAAG,EAAE,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,kBAAkB,GAAG,SAAS,CAAC,aAAa,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAEvE,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE;QACtC,OAAO,GAAG,GAAG,SAAS,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,CAAC,EAAE,kBAAkB,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACxC,2BAA2B;IAC3B,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC3B,MAAM,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,43 @@
1
+ import * as config from "../config.js";
2
+ import * as dbUtils from "../utils/dbUtils.js";
3
+ import { naisysToHostPath } from "../utils/utilities.js";
4
+ const _dbFilePath = naisysToHostPath(`${config.naisysFolder}/lib/costs.db`);
5
+ await init();
6
+ async function init() {
7
+ const newDbCreated = await dbUtils.initDatabase(_dbFilePath);
8
+ await usingDatabase(async (db) => {
9
+ if (!newDbCreated) {
10
+ return;
11
+ }
12
+ const createTables = [
13
+ `CREATE TABLE Costs (
14
+ id INTEGER PRIMARY KEY,
15
+ date TEXT NOT NULL,
16
+ username TEXT NOT NULL,
17
+ source TEXT NOT NULL,
18
+ model TEXT NOT NULL,
19
+ cost REAL NOT NULL
20
+ )`,
21
+ ];
22
+ for (const createTable of createTables) {
23
+ await db.exec(createTable);
24
+ }
25
+ });
26
+ }
27
+ export async function recordCost(cost, source, modelName) {
28
+ await usingDatabase(async (db) => {
29
+ await db.run(`INSERT INTO Costs (date, username, source, model, cost) VALUES (datetime('now'), ?, ?, ?, ?)`, [config.agent.username, source, modelName, cost]);
30
+ });
31
+ }
32
+ export async function getTotalCosts() {
33
+ return usingDatabase(async (db) => {
34
+ const result = await db.get(`SELECT sum(cost) as total
35
+ FROM Costs
36
+ WHERE username = ?`, [config.agent.username]);
37
+ return result.total;
38
+ });
39
+ }
40
+ async function usingDatabase(run) {
41
+ return dbUtils.usingDatabase(_dbFilePath, run);
42
+ }
43
+ //# sourceMappingURL=costTracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"costTracker.js","sourceRoot":"","sources":["../../src/llm/costTracker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,WAAW,GAAG,gBAAgB,CAAC,GAAG,MAAM,CAAC,YAAY,eAAe,CAAC,CAAC;AAE5E,MAAM,IAAI,EAAE,CAAC;AAEb,KAAK,UAAU,IAAI;IACjB,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;IAE7D,MAAM,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QAC/B,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QAED,MAAM,YAAY,GAAG;YACnB;;;;;;;QAOE;SACH,CAAC;QAEF,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;YACvC,MAAM,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,MAAc,EACd,SAAiB;IAEjB,MAAM,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QAC/B,MAAM,EAAE,CAAC,GAAG,CACV,8FAA8F,EAC9F,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,CACjD,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,OAAO,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QAChC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,CACzB;;2BAEqB,EACrB,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CACxB,CAAC;QAEF,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,aAAa,CAAI,GAAiC;IAC/D,OAAO,OAAO,CAAC,aAAa,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;AACjD,CAAC"}