@minhpnq1807/contextos 0.5.13 → 0.5.14

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/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.14
4
+
5
+ - Adds an actual rendered terminal demo GIF generated from `ctx debug` plus a real `codex exec` hook run.
6
+ - Points the README demo section at `docs/demo/contextos-demo.gif`.
7
+
3
8
  ## 0.5.13
4
9
 
5
10
  - Reworks the README for launch: demo-first positioning, fear hook, one-line install, before/after, and quick command table.
package/DEMO.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  Use this to record the README GIF or a short terminal clip.
4
4
 
5
+ The current rendered demo is checked in at:
6
+
7
+ ```text
8
+ docs/demo/contextos-demo.gif
9
+ ```
10
+
11
+ It was generated from an actual terminal transcript using:
12
+
13
+ ```text
14
+ node docs/demo/render-terminal-gif.mjs <terminal-log> docs/demo/contextos-demo.gif
15
+ ```
16
+
5
17
  ## Goal
6
18
 
7
19
  Show one thing clearly:
package/README.md CHANGED
@@ -21,7 +21,7 @@ Published package: [`@minhpnq1807/contextos`](https://www.npmjs.com/package/@min
21
21
 
22
22
  ## Demo
23
23
 
24
- ![ContextOS demo GIF placeholder](docs/contextos-demo-placeholder.svg)
24
+ ![ContextOS actual terminal demo](docs/demo/contextos-demo.gif)
25
25
 
26
26
  Example hook context injected before the agent works:
27
27
 
Binary file
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { execFileSync } from "node:child_process";
6
+
7
+ const [, , inputPath, outputPath = "docs/demo/contextos-demo.gif"] = process.argv;
8
+ if (!inputPath) {
9
+ console.error("Usage: node docs/demo/render-terminal-gif.mjs <terminal-log> [output.gif]");
10
+ process.exit(1);
11
+ }
12
+
13
+ const width = 960;
14
+ const height = 540;
15
+ const marginX = 52;
16
+ const marginY = 54;
17
+ const lineHeight = 18;
18
+ const maxLines = 22;
19
+ const maxColumns = 100;
20
+ const frameStep = 5;
21
+
22
+ const raw = fs.readFileSync(inputPath, "utf8");
23
+ const lines = clean(raw)
24
+ .split(/\r?\n/)
25
+ .map((line) => line.trimEnd())
26
+ .filter((line) => line && !line.includes("Script started") && !line.includes("Script done"));
27
+
28
+ const displayLines = wrapLines(lines, maxColumns).slice(0, 110);
29
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "contextos-demo-frames-"));
30
+ const frames = [];
31
+
32
+ for (let count = 1; count <= displayLines.length; count += frameStep) {
33
+ frames.push(writeFrame({ tmpDir, index: frames.length, lines: displayLines.slice(0, count) }));
34
+ }
35
+ frames.push(writeFrame({ tmpDir, index: frames.length, lines: displayLines }));
36
+
37
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true });
38
+ execFileSync("convert", ["-delay", "12", "-loop", "0", ...frames, outputPath], { stdio: "inherit" });
39
+ console.log(`Wrote ${outputPath}`);
40
+
41
+ function writeFrame({ tmpDir, index, lines }) {
42
+ const visible = lines.slice(-maxLines);
43
+ const svg = [
44
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">`,
45
+ `<rect width="${width}" height="${height}" fill="#0f1419"/>`,
46
+ `<rect x="24" y="24" width="${width - 48}" height="${height - 48}" rx="16" fill="#151b22" stroke="#34404d"/>`,
47
+ `<circle cx="56" cy="50" r="6" fill="#ff6b6b"/><circle cx="78" cy="50" r="6" fill="#ffd166"/><circle cx="100" cy="50" r="6" fill="#70d88b"/>`,
48
+ `<text x="124" y="57" fill="#9aa6b2" font-family="DejaVu Sans Mono, Consolas, monospace" font-size="15">ContextOS actual terminal demo</text>`,
49
+ `<text x="${marginX}" y="${marginY + 30}" fill="#d8dee9" font-family="DejaVu Sans Mono, Consolas, monospace" font-size="15">`
50
+ ];
51
+ visible.forEach((line, offset) => {
52
+ const y = offset === 0 ? 0 : lineHeight;
53
+ svg.push(`<tspan x="${marginX}" dy="${y}" fill="${colorForLine(line)}">${escapeXml(line)}</tspan>`);
54
+ });
55
+ svg.push("</text></svg>");
56
+ const filePath = path.join(tmpDir, `frame-${String(index).padStart(4, "0")}.svg`);
57
+ fs.writeFileSync(filePath, svg.join(""));
58
+ return filePath;
59
+ }
60
+
61
+ function clean(value) {
62
+ return String(value)
63
+ .replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, "")
64
+ .replace(/\r/g, "\n")
65
+ .replace(/\n+/g, "\n");
66
+ }
67
+
68
+ function wrapLines(sourceLines, widthLimit) {
69
+ const wrapped = [];
70
+ for (const line of sourceLines) {
71
+ if (line.length <= widthLimit) {
72
+ wrapped.push(line);
73
+ continue;
74
+ }
75
+ for (let index = 0; index < line.length; index += widthLimit) {
76
+ wrapped.push(`${index === 0 ? "" : " "}${line.slice(index, index + widthLimit)}`);
77
+ }
78
+ }
79
+ return wrapped;
80
+ }
81
+
82
+ function colorForLine(line) {
83
+ if (line.startsWith("$ ")) return "#8bd5ff";
84
+ if (/^(ContextOS debug|ContextOS report|Final additionalContext|Suggested files|Suggested workflows)/.test(line)) return "#ffd166";
85
+ if (/^(hook:|mcp:)/.test(line)) return "#9ad97f";
86
+ if (/^(codex|user|OpenAI Codex)/.test(line)) return "#c792ea";
87
+ if (/^#|^[-—]+$/.test(line)) return "#8a96a3";
88
+ return "#d8dee9";
89
+ }
90
+
91
+ function escapeXml(value) {
92
+ return String(value)
93
+ .replace(/&/g, "&amp;")
94
+ .replace(/</g, "&lt;")
95
+ .replace(/>/g, "&gt;")
96
+ .replace(/"/g, "&quot;");
97
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minhpnq1807/contextos",
3
- "version": "0.5.13",
3
+ "version": "0.5.14",
4
4
  "description": "Task-aware AGENTS.md context injection and compliance reporting for Codex, Claude Code, and Antigravity.",
5
5
  "type": "module",
6
6
  "bin": {