@tyvm/knowhow 0.0.155 ā 0.0.157
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/package.json +1 -1
- package/src/agents/base/base.ts +15 -5
- package/src/agents/tools/index.ts +1 -0
- package/src/agents/tools/list.ts +2 -0
- package/src/agents/tools/loadImageAsBase64.ts +83 -0
- package/src/auth/keyAuth.ts +5 -5
- package/src/chat/modules/AgentModule.ts +3 -3
- package/src/chat/modules/RemoteSyncModule.ts +45 -17
- package/src/clients/anthropic.ts +156 -79
- package/src/clients/attribution.ts +53 -0
- package/src/clients/http.ts +211 -84
- package/src/clients/index.ts +21 -9
- package/src/clients/openai.ts +441 -220
- package/src/clients/openrouter.ts +10 -3
- package/src/clients/pricing/openai.ts +15 -1
- package/src/clients/pricing/types.ts +15 -0
- package/src/clients/responseMetadata.ts +221 -0
- package/src/clients/types.ts +49 -4
- package/src/commands/services.ts +23 -18
- package/src/login.ts +22 -6
- package/src/processors/Base64ImageDetector.ts +12 -11
- package/src/tunnel.ts +13 -3
- package/tests/processors/Base64ImageDetector.test.ts +32 -0
- package/tests/unit/agents/tools/loadImageAsBase64.test.ts +44 -0
- package/tests/unit/auth/keyAuth.test.ts +21 -0
- package/tests/unit/clients/anthropic.responseMetadata.test.ts +81 -0
- package/tests/unit/clients/attribution.test.ts +185 -0
- package/tests/unit/clients/http.responseMetadata.test.ts +86 -0
- package/tests/unit/clients/openai.responseMetadata.test.ts +90 -0
- package/tests/unit/clients/responseMetadata.test.ts +123 -0
- package/tests/unit/login.test.ts +39 -1
- package/tests/unit/services/Mcp.test.ts +56 -0
- package/tests/unit/tunnel.test.ts +51 -0
- package/ts_build/package.json +1 -1
- package/ts_build/src/agents/base/base.js +14 -4
- package/ts_build/src/agents/base/base.js.map +1 -1
- package/ts_build/src/agents/tools/index.d.ts +1 -0
- package/ts_build/src/agents/tools/index.js +1 -0
- package/ts_build/src/agents/tools/index.js.map +1 -1
- package/ts_build/src/agents/tools/list.js +2 -0
- package/ts_build/src/agents/tools/list.js.map +1 -1
- package/ts_build/src/agents/tools/loadImageAsBase64.d.ts +3 -0
- package/ts_build/src/agents/tools/loadImageAsBase64.js +79 -0
- package/ts_build/src/agents/tools/loadImageAsBase64.js.map +1 -0
- package/ts_build/src/auth/keyAuth.js +5 -5
- package/ts_build/src/auth/keyAuth.js.map +1 -1
- package/ts_build/src/chat/modules/AgentModule.js +3 -3
- package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
- package/ts_build/src/chat/modules/RemoteSyncModule.d.ts +1 -0
- package/ts_build/src/chat/modules/RemoteSyncModule.js +19 -7
- package/ts_build/src/chat/modules/RemoteSyncModule.js.map +1 -1
- package/ts_build/src/clients/anthropic.d.ts +1 -0
- package/ts_build/src/clients/anthropic.js +83 -38
- package/ts_build/src/clients/anthropic.js.map +1 -1
- package/ts_build/src/clients/attribution.d.ts +2 -0
- package/ts_build/src/clients/attribution.js +32 -0
- package/ts_build/src/clients/attribution.js.map +1 -0
- package/ts_build/src/clients/http.js +100 -20
- package/ts_build/src/clients/http.js.map +1 -1
- package/ts_build/src/clients/index.d.ts +2 -1
- package/ts_build/src/clients/index.js +6 -2
- package/ts_build/src/clients/index.js.map +1 -1
- package/ts_build/src/clients/openai.d.ts +2 -1
- package/ts_build/src/clients/openai.js +225 -99
- package/ts_build/src/clients/openai.js.map +1 -1
- package/ts_build/src/clients/openrouter.d.ts +2 -2
- package/ts_build/src/clients/openrouter.js +6 -2
- package/ts_build/src/clients/openrouter.js.map +1 -1
- package/ts_build/src/clients/pricing/openai.js +15 -1
- package/ts_build/src/clients/pricing/openai.js.map +1 -1
- package/ts_build/src/clients/pricing/types.d.ts +6 -0
- package/ts_build/src/clients/pricing/types.js.map +1 -1
- package/ts_build/src/clients/responseMetadata.d.ts +15 -0
- package/ts_build/src/clients/responseMetadata.js +141 -0
- package/ts_build/src/clients/responseMetadata.js.map +1 -0
- package/ts_build/src/clients/types.d.ts +18 -1
- package/ts_build/src/clients/types.js +2 -1
- package/ts_build/src/clients/types.js.map +1 -1
- package/ts_build/src/commands/services.js +15 -8
- package/ts_build/src/commands/services.js.map +1 -1
- package/ts_build/src/login.js +19 -5
- package/ts_build/src/login.js.map +1 -1
- package/ts_build/src/processors/Base64ImageDetector.js +7 -3
- package/ts_build/src/processors/Base64ImageDetector.js.map +1 -1
- package/ts_build/src/tunnel.js +9 -1
- package/ts_build/src/tunnel.js.map +1 -1
- package/ts_build/tests/processors/Base64ImageDetector.test.js +28 -0
- package/ts_build/tests/processors/Base64ImageDetector.test.js.map +1 -1
- package/ts_build/tests/unit/agents/tools/loadImageAsBase64.test.d.ts +1 -0
- package/ts_build/tests/unit/agents/tools/loadImageAsBase64.test.js +67 -0
- package/ts_build/tests/unit/agents/tools/loadImageAsBase64.test.js.map +1 -0
- package/ts_build/tests/unit/auth/keyAuth.test.js +21 -0
- package/ts_build/tests/unit/auth/keyAuth.test.js.map +1 -1
- package/ts_build/tests/unit/clients/anthropic.responseMetadata.test.d.ts +1 -0
- package/ts_build/tests/unit/clients/anthropic.responseMetadata.test.js +77 -0
- package/ts_build/tests/unit/clients/anthropic.responseMetadata.test.js.map +1 -0
- package/ts_build/tests/unit/clients/attribution.test.d.ts +1 -0
- package/ts_build/tests/unit/clients/attribution.test.js +153 -0
- package/ts_build/tests/unit/clients/attribution.test.js.map +1 -0
- package/ts_build/tests/unit/clients/http.responseMetadata.test.d.ts +1 -0
- package/ts_build/tests/unit/clients/http.responseMetadata.test.js +77 -0
- package/ts_build/tests/unit/clients/http.responseMetadata.test.js.map +1 -0
- package/ts_build/tests/unit/clients/openai.responseMetadata.test.d.ts +1 -0
- package/ts_build/tests/unit/clients/openai.responseMetadata.test.js +86 -0
- package/ts_build/tests/unit/clients/openai.responseMetadata.test.js.map +1 -0
- package/ts_build/tests/unit/clients/responseMetadata.test.d.ts +1 -0
- package/ts_build/tests/unit/clients/responseMetadata.test.js +96 -0
- package/ts_build/tests/unit/clients/responseMetadata.test.js.map +1 -0
- package/ts_build/tests/unit/login.test.js +29 -1
- package/ts_build/tests/unit/login.test.js.map +1 -1
- package/ts_build/tests/unit/services/Mcp.test.d.ts +1 -0
- package/ts_build/tests/unit/services/Mcp.test.js +45 -0
- package/ts_build/tests/unit/services/Mcp.test.js.map +1 -0
- package/ts_build/tests/unit/tunnel.test.d.ts +1 -0
- package/ts_build/tests/unit/tunnel.test.js +47 -0
- package/ts_build/tests/unit/tunnel.test.js.map +1 -0
package/package.json
CHANGED
package/src/agents/base/base.ts
CHANGED
|
@@ -1307,10 +1307,19 @@ export abstract class BaseAgent implements IAgent {
|
|
|
1307
1307
|
this.logStatus();
|
|
1308
1308
|
|
|
1309
1309
|
const continuation = `<Workflow>
|
|
1310
|
-
|
|
1310
|
+
This is an automated runtime instruction, not a new user message.
|
|
1311
|
+
The original user request remains active. Do not say that the user's
|
|
1312
|
+
message was empty, and do not ask the user to repeat the request.
|
|
1313
|
+
|
|
1314
|
+
Your previous response did not terminate the task because it did not
|
|
1315
|
+
call one of the required tools: ${JSON.stringify(
|
|
1311
1316
|
this.requiredToolNames
|
|
1312
|
-
)}
|
|
1313
|
-
|
|
1317
|
+
)}.
|
|
1318
|
+
If your previous response was intended as the final response, call the
|
|
1319
|
+
appropriate required tool now with that response. Otherwise, continue
|
|
1320
|
+
working on the original request and call an appropriate required tool
|
|
1321
|
+
when the task is complete.
|
|
1322
|
+
|
|
1314
1323
|
<TaskStatus>${statusMessage}</TaskStatus>
|
|
1315
1324
|
</Workflow>`;
|
|
1316
1325
|
|
|
@@ -1680,7 +1689,7 @@ export abstract class BaseAgent implements IAgent {
|
|
|
1680
1689
|
}
|
|
1681
1690
|
|
|
1682
1691
|
const taskPrompt = `
|
|
1683
|
-
Analyze all previous messages.
|
|
1692
|
+
TASK INTERRUPT. CONTEXT COMPACTION NEEDED. Analyze all previous messages.
|
|
1684
1693
|
|
|
1685
1694
|
Generate a detailed task breakdown for this conversation, include a section for the following:
|
|
1686
1695
|
1. Task List
|
|
@@ -1737,7 +1746,8 @@ export abstract class BaseAgent implements IAgent {
|
|
|
1737
1746
|
this.log(
|
|
1738
1747
|
`Compressing messages from 0 to ${compressionEnd}, resuming from ${resumeIndex}, total messages: ${messages.length}`
|
|
1739
1748
|
);
|
|
1740
|
-
const toCompressPrompt = `
|
|
1749
|
+
const toCompressPrompt = `TASK INTERRUPT. CONTEXT COMPACTION NEEDED.
|
|
1750
|
+
We are compressing our conversation to save memory.
|
|
1741
1751
|
Please summarize the conversation so far, so that we may continue the original task with a smaller context
|
|
1742
1752
|
|
|
1743
1753
|
Include the following sections:
|
package/src/agents/tools/list.ts
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
stopObservingDefinition,
|
|
21
21
|
} from "./observe";
|
|
22
22
|
import { skillsToolDefinitions } from "./skills";
|
|
23
|
+
import { loadImageAsBase64Definition } from "./loadImageAsBase64";
|
|
23
24
|
|
|
24
25
|
function getPluginNames(): string {
|
|
25
26
|
try {
|
|
@@ -720,6 +721,7 @@ export const includedTools = [
|
|
|
720
721
|
},
|
|
721
722
|
},
|
|
722
723
|
},
|
|
724
|
+
loadImageAsBase64Definition,
|
|
723
725
|
googleSearchDefinition,
|
|
724
726
|
startAgentTaskDefinition,
|
|
725
727
|
replyToParentDefinition,
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { Tool } from "../../clients/types";
|
|
4
|
+
|
|
5
|
+
const MAX_IMAGE_BYTES = 15 * 1024 * 1024;
|
|
6
|
+
|
|
7
|
+
const MIME_TYPES: Record<string, string> = {
|
|
8
|
+
png: "image/png",
|
|
9
|
+
jpg: "image/jpeg",
|
|
10
|
+
jpeg: "image/jpeg",
|
|
11
|
+
gif: "image/gif",
|
|
12
|
+
webp: "image/webp",
|
|
13
|
+
bmp: "image/bmp",
|
|
14
|
+
svg: "image/svg+xml",
|
|
15
|
+
avif: "image/avif",
|
|
16
|
+
ico: "image/x-icon",
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function detectMimeType(buffer: Buffer, fallback: string): string {
|
|
20
|
+
if (buffer.length >= 3 && buffer[0] === 0xff && buffer[1] === 0xd8 && buffer[2] === 0xff) {
|
|
21
|
+
return "image/jpeg";
|
|
22
|
+
}
|
|
23
|
+
if (buffer.length >= 4 && buffer[0] === 0x89 && buffer[1] === 0x50 && buffer[2] === 0x4e && buffer[3] === 0x47) {
|
|
24
|
+
return "image/png";
|
|
25
|
+
}
|
|
26
|
+
if (buffer.length >= 4 && buffer.subarray(0, 4).toString("ascii") === "GIF8") {
|
|
27
|
+
return "image/gif";
|
|
28
|
+
}
|
|
29
|
+
if (
|
|
30
|
+
buffer.length >= 12 &&
|
|
31
|
+
buffer.subarray(0, 4).toString("ascii") === "RIFF" &&
|
|
32
|
+
buffer.subarray(8, 12).toString("ascii") === "WEBP"
|
|
33
|
+
) {
|
|
34
|
+
return "image/webp";
|
|
35
|
+
}
|
|
36
|
+
return fallback;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Load a reasonably sized image from the worker filesystem for UI/AI preview. */
|
|
40
|
+
export async function loadImageAsBase64(
|
|
41
|
+
filePath: string,
|
|
42
|
+
detail: "auto" | "low" | "high" = "auto"
|
|
43
|
+
): Promise<string> {
|
|
44
|
+
const stats = await fs.promises.stat(filePath).catch(() => null);
|
|
45
|
+
if (!stats) throw new Error(`File not found: ${filePath}`);
|
|
46
|
+
if (!stats.isFile()) throw new Error(`Path is not a file: ${filePath}`);
|
|
47
|
+
if (stats.size > MAX_IMAGE_BYTES) {
|
|
48
|
+
throw new Error(`Image is too large to preview (${Math.ceil(stats.size / 1024 / 1024)} MB; maximum 15 MB)`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const extension = path.extname(filePath).slice(1).toLowerCase();
|
|
52
|
+
const extensionMimeType = MIME_TYPES[extension];
|
|
53
|
+
if (!extensionMimeType) {
|
|
54
|
+
throw new Error(`Unsupported image format: ${extension || "unknown"}`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const image = await fs.promises.readFile(filePath);
|
|
58
|
+
const mimeType = detectMimeType(image, extensionMimeType);
|
|
59
|
+
return JSON.stringify({
|
|
60
|
+
type: "image_url",
|
|
61
|
+
image_url: {
|
|
62
|
+
url: `data:${mimeType};base64,${image.toString("base64")}`,
|
|
63
|
+
detail,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const loadImageAsBase64Definition: Tool = {
|
|
69
|
+
type: "function",
|
|
70
|
+
function: {
|
|
71
|
+
name: "loadImageAsBase64",
|
|
72
|
+
description: "Load an image from the worker filesystem and return it as a base64 data URL for previewing.",
|
|
73
|
+
parameters: {
|
|
74
|
+
type: "object",
|
|
75
|
+
positional: true,
|
|
76
|
+
properties: {
|
|
77
|
+
filePath: { type: "string", description: "Absolute or workspace-relative image path" },
|
|
78
|
+
detail: { type: "string", enum: ["auto", "low", "high"], description: "Image detail hint" },
|
|
79
|
+
},
|
|
80
|
+
required: ["filePath"],
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
};
|
package/src/auth/keyAuth.ts
CHANGED
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
signMessage,
|
|
11
11
|
} from "./keyManager";
|
|
12
12
|
|
|
13
|
-
const JWT_FILE_PATH = path.join(process.cwd(), ".knowhow", ".jwt");
|
|
14
13
|
const DEFAULT_API_URL = process.env.KNOWHOW_API_URL || "https://api.knowhow.tyvm.ai";
|
|
15
14
|
|
|
16
15
|
/**
|
|
@@ -140,13 +139,14 @@ export async function registerPublicKey(
|
|
|
140
139
|
}
|
|
141
140
|
|
|
142
141
|
export function storeJwt(jwt: string): void {
|
|
143
|
-
const
|
|
144
|
-
const
|
|
142
|
+
const jwtFilePath = path.join(process.cwd(), ".knowhow", ".jwt");
|
|
143
|
+
const directory = path.dirname(jwtFilePath);
|
|
144
|
+
const temporaryPath = `${jwtFilePath}.${process.pid}.tmp`;
|
|
145
145
|
fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
146
146
|
try {
|
|
147
147
|
fs.writeFileSync(temporaryPath, jwt, { mode: 0o600, flag: "wx" });
|
|
148
|
-
fs.renameSync(temporaryPath,
|
|
149
|
-
fs.chmodSync(
|
|
148
|
+
fs.renameSync(temporaryPath, jwtFilePath);
|
|
149
|
+
fs.chmodSync(jwtFilePath, 0o600);
|
|
150
150
|
} finally {
|
|
151
151
|
fs.rmSync(temporaryPath, { force: true });
|
|
152
152
|
}
|
|
@@ -810,7 +810,7 @@ export class AgentModule extends BaseChatModule {
|
|
|
810
810
|
// Match new interactive threads: local-only sessions get a fresh remote
|
|
811
811
|
// task when auto-sync is enabled.
|
|
812
812
|
if (!remoteTaskId && this.remoteSyncModule?.isAutoSyncEnabled()) {
|
|
813
|
-
|
|
813
|
+
this.remoteSyncModule.syncTaskInBackground(taskId);
|
|
814
814
|
}
|
|
815
815
|
|
|
816
816
|
// After resume finishes, revert to normal chat (non-agent mode) so the
|
|
@@ -1471,7 +1471,7 @@ export class AgentModule extends BaseChatModule {
|
|
|
1471
1471
|
!remoteTaskId &&
|
|
1472
1472
|
this.remoteSyncModule?.isAutoSyncEnabled()
|
|
1473
1473
|
) {
|
|
1474
|
-
|
|
1474
|
+
this.remoteSyncModule.syncTaskInBackground(result.taskId);
|
|
1475
1475
|
}
|
|
1476
1476
|
|
|
1477
1477
|
await this.attachedAgentChatLoop(
|
|
@@ -1566,7 +1566,7 @@ export class AgentModule extends BaseChatModule {
|
|
|
1566
1566
|
|
|
1567
1567
|
// If auto-sync is enabled, push this task to the remote KnowHow app
|
|
1568
1568
|
if (this.remoteSyncModule?.isAutoSyncEnabled()) {
|
|
1569
|
-
|
|
1569
|
+
this.remoteSyncModule.syncTaskInBackground(taskId);
|
|
1570
1570
|
}
|
|
1571
1571
|
|
|
1572
1572
|
await this.attachedAgentChatLoop(taskId, agent, formattedPrompt);
|
|
@@ -14,6 +14,7 @@ import { AgentSyncFs } from "../../services/AgentSyncFs";
|
|
|
14
14
|
import { AgentModule } from "./AgentModule";
|
|
15
15
|
import { TaskInfo } from "../types";
|
|
16
16
|
import { getConfig, updateConfig } from "../../config";
|
|
17
|
+
import { withRetry } from "../../clients/withRetry";
|
|
17
18
|
|
|
18
19
|
@TraceAll()
|
|
19
20
|
export class RemoteSyncModule extends BaseChatModule {
|
|
@@ -44,6 +45,22 @@ export class RemoteSyncModule extends BaseChatModule {
|
|
|
44
45
|
this.client = new KnowhowSimpleClient(KNOWHOW_API_URL);
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Start an automatic sync without delaying agent execution. Manual syncs use
|
|
50
|
+
* syncTask directly so the command still waits for and reports its result.
|
|
51
|
+
*/
|
|
52
|
+
public syncTaskInBackground(taskId: string): void {
|
|
53
|
+
void this.syncTask(taskId).catch((error: unknown) => {
|
|
54
|
+
// syncTask handles expected API failures itself. Keep this final guard so
|
|
55
|
+
// an unexpected failure can never become an unhandled rejection.
|
|
56
|
+
console.error(
|
|
57
|
+
`ā Unexpected remote sync failure: ${
|
|
58
|
+
error instanceof Error ? error.message : String(error)
|
|
59
|
+
}`
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
47
64
|
/**
|
|
48
65
|
* On initialize, read config to set initial autoSync state.
|
|
49
66
|
*/
|
|
@@ -157,11 +174,15 @@ export class RemoteSyncModule extends BaseChatModule {
|
|
|
157
174
|
}
|
|
158
175
|
|
|
159
176
|
console.log("š” Creating remote session for this terminal session...");
|
|
160
|
-
const result = await
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
177
|
+
const result = await withRetry(
|
|
178
|
+
() =>
|
|
179
|
+
this.client.createSessionPlaceholder({
|
|
180
|
+
title: title.slice(0, 80) || "CLI Session",
|
|
181
|
+
workerId: this.workerId,
|
|
182
|
+
metadata: { source: "cli", createdAt: new Date().toISOString() },
|
|
183
|
+
}),
|
|
184
|
+
{ maxRetries: 3, backoffMs: 500 }
|
|
185
|
+
);
|
|
165
186
|
|
|
166
187
|
this.remoteSessionId = result.sessionId;
|
|
167
188
|
console.log(`ā
Remote session created: ${result.sessionId}`);
|
|
@@ -177,12 +198,16 @@ export class RemoteSyncModule extends BaseChatModule {
|
|
|
177
198
|
agentName?: string,
|
|
178
199
|
modelName?: string
|
|
179
200
|
): Promise<{ messageId: string; taskId: string | undefined }> {
|
|
180
|
-
const result = await
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
201
|
+
const result = await withRetry(
|
|
202
|
+
() =>
|
|
203
|
+
this.client.createMessagePlaceholder(sessionId, {
|
|
204
|
+
content: prompt,
|
|
205
|
+
agentName,
|
|
206
|
+
modelName,
|
|
207
|
+
metadata: { source: "cli", createdAt: new Date().toISOString() },
|
|
208
|
+
}),
|
|
209
|
+
{ maxRetries: 3, backoffMs: 500 }
|
|
210
|
+
);
|
|
186
211
|
return { messageId: result.messageId, taskId: result.taskId };
|
|
187
212
|
}
|
|
188
213
|
|
|
@@ -273,7 +298,10 @@ export class RemoteSyncModule extends BaseChatModule {
|
|
|
273
298
|
try {
|
|
274
299
|
// Step 1: Ensure remote session exists
|
|
275
300
|
console.log("\nš Checking KnowHow API credentials...");
|
|
276
|
-
const me = await this.client.me()
|
|
301
|
+
const me = await withRetry(() => this.client.me(), {
|
|
302
|
+
maxRetries: 3,
|
|
303
|
+
backoffMs: 500,
|
|
304
|
+
});
|
|
277
305
|
console.log(`ā
Authenticated as ${me.data?.email || "unknown"}`);
|
|
278
306
|
|
|
279
307
|
const title =
|
|
@@ -341,13 +369,13 @@ export class RemoteSyncModule extends BaseChatModule {
|
|
|
341
369
|
|
|
342
370
|
this.syncedMessageCount++;
|
|
343
371
|
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
)
|
|
372
|
+
const chatUrl = new URL(KNOWHOW_API_URL);
|
|
373
|
+
chatUrl.hostname = chatUrl.hostname.replace(/^api\./, "");
|
|
374
|
+
chatUrl.pathname = chatUrl.pathname.replace(/\/api\/?$/, "");
|
|
375
|
+
chatUrl.pathname = `${chatUrl.pathname.replace(/\/$/, "")}/chat/${sessionId}`;
|
|
348
376
|
console.log(
|
|
349
377
|
`\nš¾ Local session updated with remote IDs.\n` +
|
|
350
|
-
`š View your task at: ${
|
|
378
|
+
`š View your task at: ${chatUrl.toString()}`
|
|
351
379
|
);
|
|
352
380
|
} catch (error: any) {
|
|
353
381
|
console.error(
|