@terminus-ai/cli 0.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 (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1055 -0
  3. package/bin/agent-discovery.mjs +71 -0
  4. package/bin/agent-icon.mjs +77 -0
  5. package/bin/agent-models.mjs +77 -0
  6. package/bin/agent-type.mjs +51 -0
  7. package/bin/agentdev.mjs +657 -0
  8. package/bin/app-route-script.mjs +59 -0
  9. package/bin/app-runtime-contract.mjs +2 -0
  10. package/bin/appdev-remote.mjs +346 -0
  11. package/bin/appdev.mjs +4446 -0
  12. package/bin/apps.mjs +5512 -0
  13. package/bin/capability-calls.mjs +437 -0
  14. package/bin/capsule-data.mjs +260 -0
  15. package/bin/client.mjs +189 -0
  16. package/bin/commands.mjs +1194 -0
  17. package/bin/dev-capsules.mjs +1599 -0
  18. package/bin/dev-contract.mjs +262 -0
  19. package/bin/dev-data.mjs +287 -0
  20. package/bin/dev-members.mjs +18 -0
  21. package/bin/dev-net.mjs +316 -0
  22. package/bin/dev-notification-popup.mjs +628 -0
  23. package/bin/dev-ports.mjs +567 -0
  24. package/bin/dev-server-binding.mjs +35 -0
  25. package/bin/dev-server-ops.mjs +1086 -0
  26. package/bin/dev-ui/IoskeleyMono-400.woff2 +0 -0
  27. package/bin/dev-ui/IoskeleyMono-600.woff2 +0 -0
  28. package/bin/dev-ui/OFL.txt +92 -0
  29. package/bin/dev-ui/agent-robot.webp +0 -0
  30. package/bin/dev-ui/app.js +5217 -0
  31. package/bin/dev-ui/highlight.js +195 -0
  32. package/bin/dev-ui/index.html +34 -0
  33. package/bin/dev-ui/style.css +3640 -0
  34. package/bin/devlint.mjs +112 -0
  35. package/bin/devserver.mjs +2127 -0
  36. package/bin/devtriggers.mjs +367 -0
  37. package/bin/endpoints.mjs +156 -0
  38. package/bin/errors.mjs +61 -0
  39. package/bin/files.mjs +169 -0
  40. package/bin/horizontal-capabilities/v1/contract.json +280 -0
  41. package/bin/http.mjs +500 -0
  42. package/bin/lint-manifests/justbash-commands.json +88 -0
  43. package/bin/lint-manifests/python-stdlib.json +295 -0
  44. package/bin/login-page.mjs +488 -0
  45. package/bin/schedules.mjs +664 -0
  46. package/bin/server-sandbox.mjs +204 -0
  47. package/bin/servicedev.mjs +425 -0
  48. package/bin/sync.mjs +357 -0
  49. package/bin/terminus.js +3666 -0
  50. package/bin/toolchain.mjs +125 -0
  51. package/bin/vendor/app-runtime-v1/app-host.json +124 -0
  52. package/bin/vendor/app-runtime-v1/capability-calls.json +412 -0
  53. package/bin/vendor/app-runtime-v1/doors.json +2867 -0
  54. package/bin/vendor/appd/node-harness.mjs +209 -0
  55. package/bin/vendor/appd/python-harness.py +12 -0
  56. package/bin/vendor/appd/server-protocol.json +84 -0
  57. package/bin/vendor/where.mjs +541 -0
  58. package/bin/versioning.mjs +72 -0
  59. package/bin/write-rules.mjs +398 -0
  60. package/package.json +41 -0
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Prod-compat lint for local agent dev.
3
+ *
4
+ * Local exec is native (real /bin/sh, real python) — a capability SUPERSET
5
+ * of the hosted isolate (just-bash's ~80 coreutils; stdlib-only
6
+ * CPython/WASM). These heuristics warn, never block, when a program leans
7
+ * on something the hosted tier lacks, so the authoring-time mistakes ("use
8
+ * git…", `import pandas`) surface before publish instead of after. The
9
+ * guarantee remains `terminus dev --remote`, which runs the real isolate.
10
+ *
11
+ * The manifests (bin/lint-manifests/) are read off the engines the platform
12
+ * runs: just-bash's getCommandNames() and its CPython's
13
+ * sys.stdlib_module_names, at the just-bash version terminus-backend's bashd
14
+ * pins. Each file's `source` names that version; regenerate both from the
15
+ * new version when the pin moves.
16
+ */
17
+
18
+ import { readFileSync } from "node:fs";
19
+ import path from "node:path";
20
+ import { fileURLToPath } from "node:url";
21
+
22
+ const manifestDir = path.join(path.dirname(fileURLToPath(import.meta.url)), "lint-manifests");
23
+
24
+ function loadManifest(name, key) {
25
+ try {
26
+ return new Set(JSON.parse(readFileSync(path.join(manifestDir, name), "utf8"))[key]);
27
+ } catch {
28
+ return null;
29
+ }
30
+ }
31
+
32
+ const JUSTBASH_COMMANDS = loadManifest("justbash-commands.json", "commands");
33
+ const PYTHON_STDLIB = loadManifest("python-stdlib.json", "modules");
34
+
35
+ /**
36
+ * Drop heredoc bodies before tokenizing: everything between `<<WORD` (or
37
+ * `<<-WORD` / quoted variants) and the terminator line is data, not
38
+ * commands. Without this, a `cat > file <<EOF` report body lints every
39
+ * markdown line as an unknown command.
40
+ */
41
+ export function stripHeredocBodies(command) {
42
+ const lines = command.split("\n");
43
+ const kept = [];
44
+ let terminator = null;
45
+ for (const line of lines) {
46
+ if (terminator !== null) {
47
+ if (line.trim() === terminator) terminator = null;
48
+ continue;
49
+ }
50
+ const heredoc = /<<-?\s*(?:"([^"]+)"|'([^']+)'|(\S+))/.exec(line);
51
+ if (heredoc) terminator = heredoc[1] ?? heredoc[2] ?? heredoc[3];
52
+ kept.push(line);
53
+ }
54
+ return kept.join("\n");
55
+ }
56
+
57
+ /** Shell syntax words and builtins the tokenizer must not flag. */
58
+ const SHELL_BUILTINS = new Set([
59
+ "cd", "export", "set", "unset", "exit", "return", "true", ":", "[", "[[",
60
+ "test", "read", "wait", "shift", "local", "source", ".", "eval", "exec",
61
+ "if", "then", "else", "elif", "fi", "for", "while", "until", "do", "done",
62
+ "case", "esac", "function", "{", "}", "!", "in", "time", "trap", "printf",
63
+ "pwd", "type", "command", "kill", "sleep",
64
+ ]);
65
+
66
+ /**
67
+ * Best-effort first-word extraction across pipeline/list segments. Dynamic
68
+ * commands, substitutions, and quoting escape this on purpose — the lint is
69
+ * a hint, not a gate.
70
+ */
71
+ export function lintBashCommand(command) {
72
+ if (!JUSTBASH_COMMANDS || typeof command !== "string") return [];
73
+ const warnings = new Set();
74
+ const segments = stripHeredocBodies(command)
75
+ .replace(/\$\([^)]*\)/g, " ")
76
+ .split(/\||&&|\|\||;|\n|`/);
77
+ for (const segment of segments) {
78
+ let words = segment.trim().split(/\s+/).filter(Boolean);
79
+ // Skip leading VAR=value assignments and redirections.
80
+ while (words.length && (/^[A-Za-z_][A-Za-z0-9_]*=/.test(words[0]) || /^[<>&\d]/.test(words[0]))) {
81
+ words = words.slice(1);
82
+ }
83
+ const word = words[0];
84
+ if (!word) continue;
85
+ if (word.startsWith("$") || word.startsWith('"') || word.startsWith("'")) continue;
86
+ if (word.includes("/")) continue; // explicit paths fail loudly on their own
87
+ const name = word.replace(/^\\/, "");
88
+ if (SHELL_BUILTINS.has(name) || JUSTBASH_COMMANDS.has(name)) continue;
89
+ warnings.add(
90
+ `[prod-compat] '${name}' is not available in the hosted shell tier (just-bash coreutils only)`,
91
+ );
92
+ }
93
+ return [...warnings];
94
+ }
95
+
96
+ /** Warn on imports outside the CPython stdlib the hosted WASM tier serves. */
97
+ export function lintPythonImports(code) {
98
+ if (!PYTHON_STDLIB || typeof code !== "string") return [];
99
+ const warnings = new Set();
100
+ for (const line of code.split("\n")) {
101
+ const match = /^\s*(?:import|from)\s+([A-Za-z_][A-Za-z0-9_.]*(?:\s*,\s*[A-Za-z_][A-Za-z0-9_.]*)*)/.exec(line);
102
+ if (!match) continue;
103
+ for (const raw of match[1].split(",")) {
104
+ const root = raw.trim().split(".")[0];
105
+ if (!root || PYTHON_STDLIB.has(root)) continue;
106
+ warnings.add(
107
+ `[prod-compat] python module '${root}' is outside the stdlib — the hosted tier has no pip packages`,
108
+ );
109
+ }
110
+ }
111
+ return [...warnings];
112
+ }