ikarmic-forge 0.0.0-stage → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +62 -2
- package/dist/acp/server.d.ts +55 -0
- package/dist/acp/server.d.ts.map +1 -0
- package/dist/acp/server.js +276 -0
- package/dist/acp/server.js.map +1 -0
- package/dist/app.d.ts +22 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +159 -0
- package/dist/app.js.map +1 -0
- package/dist/bin/forge.d.ts +3 -0
- package/dist/bin/forge.d.ts.map +1 -0
- package/dist/bin/forge.js +786 -0
- package/dist/bin/forge.js.map +1 -0
- package/dist/chat-files.d.ts +45 -0
- package/dist/chat-files.d.ts.map +1 -0
- package/dist/chat-files.js +189 -0
- package/dist/chat-files.js.map +1 -0
- package/dist/clipboard.d.ts +38 -0
- package/dist/clipboard.d.ts.map +1 -0
- package/dist/clipboard.js +63 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/commands/acp.d.ts +4 -0
- package/dist/commands/acp.d.ts.map +1 -0
- package/dist/commands/acp.js +36 -0
- package/dist/commands/acp.js.map +1 -0
- package/dist/commands/ai-comments.d.ts +9 -0
- package/dist/commands/ai-comments.d.ts.map +1 -0
- package/dist/commands/ai-comments.js +43 -0
- package/dist/commands/ai-comments.js.map +1 -0
- package/dist/commands/architect.d.ts +9 -0
- package/dist/commands/architect.d.ts.map +1 -0
- package/dist/commands/architect.js +27 -0
- package/dist/commands/architect.js.map +1 -0
- package/dist/commands/checkpoint.d.ts +10 -0
- package/dist/commands/checkpoint.d.ts.map +1 -0
- package/dist/commands/checkpoint.js +168 -0
- package/dist/commands/checkpoint.js.map +1 -0
- package/dist/commands/config.d.ts +15 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +180 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/diff.d.ts +29 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +90 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/hook.d.ts +10 -0
- package/dist/commands/hook.d.ts.map +1 -0
- package/dist/commands/hook.js +121 -0
- package/dist/commands/hook.js.map +1 -0
- package/dist/commands/mcp.d.ts +10 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +110 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/memory.d.ts +10 -0
- package/dist/commands/memory.d.ts.map +1 -0
- package/dist/commands/memory.js +77 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/commands/orchestrator.d.ts +22 -0
- package/dist/commands/orchestrator.d.ts.map +1 -0
- package/dist/commands/orchestrator.js +113 -0
- package/dist/commands/orchestrator.js.map +1 -0
- package/dist/commands/plugin.d.ts +3 -0
- package/dist/commands/plugin.d.ts.map +1 -0
- package/dist/commands/plugin.js +62 -0
- package/dist/commands/plugin.js.map +1 -0
- package/dist/commands/policy.d.ts +2 -0
- package/dist/commands/policy.d.ts.map +1 -0
- package/dist/commands/policy.js +21 -0
- package/dist/commands/policy.js.map +1 -0
- package/dist/commands/skill.d.ts +13 -0
- package/dist/commands/skill.d.ts.map +1 -0
- package/dist/commands/skill.js +194 -0
- package/dist/commands/skill.js.map +1 -0
- package/dist/commands/spec.d.ts +23 -0
- package/dist/commands/spec.d.ts.map +1 -0
- package/dist/commands/spec.js +147 -0
- package/dist/commands/spec.js.map +1 -0
- package/dist/commands/watch.d.ts +15 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +83 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/commands/worktree.d.ts +22 -0
- package/dist/commands/worktree.d.ts.map +1 -0
- package/dist/commands/worktree.js +187 -0
- package/dist/commands/worktree.js.map +1 -0
- package/dist/components/Approval.d.ts +9 -0
- package/dist/components/Approval.d.ts.map +1 -0
- package/dist/components/Approval.js +39 -0
- package/dist/components/Approval.js.map +1 -0
- package/dist/components/Footer.d.ts +22 -0
- package/dist/components/Footer.d.ts.map +1 -0
- package/dist/components/Footer.js +59 -0
- package/dist/components/Footer.js.map +1 -0
- package/dist/components/Header.d.ts +11 -0
- package/dist/components/Header.d.ts.map +1 -0
- package/dist/components/Header.js +23 -0
- package/dist/components/Header.js.map +1 -0
- package/dist/components/Spinner.d.ts +3 -0
- package/dist/components/Spinner.d.ts.map +1 -0
- package/dist/components/Spinner.js +8 -0
- package/dist/components/Spinner.js.map +1 -0
- package/dist/components/Stream.d.ts +10 -0
- package/dist/components/Stream.d.ts.map +1 -0
- package/dist/components/Stream.js +13 -0
- package/dist/components/Stream.js.map +1 -0
- package/dist/components/ToolEvent.d.ts +13 -0
- package/dist/components/ToolEvent.d.ts.map +1 -0
- package/dist/components/ToolEvent.js +54 -0
- package/dist/components/ToolEvent.js.map +1 -0
- package/dist/credential-store.d.ts +8 -0
- package/dist/credential-store.d.ts.map +1 -0
- package/dist/credential-store.js +37 -0
- package/dist/credential-store.js.map +1 -0
- package/dist/git-workflow.d.ts +16 -0
- package/dist/git-workflow.d.ts.map +1 -0
- package/dist/git-workflow.js +38 -0
- package/dist/git-workflow.js.map +1 -0
- package/dist/mcp-loader.d.ts +25 -0
- package/dist/mcp-loader.d.ts.map +1 -0
- package/dist/mcp-loader.js +99 -0
- package/dist/mcp-loader.js.map +1 -0
- package/dist/notify.d.ts +12 -0
- package/dist/notify.d.ts.map +1 -0
- package/dist/notify.js +47 -0
- package/dist/notify.js.map +1 -0
- package/dist/options.d.ts +449 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +871 -0
- package/dist/options.js.map +1 -0
- package/dist/repl-commands.d.ts +92 -0
- package/dist/repl-commands.d.ts.map +1 -0
- package/dist/repl-commands.js +228 -0
- package/dist/repl-commands.js.map +1 -0
- package/dist/repl-extras.d.ts +39 -0
- package/dist/repl-extras.d.ts.map +1 -0
- package/dist/repl-extras.js +120 -0
- package/dist/repl-extras.js.map +1 -0
- package/dist/repl.d.ts +76 -0
- package/dist/repl.d.ts.map +1 -0
- package/dist/repl.js +1507 -0
- package/dist/repl.js.map +1 -0
- package/dist/runner.d.ts +64 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +61 -0
- package/dist/runner.js.map +1 -0
- package/dist/session-checkpoints.d.ts +6 -0
- package/dist/session-checkpoints.d.ts.map +1 -0
- package/dist/session-checkpoints.js +25 -0
- package/dist/session-checkpoints.js.map +1 -0
- package/dist/specialists-loader.d.ts +22 -0
- package/dist/specialists-loader.d.ts.map +1 -0
- package/dist/specialists-loader.js +38 -0
- package/dist/specialists-loader.js.map +1 -0
- package/dist/tool-display.d.ts +19 -0
- package/dist/tool-display.d.ts.map +1 -0
- package/dist/tool-display.js +57 -0
- package/dist/tool-display.js.map +1 -0
- package/package.json +70 -3
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `--auto-commit`: commit the user's dirty work before a run, then what the
|
|
3
|
+
* agent changed after it, with a message drafted by the cheap model (or the
|
|
4
|
+
* main one). Always a no-op outside a git repo.
|
|
5
|
+
*/
|
|
6
|
+
import { afterRun, beforeRun, isGitRepo, loadForgeConfigFile, resolveModelAlias } from '@ikarmic/forge-core';
|
|
7
|
+
export function gitCommitOptions(options) {
|
|
8
|
+
return { attribute: !options.noAttribute, verify: options.gitCommitVerify };
|
|
9
|
+
}
|
|
10
|
+
/** Commit messages use the cheap model when one is configured, else the main model. */
|
|
11
|
+
export async function resolveCommitModel(options, model) {
|
|
12
|
+
if (!options.cheapModel)
|
|
13
|
+
return model;
|
|
14
|
+
const { config } = await loadForgeConfigFile();
|
|
15
|
+
return { ...model, ...resolveModelAlias(options.cheapModel, config.aliases, model.provider) };
|
|
16
|
+
}
|
|
17
|
+
export async function createGitWorkflow(options, cwd, model) {
|
|
18
|
+
if (!options.autoCommit || options.dryRun || !(await isGitRepo(cwd)))
|
|
19
|
+
return null;
|
|
20
|
+
const commitModel = await resolveCommitModel(options, model);
|
|
21
|
+
const commitOptions = gitCommitOptions(options);
|
|
22
|
+
let leftDirty = [];
|
|
23
|
+
return {
|
|
24
|
+
async before() {
|
|
25
|
+
const state = await beforeRun(cwd, { ...commitOptions, dirtyCommits: !options.noDirtyCommits });
|
|
26
|
+
leftDirty = state.leftDirty;
|
|
27
|
+
return state.dirtyCommit;
|
|
28
|
+
},
|
|
29
|
+
after(task) {
|
|
30
|
+
return afterRun(cwd, { leftDirty }, { ...commitOptions, model: commitModel, task });
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function formatCommitLine(commit) {
|
|
35
|
+
const first = commit.message.split('\n')[0] ?? '';
|
|
36
|
+
return `committed ${commit.commit.slice(0, 7)} ${first} (${commit.files.length} file${commit.files.length === 1 ? '' : 's'})`;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=git-workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-workflow.js","sourceRoot":"","sources":["../src/git-workflow.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAW7G,MAAM,UAAU,gBAAgB,CAAC,OAA4D;IAC3F,OAAO,EAAE,SAAS,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,eAAe,EAAE,CAAC;AAC9E,CAAC;AAED,uFAAuF;AACvF,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAuC,EAAE,KAAkB;IAClG,IAAI,CAAC,OAAO,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IACtC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAC/C,OAAO,EAAE,GAAG,KAAK,EAAE,GAAG,iBAAiB,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;AAChG,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAoI,EACpI,GAAW,EACX,KAAkB;IAElB,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAClF,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC7D,MAAM,aAAa,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAChD,IAAI,SAAS,GAAa,EAAE,CAAC;IAC7B,OAAO;QACL,KAAK,CAAC,MAAM;YACV,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,EAAE,GAAG,aAAa,EAAE,YAAY,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;YAChG,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;YAC5B,OAAO,KAAK,CAAC,WAAW,CAAC;QAC3B,CAAC;QACD,KAAK,CAAC,IAAI;YACR,OAAO,QAAQ,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,GAAG,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;QACtF,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAmB;IAClD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAClD,OAAO,aAAa,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,KAAK,MAAM,CAAC,KAAK,CAAC,MAAM,QAAQ,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AAChI,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ConnectedMcpServer, type ToolDefinition } from '@ikarmic/forge-core';
|
|
2
|
+
/**
|
|
3
|
+
* Load MCP servers from one or more config files and return their
|
|
4
|
+
* tools plus a cleanup handle the caller MUST invoke (e.g. on shutdown
|
|
5
|
+
* / task finish).
|
|
6
|
+
*
|
|
7
|
+
* Sources are merged in priority order:
|
|
8
|
+
*
|
|
9
|
+
* 1. `configPath`: explicit `--mcp-config <path>` from the CLI. Takes
|
|
10
|
+
* precedence when the same server name appears in multiple sources.
|
|
11
|
+
* 2. `~/.forge/mcp.json`: the user's marketplace registry. Servers
|
|
12
|
+
* installed via `forge mcp install` live here and are loaded
|
|
13
|
+
* automatically on every run.
|
|
14
|
+
*
|
|
15
|
+
* If both paths are the same file (or one is missing), they're handled
|
|
16
|
+
* without double-loading. If a path doesn't exist or MCP loading fails
|
|
17
|
+
* for any reason, the loader returns empty tools + a no-op cleanup and
|
|
18
|
+
* logs the error: MCP is an optional enhancement, not a hard dependency.
|
|
19
|
+
*/
|
|
20
|
+
export declare function loadMcpTools(configPath: string): Promise<{
|
|
21
|
+
tools: ToolDefinition[];
|
|
22
|
+
cleanup: () => Promise<void>;
|
|
23
|
+
servers: ConnectedMcpServer[];
|
|
24
|
+
}>;
|
|
25
|
+
//# sourceMappingURL=mcp-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-loader.d.ts","sourceRoot":"","sources":["../src/mcp-loader.ts"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,kBAAkB,EAEvB,KAAK,cAAc,EACpB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,KAAK,EAAE,cAAc,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,OAAO,EAAE,kBAAkB,EAAE,CAAA;CAAE,CAAC,CAgEnG"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import process from 'node:process';
|
|
2
|
+
import { closeAll, connectAll, defaultUserMcpPath, loadPluginMcpServers, loadMcpConfig, } from '@ikarmic/forge-core';
|
|
3
|
+
/**
|
|
4
|
+
* Load MCP servers from one or more config files and return their
|
|
5
|
+
* tools plus a cleanup handle the caller MUST invoke (e.g. on shutdown
|
|
6
|
+
* / task finish).
|
|
7
|
+
*
|
|
8
|
+
* Sources are merged in priority order:
|
|
9
|
+
*
|
|
10
|
+
* 1. `configPath`: explicit `--mcp-config <path>` from the CLI. Takes
|
|
11
|
+
* precedence when the same server name appears in multiple sources.
|
|
12
|
+
* 2. `~/.forge/mcp.json`: the user's marketplace registry. Servers
|
|
13
|
+
* installed via `forge mcp install` live here and are loaded
|
|
14
|
+
* automatically on every run.
|
|
15
|
+
*
|
|
16
|
+
* If both paths are the same file (or one is missing), they're handled
|
|
17
|
+
* without double-loading. If a path doesn't exist or MCP loading fails
|
|
18
|
+
* for any reason, the loader returns empty tools + a no-op cleanup and
|
|
19
|
+
* logs the error: MCP is an optional enhancement, not a hard dependency.
|
|
20
|
+
*/
|
|
21
|
+
export async function loadMcpTools(configPath) {
|
|
22
|
+
const userMcpPath = defaultUserMcpPath();
|
|
23
|
+
// Merge the two sources. Explicit config wins on name conflicts.
|
|
24
|
+
let merged = { mcpServers: {} };
|
|
25
|
+
const sourcesLoaded = [];
|
|
26
|
+
// 0. Servers shipped by global plugins (lowest priority).
|
|
27
|
+
const pluginServers = await loadPluginMcpServers(process.cwd()).catch(() => ({}));
|
|
28
|
+
if (Object.keys(pluginServers).length > 0) {
|
|
29
|
+
merged = mergeMcpConfigs(merged, { mcpServers: pluginServers });
|
|
30
|
+
sourcesLoaded.push('plugins');
|
|
31
|
+
}
|
|
32
|
+
// 1. User-level registry (overrides plugins).
|
|
33
|
+
if (userMcpPath !== configPath) {
|
|
34
|
+
try {
|
|
35
|
+
const userConfig = await loadMcpConfig(userMcpPath);
|
|
36
|
+
merged = mergeMcpConfigs(merged, userConfig);
|
|
37
|
+
sourcesLoaded.push(userMcpPath);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
if (!isMissingFile(err)) {
|
|
41
|
+
process.stderr.write(`forge: MCP loader (user registry) failed: ${err.message}\n`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// 2. Explicit config wins on conflicts.
|
|
46
|
+
try {
|
|
47
|
+
const config = await loadMcpConfig(configPath);
|
|
48
|
+
merged = mergeMcpConfigs(merged, config);
|
|
49
|
+
sourcesLoaded.push(configPath);
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
if (isMissingFile(err)) {
|
|
53
|
+
// When the only source is the missing explicit config AND the user
|
|
54
|
+
// registry was also missing, fall through to the "no MCP" branch.
|
|
55
|
+
if (sourcesLoaded.length === 0) {
|
|
56
|
+
return { tools: [], cleanup: async () => { }, servers: [] };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
process.stderr.write(`forge: MCP loader failed: ${err.message}\n`);
|
|
61
|
+
return { tools: [], cleanup: async () => { }, servers: [] };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
let connected = [];
|
|
65
|
+
try {
|
|
66
|
+
connected = await connectAll(merged);
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
process.stderr.write(`forge: MCP connect failed: ${err.message}\n`);
|
|
70
|
+
return { tools: [], cleanup: async () => { }, servers: [] };
|
|
71
|
+
}
|
|
72
|
+
const tools = connected.flatMap((s) => s.tools);
|
|
73
|
+
const cleanup = async () => {
|
|
74
|
+
await closeAll(connected);
|
|
75
|
+
};
|
|
76
|
+
// Brief startup announcement so the user knows MCP is active.
|
|
77
|
+
if (connected.length > 0 && process.env.FORGE_VERBOSE_MCP === '1') {
|
|
78
|
+
process.stderr.write(`forge: connected to ${connected.length} MCP server${connected.length === 1 ? '' : 's'} from ${sourcesLoaded.length} source${sourcesLoaded.length === 1 ? '' : 's'}; ${tools.length} tool${tools.length === 1 ? '' : 's'} available\n`);
|
|
79
|
+
}
|
|
80
|
+
return { tools, cleanup, servers: connected };
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Merge two MCP configs. Entries from `override` win on name conflicts;
|
|
84
|
+
* entries from `base` are kept otherwise. The function is pure: both
|
|
85
|
+
* inputs are read-only.
|
|
86
|
+
*/
|
|
87
|
+
function mergeMcpConfigs(base, override) {
|
|
88
|
+
return {
|
|
89
|
+
mcpServers: {
|
|
90
|
+
...base.mcpServers,
|
|
91
|
+
...override.mcpServers,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function isMissingFile(err) {
|
|
96
|
+
return Boolean(err && typeof err === 'object' && 'code' in err &&
|
|
97
|
+
err.code === 'ENOENT');
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=mcp-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-loader.js","sourceRoot":"","sources":["../src/mcp-loader.ts"],"names":[],"mappings":"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"}
|
package/dist/notify.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface NotifyOptions {
|
|
2
|
+
command?: string | null;
|
|
3
|
+
}
|
|
4
|
+
export type Notifier = (message: string) => void;
|
|
5
|
+
/** The OS-specific command line, or null when there is no known backend. */
|
|
6
|
+
export declare function defaultNotifyCommand(platform?: NodeJS.Platform): {
|
|
7
|
+
cmd: string;
|
|
8
|
+
args: string[];
|
|
9
|
+
} | null;
|
|
10
|
+
/** Fire-and-forget; a missing backend or a failing command never affects the run. */
|
|
11
|
+
export declare function createNotifier(opts: NotifyOptions): Notifier;
|
|
12
|
+
//# sourceMappingURL=notify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../src/notify.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAIjD,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAAC,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAczH;AAED,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,QAAQ,CAmB5D"}
|
package/dist/notify.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Desktop notification when Forge finishes and waits on you (`--notifications`).
|
|
3
|
+
* `--notifications-command <cmd>` replaces the OS default; the message is passed
|
|
4
|
+
* in the FORGE_NOTIFY_MESSAGE environment variable (and FORGE_NOTIFY_TITLE).
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from 'node:child_process';
|
|
7
|
+
const TITLE = 'IKarmic AI Forge';
|
|
8
|
+
/** The OS-specific command line, or null when there is no known backend. */
|
|
9
|
+
export function defaultNotifyCommand(platform = process.platform) {
|
|
10
|
+
if (platform === 'darwin') {
|
|
11
|
+
return { cmd: 'osascript', args: ['-e', 'display notification (system attribute "FORGE_NOTIFY_MESSAGE") with title (system attribute "FORGE_NOTIFY_TITLE")'] };
|
|
12
|
+
}
|
|
13
|
+
if (platform === 'linux') {
|
|
14
|
+
return { cmd: 'notify-send', args: [TITLE, '--', ''] };
|
|
15
|
+
}
|
|
16
|
+
if (platform === 'win32') {
|
|
17
|
+
return {
|
|
18
|
+
cmd: 'powershell',
|
|
19
|
+
args: ['-NoProfile', '-Command', 'Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show($env:FORGE_NOTIFY_MESSAGE, $env:FORGE_NOTIFY_TITLE) | Out-Null'],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
/** Fire-and-forget; a missing backend or a failing command never affects the run. */
|
|
25
|
+
export function createNotifier(opts) {
|
|
26
|
+
return (message) => {
|
|
27
|
+
const env = { ...process.env, FORGE_NOTIFY_MESSAGE: message, FORGE_NOTIFY_TITLE: TITLE };
|
|
28
|
+
try {
|
|
29
|
+
const child = opts.command
|
|
30
|
+
? spawn(opts.command, { shell: true, env, stdio: 'ignore' })
|
|
31
|
+
: (() => {
|
|
32
|
+
const d = defaultNotifyCommand();
|
|
33
|
+
if (!d)
|
|
34
|
+
return null;
|
|
35
|
+
// notify-send takes the body as an argument rather than from the environment.
|
|
36
|
+
const args = d.cmd === 'notify-send' ? [TITLE, message] : d.args;
|
|
37
|
+
return spawn(d.cmd, args, { env, stdio: 'ignore' });
|
|
38
|
+
})();
|
|
39
|
+
child?.on('error', () => { });
|
|
40
|
+
child?.unref();
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Notifications are best effort.
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=notify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../src/notify.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAQ3C,MAAM,KAAK,GAAG,kBAAkB,CAAC;AAEjC,4EAA4E;AAC5E,MAAM,UAAU,oBAAoB,CAAC,WAA4B,OAAO,CAAC,QAAQ;IAC/E,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,mHAAmH,CAAC,EAAE,CAAC;IACjK,CAAC;IACD,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC;IACzD,CAAC;IACD,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO;YACL,GAAG,EAAE,YAAY;YACjB,IAAI,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE,qJAAqJ,CAAC;SACxL,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,cAAc,CAAC,IAAmB;IAChD,OAAO,CAAC,OAAe,EAAQ,EAAE;QAC/B,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,oBAAoB,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC;QACzF,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO;gBACxB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;gBAC5D,CAAC,CAAC,CAAC,GAAG,EAAE;oBACJ,MAAM,CAAC,GAAG,oBAAoB,EAAE,CAAC;oBACjC,IAAI,CAAC,CAAC;wBAAE,OAAO,IAAI,CAAC;oBACpB,8EAA8E;oBAC9E,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;oBACjE,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACtD,CAAC,CAAC,EAAE,CAAC;YACT,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAC7B,KAAK,EAAE,KAAK,EAAE,CAAC;QACjB,CAAC;QAAC,MAAM,CAAC;YACP,iCAAiC;QACnC,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|