noah-agent 0.1.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.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +169 -0
  3. package/dist/agent/auth-gate.js +23 -0
  4. package/dist/agent/caveman.js +44 -0
  5. package/dist/agent/login.js +59 -0
  6. package/dist/cli.js +130 -0
  7. package/dist/llm/ollama.js +32 -0
  8. package/dist/llm/providers.js +38 -0
  9. package/dist/llm/registry.js +19 -0
  10. package/dist/llm/resolve.js +44 -0
  11. package/dist/modes/rpc.js +13 -0
  12. package/dist/platform/adapter.js +47 -0
  13. package/dist/platform/detect.js +18 -0
  14. package/dist/platform/linux.js +61 -0
  15. package/dist/platform/macos.js +51 -0
  16. package/dist/platform/types.js +5 -0
  17. package/dist/prompt/system.js +52 -0
  18. package/dist/runtime.js +124 -0
  19. package/dist/safety/audit.js +46 -0
  20. package/dist/safety/confirm.js +17 -0
  21. package/dist/safety/extension.js +65 -0
  22. package/dist/safety/policy.js +100 -0
  23. package/dist/sdk.js +32 -0
  24. package/dist/session.js +113 -0
  25. package/dist/sys/health.js +51 -0
  26. package/dist/sys/probe.js +128 -0
  27. package/dist/sys/report.js +55 -0
  28. package/dist/tools/logs.js +24 -0
  29. package/dist/tools/network.js +47 -0
  30. package/dist/tools/package.js +40 -0
  31. package/dist/tools/service.js +45 -0
  32. package/dist/tools/system.js +33 -0
  33. package/dist/tui/app.js +104 -0
  34. package/dist/tui/branding.js +14 -0
  35. package/dist/tui/components/audit-line.js +37 -0
  36. package/dist/tui/components/header.js +33 -0
  37. package/dist/tui/components/noah-footer.js +33 -0
  38. package/dist/tui/components/request-panel.js +23 -0
  39. package/dist/tui/components/response-view.js +17 -0
  40. package/dist/tui/components/safety-block.js +31 -0
  41. package/dist/tui/components/safety-review.js +36 -0
  42. package/dist/tui/components/thinking-view.js +22 -0
  43. package/dist/tui/components/tool-card.js +45 -0
  44. package/dist/tui/components/util.js +3 -0
  45. package/dist/tui/preview.js +33 -0
  46. package/dist/tui/space/app.js +566 -0
  47. package/dist/tui/space/components.js +261 -0
  48. package/dist/tui/space/dashboard.js +63 -0
  49. package/dist/tui/space/theme.js +39 -0
  50. package/dist/ui/ansi.js +93 -0
  51. package/dist/ui/badge.js +31 -0
  52. package/dist/ui/box.js +61 -0
  53. package/dist/ui/preview.js +37 -0
  54. package/dist/ui/render.js +140 -0
  55. package/package.json +68 -0
  56. package/themes/noah-dark-blue.json +85 -0
@@ -0,0 +1,140 @@
1
+ /**
2
+ * NOAH panels — the high-level rendering API the app calls.
3
+ * Pure string builders (easy to preview); session wiring prints them.
4
+ */
5
+ import { bold, dim, white, red, yellow, gray, cyan, green, fg256, truncate, wordWrap, UNICODE } from "./ansi.js";
6
+ import { drawBox, rule } from "./box.js";
7
+ import { badge, badgeLabel } from "./badge.js";
8
+ const WIDTH = 64;
9
+ const orange = fg256(208);
10
+ const bar = UNICODE ? "│" : "|";
11
+ const dot = UNICODE ? "●" : "*";
12
+ /** Clean NOAH wordmark — no emoji. */
13
+ export function brand() {
14
+ const mark = bold(white("NOAH"));
15
+ const sub = dim("Native Operating-system Agentic Harness");
16
+ return `\n ${mark} ${sub}\n ${gray((UNICODE ? "─" : "-").repeat(68))}\n`;
17
+ }
18
+ /** The user's request. */
19
+ export function requestPanel(text) {
20
+ return ("\n" +
21
+ drawBox([truncate(text, WIDTH)], {
22
+ title: bold(cyan("REQUEST")),
23
+ style: "round",
24
+ accent: cyan,
25
+ width: WIDTH,
26
+ }));
27
+ }
28
+ /** Section header with a status badge (used for PLAN / RESULT streams). */
29
+ export function sectionHeader(label, status) {
30
+ return `\n ${badge(status)} ${dim(label)}`;
31
+ }
32
+ /** Header shown when NOAH starts streaming its response. */
33
+ export function responseHeader() {
34
+ return `\n ${cyan(bold(dot))} ${bold(white("NOAH"))}`;
35
+ }
36
+ /** The dim left-bar prefix used for streamed response lines. */
37
+ export function barPrefix() {
38
+ return ` ${dim(bar)} `;
39
+ }
40
+ /** A text block under a left bar (Pi-style), word-wrapped to panel width. */
41
+ export function barLines(text, paint = dim) {
42
+ return wordWrap(text, WIDTH)
43
+ .map((l) => ` ${dim(bar)} ${paint(l)}`)
44
+ .join("\n");
45
+ }
46
+ /** The interactive approval prompt line (printed after SAFETY REVIEW). */
47
+ export function approvePrompt() {
48
+ return ` ${bold(yellow("Approve?"))} ${dim("[y/N]")} `;
49
+ }
50
+ /** Tool execution card. */
51
+ export function toolCard(name, command, status, output) {
52
+ const body = [];
53
+ const prefix = name === "bash" ? dim("$ ") : "";
54
+ if (command)
55
+ body.push(prefix + truncate(command, WIDTH - 2));
56
+ if (output && output.length) {
57
+ for (const line of output.slice(0, 6))
58
+ body.push(dim(truncate(line, WIDTH)));
59
+ }
60
+ if (body.length === 0)
61
+ body.push(dim("(no output)"));
62
+ const accent = status === "success" ? green : status === "blocked" ? red : orange;
63
+ return ("\n" +
64
+ drawBox(body, {
65
+ title: bold(white(`TOOL ${dim("·")} ${name}`)),
66
+ status: badgeLabel(status),
67
+ style: "round",
68
+ accent,
69
+ width: WIDTH,
70
+ }));
71
+ }
72
+ /** SAFETY REVIEW — the confirmation centerpiece (heavy box). */
73
+ export function safetyReview(command, reason, toolName) {
74
+ const body = [
75
+ white("NOAH wants to run a state-changing command:"),
76
+ "",
77
+ bold(yellow(truncate(command || toolName, WIDTH))),
78
+ "",
79
+ dim(`reason: ${reason} ${UNICODE ? "·" : "-"} tool: ${toolName}`),
80
+ ];
81
+ return ("\n" +
82
+ drawBox(body, {
83
+ title: bold(yellow("SAFETY REVIEW")),
84
+ status: badgeLabel("warning"),
85
+ style: "heavy",
86
+ accent: yellow,
87
+ width: WIDTH,
88
+ }));
89
+ }
90
+ /** SAFETY BLOCK — the catastrophic-deny centerpiece (block panel). */
91
+ export function safetyBlock(command, reason) {
92
+ const shield = UNICODE ? "⛔ " : "[X] ";
93
+ const cleanReason = reason.replace(/^blocked:\s*/i, "");
94
+ const body = [
95
+ bold(white(truncate(command, WIDTH))),
96
+ "",
97
+ bold(white(`BLOCKED ${UNICODE ? "—" : "-"} ${cleanReason}`)),
98
+ white("Catastrophic. Cannot be overridden."),
99
+ ];
100
+ return ("\n" +
101
+ drawBox(body, {
102
+ title: bold(white(`${shield}SAFETY BLOCK`)),
103
+ style: "block",
104
+ accent: red,
105
+ width: WIDTH,
106
+ }));
107
+ }
108
+ /** A single audit-trail line. */
109
+ export function auditLine(tool, command, ok) {
110
+ const mark = ok ? green(UNICODE ? "✓" : "+") : red(UNICODE ? "✗" : "x");
111
+ const ts = dim(new Date().toLocaleTimeString());
112
+ return ` ${dim("AUDIT")} ${mark} ${ts} ${cyan(tool.padEnd(6))} ${dim(truncate(command, WIDTH))}`;
113
+ }
114
+ /** Final result panel. */
115
+ export function resultPanel(text) {
116
+ return ("\n" +
117
+ rule() +
118
+ "\n " +
119
+ badge("success") +
120
+ "\n" +
121
+ barLines(text, (s) => green(s)) +
122
+ "\n");
123
+ }
124
+ /** Inline gate verdict for `--check` (allow / confirm). */
125
+ export function checkVerdict(command, action, reason) {
126
+ const status = action;
127
+ const note = action === "confirm"
128
+ ? "\n " + dim("NOAH would ask for your approval before running this.")
129
+ : "";
130
+ return `\n ${badge(status)} ${white(truncate(command, WIDTH))}\n ${dim(`${UNICODE ? "→" : "->"} ${reason}`)}${note}`;
131
+ }
132
+ /** Small status note line. */
133
+ export function note(text, status = "info") {
134
+ return ` ${badge(status)} ${dim(text)}`;
135
+ }
136
+ /** A separating rule. */
137
+ export function divider() {
138
+ return "\n" + rule();
139
+ }
140
+ export { dot };
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "noah-agent",
3
+ "version": "0.1.0",
4
+ "description": "NOAH — an AI System Administrator. Natural language controls your OS: it reads the machine, analyzes impact, recommends, and executes safely with an audited, confirm-gated trail. Cross-platform (Linux + macOS).",
5
+ "type": "module",
6
+ "author": "Sriman",
7
+ "homepage": "https://github.com/srimanh/NOAH#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/srimanh/NOAH.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/srimanh/NOAH/issues"
14
+ },
15
+ "bin": {
16
+ "noah": "dist/cli.js"
17
+ },
18
+ "exports": {
19
+ ".": "./dist/sdk.js",
20
+ "./sdk": "./dist/sdk.js"
21
+ },
22
+ "engines": {
23
+ "node": ">=20.6.0"
24
+ },
25
+ "scripts": {
26
+ "build": "tsc && chmod +x dist/cli.js",
27
+ "prepare": "npm run build",
28
+ "prepublishOnly": "npm run build && npm test",
29
+ "dev": "tsx src/cli.ts",
30
+ "noah": "npm run build && npm run dev",
31
+ "preview": "node dist/ui/preview.js",
32
+ "preview:tui": "node dist/tui/preview.js",
33
+ "test": "node --import tsx --test $(find src -name '*.test.ts')",
34
+ "start": "node dist/cli.js"
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "themes"
39
+ ],
40
+ "keywords": [
41
+ "agent",
42
+ "ai",
43
+ "llm",
44
+ "sysadmin",
45
+ "devops",
46
+ "os",
47
+ "cli",
48
+ "tui",
49
+ "terminal",
50
+ "automation",
51
+ "safety",
52
+ "anthropic",
53
+ "ollama",
54
+ "system-administrator"
55
+ ],
56
+ "license": "MIT",
57
+ "dependencies": {
58
+ "@earendil-works/pi-ai": "^0.79.2",
59
+ "@earendil-works/pi-coding-agent": "^0.79.2",
60
+ "@earendil-works/pi-tui": "^0.79.2",
61
+ "typebox": "^1.2.8"
62
+ },
63
+ "devDependencies": {
64
+ "@types/node": "^22.0.0",
65
+ "tsx": "^4.19.0",
66
+ "typescript": "^5.6.0"
67
+ }
68
+ }
@@ -0,0 +1,85 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
3
+ "name": "noah-dark-blue",
4
+ "vars": {
5
+ "blue": "#4d9fff",
6
+ "blueDeep": "#1e6fff",
7
+ "blueBright": "#8ec5ff",
8
+ "cyan": "#67e8f9",
9
+ "navy1": "#0d1b2a",
10
+ "navy2": "#13233a",
11
+ "navy3": "#1b2b44",
12
+ "text": "#cfe3ff",
13
+ "gray": "#7a8aa0",
14
+ "dimGray": "#4a5a72",
15
+ "darkGray": "#33425a",
16
+ "green": "#5fd3a0",
17
+ "red": "#ff6b81",
18
+ "yellow": "#ffd166",
19
+ "purple": "#a78bfa"
20
+ },
21
+ "colors": {
22
+ "accent": "blue",
23
+ "border": "blueDeep",
24
+ "borderAccent": "cyan",
25
+ "borderMuted": "darkGray",
26
+ "success": "green",
27
+ "error": "red",
28
+ "warning": "yellow",
29
+ "muted": "gray",
30
+ "dim": "dimGray",
31
+ "text": "text",
32
+ "thinkingText": "gray",
33
+
34
+ "selectedBg": "navy3",
35
+ "userMessageBg": "navy2",
36
+ "userMessageText": "text",
37
+ "customMessageBg": "#16203a",
38
+ "customMessageText": "text",
39
+ "customMessageLabel": "purple",
40
+ "toolPendingBg": "#102036",
41
+ "toolSuccessBg": "#0f2a22",
42
+ "toolErrorBg": "#2a1420",
43
+ "toolTitle": "blueBright",
44
+ "toolOutput": "gray",
45
+
46
+ "mdHeading": "blueBright",
47
+ "mdLink": "blue",
48
+ "mdLinkUrl": "dimGray",
49
+ "mdCode": "cyan",
50
+ "mdCodeBlock": "text",
51
+ "mdCodeBlockBorder": "darkGray",
52
+ "mdQuote": "gray",
53
+ "mdQuoteBorder": "blueDeep",
54
+ "mdHr": "darkGray",
55
+ "mdListBullet": "cyan",
56
+
57
+ "toolDiffAdded": "green",
58
+ "toolDiffRemoved": "red",
59
+ "toolDiffContext": "gray",
60
+
61
+ "syntaxComment": "#5a6b85",
62
+ "syntaxKeyword": "#4d9fff",
63
+ "syntaxFunction": "#8ec5ff",
64
+ "syntaxVariable": "#9cd0ff",
65
+ "syntaxString": "#5fd3a0",
66
+ "syntaxNumber": "#ffd166",
67
+ "syntaxType": "#67e8f9",
68
+ "syntaxOperator": "text",
69
+ "syntaxPunctuation": "gray",
70
+
71
+ "thinkingOff": "darkGray",
72
+ "thinkingMinimal": "#5a6b85",
73
+ "thinkingLow": "#3d7fd0",
74
+ "thinkingMedium": "#4d9fff",
75
+ "thinkingHigh": "#67e8f9",
76
+ "thinkingXhigh": "#a78bfa",
77
+
78
+ "bashMode": "cyan"
79
+ },
80
+ "export": {
81
+ "pageBg": "#0d1b2a",
82
+ "cardBg": "#13233a",
83
+ "infoBg": "#102036"
84
+ }
85
+ }