clavarium 0.0.2 → 0.1.0-next.2

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 (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +265 -6
  3. package/config/tools.json +172 -0
  4. package/deploy/appliance.sh +83 -0
  5. package/deploy/backup.sh +97 -0
  6. package/deploy/clavarium-host +720 -0
  7. package/deploy/clavarium.mjs +30 -0
  8. package/deploy/git-read +85 -0
  9. package/deploy/install.sh +659 -0
  10. package/deploy/move-to-mnt.sh +142 -0
  11. package/deploy/parley-archive.mjs +47 -0
  12. package/deploy/relay.sh +156 -0
  13. package/deploy/restore.sh +147 -0
  14. package/deploy/updater.mjs +600 -0
  15. package/npm-shrinkwrap.json +1951 -0
  16. package/package.json +53 -8
  17. package/server/alerts.mjs +83 -0
  18. package/server/answerer.mjs +326 -0
  19. package/server/api.mjs +458 -0
  20. package/server/bridge.mjs +271 -0
  21. package/server/capacity.mjs +220 -0
  22. package/server/conversations.mjs +895 -0
  23. package/server/dataformat.mjs +59 -0
  24. package/server/devices.mjs +257 -0
  25. package/server/door.mjs +235 -0
  26. package/server/files.mjs +455 -0
  27. package/server/gate.mjs +54 -0
  28. package/server/gitaccess.mjs +295 -0
  29. package/server/gitchecks.mjs +126 -0
  30. package/server/gitkeeper.mjs +719 -0
  31. package/server/gitpush.mjs +585 -0
  32. package/server/gitrunner.mjs +540 -0
  33. package/server/grants.mjs +110 -0
  34. package/server/guide.mjs +278 -0
  35. package/server/health.mjs +207 -0
  36. package/server/imap.mjs +75 -0
  37. package/server/mailbox.mjs +165 -0
  38. package/server/main.mjs +420 -0
  39. package/server/names.mjs +10 -0
  40. package/server/network.mjs +85 -0
  41. package/server/parley.mjs +62 -0
  42. package/server/resources.mjs +396 -0
  43. package/server/seats.mjs +24 -0
  44. package/server/secrets.mjs +118 -0
  45. package/server/setup.mjs +768 -0
  46. package/server/shelf.mjs +260 -0
  47. package/server/shortcuts.mjs +62 -0
  48. package/server/signin.mjs +185 -0
  49. package/server/smoke.mjs +26 -0
  50. package/server/store.mjs +48 -0
  51. package/server/talk.mjs +514 -0
  52. package/server/tmux.mjs +54 -0
  53. package/server/toolbox.mjs +168 -0
  54. package/server/tools.mjs +109 -0
  55. package/server/updates.mjs +116 -0
  56. package/server/vault.mjs +37 -0
  57. package/server/vm.mjs +139 -0
  58. package/server/voice.mjs +90 -0
  59. package/server/wakeups.mjs +320 -0
  60. package/web/app.js +4779 -0
  61. package/web/device.html +149 -0
  62. package/web/device.js +152 -0
  63. package/web/icon-192.png +0 -0
  64. package/web/icon-512.png +0 -0
  65. package/web/icon.svg +1 -0
  66. package/web/icons.js +9 -0
  67. package/web/index.html +784 -0
  68. package/web/links.js +995 -0
  69. package/web/manifest.webmanifest +30 -0
  70. package/web/prism-manual.js +3 -0
  71. package/web/style.css +1006 -0
  72. package/web/sw.js +26 -0
  73. package/web/voice-core.js +107 -0
  74. package/web/voice.js +56 -0
  75. package/keep.mjs +0 -8
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ /* THE COMMAND OF THE PACKAGE: the installer, at this exact version.
3
+ *
4
+ * sudo npx clavarium@X.Y.Z install --domain clav.example.com --operator you@example.com
5
+ * sudo npx clavarium@X.Y.Z install --local
6
+ * npx clavarium --version
7
+ *
8
+ * `install` runs deploy/install.sh of this package, which installs THIS
9
+ * version from npm (checked) into /opt/clavarium/releases/X.Y.Z; every other
10
+ * parameter is the installer's (install.sh --help-like usage on a bad one).
11
+ * The server itself runs from there, as a service: not from here.
12
+ */
13
+ import { spawnSync } from 'node:child_process';
14
+ import { readFileSync } from 'node:fs';
15
+ import { fileURLToPath } from 'node:url';
16
+
17
+ const version = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
18
+ const [verb, ...rest] = process.argv.slice(2);
19
+ if (verb === '--version' || verb === '-v') { console.log(version); process.exit(0); }
20
+ if (verb !== 'install') {
21
+ console.error(`Clavarium ${version}: each AI agent in its own machine, with only what you attach.\n\n`
22
+ + ` sudo npx clavarium@${version} install --domain NAME --operator EMAIL on an Ubuntu server\n`
23
+ + ` sudo npx clavarium@${version} install --local to try it on this machine\n\n`
24
+ + 'https://github.com/clavarium/clavarium');
25
+ process.exit(verb ? 64 : 0);
26
+ }
27
+ const script = fileURLToPath(new URL('./install.sh', import.meta.url));
28
+ const args = rest.some((a) => a === '--version' || a === '--from-dir') ? rest : ['--version', version, ...rest];
29
+ const r = spawnSync('/bin/bash', [script, ...args], { stdio: 'inherit' });
30
+ process.exit(r.status ?? 1);
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/sh
2
+ # THE ONE READ OF AN AGENT'S REPOSITORY, run by `clavarium-host git read`
3
+ # inside its sandbox (installed as /usr/lib/clavarium/git-read, root, 0755).
4
+ #
5
+ # Fixed text: it takes the folder's name, reads only paths of the repository,
6
+ # and never prints them. Its working directory is /resources/<name>, the only
7
+ # folder there is.
8
+ #
9
+ # It refuses a .git that is not a plain directory (a gitfile, a link, a
10
+ # commondir could send git to refs elsewhere that the check below never saw),
11
+ # refs it cannot read in full (a branch git cannot read would be missing
12
+ # without a word, and a missing branch must never look like a deleted one),
13
+ # and a shallow or grafted repository (its pack would lack the parents it
14
+ # hides, with nothing in the bundle to say so).
15
+ #
16
+ # Then it writes a version 2 bundle on stdout, BUILT HERE rather than by
17
+ # `git bundle create`: the header is the list `git for-each-ref` gives, and
18
+ # the pack holds the objects of exactly those ids. `git bundle create`
19
+ # resolves every branch a second time by its short name and silently leaves
20
+ # out one that moved meanwhile, or whose name is ambiguous (`a` beside `a/b`,
21
+ # a branch named `refs/heads/main`): a branch would vanish from a read that
22
+ # still succeeds. Here the list is taken once, and checked against the ref
23
+ # files on disk: a ref git skips without a word (a symbolic ref pointing
24
+ # nowhere or in a loop, a broken file, an invalid name), or a branch made or
25
+ # deleted during the read, refuses the read instead of hiding a branch.
26
+ #
27
+ # Every setting the repository could use to run something is overridden on
28
+ # every git command.
29
+ #
30
+ # Exit codes: 0; 3 (refs unreadable); 128 only with the 17 bytes of an
31
+ # empty bundle (no branches); 66 for anything else, with one line on stderr
32
+ # saying what. git's own codes become 66, so that a code systemd uses for
33
+ # itself (200-243) can only come from systemd. A git killed by a signal is
34
+ # killed again here by the same signal, so that the host still sees a signal.
35
+ NAME="$1"
36
+ [ -d .git ] && [ ! -L .git ] && [ ! -e .git/commondir ] && [ ! -L .git/commondir ] \
37
+ || { echo "NOT A PLAIN .git DIRECTORY" >&2; exit 66; }
38
+ for p in .git/refs .git/packed-refs; do
39
+ [ -e "$p" ] || [ -L "$p" ] || continue
40
+ find -L "$p" >/dev/null 2>&1 && [ -z "$(find -L "$p" \( ! -readable -o -type d ! -executable \) -print -quit 2>/dev/null)" ] \
41
+ || { echo "REFS UNREADABLE" >&2; exit 3; }
42
+ done
43
+ for p in .git/shallow .git/info/grafts; do
44
+ if [ -e "$p" ] || [ -L "$p" ]; then echo "SHALLOW REPOSITORY" >&2; exit 66; fi
45
+ done
46
+
47
+ # git opens THE .git checked above, and nothing else. Left to discover the
48
+ # repository, git that finds .git unusable tries the folder itself as a bare
49
+ # repository (documented discovery), and would read objects and refs none of
50
+ # the checks above looked at -- a read that succeeds where it must refuse.
51
+ GIT_DIR=.git
52
+ export GIT_DIR
53
+ g() {
54
+ /usr/bin/git -c "safe.directory=/resources/$NAME" -c safe.bareRepository=explicit -c core.hooksPath=/dev/null -c core.fsmonitor=false \
55
+ -c core.pager=cat -c core.alternateRefsCommand= -c protocol.allow=never -c pack.threads=1 \
56
+ -c pack.windowMemory=256m -c pack.useBitmaps=false "$@"
57
+ }
58
+ # git failed with code $1: a signal stays a signal, anything else is 66.
59
+ failed() {
60
+ if [ "$1" -gt 128 ] && [ "$1" -lt 193 ]; then kill -s "$(($1 - 128))" $$; fi
61
+ echo "$2" >&2
62
+ exit 66
63
+ }
64
+
65
+ format=$(g rev-parse --show-object-format) || failed $? "GIT COULD NOT OPEN THE REPOSITORY"
66
+ [ "$format" = "sha1" ] || { echo "NOT SHA-1" >&2; exit 66; }
67
+
68
+ refs=$(g for-each-ref --format='%(objectname) %(refname)' refs/heads/) || failed $? "GIT COULD NOT LIST THE BRANCHES"
69
+ listed=$(printf '%s\n' "$refs" | sed -n 's|^[0-9a-f]\{40\} ||p' | sort -u)
70
+ on_disk=$( {
71
+ [ -d .git/refs/heads ] && find -L .git/refs/heads -type f ! -name '*.lock' -printf 'refs/heads/%P\n'
72
+ [ -f .git/packed-refs ] && sed -n 's|^[0-9a-f]\{40\} \(refs/heads/.*\)$|\1|p' .git/packed-refs
73
+ } | sort -u)
74
+ [ "$listed" = "$on_disk" ] || { echo "BROKEN OR CHANGING REFS" >&2; exit 66; }
75
+ [ "$(printf '%s\n' "$refs" | grep -c .)" -le 1000 ] || { echo "MORE THAN 1000 BRANCHES" >&2; exit 66; }
76
+
77
+ if [ -z "$refs" ]; then
78
+ printf '# v2 git bundle\n\n'
79
+ exit 128
80
+ fi
81
+ printf '# v2 git bundle\n%s\n\n' "$refs"
82
+ printf '%s\n' "$refs" | cut -c1-40 | g pack-objects --stdout --revs --delta-base-offset -q
83
+ rc=$?
84
+ [ "$rc" -eq 0 ] && exit 0
85
+ failed "$rc" "GIT COULD NOT PACK THE BRANCHES"