fraim 2.0.281 → 2.0.284
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 +467 -467
- package/bin/fraim.js +12 -12
- package/dist/src/cli/mcp/fraim-mcp-latest-launcher.js +267 -182
- package/dist/src/cli/mcp/mcp-server-registry.js +11 -3
- package/dist/src/cli/setup/ide-invocation-surfaces.js +64 -64
- package/dist/src/cli/utils/agent-adapters.js +61 -61
- package/dist/src/core/handoff-contracts.js +39 -39
- package/dist/src/core/utils/stub-generator.js +53 -53
- package/dist/src/core/utils/windows-shim-path-search.js +56 -0
- package/dist/src/first-run/server.js +5 -1
- package/dist/src/first-run/session-service.js +48 -12
- package/dist/src/fraim/issues.js +4 -4
- package/dist/src/mcp/tool-schemas.js +40 -40
- package/dist/src/middleware/telemetry.js +21 -21
- package/dist/src/services/email-service.js +623 -623
- package/dist/src/services/installer-service.js +22 -22
- package/index.js +83 -83
- package/package.json +59 -59
- package/public/first-run/error-frame.js +100 -100
- package/public/first-run/index.html +35 -35
- package/public/first-run/script.js +747 -742
- package/public/first-run/styles.css +929 -929
- package/dist/src/cli/commands/learning-usage.js +0 -412
- package/dist/src/cli/commands/test-mcp.js +0 -171
- package/dist/src/cli/setup/first-run.js +0 -242
- package/dist/src/core/config-writer.js +0 -75
- package/dist/src/core/utils/job-aliases.js +0 -47
- package/dist/src/core/utils/workflow-parser.js +0 -174
- package/dist/src/services/email-service-clean.js +0 -782
|
@@ -48,6 +48,7 @@ const ide_detector_1 = require("../cli/setup/ide-detector");
|
|
|
48
48
|
const ide_global_integration_1 = require("../cli/setup/ide-global-integration");
|
|
49
49
|
const auto_mcp_setup_1 = require("../cli/setup/auto-mcp-setup");
|
|
50
50
|
const setup_1 = require("../cli/commands/setup");
|
|
51
|
+
const fraim_mcp_latest_launcher_1 = require("../cli/mcp/fraim-mcp-latest-launcher");
|
|
51
52
|
const script_sync_utils_1 = require("../cli/utils/script-sync-utils");
|
|
52
53
|
const managed_agent_paths_1 = require("../cli/utils/managed-agent-paths");
|
|
53
54
|
const managed_agent_install_1 = require("../cli/utils/managed-agent-install");
|
|
@@ -118,13 +119,18 @@ function buildPersistShellPathWindowsCommand(bins) {
|
|
|
118
119
|
`[Environment]::SetEnvironmentVariable('PATH', $cur, 'User')`,
|
|
119
120
|
].join('; ');
|
|
120
121
|
}
|
|
121
|
-
function persistShellPath() {
|
|
122
|
+
function persistShellPath(includePackagedFraimBin = false) {
|
|
122
123
|
const marker = '# FRAIM managed binaries';
|
|
123
124
|
const legacyExportLine = 'export PATH="$HOME/.fraim/node/bin:$PATH"';
|
|
124
|
-
const exportLine =
|
|
125
|
+
const exportLine = includePackagedFraimBin
|
|
126
|
+
? 'export PATH="$PATH:$HOME/.fraim/bin:$HOME/.fraim/node/bin"'
|
|
127
|
+
: 'export PATH="$PATH:$HOME/.fraim/node/bin"';
|
|
125
128
|
const stanza = `\n${marker}\n${exportLine}\n`;
|
|
126
129
|
if (process.platform === 'win32') {
|
|
127
|
-
const
|
|
130
|
+
const bins = includePackagedFraimBin
|
|
131
|
+
? [path_1.default.join((0, script_sync_utils_1.getUserFraimDir)(), 'bin'), ...(0, managed_agent_paths_1.getManagedAgentBinDirs)()]
|
|
132
|
+
: (0, managed_agent_paths_1.getManagedAgentBinDirs)();
|
|
133
|
+
const psCmd = buildPersistShellPathWindowsCommand(bins);
|
|
128
134
|
(0, child_process_1.spawnSync)('powershell', ['-NoProfile', '-NonInteractive', '-Command', psCmd], { encoding: 'utf8' });
|
|
129
135
|
return;
|
|
130
136
|
}
|
|
@@ -146,8 +152,12 @@ function persistShellPath() {
|
|
|
146
152
|
fs_1.default.writeFileSync(profile, content.replace(legacyExportLine, exportLine), 'utf8');
|
|
147
153
|
continue;
|
|
148
154
|
}
|
|
149
|
-
if (content.includes(marker))
|
|
155
|
+
if (content.includes(marker)) {
|
|
156
|
+
if (includePackagedFraimBin && !content.includes('$HOME/.fraim/bin')) {
|
|
157
|
+
fs_1.default.writeFileSync(profile, content.replace(exportLine.replace(':$HOME/.fraim/bin', ''), exportLine), 'utf8');
|
|
158
|
+
}
|
|
150
159
|
continue;
|
|
160
|
+
}
|
|
151
161
|
fs_1.default.appendFileSync(profile, stanza, 'utf8');
|
|
152
162
|
}
|
|
153
163
|
catch {
|
|
@@ -246,6 +256,7 @@ class FirstRunSessionService {
|
|
|
246
256
|
// wizard prompts the user to paste their key (see setKey / needsKey).
|
|
247
257
|
this.key = options.key || '';
|
|
248
258
|
this.headless = options.headless === true;
|
|
259
|
+
this.embeddedDesktop = options.embeddedDesktop === true;
|
|
249
260
|
this.fakeMode = getFakeStateMode();
|
|
250
261
|
this.fakeStderr =
|
|
251
262
|
process.env.FRAIM_FIRST_RUN_FAKE_STDERR ??
|
|
@@ -310,10 +321,10 @@ class FirstRunSessionService {
|
|
|
310
321
|
}
|
|
311
322
|
// Real detection — populate row statuses from `command -v` style probes.
|
|
312
323
|
const nodeRow = this.getRow('node');
|
|
313
|
-
const nodeVer = commandVersion('node');
|
|
324
|
+
const nodeVer = this.embeddedDesktop ? process.version : commandVersion('node');
|
|
314
325
|
if (nodeVer) {
|
|
315
326
|
nodeRow.status = 'ok';
|
|
316
|
-
nodeRow.verb = `${nodeVer} detected`;
|
|
327
|
+
nodeRow.verb = this.embeddedDesktop ? `${nodeVer} bundled with FRAIM` : `${nodeVer} detected`;
|
|
317
328
|
}
|
|
318
329
|
else {
|
|
319
330
|
nodeRow.status = 'pending';
|
|
@@ -330,7 +341,7 @@ class FirstRunSessionService {
|
|
|
330
341
|
gitRow.verb = 'optional — only needed for code delivery workflows';
|
|
331
342
|
}
|
|
332
343
|
const fraimRow = this.getRow('fraim');
|
|
333
|
-
if (commandVersion('npx') !== null) {
|
|
344
|
+
if (this.embeddedDesktop || commandVersion('npx') !== null) {
|
|
334
345
|
// Only mark ok if setup has previously completed (config.json is written after autoConfigureMCP).
|
|
335
346
|
// Without this, the wizard skips runFraimRow entirely and autoConfigureMCP never runs for IDEs.
|
|
336
347
|
const globalConfigPath = path_1.default.join((0, script_sync_utils_1.getUserFraimDir)(), 'config.json');
|
|
@@ -342,7 +353,7 @@ class FirstRunSessionService {
|
|
|
342
353
|
fraimRow.status = 'pending';
|
|
343
354
|
fraimRow.verb = "we'll configure your IDEs";
|
|
344
355
|
}
|
|
345
|
-
persistShellPath();
|
|
356
|
+
persistShellPath(this.embeddedDesktop);
|
|
346
357
|
}
|
|
347
358
|
else {
|
|
348
359
|
fraimRow.status = 'pending';
|
|
@@ -570,6 +581,12 @@ class FirstRunSessionService {
|
|
|
570
581
|
}
|
|
571
582
|
async runNodeRow() {
|
|
572
583
|
const row = this.getRow('node');
|
|
584
|
+
if (this.embeddedDesktop) {
|
|
585
|
+
row.status = 'ok';
|
|
586
|
+
row.verb = `${process.version} bundled with FRAIM`;
|
|
587
|
+
this.persist();
|
|
588
|
+
return this.respond(`FRAIM includes its own runtime (${process.version}).`, true);
|
|
589
|
+
}
|
|
573
590
|
// Node is bootstrapped by the install template before the wizard starts.
|
|
574
591
|
// If node is missing here something is severely wrong; fall through to error.
|
|
575
592
|
const ver = commandVersion('node');
|
|
@@ -631,7 +648,10 @@ class FirstRunSessionService {
|
|
|
631
648
|
return this.respond('FRAIM configured.', true);
|
|
632
649
|
}
|
|
633
650
|
try {
|
|
634
|
-
if (
|
|
651
|
+
if (this.embeddedDesktop) {
|
|
652
|
+
(0, fraim_mcp_latest_launcher_1.ensureFraimMcpLatestLauncher)();
|
|
653
|
+
}
|
|
654
|
+
else if (!forceConfigure && !commandVersion('fraim')) {
|
|
635
655
|
const prefix = path_1.default.join((0, script_sync_utils_1.getUserFraimDir)(), 'node');
|
|
636
656
|
fs_1.default.mkdirSync(prefix, { recursive: true });
|
|
637
657
|
row.streamOutput = 'Installing FRAIM on this machine...';
|
|
@@ -645,7 +665,7 @@ class FirstRunSessionService {
|
|
|
645
665
|
this.persist();
|
|
646
666
|
await runProcess('npm', ['install', '-g', 'fraim@latest'], { npm_config_prefix: prefix });
|
|
647
667
|
}
|
|
648
|
-
persistShellPath();
|
|
668
|
+
persistShellPath(this.embeddedDesktop);
|
|
649
669
|
const detectedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
|
|
650
670
|
if (detectedIDEs.length > 0) {
|
|
651
671
|
await (0, auto_mcp_setup_1.autoConfigureMCP)(this.key, detectedIDEs.map((ide) => ide.name));
|
|
@@ -660,7 +680,9 @@ class FirstRunSessionService {
|
|
|
660
680
|
await installSlashCommands();
|
|
661
681
|
await installGlobalRules();
|
|
662
682
|
row.status = 'ok';
|
|
663
|
-
row.verb =
|
|
683
|
+
row.verb = this.embeddedDesktop
|
|
684
|
+
? 'Ready — bundled with FRAIM Hub.'
|
|
685
|
+
: 'Ready — open a new terminal before running fraim commands.';
|
|
664
686
|
delete row.streamOutput;
|
|
665
687
|
const surfaces = this.getConfiguredAgentSurfaces();
|
|
666
688
|
this.state.setupResult = {
|
|
@@ -671,7 +693,9 @@ class FirstRunSessionService {
|
|
|
671
693
|
completedAt: new Date().toISOString(),
|
|
672
694
|
};
|
|
673
695
|
this.persist();
|
|
674
|
-
return this.respond(
|
|
696
|
+
return this.respond(this.embeddedDesktop
|
|
697
|
+
? 'FRAIM and FRAIM Hub are ready in this installed application.'
|
|
698
|
+
: 'FRAIM is ready. Open a new terminal window so your PATH update takes effect before running fraim commands.', true);
|
|
675
699
|
}
|
|
676
700
|
catch (error) {
|
|
677
701
|
const detail = error instanceof Error ? error.message : 'Unknown error';
|
|
@@ -931,6 +955,18 @@ class FirstRunSessionService {
|
|
|
931
955
|
message: "No AI agent (Claude Code or Codex) found on this machine. Let's install one first.",
|
|
932
956
|
};
|
|
933
957
|
}
|
|
958
|
+
if (this.embeddedDesktop) {
|
|
959
|
+
(0, fraim_mcp_latest_launcher_1.ensureFraimMcpLatestLauncher)();
|
|
960
|
+
if (!fs_1.default.existsSync((0, fraim_mcp_latest_launcher_1.getFraimCliShimPath)())) {
|
|
961
|
+
return {
|
|
962
|
+
ok: false,
|
|
963
|
+
needsAgentSetup: true,
|
|
964
|
+
message: 'FRAIM CLI was not installed into the packaged desktop profile. Re-run FRAIM setup before opening Hub.',
|
|
965
|
+
};
|
|
966
|
+
}
|
|
967
|
+
appendInstallLog('hub-opened embedded-desktop');
|
|
968
|
+
return { ok: true, desktop: true, message: 'Opening FRAIM Hub in this app.' };
|
|
969
|
+
}
|
|
934
970
|
try {
|
|
935
971
|
const npxBinary = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
936
972
|
// Issue #866 R1/R2: launch the FRAIM Hub desktop (Electron) app, not a
|
package/dist/src/fraim/issues.js
CHANGED
|
@@ -45,8 +45,8 @@ async function fileFraimIssue(params) {
|
|
|
45
45
|
if (!token) {
|
|
46
46
|
return {
|
|
47
47
|
success: false,
|
|
48
|
-
message: `GitHub integration requires GITHUB_TOKEN environment variable.
|
|
49
|
-
|
|
48
|
+
message: `GitHub integration requires GITHUB_TOKEN environment variable.
|
|
49
|
+
|
|
50
50
|
Please set GITHUB_TOKEN environment variable to file issues in ${owner}/${repo}.`
|
|
51
51
|
};
|
|
52
52
|
}
|
|
@@ -102,8 +102,8 @@ async function listFraimIssuesByReporter(params) {
|
|
|
102
102
|
if (!token) {
|
|
103
103
|
return {
|
|
104
104
|
success: false,
|
|
105
|
-
message: `GitHub integration requires GITHUB_TOKEN environment variable.
|
|
106
|
-
|
|
105
|
+
message: `GitHub integration requires GITHUB_TOKEN environment variable.
|
|
106
|
+
|
|
107
107
|
Please set GITHUB_TOKEN environment variable to query issues in ${FRAIM_REPO_OWNER}/${FRAIM_REPO_NAME}.`
|
|
108
108
|
};
|
|
109
109
|
}
|
|
@@ -42,19 +42,19 @@ const getToolDefinitions = (options = {}) => {
|
|
|
42
42
|
? ['sessionId', ...fields]
|
|
43
43
|
: fields;
|
|
44
44
|
const fraimConnectDescription = isLocalProxySurface
|
|
45
|
-
? `Bootstrap and initialize a FRAIM session and obtain the sessionId used by active FRAIM workflow tools. Use this after explicit FRAIM activation: the user invoked FRAIM, named a FRAIM job, asked for FRAIM job recommendations, or the active surface selected a FRAIM job. Must be called before any FRAIM workflow tool calls. For ordinary requests, do not start a FRAIM session or scan the catalog.
|
|
46
|
-
|
|
47
|
-
Example:
|
|
48
|
-
{
|
|
49
|
-
"agent": {"name": "Claude", "model": "claude-3.5-sonnet"}
|
|
45
|
+
? `Bootstrap and initialize a FRAIM session and obtain the sessionId used by active FRAIM workflow tools. Use this after explicit FRAIM activation: the user invoked FRAIM, named a FRAIM job, asked for FRAIM job recommendations, or the active surface selected a FRAIM job. Must be called before any FRAIM workflow tool calls. For ordinary requests, do not start a FRAIM session or scan the catalog.
|
|
46
|
+
|
|
47
|
+
Example:
|
|
48
|
+
{
|
|
49
|
+
"agent": {"name": "Claude", "model": "claude-3.5-sonnet"}
|
|
50
50
|
}`
|
|
51
|
-
: `Bootstrap and initialize a FRAIM session and obtain the sessionId used by active FRAIM workflow tools. Use this after explicit FRAIM activation: the user invoked FRAIM, named a FRAIM job, asked for FRAIM job recommendations, or the active surface selected a FRAIM job. Must be called before any FRAIM workflow tool calls. For ordinary requests, do not start a FRAIM session or scan the catalog.
|
|
52
|
-
|
|
53
|
-
Hosted marketplace clients may call this with only agent information. If machine or repository context is omitted, FRAIM creates a hosted marketplace session context automatically.
|
|
54
|
-
|
|
55
|
-
Example:
|
|
56
|
-
{
|
|
57
|
-
"agent": {"name": "ChatGPT", "model": "gpt-5"}
|
|
51
|
+
: `Bootstrap and initialize a FRAIM session and obtain the sessionId used by active FRAIM workflow tools. Use this after explicit FRAIM activation: the user invoked FRAIM, named a FRAIM job, asked for FRAIM job recommendations, or the active surface selected a FRAIM job. Must be called before any FRAIM workflow tool calls. For ordinary requests, do not start a FRAIM session or scan the catalog.
|
|
52
|
+
|
|
53
|
+
Hosted marketplace clients may call this with only agent information. If machine or repository context is omitted, FRAIM creates a hosted marketplace session context automatically.
|
|
54
|
+
|
|
55
|
+
Example:
|
|
56
|
+
{
|
|
57
|
+
"agent": {"name": "ChatGPT", "model": "gpt-5"}
|
|
58
58
|
}`;
|
|
59
59
|
return [
|
|
60
60
|
{
|
|
@@ -198,12 +198,12 @@ Example:
|
|
|
198
198
|
},
|
|
199
199
|
{
|
|
200
200
|
name: 'get_fraim_file',
|
|
201
|
-
description: `Get a specific skill, rule, or reference file from the FRAIM registry by path.
|
|
202
|
-
|
|
203
|
-
For running FRAIM jobs, use get_fraim_job instead — do NOT call get_fraim_file for job execution.
|
|
204
|
-
|
|
205
|
-
Examples:
|
|
206
|
-
- get_fraim_file({ path: "skills/communication/active-listening.md" })
|
|
201
|
+
description: `Get a specific skill, rule, or reference file from the FRAIM registry by path.
|
|
202
|
+
|
|
203
|
+
For running FRAIM jobs, use get_fraim_job instead — do NOT call get_fraim_file for job execution.
|
|
204
|
+
|
|
205
|
+
Examples:
|
|
206
|
+
- get_fraim_file({ path: "skills/communication/active-listening.md" })
|
|
207
207
|
- get_fraim_file({ path: "rules/local-development.md" })`,
|
|
208
208
|
annotations: readOnlyClosedWorldAnnotations,
|
|
209
209
|
inputSchema: {
|
|
@@ -224,13 +224,13 @@ Examples:
|
|
|
224
224
|
},
|
|
225
225
|
{
|
|
226
226
|
name: 'get_fraim_job',
|
|
227
|
-
description: `Execute a named FRAIM job after explicit FRAIM activation. Call this tool whenever the user asks to run, start, or execute a named FRAIM job. Returns phased instructions — follow each phase and call seekMentoring to advance phases.
|
|
228
|
-
|
|
229
|
-
Do NOT use get_fraim_file to load job content. Always use get_fraim_job for job execution.
|
|
230
|
-
|
|
231
|
-
Examples:
|
|
232
|
-
- get_fraim_job({ job: "feature-specification" })
|
|
233
|
-
- get_fraim_job({ job: "technical-design" })
|
|
227
|
+
description: `Execute a named FRAIM job after explicit FRAIM activation. Call this tool whenever the user asks to run, start, or execute a named FRAIM job. Returns phased instructions — follow each phase and call seekMentoring to advance phases.
|
|
228
|
+
|
|
229
|
+
Do NOT use get_fraim_file to load job content. Always use get_fraim_job for job execution.
|
|
230
|
+
|
|
231
|
+
Examples:
|
|
232
|
+
- get_fraim_job({ job: "feature-specification" })
|
|
233
|
+
- get_fraim_job({ job: "technical-design" })
|
|
234
234
|
- get_fraim_job({ job: "feature-implementation" })`,
|
|
235
235
|
annotations: readOnlyClosedWorldAnnotations,
|
|
236
236
|
inputSchema: {
|
|
@@ -263,11 +263,11 @@ Examples:
|
|
|
263
263
|
},
|
|
264
264
|
{
|
|
265
265
|
name: 'file_fraim_github_issue',
|
|
266
|
-
description: `Create a GitHub issue in the FRAIM repository.
|
|
267
|
-
|
|
268
|
-
Use this tool when you need to report a bug, request a feature from FRAIM. Do not use this tool to file issues in other repositories.
|
|
269
|
-
Supports dry-run mode to preview the operation.
|
|
270
|
-
|
|
266
|
+
description: `Create a GitHub issue in the FRAIM repository.
|
|
267
|
+
|
|
268
|
+
Use this tool when you need to report a bug, request a feature from FRAIM. Do not use this tool to file issues in other repositories.
|
|
269
|
+
Supports dry-run mode to preview the operation.
|
|
270
|
+
|
|
271
271
|
This tool accepts text only. If visual evidence is needed, upload images to a stable shared HTTPS URL first and include those URLs in the issue body as markdown images or plain links. Do not include local file paths or base64-encoded image data in the issue body.`,
|
|
272
272
|
annotations: writeOpenWorldAnnotations,
|
|
273
273
|
inputSchema: {
|
|
@@ -297,16 +297,16 @@ This tool accepts text only. If visual evidence is needed, upload images to a st
|
|
|
297
297
|
},
|
|
298
298
|
{
|
|
299
299
|
name: 'list_my_fraim_github_issues',
|
|
300
|
-
description: `List issues the current FRAIM user filed into the FRAIM GitHub repository.
|
|
301
|
-
|
|
302
|
-
This tool is the read-side companion to file_fraim_github_issue. Use it when you need a simple list of issues filed by the current FRAIM user into the FRAIM repository.
|
|
303
|
-
|
|
304
|
-
Returns only:
|
|
305
|
-
- issue number
|
|
306
|
-
- title
|
|
307
|
-
- status
|
|
308
|
-
- created date
|
|
309
|
-
|
|
300
|
+
description: `List issues the current FRAIM user filed into the FRAIM GitHub repository.
|
|
301
|
+
|
|
302
|
+
This tool is the read-side companion to file_fraim_github_issue. Use it when you need a simple list of issues filed by the current FRAIM user into the FRAIM repository.
|
|
303
|
+
|
|
304
|
+
Returns only:
|
|
305
|
+
- issue number
|
|
306
|
+
- title
|
|
307
|
+
- status
|
|
308
|
+
- created date
|
|
309
|
+
|
|
310
310
|
Do not use this tool for other repositories or external project issue trackers.`,
|
|
311
311
|
annotations: readOnlyOpenWorldAnnotations,
|
|
312
312
|
inputSchema: {
|
|
@@ -84,9 +84,9 @@ class TelemetryMiddleware {
|
|
|
84
84
|
jsonrpc: '2.0',
|
|
85
85
|
error: {
|
|
86
86
|
code: -32600,
|
|
87
|
-
message: `Missing Session ID. REQUIRED ACTION:
|
|
88
|
-
1. Call 'fraim_connect' first
|
|
89
|
-
2. Capture the returned sessionId
|
|
87
|
+
message: `Missing Session ID. REQUIRED ACTION:
|
|
88
|
+
1. Call 'fraim_connect' first
|
|
89
|
+
2. Capture the returned sessionId
|
|
90
90
|
3. Include that sessionId on every subsequent FRAIM tool call (params.sessionId or params.arguments.sessionId).`
|
|
91
91
|
},
|
|
92
92
|
id: req.body?.id || null
|
|
@@ -97,24 +97,24 @@ class TelemetryMiddleware {
|
|
|
97
97
|
if (!isActive) {
|
|
98
98
|
const sessionStartGuidance = isProxiedAgentCall
|
|
99
99
|
? `Session Not Started. REQUIRED ACTION: Call 'fraim_connect' tool first, then include the returned sessionId on every subsequent FRAIM tool call.`
|
|
100
|
-
: `Session Not Started. REQUIRED ACTION: Call 'fraim_connect' tool first with these parameters:
|
|
101
|
-
|
|
102
|
-
{
|
|
103
|
-
"agent": {
|
|
104
|
-
"name": "YourAgentName",
|
|
105
|
-
"model": "your-model-name"
|
|
106
|
-
},
|
|
107
|
-
"machine": {
|
|
108
|
-
"hostname": "use os.hostname()",
|
|
109
|
-
"platform": "use process.platform"
|
|
110
|
-
},
|
|
111
|
-
"repo": {
|
|
112
|
-
"url": "git remote URL",
|
|
113
|
-
"owner": "repo owner",
|
|
114
|
-
"name": "repo name"
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
100
|
+
: `Session Not Started. REQUIRED ACTION: Call 'fraim_connect' tool first with these parameters:
|
|
101
|
+
|
|
102
|
+
{
|
|
103
|
+
"agent": {
|
|
104
|
+
"name": "YourAgentName",
|
|
105
|
+
"model": "your-model-name"
|
|
106
|
+
},
|
|
107
|
+
"machine": {
|
|
108
|
+
"hostname": "use os.hostname()",
|
|
109
|
+
"platform": "use process.platform"
|
|
110
|
+
},
|
|
111
|
+
"repo": {
|
|
112
|
+
"url": "git remote URL",
|
|
113
|
+
"owner": "repo owner",
|
|
114
|
+
"name": "repo name"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
118
|
After successful fraim_connect, all other FRAIM tools will work. This is required for telemetry and session management.`;
|
|
119
119
|
return res.status(400).json({
|
|
120
120
|
jsonrpc: '2.0',
|