@agimon-ai/po-ui 0.0.0-alpha.2 → 0.0.0-alpha.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/dist/config.mjs CHANGED
@@ -1,2 +1 @@
1
- import { CONFIG_ACTION, ConfigActionSchema, ConfigChoiceSchema, ConfigFieldKindSchema, ConfigFieldSchema, ConfigProgressSchema, ConfigSectionSchema, ConfigSourceSchema, ConfigStatusSchema, ConfigStepSchema } from "@agimon-ai/po-core/config";
2
- export { CONFIG_ACTION, ConfigActionSchema, ConfigChoiceSchema, ConfigFieldKindSchema, ConfigFieldSchema, ConfigProgressSchema, ConfigSectionSchema, ConfigSourceSchema, ConfigStatusSchema, ConfigStepSchema };
1
+ export { CONFIG_ACTION, ConfigActionSchema, ConfigChoiceSchema, ConfigFieldKindSchema, ConfigFieldSchema, ConfigProgressSchema, ConfigSectionSchema, ConfigSourceSchema, ConfigStatusSchema, ConfigStepSchema } from "@agimon-ai/po-core/config";
@@ -1,10 +1,10 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
3
- let node_fs = require("node:fs");
4
- node_fs = require_rolldown_runtime.__toESM(node_fs, 1);
5
3
  let node_path = require("node:path");
6
4
  node_path = require_rolldown_runtime.__toESM(node_path, 1);
7
- //#region src/services/extensionSource/index.ts
5
+ let node_fs = require("node:fs");
6
+ node_fs = require_rolldown_runtime.__toESM(node_fs, 1);
7
+ //#region src/services/extensionSource/packageName.ts
8
8
  /**
9
9
  * Display name for an extension that Pi could not attribute to a package.
10
10
  *
@@ -14,26 +14,47 @@ node_path = require_rolldown_runtime.__toESM(node_path, 1);
14
14
  * package that registered the tools.
15
15
  */
16
16
  /** Results are stable for the life of a session, and every source hits the same few dirs. */
17
- const cache = /* @__PURE__ */ new Map();
17
+ const nameCache = /* @__PURE__ */ new Map();
18
18
  const packageCache = /* @__PURE__ */ new Map();
19
+ const MANIFEST_FILE = "package.json";
20
+ /** The manifest's non-empty name; undefined for a malformed or nameless manifest. */
21
+ function manifestPackageName(text) {
22
+ try {
23
+ const manifest = JSON.parse(text);
24
+ return typeof manifest.name === "string" && manifest.name.length > 0 ? manifest.name : void 0;
25
+ } catch {
26
+ return;
27
+ }
28
+ }
29
+ /** The next directory to search, or undefined at the filesystem root. */
30
+ function parentDirectory(directory) {
31
+ const parent = node_path.default.dirname(directory);
32
+ return parent === directory ? void 0 : parent;
33
+ }
34
+ /** `@agimon-ai/po-task` reads as `po-task`; the scope is noise in a tree. */
35
+ function displayExtensionName(name, entryPath) {
36
+ return name ? name.split("/").pop() ?? name : node_path.default.basename(entryPath, node_path.default.extname(entryPath));
37
+ }
38
+ //#endregion
39
+ //#region src/services/extensionSource/sync.ts
19
40
  function packageName(directory) {
20
- let current = directory;
21
- for (;;) {
41
+ for (let current = directory; current !== void 0; current = parentDirectory(current)) {
42
+ let text;
22
43
  try {
23
- const manifest = JSON.parse(node_fs.default.readFileSync(node_path.default.join(current, "package.json"), "utf8"));
24
- if (typeof manifest.name === "string" && manifest.name.length > 0) return manifest.name;
25
- } catch {}
26
- const parent = node_path.default.dirname(current);
27
- if (parent === current) return void 0;
28
- current = parent;
44
+ text = node_fs.default.readFileSync(node_path.default.join(current, MANIFEST_FILE), "utf8");
45
+ } catch {
46
+ continue;
47
+ }
48
+ const name = manifestPackageName(text);
49
+ if (name) return name;
29
50
  }
30
51
  }
52
+ /** @deprecated Node-only sync shim; use readExtensionName. Removed in M2. */
31
53
  function extensionName(entryPath) {
32
- const cached = cache.get(entryPath);
54
+ const cached = nameCache.get(entryPath);
33
55
  if (cached !== void 0) return cached;
34
- const name = packageName(node_path.default.dirname(entryPath));
35
- const resolved = name ? name.split("/").pop() ?? name : node_path.default.basename(entryPath, node_path.default.extname(entryPath));
36
- cache.set(entryPath, resolved);
56
+ const resolved = displayExtensionName(packageName(node_path.default.dirname(entryPath)), entryPath);
57
+ nameCache.set(entryPath, resolved);
37
58
  return resolved;
38
59
  }
39
60
  /**
@@ -44,6 +65,8 @@ function extensionName(entryPath) {
44
65
  * `@agimon-ai/po-team`, so joining a registered tool back to the layer that
45
66
  * admitted it needs the unshortened name. Attribution and display are different
46
67
  * jobs, so they get different functions rather than one lossy one.
68
+ *
69
+ * @deprecated Node-only sync shim; use readExtensionPackageName. Removed in M2.
47
70
  */
48
71
  function extensionPackageName(entryPath) {
49
72
  const cached = packageCache.get(entryPath);
@@ -53,7 +76,34 @@ function extensionPackageName(entryPath) {
53
76
  return name;
54
77
  }
55
78
  //#endregion
79
+ //#region src/services/extensionSource/index.ts
80
+ async function readPackageName(fs, directory, context) {
81
+ for (let current = directory; current !== void 0; current = parentDirectory(current)) {
82
+ const text = await fs.readTextFile(node_path.default.join(current, MANIFEST_FILE), context);
83
+ const name = text.ok ? manifestPackageName(text.value) : void 0;
84
+ if (name) return name;
85
+ }
86
+ }
87
+ /** Display name of the package that owns an extension entry, read through `fs`. */
88
+ async function readExtensionName(fs, entryPath, context) {
89
+ const cached = nameCache.get(entryPath);
90
+ if (cached !== void 0) return cached;
91
+ const resolved = displayExtensionName(await readPackageName(fs, node_path.default.dirname(entryPath), context), entryPath);
92
+ nameCache.set(entryPath, resolved);
93
+ return resolved;
94
+ }
95
+ /** The owning package name with its scope, read through `fs`; see `extensionPackageName`. */
96
+ async function readExtensionPackageName(fs, entryPath, context) {
97
+ const cached = packageCache.get(entryPath);
98
+ if (cached !== void 0) return cached.name;
99
+ const name = await readPackageName(fs, node_path.default.dirname(entryPath), context);
100
+ packageCache.set(entryPath, { name });
101
+ return name;
102
+ }
103
+ //#endregion
56
104
  exports.extensionName = extensionName;
57
105
  exports.extensionPackageName = extensionPackageName;
106
+ exports.readExtensionName = readExtensionName;
107
+ exports.readExtensionPackageName = readExtensionPackageName;
58
108
 
59
109
  //# sourceMappingURL=extensionName.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"extensionName.cjs","names":["fs","path"],"sources":["../src/services/extensionSource/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\n/**\n * Display name for an extension that Pi could not attribute to a package.\n *\n * Pi stamps every `--extension <path>` argument with the literal source `cli`,\n * and po launches all of its extensions that way, so the only surviving\n * identity is the entry path. The nearest `package.json` above it names the\n * package that registered the tools.\n */\n\n/** Results are stable for the life of a session, and every source hits the same few dirs. */\nconst cache = new Map<string, string>();\n// Wrapped, because \"no package above this path\" is a real answer worth caching\n// and a bare undefined cannot be told apart from a miss.\nconst packageCache = new Map<string, { readonly name: string | undefined }>();\nfunction packageName(directory: string): string | undefined {\n let current = directory;\n for (;;) {\n try {\n const manifest = JSON.parse(fs.readFileSync(path.join(current, 'package.json'), 'utf8')) as { name?: unknown };\n if (typeof manifest.name === 'string' && manifest.name.length > 0) return manifest.name;\n } catch {\n // No manifest here, or an unreadable one; keep walking up.\n }\n const parent = path.dirname(current);\n if (parent === current) return undefined;\n current = parent;\n }\n}\n\nexport function extensionName(entryPath: string): string {\n const cached = cache.get(entryPath);\n if (cached !== undefined) return cached;\n const name = packageName(path.dirname(entryPath));\n // `@agimon-ai/po-task` reads as `doom-task`; the scope is noise in a tree.\n const resolved = name ? (name.split('/').pop() ?? name) : path.basename(entryPath, path.extname(entryPath));\n cache.set(entryPath, resolved);\n return resolved;\n}\n\n/**\n * The package name exactly as a manifest spells it, scope and all.\n *\n * `extensionName` drops the scope because a tree reads better without it, but\n * that makes it useless as a key: `.po/modes.yaml` names packages as\n * `@agimon-ai/po-team`, so joining a registered tool back to the layer that\n * admitted it needs the unshortened name. Attribution and display are different\n * jobs, so they get different functions rather than one lossy one.\n */\nexport function extensionPackageName(entryPath: string): string | undefined {\n const cached = packageCache.get(entryPath);\n if (cached !== undefined) return cached.name;\n const name = packageName(path.dirname(entryPath));\n packageCache.set(entryPath, { name });\n return name;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAaA,MAAM,wBAAQ,IAAI,IAAoB;AAGtC,MAAM,+BAAe,IAAI,IAAmD;AAC5E,SAAS,YAAY,WAAuC;CAC1D,IAAI,UAAU;CACd,SAAS;EACP,IAAI;GACF,MAAM,WAAW,KAAK,MAAMA,QAAAA,QAAG,aAAaC,UAAAA,QAAK,KAAK,SAAS,cAAc,GAAG,MAAM,CAAC;GACvF,IAAI,OAAO,SAAS,SAAS,YAAY,SAAS,KAAK,SAAS,GAAG,OAAO,SAAS;EACrF,QAAQ,CAER;EACA,MAAM,SAASA,UAAAA,QAAK,QAAQ,OAAO;EACnC,IAAI,WAAW,SAAS,OAAO,KAAA;EAC/B,UAAU;CACZ;AACF;AAEA,SAAgB,cAAc,WAA2B;CACvD,MAAM,SAAS,MAAM,IAAI,SAAS;CAClC,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,MAAM,OAAO,YAAYA,UAAAA,QAAK,QAAQ,SAAS,CAAC;CAEhD,MAAM,WAAW,OAAQ,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK,OAAQA,UAAAA,QAAK,SAAS,WAAWA,UAAAA,QAAK,QAAQ,SAAS,CAAC;CAC1G,MAAM,IAAI,WAAW,QAAQ;CAC7B,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,qBAAqB,WAAuC;CAC1E,MAAM,SAAS,aAAa,IAAI,SAAS;CACzC,IAAI,WAAW,KAAA,GAAW,OAAO,OAAO;CACxC,MAAM,OAAO,YAAYA,UAAAA,QAAK,QAAQ,SAAS,CAAC;CAChD,aAAa,IAAI,WAAW,EAAE,KAAK,CAAC;CACpC,OAAO;AACT"}
1
+ {"version":3,"file":"extensionName.cjs","names":["path","fs","path","path"],"sources":["../src/services/extensionSource/packageName.ts","../src/services/extensionSource/sync.ts","../src/services/extensionSource/index.ts"],"sourcesContent":["import path from 'node:path';\n\n/**\n * Display name for an extension that Pi could not attribute to a package.\n *\n * Pi stamps every `--extension <path>` argument with the literal source `cli`,\n * and po launches all of its extensions that way, so the only surviving\n * identity is the entry path. The nearest `package.json` above it names the\n * package that registered the tools.\n */\n\n/** Results are stable for the life of a session, and every source hits the same few dirs. */\nexport const nameCache = new Map<string, string>();\n// Wrapped, because \"no package above this path\" is a real answer worth caching\n// and a bare undefined cannot be told apart from a miss.\nexport const packageCache = new Map<string, { readonly name: string | undefined }>();\n\nexport const MANIFEST_FILE = 'package.json';\n\n/** The manifest's non-empty name; undefined for a malformed or nameless manifest. */\nexport function manifestPackageName(text: string): string | undefined {\n try {\n const manifest = JSON.parse(text) as { name?: unknown };\n return typeof manifest.name === 'string' && manifest.name.length > 0 ? manifest.name : undefined;\n } catch {\n // An unreadable manifest names nothing; keep walking up.\n return undefined;\n }\n}\n\n/** The next directory to search, or undefined at the filesystem root. */\nexport function parentDirectory(directory: string): string | undefined {\n const parent = path.dirname(directory);\n return parent === directory ? undefined : parent;\n}\n\n/** `@agimon-ai/po-task` reads as `po-task`; the scope is noise in a tree. */\nexport function displayExtensionName(name: string | undefined, entryPath: string): string {\n return name ? (name.split('/').pop() ?? name) : path.basename(entryPath, path.extname(entryPath));\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nimport {\n MANIFEST_FILE,\n displayExtensionName,\n manifestPackageName,\n nameCache,\n packageCache,\n parentDirectory,\n} from './packageName';\n\nfunction packageName(directory: string): string | undefined {\n for (let current: string | undefined = directory; current !== undefined; current = parentDirectory(current)) {\n let text: string;\n try {\n text = fs.readFileSync(path.join(current, MANIFEST_FILE), 'utf8');\n } catch {\n // No manifest here; keep walking up.\n continue;\n }\n const name = manifestPackageName(text);\n if (name) return name;\n }\n return undefined;\n}\n\n/** @deprecated Node-only sync shim; use readExtensionName. Removed in M2. */\nexport function extensionName(entryPath: string): string {\n const cached = nameCache.get(entryPath);\n if (cached !== undefined) return cached;\n const resolved = displayExtensionName(packageName(path.dirname(entryPath)), entryPath);\n nameCache.set(entryPath, resolved);\n return resolved;\n}\n\n/**\n * The package name exactly as a manifest spells it, scope and all.\n *\n * `extensionName` drops the scope because a tree reads better without it, but\n * that makes it useless as a key: `.po/modes.yaml` names packages as\n * `@agimon-ai/po-team`, so joining a registered tool back to the layer that\n * admitted it needs the unshortened name. Attribution and display are different\n * jobs, so they get different functions rather than one lossy one.\n *\n * @deprecated Node-only sync shim; use readExtensionPackageName. Removed in M2.\n */\nexport function extensionPackageName(entryPath: string): string | undefined {\n const cached = packageCache.get(entryPath);\n if (cached !== undefined) return cached.name;\n const name = packageName(path.dirname(entryPath));\n packageCache.set(entryPath, { name });\n return name;\n}\n","import path from 'node:path';\n\nimport type { FileSystem } from '@agimon-ai/po-core/platform';\n\nimport {\n MANIFEST_FILE,\n displayExtensionName,\n manifestPackageName,\n nameCache,\n packageCache,\n parentDirectory,\n} from './packageName';\n\nexport { extensionName, extensionPackageName } from './sync';\n\ntype IoContext = Parameters<FileSystem['readTextFile']>[1];\n\nasync function readPackageName(fs: FileSystem, directory: string, context: IoContext): Promise<string | undefined> {\n for (let current: string | undefined = directory; current !== undefined; current = parentDirectory(current)) {\n const text = await fs.readTextFile(path.join(current, MANIFEST_FILE), context);\n // No readable manifest here; keep walking up.\n const name = text.ok ? manifestPackageName(text.value) : undefined;\n if (name) return name;\n }\n return undefined;\n}\n\n/** Display name of the package that owns an extension entry, read through `fs`. */\nexport async function readExtensionName(fs: FileSystem, entryPath: string, context: IoContext): Promise<string> {\n const cached = nameCache.get(entryPath);\n if (cached !== undefined) return cached;\n const resolved = displayExtensionName(await readPackageName(fs, path.dirname(entryPath), context), entryPath);\n nameCache.set(entryPath, resolved);\n return resolved;\n}\n\n/** The owning package name with its scope, read through `fs`; see `extensionPackageName`. */\nexport async function readExtensionPackageName(\n fs: FileSystem,\n entryPath: string,\n context: IoContext,\n): Promise<string | undefined> {\n const cached = packageCache.get(entryPath);\n if (cached !== undefined) return cached.name;\n const name = await readPackageName(fs, path.dirname(entryPath), context);\n packageCache.set(entryPath, { name });\n return name;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAYA,MAAa,4BAAY,IAAI,IAAoB;AAGjD,MAAa,+BAAe,IAAI,IAAmD;AAEnF,MAAa,gBAAgB;;AAG7B,SAAgB,oBAAoB,MAAkC;CACpE,IAAI;EACF,MAAM,WAAW,KAAK,MAAM,IAAI;EAChC,OAAO,OAAO,SAAS,SAAS,YAAY,SAAS,KAAK,SAAS,IAAI,SAAS,OAAO,KAAA;CACzF,QAAQ;EAEN;CACF;AACF;;AAGA,SAAgB,gBAAgB,WAAuC;CACrE,MAAM,SAASA,UAAAA,QAAK,QAAQ,SAAS;CACrC,OAAO,WAAW,YAAY,KAAA,IAAY;AAC5C;;AAGA,SAAgB,qBAAqB,MAA0B,WAA2B;CACxF,OAAO,OAAQ,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK,OAAQA,UAAAA,QAAK,SAAS,WAAWA,UAAAA,QAAK,QAAQ,SAAS,CAAC;AAClG;;;AC3BA,SAAS,YAAY,WAAuC;CAC1D,KAAK,IAAI,UAA8B,WAAW,YAAY,KAAA,GAAW,UAAU,gBAAgB,OAAO,GAAG;EAC3G,IAAI;EACJ,IAAI;GACF,OAAOC,QAAAA,QAAG,aAAaC,UAAAA,QAAK,KAAK,SAAS,aAAa,GAAG,MAAM;EAClE,QAAQ;GAEN;EACF;EACA,MAAM,OAAO,oBAAoB,IAAI;EACrC,IAAI,MAAM,OAAO;CACnB;AAEF;;AAGA,SAAgB,cAAc,WAA2B;CACvD,MAAM,SAAS,UAAU,IAAI,SAAS;CACtC,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,MAAM,WAAW,qBAAqB,YAAYA,UAAAA,QAAK,QAAQ,SAAS,CAAC,GAAG,SAAS;CACrF,UAAU,IAAI,WAAW,QAAQ;CACjC,OAAO;AACT;;;;;;;;;;;;AAaA,SAAgB,qBAAqB,WAAuC;CAC1E,MAAM,SAAS,aAAa,IAAI,SAAS;CACzC,IAAI,WAAW,KAAA,GAAW,OAAO,OAAO;CACxC,MAAM,OAAO,YAAYA,UAAAA,QAAK,QAAQ,SAAS,CAAC;CAChD,aAAa,IAAI,WAAW,EAAE,KAAK,CAAC;CACpC,OAAO;AACT;;;ACpCA,eAAe,gBAAgB,IAAgB,WAAmB,SAAiD;CACjH,KAAK,IAAI,UAA8B,WAAW,YAAY,KAAA,GAAW,UAAU,gBAAgB,OAAO,GAAG;EAC3G,MAAM,OAAO,MAAM,GAAG,aAAaC,UAAAA,QAAK,KAAK,SAAS,aAAa,GAAG,OAAO;EAE7E,MAAM,OAAO,KAAK,KAAK,oBAAoB,KAAK,KAAK,IAAI,KAAA;EACzD,IAAI,MAAM,OAAO;CACnB;AAEF;;AAGA,eAAsB,kBAAkB,IAAgB,WAAmB,SAAqC;CAC9G,MAAM,SAAS,UAAU,IAAI,SAAS;CACtC,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,MAAM,WAAW,qBAAqB,MAAM,gBAAgB,IAAIA,UAAAA,QAAK,QAAQ,SAAS,GAAG,OAAO,GAAG,SAAS;CAC5G,UAAU,IAAI,WAAW,QAAQ;CACjC,OAAO;AACT;;AAGA,eAAsB,yBACpB,IACA,WACA,SAC6B;CAC7B,MAAM,SAAS,aAAa,IAAI,SAAS;CACzC,IAAI,WAAW,KAAA,GAAW,OAAO,OAAO;CACxC,MAAM,OAAO,MAAM,gBAAgB,IAAIA,UAAAA,QAAK,QAAQ,SAAS,GAAG,OAAO;CACvE,aAAa,IAAI,WAAW,EAAE,KAAK,CAAC;CACpC,OAAO;AACT"}
@@ -1,4 +1,6 @@
1
- //#region src/services/extensionSource/index.d.ts
1
+ import { FileSystem } from "@agimon-ai/po-core/platform";
2
+ //#region src/services/extensionSource/sync.d.ts
3
+ /** @deprecated Node-only sync shim; use readExtensionName. Removed in M2. */
2
4
  export declare function extensionName(entryPath: string): string;
3
5
  /**
4
6
  * The package name exactly as a manifest spells it, scope and all.
@@ -8,7 +10,17 @@ export declare function extensionName(entryPath: string): string;
8
10
  * `@agimon-ai/po-team`, so joining a registered tool back to the layer that
9
11
  * admitted it needs the unshortened name. Attribution and display are different
10
12
  * jobs, so they get different functions rather than one lossy one.
13
+ *
14
+ * @deprecated Node-only sync shim; use readExtensionPackageName. Removed in M2.
11
15
  */
12
16
  export declare function extensionPackageName(entryPath: string): string | undefined;
13
17
  //#endregion
18
+ //#region src/services/extensionSource/index.d.ts
19
+ type IoContext = Parameters<FileSystem['readTextFile']>[1];
20
+ /** Display name of the package that owns an extension entry, read through `fs`. */
21
+ export declare function readExtensionName(fs: FileSystem, entryPath: string, context: IoContext): Promise<string>;
22
+ /** The owning package name with its scope, read through `fs`; see `extensionPackageName`. */
23
+ export declare function readExtensionPackageName(fs: FileSystem, entryPath: string, context: IoContext): Promise<string | undefined>;
24
+ //#endregion
25
+ export {};
14
26
  //# sourceMappingURL=extensionName.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extensionName.d.mts","names":[],"sources":["../src/services/extensionSource/index.ts"],"mappings":";wBAgCgB,cAAc;;;;;;;;;;wBAmBd,qBAAqB"}
1
+ {"version":3,"file":"extensionName.d.mts","names":[],"sources":["../src/services/extensionSource/sync.ts","../src/services/extensionSource/index.ts"],"mappings":";;;wBA4BgB,cAAc;;;;;;;;;;;;wBAmBd,qBAAqB;;;KChChC,YAAY,WAAW;;wBAaN,kBAAkB,IAAI,YAAY,mBAAmB,SAAS,YAAY;;wBAS1E,yBACpB,IAAI,YACJ,mBACA,SAAS,YACR"}
@@ -1,6 +1,6 @@
1
- import fs from "node:fs";
2
1
  import path from "node:path";
3
- //#region src/services/extensionSource/index.ts
2
+ import fs from "node:fs";
3
+ //#region src/services/extensionSource/packageName.ts
4
4
  /**
5
5
  * Display name for an extension that Pi could not attribute to a package.
6
6
  *
@@ -10,26 +10,47 @@ import path from "node:path";
10
10
  * package that registered the tools.
11
11
  */
12
12
  /** Results are stable for the life of a session, and every source hits the same few dirs. */
13
- const cache = /* @__PURE__ */ new Map();
13
+ const nameCache = /* @__PURE__ */ new Map();
14
14
  const packageCache = /* @__PURE__ */ new Map();
15
+ const MANIFEST_FILE = "package.json";
16
+ /** The manifest's non-empty name; undefined for a malformed or nameless manifest. */
17
+ function manifestPackageName(text) {
18
+ try {
19
+ const manifest = JSON.parse(text);
20
+ return typeof manifest.name === "string" && manifest.name.length > 0 ? manifest.name : void 0;
21
+ } catch {
22
+ return;
23
+ }
24
+ }
25
+ /** The next directory to search, or undefined at the filesystem root. */
26
+ function parentDirectory(directory) {
27
+ const parent = path.dirname(directory);
28
+ return parent === directory ? void 0 : parent;
29
+ }
30
+ /** `@agimon-ai/po-task` reads as `po-task`; the scope is noise in a tree. */
31
+ function displayExtensionName(name, entryPath) {
32
+ return name ? name.split("/").pop() ?? name : path.basename(entryPath, path.extname(entryPath));
33
+ }
34
+ //#endregion
35
+ //#region src/services/extensionSource/sync.ts
15
36
  function packageName(directory) {
16
- let current = directory;
17
- for (;;) {
37
+ for (let current = directory; current !== void 0; current = parentDirectory(current)) {
38
+ let text;
18
39
  try {
19
- const manifest = JSON.parse(fs.readFileSync(path.join(current, "package.json"), "utf8"));
20
- if (typeof manifest.name === "string" && manifest.name.length > 0) return manifest.name;
21
- } catch {}
22
- const parent = path.dirname(current);
23
- if (parent === current) return void 0;
24
- current = parent;
40
+ text = fs.readFileSync(path.join(current, MANIFEST_FILE), "utf8");
41
+ } catch {
42
+ continue;
43
+ }
44
+ const name = manifestPackageName(text);
45
+ if (name) return name;
25
46
  }
26
47
  }
48
+ /** @deprecated Node-only sync shim; use readExtensionName. Removed in M2. */
27
49
  function extensionName(entryPath) {
28
- const cached = cache.get(entryPath);
50
+ const cached = nameCache.get(entryPath);
29
51
  if (cached !== void 0) return cached;
30
- const name = packageName(path.dirname(entryPath));
31
- const resolved = name ? name.split("/").pop() ?? name : path.basename(entryPath, path.extname(entryPath));
32
- cache.set(entryPath, resolved);
52
+ const resolved = displayExtensionName(packageName(path.dirname(entryPath)), entryPath);
53
+ nameCache.set(entryPath, resolved);
33
54
  return resolved;
34
55
  }
35
56
  /**
@@ -40,6 +61,8 @@ function extensionName(entryPath) {
40
61
  * `@agimon-ai/po-team`, so joining a registered tool back to the layer that
41
62
  * admitted it needs the unshortened name. Attribution and display are different
42
63
  * jobs, so they get different functions rather than one lossy one.
64
+ *
65
+ * @deprecated Node-only sync shim; use readExtensionPackageName. Removed in M2.
43
66
  */
44
67
  function extensionPackageName(entryPath) {
45
68
  const cached = packageCache.get(entryPath);
@@ -49,6 +72,31 @@ function extensionPackageName(entryPath) {
49
72
  return name;
50
73
  }
51
74
  //#endregion
52
- export { extensionName, extensionPackageName };
75
+ //#region src/services/extensionSource/index.ts
76
+ async function readPackageName(fs, directory, context) {
77
+ for (let current = directory; current !== void 0; current = parentDirectory(current)) {
78
+ const text = await fs.readTextFile(path.join(current, MANIFEST_FILE), context);
79
+ const name = text.ok ? manifestPackageName(text.value) : void 0;
80
+ if (name) return name;
81
+ }
82
+ }
83
+ /** Display name of the package that owns an extension entry, read through `fs`. */
84
+ async function readExtensionName(fs, entryPath, context) {
85
+ const cached = nameCache.get(entryPath);
86
+ if (cached !== void 0) return cached;
87
+ const resolved = displayExtensionName(await readPackageName(fs, path.dirname(entryPath), context), entryPath);
88
+ nameCache.set(entryPath, resolved);
89
+ return resolved;
90
+ }
91
+ /** The owning package name with its scope, read through `fs`; see `extensionPackageName`. */
92
+ async function readExtensionPackageName(fs, entryPath, context) {
93
+ const cached = packageCache.get(entryPath);
94
+ if (cached !== void 0) return cached.name;
95
+ const name = await readPackageName(fs, path.dirname(entryPath), context);
96
+ packageCache.set(entryPath, { name });
97
+ return name;
98
+ }
99
+ //#endregion
100
+ export { extensionName, extensionPackageName, readExtensionName, readExtensionPackageName };
53
101
 
54
102
  //# sourceMappingURL=extensionName.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"extensionName.mjs","names":[],"sources":["../src/services/extensionSource/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\n/**\n * Display name for an extension that Pi could not attribute to a package.\n *\n * Pi stamps every `--extension <path>` argument with the literal source `cli`,\n * and po launches all of its extensions that way, so the only surviving\n * identity is the entry path. The nearest `package.json` above it names the\n * package that registered the tools.\n */\n\n/** Results are stable for the life of a session, and every source hits the same few dirs. */\nconst cache = new Map<string, string>();\n// Wrapped, because \"no package above this path\" is a real answer worth caching\n// and a bare undefined cannot be told apart from a miss.\nconst packageCache = new Map<string, { readonly name: string | undefined }>();\nfunction packageName(directory: string): string | undefined {\n let current = directory;\n for (;;) {\n try {\n const manifest = JSON.parse(fs.readFileSync(path.join(current, 'package.json'), 'utf8')) as { name?: unknown };\n if (typeof manifest.name === 'string' && manifest.name.length > 0) return manifest.name;\n } catch {\n // No manifest here, or an unreadable one; keep walking up.\n }\n const parent = path.dirname(current);\n if (parent === current) return undefined;\n current = parent;\n }\n}\n\nexport function extensionName(entryPath: string): string {\n const cached = cache.get(entryPath);\n if (cached !== undefined) return cached;\n const name = packageName(path.dirname(entryPath));\n // `@agimon-ai/po-task` reads as `doom-task`; the scope is noise in a tree.\n const resolved = name ? (name.split('/').pop() ?? name) : path.basename(entryPath, path.extname(entryPath));\n cache.set(entryPath, resolved);\n return resolved;\n}\n\n/**\n * The package name exactly as a manifest spells it, scope and all.\n *\n * `extensionName` drops the scope because a tree reads better without it, but\n * that makes it useless as a key: `.po/modes.yaml` names packages as\n * `@agimon-ai/po-team`, so joining a registered tool back to the layer that\n * admitted it needs the unshortened name. Attribution and display are different\n * jobs, so they get different functions rather than one lossy one.\n */\nexport function extensionPackageName(entryPath: string): string | undefined {\n const cached = packageCache.get(entryPath);\n if (cached !== undefined) return cached.name;\n const name = packageName(path.dirname(entryPath));\n packageCache.set(entryPath, { name });\n return name;\n}\n"],"mappings":";;;;;;;;;;;;AAaA,MAAM,wBAAQ,IAAI,IAAoB;AAGtC,MAAM,+BAAe,IAAI,IAAmD;AAC5E,SAAS,YAAY,WAAuC;CAC1D,IAAI,UAAU;CACd,SAAS;EACP,IAAI;GACF,MAAM,WAAW,KAAK,MAAM,GAAG,aAAa,KAAK,KAAK,SAAS,cAAc,GAAG,MAAM,CAAC;GACvF,IAAI,OAAO,SAAS,SAAS,YAAY,SAAS,KAAK,SAAS,GAAG,OAAO,SAAS;EACrF,QAAQ,CAER;EACA,MAAM,SAAS,KAAK,QAAQ,OAAO;EACnC,IAAI,WAAW,SAAS,OAAO,KAAA;EAC/B,UAAU;CACZ;AACF;AAEA,SAAgB,cAAc,WAA2B;CACvD,MAAM,SAAS,MAAM,IAAI,SAAS;CAClC,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,MAAM,OAAO,YAAY,KAAK,QAAQ,SAAS,CAAC;CAEhD,MAAM,WAAW,OAAQ,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK,OAAQ,KAAK,SAAS,WAAW,KAAK,QAAQ,SAAS,CAAC;CAC1G,MAAM,IAAI,WAAW,QAAQ;CAC7B,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,qBAAqB,WAAuC;CAC1E,MAAM,SAAS,aAAa,IAAI,SAAS;CACzC,IAAI,WAAW,KAAA,GAAW,OAAO,OAAO;CACxC,MAAM,OAAO,YAAY,KAAK,QAAQ,SAAS,CAAC;CAChD,aAAa,IAAI,WAAW,EAAE,KAAK,CAAC;CACpC,OAAO;AACT"}
1
+ {"version":3,"file":"extensionName.mjs","names":[],"sources":["../src/services/extensionSource/packageName.ts","../src/services/extensionSource/sync.ts","../src/services/extensionSource/index.ts"],"sourcesContent":["import path from 'node:path';\n\n/**\n * Display name for an extension that Pi could not attribute to a package.\n *\n * Pi stamps every `--extension <path>` argument with the literal source `cli`,\n * and po launches all of its extensions that way, so the only surviving\n * identity is the entry path. The nearest `package.json` above it names the\n * package that registered the tools.\n */\n\n/** Results are stable for the life of a session, and every source hits the same few dirs. */\nexport const nameCache = new Map<string, string>();\n// Wrapped, because \"no package above this path\" is a real answer worth caching\n// and a bare undefined cannot be told apart from a miss.\nexport const packageCache = new Map<string, { readonly name: string | undefined }>();\n\nexport const MANIFEST_FILE = 'package.json';\n\n/** The manifest's non-empty name; undefined for a malformed or nameless manifest. */\nexport function manifestPackageName(text: string): string | undefined {\n try {\n const manifest = JSON.parse(text) as { name?: unknown };\n return typeof manifest.name === 'string' && manifest.name.length > 0 ? manifest.name : undefined;\n } catch {\n // An unreadable manifest names nothing; keep walking up.\n return undefined;\n }\n}\n\n/** The next directory to search, or undefined at the filesystem root. */\nexport function parentDirectory(directory: string): string | undefined {\n const parent = path.dirname(directory);\n return parent === directory ? undefined : parent;\n}\n\n/** `@agimon-ai/po-task` reads as `po-task`; the scope is noise in a tree. */\nexport function displayExtensionName(name: string | undefined, entryPath: string): string {\n return name ? (name.split('/').pop() ?? name) : path.basename(entryPath, path.extname(entryPath));\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nimport {\n MANIFEST_FILE,\n displayExtensionName,\n manifestPackageName,\n nameCache,\n packageCache,\n parentDirectory,\n} from './packageName';\n\nfunction packageName(directory: string): string | undefined {\n for (let current: string | undefined = directory; current !== undefined; current = parentDirectory(current)) {\n let text: string;\n try {\n text = fs.readFileSync(path.join(current, MANIFEST_FILE), 'utf8');\n } catch {\n // No manifest here; keep walking up.\n continue;\n }\n const name = manifestPackageName(text);\n if (name) return name;\n }\n return undefined;\n}\n\n/** @deprecated Node-only sync shim; use readExtensionName. Removed in M2. */\nexport function extensionName(entryPath: string): string {\n const cached = nameCache.get(entryPath);\n if (cached !== undefined) return cached;\n const resolved = displayExtensionName(packageName(path.dirname(entryPath)), entryPath);\n nameCache.set(entryPath, resolved);\n return resolved;\n}\n\n/**\n * The package name exactly as a manifest spells it, scope and all.\n *\n * `extensionName` drops the scope because a tree reads better without it, but\n * that makes it useless as a key: `.po/modes.yaml` names packages as\n * `@agimon-ai/po-team`, so joining a registered tool back to the layer that\n * admitted it needs the unshortened name. Attribution and display are different\n * jobs, so they get different functions rather than one lossy one.\n *\n * @deprecated Node-only sync shim; use readExtensionPackageName. Removed in M2.\n */\nexport function extensionPackageName(entryPath: string): string | undefined {\n const cached = packageCache.get(entryPath);\n if (cached !== undefined) return cached.name;\n const name = packageName(path.dirname(entryPath));\n packageCache.set(entryPath, { name });\n return name;\n}\n","import path from 'node:path';\n\nimport type { FileSystem } from '@agimon-ai/po-core/platform';\n\nimport {\n MANIFEST_FILE,\n displayExtensionName,\n manifestPackageName,\n nameCache,\n packageCache,\n parentDirectory,\n} from './packageName';\n\nexport { extensionName, extensionPackageName } from './sync';\n\ntype IoContext = Parameters<FileSystem['readTextFile']>[1];\n\nasync function readPackageName(fs: FileSystem, directory: string, context: IoContext): Promise<string | undefined> {\n for (let current: string | undefined = directory; current !== undefined; current = parentDirectory(current)) {\n const text = await fs.readTextFile(path.join(current, MANIFEST_FILE), context);\n // No readable manifest here; keep walking up.\n const name = text.ok ? manifestPackageName(text.value) : undefined;\n if (name) return name;\n }\n return undefined;\n}\n\n/** Display name of the package that owns an extension entry, read through `fs`. */\nexport async function readExtensionName(fs: FileSystem, entryPath: string, context: IoContext): Promise<string> {\n const cached = nameCache.get(entryPath);\n if (cached !== undefined) return cached;\n const resolved = displayExtensionName(await readPackageName(fs, path.dirname(entryPath), context), entryPath);\n nameCache.set(entryPath, resolved);\n return resolved;\n}\n\n/** The owning package name with its scope, read through `fs`; see `extensionPackageName`. */\nexport async function readExtensionPackageName(\n fs: FileSystem,\n entryPath: string,\n context: IoContext,\n): Promise<string | undefined> {\n const cached = packageCache.get(entryPath);\n if (cached !== undefined) return cached.name;\n const name = await readPackageName(fs, path.dirname(entryPath), context);\n packageCache.set(entryPath, { name });\n return name;\n}\n"],"mappings":";;;;;;;;;;;;AAYA,MAAa,4BAAY,IAAI,IAAoB;AAGjD,MAAa,+BAAe,IAAI,IAAmD;AAEnF,MAAa,gBAAgB;;AAG7B,SAAgB,oBAAoB,MAAkC;CACpE,IAAI;EACF,MAAM,WAAW,KAAK,MAAM,IAAI;EAChC,OAAO,OAAO,SAAS,SAAS,YAAY,SAAS,KAAK,SAAS,IAAI,SAAS,OAAO,KAAA;CACzF,QAAQ;EAEN;CACF;AACF;;AAGA,SAAgB,gBAAgB,WAAuC;CACrE,MAAM,SAAS,KAAK,QAAQ,SAAS;CACrC,OAAO,WAAW,YAAY,KAAA,IAAY;AAC5C;;AAGA,SAAgB,qBAAqB,MAA0B,WAA2B;CACxF,OAAO,OAAQ,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK,OAAQ,KAAK,SAAS,WAAW,KAAK,QAAQ,SAAS,CAAC;AAClG;;;AC3BA,SAAS,YAAY,WAAuC;CAC1D,KAAK,IAAI,UAA8B,WAAW,YAAY,KAAA,GAAW,UAAU,gBAAgB,OAAO,GAAG;EAC3G,IAAI;EACJ,IAAI;GACF,OAAO,GAAG,aAAa,KAAK,KAAK,SAAS,aAAa,GAAG,MAAM;EAClE,QAAQ;GAEN;EACF;EACA,MAAM,OAAO,oBAAoB,IAAI;EACrC,IAAI,MAAM,OAAO;CACnB;AAEF;;AAGA,SAAgB,cAAc,WAA2B;CACvD,MAAM,SAAS,UAAU,IAAI,SAAS;CACtC,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,MAAM,WAAW,qBAAqB,YAAY,KAAK,QAAQ,SAAS,CAAC,GAAG,SAAS;CACrF,UAAU,IAAI,WAAW,QAAQ;CACjC,OAAO;AACT;;;;;;;;;;;;AAaA,SAAgB,qBAAqB,WAAuC;CAC1E,MAAM,SAAS,aAAa,IAAI,SAAS;CACzC,IAAI,WAAW,KAAA,GAAW,OAAO,OAAO;CACxC,MAAM,OAAO,YAAY,KAAK,QAAQ,SAAS,CAAC;CAChD,aAAa,IAAI,WAAW,EAAE,KAAK,CAAC;CACpC,OAAO;AACT;;;ACpCA,eAAe,gBAAgB,IAAgB,WAAmB,SAAiD;CACjH,KAAK,IAAI,UAA8B,WAAW,YAAY,KAAA,GAAW,UAAU,gBAAgB,OAAO,GAAG;EAC3G,MAAM,OAAO,MAAM,GAAG,aAAa,KAAK,KAAK,SAAS,aAAa,GAAG,OAAO;EAE7E,MAAM,OAAO,KAAK,KAAK,oBAAoB,KAAK,KAAK,IAAI,KAAA;EACzD,IAAI,MAAM,OAAO;CACnB;AAEF;;AAGA,eAAsB,kBAAkB,IAAgB,WAAmB,SAAqC;CAC9G,MAAM,SAAS,UAAU,IAAI,SAAS;CACtC,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,MAAM,WAAW,qBAAqB,MAAM,gBAAgB,IAAI,KAAK,QAAQ,SAAS,GAAG,OAAO,GAAG,SAAS;CAC5G,UAAU,IAAI,WAAW,QAAQ;CACjC,OAAO;AACT;;AAGA,eAAsB,yBACpB,IACA,WACA,SAC6B;CAC7B,MAAM,SAAS,aAAa,IAAI,SAAS;CACzC,IAAI,WAAW,KAAA,GAAW,OAAO,OAAO;CACxC,MAAM,OAAO,MAAM,gBAAgB,IAAI,KAAK,QAAQ,SAAS,GAAG,OAAO;CACvE,aAAa,IAAI,WAAW,EAAE,KAAK,CAAC;CACpC,OAAO;AACT"}
package/dist/footer.mjs CHANGED
@@ -1,2 +1 @@
1
- import { FooterStatusItemSchema, FooterStatusPlacementSchema, FooterTextColorSchema, FooterTextSegmentSchema } from "@agimon-ai/po-core/footer";
2
- export { FooterStatusItemSchema, FooterStatusPlacementSchema, FooterTextColorSchema, FooterTextSegmentSchema };
1
+ export { FooterStatusItemSchema, FooterStatusPlacementSchema, FooterTextColorSchema, FooterTextSegmentSchema } from "@agimon-ai/po-core/footer";
@@ -1,2 +1 @@
1
- import { t as readDoomHarnessMetadata } from "./harnessMetadata-DkMSJutN.mjs";
2
- export { readDoomHarnessMetadata };
1
+ export { t as readDoomHarnessMetadata } from "./harnessMetadata-DkMSJutN.mjs";
@@ -1,14 +1,7 @@
1
1
  import { FooterTextColor } from "@agimon-ai/po-core/footer";
2
- //#region src/services/theme/index.d.ts
2
+ import { FileSystem } from "@agimon-ai/po-core/platform";
3
+ //#region src/services/theme/defaultTheme.d.ts
3
4
  declare const DEFAULT_THEME_NAME = "po-dark";
4
- /** Stable semantic color shared by every UI surface that identifies an agent run. */
5
- declare function agentIdentityColor(identity: string): FooterTextColor;
6
- /**
7
- * Prefer the identity's stable color, then walk the palette to avoid reusing a
8
- * color already visible on the same surface. Once every color is occupied,
9
- * reuse the stable preference rather than changing existing assignments.
10
- */
11
- declare function allocateAgentIdentityColor(identity: string, occupied: ReadonlySet<FooterTextColor>): FooterTextColor;
12
5
  declare const DEFAULT_THEME: {
13
6
  readonly $schema: 'https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json';
14
7
  readonly name: "po-dark";
@@ -97,7 +90,22 @@ declare const DEFAULT_THEME: {
97
90
  readonly infoBg: '#3b3526';
98
91
  };
99
92
  };
93
+ //#endregion
94
+ //#region src/services/theme/sync.d.ts
95
+ /** @deprecated Node-only sync shim; use writeDefaultThemeFile. Removed in M2. */
100
96
  declare function writeDefaultTheme(temporaryDirectory: string): Promise<string>;
101
97
  //#endregion
102
- export { writeDefaultTheme as a, allocateAgentIdentityColor as i, DEFAULT_THEME_NAME as n, agentIdentityColor as r, DEFAULT_THEME as t };
103
- //# sourceMappingURL=index-Dpzvl-vg.d.mts.map
98
+ //#region src/services/theme/index.d.ts
99
+ /** Stable semantic color shared by every UI surface that identifies an agent run. */
100
+ declare function agentIdentityColor(identity: string): FooterTextColor;
101
+ /**
102
+ * Prefer the identity's stable color, then walk the palette to avoid reusing a
103
+ * color already visible on the same surface. Once every color is occupied,
104
+ * reuse the stable preference rather than changing existing assignments.
105
+ */
106
+ declare function allocateAgentIdentityColor(identity: string, occupied: ReadonlySet<FooterTextColor>): FooterTextColor;
107
+ /** Writes the default theme into `temporaryDirectory` through `fs`, readable by its owner only, and returns its path. */
108
+ declare function writeDefaultThemeFile(fs: FileSystem, temporaryDirectory: string, context: Parameters<FileSystem['writeFile']>[2]): Promise<string>;
109
+ //#endregion
110
+ export { DEFAULT_THEME as a, writeDefaultTheme as i, allocateAgentIdentityColor as n, DEFAULT_THEME_NAME as o, writeDefaultThemeFile as r, agentIdentityColor as t };
111
+ //# sourceMappingURL=index-DFSkSBBh.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-DFSkSBBh.d.mts","names":[],"sources":["../src/services/theme/defaultTheme.ts","../src/services/theme/sync.ts","../src/services/theme/index.ts"],"mappings":";;;cAEa;cAKA;WACX;WAEA;WAGA;aACE;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aAEA;aACA;;WAEF;aACE;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aAEA;aACA;aACA;aACA;aACA;aACA;aACA;aAGA;aACA;aACA;aACA;aAEA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aAEA;aACA;aACA;aAEA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;aAEA;;WAEF;aACE;aACA;aACA;;;;;;iBCpGkB,kBAAkB,6BAA6B;;;;iBCsBrD,mBAAmB,mBAAmB;;;;;;iBAStC,2BAA2B,kBAAkB,UAAU,YAAY,mBAAmB;;iBAUhF,sBACpB,IAAI,YACJ,4BACA,SAAS,WAAW,8BACnB"}
package/dist/index.cjs CHANGED
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_harnessMetadata = require("./harnessMetadata-Dw9Rb1nW.cjs");
3
3
  const require_telemetry = require("./telemetry-DMR6cIT1.cjs");
4
4
  const require_uiState = require("./uiState-rUwgKslb.cjs");
5
- const require_theme = require("./theme-2wveit5V.cjs");
5
+ const require_theme = require("./theme-BfC_GGQ4.cjs");
6
6
  exports.DEFAULT_THEME = require_theme.DEFAULT_THEME;
7
7
  exports.DEFAULT_THEME_NAME = require_theme.DEFAULT_THEME_NAME;
8
8
  exports.DoomUiState = require_uiState.DoomUiState;
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { n as readDoomHarnessMetadata, t as DoomHarnessMetadata } from "./harnessMetadata-CzsdGAxL.mjs";
2
2
  import { a as UiTelemetryOptions, i as UiTelemetry, n as UiEventAttributes, o as createUiTelemetry, r as UiEventName, t as UI_EVENT } from "./index-Bx49wmE7.mjs";
3
3
  import { n as LeaderOption, r as LeaderSnapshot, t as DoomUiState } from "./uiState-Binu4nUb.mjs";
4
- import { a as writeDefaultTheme, n as DEFAULT_THEME_NAME, t as DEFAULT_THEME } from "./index-Dpzvl-vg.mjs";
4
+ import { a as DEFAULT_THEME, i as writeDefaultTheme, o as DEFAULT_THEME_NAME } from "./index-DFSkSBBh.mjs";
5
5
  import { ConfigChoice, ConfigField, ConfigSection, ConfigStep, DoomConfigActionInput, DoomConfigContributionHandle, DoomConfigContributionOptions } from "@agimon-ai/po-core/config";
6
6
  import { DoomFooterContributionDefinition, DoomFooterContributionHandle, DoomFooterContributionValue } from "@agimon-ai/po-core/footer";
7
7
  import { DoomLeaderContributionHandle, LeaderBinding as DoomLeaderBinding, LeaderCommand as DoomLeaderCommand, LeaderContribution as DoomLeaderContribution, LeaderSegment as DoomLeaderSegment } from "@agimon-ai/po-core/leader";
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as readDoomHarnessMetadata } from "./harnessMetadata-DkMSJutN.mjs";
2
2
  import { n as createUiTelemetry, t as UI_EVENT } from "./telemetry--EgKB9ei.mjs";
3
3
  import { t as DoomUiState } from "./uiState-G_Pso-5i.mjs";
4
- import { a as writeDefaultTheme, n as DEFAULT_THEME_NAME, t as DEFAULT_THEME } from "./theme-Byj_dBlT.mjs";
4
+ import { a as DEFAULT_THEME, i as writeDefaultTheme, o as DEFAULT_THEME_NAME } from "./theme-BX_hfErv.mjs";
5
5
  export { DEFAULT_THEME, DEFAULT_THEME_NAME, DoomUiState, UI_EVENT, createUiTelemetry, readDoomHarnessMetadata, writeDefaultTheme };
@@ -1,2 +1 @@
1
- import { n as createUiTelemetry, t as UI_EVENT } from "./telemetry--EgKB9ei.mjs";
2
- export { UI_EVENT, createUiTelemetry };
1
+ export { t as UI_EVENT, n as createUiTelemetry } from "./telemetry--EgKB9ei.mjs";
package/dist/skills.mjs CHANGED
@@ -1,2 +1 @@
1
- import { DOOM_SKILL_SOURCES_SERVICE, SkillSourceContributionSchema, SkillSourceNameSchema, createDoomSkillSourcesService, readDoomSkillSourcesService, requireDoomSkillSourcesService } from "@agimon-ai/po-core/skills";
2
- export { DOOM_SKILL_SOURCES_SERVICE, SkillSourceContributionSchema, SkillSourceNameSchema, createDoomSkillSourcesService, readDoomSkillSourcesService, requireDoomSkillSourcesService };
1
+ export { DOOM_SKILL_SOURCES_SERVICE, SkillSourceContributionSchema, SkillSourceNameSchema, createDoomSkillSourcesService, readDoomSkillSourcesService, requireDoomSkillSourcesService } from "@agimon-ai/po-core/skills";
@@ -1,40 +1,8 @@
1
- import fs from "node:fs";
2
1
  import path from "node:path";
3
- //#region src/services/theme/index.ts
2
+ import fs from "node:fs";
3
+ import { getOrThrow, nodeHost } from "@agimon-ai/po-core/platform";
4
+ //#region src/services/theme/defaultTheme.ts
4
5
  const DEFAULT_THEME_NAME = "po-dark";
5
- const AGENT_IDENTITY_COLORS = [
6
- "accent",
7
- "mdCode",
8
- "toolDiffAdded",
9
- "warning",
10
- "mdHeading",
11
- "syntaxNumber"
12
- ];
13
- function agentIdentityColorIndex(identity) {
14
- let hash = 2166136261;
15
- for (const character of identity) {
16
- hash ^= character.charCodeAt(0);
17
- hash = Math.imul(hash, 16777619);
18
- }
19
- return (hash >>> 0) % AGENT_IDENTITY_COLORS.length;
20
- }
21
- /** Stable semantic color shared by every UI surface that identifies an agent run. */
22
- function agentIdentityColor(identity) {
23
- return AGENT_IDENTITY_COLORS[agentIdentityColorIndex(identity)];
24
- }
25
- /**
26
- * Prefer the identity's stable color, then walk the palette to avoid reusing a
27
- * color already visible on the same surface. Once every color is occupied,
28
- * reuse the stable preference rather than changing existing assignments.
29
- */
30
- function allocateAgentIdentityColor(identity, occupied) {
31
- const preferredIndex = agentIdentityColorIndex(identity);
32
- for (let offset = 0; offset < AGENT_IDENTITY_COLORS.length; offset++) {
33
- const color = AGENT_IDENTITY_COLORS[(preferredIndex + offset) % AGENT_IDENTITY_COLORS.length];
34
- if (!occupied.has(color)) return color;
35
- }
36
- return AGENT_IDENTITY_COLORS[preferredIndex];
37
- }
38
6
  const DEFAULT_THEME = {
39
7
  $schema: "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
40
8
  name: DEFAULT_THEME_NAME,
@@ -123,12 +91,64 @@ const DEFAULT_THEME = {
123
91
  infoBg: "#3b3526"
124
92
  }
125
93
  };
94
+ /** Where the default theme goes in `temporaryDirectory`, and its file content. */
95
+ function defaultThemeFile(temporaryDirectory) {
96
+ return {
97
+ path: path.join(temporaryDirectory, `${DEFAULT_THEME_NAME}.json`),
98
+ content: `${JSON.stringify(DEFAULT_THEME, null, 2)}\n`
99
+ };
100
+ }
101
+ //#endregion
102
+ //#region src/services/theme/sync.ts
103
+ /** @deprecated Node-only sync shim; use writeDefaultThemeFile. Removed in M2. */
126
104
  async function writeDefaultTheme(temporaryDirectory) {
127
- const themePath = path.join(temporaryDirectory, `${DEFAULT_THEME_NAME}.json`);
128
- await fs.promises.writeFile(themePath, `${JSON.stringify(DEFAULT_THEME, null, 2)}\n`, { mode: 384 });
129
- return themePath;
105
+ const { path, content } = defaultThemeFile(temporaryDirectory);
106
+ await fs.promises.writeFile(path, content, { mode: 384 });
107
+ return path;
108
+ }
109
+ //#endregion
110
+ //#region src/services/theme/index.ts
111
+ const AGENT_IDENTITY_COLORS = [
112
+ "accent",
113
+ "mdCode",
114
+ "toolDiffAdded",
115
+ "warning",
116
+ "mdHeading",
117
+ "syntaxNumber"
118
+ ];
119
+ function agentIdentityColorIndex(identity) {
120
+ let hash = 2166136261;
121
+ for (const character of identity) {
122
+ hash ^= character.charCodeAt(0);
123
+ hash = Math.imul(hash, 16777619);
124
+ }
125
+ return (hash >>> 0) % AGENT_IDENTITY_COLORS.length;
126
+ }
127
+ /** Stable semantic color shared by every UI surface that identifies an agent run. */
128
+ function agentIdentityColor(identity) {
129
+ return AGENT_IDENTITY_COLORS[agentIdentityColorIndex(identity)];
130
+ }
131
+ /**
132
+ * Prefer the identity's stable color, then walk the palette to avoid reusing a
133
+ * color already visible on the same surface. Once every color is occupied,
134
+ * reuse the stable preference rather than changing existing assignments.
135
+ */
136
+ function allocateAgentIdentityColor(identity, occupied) {
137
+ const preferredIndex = agentIdentityColorIndex(identity);
138
+ for (let offset = 0; offset < AGENT_IDENTITY_COLORS.length; offset++) {
139
+ const color = AGENT_IDENTITY_COLORS[(preferredIndex + offset) % AGENT_IDENTITY_COLORS.length];
140
+ if (!occupied.has(color)) return color;
141
+ }
142
+ return AGENT_IDENTITY_COLORS[preferredIndex];
143
+ }
144
+ /** Writes the default theme into `temporaryDirectory` through `fs`, readable by its owner only, and returns its path. */
145
+ async function writeDefaultThemeFile(fs, temporaryDirectory, context) {
146
+ const { path, content } = defaultThemeFile(temporaryDirectory);
147
+ getOrThrow(await fs.writeFile(path, content, context));
148
+ await nodeHost.setMode(path, 384);
149
+ return path;
130
150
  }
131
151
  //#endregion
132
- export { writeDefaultTheme as a, allocateAgentIdentityColor as i, DEFAULT_THEME_NAME as n, agentIdentityColor as r, DEFAULT_THEME as t };
152
+ export { DEFAULT_THEME as a, writeDefaultTheme as i, allocateAgentIdentityColor as n, DEFAULT_THEME_NAME as o, writeDefaultThemeFile as r, agentIdentityColor as t };
133
153
 
134
- //# sourceMappingURL=theme-Byj_dBlT.mjs.map
154
+ //# sourceMappingURL=theme-BX_hfErv.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-BX_hfErv.mjs","names":[],"sources":["../src/services/theme/defaultTheme.ts","../src/services/theme/sync.ts","../src/services/theme/index.ts"],"sourcesContent":["import path from 'node:path';\n\nexport const DEFAULT_THEME_NAME = 'po-dark';\n\n/** The theme file is readable by its owner only. */\nexport const DEFAULT_THEME_FILE_MODE = 0o600;\n\nexport const DEFAULT_THEME = {\n $schema:\n 'https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json',\n name: DEFAULT_THEME_NAME,\n // Po Jade's quiet ink surfaces and green identity. Syntax colors retain\n // their meaning instead of making every operation a brand accent.\n vars: {\n bg: '#1c1c1c',\n bgAlt: '#171717',\n bgActive: '#2b2b2b',\n bgHover: '#2b2b2b',\n fg: '#dedede',\n fgAlt: '#b0b0b0',\n grey: '#343434',\n greyAlt: '#555555',\n blue: '#8cb5cc',\n darkBlue: '#284b64',\n cyan: '#8fc8c7',\n green: '#81cca3',\n lightGreen: '#a5d9b5',\n teal: '#8ec1ab',\n orange: '#d3ad83',\n red: '#e99185',\n violet: '#b0a0ce',\n magenta: '#c19aae',\n yellow: '#d6be82',\n lightYellow: '#e1cf9e',\n comment: '#a4a4a4',\n // Recessed diff bands retain readable syntax and quiet foreground text.\n diffAddedBg: '#152d20',\n diffRemovedBg: '#35201b',\n },\n colors: {\n accent: 'green',\n border: 'greyAlt',\n borderAccent: 'green',\n borderMuted: 'grey',\n success: 'green',\n error: 'red',\n warning: 'yellow',\n muted: 'fgAlt',\n dim: 'comment',\n text: 'fg',\n thinkingText: 'fgAlt',\n\n selectedBg: 'bgHover',\n userMessageBg: 'bgActive',\n userMessageText: 'fg',\n customMessageBg: '#292c2a',\n customMessageText: 'fg',\n customMessageLabel: 'green',\n toolPendingBg: 'bgAlt',\n // Doubles as the added/removed band behind a diff row, so it stays a wash\n // rather than a fill: syntax highlighting has to remain legible on top.\n toolSuccessBg: 'diffAddedBg',\n toolErrorBg: 'diffRemovedBg',\n toolTitle: 'green',\n toolOutput: 'fg',\n\n mdHeading: 'magenta',\n mdLink: 'blue',\n mdLinkUrl: 'comment',\n mdCode: 'cyan',\n mdCodeBlock: 'lightYellow',\n mdCodeBlockBorder: 'greyAlt',\n mdQuote: 'fgAlt',\n mdQuoteBorder: 'greyAlt',\n mdHr: 'greyAlt',\n mdListBullet: 'green',\n\n toolDiffAdded: 'lightGreen',\n toolDiffRemoved: 'red',\n toolDiffContext: 'fgAlt',\n\n syntaxComment: 'comment',\n syntaxKeyword: 'blue',\n syntaxFunction: 'magenta',\n syntaxVariable: 'violet',\n syntaxString: 'green',\n syntaxNumber: 'orange',\n syntaxType: 'yellow',\n syntaxOperator: 'orange',\n syntaxPunctuation: 'fgAlt',\n\n // A rising ramp from quiet ink through the semantic syntax ladder.\n thinkingOff: 'grey',\n thinkingMinimal: 'fgAlt',\n thinkingLow: 'darkBlue',\n thinkingMedium: 'blue',\n thinkingHigh: 'teal',\n thinkingXhigh: 'magenta',\n thinkingMax: 'red',\n\n bashMode: 'lightGreen',\n },\n export: {\n pageBg: 'bg',\n cardBg: 'bgAlt',\n infoBg: '#3b3526',\n },\n} as const;\n\n/** Where the default theme goes in `temporaryDirectory`, and its file content. */\nexport function defaultThemeFile(temporaryDirectory: string): { path: string; content: string } {\n return {\n path: path.join(temporaryDirectory, `${DEFAULT_THEME_NAME}.json`),\n content: `${JSON.stringify(DEFAULT_THEME, null, 2)}\\n`,\n };\n}\n","import fs from 'node:fs';\n\nimport { DEFAULT_THEME_FILE_MODE, defaultThemeFile } from './defaultTheme';\n\n/** @deprecated Node-only sync shim; use writeDefaultThemeFile. Removed in M2. */\nexport async function writeDefaultTheme(temporaryDirectory: string): Promise<string> {\n const { path, content } = defaultThemeFile(temporaryDirectory);\n await fs.promises.writeFile(path, content, { mode: DEFAULT_THEME_FILE_MODE });\n return path;\n}\n","import type { FooterTextColor } from '@agimon-ai/po-core/footer';\nimport { type FileSystem, getOrThrow, nodeHost } from '@agimon-ai/po-core/platform';\n\nimport { DEFAULT_THEME_FILE_MODE, defaultThemeFile } from './defaultTheme';\n\nexport { DEFAULT_THEME, DEFAULT_THEME_NAME } from './defaultTheme';\nexport { writeDefaultTheme } from './sync';\n\nconst AGENT_IDENTITY_COLORS = [\n 'accent',\n 'mdCode',\n 'toolDiffAdded',\n 'warning',\n 'mdHeading',\n 'syntaxNumber',\n] as const satisfies readonly FooterTextColor[];\n\nfunction agentIdentityColorIndex(identity: string): number {\n let hash = 2_166_136_261;\n for (const character of identity) {\n hash ^= character.charCodeAt(0);\n hash = Math.imul(hash, 16_777_619);\n }\n return (hash >>> 0) % AGENT_IDENTITY_COLORS.length;\n}\n\n/** Stable semantic color shared by every UI surface that identifies an agent run. */\nexport function agentIdentityColor(identity: string): FooterTextColor {\n return AGENT_IDENTITY_COLORS[agentIdentityColorIndex(identity)]!;\n}\n\n/**\n * Prefer the identity's stable color, then walk the palette to avoid reusing a\n * color already visible on the same surface. Once every color is occupied,\n * reuse the stable preference rather than changing existing assignments.\n */\nexport function allocateAgentIdentityColor(identity: string, occupied: ReadonlySet<FooterTextColor>): FooterTextColor {\n const preferredIndex = agentIdentityColorIndex(identity);\n for (let offset = 0; offset < AGENT_IDENTITY_COLORS.length; offset++) {\n const color = AGENT_IDENTITY_COLORS[(preferredIndex + offset) % AGENT_IDENTITY_COLORS.length]!;\n if (!occupied.has(color)) return color;\n }\n return AGENT_IDENTITY_COLORS[preferredIndex]!;\n}\n\n/** Writes the default theme into `temporaryDirectory` through `fs`, readable by its owner only, and returns its path. */\nexport async function writeDefaultThemeFile(\n fs: FileSystem,\n temporaryDirectory: string,\n context: Parameters<FileSystem['writeFile']>[2],\n): Promise<string> {\n const { path, content } = defaultThemeFile(temporaryDirectory);\n getOrThrow(await fs.writeFile(path, content, context));\n await nodeHost.setMode(path, DEFAULT_THEME_FILE_MODE);\n return path;\n}\n"],"mappings":";;;;AAEA,MAAa,qBAAqB;AAKlC,MAAa,gBAAgB;CAC3B,SACE;CACF,MAAM;CAGN,MAAM;EACJ,IAAI;EACJ,OAAO;EACP,UAAU;EACV,SAAS;EACT,IAAI;EACJ,OAAO;EACP,MAAM;EACN,SAAS;EACT,MAAM;EACN,UAAU;EACV,MAAM;EACN,OAAO;EACP,YAAY;EACZ,MAAM;EACN,QAAQ;EACR,KAAK;EACL,QAAQ;EACR,SAAS;EACT,QAAQ;EACR,aAAa;EACb,SAAS;EAET,aAAa;EACb,eAAe;CACjB;CACA,QAAQ;EACN,QAAQ;EACR,QAAQ;EACR,cAAc;EACd,aAAa;EACb,SAAS;EACT,OAAO;EACP,SAAS;EACT,OAAO;EACP,KAAK;EACL,MAAM;EACN,cAAc;EAEd,YAAY;EACZ,eAAe;EACf,iBAAiB;EACjB,iBAAiB;EACjB,mBAAmB;EACnB,oBAAoB;EACpB,eAAe;EAGf,eAAe;EACf,aAAa;EACb,WAAW;EACX,YAAY;EAEZ,WAAW;EACX,QAAQ;EACR,WAAW;EACX,QAAQ;EACR,aAAa;EACb,mBAAmB;EACnB,SAAS;EACT,eAAe;EACf,MAAM;EACN,cAAc;EAEd,eAAe;EACf,iBAAiB;EACjB,iBAAiB;EAEjB,eAAe;EACf,eAAe;EACf,gBAAgB;EAChB,gBAAgB;EAChB,cAAc;EACd,cAAc;EACd,YAAY;EACZ,gBAAgB;EAChB,mBAAmB;EAGnB,aAAa;EACb,iBAAiB;EACjB,aAAa;EACb,gBAAgB;EAChB,cAAc;EACd,eAAe;EACf,aAAa;EAEb,UAAU;CACZ;CACA,QAAQ;EACN,QAAQ;EACR,QAAQ;EACR,QAAQ;CACV;AACF;;AAGA,SAAgB,iBAAiB,oBAA+D;CAC9F,OAAO;EACL,MAAM,KAAK,KAAK,oBAAoB,GAAG,mBAAmB,MAAM;EAChE,SAAS,GAAG,KAAK,UAAU,eAAe,MAAM,CAAC,EAAE;CACrD;AACF;;;;AC9GA,eAAsB,kBAAkB,oBAA6C;CACnF,MAAM,EAAE,MAAM,YAAY,iBAAiB,kBAAkB;CAC7D,MAAM,GAAG,SAAS,UAAU,MAAM,SAAS,EAAE,MAAA,IAA8B,CAAC;CAC5E,OAAO;AACT;;;ACDA,MAAM,wBAAwB;CAC5B;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAS,wBAAwB,UAA0B;CACzD,IAAI,OAAO;CACX,KAAK,MAAM,aAAa,UAAU;EAChC,QAAQ,UAAU,WAAW,CAAC;EAC9B,OAAO,KAAK,KAAK,MAAM,QAAU;CACnC;CACA,QAAQ,SAAS,KAAK,sBAAsB;AAC9C;;AAGA,SAAgB,mBAAmB,UAAmC;CACpE,OAAO,sBAAsB,wBAAwB,QAAQ;AAC/D;;;;;;AAOA,SAAgB,2BAA2B,UAAkB,UAAyD;CACpH,MAAM,iBAAiB,wBAAwB,QAAQ;CACvD,KAAK,IAAI,SAAS,GAAG,SAAS,sBAAsB,QAAQ,UAAU;EACpE,MAAM,QAAQ,uBAAuB,iBAAiB,UAAU,sBAAsB;EACtF,IAAI,CAAC,SAAS,IAAI,KAAK,GAAG,OAAO;CACnC;CACA,OAAO,sBAAsB;AAC/B;;AAGA,eAAsB,sBACpB,IACA,oBACA,SACiB;CACjB,MAAM,EAAE,MAAM,YAAY,iBAAiB,kBAAkB;CAC7D,WAAW,MAAM,GAAG,UAAU,MAAM,SAAS,OAAO,CAAC;CACrD,MAAM,SAAS,QAAQ,MAAA,GAA6B;CACpD,OAAO;AACT"}
@@ -1,43 +1,11 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.cjs");
2
- let node_fs = require("node:fs");
3
- node_fs = require_rolldown_runtime.__toESM(node_fs, 1);
4
2
  let node_path = require("node:path");
5
3
  node_path = require_rolldown_runtime.__toESM(node_path, 1);
6
- //#region src/services/theme/index.ts
4
+ let node_fs = require("node:fs");
5
+ node_fs = require_rolldown_runtime.__toESM(node_fs, 1);
6
+ let _agimon_ai_po_core_platform = require("@agimon-ai/po-core/platform");
7
+ //#region src/services/theme/defaultTheme.ts
7
8
  const DEFAULT_THEME_NAME = "po-dark";
8
- const AGENT_IDENTITY_COLORS = [
9
- "accent",
10
- "mdCode",
11
- "toolDiffAdded",
12
- "warning",
13
- "mdHeading",
14
- "syntaxNumber"
15
- ];
16
- function agentIdentityColorIndex(identity) {
17
- let hash = 2166136261;
18
- for (const character of identity) {
19
- hash ^= character.charCodeAt(0);
20
- hash = Math.imul(hash, 16777619);
21
- }
22
- return (hash >>> 0) % AGENT_IDENTITY_COLORS.length;
23
- }
24
- /** Stable semantic color shared by every UI surface that identifies an agent run. */
25
- function agentIdentityColor(identity) {
26
- return AGENT_IDENTITY_COLORS[agentIdentityColorIndex(identity)];
27
- }
28
- /**
29
- * Prefer the identity's stable color, then walk the palette to avoid reusing a
30
- * color already visible on the same surface. Once every color is occupied,
31
- * reuse the stable preference rather than changing existing assignments.
32
- */
33
- function allocateAgentIdentityColor(identity, occupied) {
34
- const preferredIndex = agentIdentityColorIndex(identity);
35
- for (let offset = 0; offset < AGENT_IDENTITY_COLORS.length; offset++) {
36
- const color = AGENT_IDENTITY_COLORS[(preferredIndex + offset) % AGENT_IDENTITY_COLORS.length];
37
- if (!occupied.has(color)) return color;
38
- }
39
- return AGENT_IDENTITY_COLORS[preferredIndex];
40
- }
41
9
  const DEFAULT_THEME = {
42
10
  $schema: "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
43
11
  name: DEFAULT_THEME_NAME,
@@ -126,10 +94,62 @@ const DEFAULT_THEME = {
126
94
  infoBg: "#3b3526"
127
95
  }
128
96
  };
97
+ /** Where the default theme goes in `temporaryDirectory`, and its file content. */
98
+ function defaultThemeFile(temporaryDirectory) {
99
+ return {
100
+ path: node_path.default.join(temporaryDirectory, `${DEFAULT_THEME_NAME}.json`),
101
+ content: `${JSON.stringify(DEFAULT_THEME, null, 2)}\n`
102
+ };
103
+ }
104
+ //#endregion
105
+ //#region src/services/theme/sync.ts
106
+ /** @deprecated Node-only sync shim; use writeDefaultThemeFile. Removed in M2. */
129
107
  async function writeDefaultTheme(temporaryDirectory) {
130
- const themePath = node_path.default.join(temporaryDirectory, `${DEFAULT_THEME_NAME}.json`);
131
- await node_fs.default.promises.writeFile(themePath, `${JSON.stringify(DEFAULT_THEME, null, 2)}\n`, { mode: 384 });
132
- return themePath;
108
+ const { path, content } = defaultThemeFile(temporaryDirectory);
109
+ await node_fs.default.promises.writeFile(path, content, { mode: 384 });
110
+ return path;
111
+ }
112
+ //#endregion
113
+ //#region src/services/theme/index.ts
114
+ const AGENT_IDENTITY_COLORS = [
115
+ "accent",
116
+ "mdCode",
117
+ "toolDiffAdded",
118
+ "warning",
119
+ "mdHeading",
120
+ "syntaxNumber"
121
+ ];
122
+ function agentIdentityColorIndex(identity) {
123
+ let hash = 2166136261;
124
+ for (const character of identity) {
125
+ hash ^= character.charCodeAt(0);
126
+ hash = Math.imul(hash, 16777619);
127
+ }
128
+ return (hash >>> 0) % AGENT_IDENTITY_COLORS.length;
129
+ }
130
+ /** Stable semantic color shared by every UI surface that identifies an agent run. */
131
+ function agentIdentityColor(identity) {
132
+ return AGENT_IDENTITY_COLORS[agentIdentityColorIndex(identity)];
133
+ }
134
+ /**
135
+ * Prefer the identity's stable color, then walk the palette to avoid reusing a
136
+ * color already visible on the same surface. Once every color is occupied,
137
+ * reuse the stable preference rather than changing existing assignments.
138
+ */
139
+ function allocateAgentIdentityColor(identity, occupied) {
140
+ const preferredIndex = agentIdentityColorIndex(identity);
141
+ for (let offset = 0; offset < AGENT_IDENTITY_COLORS.length; offset++) {
142
+ const color = AGENT_IDENTITY_COLORS[(preferredIndex + offset) % AGENT_IDENTITY_COLORS.length];
143
+ if (!occupied.has(color)) return color;
144
+ }
145
+ return AGENT_IDENTITY_COLORS[preferredIndex];
146
+ }
147
+ /** Writes the default theme into `temporaryDirectory` through `fs`, readable by its owner only, and returns its path. */
148
+ async function writeDefaultThemeFile(fs, temporaryDirectory, context) {
149
+ const { path, content } = defaultThemeFile(temporaryDirectory);
150
+ (0, _agimon_ai_po_core_platform.getOrThrow)(await fs.writeFile(path, content, context));
151
+ await _agimon_ai_po_core_platform.nodeHost.setMode(path, 384);
152
+ return path;
133
153
  }
134
154
  //#endregion
135
155
  Object.defineProperty(exports, "DEFAULT_THEME", {
@@ -162,5 +182,11 @@ Object.defineProperty(exports, "writeDefaultTheme", {
162
182
  return writeDefaultTheme;
163
183
  }
164
184
  });
185
+ Object.defineProperty(exports, "writeDefaultThemeFile", {
186
+ enumerable: true,
187
+ get: function() {
188
+ return writeDefaultThemeFile;
189
+ }
190
+ });
165
191
 
166
- //# sourceMappingURL=theme-2wveit5V.cjs.map
192
+ //# sourceMappingURL=theme-BfC_GGQ4.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-BfC_GGQ4.cjs","names":["path","fs","nodeHost"],"sources":["../src/services/theme/defaultTheme.ts","../src/services/theme/sync.ts","../src/services/theme/index.ts"],"sourcesContent":["import path from 'node:path';\n\nexport const DEFAULT_THEME_NAME = 'po-dark';\n\n/** The theme file is readable by its owner only. */\nexport const DEFAULT_THEME_FILE_MODE = 0o600;\n\nexport const DEFAULT_THEME = {\n $schema:\n 'https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json',\n name: DEFAULT_THEME_NAME,\n // Po Jade's quiet ink surfaces and green identity. Syntax colors retain\n // their meaning instead of making every operation a brand accent.\n vars: {\n bg: '#1c1c1c',\n bgAlt: '#171717',\n bgActive: '#2b2b2b',\n bgHover: '#2b2b2b',\n fg: '#dedede',\n fgAlt: '#b0b0b0',\n grey: '#343434',\n greyAlt: '#555555',\n blue: '#8cb5cc',\n darkBlue: '#284b64',\n cyan: '#8fc8c7',\n green: '#81cca3',\n lightGreen: '#a5d9b5',\n teal: '#8ec1ab',\n orange: '#d3ad83',\n red: '#e99185',\n violet: '#b0a0ce',\n magenta: '#c19aae',\n yellow: '#d6be82',\n lightYellow: '#e1cf9e',\n comment: '#a4a4a4',\n // Recessed diff bands retain readable syntax and quiet foreground text.\n diffAddedBg: '#152d20',\n diffRemovedBg: '#35201b',\n },\n colors: {\n accent: 'green',\n border: 'greyAlt',\n borderAccent: 'green',\n borderMuted: 'grey',\n success: 'green',\n error: 'red',\n warning: 'yellow',\n muted: 'fgAlt',\n dim: 'comment',\n text: 'fg',\n thinkingText: 'fgAlt',\n\n selectedBg: 'bgHover',\n userMessageBg: 'bgActive',\n userMessageText: 'fg',\n customMessageBg: '#292c2a',\n customMessageText: 'fg',\n customMessageLabel: 'green',\n toolPendingBg: 'bgAlt',\n // Doubles as the added/removed band behind a diff row, so it stays a wash\n // rather than a fill: syntax highlighting has to remain legible on top.\n toolSuccessBg: 'diffAddedBg',\n toolErrorBg: 'diffRemovedBg',\n toolTitle: 'green',\n toolOutput: 'fg',\n\n mdHeading: 'magenta',\n mdLink: 'blue',\n mdLinkUrl: 'comment',\n mdCode: 'cyan',\n mdCodeBlock: 'lightYellow',\n mdCodeBlockBorder: 'greyAlt',\n mdQuote: 'fgAlt',\n mdQuoteBorder: 'greyAlt',\n mdHr: 'greyAlt',\n mdListBullet: 'green',\n\n toolDiffAdded: 'lightGreen',\n toolDiffRemoved: 'red',\n toolDiffContext: 'fgAlt',\n\n syntaxComment: 'comment',\n syntaxKeyword: 'blue',\n syntaxFunction: 'magenta',\n syntaxVariable: 'violet',\n syntaxString: 'green',\n syntaxNumber: 'orange',\n syntaxType: 'yellow',\n syntaxOperator: 'orange',\n syntaxPunctuation: 'fgAlt',\n\n // A rising ramp from quiet ink through the semantic syntax ladder.\n thinkingOff: 'grey',\n thinkingMinimal: 'fgAlt',\n thinkingLow: 'darkBlue',\n thinkingMedium: 'blue',\n thinkingHigh: 'teal',\n thinkingXhigh: 'magenta',\n thinkingMax: 'red',\n\n bashMode: 'lightGreen',\n },\n export: {\n pageBg: 'bg',\n cardBg: 'bgAlt',\n infoBg: '#3b3526',\n },\n} as const;\n\n/** Where the default theme goes in `temporaryDirectory`, and its file content. */\nexport function defaultThemeFile(temporaryDirectory: string): { path: string; content: string } {\n return {\n path: path.join(temporaryDirectory, `${DEFAULT_THEME_NAME}.json`),\n content: `${JSON.stringify(DEFAULT_THEME, null, 2)}\\n`,\n };\n}\n","import fs from 'node:fs';\n\nimport { DEFAULT_THEME_FILE_MODE, defaultThemeFile } from './defaultTheme';\n\n/** @deprecated Node-only sync shim; use writeDefaultThemeFile. Removed in M2. */\nexport async function writeDefaultTheme(temporaryDirectory: string): Promise<string> {\n const { path, content } = defaultThemeFile(temporaryDirectory);\n await fs.promises.writeFile(path, content, { mode: DEFAULT_THEME_FILE_MODE });\n return path;\n}\n","import type { FooterTextColor } from '@agimon-ai/po-core/footer';\nimport { type FileSystem, getOrThrow, nodeHost } from '@agimon-ai/po-core/platform';\n\nimport { DEFAULT_THEME_FILE_MODE, defaultThemeFile } from './defaultTheme';\n\nexport { DEFAULT_THEME, DEFAULT_THEME_NAME } from './defaultTheme';\nexport { writeDefaultTheme } from './sync';\n\nconst AGENT_IDENTITY_COLORS = [\n 'accent',\n 'mdCode',\n 'toolDiffAdded',\n 'warning',\n 'mdHeading',\n 'syntaxNumber',\n] as const satisfies readonly FooterTextColor[];\n\nfunction agentIdentityColorIndex(identity: string): number {\n let hash = 2_166_136_261;\n for (const character of identity) {\n hash ^= character.charCodeAt(0);\n hash = Math.imul(hash, 16_777_619);\n }\n return (hash >>> 0) % AGENT_IDENTITY_COLORS.length;\n}\n\n/** Stable semantic color shared by every UI surface that identifies an agent run. */\nexport function agentIdentityColor(identity: string): FooterTextColor {\n return AGENT_IDENTITY_COLORS[agentIdentityColorIndex(identity)]!;\n}\n\n/**\n * Prefer the identity's stable color, then walk the palette to avoid reusing a\n * color already visible on the same surface. Once every color is occupied,\n * reuse the stable preference rather than changing existing assignments.\n */\nexport function allocateAgentIdentityColor(identity: string, occupied: ReadonlySet<FooterTextColor>): FooterTextColor {\n const preferredIndex = agentIdentityColorIndex(identity);\n for (let offset = 0; offset < AGENT_IDENTITY_COLORS.length; offset++) {\n const color = AGENT_IDENTITY_COLORS[(preferredIndex + offset) % AGENT_IDENTITY_COLORS.length]!;\n if (!occupied.has(color)) return color;\n }\n return AGENT_IDENTITY_COLORS[preferredIndex]!;\n}\n\n/** Writes the default theme into `temporaryDirectory` through `fs`, readable by its owner only, and returns its path. */\nexport async function writeDefaultThemeFile(\n fs: FileSystem,\n temporaryDirectory: string,\n context: Parameters<FileSystem['writeFile']>[2],\n): Promise<string> {\n const { path, content } = defaultThemeFile(temporaryDirectory);\n getOrThrow(await fs.writeFile(path, content, context));\n await nodeHost.setMode(path, DEFAULT_THEME_FILE_MODE);\n return path;\n}\n"],"mappings":";;;;;;;AAEA,MAAa,qBAAqB;AAKlC,MAAa,gBAAgB;CAC3B,SACE;CACF,MAAM;CAGN,MAAM;EACJ,IAAI;EACJ,OAAO;EACP,UAAU;EACV,SAAS;EACT,IAAI;EACJ,OAAO;EACP,MAAM;EACN,SAAS;EACT,MAAM;EACN,UAAU;EACV,MAAM;EACN,OAAO;EACP,YAAY;EACZ,MAAM;EACN,QAAQ;EACR,KAAK;EACL,QAAQ;EACR,SAAS;EACT,QAAQ;EACR,aAAa;EACb,SAAS;EAET,aAAa;EACb,eAAe;CACjB;CACA,QAAQ;EACN,QAAQ;EACR,QAAQ;EACR,cAAc;EACd,aAAa;EACb,SAAS;EACT,OAAO;EACP,SAAS;EACT,OAAO;EACP,KAAK;EACL,MAAM;EACN,cAAc;EAEd,YAAY;EACZ,eAAe;EACf,iBAAiB;EACjB,iBAAiB;EACjB,mBAAmB;EACnB,oBAAoB;EACpB,eAAe;EAGf,eAAe;EACf,aAAa;EACb,WAAW;EACX,YAAY;EAEZ,WAAW;EACX,QAAQ;EACR,WAAW;EACX,QAAQ;EACR,aAAa;EACb,mBAAmB;EACnB,SAAS;EACT,eAAe;EACf,MAAM;EACN,cAAc;EAEd,eAAe;EACf,iBAAiB;EACjB,iBAAiB;EAEjB,eAAe;EACf,eAAe;EACf,gBAAgB;EAChB,gBAAgB;EAChB,cAAc;EACd,cAAc;EACd,YAAY;EACZ,gBAAgB;EAChB,mBAAmB;EAGnB,aAAa;EACb,iBAAiB;EACjB,aAAa;EACb,gBAAgB;EAChB,cAAc;EACd,eAAe;EACf,aAAa;EAEb,UAAU;CACZ;CACA,QAAQ;EACN,QAAQ;EACR,QAAQ;EACR,QAAQ;CACV;AACF;;AAGA,SAAgB,iBAAiB,oBAA+D;CAC9F,OAAO;EACL,MAAMA,UAAAA,QAAK,KAAK,oBAAoB,GAAG,mBAAmB,MAAM;EAChE,SAAS,GAAG,KAAK,UAAU,eAAe,MAAM,CAAC,EAAE;CACrD;AACF;;;;AC9GA,eAAsB,kBAAkB,oBAA6C;CACnF,MAAM,EAAE,MAAM,YAAY,iBAAiB,kBAAkB;CAC7D,MAAMC,QAAAA,QAAG,SAAS,UAAU,MAAM,SAAS,EAAE,MAAA,IAA8B,CAAC;CAC5E,OAAO;AACT;;;ACDA,MAAM,wBAAwB;CAC5B;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAS,wBAAwB,UAA0B;CACzD,IAAI,OAAO;CACX,KAAK,MAAM,aAAa,UAAU;EAChC,QAAQ,UAAU,WAAW,CAAC;EAC9B,OAAO,KAAK,KAAK,MAAM,QAAU;CACnC;CACA,QAAQ,SAAS,KAAK,sBAAsB;AAC9C;;AAGA,SAAgB,mBAAmB,UAAmC;CACpE,OAAO,sBAAsB,wBAAwB,QAAQ;AAC/D;;;;;;AAOA,SAAgB,2BAA2B,UAAkB,UAAyD;CACpH,MAAM,iBAAiB,wBAAwB,QAAQ;CACvD,KAAK,IAAI,SAAS,GAAG,SAAS,sBAAsB,QAAQ,UAAU;EACpE,MAAM,QAAQ,uBAAuB,iBAAiB,UAAU,sBAAsB;EACtF,IAAI,CAAC,SAAS,IAAI,KAAK,GAAG,OAAO;CACnC;CACA,OAAO,sBAAsB;AAC/B;;AAGA,eAAsB,sBACpB,IACA,oBACA,SACiB;CACjB,MAAM,EAAE,MAAM,YAAY,iBAAiB,kBAAkB;CAC7D,CAAA,GAAA,4BAAA,WAAA,CAAW,MAAM,GAAG,UAAU,MAAM,SAAS,OAAO,CAAC;CACrD,MAAMC,4BAAAA,SAAS,QAAQ,MAAA,GAA6B;CACpD,OAAO;AACT"}
package/dist/theme.cjs CHANGED
@@ -1,7 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_theme = require("./theme-2wveit5V.cjs");
2
+ const require_theme = require("./theme-BfC_GGQ4.cjs");
3
3
  exports.DEFAULT_THEME = require_theme.DEFAULT_THEME;
4
4
  exports.DEFAULT_THEME_NAME = require_theme.DEFAULT_THEME_NAME;
5
5
  exports.agentIdentityColor = require_theme.agentIdentityColor;
6
6
  exports.allocateAgentIdentityColor = require_theme.allocateAgentIdentityColor;
7
7
  exports.writeDefaultTheme = require_theme.writeDefaultTheme;
8
+ exports.writeDefaultThemeFile = require_theme.writeDefaultThemeFile;
package/dist/theme.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as writeDefaultTheme, i as allocateAgentIdentityColor, n as DEFAULT_THEME_NAME, r as agentIdentityColor, t as DEFAULT_THEME } from "./index-Dpzvl-vg.mjs";
2
- export { DEFAULT_THEME, DEFAULT_THEME_NAME, agentIdentityColor, allocateAgentIdentityColor, writeDefaultTheme };
1
+ import { a as DEFAULT_THEME, i as writeDefaultTheme, n as allocateAgentIdentityColor, o as DEFAULT_THEME_NAME, r as writeDefaultThemeFile, t as agentIdentityColor } from "./index-DFSkSBBh.mjs";
2
+ export { DEFAULT_THEME, DEFAULT_THEME_NAME, agentIdentityColor, allocateAgentIdentityColor, writeDefaultTheme, writeDefaultThemeFile };
package/dist/theme.mjs CHANGED
@@ -1,2 +1 @@
1
- import { a as writeDefaultTheme, i as allocateAgentIdentityColor, n as DEFAULT_THEME_NAME, r as agentIdentityColor, t as DEFAULT_THEME } from "./theme-Byj_dBlT.mjs";
2
- export { DEFAULT_THEME, DEFAULT_THEME_NAME, agentIdentityColor, allocateAgentIdentityColor, writeDefaultTheme };
1
+ export { a as DEFAULT_THEME, o as DEFAULT_THEME_NAME, t as agentIdentityColor, n as allocateAgentIdentityColor, i as writeDefaultTheme, r as writeDefaultThemeFile } from "./theme-BX_hfErv.mjs";
@@ -1,2 +1 @@
1
- import { buildToolSources, tokensForSource, tokensForTool } from "@agimon-ai/po-core/toolInventory";
2
- export { buildToolSources, tokensForSource, tokensForTool };
1
+ export { buildToolSources, tokensForSource, tokensForTool } from "@agimon-ai/po-core/toolInventory";
package/dist/uiState.mjs CHANGED
@@ -1,2 +1 @@
1
- import { n as projectMinorModeRecords, t as DoomUiState } from "./uiState-G_Pso-5i.mjs";
2
- export { DoomUiState, projectMinorModeRecords };
1
+ export { t as DoomUiState, n as projectMinorModeRecords } from "./uiState-G_Pso-5i.mjs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/po-ui",
3
- "version": "0.0.0-alpha.2",
3
+ "version": "0.0.0-alpha.3",
4
4
  "description": "Leader-key menus, themes, and TUI components for Po and Pi extensions.",
5
5
  "keywords": [
6
6
  "ai",
@@ -110,33 +110,33 @@
110
110
  "access": "public"
111
111
  },
112
112
  "dependencies": {
113
- "@agimon-ai/po-core": "0.0.0-alpha.2",
114
- "@agimon-ai/po-hashline": "0.0.0-alpha.2",
115
- "@agimon-ai/po-minor-mode": "0.0.0-alpha.2",
116
- "@agimon-ai/po-telemetry": "0.0.0-alpha.2",
117
- "@agimon-ai/po-web-components": "0.0.0-alpha.2",
113
+ "@agimon-ai/po-core": "0.0.0-alpha.3",
114
+ "@agimon-ai/po-hashline": "0.0.0-alpha.3",
115
+ "@agimon-ai/po-minor-mode": "0.0.0-alpha.3",
116
+ "@agimon-ai/po-telemetry": "0.0.0-alpha.3",
117
+ "@agimon-ai/po-web-components": "0.0.0-alpha.3",
118
118
  "@deepseek-ai/cordis": "4.0.4",
119
119
  "yaml": "2.9.1"
120
120
  },
121
121
  "devDependencies": {
122
- "@agimon-ai/po-build": "0.0.0-alpha.2",
123
- "@agimon-ai/po-core": "0.0.0-alpha.2",
124
- "@agimon-ai/po-web-components": "0.0.0-alpha.2",
122
+ "@agimon-ai/po-build": "0.0.0-alpha.3",
123
+ "@agimon-ai/po-core": "0.0.0-alpha.3",
124
+ "@agimon-ai/po-web-components": "0.0.0-alpha.3",
125
125
  "@earendil-works/pi-coding-agent": "1.2.0",
126
126
  "@tanstack/react-store": "0.11.2",
127
127
  "@tanstack/store": "0.11.2",
128
- "@types/node": "26.6.4",
128
+ "@types/node": "25.9.9",
129
129
  "@types/react": "19.3.0",
130
130
  "@vitest/coverage-v8": "5.0.3",
131
131
  "react": "19.3.0",
132
132
  "react-dom": "19.3.0",
133
- "tsdown": "0.23.0",
133
+ "tsdown": "0.23.1",
134
134
  "typescript": "7.0.2",
135
135
  "vitest": "5.0.3"
136
136
  },
137
137
  "peerDependencies": {
138
- "@agimon-ai/po-core": "0.0.0-alpha.2",
139
- "@agimon-ai/po-web-components": "0.0.0-alpha.2",
138
+ "@agimon-ai/po-core": "0.0.0-alpha.3",
139
+ "@agimon-ai/po-web-components": "0.0.0-alpha.3",
140
140
  "@earendil-works/pi-coding-agent": "1.2.0"
141
141
  },
142
142
  "peerDependenciesMeta": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-Dpzvl-vg.d.mts","names":[],"sources":["../src/services/theme/index.ts"],"mappings":";;cAKa;;iBAqBG,mBAAmB,mBAAmB;;;;;;iBAStC,2BAA2B,kBAAkB,UAAU,YAAY,mBAAmB;cASzF;WACX;WAEA;WAGA;aACE;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aAEA;aACA;;WAEF;aACE;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aAEA;aACA;aACA;aACA;aACA;aACA;aACA;aAGA;aACA;aACA;aACA;aAEA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aAEA;aACA;aACA;aAEA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aACA;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;aAEA;;WAEF;aACE;aACA;aACA;;;iBAIkB,kBAAkB,6BAA6B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"theme-2wveit5V.cjs","names":["path","fs"],"sources":["../src/services/theme/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { FooterTextColor } from '@agimon-ai/po-core/footer';\n\nexport const DEFAULT_THEME_NAME = 'po-dark';\n\nconst AGENT_IDENTITY_COLORS = [\n 'accent',\n 'mdCode',\n 'toolDiffAdded',\n 'warning',\n 'mdHeading',\n 'syntaxNumber',\n] as const satisfies readonly FooterTextColor[];\n\nfunction agentIdentityColorIndex(identity: string): number {\n let hash = 2_166_136_261;\n for (const character of identity) {\n hash ^= character.charCodeAt(0);\n hash = Math.imul(hash, 16_777_619);\n }\n return (hash >>> 0) % AGENT_IDENTITY_COLORS.length;\n}\n\n/** Stable semantic color shared by every UI surface that identifies an agent run. */\nexport function agentIdentityColor(identity: string): FooterTextColor {\n return AGENT_IDENTITY_COLORS[agentIdentityColorIndex(identity)]!;\n}\n\n/**\n * Prefer the identity's stable color, then walk the palette to avoid reusing a\n * color already visible on the same surface. Once every color is occupied,\n * reuse the stable preference rather than changing existing assignments.\n */\nexport function allocateAgentIdentityColor(identity: string, occupied: ReadonlySet<FooterTextColor>): FooterTextColor {\n const preferredIndex = agentIdentityColorIndex(identity);\n for (let offset = 0; offset < AGENT_IDENTITY_COLORS.length; offset++) {\n const color = AGENT_IDENTITY_COLORS[(preferredIndex + offset) % AGENT_IDENTITY_COLORS.length]!;\n if (!occupied.has(color)) return color;\n }\n return AGENT_IDENTITY_COLORS[preferredIndex]!;\n}\n\nexport const DEFAULT_THEME = {\n $schema:\n 'https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json',\n name: DEFAULT_THEME_NAME,\n // Po Jade's quiet ink surfaces and green identity. Syntax colors retain\n // their meaning instead of making every operation a brand accent.\n vars: {\n bg: '#1c1c1c',\n bgAlt: '#171717',\n bgActive: '#2b2b2b',\n bgHover: '#2b2b2b',\n fg: '#dedede',\n fgAlt: '#b0b0b0',\n grey: '#343434',\n greyAlt: '#555555',\n blue: '#8cb5cc',\n darkBlue: '#284b64',\n cyan: '#8fc8c7',\n green: '#81cca3',\n lightGreen: '#a5d9b5',\n teal: '#8ec1ab',\n orange: '#d3ad83',\n red: '#e99185',\n violet: '#b0a0ce',\n magenta: '#c19aae',\n yellow: '#d6be82',\n lightYellow: '#e1cf9e',\n comment: '#a4a4a4',\n // Recessed diff bands retain readable syntax and quiet foreground text.\n diffAddedBg: '#152d20',\n diffRemovedBg: '#35201b',\n },\n colors: {\n accent: 'green',\n border: 'greyAlt',\n borderAccent: 'green',\n borderMuted: 'grey',\n success: 'green',\n error: 'red',\n warning: 'yellow',\n muted: 'fgAlt',\n dim: 'comment',\n text: 'fg',\n thinkingText: 'fgAlt',\n\n selectedBg: 'bgHover',\n userMessageBg: 'bgActive',\n userMessageText: 'fg',\n customMessageBg: '#292c2a',\n customMessageText: 'fg',\n customMessageLabel: 'green',\n toolPendingBg: 'bgAlt',\n // Doubles as the added/removed band behind a diff row, so it stays a wash\n // rather than a fill: syntax highlighting has to remain legible on top.\n toolSuccessBg: 'diffAddedBg',\n toolErrorBg: 'diffRemovedBg',\n toolTitle: 'green',\n toolOutput: 'fg',\n\n mdHeading: 'magenta',\n mdLink: 'blue',\n mdLinkUrl: 'comment',\n mdCode: 'cyan',\n mdCodeBlock: 'lightYellow',\n mdCodeBlockBorder: 'greyAlt',\n mdQuote: 'fgAlt',\n mdQuoteBorder: 'greyAlt',\n mdHr: 'greyAlt',\n mdListBullet: 'green',\n\n toolDiffAdded: 'lightGreen',\n toolDiffRemoved: 'red',\n toolDiffContext: 'fgAlt',\n\n syntaxComment: 'comment',\n syntaxKeyword: 'blue',\n syntaxFunction: 'magenta',\n syntaxVariable: 'violet',\n syntaxString: 'green',\n syntaxNumber: 'orange',\n syntaxType: 'yellow',\n syntaxOperator: 'orange',\n syntaxPunctuation: 'fgAlt',\n\n // A rising ramp from quiet ink through the semantic syntax ladder.\n thinkingOff: 'grey',\n thinkingMinimal: 'fgAlt',\n thinkingLow: 'darkBlue',\n thinkingMedium: 'blue',\n thinkingHigh: 'teal',\n thinkingXhigh: 'magenta',\n thinkingMax: 'red',\n\n bashMode: 'lightGreen',\n },\n export: {\n pageBg: 'bg',\n cardBg: 'bgAlt',\n infoBg: '#3b3526',\n },\n} as const;\n\nexport async function writeDefaultTheme(temporaryDirectory: string): Promise<string> {\n const themePath = path.join(temporaryDirectory, `${DEFAULT_THEME_NAME}.json`);\n await fs.promises.writeFile(themePath, `${JSON.stringify(DEFAULT_THEME, null, 2)}\\n`, { mode: 0o600 });\n return themePath;\n}\n"],"mappings":";;;;;;AAKA,MAAa,qBAAqB;AAElC,MAAM,wBAAwB;CAC5B;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAS,wBAAwB,UAA0B;CACzD,IAAI,OAAO;CACX,KAAK,MAAM,aAAa,UAAU;EAChC,QAAQ,UAAU,WAAW,CAAC;EAC9B,OAAO,KAAK,KAAK,MAAM,QAAU;CACnC;CACA,QAAQ,SAAS,KAAK,sBAAsB;AAC9C;;AAGA,SAAgB,mBAAmB,UAAmC;CACpE,OAAO,sBAAsB,wBAAwB,QAAQ;AAC/D;;;;;;AAOA,SAAgB,2BAA2B,UAAkB,UAAyD;CACpH,MAAM,iBAAiB,wBAAwB,QAAQ;CACvD,KAAK,IAAI,SAAS,GAAG,SAAS,sBAAsB,QAAQ,UAAU;EACpE,MAAM,QAAQ,uBAAuB,iBAAiB,UAAU,sBAAsB;EACtF,IAAI,CAAC,SAAS,IAAI,KAAK,GAAG,OAAO;CACnC;CACA,OAAO,sBAAsB;AAC/B;AAEA,MAAa,gBAAgB;CAC3B,SACE;CACF,MAAM;CAGN,MAAM;EACJ,IAAI;EACJ,OAAO;EACP,UAAU;EACV,SAAS;EACT,IAAI;EACJ,OAAO;EACP,MAAM;EACN,SAAS;EACT,MAAM;EACN,UAAU;EACV,MAAM;EACN,OAAO;EACP,YAAY;EACZ,MAAM;EACN,QAAQ;EACR,KAAK;EACL,QAAQ;EACR,SAAS;EACT,QAAQ;EACR,aAAa;EACb,SAAS;EAET,aAAa;EACb,eAAe;CACjB;CACA,QAAQ;EACN,QAAQ;EACR,QAAQ;EACR,cAAc;EACd,aAAa;EACb,SAAS;EACT,OAAO;EACP,SAAS;EACT,OAAO;EACP,KAAK;EACL,MAAM;EACN,cAAc;EAEd,YAAY;EACZ,eAAe;EACf,iBAAiB;EACjB,iBAAiB;EACjB,mBAAmB;EACnB,oBAAoB;EACpB,eAAe;EAGf,eAAe;EACf,aAAa;EACb,WAAW;EACX,YAAY;EAEZ,WAAW;EACX,QAAQ;EACR,WAAW;EACX,QAAQ;EACR,aAAa;EACb,mBAAmB;EACnB,SAAS;EACT,eAAe;EACf,MAAM;EACN,cAAc;EAEd,eAAe;EACf,iBAAiB;EACjB,iBAAiB;EAEjB,eAAe;EACf,eAAe;EACf,gBAAgB;EAChB,gBAAgB;EAChB,cAAc;EACd,cAAc;EACd,YAAY;EACZ,gBAAgB;EAChB,mBAAmB;EAGnB,aAAa;EACb,iBAAiB;EACjB,aAAa;EACb,gBAAgB;EAChB,cAAc;EACd,eAAe;EACf,aAAa;EAEb,UAAU;CACZ;CACA,QAAQ;EACN,QAAQ;EACR,QAAQ;EACR,QAAQ;CACV;AACF;AAEA,eAAsB,kBAAkB,oBAA6C;CACnF,MAAM,YAAYA,UAAAA,QAAK,KAAK,oBAAoB,GAAG,mBAAmB,MAAM;CAC5E,MAAMC,QAAAA,QAAG,SAAS,UAAU,WAAW,GAAG,KAAK,UAAU,eAAe,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,IAAM,CAAC;CACrG,OAAO;AACT"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"theme-Byj_dBlT.mjs","names":[],"sources":["../src/services/theme/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { FooterTextColor } from '@agimon-ai/po-core/footer';\n\nexport const DEFAULT_THEME_NAME = 'po-dark';\n\nconst AGENT_IDENTITY_COLORS = [\n 'accent',\n 'mdCode',\n 'toolDiffAdded',\n 'warning',\n 'mdHeading',\n 'syntaxNumber',\n] as const satisfies readonly FooterTextColor[];\n\nfunction agentIdentityColorIndex(identity: string): number {\n let hash = 2_166_136_261;\n for (const character of identity) {\n hash ^= character.charCodeAt(0);\n hash = Math.imul(hash, 16_777_619);\n }\n return (hash >>> 0) % AGENT_IDENTITY_COLORS.length;\n}\n\n/** Stable semantic color shared by every UI surface that identifies an agent run. */\nexport function agentIdentityColor(identity: string): FooterTextColor {\n return AGENT_IDENTITY_COLORS[agentIdentityColorIndex(identity)]!;\n}\n\n/**\n * Prefer the identity's stable color, then walk the palette to avoid reusing a\n * color already visible on the same surface. Once every color is occupied,\n * reuse the stable preference rather than changing existing assignments.\n */\nexport function allocateAgentIdentityColor(identity: string, occupied: ReadonlySet<FooterTextColor>): FooterTextColor {\n const preferredIndex = agentIdentityColorIndex(identity);\n for (let offset = 0; offset < AGENT_IDENTITY_COLORS.length; offset++) {\n const color = AGENT_IDENTITY_COLORS[(preferredIndex + offset) % AGENT_IDENTITY_COLORS.length]!;\n if (!occupied.has(color)) return color;\n }\n return AGENT_IDENTITY_COLORS[preferredIndex]!;\n}\n\nexport const DEFAULT_THEME = {\n $schema:\n 'https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json',\n name: DEFAULT_THEME_NAME,\n // Po Jade's quiet ink surfaces and green identity. Syntax colors retain\n // their meaning instead of making every operation a brand accent.\n vars: {\n bg: '#1c1c1c',\n bgAlt: '#171717',\n bgActive: '#2b2b2b',\n bgHover: '#2b2b2b',\n fg: '#dedede',\n fgAlt: '#b0b0b0',\n grey: '#343434',\n greyAlt: '#555555',\n blue: '#8cb5cc',\n darkBlue: '#284b64',\n cyan: '#8fc8c7',\n green: '#81cca3',\n lightGreen: '#a5d9b5',\n teal: '#8ec1ab',\n orange: '#d3ad83',\n red: '#e99185',\n violet: '#b0a0ce',\n magenta: '#c19aae',\n yellow: '#d6be82',\n lightYellow: '#e1cf9e',\n comment: '#a4a4a4',\n // Recessed diff bands retain readable syntax and quiet foreground text.\n diffAddedBg: '#152d20',\n diffRemovedBg: '#35201b',\n },\n colors: {\n accent: 'green',\n border: 'greyAlt',\n borderAccent: 'green',\n borderMuted: 'grey',\n success: 'green',\n error: 'red',\n warning: 'yellow',\n muted: 'fgAlt',\n dim: 'comment',\n text: 'fg',\n thinkingText: 'fgAlt',\n\n selectedBg: 'bgHover',\n userMessageBg: 'bgActive',\n userMessageText: 'fg',\n customMessageBg: '#292c2a',\n customMessageText: 'fg',\n customMessageLabel: 'green',\n toolPendingBg: 'bgAlt',\n // Doubles as the added/removed band behind a diff row, so it stays a wash\n // rather than a fill: syntax highlighting has to remain legible on top.\n toolSuccessBg: 'diffAddedBg',\n toolErrorBg: 'diffRemovedBg',\n toolTitle: 'green',\n toolOutput: 'fg',\n\n mdHeading: 'magenta',\n mdLink: 'blue',\n mdLinkUrl: 'comment',\n mdCode: 'cyan',\n mdCodeBlock: 'lightYellow',\n mdCodeBlockBorder: 'greyAlt',\n mdQuote: 'fgAlt',\n mdQuoteBorder: 'greyAlt',\n mdHr: 'greyAlt',\n mdListBullet: 'green',\n\n toolDiffAdded: 'lightGreen',\n toolDiffRemoved: 'red',\n toolDiffContext: 'fgAlt',\n\n syntaxComment: 'comment',\n syntaxKeyword: 'blue',\n syntaxFunction: 'magenta',\n syntaxVariable: 'violet',\n syntaxString: 'green',\n syntaxNumber: 'orange',\n syntaxType: 'yellow',\n syntaxOperator: 'orange',\n syntaxPunctuation: 'fgAlt',\n\n // A rising ramp from quiet ink through the semantic syntax ladder.\n thinkingOff: 'grey',\n thinkingMinimal: 'fgAlt',\n thinkingLow: 'darkBlue',\n thinkingMedium: 'blue',\n thinkingHigh: 'teal',\n thinkingXhigh: 'magenta',\n thinkingMax: 'red',\n\n bashMode: 'lightGreen',\n },\n export: {\n pageBg: 'bg',\n cardBg: 'bgAlt',\n infoBg: '#3b3526',\n },\n} as const;\n\nexport async function writeDefaultTheme(temporaryDirectory: string): Promise<string> {\n const themePath = path.join(temporaryDirectory, `${DEFAULT_THEME_NAME}.json`);\n await fs.promises.writeFile(themePath, `${JSON.stringify(DEFAULT_THEME, null, 2)}\\n`, { mode: 0o600 });\n return themePath;\n}\n"],"mappings":";;;AAKA,MAAa,qBAAqB;AAElC,MAAM,wBAAwB;CAC5B;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAS,wBAAwB,UAA0B;CACzD,IAAI,OAAO;CACX,KAAK,MAAM,aAAa,UAAU;EAChC,QAAQ,UAAU,WAAW,CAAC;EAC9B,OAAO,KAAK,KAAK,MAAM,QAAU;CACnC;CACA,QAAQ,SAAS,KAAK,sBAAsB;AAC9C;;AAGA,SAAgB,mBAAmB,UAAmC;CACpE,OAAO,sBAAsB,wBAAwB,QAAQ;AAC/D;;;;;;AAOA,SAAgB,2BAA2B,UAAkB,UAAyD;CACpH,MAAM,iBAAiB,wBAAwB,QAAQ;CACvD,KAAK,IAAI,SAAS,GAAG,SAAS,sBAAsB,QAAQ,UAAU;EACpE,MAAM,QAAQ,uBAAuB,iBAAiB,UAAU,sBAAsB;EACtF,IAAI,CAAC,SAAS,IAAI,KAAK,GAAG,OAAO;CACnC;CACA,OAAO,sBAAsB;AAC/B;AAEA,MAAa,gBAAgB;CAC3B,SACE;CACF,MAAM;CAGN,MAAM;EACJ,IAAI;EACJ,OAAO;EACP,UAAU;EACV,SAAS;EACT,IAAI;EACJ,OAAO;EACP,MAAM;EACN,SAAS;EACT,MAAM;EACN,UAAU;EACV,MAAM;EACN,OAAO;EACP,YAAY;EACZ,MAAM;EACN,QAAQ;EACR,KAAK;EACL,QAAQ;EACR,SAAS;EACT,QAAQ;EACR,aAAa;EACb,SAAS;EAET,aAAa;EACb,eAAe;CACjB;CACA,QAAQ;EACN,QAAQ;EACR,QAAQ;EACR,cAAc;EACd,aAAa;EACb,SAAS;EACT,OAAO;EACP,SAAS;EACT,OAAO;EACP,KAAK;EACL,MAAM;EACN,cAAc;EAEd,YAAY;EACZ,eAAe;EACf,iBAAiB;EACjB,iBAAiB;EACjB,mBAAmB;EACnB,oBAAoB;EACpB,eAAe;EAGf,eAAe;EACf,aAAa;EACb,WAAW;EACX,YAAY;EAEZ,WAAW;EACX,QAAQ;EACR,WAAW;EACX,QAAQ;EACR,aAAa;EACb,mBAAmB;EACnB,SAAS;EACT,eAAe;EACf,MAAM;EACN,cAAc;EAEd,eAAe;EACf,iBAAiB;EACjB,iBAAiB;EAEjB,eAAe;EACf,eAAe;EACf,gBAAgB;EAChB,gBAAgB;EAChB,cAAc;EACd,cAAc;EACd,YAAY;EACZ,gBAAgB;EAChB,mBAAmB;EAGnB,aAAa;EACb,iBAAiB;EACjB,aAAa;EACb,gBAAgB;EAChB,cAAc;EACd,eAAe;EACf,aAAa;EAEb,UAAU;CACZ;CACA,QAAQ;EACN,QAAQ;EACR,QAAQ;EACR,QAAQ;CACV;AACF;AAEA,eAAsB,kBAAkB,oBAA6C;CACnF,MAAM,YAAY,KAAK,KAAK,oBAAoB,GAAG,mBAAmB,MAAM;CAC5E,MAAM,GAAG,SAAS,UAAU,WAAW,GAAG,KAAK,UAAU,eAAe,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,IAAM,CAAC;CACrG,OAAO;AACT"}