antcolony
All repositories: gitoria
4.1 KB
// util.hl — small helpers the language does not ship (statics only; importing runs nothing).// Workarounds noted where a Hybriel ticket is the reason (see the worker guide on Byrodin:// /CONTAINERS/projects/antcolony/docs/hybriel-for-app-workers.md).import { readFile, exists } from 'hl:fs'import { cwd } from 'hl:proc'import { jsonErrorAt } from './jsoncheck.hl'static NL = ""// hlTypeName says 'Hybrid' for objects AND lists (hybriel#14): a list has a length, an object has notstatic isList = (v) => { return v != null && hlTypeName(v) == 'Hybrid' && JSON.stringify(v).startsWith('[') }static isObject = (v) => { return v != null && hlTypeName(v) == 'Hybrid' && !isList(v) }static isString = (v) => { return v != null && hlTypeName(v) == 'String' }static nonEmpty = (v) => { return isString(v) && v.trim() != '' }// a path the USER typed (argument or env) is relative to where they ran us, not to this// script (hl:fs resolves relative paths against the entry script's directory)static fromCwd = (p) => {if (p == null || p == '') { return p }if (p.startsWith('/')) { return p }return cwd() + '/' + p}// a file as JSON: { value } or { error } — JSON.parse cannot fail softly (hybriel#6), so the// syntax is checked first (jsoncheck.hl, a copy of tickets')static readJson = (path) => {if (!exists(path)) { return { error = 'no such file: ' + path } }let text = readFile(path)let at = jsonErrorAt(text)if (at >= 0) { return { error = path + ': invalid JSON at character ' + at } }return { value = JSON.parse(text) text = text }}// sort a list IN PLACE by a numeric key, ascending, stable (list sort() is NotCallable, hybriel#1)static sortByNumber = (list, keyOf) => {let i = 1while (i < list.length) {let cur = list[i]let k = keyOf(cur)let j = i - 1while (j >= 0 && keyOf(list[j]) > k) {list[j + 1] = list[j]j = j - 1}list[j + 1] = curi = i + 1}return list}// a > b for strings by char code (no string ordering operators, hybriel#2)static after = (a, b) => {let i = 0while (i < a.length && i < b.length) {let x = a.charCodeAt(i)let y = b.charCodeAt(i)if (x != y) { return x > y }i = i + 1}return a.length > b.length}static sortStrings = (list) => {let i = 1while (i < list.length) {let cur = list[i]let j = i - 1while (j >= 0 && after(list[j], cur)) {list[j + 1] = list[j]j = j - 1}list[j + 1] = curi = i + 1}return list}// a Markdown code fence longer than any backtick run inside `text`static fenceFor = (text) => {let longest = 0let run = 0let i = 0while (i < text.length) {if (text.charCodeAt(i) == 96) { run = run + 1 } else { run = 0 }if (run > longest) { longest = run }i = i + 1}let f = '```'while (f.length <= longest) { f = f + '`' }return f}// `--name value` from an argument list, or nullstatic option = (argv, name) => {let i = 0while (i < argv.length) {if (argv[i] == name && i + 1 < argv.length) { return argv[i + 1] }i = i + 1}return null}// the positional arguments (no --options and their values; --post, --dry-run, --again, --once, --live, --expire and the// librarian's --post-files, --render, --retry-refused are flags)static positionals = (argv) => {let out = []let i = 0while (i < argv.length) {let a = argv[i]if (a == '--post' || a == '--dry-run' || a == '--again' || a == '--once' || a == '--live' || a == '--expire' || a == '--deploy' || a == '--post-files' || a == '--render' || a == '--retry-refused') {i = i + 1} else if (a.startsWith('--')) {i = i + 2} else {out.push(a)i = i + 1}}return out}// capabilities (antcolony#15): "gpu, chrome ,deploy" → ['gpu','chrome','deploy'] (trimmed, lower case, no empties, no repeats)static parseCapabilities = (text) => {let out = []if (text == null) { return out }for (p of text.split(',')) {let c = p.trim().toLowerCase()if (c != '' && !out.includes(c)) { out.push(c) }}return out}// what of `needs` a host with `offers` lacks (both lists of lower-case names)static missingCapabilities = (needs, offers) => {let out = []for (n of needs) { if (!offers.includes(n)) { out.push(n) } }return out}
Branches
- mainmain branch
Latest commits
- 3a4d0324antcolony#37: a too-long report gets up to 3 fix tries, finished work is never thrown away for lengthmre
- a6af7883tracker: worker box sees calendar.worldapi.org (login to copy)mre
- c613d26btemplates: bridges to external components (login.js for ident's selector) are allowed (creator 2026-09-27)mre
- 9062978ctracker: worker box sees /media/STORAGE/projects/old-tracker read-only (tracker#2 source data)mre
- 7f9660eeState of 2026-09-27, before the move to gitoriamre