@teeras/afterhours 0.1.1 → 0.2.0

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 (84) hide show
  1. package/README.md +101 -15
  2. package/dist/activity.d.ts +15 -1
  3. package/dist/activity.d.ts.map +1 -1
  4. package/dist/activity.js +76 -1
  5. package/dist/activity.js.map +1 -1
  6. package/dist/autosync.d.ts +22 -0
  7. package/dist/autosync.d.ts.map +1 -0
  8. package/dist/autosync.js +85 -0
  9. package/dist/autosync.js.map +1 -0
  10. package/dist/cli.js +112 -9
  11. package/dist/cli.js.map +1 -1
  12. package/dist/cloud.d.ts +5 -0
  13. package/dist/cloud.d.ts.map +1 -1
  14. package/dist/cloud.js +10 -2
  15. package/dist/cloud.js.map +1 -1
  16. package/dist/collect.d.ts +3 -1
  17. package/dist/collect.d.ts.map +1 -1
  18. package/dist/collect.js +8 -7
  19. package/dist/collect.js.map +1 -1
  20. package/dist/detect.d.ts.map +1 -1
  21. package/dist/detect.js +35 -6
  22. package/dist/detect.js.map +1 -1
  23. package/dist/hooks.d.ts +29 -0
  24. package/dist/hooks.d.ts.map +1 -0
  25. package/dist/hooks.js +196 -0
  26. package/dist/hooks.js.map +1 -0
  27. package/dist/index.d.ts +9 -2
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +8 -1
  30. package/dist/index.js.map +1 -1
  31. package/dist/install.d.ts +25 -0
  32. package/dist/install.d.ts.map +1 -0
  33. package/dist/install.js +155 -0
  34. package/dist/install.js.map +1 -0
  35. package/dist/moments.d.ts +21 -0
  36. package/dist/moments.d.ts.map +1 -0
  37. package/dist/moments.js +52 -0
  38. package/dist/moments.js.map +1 -0
  39. package/dist/off.d.ts +24 -0
  40. package/dist/off.d.ts.map +1 -0
  41. package/dist/off.js +36 -0
  42. package/dist/off.js.map +1 -0
  43. package/dist/privacy.d.ts +8 -0
  44. package/dist/privacy.d.ts.map +1 -1
  45. package/dist/privacy.js +26 -1
  46. package/dist/privacy.js.map +1 -1
  47. package/dist/qr.d.ts +29 -0
  48. package/dist/qr.d.ts.map +1 -0
  49. package/dist/qr.js +92 -0
  50. package/dist/qr.js.map +1 -0
  51. package/dist/render.d.ts.map +1 -1
  52. package/dist/render.js +38 -1
  53. package/dist/render.js.map +1 -1
  54. package/dist/report.d.ts.map +1 -1
  55. package/dist/report.js +82 -1
  56. package/dist/report.js.map +1 -1
  57. package/dist/runtime.d.ts +18 -0
  58. package/dist/runtime.d.ts.map +1 -0
  59. package/dist/runtime.js +70 -0
  60. package/dist/runtime.js.map +1 -0
  61. package/dist/secret.d.ts +9 -0
  62. package/dist/secret.d.ts.map +1 -0
  63. package/dist/secret.js +32 -0
  64. package/dist/secret.js.map +1 -0
  65. package/dist/setup.d.ts +18 -0
  66. package/dist/setup.d.ts.map +1 -0
  67. package/dist/setup.js +155 -0
  68. package/dist/setup.js.map +1 -0
  69. package/dist/sources/claude.d.ts.map +1 -1
  70. package/dist/sources/claude.js +141 -18
  71. package/dist/sources/claude.js.map +1 -1
  72. package/dist/sources/codex.d.ts.map +1 -1
  73. package/dist/sources/codex.js +209 -18
  74. package/dist/sources/codex.js.map +1 -1
  75. package/dist/sources/cursor.d.ts.map +1 -1
  76. package/dist/sources/cursor.js +1 -0
  77. package/dist/sources/cursor.js.map +1 -1
  78. package/dist/sources/gemini.d.ts.map +1 -1
  79. package/dist/sources/gemini.js +73 -8
  80. package/dist/sources/gemini.js.map +1 -1
  81. package/dist/types.d.ts +61 -6
  82. package/dist/types.d.ts.map +1 -1
  83. package/llms-install.md +29 -0
  84. package/package.json +3 -2
@@ -0,0 +1,155 @@
1
+ import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { isAbsolute, join } from "node:path";
4
+ import { isDirectory } from "./files.js";
5
+ import { CODEX_HOOKS_DESCRIPTION, claudeHookSettings, codexHookSettings } from "./hooks.js";
6
+ // Same override rule as detect.ts: env roots apply only for the real home.
7
+ function agentRoot(home, key, fallback) {
8
+ const configured = process.env[key]?.trim();
9
+ return home === homedir() && configured && isAbsolute(configured) ? configured : fallback;
10
+ }
11
+ /**
12
+ * A file that exists but fails to parse, or whose top level isn't an object
13
+ * (e.g. a JSON array), is `unreadable` — never treated as empty. Merging on
14
+ * top of `{}` would silently overwrite whatever the user actually had there
15
+ * (their `permissions.deny`, other hooks, env, MCP config) with no warning.
16
+ */
17
+ function readSettings(path) {
18
+ if (!existsSync(path))
19
+ return { kind: "absent" };
20
+ let raw;
21
+ try {
22
+ raw = readFileSync(path, "utf8");
23
+ }
24
+ catch {
25
+ return { kind: "unreadable" };
26
+ }
27
+ let parsed;
28
+ try {
29
+ parsed = JSON.parse(raw);
30
+ }
31
+ catch {
32
+ return { kind: "unreadable" };
33
+ }
34
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
35
+ return { kind: "object", value: parsed };
36
+ }
37
+ return { kind: "unreadable" };
38
+ }
39
+ /**
40
+ * Ours in either form: the PATH-based `trs hook` a hand-merged user pasted, or
41
+ * the absolute durable command setup installs. Recognizing both keeps a second
42
+ * run from appending a duplicate hook to a working configuration.
43
+ */
44
+ function isTeerasHookCommand(command) {
45
+ if (typeof command !== "string")
46
+ return false;
47
+ const normalized = command.replaceAll("\\", "/");
48
+ return normalized.includes("trs hook") || normalized.includes(".teeras/afterhours/bin/cli.js");
49
+ }
50
+ function hasTeerasHook(entries) {
51
+ if (!Array.isArray(entries))
52
+ return false;
53
+ return entries.some((entry) => {
54
+ const hooks = entry?.hooks;
55
+ return Array.isArray(hooks) && hooks.some((hook) => isTeerasHookCommand(hook?.command));
56
+ });
57
+ }
58
+ function mergeHooks(path, fragment, agent, detected) {
59
+ if (!detected)
60
+ return { agent, detected, path, action: "skipped" };
61
+ const read = readSettings(path);
62
+ if (read.kind === "unreadable")
63
+ return { agent, detected, path, action: "unreadable" };
64
+ const settings = read.kind === "object" ? read.value : {};
65
+ const existingHooks = typeof settings.hooks === "object" && settings.hooks !== null && !Array.isArray(settings.hooks)
66
+ ? settings.hooks
67
+ : {};
68
+ let changed = false;
69
+ for (const [event, entries] of Object.entries(fragment.hooks)) {
70
+ if (hasTeerasHook(existingHooks[event]))
71
+ continue;
72
+ const current = Array.isArray(existingHooks[event]) ? existingHooks[event] : [];
73
+ existingHooks[event] = [...current, ...entries];
74
+ changed = true;
75
+ }
76
+ if (!changed)
77
+ return { agent, detected, path, action: "already-installed" };
78
+ const next = { ...settings, ...(agent === "codex" ? { description: fragment.description } : {}), hooks: existingHooks };
79
+ writeFileSync(path, `${JSON.stringify(next, null, 2)}\n`);
80
+ return { agent, detected, path, action: "installed" };
81
+ }
82
+ export function installClaudeHooks(home = homedir(), command) {
83
+ const root = agentRoot(home, "CLAUDE_CONFIG_DIR", join(home, ".claude"));
84
+ return mergeHooks(join(root, "settings.json"), claudeHookSettings(command), "claude-code", isDirectory(root));
85
+ }
86
+ export function installCodexHooks(home = homedir(), command) {
87
+ const root = agentRoot(home, "CODEX_HOME", join(home, ".codex"));
88
+ return mergeHooks(join(root, "hooks.json"), codexHookSettings(command), "codex", isDirectory(root));
89
+ }
90
+ export function installHooks(home = homedir(), commands = {}) {
91
+ return [installClaudeHooks(home, commands.claude), installCodexHooks(home, commands.codex)];
92
+ }
93
+ /**
94
+ * `trs off`'s uninstall. Removes only entries whose command is ours (either
95
+ * form `isTeerasHookCommand` recognizes), event by event, and never rewrites
96
+ * a settings file it cannot parse — the same refusal `mergeHooks` honors on
97
+ * install applies symmetrically here.
98
+ */
99
+ function removeTeerasHooks(path, agent) {
100
+ const read = readSettings(path);
101
+ if (read.kind === "absent")
102
+ return { agent, path, action: "not-installed" };
103
+ if (read.kind === "unreadable")
104
+ return { agent, path, action: "unreadable" };
105
+ const settings = read.value;
106
+ const hooks = settings.hooks;
107
+ if (typeof hooks !== "object" || hooks === null || Array.isArray(hooks)) {
108
+ return { agent, path, action: "not-installed" };
109
+ }
110
+ let changed = false;
111
+ const nextHooks = {};
112
+ for (const [event, entries] of Object.entries(hooks)) {
113
+ if (!Array.isArray(entries)) {
114
+ nextHooks[event] = entries;
115
+ continue;
116
+ }
117
+ const kept = entries.filter((entry) => {
118
+ const entryHooks = entry?.hooks;
119
+ const isOurs = Array.isArray(entryHooks) && entryHooks.some((hook) => isTeerasHookCommand(hook?.command));
120
+ if (isOurs)
121
+ changed = true;
122
+ return !isOurs;
123
+ });
124
+ if (kept.length > 0)
125
+ nextHooks[event] = kept;
126
+ }
127
+ if (!changed)
128
+ return { agent, path, action: "not-installed" };
129
+ // Removal has to be able to reach zero. A file left holding `"hooks": {}`
130
+ // and our own `"description": "Teeras…"` still announces Teeras to anyone
131
+ // who opens it, right after `trs off` said everything was removed — so the
132
+ // empty husk goes too, and a file that was only ever ours is deleted rather
133
+ // than rewritten as `{}`. Anything the user put there is untouched: the
134
+ // description is dropped only when it is verbatim the one we write.
135
+ const { hooks: _removed, ...rest } = settings;
136
+ const next = Object.keys(nextHooks).length > 0 ? { ...rest, hooks: nextHooks } : rest;
137
+ if (Object.keys(nextHooks).length === 0 && next.description === CODEX_HOOKS_DESCRIPTION) {
138
+ delete next.description;
139
+ }
140
+ if (Object.keys(next).length === 0) {
141
+ rmSync(path, { force: true });
142
+ return { agent, path, action: "removed" };
143
+ }
144
+ writeFileSync(path, `${JSON.stringify(next, null, 2)}\n`);
145
+ return { agent, path, action: "removed" };
146
+ }
147
+ export function uninstallHooks(home = homedir()) {
148
+ const claudeRoot = agentRoot(home, "CLAUDE_CONFIG_DIR", join(home, ".claude"));
149
+ const codexRoot = agentRoot(home, "CODEX_HOME", join(home, ".codex"));
150
+ return [
151
+ removeTeerasHooks(join(claudeRoot, "settings.json"), "claude-code"),
152
+ removeTeerasHooks(join(codexRoot, "hooks.json"), "codex"),
153
+ ];
154
+ }
155
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { AiMoment, AiMomentArtifactKind, AiMomentVisibility } from "./types.js";
2
+ /** Hash bytes locally; the artifact itself is intentionally not part of a snapshot. */
3
+ export declare function artifactFingerprint(bytes: Uint8Array): string;
4
+ export declare function createAiMoment(input: {
5
+ capturedAt?: Date | string;
6
+ sourceId: string;
7
+ episodeId?: string | null;
8
+ intent: string;
9
+ artifactKind: AiMomentArtifactKind;
10
+ artifactHash: string;
11
+ artifactBytes?: number | null;
12
+ artifactLabel?: string | null;
13
+ satisfaction?: number | null;
14
+ reflection?: string | null;
15
+ outcome?: AiMoment["outcome"];
16
+ visibility?: AiMomentVisibility;
17
+ }): AiMoment;
18
+ export declare function momentsPath(home?: string): string;
19
+ export declare function readAiMoments(home?: string): AiMoment[];
20
+ export declare function appendAiMoment(moment: AiMoment, home?: string): void;
21
+ //# sourceMappingURL=moments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moments.d.ts","sourceRoot":"","sources":["../src/moments.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErF,uFAAuF;AACvF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAE7D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,oBAAoB,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC9B,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACjC,GAAG,QAAQ,CAqBX;AAED,wBAAgB,WAAW,CAAC,IAAI,SAAY,GAAG,MAAM,CAAqD;AAE1G,wBAAgB,aAAa,CAAC,IAAI,SAAY,GAAG,QAAQ,EAAE,CAK1D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,SAAY,GAAG,IAAI,CAOvE"}
@@ -0,0 +1,52 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { chmodSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { homedir } from "node:os";
5
+ /** Hash bytes locally; the artifact itself is intentionally not part of a snapshot. */
6
+ export function artifactFingerprint(bytes) {
7
+ return createHash("sha256").update(bytes).digest("hex");
8
+ }
9
+ export function createAiMoment(input) {
10
+ if (!/^[a-f0-9]{64}$/i.test(input.artifactHash))
11
+ throw new Error("artifactHash must be a SHA-256 hex digest");
12
+ const intent = input.intent.trim();
13
+ if (!intent || intent.length > 500)
14
+ throw new Error("intent must be 1–500 characters");
15
+ const capturedAt = new Date(input.capturedAt ?? Date.now());
16
+ if (!Number.isFinite(capturedAt.getTime()))
17
+ throw new Error("capturedAt must be a valid date");
18
+ return {
19
+ id: randomUUID(),
20
+ capturedAt: capturedAt.toISOString(),
21
+ sourceId: input.sourceId,
22
+ episodeId: input.episodeId ?? null,
23
+ intent,
24
+ artifactKind: input.artifactKind,
25
+ artifactHash: input.artifactHash.toLowerCase(),
26
+ artifactBytes: input.artifactBytes ?? null,
27
+ artifactLabel: input.artifactLabel?.trim() || null,
28
+ satisfaction: input.satisfaction ?? null,
29
+ reflection: input.reflection?.trim() || null,
30
+ outcome: input.outcome ?? "kept",
31
+ visibility: input.visibility ?? "private",
32
+ };
33
+ }
34
+ export function momentsPath(home = homedir()) { return join(home, ".teeras", "ai-moments.json"); }
35
+ export function readAiMoments(home = homedir()) {
36
+ try {
37
+ const parsed = JSON.parse(readFileSync(momentsPath(home), "utf8"));
38
+ return Array.isArray(parsed) ? parsed.filter((item) => !!item && typeof item === "object") : [];
39
+ }
40
+ catch {
41
+ return [];
42
+ }
43
+ }
44
+ export function appendAiMoment(moment, home = homedir()) {
45
+ const path = momentsPath(home);
46
+ const existing = readAiMoments(home).filter((item) => item.id !== moment.id);
47
+ const directory = path.slice(0, path.lastIndexOf("/"));
48
+ mkdirSync(directory, { recursive: true, mode: 0o700 });
49
+ writeFileSync(path, JSON.stringify([...existing, moment], null, 2), { mode: 0o600 });
50
+ chmodSync(path, 0o600);
51
+ }
52
+ //# sourceMappingURL=moments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moments.js","sourceRoot":"","sources":["../src/moments.ts"],"names":[],"mappings":"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"}
package/dist/off.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ import { type HookRemoveResult } from "./install.js";
2
+ /**
3
+ * What happened to the durable runtime copy in `~/.teeras/afterhours/bin`.
4
+ *
5
+ * `kept` is the safety case, and the reason this lives in its own module
6
+ * instead of inline in the CLI. A settings file we could not read still
7
+ * contains its Teeras hook entry — that entry names the runtime by absolute
8
+ * path. Deleting the runtime anyway would leave every later agent lifecycle
9
+ * event invoking a file that is gone, which is exactly the "a hook must never
10
+ * interrupt the agent" rule broken by the off switch itself. So an unreadable
11
+ * settings file means the runtime stays, and the person is told why.
12
+ */
13
+ export type RuntimeOutcome = "removed" | "nothing-to-remove" | "kept";
14
+ export interface OffResult {
15
+ hooks: HookRemoveResult[];
16
+ runtime: RuntimeOutcome;
17
+ lines: string[];
18
+ }
19
+ export interface OffDeps {
20
+ uninstall?: (home: string) => HookRemoveResult[];
21
+ removeRuntime?: (home: string) => boolean;
22
+ }
23
+ export declare function runOff(home?: string, deps?: OffDeps): OffResult;
24
+ //# sourceMappingURL=off.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"off.d.ts","sourceRoot":"","sources":["../src/off.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGrE;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,mBAAmB,GAAG,MAAM,CAAC;AAEtE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,OAAO,EAAE,cAAc,CAAC;IACxB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,OAAO;IACtB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,gBAAgB,EAAE,CAAC;IACjD,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CAC3C;AAMD,wBAAgB,MAAM,CAAC,IAAI,GAAE,MAAkB,EAAE,IAAI,GAAE,OAAY,GAAG,SAAS,CAyC9E"}
package/dist/off.js ADDED
@@ -0,0 +1,36 @@
1
+ import { homedir } from "node:os";
2
+ import { uninstallHooks } from "./install.js";
3
+ import { removeRuntime } from "./runtime.js";
4
+ function label(agent) {
5
+ return agent === "claude-code" ? "Claude Code" : "Codex";
6
+ }
7
+ export function runOff(home = homedir(), deps = {}) {
8
+ const uninstall = deps.uninstall ?? uninstallHooks;
9
+ const remove = deps.removeRuntime ?? removeRuntime;
10
+ const hooks = uninstall(home);
11
+ const removedAgents = hooks.filter((result) => result.action === "removed").map((result) => label(result.agent));
12
+ const unreadableAgents = hooks.filter((result) => result.action === "unreadable").map((result) => label(result.agent));
13
+ const runtime = unreadableAgents.length > 0
14
+ ? "kept"
15
+ : remove(home)
16
+ ? "removed"
17
+ : "nothing-to-remove";
18
+ const runtimeLine = runtime === "removed"
19
+ ? "removed · ~/.teeras/afterhours/bin"
20
+ : runtime === "kept"
21
+ ? "kept · a hook still points at it"
22
+ : "nothing to remove";
23
+ const lines = [
24
+ "",
25
+ " teeras · off",
26
+ "",
27
+ ` hooks ${removedAgents.length > 0 ? `removed · ${removedAgents.join(", ")}` : "nothing to remove"}`,
28
+ ` runtime ${runtimeLine}`,
29
+ ];
30
+ if (unreadableAgents.length > 0) {
31
+ lines.push(` left untouched ${unreadableAgents.join(", ")} settings file could not be read`, " that file still calls the Teeras hook, so the runtime it calls was left in place.", " repair the settings file (or delete its Teeras hook entry by hand), then run `trs off` again.");
32
+ }
33
+ lines.push("", " still on this computer: your local journal and account credentials.", " run `trs logout` too if you want the account disconnected as well.", "");
34
+ return { hooks, runtime, lines };
35
+ }
36
+ //# sourceMappingURL=off.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"off.js","sourceRoot":"","sources":["../src/off.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,cAAc,EAAyB,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AA0B7C,SAAS,KAAK,CAAC,KAAgC;IAC7C,OAAO,KAAK,KAAK,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,OAAe,OAAO,EAAE,EAAE,OAAgB,EAAE;IACjE,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,cAAc,CAAC;IACnD,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC;IAEnD,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACjH,MAAM,gBAAgB,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAEvH,MAAM,OAAO,GAAmB,gBAAgB,CAAC,MAAM,GAAG,CAAC;QACzD,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;YACZ,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,mBAAmB,CAAC;IAE1B,MAAM,WAAW,GAAG,OAAO,KAAK,SAAS;QACvC,CAAC,CAAC,oCAAoC;QACtC,CAAC,CAAC,OAAO,KAAK,MAAM;YAClB,CAAC,CAAC,kCAAkC;YACpC,CAAC,CAAC,mBAAmB,CAAC;IAE1B,MAAM,KAAK,GAAG;QACZ,EAAE;QACF,gBAAgB;QAChB,EAAE;QACF,cAAc,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,mBAAmB,EAAE;QACxG,cAAc,WAAW,EAAE;KAC5B,CAAC;IACF,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CACR,qBAAqB,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,kCAAkC,EAClF,qFAAqF,EACrF,iGAAiG,CAClG,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,IAAI,CACR,EAAE,EACF,uEAAuE,EACvE,sEAAsE,EACtE,EAAE,CACH,CAAC;IACF,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AACnC,CAAC"}
package/dist/privacy.d.ts CHANGED
@@ -1,3 +1,11 @@
1
1
  import type { DataBoundary } from "./types.js";
2
+ /**
3
+ * Replace a leading home-directory prefix with `~`. Setup's `--json` output
4
+ * and error messages are read by a coding agent and often relayed verbatim
5
+ * into an LLM transcript sent to a third party — absolute paths there leak
6
+ * the operator's real username. Returns the path unchanged if it is not
7
+ * under `home` (no partial-segment matches, e.g. `/Users/alice2`).
8
+ */
9
+ export declare function tildePath(path: string, home?: string): string;
2
10
  export declare const DATA_BOUNDARY: DataBoundary;
3
11
  //# sourceMappingURL=privacy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"privacy.d.ts","sourceRoot":"","sources":["../src/privacy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,eAAO,MAAM,aAAa,EAAE,YAY3B,CAAC"}
1
+ {"version":3,"file":"privacy.d.ts","sourceRoot":"","sources":["../src/privacy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAkB,GAAG,MAAM,CAIxE;AAED,eAAO,MAAM,aAAa,EAAE,YAsB3B,CAAC"}
package/dist/privacy.js CHANGED
@@ -1,7 +1,32 @@
1
+ import { homedir } from "node:os";
2
+ import { sep } from "node:path";
3
+ /**
4
+ * Replace a leading home-directory prefix with `~`. Setup's `--json` output
5
+ * and error messages are read by a coding agent and often relayed verbatim
6
+ * into an LLM transcript sent to a third party — absolute paths there leak
7
+ * the operator's real username. Returns the path unchanged if it is not
8
+ * under `home` (no partial-segment matches, e.g. `/Users/alice2`).
9
+ */
10
+ export function tildePath(path, home = homedir()) {
11
+ if (path === home)
12
+ return "~";
13
+ const prefix = home.endsWith(sep) ? home : `${home}${sep}`;
14
+ return path.startsWith(prefix) ? `~${sep}${path.slice(prefix.length)}` : path;
15
+ }
1
16
  export const DATA_BOUNDARY = {
2
17
  mode: "local-first",
3
18
  sync: "off-until-user-connects",
4
- retained: ["hourly timestamps", "local date and hour", "event kinds", "session counts", "token counters"],
19
+ retained: [
20
+ "hourly timestamps",
21
+ "local date and hour",
22
+ "event kinds",
23
+ "session counts",
24
+ "token counters",
25
+ "content-free delegation episodes",
26
+ "measurement provenance and missingness",
27
+ "agent and model family",
28
+ "approval and lifecycle signals",
29
+ ],
5
30
  neverRetained: [
6
31
  "prompt text",
7
32
  "source code",
@@ -1 +1 @@
1
- {"version":3,"file":"privacy.js","sourceRoot":"","sources":["../src/privacy.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,yBAAyB;IAC/B,QAAQ,EAAE,CAAC,mBAAmB,EAAE,qBAAqB,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,CAAC;IACzG,aAAa,EAAE;QACb,aAAa;QACb,aAAa;QACb,cAAc;QACd,kBAAkB;QAClB,qBAAqB;QACrB,YAAY;KACb;CACF,CAAC"}
1
+ {"version":3,"file":"privacy.js","sourceRoot":"","sources":["../src/privacy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAGhC;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,OAAe,OAAO,EAAE;IAC9D,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,GAAG,CAAC;IAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,GAAG,EAAE,CAAC;IAC3D,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAChF,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,yBAAyB;IAC/B,QAAQ,EAAE;QACR,mBAAmB;QACnB,qBAAqB;QACrB,aAAa;QACb,gBAAgB;QAChB,gBAAgB;QAChB,kCAAkC;QAClC,wCAAwC;QACxC,wBAAwB;QACxB,gCAAgC;KACjC;IACD,aAAa,EAAE;QACb,aAAa;QACb,aAAa;QACb,cAAc;QACd,kBAAkB;QAClB,qBAAqB;QACrB,YAAY;KACb;CACF,CAAC"}
package/dist/qr.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * A scannable QR pointing at the one-tap dashboard link. The URL is fixed, so
3
+ * the module matrix is generated once (offline, from the URL below) and
4
+ * embedded here rather than computed at runtime — this package carries zero
5
+ * dependencies, and a general-purpose QR encoder is not worth adding for one
6
+ * constant link.
7
+ *
8
+ * Version 2, error-correction level M, 25x25 modules. Verified against a real
9
+ * QR reader (zbarimg) two ways before landing: the raw matrix as an image,
10
+ * and — the exact thing this module produces — the half-block ASCII render
11
+ * rasterized back to pixels and re-decoded. See tests/qr.test.ts, which pins
12
+ * the verified render byte-for-byte.
13
+ */
14
+ export declare const TEERAS_APP_URL = "https://teeras.com/app";
15
+ /**
16
+ * Renders the fixed teeras.com/app QR as half-block terminal lines (▀ ▄ █),
17
+ * packing two module rows into one character row so modules read as roughly
18
+ * square in a typical monospace terminal. Includes the required quiet zone;
19
+ * deliberately makes no assumption about the terminal's light/dark theme —
20
+ * the render decodes under either color polarity.
21
+ */
22
+ export declare function renderQrLines(): string[];
23
+ /**
24
+ * The QR block for terminal output, captioned honestly, or just the bare
25
+ * URL when the output can't show block characters usefully (piped,
26
+ * redirected, or no TTY) — a QR that can't be scanned is worse than a link.
27
+ */
28
+ export declare function qrBlock(isTty: boolean): string[];
29
+ //# sourceMappingURL=qr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qr.d.ts","sourceRoot":"","sources":["../src/qr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,2BAA2B,CAAC;AA2CvD;;;;;;GAMG;AACH,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAexC;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAQhD"}
package/dist/qr.js ADDED
@@ -0,0 +1,92 @@
1
+ /**
2
+ * A scannable QR pointing at the one-tap dashboard link. The URL is fixed, so
3
+ * the module matrix is generated once (offline, from the URL below) and
4
+ * embedded here rather than computed at runtime — this package carries zero
5
+ * dependencies, and a general-purpose QR encoder is not worth adding for one
6
+ * constant link.
7
+ *
8
+ * Version 2, error-correction level M, 25x25 modules. Verified against a real
9
+ * QR reader (zbarimg) two ways before landing: the raw matrix as an image,
10
+ * and — the exact thing this module produces — the half-block ASCII render
11
+ * rasterized back to pixels and re-decoded. See tests/qr.test.ts, which pins
12
+ * the verified render byte-for-byte.
13
+ */
14
+ export const TEERAS_APP_URL = "https://teeras.com/app";
15
+ // One string per module row: "1" is a dark module, "0" is light.
16
+ const QR_MODULES = [
17
+ "1111111011011011101111111",
18
+ "1000001001001100101000001",
19
+ "1011101000111010001011101",
20
+ "1011101010001100101011101",
21
+ "1011101010011011101011101",
22
+ "1000001011011000101000001",
23
+ "1111111010101010101111111",
24
+ "0000000010100010100000000",
25
+ "1000101110100000011111001",
26
+ "0001100100010111100011010",
27
+ "1011011001110001100001100",
28
+ "0110110001111010000100110",
29
+ "1111011100001001011001111",
30
+ "1010010111100101000010010",
31
+ "0001001100100001000111100",
32
+ "0001110011001000100110110",
33
+ "1100001011010000111111100",
34
+ "0000000011001101100010000",
35
+ "1111111010111000101010000",
36
+ "1000001000010000100011111",
37
+ "1011101011001110111111111",
38
+ "1011101000000111011100111",
39
+ "1011101001100001101001010",
40
+ "1000001001101001010111110",
41
+ "1111111011111111000000111",
42
+ ];
43
+ const QUIET_SIDE = 4;
44
+ const QUIET_TOP = 4;
45
+ // One module more than the minimum on the bottom pads the row count to even,
46
+ // so each output row can pair two module rows into one half-block character.
47
+ const QUIET_BOTTOM = 5;
48
+ function isDark(row, col) {
49
+ if (row < 0 || row >= QR_MODULES.length)
50
+ return false;
51
+ const line = QR_MODULES[row];
52
+ return col >= 0 && col < line.length && line[col] === "1";
53
+ }
54
+ /**
55
+ * Renders the fixed teeras.com/app QR as half-block terminal lines (▀ ▄ █),
56
+ * packing two module rows into one character row so modules read as roughly
57
+ * square in a typical monospace terminal. Includes the required quiet zone;
58
+ * deliberately makes no assumption about the terminal's light/dark theme —
59
+ * the render decodes under either color polarity.
60
+ */
61
+ export function renderQrLines() {
62
+ const width = QR_MODULES.length + QUIET_SIDE * 2;
63
+ const totalRows = QR_MODULES.length + QUIET_TOP + QUIET_BOTTOM;
64
+ const lines = [];
65
+ for (let y = 0; y < totalRows; y += 2) {
66
+ let line = "";
67
+ for (let x = 0; x < width; x++) {
68
+ const col = x - QUIET_SIDE;
69
+ const top = isDark(y - QUIET_TOP, col);
70
+ const bottom = isDark(y + 1 - QUIET_TOP, col);
71
+ line += top && bottom ? "█" : top ? "▀" : bottom ? "▄" : " ";
72
+ }
73
+ lines.push(line);
74
+ }
75
+ return lines;
76
+ }
77
+ /**
78
+ * The QR block for terminal output, captioned honestly, or just the bare
79
+ * URL when the output can't show block characters usefully (piped,
80
+ * redirected, or no TTY) — a QR that can't be scanned is worse than a link.
81
+ */
82
+ export function qrBlock(isTty) {
83
+ if (!isTty)
84
+ return [` ${TEERAS_APP_URL}`];
85
+ return [
86
+ ...renderQrLines().map((line) => ` ${line}`),
87
+ "",
88
+ ` ${TEERAS_APP_URL}`,
89
+ " your week on your phone · iOS app coming soon",
90
+ ];
91
+ }
92
+ //# sourceMappingURL=qr.js.map
package/dist/qr.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qr.js","sourceRoot":"","sources":["../src/qr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,wBAAwB,CAAC;AAEvD,iEAAiE;AACjE,MAAM,UAAU,GAAsB;IACpC,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;IAC3B,2BAA2B;CAC5B,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,CAAC;AACrB,MAAM,SAAS,GAAG,CAAC,CAAC;AACpB,6EAA6E;AAC7E,6EAA6E;AAC7E,MAAM,YAAY,GAAG,CAAC,CAAC;AAEvB,SAAS,MAAM,CAAC,GAAW,EAAE,GAAW;IACtC,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,IAAI,UAAU,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAE,CAAC;IAC9B,OAAO,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC;AAC5D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,GAAG,UAAU,GAAG,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC;IAC/D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC;YAC3B,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,GAAG,SAAS,EAAE,GAAG,CAAC,CAAC;YACvC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,EAAE,GAAG,CAAC,CAAC;YAC9C,IAAI,IAAI,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAC/D,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,KAAK,cAAc,EAAE,CAAC,CAAC;IAC3C,OAAO;QACL,GAAG,aAAa,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7C,EAAE;QACF,KAAK,cAAc,EAAE;QACrB,iDAAiD;KAClD,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAMvE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,kBAAkB,EAAE,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAiB3F"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA0CvE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,kBAAkB,EAAE,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAoB3F"}
package/dist/render.js CHANGED
@@ -1,15 +1,52 @@
1
1
  function hours(minutes) {
2
2
  return `${(minutes / 60).toFixed(1)}h`;
3
3
  }
4
+ function minutesLabel(minutes) {
5
+ return minutes >= 90 ? hours(minutes) : `${minutes}m`;
6
+ }
7
+ /** One fresh, honest line per day. Never guilt; good news is allowed to be good. */
8
+ function todayLines(report) {
9
+ const today = report.today;
10
+ const baseline = report.baselineLifeReturnedMinutes;
11
+ if (today.agentActiveMinutes === 0 && today.humanAttentionMinutes === 0) {
12
+ return [" today quiet so far — nothing has needed you."];
13
+ }
14
+ const returned = `+${hours(today.lifeReturnedMinutes)} time back (est.)`;
15
+ const compared = baseline == null
16
+ ? `${returned} · first measured day`
17
+ : `${returned} · typical day +${hours(baseline)}`;
18
+ const lines = [` today ${compared}`];
19
+ if (today.longestRunMinutes > 0 && today.longestRunSource) {
20
+ lines.push(` longest solo run ${minutesLabel(today.longestRunMinutes)} · ${today.longestRunSource}`);
21
+ }
22
+ return lines;
23
+ }
24
+ /**
25
+ * The other half of the returned-time fact. Agent work that overlaps compresses
26
+ * into fewer hours of the person's week rather than returning more of it, so
27
+ * the ratio is stated plainly instead of being folded into the time back.
28
+ * Silent below 1.1x — "1.0 agents at once" is noise, not news.
29
+ */
30
+ function parallelLine(report) {
31
+ const ratio = report.parallelRatio;
32
+ if (ratio == null || ratio < 1.1)
33
+ return [];
34
+ return [
35
+ ` agents at once ${ratio.toFixed(1)}× · that work filled ${hours(report.agentWallClockMinutes)} of your week`,
36
+ ];
37
+ }
4
38
  export function renderReport(snapshot, report) {
5
39
  const active = snapshot.sources.filter((source) => source.configured).map((source) => source.name);
6
40
  return [
7
41
  "",
8
42
  " teeras · afterhours",
9
43
  "",
10
- ` life returned +${hours(report.lifeReturnedMinutes)}`,
44
+ ...todayLines(report),
45
+ "",
46
+ ` time back · estimate +${hours(report.lifeReturnedMinutes)} this week`,
11
47
  ` human attention ${hours(report.humanAttentionMinutes)} estimated`,
12
48
  ` agent active time ${hours(report.agentActiveMinutes)} observed`,
49
+ ...parallelLine(report),
13
50
  ` nights protected ${report.protectedNights}/${report.observedNights}`,
14
51
  "",
15
52
  ` ${report.nextMove}`,
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAEA,SAAS,KAAK,CAAC,OAAe;IAC5B,OAAO,GAAG,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAA4B,EAAE,MAAwB;IACjF,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACnG,OAAO;QACL,EAAE;QACF,uBAAuB;QACvB,EAAE;QACF,0BAA0B,KAAK,CAAC,MAAM,CAAC,mBAAmB,CAAC,EAAE;QAC7D,yBAAyB,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,YAAY;QACxE,yBAAyB,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,WAAW;QACpE,yBAAyB,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,cAAc,EAAE;QAC1E,EAAE;QACF,KAAK,MAAM,CAAC,QAAQ,EAAE;QACtB,EAAE;QACF,sBAAsB,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,+BAA+B,EAAE;QAC/F,sEAAsE;QACtE,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAEA,SAAS,KAAK,CAAC,OAAe;IAC5B,OAAO,GAAG,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AACzC,CAAC;AAED,SAAS,YAAY,CAAC,OAAe;IACnC,OAAO,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC;AACxD,CAAC;AAED,oFAAoF;AACpF,SAAS,UAAU,CAAC,MAAwB;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC,2BAA2B,CAAC;IACpD,IAAI,KAAK,CAAC,kBAAkB,KAAK,CAAC,IAAI,KAAK,CAAC,qBAAqB,KAAK,CAAC,EAAE,CAAC;QACxE,OAAO,CAAC,8DAA8D,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,mBAAmB,CAAC,mBAAmB,CAAC;IACzE,MAAM,QAAQ,GAAG,QAAQ,IAAI,IAAI;QAC/B,CAAC,CAAC,GAAG,QAAQ,uBAAuB;QACpC,CAAC,CAAC,GAAG,QAAQ,mBAAmB,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;IACpD,MAAM,KAAK,GAAG,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAC;IACpD,IAAI,KAAK,CAAC,iBAAiB,GAAG,CAAC,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;QAC1D,KAAK,CAAC,IAAI,CAAC,yBAAyB,YAAY,CAAC,KAAK,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAC3G,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,MAAwB;IAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,aAAa,CAAC;IACnC,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,GAAG,GAAG;QAAE,OAAO,EAAE,CAAC;IAC5C,OAAO;QACL,yBAAyB,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,eAAe;KACpH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAA4B,EAAE,MAAwB;IACjF,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACnG,OAAO;QACL,EAAE;QACF,uBAAuB;QACvB,EAAE;QACF,GAAG,UAAU,CAAC,MAAM,CAAC;QACrB,EAAE;QACF,2BAA2B,KAAK,CAAC,MAAM,CAAC,mBAAmB,CAAC,YAAY;QACxE,yBAAyB,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,YAAY;QACxE,yBAAyB,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,WAAW;QACpE,GAAG,YAAY,CAAC,MAAM,CAAC;QACvB,yBAAyB,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,cAAc,EAAE;QAC1E,EAAE;QACF,KAAK,MAAM,CAAC,QAAQ,EAAE;QACtB,EAAE;QACF,sBAAsB,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,+BAA+B,EAAE;QAC/F,sEAAsE;QACtE,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AASvF,wBAAgB,UAAU,CAAC,QAAQ,EAAE,kBAAkB,EAAE,QAAQ,SAAK,GAAG,gBAAgB,CA+BxF"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAkB,gBAAgB,EAAE,kBAAkB,EAAmB,MAAM,YAAY,CAAC;AA0FxG,wBAAgB,UAAU,CAAC,QAAQ,EAAE,kBAAkB,EAAE,QAAQ,SAAK,GAAG,gBAAgB,CAuCxF"}