omegon 0.9.2 → 0.10.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.
- package/extensions/lib/sci-ui.ts +1 -1
- package/extensions/sermon-widget.ts +140 -0
- package/extensions/sermon.ts +147 -0
- package/extensions/spinner-verbs.ts +101 -10
- package/node_modules/@styrene-lab/pi-ai/dist/models.generated.d.ts +0 -34
- package/node_modules/@styrene-lab/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/node_modules/@styrene-lab/pi-ai/dist/models.generated.js +0 -34
- package/node_modules/@styrene-lab/pi-ai/dist/models.generated.js.map +1 -1
- package/node_modules/@styrene-lab/pi-ai/dist/utils/oauth/anthropic.d.ts.map +1 -1
- package/node_modules/@styrene-lab/pi-ai/dist/utils/oauth/anthropic.js +0 -1
- package/node_modules/@styrene-lab/pi-ai/dist/utils/oauth/anthropic.js.map +1 -1
- package/node_modules/@styrene-lab/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +4 -0
- package/node_modules/@styrene-lab/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/node_modules/@styrene-lab/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +34 -8
- package/node_modules/@styrene-lab/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/node_modules/@styrene-lab/pi-tui/dist/components/box.d.ts +9 -1
- package/node_modules/@styrene-lab/pi-tui/dist/components/box.d.ts.map +1 -1
- package/node_modules/@styrene-lab/pi-tui/dist/components/box.js +23 -5
- package/node_modules/@styrene-lab/pi-tui/dist/components/box.js.map +1 -1
- package/node_modules/@styrene-lab/pi-tui/dist/components/text.d.ts +7 -0
- package/node_modules/@styrene-lab/pi-tui/dist/components/text.d.ts.map +1 -1
- package/node_modules/@styrene-lab/pi-tui/dist/components/text.js +26 -8
- package/node_modules/@styrene-lab/pi-tui/dist/components/text.js.map +1 -1
- package/package.json +1 -1
- package/scripts/check-vendor-dist.mjs +6 -8
- package/scripts/check-vendor-dist.test.mjs +129 -0
- package/scripts/publish-pi-mono.sh +2 -1
- package/themes/alpharius.json +1 -1
|
@@ -7,6 +7,8 @@ export class Text {
|
|
|
7
7
|
paddingX; // Left/right padding
|
|
8
8
|
paddingY; // Top/bottom padding
|
|
9
9
|
customBgFn;
|
|
10
|
+
borderFn;
|
|
11
|
+
borderGlyph = "▎";
|
|
10
12
|
// Cache for rendered output
|
|
11
13
|
cachedText;
|
|
12
14
|
cachedWidth;
|
|
@@ -17,6 +19,18 @@ export class Text {
|
|
|
17
19
|
this.paddingY = paddingY;
|
|
18
20
|
this.customBgFn = customBgFn;
|
|
19
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Set a left-border color function. When set, each line is prefixed with
|
|
24
|
+
* a thin vertical bar in the given color. Pass undefined to remove.
|
|
25
|
+
*/
|
|
26
|
+
setBorderFn(fn, glyph) {
|
|
27
|
+
this.borderFn = fn;
|
|
28
|
+
if (glyph !== undefined)
|
|
29
|
+
this.borderGlyph = glyph;
|
|
30
|
+
this.cachedText = undefined;
|
|
31
|
+
this.cachedWidth = undefined;
|
|
32
|
+
this.cachedLines = undefined;
|
|
33
|
+
}
|
|
20
34
|
setText(text) {
|
|
21
35
|
this.text = text;
|
|
22
36
|
this.cachedText = undefined;
|
|
@@ -49,34 +63,38 @@ export class Text {
|
|
|
49
63
|
}
|
|
50
64
|
// Replace tabs with 3 spaces
|
|
51
65
|
const normalizedText = this.text.replace(/\t/g, " ");
|
|
52
|
-
// Calculate content width (subtract left/right margins)
|
|
53
|
-
const
|
|
66
|
+
// Calculate content width (subtract left/right margins and optional border)
|
|
67
|
+
const hasBorder = !!this.borderFn;
|
|
68
|
+
const borderWidth = hasBorder ? 1 : 0;
|
|
69
|
+
const contentWidth = Math.max(1, width - this.paddingX * 2 - borderWidth);
|
|
54
70
|
// Wrap text (this preserves ANSI codes but does NOT pad)
|
|
55
71
|
const wrappedLines = wrapTextWithAnsi(normalizedText, contentWidth);
|
|
56
72
|
// Add margins and background to each line
|
|
57
73
|
const leftMargin = " ".repeat(this.paddingX);
|
|
58
74
|
const rightMargin = " ".repeat(this.paddingX);
|
|
59
75
|
const contentLines = [];
|
|
76
|
+
const borderStr = hasBorder ? this.borderFn(this.borderGlyph) : "";
|
|
77
|
+
const innerWidth = hasBorder ? width - 1 : width;
|
|
60
78
|
for (const line of wrappedLines) {
|
|
61
79
|
// Add margins
|
|
62
80
|
const lineWithMargins = leftMargin + line + rightMargin;
|
|
63
81
|
// Apply background if specified (this also pads to full width)
|
|
64
82
|
if (this.customBgFn) {
|
|
65
|
-
contentLines.push(applyBackgroundToLine(lineWithMargins,
|
|
83
|
+
contentLines.push(borderStr + applyBackgroundToLine(lineWithMargins, innerWidth, this.customBgFn));
|
|
66
84
|
}
|
|
67
85
|
else {
|
|
68
86
|
// No background - just pad to width with spaces
|
|
69
87
|
const visibleLen = visibleWidth(lineWithMargins);
|
|
70
|
-
const paddingNeeded = Math.max(0,
|
|
71
|
-
contentLines.push(lineWithMargins + " ".repeat(paddingNeeded));
|
|
88
|
+
const paddingNeeded = Math.max(0, innerWidth - visibleLen);
|
|
89
|
+
contentLines.push(borderStr + lineWithMargins + " ".repeat(paddingNeeded));
|
|
72
90
|
}
|
|
73
91
|
}
|
|
74
92
|
// Add top/bottom padding (empty lines)
|
|
75
|
-
const emptyLine = " ".repeat(
|
|
93
|
+
const emptyLine = " ".repeat(innerWidth);
|
|
76
94
|
const emptyLines = [];
|
|
77
95
|
for (let i = 0; i < this.paddingY; i++) {
|
|
78
|
-
const line = this.customBgFn ? applyBackgroundToLine(emptyLine,
|
|
79
|
-
emptyLines.push(line);
|
|
96
|
+
const line = this.customBgFn ? applyBackgroundToLine(emptyLine, innerWidth, this.customBgFn) : emptyLine;
|
|
97
|
+
emptyLines.push(borderStr + line);
|
|
80
98
|
}
|
|
81
99
|
const result = [...emptyLines, ...contentLines, ...emptyLines];
|
|
82
100
|
// Update cache
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/components/text.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpF;;GAEG;AACH,MAAM,OAAO,IAAI;IACR,IAAI,CAAS;IACb,QAAQ,CAAS,CAAC,qBAAqB;IACvC,QAAQ,CAAS,CAAC,qBAAqB;IACvC,UAAU,CAA4B;
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/components/text.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Component } from \"../tui.js\";\nimport { applyBackgroundToLine, visibleWidth, wrapTextWithAnsi } from \"../utils.js\";\n\n/**\n * Text component - displays multi-line text with word wrapping\n */\nexport class Text implements Component {\n\tprivate text: string;\n\tprivate paddingX: number; // Left/right padding\n\tprivate paddingY: number; // Top/bottom padding\n\tprivate customBgFn?: (text: string) => string;\n\tprivate borderFn?: (glyph: string) => string;\n\tprivate borderGlyph = \"▎\";\n\n\t// Cache for rendered output\n\tprivate cachedText?: string;\n\tprivate cachedWidth?: number;\n\tprivate cachedLines?: string[];\n\n\tconstructor(text: string = \"\", paddingX: number = 1, paddingY: number = 1, customBgFn?: (text: string) => string) {\n\t\tthis.text = text;\n\t\tthis.paddingX = paddingX;\n\t\tthis.paddingY = paddingY;\n\t\tthis.customBgFn = customBgFn;\n\t}\n\n\t/**\n\t * Set a left-border color function. When set, each line is prefixed with\n\t * a thin vertical bar in the given color. Pass undefined to remove.\n\t */\n\tsetBorderFn(fn?: (glyph: string) => string, glyph?: string): void {\n\t\tthis.borderFn = fn;\n\t\tif (glyph !== undefined) this.borderGlyph = glyph;\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tsetText(text: string): void {\n\t\tthis.text = text;\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tsetCustomBgFn(customBgFn?: (text: string) => string): void {\n\t\tthis.customBgFn = customBgFn;\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\tinvalidate(): void {\n\t\tthis.cachedText = undefined;\n\t\tthis.cachedWidth = undefined;\n\t\tthis.cachedLines = undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\t// Check cache\n\t\tif (this.cachedLines && this.cachedText === this.text && this.cachedWidth === width) {\n\t\t\treturn this.cachedLines;\n\t\t}\n\n\t\t// Don't render anything if there's no actual text\n\t\tif (!this.text || this.text.trim() === \"\") {\n\t\t\tconst result: string[] = [];\n\t\t\tthis.cachedText = this.text;\n\t\t\tthis.cachedWidth = width;\n\t\t\tthis.cachedLines = result;\n\t\t\treturn result;\n\t\t}\n\n\t\t// Replace tabs with 3 spaces\n\t\tconst normalizedText = this.text.replace(/\\t/g, \" \");\n\n\t\t// Calculate content width (subtract left/right margins and optional border)\n\t\tconst hasBorder = !!this.borderFn;\n\t\tconst borderWidth = hasBorder ? 1 : 0;\n\t\tconst contentWidth = Math.max(1, width - this.paddingX * 2 - borderWidth);\n\n\t\t// Wrap text (this preserves ANSI codes but does NOT pad)\n\t\tconst wrappedLines = wrapTextWithAnsi(normalizedText, contentWidth);\n\n\t\t// Add margins and background to each line\n\t\tconst leftMargin = \" \".repeat(this.paddingX);\n\t\tconst rightMargin = \" \".repeat(this.paddingX);\n\t\tconst contentLines: string[] = [];\n\n\t\tconst borderStr = hasBorder ? this.borderFn!(this.borderGlyph) : \"\";\n\t\tconst innerWidth = hasBorder ? width - 1 : width;\n\n\t\tfor (const line of wrappedLines) {\n\t\t\t// Add margins\n\t\t\tconst lineWithMargins = leftMargin + line + rightMargin;\n\n\t\t\t// Apply background if specified (this also pads to full width)\n\t\t\tif (this.customBgFn) {\n\t\t\t\tcontentLines.push(borderStr + applyBackgroundToLine(lineWithMargins, innerWidth, this.customBgFn));\n\t\t\t} else {\n\t\t\t\t// No background - just pad to width with spaces\n\t\t\t\tconst visibleLen = visibleWidth(lineWithMargins);\n\t\t\t\tconst paddingNeeded = Math.max(0, innerWidth - visibleLen);\n\t\t\t\tcontentLines.push(borderStr + lineWithMargins + \" \".repeat(paddingNeeded));\n\t\t\t}\n\t\t}\n\n\t\t// Add top/bottom padding (empty lines)\n\t\tconst emptyLine = \" \".repeat(innerWidth);\n\t\tconst emptyLines: string[] = [];\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tconst line = this.customBgFn ? applyBackgroundToLine(emptyLine, innerWidth, this.customBgFn) : emptyLine;\n\t\t\temptyLines.push(borderStr + line);\n\t\t}\n\n\t\tconst result = [...emptyLines, ...contentLines, ...emptyLines];\n\n\t\t// Update cache\n\t\tthis.cachedText = this.text;\n\t\tthis.cachedWidth = width;\n\t\tthis.cachedLines = result;\n\n\t\treturn result.length > 0 ? result : [\"\"];\n\t}\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omegon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Omegon — an opinionated distribution of pi (by Mario Zechner) with extensions for lifecycle management, memory, orchestration, and visualization",
|
|
5
5
|
"bin": {
|
|
6
6
|
"omegon": "bin/omegon.mjs",
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* check-vendor-dist.mjs — Verify that vendor/pi-mono dist/ directories
|
|
3
|
-
* exist and
|
|
3
|
+
* exist and contain compiled output.
|
|
4
|
+
*
|
|
5
|
+
* This is an existence guard, not a freshness check. Freshness is guaranteed
|
|
6
|
+
* by the CI build step running `npm run build` on every publish invocation.
|
|
4
7
|
*
|
|
5
|
-
* Guards against publishing omegon with stale or missing vendor dist.
|
|
6
8
|
* Run after `npm run build` in vendor/pi-mono and before `npm publish`.
|
|
7
9
|
*/
|
|
8
10
|
|
|
9
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
11
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
10
12
|
import { resolve, dirname } from "node:path";
|
|
11
13
|
import { fileURLToPath } from "node:url";
|
|
12
|
-
import { execSync } from "node:child_process";
|
|
13
14
|
|
|
14
15
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
16
|
const root = resolve(__dirname, "..");
|
|
16
|
-
const vendorRoot = resolve(root, "vendor/pi-mono");
|
|
17
17
|
|
|
18
18
|
const pkg = JSON.parse(readFileSync(resolve(root, "package.json"), "utf8"));
|
|
19
19
|
const bundled = pkg.bundleDependencies || [];
|
|
@@ -34,9 +34,7 @@ for (const name of bundled) {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
// Spot-check: the dist should have .js files
|
|
37
|
-
const hasJs =
|
|
38
|
-
encoding: "utf8",
|
|
39
|
-
}).trim();
|
|
37
|
+
const hasJs = readdirSync(distDir).some((e) => e.endsWith(".js"));
|
|
40
38
|
if (!hasJs) {
|
|
41
39
|
console.error(`✗ ${name}: dist/ exists but contains no .js files`);
|
|
42
40
|
failed = true;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for check-vendor-dist.mjs and the prepack dist guard.
|
|
3
|
+
*
|
|
4
|
+
* Validates that the guardrails correctly detect missing/empty vendor dist.
|
|
5
|
+
* Uses a temp directory with a mock package structure.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, it, after } from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import {
|
|
11
|
+
mkdirSync,
|
|
12
|
+
writeFileSync,
|
|
13
|
+
readFileSync,
|
|
14
|
+
rmSync,
|
|
15
|
+
existsSync,
|
|
16
|
+
readdirSync,
|
|
17
|
+
} from "node:fs";
|
|
18
|
+
import { join } from "node:path";
|
|
19
|
+
import { tmpdir } from "node:os";
|
|
20
|
+
|
|
21
|
+
const tmp = join(tmpdir(), `vendor-dist-test-${Date.now()}`);
|
|
22
|
+
|
|
23
|
+
function makeMockProject(opts = {}) {
|
|
24
|
+
const { hasDist = true, hasJs = true } = opts;
|
|
25
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
26
|
+
|
|
27
|
+
const vendorPkg = join(tmp, "vendor", "mock-pkg");
|
|
28
|
+
mkdirSync(vendorPkg, { recursive: true });
|
|
29
|
+
writeFileSync(
|
|
30
|
+
join(vendorPkg, "package.json"),
|
|
31
|
+
JSON.stringify({ name: "@test/mock", version: "1.0.0" }),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
if (hasDist) {
|
|
35
|
+
mkdirSync(join(vendorPkg, "dist"), { recursive: true });
|
|
36
|
+
if (hasJs) {
|
|
37
|
+
writeFileSync(join(vendorPkg, "dist", "index.js"), "export default 1;");
|
|
38
|
+
} else {
|
|
39
|
+
writeFileSync(join(vendorPkg, "dist", "readme.txt"), "no js here");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
writeFileSync(
|
|
44
|
+
join(tmp, "package.json"),
|
|
45
|
+
JSON.stringify({
|
|
46
|
+
name: "test-root",
|
|
47
|
+
version: "1.0.0",
|
|
48
|
+
dependencies: { "@test/mock": "file:./vendor/mock-pkg" },
|
|
49
|
+
bundleDependencies: ["@test/mock"],
|
|
50
|
+
}),
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
return tmp;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function readPkg(root) {
|
|
57
|
+
return JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
describe("check-vendor-dist", () => {
|
|
61
|
+
after(() => rmSync(tmp, { recursive: true, force: true }));
|
|
62
|
+
|
|
63
|
+
it("passes when dist/ exists with .js files", () => {
|
|
64
|
+
const root = makeMockProject({ hasDist: true, hasJs: true });
|
|
65
|
+
const pkg = readPkg(root);
|
|
66
|
+
for (const name of pkg.bundleDependencies) {
|
|
67
|
+
const ref = pkg.dependencies[name];
|
|
68
|
+
assert.ok(ref.startsWith("file:"));
|
|
69
|
+
const distDir = join(root, ref.slice(5), "dist");
|
|
70
|
+
assert.ok(existsSync(distDir), `dist/ should exist at ${distDir}`);
|
|
71
|
+
const hasJs = readdirSync(distDir).some((e) => e.endsWith(".js"));
|
|
72
|
+
assert.ok(hasJs, "dist/ should contain .js files");
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("detects missing dist/ directory", () => {
|
|
77
|
+
makeMockProject({ hasDist: false });
|
|
78
|
+
const pkg = readPkg(tmp);
|
|
79
|
+
const ref = pkg.dependencies["@test/mock"];
|
|
80
|
+
const distDir = join(tmp, ref.slice(5), "dist");
|
|
81
|
+
assert.ok(!existsSync(distDir), "dist/ should not exist");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("detects dist/ with no .js files", () => {
|
|
85
|
+
makeMockProject({ hasDist: true, hasJs: false });
|
|
86
|
+
const pkg = readPkg(tmp);
|
|
87
|
+
const ref = pkg.dependencies["@test/mock"];
|
|
88
|
+
const distDir = join(tmp, ref.slice(5), "dist");
|
|
89
|
+
assert.ok(existsSync(distDir), "dist/ should exist");
|
|
90
|
+
const hasJs = readdirSync(distDir).some((e) => e.endsWith(".js"));
|
|
91
|
+
assert.ok(!hasJs, "dist/ should contain no .js files");
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe("prepack dist guard", () => {
|
|
96
|
+
after(() => rmSync(tmp, { recursive: true, force: true }));
|
|
97
|
+
|
|
98
|
+
it("readdirSync check catches missing dist", () => {
|
|
99
|
+
makeMockProject({ hasDist: false });
|
|
100
|
+
const pkg = readPkg(tmp);
|
|
101
|
+
const ref = pkg.dependencies["@test/mock"];
|
|
102
|
+
const distDir = join(tmp, ref.slice(5), "dist");
|
|
103
|
+
|
|
104
|
+
let caught = false;
|
|
105
|
+
try {
|
|
106
|
+
const entries = readdirSync(distDir);
|
|
107
|
+
if (!entries.some((e) => e.endsWith(".js"))) throw new Error("no .js");
|
|
108
|
+
} catch {
|
|
109
|
+
caught = true;
|
|
110
|
+
}
|
|
111
|
+
assert.ok(caught, "should catch missing dist/");
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("readdirSync check catches empty dist", () => {
|
|
115
|
+
makeMockProject({ hasDist: true, hasJs: false });
|
|
116
|
+
const pkg = readPkg(tmp);
|
|
117
|
+
const ref = pkg.dependencies["@test/mock"];
|
|
118
|
+
const distDir = join(tmp, ref.slice(5), "dist");
|
|
119
|
+
|
|
120
|
+
let caught = false;
|
|
121
|
+
try {
|
|
122
|
+
const entries = readdirSync(distDir);
|
|
123
|
+
if (!entries.some((e) => e.endsWith(".js"))) throw new Error("no .js");
|
|
124
|
+
} catch {
|
|
125
|
+
caught = true;
|
|
126
|
+
}
|
|
127
|
+
assert.ok(caught, "should catch dist/ with no .js files");
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Publish pi-mono fork packages to npm if their versions don't match what's on the registry.
|
|
3
3
|
# Called by CI before publishing omegon itself.
|
|
4
|
-
#
|
|
4
|
+
# Phase 1 rewrites file: refs in pi-mono's internal cross-deps for standalone npm publish.
|
|
5
|
+
# Omegon's own package.json keeps file: refs — bundleDependencies + prepack.mjs handles materialization.
|
|
5
6
|
set -euo pipefail
|
|
6
7
|
|
|
7
8
|
PACKAGES=("ai" "tui" "agent" "coding-agent" "mom" "pods" "web-ui")
|
package/themes/alpharius.json
CHANGED