blacksmith-organization-system 0.4.2 → 1.0.0-dev.3
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.
- package/.claude-plugin/marketplace.json +17 -0
- package/.claude-plugin/mcp.json +8 -0
- package/.claude-plugin/plugin.json +16 -0
- package/AGENTS.md +114 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +1 -1
- package/README.md +74 -57
- package/bin/bos +3 -0
- package/hooks/hooks.json +40 -0
- package/package.json +82 -22
- package/resources/house/HOUSE.md +22 -0
- package/resources/house/bloodlines.json +35 -0
- package/resources/house/children/deepseeks-of-anubis.json +4 -0
- package/resources/house/children/eon.json +7 -0
- package/resources/house/children/hermetic-officer.json +1 -0
- package/resources/house/children/ifrit.json +1 -0
- package/resources/house/children/license-keepers.json +4 -0
- package/resources/house/children/sebas.json +10 -0
- package/resources/house/children/shakespeare.json +10 -0
- package/resources/house/orders/ravensarmy.json +6 -0
- package/resources/house/orders/seiaic-ucdi.json +5 -0
- package/resources/ravens/skryba.md +19 -0
- package/resources/workshop-root/AGENTS.md +92 -0
- package/resources/workshop-root/CLAUDE.md +1 -0
- package/resources/workshop.default.json +6 -0
- package/skills/bos-archive/SKILL.md +28 -0
- package/skills/bos-craftbook/SKILL.md +32 -0
- package/skills/bos-craftset/SKILL.md +36 -0
- package/skills/bos-devarmory/SKILL.md +34 -0
- package/skills/bos-exhibit/SKILL.md +28 -0
- package/skills/bos-forge/SKILL.md +28 -0
- package/skills/bos-house/SKILL.md +52 -0
- package/skills/bos-project/SKILL.md +27 -0
- package/skills/bos-sarcophag/SKILL.md +26 -0
- package/skills/bos-scope/SKILL.md +33 -0
- package/skills/bos-sheme/SKILL.md +38 -0
- package/skills/bos-throwbox/SKILL.md +27 -0
- package/skills/bos-workshop/SKILL.md +65 -0
- package/{config/README.md → skills/bos-workshop/assets/.gitkeep} +0 -0
- package/skills/bos-workshop/references/bos-codebase.md +116 -0
- package/skills/bos-workshop/references/bos-concept.md +121 -0
- package/skills/bos-workshop/scripts/find-workshop.sh +30 -0
- package/src/agent-hook.mjs +28 -0
- package/src/bridge/_index.mjs +24 -0
- package/src/bridge/bos-instances-link/_index.mjs +18 -0
- package/src/bridge/docker-host/_index.mjs +43 -0
- package/src/bridge/docker-host/container.mjs +32 -0
- package/src/bridge/docker-host/image.mjs +23 -0
- package/src/bridge/docker-host/volume.mjs +12 -0
- package/src/bridge/docker-publish/_index.mjs +24 -0
- package/src/bridge/git-client/_index.mjs +121 -0
- package/src/bridge/git-client/author.mjs +26 -0
- package/src/bridge/gitea-api/_index.mjs +62 -0
- package/src/bridge/github-api/_index.mjs +45 -0
- package/src/bridge/npm-publish/_index.mjs +19 -0
- package/src/bridge/ollama-link/_index.mjs +93 -0
- package/src/bridge/ollama-link/ravens.mjs +29 -0
- package/src/bridge/ssh-link/_index.mjs +33 -0
- package/src/bridge/subprocess-runner/_index.mjs +33 -0
- package/src/cli.mjs +29 -0
- package/src/commands/_index.mjs +51 -0
- package/src/commands/bootstrap/exec.mjs +7 -0
- package/src/commands/bootstrap/help.md +5 -0
- package/src/commands/bootstrap/index.json +7 -0
- package/src/commands/close/exec.mjs +4 -0
- package/src/commands/close/help.md +5 -0
- package/src/commands/close/index.json +7 -0
- package/src/commands/describe/exec.mjs +11 -0
- package/src/commands/describe/help.md +5 -0
- package/src/commands/describe/index.json +7 -0
- package/src/commands/help/exec.mjs +6 -0
- package/src/commands/help/help.md +3 -0
- package/src/commands/help/index.json +6 -0
- package/src/commands/hook/exec.mjs +3 -0
- package/src/commands/hook/help.md +4 -0
- package/src/commands/hook/index.json +7 -0
- package/src/commands/hooks/exec.mjs +5 -0
- package/src/commands/hooks/help.md +4 -0
- package/src/commands/hooks/index.json +7 -0
- package/src/commands/house/exec.mjs +8 -0
- package/src/commands/house/help.md +8 -0
- package/src/commands/house/index.json +7 -0
- package/src/commands/locate/exec.mjs +2 -0
- package/src/commands/locate/help.md +6 -0
- package/src/commands/locate/index.json +6 -0
- package/src/commands/mode/exec.mjs +17 -0
- package/src/commands/mode/help.md +14 -0
- package/src/commands/mode/index.json +8 -0
- package/src/commands/mode/repl.mjs +18 -0
- package/src/commands/open/exec.mjs +5 -0
- package/src/commands/open/help.md +4 -0
- package/src/commands/open/index.json +7 -0
- package/src/commands/promote/exec.mjs +5 -0
- package/src/commands/promote/help.md +6 -0
- package/src/commands/promote/index.json +7 -0
- package/src/commands/repl/exec.mjs +3 -0
- package/src/commands/repl/help.md +4 -0
- package/src/commands/repl/index.json +6 -0
- package/src/commands/seal/exec.mjs +8 -0
- package/src/commands/seal/help.md +4 -0
- package/src/commands/seal/index.json +7 -0
- package/src/commands/sink/exec.mjs +2 -0
- package/src/commands/sink/help.md +6 -0
- package/src/commands/sink/index.json +7 -0
- package/src/commands/skills/exec.mjs +5 -0
- package/src/commands/skills/help.md +5 -0
- package/src/commands/skills/index.json +7 -0
- package/src/commands/status/exec.mjs +2 -0
- package/src/commands/status/help.md +6 -0
- package/src/commands/status/index.json +7 -0
- package/src/commands/status/repl.mjs +14 -0
- package/src/commands/verify/exec.mjs +9 -0
- package/src/commands/verify/help.md +4 -0
- package/src/commands/verify/index.json +7 -0
- package/src/controllers/_index.mjs +5 -0
- package/src/controllers/skills-controll.mjs +13 -0
- package/src/controllers/workshop-controll.mjs +48 -0
- package/src/core/basic-bridge.mjs +29 -0
- package/src/core/basic-controll.mjs +26 -0
- package/src/core/basic-element.mjs +149 -0
- package/src/core/basic-model.mjs +7 -0
- package/src/core/basic-procedure.mjs +37 -0
- package/src/core/basic-submodule.mjs +21 -0
- package/src/core/basic-view.mjs +21 -0
- package/src/core/self.mjs +10 -0
- package/src/index.mjs +24 -0
- package/src/main.ts +82 -0
- package/src/mcp.mjs +8 -0
- package/src/models/_index.mjs +43 -0
- package/src/models/archive/class.mjs +9 -0
- package/src/models/craftbook/class.mjs +11 -0
- package/src/models/craftbook/hang.scrapnotes.mjs +10 -0
- package/src/models/craftset/class.mjs +14 -0
- package/src/models/devarmory/class.mjs +10 -0
- package/src/models/exhibit/class.mjs +8 -0
- package/src/models/forge/class.mjs +19 -0
- package/src/models/house/bloodlines.mjs +27 -0
- package/src/models/house/class.mjs +53 -0
- package/src/models/house/groups.mjs +38 -0
- package/src/models/project/anatomy.mjs +11 -0
- package/src/models/project/class.mjs +20 -0
- package/src/models/sarcophag/class.mjs +8 -0
- package/src/models/scope/class.mjs +19 -0
- package/src/models/sheme/class.mjs +8 -0
- package/src/models/throwbox/class.mjs +9 -0
- package/src/models/workshop/class.mjs +30 -0
- package/src/models/workshop/hang.data.mjs +10 -0
- package/src/models/workshop/hang.nests.mjs +14 -0
- package/src/models/workshop/hang.setup.mjs +10 -0
- package/src/models/workshop/hang.storylines.logs.mjs +10 -0
- package/src/models/workshop/hang.storylines.manifests.mjs +10 -0
- package/src/models/workshop/hang.storylines.mjs +39 -0
- package/src/models/workshop/hang.storylines.ttystories.mjs +10 -0
- package/src/models/workshop/hang.system.mjs +25 -0
- package/src/models/workshop/host-roles.mjs +9 -0
- package/src/models/workshop/locate.mjs +60 -0
- package/src/models/workshop/modes.mjs +31 -0
- package/src/models/workshop/taskfile.mjs +21 -0
- package/src/procedures/_index.mjs +32 -0
- package/src/procedures/agent-recording/_index.mjs +34 -0
- package/src/procedures/agent-recording/situate.mjs +11 -0
- package/src/procedures/bootstrapping/DESCRIPTION.md +6 -0
- package/src/procedures/bootstrapping/_index.mjs +13 -0
- package/src/procedures/bootstrapping/deploy-guides.mjs +15 -0
- package/src/procedures/bootstrapping/ensure-tree.mjs +4 -0
- package/src/procedures/closing/DESCRIPTION.md +6 -0
- package/src/procedures/closing/_index.mjs +11 -0
- package/src/procedures/closing/capture-ttystory.mjs +14 -0
- package/src/procedures/closing/record-closing.mjs +6 -0
- package/src/procedures/describing/DESCRIPTION.md +23 -0
- package/src/procedures/describing/_index.mjs +15 -0
- package/src/procedures/describing/ask-skryba.mjs +82 -0
- package/src/procedures/describing/compose-message.mjs +25 -0
- package/src/procedures/describing/read-staged.mjs +7 -0
- package/src/procedures/describing/scopes.mjs +38 -0
- package/src/procedures/describing/staged-diff.mjs +25 -0
- package/src/procedures/describing/write-message.mjs +15 -0
- package/src/procedures/gathering/DESCRIPTION.md +13 -0
- package/src/procedures/gathering/_index.mjs +13 -0
- package/src/procedures/gathering/list-served.mjs +9 -0
- package/src/procedures/gathering/merge-residents.mjs +31 -0
- package/src/procedures/gathering/read-registry.mjs +7 -0
- package/src/procedures/hooking/DESCRIPTION.md +6 -0
- package/src/procedures/hooking/_index.mjs +12 -0
- package/src/procedures/hooking/hooks.mjs +10 -0
- package/src/procedures/hooking/install-hooks.mjs +34 -0
- package/src/procedures/hooking/record-hook.mjs +13 -0
- package/src/procedures/inspecting/DESCRIPTION.md +3 -0
- package/src/procedures/inspecting/_index.mjs +9 -0
- package/src/procedures/loading/DESCRIPTION.md +4 -0
- package/src/procedures/loading/_index.mjs +15 -0
- package/src/procedures/loading/load-config.mjs +16 -0
- package/src/procedures/loading/validate-mode.mjs +8 -0
- package/src/procedures/loading/validate-role.mjs +8 -0
- package/src/procedures/locating/DESCRIPTION.md +6 -0
- package/src/procedures/locating/_index.mjs +13 -0
- package/src/procedures/locating/locate-self.mjs +7 -0
- package/src/procedures/locating/locate-workshop.mjs +16 -0
- package/src/procedures/locating/read-environment.mjs +12 -0
- package/src/procedures/mode-switching/DESCRIPTION.md +7 -0
- package/src/procedures/mode-switching/_index.mjs +10 -0
- package/src/procedures/mode-switching/record-mode.mjs +8 -0
- package/src/procedures/mode-switching/switch-mode.mjs +16 -0
- package/src/procedures/opening/DESCRIPTION.md +6 -0
- package/src/procedures/opening/_index.mjs +8 -0
- package/src/procedures/opening/record-opening.mjs +4 -0
- package/src/procedures/promoting/DESCRIPTION.md +8 -0
- package/src/procedures/promoting/_index.mjs +14 -0
- package/src/procedures/promoting/apply.mjs +28 -0
- package/src/procedures/promoting/branch-flow.mjs +23 -0
- package/src/procedures/promoting/plan.mjs +14 -0
- package/src/procedures/promoting/read-position.mjs +15 -0
- package/src/procedures/sinking/DESCRIPTION.md +8 -0
- package/src/procedures/sinking/_index.mjs +12 -0
- package/src/procedures/sinking/inventory-forge.mjs +18 -0
- package/src/procedures/sinking/inventory-tools.mjs +7 -0
- package/src/procedures/skilling/DESCRIPTION.md +11 -0
- package/src/procedures/skilling/_index.mjs +15 -0
- package/src/procedures/skilling/collect-models.mjs +15 -0
- package/src/procedures/skilling/compose-skill.mjs +49 -0
- package/src/procedures/skilling/glossary.mjs +23 -0
- package/src/procedures/skilling/register-skills.mjs +21 -0
- package/src/procedures/skilling/write-skills.mjs +19 -0
- package/src/views/_index.mjs +23 -0
- package/src/views/agent/_index.mjs +2 -0
- package/src/views/agent/brief.mjs +34 -0
- package/src/views/help/_index.mjs +41 -0
- package/src/views/house/_index.mjs +56 -0
- package/src/views/inventory/_index.mjs +27 -0
- package/src/views/mcp/_index.mjs +31 -0
- package/src/views/mcp/tools.mjs +87 -0
- package/src/views/mode/_index.mjs +34 -0
- package/src/views/mode/chooser.mjs +37 -0
- package/src/views/promotion/_index.mjs +20 -0
- package/src/views/repl/_index.mjs +30 -0
- package/src/views/skills/_index.mjs +24 -0
- package/src/views/status/_index.mjs +57 -0
- package/src/views/status/tree.mjs +19 -0
- package/src/views/terminal/paint.mjs +22 -0
- package/template/SKILL.md +16 -0
- package/docs/README.md +0 -15
- package/docs/devlog.md +0 -20
- package/invoke-api.js +0 -0
- package/invoke-cli.js +0 -105
- package/invoke-desktop.js +0 -0
- package/invoke-exec.js +0 -0
- package/invoke-webapp.js +0 -0
- package/main.js +0 -33
- package/shell-procedures/deploy-new-workshop.sh +0 -15
- package/shell-procedures/new-project.sh +0 -0
- package/shell-procedures/new-sheme.sh +0 -0
- package/shell-procedures/new-superproject.sh +0 -6
- package/shell-procedures/open-project.sh +0 -0
- package/shell-procedures/pack-backup.sh +0 -22
- package/shell-procedures/project-to-sarcophag.sh +0 -0
- package/shell-procedures/publicate.sh +0 -0
- package/shell-procedures/pull-archive.sh +0 -0
- package/shell-procedures/purge-workshop.sh +0 -4
- package/shell-procedures/push-to-bos-server.sh +0 -0
- package/shell-procedures/start-cli-interface.sh +0 -1
- package/shell-procedures/sweep-into-throwbox.sh +0 -0
- package/shell-procedures/synchronize.sh +0 -7
- package/system/bridges/README.md +0 -4
- package/system/bridges/main.js +0 -41
- package/system/commands/README.md +0 -0
- package/system/commands/debug.js +0 -20
- package/system/commands/exit.js +0 -19
- package/system/core/README.md +0 -0
- package/system/core/basic-subject-model.js +0 -200
- package/system/core/config-controll.js +0 -51
- package/system/core/contain-controll.js +0 -28
- package/system/core/event-controll.js +0 -12
- package/system/core/extending-mod.js +0 -145
- package/system/core/main.js +0 -184
- package/system/core/raport-controll.js +0 -10
- package/system/core/static-extender.js +0 -19
- package/system/factors/README.md +0 -0
- package/system/factors/bridge-factory.js +0 -5
- package/system/factors/command-factory.js +0 -45
- package/system/factors/config-factory.js +0 -6
- package/system/factors/controller-factory.js +0 -5
- package/system/factors/interface-factory.js +0 -70
- package/system/factors/model-factory.js +0 -0
- package/system/interfaces/README.md +0 -28
- package/system/interfaces/cli/index.js +0 -96
- package/system/interfaces/cli/init.js +0 -47
- package/system/interfaces/cli/loop.js +0 -7
- package/system/interfaces/cli/on-close.js +0 -17
- package/system/interfaces/cli/on-line.js +0 -24
- package/system/interfaces/cli/on-resume.js +0 -15
- package/system/interfaces/cli/setup.js +0 -8
- package/system/models/README.md +0 -47
- package/system/models/archive/README.md +0 -0
- package/system/models/archive/actions/README.md +0 -0
- package/system/models/archive/class.js +0 -23
- package/system/models/archive/events/README.md +0 -0
- package/system/models/archive/index.json +0 -18
- package/system/models/archive/listeners/README.md +0 -0
- package/system/models/archive/methods/README.md +0 -0
- package/system/models/forge/README.md +0 -0
- package/system/models/forge/actions/README.md +0 -0
- package/system/models/forge/class.js +0 -23
- package/system/models/forge/events/README.md +0 -0
- package/system/models/forge/index.json +0 -18
- package/system/models/forge/listeners/README.md +0 -0
- package/system/models/forge/methods/README.md +0 -0
- package/system/models/project/README.md +0 -0
- package/system/models/project/actions/README.md +0 -0
- package/system/models/project/class.js +0 -23
- package/system/models/project/events/README.md +0 -0
- package/system/models/project/index.json +0 -18
- package/system/models/project/listeners/README.md +0 -0
- package/system/models/project/methods/README.md +0 -0
- package/system/models/sarcophag/README.md +0 -0
- package/system/models/sarcophag/actions/README.md +0 -0
- package/system/models/sarcophag/class.js +0 -22
- package/system/models/sarcophag/events/README.md +0 -0
- package/system/models/sarcophag/index.json +0 -18
- package/system/models/sarcophag/listeners/README.md +0 -0
- package/system/models/sarcophag/methods/README.md +0 -0
- package/system/models/sheme/README.md +0 -0
- package/system/models/sheme/actions/README.md +0 -0
- package/system/models/sheme/class.js +0 -23
- package/system/models/sheme/events/README.md +0 -0
- package/system/models/sheme/index.json +0 -18
- package/system/models/sheme/listeners/README.md +0 -0
- package/system/models/sheme/methods/README.md +0 -0
- package/system/models/superproject/README.md +0 -0
- package/system/models/superproject/actions/README.md +0 -0
- package/system/models/superproject/class.js +0 -23
- package/system/models/superproject/events/README.md +0 -0
- package/system/models/superproject/index.json +0 -18
- package/system/models/superproject/listeners/README.md +0 -0
- package/system/models/superproject/methods/README.md +0 -0
- package/system/models/throwbox/README.md +0 -0
- package/system/models/throwbox/actions/README.md +0 -0
- package/system/models/throwbox/class.js +0 -23
- package/system/models/throwbox/events/README.md +0 -0
- package/system/models/throwbox/index.json +0 -18
- package/system/models/throwbox/listeners/README.md +0 -0
- package/system/models/throwbox/methods/README.md +0 -0
- package/system/models/workshop/README.md +0 -0
- package/system/models/workshop/actions/README.md +0 -0
- package/system/models/workshop/class.js +0 -22
- package/system/models/workshop/events/README.md +0 -0
- package/system/models/workshop/index.json +0 -18
- package/system/models/workshop/listeners/README.md +0 -0
- package/system/models/workshop/methods/README.md +0 -0
- package/system/resources/textarts/big-logo-title.txt +0 -24
- package/system/resources/textarts/big-shortcut-logo-title.txt +0 -10
- package/system/resources/textarts/medium-logo-title.txt +0 -13
- package/system/resources/textarts/minimenu-header.ptxml +0 -13
- package/system/resources/textarts/minimenu-header.txt +0 -11
- package/system/resources/textarts/small-logo-title.txt +0 -10
- package/system/resources/textarts/wellcome.txt +0 -10
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// The self-hosted Gitea that carries private scope repositories and pre-public drafts.
|
|
2
|
+
// Address: options.url or $GITEA_URL (e.g. http://gitea.lan:3000); token: options.token or $GITEA_TOKEN.
|
|
3
|
+
import { BOS } from "../../main.ts";
|
|
4
|
+
|
|
5
|
+
export class GiteaApi extends BOS.Bridge {
|
|
6
|
+
static id = "gitea-api";
|
|
7
|
+
|
|
8
|
+
get url() {
|
|
9
|
+
const url = this.options.url ?? process.env.GITEA_URL;
|
|
10
|
+
if (!url) throw new Error("Gitea address unknown: set $GITEA_URL");
|
|
11
|
+
return url.replace(/\/+$/, "");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get token() {
|
|
15
|
+
return this.options.token ?? process.env.GITEA_TOKEN;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async request(method, path, body) {
|
|
19
|
+
const response = await fetch(`${this.url}/api/v1${path}`, {
|
|
20
|
+
method,
|
|
21
|
+
headers: {
|
|
22
|
+
"content-type": "application/json",
|
|
23
|
+
...(this.token ? { authorization: `token ${this.token}` } : {}),
|
|
24
|
+
},
|
|
25
|
+
body: body && JSON.stringify(body),
|
|
26
|
+
});
|
|
27
|
+
if (!response.ok) throw new Error(`gitea ${method} ${path}: ${response.status} ${response.statusText}`);
|
|
28
|
+
return response.status === 204 ? null : response.json();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async available() {
|
|
32
|
+
try {
|
|
33
|
+
await this.request("GET", "/version");
|
|
34
|
+
return true;
|
|
35
|
+
} catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async me() {
|
|
41
|
+
return (await this.request("GET", "/user")).login;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async repos() {
|
|
45
|
+
return (await this.request("GET", "/user/repos")).map((r) => ({
|
|
46
|
+
name: r.full_name,
|
|
47
|
+
private: r.private,
|
|
48
|
+
url: r.clone_url,
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// scopes are private by default
|
|
53
|
+
createRepo(name, { private: isPrivate = true, description = "" } = {}) {
|
|
54
|
+
return this.request("POST", "/user/repos", { name, private: isPrivate, description, default_branch: "master" });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
cloneUrl(owner, repo) {
|
|
58
|
+
return `${this.url}/${owner}/${repo}.git`;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export default GiteaApi;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// GitHub through octokit. Token: options.token, $GITHUB_TOKEN or $GH_TOKEN.
|
|
2
|
+
import { Octokit } from "octokit";
|
|
3
|
+
|
|
4
|
+
import { BOS } from "../../main.ts";
|
|
5
|
+
|
|
6
|
+
export class GithubApi extends BOS.Bridge {
|
|
7
|
+
static id = "github-api";
|
|
8
|
+
|
|
9
|
+
connect() {
|
|
10
|
+
return new Octokit({ auth: this.options.token ?? process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async available() {
|
|
14
|
+
try {
|
|
15
|
+
await this.me();
|
|
16
|
+
return true;
|
|
17
|
+
} catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async me() {
|
|
23
|
+
return (await this.client.rest.users.getAuthenticated()).data.login;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async repos() {
|
|
27
|
+
const repos = await this.client.paginate(this.client.rest.repos.listForAuthenticatedUser, { per_page: 100 });
|
|
28
|
+
return repos.map((r) => ({ name: r.full_name, private: r.private, url: r.clone_url, branch: r.default_branch }));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async repo(owner, repo) {
|
|
32
|
+
return (await this.client.rest.repos.get({ owner, repo })).data;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async createRepo(name, { private: isPrivate = false, description = "" } = {}) {
|
|
36
|
+
return (await this.client.rest.repos.createForAuthenticatedUser({ name, private: isPrivate, description })).data;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// releasing → master lands in canon through a pull request
|
|
40
|
+
async pullRequest({ owner, repo, head, base = "master", title = `${head} → ${base}`, body = "" }) {
|
|
41
|
+
return (await this.client.rest.pulls.create({ owner, repo, head, base, title, body })).data;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default GithubApi;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Publishing a package to npm. Dry run unless told otherwise.
|
|
2
|
+
import { BOS } from "../../main.ts";
|
|
3
|
+
import SubprocessRunner from "../subprocess-runner/_index.mjs";
|
|
4
|
+
|
|
5
|
+
const npm = new SubprocessRunner({ command: "npm" });
|
|
6
|
+
|
|
7
|
+
export class NpmPublish extends BOS.Bridge {
|
|
8
|
+
static id = "npm-publish";
|
|
9
|
+
|
|
10
|
+
available() {
|
|
11
|
+
return npm.available();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
publish(dir, { dryRun = true, tag = "latest" } = {}) {
|
|
15
|
+
return npm.run("npm", ["publish", "--tag", tag, ...(dryRun ? ["--dry-run"] : [])], { cwd: dir, inherit: true });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default NpmPublish;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Local language models through the ollama client (host: options.host, $OLLAMA_HOST
|
|
2
|
+
// or http://127.0.0.1:11434). Ravens (resources/ravens/) speak through it.
|
|
3
|
+
// Before any call the House (resources/house/) is asked: only active residents are called.
|
|
4
|
+
import { Ollama } from "ollama";
|
|
5
|
+
|
|
6
|
+
import { BOS } from "../../main.ts";
|
|
7
|
+
import House from "../../models/house/class.mjs";
|
|
8
|
+
import { listRavens, readRaven } from "./ravens.mjs";
|
|
9
|
+
|
|
10
|
+
export class OllamaLink extends BOS.Bridge {
|
|
11
|
+
static id = "ollama-link";
|
|
12
|
+
|
|
13
|
+
connect() {
|
|
14
|
+
return new Ollama({ host: this.options.host ?? process.env.OLLAMA_HOST ?? "http://127.0.0.1:11434" });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// give up after `ms`, abort the request, and answer null instead of throwing
|
|
18
|
+
async within(ms, work) {
|
|
19
|
+
let timer;
|
|
20
|
+
const timeout = new Promise((resolve) => {
|
|
21
|
+
timer = setTimeout(() => {
|
|
22
|
+
this.client.abort();
|
|
23
|
+
resolve(null);
|
|
24
|
+
}, ms);
|
|
25
|
+
});
|
|
26
|
+
try {
|
|
27
|
+
return await Promise.race([work(), timeout]);
|
|
28
|
+
} catch {
|
|
29
|
+
return null;
|
|
30
|
+
} finally {
|
|
31
|
+
clearTimeout(timer);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// names, architectures and parents of the served models: reading the list starts no model
|
|
36
|
+
async catalog() {
|
|
37
|
+
const listed = await this.within(2000, () => this.client.list());
|
|
38
|
+
return (
|
|
39
|
+
listed?.models.map((m) => ({
|
|
40
|
+
name: m.name,
|
|
41
|
+
family: m.details?.family ?? null,
|
|
42
|
+
parent: m.details?.parent_model || null,
|
|
43
|
+
})) ?? []
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async models() {
|
|
48
|
+
return (await this.catalog()).map((entry) => entry.name);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get house() {
|
|
52
|
+
this._house ??= new House();
|
|
53
|
+
return this._house;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async available(model) {
|
|
57
|
+
if (model && !this.house.mayCall(model)) return false;
|
|
58
|
+
const models = await this.models();
|
|
59
|
+
return model ? models.some((name) => name === model || name === `${model}:latest`) : models.length > 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
raven(name) {
|
|
63
|
+
return readRaven(name);
|
|
64
|
+
}
|
|
65
|
+
ravens() {
|
|
66
|
+
return listRavens();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// one question to one raven; `format` is a JSON schema for structured answers
|
|
70
|
+
// a cold model can take a minute to load; keep_alive keeps it warm for the next calls
|
|
71
|
+
async ask(ravenName, prompt, { format, timeout = 90000, model, keepAlive = "30m" } = {}) {
|
|
72
|
+
const raven = this.raven(ravenName);
|
|
73
|
+
const chosen = model ?? process.env[`BOS_${ravenName.toUpperCase()}_MODEL`] ?? raven.model;
|
|
74
|
+
const { state, reason } = this.house.stateOf(chosen);
|
|
75
|
+
if (state !== "active") throw new Error(`${chosen} is ${state} and is not called.${reason ? ` ${reason}` : ""}`);
|
|
76
|
+
const response = await this.within(timeout, () =>
|
|
77
|
+
this.client.chat({
|
|
78
|
+
model: chosen,
|
|
79
|
+
messages: [
|
|
80
|
+
{ role: "system", content: raven.system },
|
|
81
|
+
{ role: "user", content: prompt },
|
|
82
|
+
],
|
|
83
|
+
format,
|
|
84
|
+
stream: false,
|
|
85
|
+
keep_alive: keepAlive,
|
|
86
|
+
options: { temperature: 0.2 },
|
|
87
|
+
}),
|
|
88
|
+
);
|
|
89
|
+
return response?.message?.content ?? null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export default OllamaLink;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Ravens: AI helpers of the workshop, one markdown file each in resources/ravens/.
|
|
2
|
+
// Frontmatter (model, duty) + the text below it as the raven's system prompt.
|
|
3
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
import { RESOURCES } from "../../core/self.mjs";
|
|
7
|
+
|
|
8
|
+
const DIR = join(RESOURCES, "ravens");
|
|
9
|
+
|
|
10
|
+
export function readRaven(name) {
|
|
11
|
+
const path = join(DIR, `${name}.md`);
|
|
12
|
+
if (!existsSync(path)) throw new Error(`no raven "${name}" in resources/ravens/`);
|
|
13
|
+
const [, head = "", system = ""] = readFileSync(path, "utf8").match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/) ?? [];
|
|
14
|
+
const meta = Object.fromEntries(
|
|
15
|
+
head
|
|
16
|
+
.split("\n")
|
|
17
|
+
.map((line) => line.match(/^(\w+):\s*(.*)$/))
|
|
18
|
+
.filter(Boolean)
|
|
19
|
+
.map(([, k, v]) => [k, v.trim()]),
|
|
20
|
+
);
|
|
21
|
+
return { name, ...meta, system: system.trim() };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const listRavens = () =>
|
|
25
|
+
existsSync(DIR)
|
|
26
|
+
? readdirSync(DIR)
|
|
27
|
+
.filter((file) => file.endsWith(".md"))
|
|
28
|
+
.map((file) => readRaven(file.slice(0, -3)))
|
|
29
|
+
: [];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Other hosts over ssh; aliases come from ~/.ssh/config (glossary: setup).
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
import { BOS } from "../../main.ts";
|
|
7
|
+
import SubprocessRunner from "../subprocess-runner/_index.mjs";
|
|
8
|
+
|
|
9
|
+
const ssh = new SubprocessRunner({ command: "ssh" });
|
|
10
|
+
|
|
11
|
+
export class SshLink extends BOS.Bridge {
|
|
12
|
+
static id = "ssh-link";
|
|
13
|
+
|
|
14
|
+
available() {
|
|
15
|
+
return Promise.resolve(ssh.try("ssh", ["-V"]) !== null);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
aliases(config = join(homedir(), ".ssh", "config")) {
|
|
19
|
+
try {
|
|
20
|
+
return [...readFileSync(config, "utf8").matchAll(/^\s*Host\s+(.+)$/gim)]
|
|
21
|
+
.flatMap((match) => match[1].split(/\s+/))
|
|
22
|
+
.filter((alias) => !alias.includes("*"));
|
|
23
|
+
} catch {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
run(host, command) {
|
|
29
|
+
return ssh.run("ssh", ["-o", "BatchMode=yes", host, command]);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default SshLink;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Any command-line tool as a bridge: run it, or ask whether it is installed.
|
|
2
|
+
import { execFileSync, spawnSync } from "node:child_process";
|
|
3
|
+
|
|
4
|
+
import { BOS } from "../../main.ts";
|
|
5
|
+
|
|
6
|
+
export class SubprocessRunner extends BOS.Bridge {
|
|
7
|
+
static id = "subprocess-runner";
|
|
8
|
+
|
|
9
|
+
async available(command = this.options.command) {
|
|
10
|
+
if (!command) return false;
|
|
11
|
+
return spawnSync(command, ["--version"], { stdio: "ignore" }).status === 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
run(command, args = [], { cwd = process.cwd(), inherit = false } = {}) {
|
|
15
|
+
const output = execFileSync(command, args, {
|
|
16
|
+
cwd,
|
|
17
|
+
encoding: "utf8",
|
|
18
|
+
stdio: inherit ? "inherit" : ["ignore", "pipe", "pipe"],
|
|
19
|
+
});
|
|
20
|
+
return typeof output === "string" ? output.trim() : "";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// like run, but null instead of throwing
|
|
24
|
+
try(command, args, options) {
|
|
25
|
+
try {
|
|
26
|
+
return this.run(command, args, options);
|
|
27
|
+
} catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default SubprocessRunner;
|
package/src/cli.mjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// bos <command> [operands] [--json] [--dry-run] [--workshop=PATH]
|
|
3
|
+
import { VERSION } from "./core/self.mjs";
|
|
4
|
+
import { BOS } from "./main.ts";
|
|
5
|
+
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
const flags = Object.fromEntries(
|
|
8
|
+
args
|
|
9
|
+
.filter((arg) => arg.startsWith("--"))
|
|
10
|
+
.map((arg) => {
|
|
11
|
+
const [key, value = true] = arg.slice(2).split("=");
|
|
12
|
+
return [key.replace(/-(\w)/g, (_, c) => c.toUpperCase()), value];
|
|
13
|
+
}),
|
|
14
|
+
);
|
|
15
|
+
const [name = "help", ...operands] = args.filter((arg) => !arg.startsWith("--"));
|
|
16
|
+
|
|
17
|
+
if (flags.version) {
|
|
18
|
+
console.log(VERSION);
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const bos = await new BOS({ workshop: flags.workshop }).load();
|
|
24
|
+
const output = await bos.command(name, operands, flags);
|
|
25
|
+
if (output !== undefined) console.log(typeof output === "string" ? output : JSON.stringify(output, null, 2));
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error(`bos ${name}: ${error.message}${error.procedure ? `\n in ${error.procedure}` : ""}`);
|
|
28
|
+
process.exitCode = 1;
|
|
29
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*
|
|
2
|
+
based on index.json in dirs generate commands
|
|
3
|
+
{
|
|
4
|
+
"path": "/status", # url path for apis
|
|
5
|
+
"info": "status information", # shortest explanation
|
|
6
|
+
"help": ["./help.md", "MD"], # detailed usage with render filetype handling
|
|
7
|
+
"inline": "./exec.mjs", # when called as oneline command with subcommand to return output to standard output, if it is streamable command then piping of input-output should be also handled there somewhere... it can be splitted to another file but have to be imported later
|
|
8
|
+
"repl": "./repl.mjs" # interactive cli menu that allows standard input of choice or more advanced nice-looking terminal gui based on universal ascii base
|
|
9
|
+
"mode": "conform" # mode of work the command serves (almanac, conform, smeltry, commandorate, provision); none: general
|
|
10
|
+
}
|
|
11
|
+
not all of these are required, most minimalistic now is "help" - only show universal help on general error or invoking help
|
|
12
|
+
should list commands and what they does
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
16
|
+
import { dirname, join } from "node:path";
|
|
17
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
18
|
+
|
|
19
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
|
|
21
|
+
// "./exec.mjs" → a function that imports the module on first call and runs its default export
|
|
22
|
+
const lazy = (dir, file) => async (context) => (await import(pathToFileURL(join(dir, file)))).default(context);
|
|
23
|
+
|
|
24
|
+
export function loadCommand(dir, name = dir.split("/").pop()) {
|
|
25
|
+
const index = JSON.parse(readFileSync(join(dir, "index.json"), "utf8"));
|
|
26
|
+
const [helpFile, helpType = "MD"] = [].concat(index.help ?? []);
|
|
27
|
+
return {
|
|
28
|
+
name,
|
|
29
|
+
path: index.path ?? `/${name}`,
|
|
30
|
+
info: index.info ?? "",
|
|
31
|
+
mode: index.mode ?? null, // the mode of work this command serves; null: any mode
|
|
32
|
+
help: () =>
|
|
33
|
+
helpFile && existsSync(join(dir, helpFile))
|
|
34
|
+
? { text: readFileSync(join(dir, helpFile), "utf8"), type: helpType }
|
|
35
|
+
: null,
|
|
36
|
+
inline: index.inline
|
|
37
|
+
? lazy(dir, index.inline)
|
|
38
|
+
: async () => {
|
|
39
|
+
throw new Error(`${name} has no inline form; see: bos help ${name}`);
|
|
40
|
+
},
|
|
41
|
+
repl: index.repl ? lazy(dir, index.repl) : null,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function loadCommands(root = HERE) {
|
|
46
|
+
return Object.fromEntries(
|
|
47
|
+
readdirSync(root, { withFileTypes: true })
|
|
48
|
+
.filter((entry) => entry.isDirectory() && existsSync(join(root, entry.name, "index.json")))
|
|
49
|
+
.map((entry) => [entry.name, loadCommand(join(root, entry.name), entry.name)]),
|
|
50
|
+
);
|
|
51
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default async ({ bos, operands: [file, source], flags }) => {
|
|
2
|
+
const context = await bos.workshop.describe({
|
|
3
|
+
...(flags.hook ? { file, source } : {}),
|
|
4
|
+
...(flags.skryba === "0" || flags.plain ? { skryba: false } : {}),
|
|
5
|
+
});
|
|
6
|
+
if (flags.hook) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
const note = context.skryba && !context.skryba.used ? `\n# Skryba: ${context.skryba.reason}` : "";
|
|
10
|
+
return (context.message ?? "nothing staged") + note;
|
|
11
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export default ({ bos, operands: [name], flags }) => {
|
|
2
|
+
const view = new bos.views.HelpView();
|
|
3
|
+
const state = { commands: bos.commands, command: name, help: name && bos.commands[name]?.help() };
|
|
4
|
+
if (name && !bos.commands[name]) throw new Error(`unknown command "${name}"`);
|
|
5
|
+
return view.render(state, flags.json ? "json" : "text");
|
|
6
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# house
|
|
2
|
+
|
|
3
|
+
`bos house [--all]` shows the House of Anubis: each family of
|
|
4
|
+
`resources/house/families/` with its state (active, resting, frozen), its
|
|
5
|
+
residents, their duties, and whether ollama serves them now. `--all` also
|
|
6
|
+
lists the served models no family claims yet.
|
|
7
|
+
|
|
8
|
+
Only model names are read from ollama; no resident is started or prompted.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# locate
|
|
2
|
+
|
|
3
|
+
`bos locate` prints the active workshop and the rule that found it:
|
|
4
|
+
`--workshop`, then `$BOS_WORKSHOP`, the nearest parent `__WORKSHOP`, the
|
|
5
|
+
workshop BOS is installed in, and `~/__WORKSHOP`. Also shows where BOS itself
|
|
6
|
+
sits, e.g. `forge / blacksmith-organization-system / bos-skillset`.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { modeByDigit } from "../../models/workshop/modes.mjs";
|
|
2
|
+
|
|
3
|
+
export default async ({ bos, operands: [asked], flags }) => {
|
|
4
|
+
const view = new bos.views.ModeView();
|
|
5
|
+
const format = flags.json ? "json" : "text";
|
|
6
|
+
|
|
7
|
+
if (asked === undefined) {
|
|
8
|
+
const { config } = await bos.workshop.status();
|
|
9
|
+
const digit = await bos.views.chooseDigit(`${view.menu(config.mode)}choose 0-5: `, 5);
|
|
10
|
+
if (digit === 0) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
asked = modeByDigit(digit);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return view.render(await bos.workshop.mode(asked), format);
|
|
17
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# mode
|
|
2
|
+
|
|
3
|
+
`bos mode <name|digit>` switches the mode of work of this workshop.
|
|
4
|
+
`bos mode` shows the menu and waits for one digit (no Enter needed); `0` leaves it.
|
|
5
|
+
|
|
6
|
+
| digit | mode | covers |
|
|
7
|
+
| ----- | ---- | ------ |
|
|
8
|
+
| 1 | ALMANAC | emergency protocols: sinking |
|
|
9
|
+
| 2 | CONFORM | establishing the workshop, migrations, cleaning, verifying, syncing between fortified workshops |
|
|
10
|
+
| 3 | SMELTRY | code, development, active editing, publishing changes |
|
|
11
|
+
| 4 | COMMANDORATE | rulesets, privileges, roles, switching modes |
|
|
12
|
+
| 5 | PROVISION | presenting what a source of truth delivers, e.g. a repository on GitHub |
|
|
13
|
+
|
|
14
|
+
The mode is kept in `.BOS/workshop.json`, and every switch is recorded in storylines.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { modeByDigit } from "../../models/workshop/modes.mjs";
|
|
2
|
+
|
|
3
|
+
// inside `bos repl` the prompt owns the input, so the digit is confirmed with Enter
|
|
4
|
+
export default async ({ bos, operands: [asked], io }) => {
|
|
5
|
+
const view = new bos.views.ModeView();
|
|
6
|
+
|
|
7
|
+
if (asked === undefined) {
|
|
8
|
+
const { config } = await bos.workshop.status();
|
|
9
|
+
console.log(view.menu(config.mode));
|
|
10
|
+
const digit = Number((await io.question("choose 0-5: ")).trim()[0]);
|
|
11
|
+
if (!digit || digit > 5) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
asked = modeByDigit(digit);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return view.text(await bos.workshop.mode(asked));
|
|
18
|
+
};
|