aibroker 0.2.6 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +164 -4
- package/dist/adapters/iterm/core.d.ts +2 -0
- package/dist/adapters/iterm/core.d.ts.map +1 -1
- package/dist/adapters/iterm/core.js +13 -5
- package/dist/adapters/iterm/core.js.map +1 -1
- package/dist/adapters/iterm/iterm2-api.d.ts +20 -0
- package/dist/adapters/iterm/iterm2-api.d.ts.map +1 -0
- package/dist/adapters/iterm/iterm2-api.js +244 -0
- package/dist/adapters/iterm/iterm2-api.js.map +1 -0
- package/dist/adapters/iterm/sessions.d.ts.map +1 -1
- package/dist/adapters/iterm/sessions.js +3 -2
- package/dist/adapters/iterm/sessions.js.map +1 -1
- package/dist/adapters/kokoro/media.d.ts +2 -1
- package/dist/adapters/kokoro/media.d.ts.map +1 -1
- package/dist/adapters/kokoro/media.js +53 -5
- package/dist/adapters/kokoro/media.js.map +1 -1
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-13-56).d.ts +49 -0
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-13-56).d.ts.map +1 -0
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-13-56).js +632 -0
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-13-56).js.map +1 -0
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-13-59).js +632 -0
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-15-36).d.ts +49 -0
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-15-36).d.ts.map +1 -0
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-15-36).js +614 -0
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-15-36).js.map +1 -0
- package/dist/adapters/pailot/gateway (SFConflict mnott 2026-03-06-21-15-46).js +614 -0
- package/dist/adapters/pailot/gateway.d.ts +48 -0
- package/dist/adapters/pailot/gateway.d.ts (SFConflict mnott 2026-03-06-21-13-59).map +1 -0
- package/dist/adapters/pailot/gateway.d.ts (SFConflict mnott 2026-03-06-21-15-46).map +1 -0
- package/dist/adapters/pailot/gateway.d.ts.map +1 -0
- package/dist/adapters/pailot/gateway.js +828 -0
- package/dist/adapters/pailot/gateway.js (SFConflict mnott 2026-03-06-21-13-59).map +1 -0
- package/dist/adapters/pailot/gateway.js (SFConflict mnott 2026-03-06-21-15-46).map +1 -0
- package/dist/adapters/pailot/gateway.js.map +1 -0
- package/dist/backend/api.d.ts +5 -1
- package/dist/backend/api.d.ts.map +1 -1
- package/dist/backend/api.js +74 -3
- package/dist/backend/api.js.map +1 -1
- package/dist/core/hybrid.d.ts +7 -0
- package/dist/core/hybrid.d.ts.map +1 -1
- package/dist/core/hybrid.js +33 -0
- package/dist/core/hybrid.js.map +1 -1
- package/dist/core/state.d.ts +3 -0
- package/dist/core/state.d.ts.map +1 -1
- package/dist/core/state.js +4 -0
- package/dist/core/state.js.map +1 -1
- package/dist/core/status-cache.d.ts +51 -0
- package/dist/core/status-cache.d.ts.map +1 -0
- package/dist/core/status-cache.js +62 -0
- package/dist/core/status-cache.js.map +1 -0
- package/dist/daemon/adapter-registry (SFConflict mnott 2026-03-06-21-15-36).d.ts +63 -0
- package/dist/daemon/adapter-registry (SFConflict mnott 2026-03-06-21-15-36).d.ts.map +1 -0
- package/dist/daemon/adapter-registry (SFConflict mnott 2026-03-06-21-15-36).js +229 -0
- package/dist/daemon/adapter-registry (SFConflict mnott 2026-03-06-21-15-36).js.map +1 -0
- package/dist/daemon/adapter-registry.d.ts +63 -0
- package/dist/daemon/adapter-registry.d.ts.map +1 -0
- package/dist/daemon/adapter-registry.js +240 -0
- package/dist/daemon/adapter-registry.js.map +1 -0
- package/dist/daemon/cli.d.ts +14 -0
- package/dist/daemon/cli.d.ts.map +1 -0
- package/dist/daemon/cli.js +150 -0
- package/dist/daemon/cli.js.map +1 -0
- package/dist/daemon/command-context.d.ts +24 -0
- package/dist/daemon/command-context.d.ts.map +1 -0
- package/dist/daemon/command-context.js +13 -0
- package/dist/daemon/command-context.js.map +1 -0
- package/dist/daemon/commands.d.ts +22 -0
- package/dist/daemon/commands.d.ts.map +1 -0
- package/dist/daemon/commands.js +632 -0
- package/dist/daemon/commands.js.map +1 -0
- package/dist/daemon/core-handlers.d.ts +24 -0
- package/dist/daemon/core-handlers.d.ts.map +1 -0
- package/dist/daemon/core-handlers.js +640 -0
- package/dist/daemon/core-handlers.js.map +1 -0
- package/dist/daemon/create-adapter.d.ts +22 -0
- package/dist/daemon/create-adapter.d.ts.map +1 -0
- package/dist/daemon/create-adapter.js +153 -0
- package/dist/daemon/create-adapter.js.map +1 -0
- package/dist/daemon/image-gen.d.ts +28 -0
- package/dist/daemon/image-gen.d.ts.map +1 -0
- package/dist/daemon/image-gen.js +97 -0
- package/dist/daemon/image-gen.js.map +1 -0
- package/dist/daemon/index.d.ts +12 -0
- package/dist/daemon/index.d.ts.map +1 -0
- package/dist/daemon/index.js +184 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/pai-projects.d.ts +68 -0
- package/dist/daemon/pai-projects.d.ts.map +1 -0
- package/dist/daemon/pai-projects.js +174 -0
- package/dist/daemon/pai-projects.js.map +1 -0
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-13-56).d.ts +12 -0
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-13-56).d.ts.map +1 -0
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-13-56).js +252 -0
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-13-56).js.map +1 -0
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-13-59).js +252 -0
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-15-36).d.ts +12 -0
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-15-36).d.ts.map +1 -0
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-15-36).js +240 -0
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-15-36).js.map +1 -0
- package/dist/daemon/screenshot (SFConflict mnott 2026-03-06-21-15-46).js +240 -0
- package/dist/daemon/screenshot.d.ts +12 -0
- package/dist/daemon/screenshot.d.ts (SFConflict mnott 2026-03-06-21-13-59).map +1 -0
- package/dist/daemon/screenshot.d.ts (SFConflict mnott 2026-03-06-21-15-46).map +1 -0
- package/dist/daemon/screenshot.d.ts.map +1 -0
- package/dist/daemon/screenshot.js +252 -0
- package/dist/daemon/screenshot.js (SFConflict mnott 2026-03-06-21-13-59).map +1 -0
- package/dist/daemon/screenshot.js (SFConflict mnott 2026-03-06-21-15-46).map +1 -0
- package/dist/daemon/screenshot.js.map +1 -0
- package/dist/daemon/session-content.d.ts +27 -0
- package/dist/daemon/session-content.d.ts.map +1 -0
- package/dist/daemon/session-content.js +76 -0
- package/dist/daemon/session-content.js.map +1 -0
- package/dist/daemon/vision.d.ts +46 -0
- package/dist/daemon/vision.d.ts.map +1 -0
- package/dist/daemon/vision.js +176 -0
- package/dist/daemon/vision.js.map +1 -0
- package/dist/index.d.ts +16 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/ipc/client.d.ts +4 -1
- package/dist/ipc/client.d.ts.map +1 -1
- package/dist/ipc/client.js +10 -1
- package/dist/ipc/client.js.map +1 -1
- package/dist/ipc/validate.d.ts +52 -0
- package/dist/ipc/validate.d.ts.map +1 -0
- package/dist/ipc/validate.js +129 -0
- package/dist/ipc/validate.js.map +1 -0
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-13-56).d.ts +23 -0
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-13-56).d.ts.map +1 -0
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-13-56).js +595 -0
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-13-56).js.map +1 -0
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-13-59).js +595 -0
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-15-36).d.ts +23 -0
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-15-36).d.ts.map +1 -0
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-15-36).js +592 -0
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-15-36).js.map +1 -0
- package/dist/mcp/index (SFConflict mnott 2026-03-06-21-15-46).js +592 -0
- package/dist/mcp/index.d.ts +23 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +660 -0
- package/dist/mcp/index.js (SFConflict mnott 2026-03-06-21-13-59).map +1 -0
- package/dist/mcp/index.js (SFConflict mnott 2026-03-06-21-15-46).map +1 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/types/adapter.d.ts +41 -0
- package/dist/types/adapter.d.ts.map +1 -0
- package/dist/types/adapter.js +2 -0
- package/dist/types/adapter.js.map +1 -0
- package/dist/types/backend.d.ts +29 -1
- package/dist/types/backend.d.ts.map +1 -1
- package/dist/types/broker.d.ts +47 -0
- package/dist/types/broker.d.ts.map +1 -0
- package/dist/types/broker.js +21 -0
- package/dist/types/broker.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/package.json +12 -2
- package/templates/adapter/ONBOARDING_PROMPT.md +309 -0
- package/templates/adapter/README.md.tmpl +81 -0
- package/templates/adapter/package.json.tmpl +23 -0
- package/templates/adapter/src/watcher/cli.ts.tmpl +12 -0
- package/templates/adapter/src/watcher/commands.ts.tmpl +44 -0
- package/templates/adapter/src/watcher/connection.ts.tmpl +59 -0
- package/templates/adapter/src/watcher/index.ts.tmpl +201 -0
- package/templates/adapter/src/watcher/ipc-server.ts.tmpl +250 -0
- package/templates/adapter/src/watcher/send.ts.tmpl +62 -0
- package/templates/adapter/src/watcher/state.ts.tmpl +39 -0
- package/templates/adapter/tsconfig.json.tmpl +14 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* daemon/pai-projects.ts — PAI named session integration.
|
|
3
|
+
*
|
|
4
|
+
* Shells out to the `pai` CLI to list and launch named Claude project sessions.
|
|
5
|
+
* Results are cached for 30 seconds to avoid hammering the CLI on every request.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* const projects = await listPaiProjects();
|
|
9
|
+
* const project = await findPaiProject("whazaa");
|
|
10
|
+
* const { pid, sessionId } = await launchPaiProject("whazaa");
|
|
11
|
+
*/
|
|
12
|
+
export interface PaiProject {
|
|
13
|
+
name: string;
|
|
14
|
+
names: string[];
|
|
15
|
+
slug: string;
|
|
16
|
+
displayName: string;
|
|
17
|
+
rootPath: string;
|
|
18
|
+
sessionCount: number;
|
|
19
|
+
lastActive: string;
|
|
20
|
+
sessionConfig?: {
|
|
21
|
+
permission?: string;
|
|
22
|
+
flags?: string;
|
|
23
|
+
env?: Record<string, string>;
|
|
24
|
+
autoStart?: boolean;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Invalidate the project list cache (e.g. after launching a project). */
|
|
28
|
+
export declare function invalidatePaiProjectCache(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Return all named PAI projects.
|
|
31
|
+
* Results are cached for 30 seconds.
|
|
32
|
+
*/
|
|
33
|
+
export declare function listPaiProjects(): Promise<PaiProject[]>;
|
|
34
|
+
/**
|
|
35
|
+
* Find a project by any of its names or aliases.
|
|
36
|
+
* Matching is case-insensitive.
|
|
37
|
+
*/
|
|
38
|
+
export declare function findPaiProject(name: string): Promise<PaiProject | undefined>;
|
|
39
|
+
/**
|
|
40
|
+
* Get the effective (merged) config for a PAI project.
|
|
41
|
+
*
|
|
42
|
+
* Calls `pai project config <name> --json` which returns project config,
|
|
43
|
+
* global defaults, and the merged effective config. We use `effective`
|
|
44
|
+
* because it respects the resolution order: project overrides globals.
|
|
45
|
+
*/
|
|
46
|
+
export declare function getEffectiveConfig(name: string): Promise<{
|
|
47
|
+
permission?: string;
|
|
48
|
+
flags?: string;
|
|
49
|
+
env?: Record<string, string>;
|
|
50
|
+
autoStart?: boolean;
|
|
51
|
+
} | undefined>;
|
|
52
|
+
/**
|
|
53
|
+
* Launch Claude in the named project's directory as a visual iTerm2 tab.
|
|
54
|
+
*
|
|
55
|
+
* Uses `pai project config <name> --json` to get the effective (merged)
|
|
56
|
+
* config, then builds a shell command that:
|
|
57
|
+
* 1. cd's to the project directory
|
|
58
|
+
* 2. Exports any env vars from the config
|
|
59
|
+
* 3. Runs `claude` with the configured flags
|
|
60
|
+
*
|
|
61
|
+
* Opens a new iTerm2 tab via AppleScript and types the command into it.
|
|
62
|
+
* Returns the iTerm2 session ID for registration with HybridSessionManager.
|
|
63
|
+
*/
|
|
64
|
+
export declare function launchPaiProject(name: string): Promise<{
|
|
65
|
+
itermSessionId: string;
|
|
66
|
+
sessionId: string;
|
|
67
|
+
}>;
|
|
68
|
+
//# sourceMappingURL=pai-projects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pai-projects.d.ts","sourceRoot":"","sources":["../../src/daemon/pai-projects.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE;QACd,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,CAAC;CACH;AAiBD,0EAA0E;AAC1E,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD;AA8DD;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAS7D;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CASlF;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GAAG,SAAS,CAAC,CAWb;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAqCxD"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* daemon/pai-projects.ts — PAI named session integration.
|
|
3
|
+
*
|
|
4
|
+
* Shells out to the `pai` CLI to list and launch named Claude project sessions.
|
|
5
|
+
* Results are cached for 30 seconds to avoid hammering the CLI on every request.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* const projects = await listPaiProjects();
|
|
9
|
+
* const project = await findPaiProject("whazaa");
|
|
10
|
+
* const { pid, sessionId } = await launchPaiProject("whazaa");
|
|
11
|
+
*/
|
|
12
|
+
import { execFile } from "node:child_process";
|
|
13
|
+
import { promisify } from "node:util";
|
|
14
|
+
import { log } from "../core/log.js";
|
|
15
|
+
import { createClaudeSession } from "../adapters/iterm/sessions.js";
|
|
16
|
+
const execFileAsync = promisify(execFile);
|
|
17
|
+
const CACHE_TTL_MS = 30_000;
|
|
18
|
+
let _cache = null;
|
|
19
|
+
function isCacheValid() {
|
|
20
|
+
if (!_cache)
|
|
21
|
+
return false;
|
|
22
|
+
return Date.now() - _cache.fetchedAt < CACHE_TTL_MS;
|
|
23
|
+
}
|
|
24
|
+
/** Invalidate the project list cache (e.g. after launching a project). */
|
|
25
|
+
export function invalidatePaiProjectCache() {
|
|
26
|
+
_cache = null;
|
|
27
|
+
}
|
|
28
|
+
// ── Raw CLI call ──
|
|
29
|
+
/** Call `pai project names --json` and parse the JSON output. */
|
|
30
|
+
async function fetchFromCli() {
|
|
31
|
+
try {
|
|
32
|
+
const { stdout } = await execFileAsync("pai", ["project", "names", "--json"], {
|
|
33
|
+
timeout: 5_000,
|
|
34
|
+
env: { ...process.env },
|
|
35
|
+
});
|
|
36
|
+
const raw = JSON.parse(stdout.trim());
|
|
37
|
+
if (!Array.isArray(raw)) {
|
|
38
|
+
log("pai-projects: unexpected output shape (not array)");
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
return raw.map((item) => ({
|
|
42
|
+
name: String(item.name ?? ""),
|
|
43
|
+
names: Array.isArray(item.names) ? item.names.map(String) : [String(item.name ?? "")],
|
|
44
|
+
slug: String(item.slug ?? ""),
|
|
45
|
+
displayName: String(item.display_name ?? item.name ?? ""),
|
|
46
|
+
rootPath: String(item.root_path ?? ""),
|
|
47
|
+
sessionCount: typeof item.session_count === "number" ? item.session_count : 0,
|
|
48
|
+
lastActive: String(item.last_active ?? ""),
|
|
49
|
+
sessionConfig: item.session_config
|
|
50
|
+
? {
|
|
51
|
+
permission: typeof item.session_config.permission === "string"
|
|
52
|
+
? item.session_config.permission
|
|
53
|
+
: undefined,
|
|
54
|
+
flags: typeof item.session_config.flags === "string"
|
|
55
|
+
? item.session_config.flags
|
|
56
|
+
: undefined,
|
|
57
|
+
env: item.session_config.env != null &&
|
|
58
|
+
typeof item.session_config.env === "object"
|
|
59
|
+
? item.session_config.env
|
|
60
|
+
: undefined,
|
|
61
|
+
autoStart: typeof item.session_config.autoStart === "boolean"
|
|
62
|
+
? item.session_config.autoStart
|
|
63
|
+
: undefined,
|
|
64
|
+
}
|
|
65
|
+
: undefined,
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
70
|
+
// pai not installed, no projects, or timeout — all non-fatal
|
|
71
|
+
if (msg.includes("ENOENT")) {
|
|
72
|
+
log("pai-projects: `pai` binary not found — returning empty project list");
|
|
73
|
+
}
|
|
74
|
+
else if (msg.includes("ETIMEDOUT") || msg.includes("timed out")) {
|
|
75
|
+
log("pai-projects: `pai project names --json` timed out");
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
log(`pai-projects: CLI error — ${msg}`);
|
|
79
|
+
}
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// ── Public API ──
|
|
84
|
+
/**
|
|
85
|
+
* Return all named PAI projects.
|
|
86
|
+
* Results are cached for 30 seconds.
|
|
87
|
+
*/
|
|
88
|
+
export async function listPaiProjects() {
|
|
89
|
+
if (isCacheValid()) {
|
|
90
|
+
return _cache.projects;
|
|
91
|
+
}
|
|
92
|
+
const projects = await fetchFromCli();
|
|
93
|
+
_cache = { projects, fetchedAt: Date.now() };
|
|
94
|
+
log(`pai-projects: loaded ${projects.length} project(s)`);
|
|
95
|
+
return projects;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Find a project by any of its names or aliases.
|
|
99
|
+
* Matching is case-insensitive.
|
|
100
|
+
*/
|
|
101
|
+
export async function findPaiProject(name) {
|
|
102
|
+
const projects = await listPaiProjects();
|
|
103
|
+
const needle = name.toLowerCase();
|
|
104
|
+
return projects.find((p) => p.name.toLowerCase() === needle ||
|
|
105
|
+
p.names.some((n) => n.toLowerCase() === needle) ||
|
|
106
|
+
p.slug.toLowerCase() === needle);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get the effective (merged) config for a PAI project.
|
|
110
|
+
*
|
|
111
|
+
* Calls `pai project config <name> --json` which returns project config,
|
|
112
|
+
* global defaults, and the merged effective config. We use `effective`
|
|
113
|
+
* because it respects the resolution order: project overrides globals.
|
|
114
|
+
*/
|
|
115
|
+
export async function getEffectiveConfig(name) {
|
|
116
|
+
try {
|
|
117
|
+
const { stdout } = await execFileAsync("pai", ["project", "config", name, "--json"], {
|
|
118
|
+
timeout: 5_000,
|
|
119
|
+
env: { ...process.env },
|
|
120
|
+
});
|
|
121
|
+
const data = JSON.parse(stdout.trim());
|
|
122
|
+
return data.effective ?? undefined;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Launch Claude in the named project's directory as a visual iTerm2 tab.
|
|
130
|
+
*
|
|
131
|
+
* Uses `pai project config <name> --json` to get the effective (merged)
|
|
132
|
+
* config, then builds a shell command that:
|
|
133
|
+
* 1. cd's to the project directory
|
|
134
|
+
* 2. Exports any env vars from the config
|
|
135
|
+
* 3. Runs `claude` with the configured flags
|
|
136
|
+
*
|
|
137
|
+
* Opens a new iTerm2 tab via AppleScript and types the command into it.
|
|
138
|
+
* Returns the iTerm2 session ID for registration with HybridSessionManager.
|
|
139
|
+
*/
|
|
140
|
+
export async function launchPaiProject(name) {
|
|
141
|
+
const project = await findPaiProject(name);
|
|
142
|
+
if (!project) {
|
|
143
|
+
throw new Error(`PAI project "${name}" not found`);
|
|
144
|
+
}
|
|
145
|
+
// Get effective config (project overrides global defaults)
|
|
146
|
+
const effective = await getEffectiveConfig(name) ?? project.sessionConfig ?? {};
|
|
147
|
+
const flags = effective.flags ?? "";
|
|
148
|
+
const env = effective.env ?? {};
|
|
149
|
+
// Build the shell command: export envs, cd, run claude
|
|
150
|
+
const parts = [];
|
|
151
|
+
for (const [key, value] of Object.entries(env)) {
|
|
152
|
+
parts.push(`export ${key}=${shellEscape(value)}`);
|
|
153
|
+
}
|
|
154
|
+
parts.push(`cd ${shellEscape(project.rootPath)}`);
|
|
155
|
+
parts.push(`claude ${flags}`.trim());
|
|
156
|
+
const command = parts.join(" && ");
|
|
157
|
+
const sessionId = `pai-${project.slug}-${Date.now()}`;
|
|
158
|
+
log(`pai-projects: launching visual session for "${project.name}" ` +
|
|
159
|
+
`in "${project.rootPath}" (command: ${command})`);
|
|
160
|
+
// Open new iTerm2 tab and run the command
|
|
161
|
+
const itermSessionId = createClaudeSession(command);
|
|
162
|
+
if (!itermSessionId) {
|
|
163
|
+
throw new Error(`Failed to create iTerm2 tab for project "${name}"`);
|
|
164
|
+
}
|
|
165
|
+
log(`pai-projects: opened iTerm2 session ${itermSessionId} for project "${project.name}"`);
|
|
166
|
+
return { itermSessionId, sessionId };
|
|
167
|
+
}
|
|
168
|
+
/** Escape a string for safe use in a shell command. */
|
|
169
|
+
function shellEscape(s) {
|
|
170
|
+
if (/^[a-zA-Z0-9_./:=-]+$/.test(s))
|
|
171
|
+
return s;
|
|
172
|
+
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=pai-projects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pai-projects.js","sourceRoot":"","sources":["../../src/daemon/pai-projects.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* daemon/screenshot.ts — Screenshot capture for the AIBroker hub.
|
|
3
|
+
*
|
|
4
|
+
* Captures the iTerm2 window containing the active session and sends
|
|
5
|
+
* it back through the CommandContext reply channel. Handles screen-lock
|
|
6
|
+
* detection with text fallback.
|
|
7
|
+
*
|
|
8
|
+
* Extracted from Whazaa's screenshot.ts — now transport-agnostic.
|
|
9
|
+
*/
|
|
10
|
+
import type { CommandContext } from "./command-context.js";
|
|
11
|
+
export declare function handleScreenshot(ctx: CommandContext): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=screenshot%20(SFConflict%20mnott%202026-03-06-21-13-56).d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot (SFConflict mnott 2026-03-06-21-13-56).d.ts","sourceRoot":"","sources":["../../src/daemon/screenshot (SFConflict mnott 2026-03-06-21-13-56).ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAqBH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AA2G3D,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAmJzE"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* daemon/screenshot.ts — Screenshot capture for the AIBroker hub.
|
|
3
|
+
*
|
|
4
|
+
* Captures the iTerm2 window containing the active session and sends
|
|
5
|
+
* it back through the CommandContext reply channel. Handles screen-lock
|
|
6
|
+
* detection with text fallback.
|
|
7
|
+
*
|
|
8
|
+
* Extracted from Whazaa's screenshot.ts — now transport-agnostic.
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync, unlinkSync } from "node:fs";
|
|
11
|
+
import { tmpdir } from "node:os";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { spawnSync, execSync } from "node:child_process";
|
|
14
|
+
import { runAppleScript, stripItermPrefix, } from "../adapters/iterm/core.js";
|
|
15
|
+
import { listClaudeSessions } from "../adapters/iterm/sessions.js";
|
|
16
|
+
import { log } from "../core/log.js";
|
|
17
|
+
import { activeClientId, activeItermSessionId, setActiveItermSessionId, sessionRegistry, } from "../core/state.js";
|
|
18
|
+
import { broadcastImage, broadcastText } from "../adapters/pailot/gateway.js";
|
|
19
|
+
let lastScreenshotContent = null;
|
|
20
|
+
function getActiveSessionContent() {
|
|
21
|
+
const activeEntry = activeClientId ? sessionRegistry.get(activeClientId) : undefined;
|
|
22
|
+
const itermId = stripItermPrefix((activeItermSessionId || undefined) ?? activeEntry?.itermSessionId);
|
|
23
|
+
if (!itermId)
|
|
24
|
+
return null;
|
|
25
|
+
const result = spawnSync("osascript", [], {
|
|
26
|
+
input: `tell application "iTerm2"
|
|
27
|
+
repeat with w in windows
|
|
28
|
+
repeat with t in tabs of w
|
|
29
|
+
repeat with s in sessions of t
|
|
30
|
+
if id of s is "${itermId}" then
|
|
31
|
+
return contents of s
|
|
32
|
+
end if
|
|
33
|
+
end repeat
|
|
34
|
+
end repeat
|
|
35
|
+
end repeat
|
|
36
|
+
return ""
|
|
37
|
+
end tell`,
|
|
38
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
39
|
+
timeout: 10_000,
|
|
40
|
+
});
|
|
41
|
+
if (result.status !== 0 || result.signal)
|
|
42
|
+
return null;
|
|
43
|
+
const stdout = result.stdout?.toString().trim() ?? "";
|
|
44
|
+
return stdout || null;
|
|
45
|
+
}
|
|
46
|
+
async function handleTextScreenshot(ctx) {
|
|
47
|
+
try {
|
|
48
|
+
const candidates = [];
|
|
49
|
+
const activeEntry = activeClientId ? sessionRegistry.get(activeClientId) : undefined;
|
|
50
|
+
const primaryId = stripItermPrefix((activeItermSessionId || undefined) ?? activeEntry?.itermSessionId);
|
|
51
|
+
if (primaryId)
|
|
52
|
+
candidates.push({ id: primaryId, source: "active" });
|
|
53
|
+
const registryEntries = [...sessionRegistry.values()]
|
|
54
|
+
.sort((a, b) => b.registeredAt - a.registeredAt);
|
|
55
|
+
for (const entry of registryEntries) {
|
|
56
|
+
const rid = stripItermPrefix(entry.itermSessionId);
|
|
57
|
+
if (rid && !candidates.some((c) => c.id === rid)) {
|
|
58
|
+
candidates.push({ id: rid, source: `registry:${entry.name}` });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (candidates.length === 0) {
|
|
62
|
+
await ctx.reply("Screen is locked and no iTerm2 session found — cannot capture.");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
for (const candidate of candidates) {
|
|
66
|
+
const script = `tell application "iTerm2"
|
|
67
|
+
repeat with w in windows
|
|
68
|
+
repeat with t in tabs of w
|
|
69
|
+
repeat with s in sessions of t
|
|
70
|
+
if id of s is "${candidate.id}" then
|
|
71
|
+
return contents of s
|
|
72
|
+
end if
|
|
73
|
+
end repeat
|
|
74
|
+
end repeat
|
|
75
|
+
end repeat
|
|
76
|
+
return "::NOT_FOUND::"
|
|
77
|
+
end tell`;
|
|
78
|
+
const result = spawnSync("osascript", [], {
|
|
79
|
+
input: script,
|
|
80
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
81
|
+
timeout: 10_000,
|
|
82
|
+
});
|
|
83
|
+
const stdout = result.stdout?.toString().trim() ?? "";
|
|
84
|
+
if (result.signal === "SIGTERM" || result.status !== 0 || stdout === "::NOT_FOUND::" || stdout === "")
|
|
85
|
+
continue;
|
|
86
|
+
lastScreenshotContent = stdout;
|
|
87
|
+
// Send to PAILot (skip if the request came from PAILot — ctx.reply handles it)
|
|
88
|
+
if (ctx.source !== "pailot") {
|
|
89
|
+
const cleaned = stdout
|
|
90
|
+
.split("\n")
|
|
91
|
+
.filter((line) => !/^[─━═┄┈╌╍┅┉]{3,}\s*$/.test(line.trim()))
|
|
92
|
+
.filter((line) => line.trim() !== "")
|
|
93
|
+
.slice(-50)
|
|
94
|
+
.join("\n");
|
|
95
|
+
broadcastText(`Terminal capture (screen locked):\n\n${cleaned}`);
|
|
96
|
+
}
|
|
97
|
+
// Send to originating adapter
|
|
98
|
+
const maxLen = 4000;
|
|
99
|
+
const trimmed = stdout.length > maxLen ? "...\n" + stdout.slice(-maxLen) : stdout;
|
|
100
|
+
await ctx.reply(`*Terminal capture (screen locked):*\n\n\`\`\`\n${trimmed}\n\`\`\``);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
await ctx.reply(`Screen is locked — tried ${candidates.length} session(s) but none returned buffer content.`);
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
107
|
+
log(`/ss: text capture error — ${msg}`);
|
|
108
|
+
await ctx.reply(`Screen is locked — text capture failed: ${msg}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export async function handleScreenshot(ctx) {
|
|
112
|
+
// Check if content is unchanged
|
|
113
|
+
const currentContent = getActiveSessionContent();
|
|
114
|
+
if (currentContent && lastScreenshotContent) {
|
|
115
|
+
const tail = (s) => s.split("\n").slice(-100).join("\n").trim();
|
|
116
|
+
if (tail(currentContent) === tail(lastScreenshotContent)) {
|
|
117
|
+
const lines = currentContent
|
|
118
|
+
.split("\n")
|
|
119
|
+
.filter((l) => !/^[─━═┄┈╌╍┅┉]{3,}\s*$/.test(l.trim()))
|
|
120
|
+
.filter((l) => l.trim() !== "")
|
|
121
|
+
.slice(-30)
|
|
122
|
+
.join("\n");
|
|
123
|
+
if (lines) {
|
|
124
|
+
if (ctx.source !== "pailot")
|
|
125
|
+
broadcastText(lines);
|
|
126
|
+
await ctx.reply(`*Terminal (unchanged):*\n\n\`\`\`\n${lines}\n\`\`\``);
|
|
127
|
+
log("/ss: content unchanged, sent tail as text");
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
lastScreenshotContent = currentContent;
|
|
133
|
+
// Check screen lock
|
|
134
|
+
try {
|
|
135
|
+
const lockCheck = spawnSync("sh", ["-c", "ioreg -n Root -d1 -a | grep -c CGSSessionScreenIsLocked"], { timeout: 5_000, encoding: "utf8" });
|
|
136
|
+
if (parseInt((lockCheck.stdout ?? "0").trim(), 10) > 0) {
|
|
137
|
+
log("/ss: screen is locked — falling back to terminal text capture");
|
|
138
|
+
await handleTextScreenshot(ctx);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch { /* proceed */ }
|
|
143
|
+
await ctx.reply("Capturing screenshot...");
|
|
144
|
+
const filePath = join(tmpdir(), `aibroker-screenshot-${Date.now()}.png`);
|
|
145
|
+
try {
|
|
146
|
+
// Resolve the window
|
|
147
|
+
let windowId;
|
|
148
|
+
const activeEntry = activeClientId ? sessionRegistry.get(activeClientId) : undefined;
|
|
149
|
+
let itermSessionId = stripItermPrefix((activeItermSessionId || undefined) ?? activeEntry?.itermSessionId);
|
|
150
|
+
if (!itermSessionId) {
|
|
151
|
+
const registryEntries = [...sessionRegistry.values()]
|
|
152
|
+
.sort((a, b) => b.registeredAt - a.registeredAt);
|
|
153
|
+
const newest = registryEntries.find(e => e.itermSessionId);
|
|
154
|
+
if (newest?.itermSessionId) {
|
|
155
|
+
itermSessionId = stripItermPrefix(newest.itermSessionId);
|
|
156
|
+
setActiveItermSessionId(itermSessionId);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (!itermSessionId) {
|
|
160
|
+
const liveSessions = listClaudeSessions();
|
|
161
|
+
if (liveSessions.length > 0) {
|
|
162
|
+
itermSessionId = liveSessions[0].id;
|
|
163
|
+
setActiveItermSessionId(liveSessions[0].id);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (itermSessionId) {
|
|
167
|
+
const findAndRaiseScript = `tell application "iTerm2"
|
|
168
|
+
repeat with w in windows
|
|
169
|
+
set tabCount to count of tabs of w
|
|
170
|
+
repeat with tabIdx from 1 to tabCount
|
|
171
|
+
set t to tab tabIdx of w
|
|
172
|
+
repeat with s in sessions of t
|
|
173
|
+
if id of s is "${itermSessionId}" then
|
|
174
|
+
select t
|
|
175
|
+
set index of w to 1
|
|
176
|
+
activate
|
|
177
|
+
return (id of w as text)
|
|
178
|
+
end if
|
|
179
|
+
end repeat
|
|
180
|
+
end repeat
|
|
181
|
+
end repeat
|
|
182
|
+
return ""
|
|
183
|
+
end tell`;
|
|
184
|
+
const findResult = runAppleScript(findAndRaiseScript);
|
|
185
|
+
if (findResult && findResult !== "") {
|
|
186
|
+
windowId = findResult.trim();
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
runAppleScript('tell application "iTerm2" to activate');
|
|
190
|
+
const fb = runAppleScript(`tell application "iTerm2"\n set w to window 1\n activate\n return (id of w as text)\nend tell`) ?? "";
|
|
191
|
+
windowId = fb.trim();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
runAppleScript('tell application "iTerm2" to activate');
|
|
196
|
+
const fb = runAppleScript(`tell application "iTerm2"\n set w to window 1\n activate\n return (id of w as text)\nend tell`) ?? "";
|
|
197
|
+
windowId = fb.trim();
|
|
198
|
+
}
|
|
199
|
+
if (!windowId) {
|
|
200
|
+
await ctx.reply("Error: Could not get iTerm2 window ID.");
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
204
|
+
const boundsScript = `tell application "iTerm2"
|
|
205
|
+
repeat with w in windows
|
|
206
|
+
if (id of w as text) is "${windowId}" then
|
|
207
|
+
set wBounds to bounds of w
|
|
208
|
+
set wx to item 1 of wBounds
|
|
209
|
+
set wy to item 2 of wBounds
|
|
210
|
+
set wx2 to item 3 of wBounds
|
|
211
|
+
set wy2 to item 4 of wBounds
|
|
212
|
+
return (wx as text) & "," & (wy as text) & "," & ((wx2 - wx) as text) & "," & ((wy2 - wy) as text)
|
|
213
|
+
end if
|
|
214
|
+
end repeat
|
|
215
|
+
return ""
|
|
216
|
+
end tell`;
|
|
217
|
+
const boundsResult = runAppleScript(boundsScript) ?? "";
|
|
218
|
+
const bounds = boundsResult.trim();
|
|
219
|
+
if (!bounds || !bounds.includes(",")) {
|
|
220
|
+
throw new Error("Could not get window bounds from iTerm2");
|
|
221
|
+
}
|
|
222
|
+
log(`/ss: capturing screen region ${bounds} (iTerm2 window ${windowId})`);
|
|
223
|
+
execSync(`/usr/sbin/screencapture -x -R ${bounds} "${filePath}"`, { timeout: 15_000 });
|
|
224
|
+
const buffer = readFileSync(filePath);
|
|
225
|
+
// Send to PAILot WebSocket clients (skip if request came from PAILot)
|
|
226
|
+
if (ctx.source !== "pailot")
|
|
227
|
+
broadcastImage(buffer, "Screenshot");
|
|
228
|
+
// Send to originating adapter
|
|
229
|
+
await ctx.replyImage(buffer, "Screenshot");
|
|
230
|
+
log("/ss: screenshot sent");
|
|
231
|
+
}
|
|
232
|
+
catch (err) {
|
|
233
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
234
|
+
log(`/ss: screencapture failed — ${msg}`);
|
|
235
|
+
// If screencapture failed (e.g. screen locked but ioreg didn't detect it,
|
|
236
|
+
// or "could not create image from rect"), fall back to text mode
|
|
237
|
+
log("/ss: falling back to terminal text capture");
|
|
238
|
+
try {
|
|
239
|
+
unlinkSync(filePath);
|
|
240
|
+
}
|
|
241
|
+
catch { /* ignore */ }
|
|
242
|
+
await handleTextScreenshot(ctx);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
finally {
|
|
246
|
+
try {
|
|
247
|
+
unlinkSync(filePath);
|
|
248
|
+
}
|
|
249
|
+
catch { /* ignore */ }
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=screenshot%20(SFConflict%20mnott%202026-03-06-21-13-56).js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot (SFConflict mnott 2026-03-06-21-13-56).js","sourceRoot":"","sources":["../../src/daemon/screenshot (SFConflict mnott 2026-03-06-21-13-56).ts"],"names":[],"mappings":"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"}
|