ikarmic-forge 0.0.0-stage → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +58 -2
  3. package/dist/acp/server.d.ts +53 -0
  4. package/dist/acp/server.d.ts.map +1 -0
  5. package/dist/acp/server.js +235 -0
  6. package/dist/acp/server.js.map +1 -0
  7. package/dist/app.d.ts +22 -0
  8. package/dist/app.d.ts.map +1 -0
  9. package/dist/app.js +159 -0
  10. package/dist/app.js.map +1 -0
  11. package/dist/bin/forge.d.ts +3 -0
  12. package/dist/bin/forge.d.ts.map +1 -0
  13. package/dist/bin/forge.js +747 -0
  14. package/dist/bin/forge.js.map +1 -0
  15. package/dist/chat-files.d.ts +37 -0
  16. package/dist/chat-files.d.ts.map +1 -0
  17. package/dist/chat-files.js +152 -0
  18. package/dist/chat-files.js.map +1 -0
  19. package/dist/commands/acp.d.ts +4 -0
  20. package/dist/commands/acp.d.ts.map +1 -0
  21. package/dist/commands/acp.js +36 -0
  22. package/dist/commands/acp.js.map +1 -0
  23. package/dist/commands/ai-comments.d.ts +9 -0
  24. package/dist/commands/ai-comments.d.ts.map +1 -0
  25. package/dist/commands/ai-comments.js +43 -0
  26. package/dist/commands/ai-comments.js.map +1 -0
  27. package/dist/commands/architect.d.ts +9 -0
  28. package/dist/commands/architect.d.ts.map +1 -0
  29. package/dist/commands/architect.js +27 -0
  30. package/dist/commands/architect.js.map +1 -0
  31. package/dist/commands/checkpoint.d.ts +10 -0
  32. package/dist/commands/checkpoint.d.ts.map +1 -0
  33. package/dist/commands/checkpoint.js +168 -0
  34. package/dist/commands/checkpoint.js.map +1 -0
  35. package/dist/commands/config.d.ts +15 -0
  36. package/dist/commands/config.d.ts.map +1 -0
  37. package/dist/commands/config.js +180 -0
  38. package/dist/commands/config.js.map +1 -0
  39. package/dist/commands/diff.d.ts +29 -0
  40. package/dist/commands/diff.d.ts.map +1 -0
  41. package/dist/commands/diff.js +90 -0
  42. package/dist/commands/diff.js.map +1 -0
  43. package/dist/commands/hook.d.ts +10 -0
  44. package/dist/commands/hook.d.ts.map +1 -0
  45. package/dist/commands/hook.js +121 -0
  46. package/dist/commands/hook.js.map +1 -0
  47. package/dist/commands/mcp.d.ts +10 -0
  48. package/dist/commands/mcp.d.ts.map +1 -0
  49. package/dist/commands/mcp.js +110 -0
  50. package/dist/commands/mcp.js.map +1 -0
  51. package/dist/commands/orchestrator.d.ts +22 -0
  52. package/dist/commands/orchestrator.d.ts.map +1 -0
  53. package/dist/commands/orchestrator.js +113 -0
  54. package/dist/commands/orchestrator.js.map +1 -0
  55. package/dist/commands/plugin.d.ts +3 -0
  56. package/dist/commands/plugin.d.ts.map +1 -0
  57. package/dist/commands/plugin.js +62 -0
  58. package/dist/commands/plugin.js.map +1 -0
  59. package/dist/commands/policy.d.ts +2 -0
  60. package/dist/commands/policy.d.ts.map +1 -0
  61. package/dist/commands/policy.js +21 -0
  62. package/dist/commands/policy.js.map +1 -0
  63. package/dist/commands/skill.d.ts +13 -0
  64. package/dist/commands/skill.d.ts.map +1 -0
  65. package/dist/commands/skill.js +194 -0
  66. package/dist/commands/skill.js.map +1 -0
  67. package/dist/commands/spec.d.ts +13 -0
  68. package/dist/commands/spec.d.ts.map +1 -0
  69. package/dist/commands/spec.js +76 -0
  70. package/dist/commands/spec.js.map +1 -0
  71. package/dist/commands/watch.d.ts +15 -0
  72. package/dist/commands/watch.d.ts.map +1 -0
  73. package/dist/commands/watch.js +83 -0
  74. package/dist/commands/watch.js.map +1 -0
  75. package/dist/commands/worktree.d.ts +22 -0
  76. package/dist/commands/worktree.d.ts.map +1 -0
  77. package/dist/commands/worktree.js +187 -0
  78. package/dist/commands/worktree.js.map +1 -0
  79. package/dist/components/Approval.d.ts +9 -0
  80. package/dist/components/Approval.d.ts.map +1 -0
  81. package/dist/components/Approval.js +37 -0
  82. package/dist/components/Approval.js.map +1 -0
  83. package/dist/components/Footer.d.ts +22 -0
  84. package/dist/components/Footer.d.ts.map +1 -0
  85. package/dist/components/Footer.js +59 -0
  86. package/dist/components/Footer.js.map +1 -0
  87. package/dist/components/Header.d.ts +11 -0
  88. package/dist/components/Header.d.ts.map +1 -0
  89. package/dist/components/Header.js +23 -0
  90. package/dist/components/Header.js.map +1 -0
  91. package/dist/components/Spinner.d.ts +3 -0
  92. package/dist/components/Spinner.d.ts.map +1 -0
  93. package/dist/components/Spinner.js +8 -0
  94. package/dist/components/Spinner.js.map +1 -0
  95. package/dist/components/Stream.d.ts +10 -0
  96. package/dist/components/Stream.d.ts.map +1 -0
  97. package/dist/components/Stream.js +13 -0
  98. package/dist/components/Stream.js.map +1 -0
  99. package/dist/components/ToolEvent.d.ts +13 -0
  100. package/dist/components/ToolEvent.d.ts.map +1 -0
  101. package/dist/components/ToolEvent.js +54 -0
  102. package/dist/components/ToolEvent.js.map +1 -0
  103. package/dist/credential-store.d.ts +8 -0
  104. package/dist/credential-store.d.ts.map +1 -0
  105. package/dist/credential-store.js +37 -0
  106. package/dist/credential-store.js.map +1 -0
  107. package/dist/git-workflow.d.ts +16 -0
  108. package/dist/git-workflow.d.ts.map +1 -0
  109. package/dist/git-workflow.js +38 -0
  110. package/dist/git-workflow.js.map +1 -0
  111. package/dist/mcp-loader.d.ts +25 -0
  112. package/dist/mcp-loader.d.ts.map +1 -0
  113. package/dist/mcp-loader.js +99 -0
  114. package/dist/mcp-loader.js.map +1 -0
  115. package/dist/notify.d.ts +12 -0
  116. package/dist/notify.d.ts.map +1 -0
  117. package/dist/notify.js +47 -0
  118. package/dist/notify.js.map +1 -0
  119. package/dist/options.d.ts +407 -0
  120. package/dist/options.d.ts.map +1 -0
  121. package/dist/options.js +792 -0
  122. package/dist/options.js.map +1 -0
  123. package/dist/repl-commands.d.ts +53 -0
  124. package/dist/repl-commands.d.ts.map +1 -0
  125. package/dist/repl-commands.js +141 -0
  126. package/dist/repl-commands.js.map +1 -0
  127. package/dist/repl.d.ts +52 -0
  128. package/dist/repl.d.ts.map +1 -0
  129. package/dist/repl.js +1174 -0
  130. package/dist/repl.js.map +1 -0
  131. package/dist/runner.d.ts +64 -0
  132. package/dist/runner.d.ts.map +1 -0
  133. package/dist/runner.js +61 -0
  134. package/dist/runner.js.map +1 -0
  135. package/dist/session-checkpoints.d.ts +6 -0
  136. package/dist/session-checkpoints.d.ts.map +1 -0
  137. package/dist/session-checkpoints.js +25 -0
  138. package/dist/session-checkpoints.js.map +1 -0
  139. package/dist/specialists-loader.d.ts +22 -0
  140. package/dist/specialists-loader.d.ts.map +1 -0
  141. package/dist/specialists-loader.js +38 -0
  142. package/dist/specialists-loader.js.map +1 -0
  143. package/dist/tool-display.d.ts +19 -0
  144. package/dist/tool-display.d.ts.map +1 -0
  145. package/dist/tool-display.js +57 -0
  146. package/dist/tool-display.js.map +1 -0
  147. package/package.json +70 -3
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ import { Box, Text } from 'ink';
3
+ import { getUnifiedDiffText, summarizeResult } from '../tool-display.js';
4
+ function diffLineColor(line) {
5
+ if (line.startsWith('+++') || line.startsWith('---'))
6
+ return 'gray';
7
+ if (line.startsWith('@@'))
8
+ return 'cyan';
9
+ if (line.startsWith('+'))
10
+ return 'green';
11
+ if (line.startsWith('-'))
12
+ return 'red';
13
+ return 'gray';
14
+ }
15
+ export const ToolEvent = React.memo(function ToolEvent(props) {
16
+ const { name, args, result, isError, durationMs, pending, detail = 'compact' } = props;
17
+ const argSummary = summarizeArgs(args);
18
+ const diffText = pending ? null : getUnifiedDiffText(name, args, result);
19
+ const resultSummary = pending || diffText ? undefined : summarizeResult(result, isError, detail);
20
+ return (React.createElement(Box, { flexDirection: "column", marginLeft: 2, marginTop: 1 },
21
+ React.createElement(Box, null,
22
+ React.createElement(Text, { color: isError ? 'red' : 'blue', bold: true },
23
+ isError ? '✗' : pending ? '◌' : '✓',
24
+ " ",
25
+ name),
26
+ React.createElement(Text, { color: "gray" }, argSummary),
27
+ durationMs !== undefined && (React.createElement(Text, { color: "gray" },
28
+ " \u00B7 ",
29
+ durationMs,
30
+ "ms"))),
31
+ diffText && (React.createElement(Box, { flexDirection: "column", marginLeft: 2 }, diffText.replace(/\n$/, '').split('\n').map((line, i) => (React.createElement(Text, { key: i, color: diffLineColor(line) }, line))))),
32
+ resultSummary !== undefined && (React.createElement(Box, { marginLeft: 2 },
33
+ React.createElement(Text, { color: isError ? 'red' : 'gray' }, resultSummary)))));
34
+ });
35
+ function summarizeArgs(args) {
36
+ if (args === undefined || args === null)
37
+ return '()';
38
+ if (typeof args !== 'object')
39
+ return `(${String(args)})`;
40
+ const obj = args;
41
+ const keys = Object.keys(obj);
42
+ if (keys.length === 0)
43
+ return '()';
44
+ const parts = keys.slice(0, 3).map((k) => {
45
+ const v = obj[k];
46
+ const vs = typeof v === 'string' ? JSON.stringify(v) : JSON.stringify(v);
47
+ const truncated = vs.length > 80 ? vs.slice(0, 77) + '...' : vs;
48
+ return `${k}=${truncated}`;
49
+ });
50
+ if (keys.length > 3)
51
+ parts.push(`+${keys.length - 3} more`);
52
+ return `(${parts.join(' ')})`;
53
+ }
54
+ //# sourceMappingURL=ToolEvent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolEvent.js","sourceRoot":"","sources":["../../src/components/ToolEvent.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { CredentialStore } from '@ikarmic/forge-core';
2
+ /**
3
+ * OS-keychain-backed CredentialStore for the CLI. Uses the same
4
+ * service/account naming as the VS Code SecretStorage implementation
5
+ * so a key entered on one surface is visible on the other.
6
+ */
7
+ export declare function createKeyringCredentialStore(): CredentialStore;
8
+ //# sourceMappingURL=credential-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-store.d.ts","sourceRoot":"","sources":["../src/credential-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D;;;;GAIG;AACH,wBAAgB,4BAA4B,IAAI,eAAe,CA0B9D"}
@@ -0,0 +1,37 @@
1
+ import { Entry } from '@napi-rs/keyring';
2
+ import { CREDENTIAL_SERVICE_NAME, credentialAccountKey } from '@ikarmic/forge-core';
3
+ /**
4
+ * OS-keychain-backed CredentialStore for the CLI. Uses the same
5
+ * service/account naming as the VS Code SecretStorage implementation
6
+ * so a key entered on one surface is visible on the other.
7
+ */
8
+ export function createKeyringCredentialStore() {
9
+ return {
10
+ async get(provider) {
11
+ try {
12
+ const entry = new Entry(CREDENTIAL_SERVICE_NAME, credentialAccountKey(provider));
13
+ return entry.getPassword() ?? undefined;
14
+ }
15
+ catch {
16
+ // OS keychain unavailable (e.g. headless Linux without libsecret):
17
+ // treat as "not set" rather than surfacing a low-level error.
18
+ return undefined;
19
+ }
20
+ },
21
+ async set(provider, key) {
22
+ const entry = new Entry(CREDENTIAL_SERVICE_NAME, credentialAccountKey(provider));
23
+ entry.setPassword(key);
24
+ },
25
+ async delete(provider) {
26
+ try {
27
+ const entry = new Entry(CREDENTIAL_SERVICE_NAME, credentialAccountKey(provider));
28
+ entry.deletePassword();
29
+ }
30
+ catch {
31
+ // Already absent, or keychain unavailable: deleting a
32
+ // non-existent entry is a no-op either way.
33
+ }
34
+ },
35
+ };
36
+ }
37
+ //# sourceMappingURL=credential-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-store.js","sourceRoot":"","sources":["../src/credential-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAGpF;;;;GAIG;AACH,MAAM,UAAU,4BAA4B;IAC1C,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,QAAQ;YAChB,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,uBAAuB,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACjF,OAAO,KAAK,CAAC,WAAW,EAAE,IAAI,SAAS,CAAC;YAC1C,CAAC;YAAC,MAAM,CAAC;gBACP,oEAAoE;gBACpE,8DAA8D;gBAC9D,OAAO,SAAS,CAAC;YACnB,CAAC;QACH,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG;YACrB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,uBAAuB,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC;YACjF,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,QAAQ;YACnB,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,uBAAuB,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACjF,KAAK,CAAC,cAAc,EAAE,CAAC;YACzB,CAAC;YAAC,MAAM,CAAC;gBACP,sDAAsD;gBACtD,4CAA4C;YAC9C,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { ForgeCommit, GitCommitOptions, ModelConfig } from '@ikarmic/forge-core';
2
+ import type { CliOptions } from './options.js';
3
+ export interface GitWorkflow {
4
+ /** Call before the agent starts. Returns the commit that saved your own changes, if any. */
5
+ before(): Promise<ForgeCommit | null>;
6
+ /** Call after a completed run. Returns the commit holding the agent's changes, if any. */
7
+ after(task: string): Promise<ForgeCommit | null>;
8
+ }
9
+ export declare function gitCommitOptions(options: Pick<CliOptions, 'noAttribute' | 'gitCommitVerify'>): GitCommitOptions;
10
+ /** Commit messages use the cheap model when one is configured, else the main model. */
11
+ export declare function resolveCommitModel(options: Pick<CliOptions, 'cheapModel'>, model: ModelConfig): Promise<ModelConfig>;
12
+ export declare function createGitWorkflow(options: Pick<CliOptions, 'autoCommit' | 'noDirtyCommits' | 'noAttribute' | 'gitCommitVerify' | 'cheapModel'> & {
13
+ dryRun?: boolean;
14
+ }, cwd: string, model: ModelConfig): Promise<GitWorkflow | null>;
15
+ export declare function formatCommitLine(commit: ForgeCommit): string;
16
+ //# sourceMappingURL=git-workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-workflow.d.ts","sourceRoot":"","sources":["../src/git-workflow.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACtF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,WAAW,WAAW;IAC1B,4FAA4F;IAC5F,MAAM,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACtC,0FAA0F;IAC1F,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CAClD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,aAAa,GAAG,iBAAiB,CAAC,GAAG,gBAAgB,CAE/G;AAED,uFAAuF;AACvF,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAI1H;AAED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,YAAY,GAAG,gBAAgB,GAAG,aAAa,GAAG,iBAAiB,GAAG,YAAY,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,EACpI,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAe7B;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAG5D"}
@@ -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":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,OAAO,EACL,QAAQ,EACR,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,GAId,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,UAAkB;IAElB,MAAM,WAAW,GAAG,kBAAkB,EAAE,CAAC;IAEzC,iEAAiE;IACjE,IAAI,MAAM,GAAkB,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;IAC/C,MAAM,aAAa,GAAa,EAAE,CAAC;IAEnC,0DAA0D;IAC1D,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClF,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,GAAG,eAAe,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC,CAAC;QAChE,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC;IAED,8CAA8C;IAC9C,IAAI,WAAW,KAAK,UAAU,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;YACpD,MAAM,GAAG,eAAe,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAC7C,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,6CAA8C,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;YAChG,CAAC;QACH,CAAC;IACH,CAAC;IAED,wCAAwC;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,UAAU,CAAC,CAAC;QAC/C,MAAM,GAAG,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACzC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,mEAAmE;YACnE,kEAAkE;YAClE,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC/B,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;YAC7D,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA8B,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;YAC9E,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,IAAI,SAAS,GAAyB,EAAE,CAAC;IACzC,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA+B,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QAC/E,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC7D,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;QACzB,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC5B,CAAC,CAAC;IACF,8DAA8D;IAC9D,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,GAAG,EAAE,CAAC;QAClE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uBAAuB,SAAS,CAAC,MAAM,cAAc,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,SAAS,aAAa,CAAC,MAAM,UAAU,aAAa,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC,MAAM,QAAQ,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,cAAc,CACvO,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAChD,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CAAC,IAAmB,EAAE,QAAuB;IACnE,OAAO;QACL,UAAU,EAAE;YACV,GAAG,IAAI,CAAC,UAAU;YAClB,GAAG,QAAQ,CAAC,UAAU;SACvB;KACF,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,GAAY;IACjC,OAAO,OAAO,CACZ,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,IAAK,GAA+B;QACzE,GAAyB,CAAC,IAAI,KAAK,QAAQ,CAC/C,CAAC;AACJ,CAAC"}
@@ -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"}