tarsk 0.5.43 → 0.5.44
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/dist/index.js +318 -144
- package/dist/public/assets/{account-view-xKotpUyx.js → account-view-CTizS7Yb.js} +1 -1
- package/dist/public/assets/{api-D6uLdHBQ.js → api-Cuj9iSVv.js} +1 -1
- package/dist/public/assets/{browser-tab-DxigYzoT.js → browser-tab-DSpOIu84.js} +1 -1
- package/dist/public/assets/commit-dialog-kTaKOsNO.js +1 -0
- package/dist/public/assets/{context-menu-rC7iWcty.js → context-menu-DRXV-Suu.js} +1 -1
- package/dist/public/assets/create-repo-dialog-gIZLk6LZ.js +1 -0
- package/dist/public/assets/dialogs-config-CxRnlUcQ.js +51 -0
- package/dist/public/assets/diff-view-B2OdJMRe.js +3 -0
- package/dist/public/assets/explorer-tab-view-fejcb7N1.js +2 -0
- package/dist/public/assets/{explorer-tree-BC4fBpxi.js → explorer-tree-C2kLAwI0.js} +1 -1
- package/dist/public/assets/{explorer-view-DIM08sdy.js → explorer-view-BmKKHyrH.js} +1 -1
- package/dist/public/assets/git-history-dialog-B2ABiCXZ.js +1 -0
- package/dist/public/assets/git-ops-button-Bxx_jyqR.js +2 -0
- package/dist/public/assets/history-view-DebwP9D7.js +9 -0
- package/dist/public/assets/{index-DKOXV50p.css → index-C2_gO3dh.css} +1 -1
- package/dist/public/assets/index-D9aY24hf.js +89 -0
- package/dist/public/assets/{mcp-server-card-Cy4RU2_Q.js → mcp-server-card-B6iwOybN.js} +1 -1
- package/dist/public/assets/merged-pr-dialog-CObeSEaB.js +1 -0
- package/dist/public/assets/{model-star-rating-BmkpdXfr.js → model-star-rating-BgdOyTTO.js} +1 -1
- package/dist/public/assets/onboarding-BN_K08ma.js +1 -0
- package/dist/public/assets/project-settings-view-BDvHOmF8.js +1 -0
- package/dist/public/assets/providers-list-view-DydWz8z3.js +1 -0
- package/dist/public/assets/pull-request-dialog-LJhZpT8C.js +1 -0
- package/dist/public/assets/pull-with-changes-dialog-BPIj9wIk.js +1 -0
- package/dist/public/assets/push-before-pr-dialog-DzBp93KT.js +1 -0
- package/dist/public/assets/{radio-group-CbatNaj1.js → radio-group-B9xMCZ1X.js} +1 -1
- package/dist/public/assets/react-vendor-CE5Dmjd0.js +16 -0
- package/dist/public/assets/settings-general-view-D_44BPVr.js +1 -0
- package/dist/public/assets/{settings-instructions-view-DMAjbi6E.js → settings-instructions-view-Y6EK67-G.js} +1 -1
- package/dist/public/assets/{settings-list-B8hiBkBz.js → settings-list-BZDwK9bE.js} +1 -1
- package/dist/public/assets/settings-mcp-servers-view-B8IqOOnN.js +5 -0
- package/dist/public/assets/{settings-models-skeleton-DPnYbg69.js → settings-models-skeleton-DAEnT4kC.js} +1 -1
- package/dist/public/assets/settings-models-view-CluPgRkw.js +1 -0
- package/dist/public/assets/{settings-rules-view-DBk7DzV2.js → settings-rules-view-CxHrCDwn.js} +3 -3
- package/dist/public/assets/settings-skills-view-BE9u6FvJ.js +2 -0
- package/dist/public/assets/settings-slash-commands-view-CVOZ3GH3.js +1 -0
- package/dist/public/assets/{settings-subagents-view-D98Nxoly.js → settings-subagents-view-mguSf6zE.js} +2 -2
- package/dist/public/assets/settings-system-prompt-view-0sXVxXh3.js +1 -0
- package/dist/public/assets/settings-view-BE8EW7s7.js +2 -0
- package/dist/public/assets/{skeleton-BHhGML7J.js → skeleton-CVhaOA8k.js} +1 -1
- package/dist/public/assets/{slug-utils-DyRUJ1NS.js → slug-utils-DGOwJkKI.js} +1 -1
- package/dist/public/assets/{terminal-panel-DTOx74_o.js → terminal-panel-PjkgqbY6.js} +1 -1
- package/dist/public/assets/{ui-components-Jc6oi6bz.js → ui-components-DaffuSG7.js} +1 -1
- package/dist/public/assets/{use-deferred-search-B7EdyRbt.js → use-deferred-search-b843Ztu9.js} +1 -1
- package/dist/public/assets/{utils-tgi5ym_d.js → utils-BIt9KCVx.js} +1 -1
- package/dist/public/assets/vosk-speech-CgILeNJR.js +2 -0
- package/dist/public/assets/{web-CUAWBWPy.js → web-BBGaE-6B.js} +1 -1
- package/dist/public/assets/{web-C3vJZ_3_.js → web-D6dBzWD1.js} +1 -1
- package/dist/public/index.html +8 -8
- package/package.json +1 -1
- package/dist/public/assets/commit-dialog-CLQM9ah3.js +0 -1
- package/dist/public/assets/create-repo-dialog-C6k5wZPW.js +0 -1
- package/dist/public/assets/dialogs-config-CjKh5Rl2.js +0 -51
- package/dist/public/assets/diff-view-DWDWI5nl.js +0 -3
- package/dist/public/assets/explorer-tab-view-B0kT8Hl6.js +0 -2
- package/dist/public/assets/git-history-dialog-CuxOTngT.js +0 -1
- package/dist/public/assets/git-ops-button-C04zFAnF.js +0 -2
- package/dist/public/assets/history-view-ar7GLZ-R.js +0 -9
- package/dist/public/assets/index--HY4BbcM.js +0 -90
- package/dist/public/assets/merged-pr-dialog-Bo07VouF.js +0 -1
- package/dist/public/assets/onboarding-ClZrOxX7.js +0 -1
- package/dist/public/assets/project-settings-view-Dm9pQAp_.js +0 -1
- package/dist/public/assets/providers-list-view-D5gHsjl_.js +0 -1
- package/dist/public/assets/pull-request-dialog-8AYlOUNX.js +0 -1
- package/dist/public/assets/pull-with-changes-dialog-CSa5OE-d.js +0 -1
- package/dist/public/assets/push-before-pr-dialog-D5W_xsqv.js +0 -1
- package/dist/public/assets/react-vendor-DwQYi7es.js +0 -16
- package/dist/public/assets/settings-general-view-BP5ULy9A.js +0 -1
- package/dist/public/assets/settings-mcp-servers-view-OimQz-Rd.js +0 -5
- package/dist/public/assets/settings-models-view-Fq3WtdKG.js +0 -1
- package/dist/public/assets/settings-skills-view-CmOw-WMM.js +0 -2
- package/dist/public/assets/settings-slash-commands-view-FsrF5FkK.js +0 -1
- package/dist/public/assets/settings-system-prompt-view-B6Hy9ZyK.js +0 -1
- package/dist/public/assets/settings-view-J-rjoRcU.js +0 -2
- package/dist/public/assets/whisper-wasm-CWcbC1MB.js +0 -2
- package/dist/public/wasm/libmain-CWYJvMY5.js +0 -3318
- package/dist/public/wasm/libmain-D9-QM3iM.mjs +0 -3301
package/dist/index.js
CHANGED
|
@@ -9080,12 +9080,87 @@ function stageAllChanges(gitRoot) {
|
|
|
9080
9080
|
proc.on("error", reject);
|
|
9081
9081
|
});
|
|
9082
9082
|
}
|
|
9083
|
+
function getCommitCount(gitRoot) {
|
|
9084
|
+
return new Promise((resolve8, reject) => {
|
|
9085
|
+
const proc = spawnProcess("git", ["rev-list", "--count", "HEAD"], { cwd: gitRoot });
|
|
9086
|
+
let out = "";
|
|
9087
|
+
let err = "";
|
|
9088
|
+
if (proc.stdout) {
|
|
9089
|
+
proc.stdout.on("data", (d) => {
|
|
9090
|
+
out += d.toString();
|
|
9091
|
+
});
|
|
9092
|
+
}
|
|
9093
|
+
if (proc.stderr) {
|
|
9094
|
+
proc.stderr.on("data", (d) => {
|
|
9095
|
+
err += d.toString();
|
|
9096
|
+
});
|
|
9097
|
+
}
|
|
9098
|
+
proc.on("close", (code) => {
|
|
9099
|
+
if (code === 0) {
|
|
9100
|
+
resolve8(parseInt(out.trim(), 10) || 0);
|
|
9101
|
+
return;
|
|
9102
|
+
}
|
|
9103
|
+
if (/unknown revision|ambiguous argument|does not have any commits yet|bad revision|needed a single revision/i.test(
|
|
9104
|
+
err
|
|
9105
|
+
)) {
|
|
9106
|
+
resolve8(0);
|
|
9107
|
+
return;
|
|
9108
|
+
}
|
|
9109
|
+
reject(new Error(err.trim() || "Failed to count commits"));
|
|
9110
|
+
});
|
|
9111
|
+
proc.on("error", reject);
|
|
9112
|
+
});
|
|
9113
|
+
}
|
|
9114
|
+
function checkBranchExists(gitRoot, branchName) {
|
|
9115
|
+
return new Promise((resolve8) => {
|
|
9116
|
+
const proc = spawnProcess(
|
|
9117
|
+
"git",
|
|
9118
|
+
["show-ref", "--verify", "--quiet", `refs/heads/${branchName}`],
|
|
9119
|
+
{
|
|
9120
|
+
cwd: gitRoot
|
|
9121
|
+
}
|
|
9122
|
+
);
|
|
9123
|
+
proc.on("close", (code) => {
|
|
9124
|
+
resolve8(code === 0);
|
|
9125
|
+
});
|
|
9126
|
+
proc.on("error", () => {
|
|
9127
|
+
resolve8(false);
|
|
9128
|
+
});
|
|
9129
|
+
});
|
|
9130
|
+
}
|
|
9131
|
+
function renameCurrentBranch(gitRoot, newBranchName) {
|
|
9132
|
+
return new Promise((resolve8, reject) => {
|
|
9133
|
+
const proc = spawnProcess("git", ["branch", "-m", newBranchName], {
|
|
9134
|
+
cwd: gitRoot
|
|
9135
|
+
});
|
|
9136
|
+
let err = "";
|
|
9137
|
+
if (proc.stderr) {
|
|
9138
|
+
proc.stderr.on("data", (d) => {
|
|
9139
|
+
err += d.toString();
|
|
9140
|
+
});
|
|
9141
|
+
}
|
|
9142
|
+
proc.on("close", (code) => {
|
|
9143
|
+
if (code === 0) {
|
|
9144
|
+
resolve8();
|
|
9145
|
+
} else {
|
|
9146
|
+
reject(new Error(err || `Failed to rename branch to "${newBranchName}"`));
|
|
9147
|
+
}
|
|
9148
|
+
});
|
|
9149
|
+
proc.on("error", reject);
|
|
9150
|
+
});
|
|
9151
|
+
}
|
|
9083
9152
|
function commitChanges(gitRoot, message) {
|
|
9084
9153
|
return new Promise((resolve8, reject) => {
|
|
9085
9154
|
const proc = spawnProcess("git", ["commit", "-m", message], { cwd: gitRoot });
|
|
9155
|
+
let err = "";
|
|
9156
|
+
if (proc.stderr) {
|
|
9157
|
+
proc.stderr.on("data", (d) => {
|
|
9158
|
+
err += d.toString();
|
|
9159
|
+
});
|
|
9160
|
+
}
|
|
9086
9161
|
proc.on("close", (code) => {
|
|
9087
|
-
if (code === 0) resolve8();
|
|
9088
|
-
else reject(new Error("Failed to commit changes"));
|
|
9162
|
+
if (code === 0) resolve8({ createdCommit: true });
|
|
9163
|
+
else reject(new Error(err.trim() || "Failed to commit changes"));
|
|
9089
9164
|
});
|
|
9090
9165
|
proc.on("error", reject);
|
|
9091
9166
|
});
|
|
@@ -14661,7 +14736,8 @@ async function postChatMessage(c, threadManager, agentExecutor, conversationMana
|
|
|
14661
14736
|
attachments,
|
|
14662
14737
|
planMode,
|
|
14663
14738
|
ralphMode,
|
|
14664
|
-
checkpointRef
|
|
14739
|
+
checkpointRef,
|
|
14740
|
+
conversationId: requestedConversationId
|
|
14665
14741
|
} = body;
|
|
14666
14742
|
let model = baseModel;
|
|
14667
14743
|
if (provider && typeof provider === "string") {
|
|
@@ -14758,7 +14834,7 @@ async function postChatMessage(c, threadManager, agentExecutor, conversationMana
|
|
|
14758
14834
|
}
|
|
14759
14835
|
return streamAsyncGenerator(c, replayGenerator());
|
|
14760
14836
|
}
|
|
14761
|
-
let conversationId = thread.currentConversationId;
|
|
14837
|
+
let conversationId = typeof requestedConversationId === "string" && requestedConversationId.length > 0 ? requestedConversationId : thread.currentConversationId;
|
|
14762
14838
|
if (!conversationId) {
|
|
14763
14839
|
conversationId = randomUUID8();
|
|
14764
14840
|
const db2 = await getDatabase();
|
|
@@ -19449,7 +19525,8 @@ import { rm as rm4 } from "fs/promises";
|
|
|
19449
19525
|
// src/agent/agent.process-manager.ts
|
|
19450
19526
|
init_utils();
|
|
19451
19527
|
import { EventEmitter } from "events";
|
|
19452
|
-
|
|
19528
|
+
|
|
19529
|
+
// src/core/dev-server-url-detector.ts
|
|
19453
19530
|
var URL_PATTERNS = [
|
|
19454
19531
|
// http(s)://localhost:PORT
|
|
19455
19532
|
/https?:\/\/localhost[:/](\d+)/i,
|
|
@@ -19462,6 +19539,24 @@ var URL_PATTERNS = [
|
|
|
19462
19539
|
// Local address patterns like http://192.168...
|
|
19463
19540
|
/https?:\/\/(192\.168\.\d+\.\d+):(\d+)/i
|
|
19464
19541
|
];
|
|
19542
|
+
function detectDevServerUrl(text) {
|
|
19543
|
+
for (const pattern of URL_PATTERNS) {
|
|
19544
|
+
const match = text.match(pattern);
|
|
19545
|
+
if (match) {
|
|
19546
|
+
if (match[1] && !match[0].includes("://")) {
|
|
19547
|
+
if (match[0].startsWith("127.0.0.1:")) {
|
|
19548
|
+
return `http://${match[0]}`;
|
|
19549
|
+
}
|
|
19550
|
+
return `http://localhost:${match[1]}`;
|
|
19551
|
+
}
|
|
19552
|
+
return match[0];
|
|
19553
|
+
}
|
|
19554
|
+
}
|
|
19555
|
+
return void 0;
|
|
19556
|
+
}
|
|
19557
|
+
|
|
19558
|
+
// src/agent/agent.process-manager.ts
|
|
19559
|
+
init_tarsk_debug();
|
|
19465
19560
|
var ProcessManager = class extends EventEmitter {
|
|
19466
19561
|
processes = /* @__PURE__ */ new Map();
|
|
19467
19562
|
detectedUrls = /* @__PURE__ */ new Map();
|
|
@@ -19537,7 +19632,7 @@ var ProcessManager = class extends EventEmitter {
|
|
|
19537
19632
|
const text = data.toString();
|
|
19538
19633
|
urlBuffer += text;
|
|
19539
19634
|
if (!urlDetected) {
|
|
19540
|
-
const detectedUrl =
|
|
19635
|
+
const detectedUrl = detectDevServerUrl(urlBuffer);
|
|
19541
19636
|
if (detectedUrl) {
|
|
19542
19637
|
urlDetected = true;
|
|
19543
19638
|
this.detectedUrls.set(projectId, detectedUrl);
|
|
@@ -19551,7 +19646,7 @@ var ProcessManager = class extends EventEmitter {
|
|
|
19551
19646
|
const text = data.toString();
|
|
19552
19647
|
urlBuffer += text;
|
|
19553
19648
|
if (!urlDetected) {
|
|
19554
|
-
const detectedUrl =
|
|
19649
|
+
const detectedUrl = detectDevServerUrl(urlBuffer);
|
|
19555
19650
|
if (detectedUrl) {
|
|
19556
19651
|
urlDetected = true;
|
|
19557
19652
|
this.detectedUrls.set(projectId, detectedUrl);
|
|
@@ -19642,23 +19737,6 @@ var ProcessManager = class extends EventEmitter {
|
|
|
19642
19737
|
getDetectedUrl(projectId) {
|
|
19643
19738
|
return this.detectedUrls.get(projectId);
|
|
19644
19739
|
}
|
|
19645
|
-
/**
|
|
19646
|
-
* Detect URL from text output
|
|
19647
|
-
* @param text - The text to search for URLs
|
|
19648
|
-
* @returns The first detected URL or undefined
|
|
19649
|
-
*/
|
|
19650
|
-
detectUrl(text) {
|
|
19651
|
-
for (const pattern of URL_PATTERNS) {
|
|
19652
|
-
const match = text.match(pattern);
|
|
19653
|
-
if (match) {
|
|
19654
|
-
if (match[1] && !match[0].includes("://")) {
|
|
19655
|
-
return `http://localhost:${match[1]}`;
|
|
19656
|
-
}
|
|
19657
|
-
return match[0];
|
|
19658
|
-
}
|
|
19659
|
-
}
|
|
19660
|
-
return void 0;
|
|
19661
|
-
}
|
|
19662
19740
|
};
|
|
19663
19741
|
|
|
19664
19742
|
// src/features/projects/projects.creator.ts
|
|
@@ -20829,10 +20907,10 @@ async function loadUtils() {
|
|
|
20829
20907
|
}
|
|
20830
20908
|
}
|
|
20831
20909
|
var ProjectCreator = class {
|
|
20832
|
-
constructor(rootFolder, metadataManager,
|
|
20910
|
+
constructor(rootFolder, metadataManager, gitManager2, processingStateManager, runCommandCallbacks) {
|
|
20833
20911
|
this.rootFolder = rootFolder;
|
|
20834
20912
|
this.metadataManager = metadataManager;
|
|
20835
|
-
this.gitManager =
|
|
20913
|
+
this.gitManager = gitManager2;
|
|
20836
20914
|
this.processingStateManager = processingStateManager;
|
|
20837
20915
|
this.runCommandCallbacks = runCommandCallbacks;
|
|
20838
20916
|
}
|
|
@@ -21526,7 +21604,7 @@ var ProjectManagerImpl = class {
|
|
|
21526
21604
|
* - 1.1 - WHEN a user provides a git URL to create a new Project, THE CLI SHALL clone the repository into a folder under the Root_Folder
|
|
21527
21605
|
* - 1.4 - THE CLI SHALL determine the storage path for each Project folder
|
|
21528
21606
|
*/
|
|
21529
|
-
constructor(rootFolder, metadataManager,
|
|
21607
|
+
constructor(rootFolder, metadataManager, gitManager2, processingStateManager) {
|
|
21530
21608
|
this.rootFolder = rootFolder;
|
|
21531
21609
|
this.metadataManager = metadataManager;
|
|
21532
21610
|
this.processManager = new ProcessManager();
|
|
@@ -21535,7 +21613,7 @@ var ProjectManagerImpl = class {
|
|
|
21535
21613
|
this.projectCreator = new ProjectCreator(
|
|
21536
21614
|
rootFolder,
|
|
21537
21615
|
metadataManager,
|
|
21538
|
-
|
|
21616
|
+
gitManager2,
|
|
21539
21617
|
processingStateManager,
|
|
21540
21618
|
{
|
|
21541
21619
|
suggestRunCommand: (id) => this.suggestRunCommand(id),
|
|
@@ -23326,9 +23404,9 @@ var ThreadManagerImpl = class {
|
|
|
23326
23404
|
* - 2.1 - WHEN a user creates a new Thread for a Project, THE CLI SHALL create a new clone of the Project's git repository
|
|
23327
23405
|
* - 2.4 - THE System SHALL maintain a title for each Thread
|
|
23328
23406
|
*/
|
|
23329
|
-
constructor(metadataManager,
|
|
23407
|
+
constructor(metadataManager, gitManager2, processingStateManager, rootFolder = "") {
|
|
23330
23408
|
this.metadataManager = metadataManager;
|
|
23331
|
-
this.gitManager =
|
|
23409
|
+
this.gitManager = gitManager2;
|
|
23332
23410
|
this.processingStateManager = processingStateManager;
|
|
23333
23411
|
this.rootFolder = rootFolder;
|
|
23334
23412
|
}
|
|
@@ -23807,7 +23885,7 @@ function validateThreadName(name) {
|
|
|
23807
23885
|
}
|
|
23808
23886
|
|
|
23809
23887
|
// src/features/threads/threads-create.route.ts
|
|
23810
|
-
async function handleCreateThread(c, threadManager,
|
|
23888
|
+
async function handleCreateThread(c, threadManager, gitManager2) {
|
|
23811
23889
|
try {
|
|
23812
23890
|
const body = await c.req.json();
|
|
23813
23891
|
const { projectId, title } = body;
|
|
@@ -23833,11 +23911,11 @@ async function handleCreateThread(c, threadManager, gitManager) {
|
|
|
23833
23911
|
return errorResponse(c, ErrorCodes.INVALID_REQUEST, nameError, 400);
|
|
23834
23912
|
}
|
|
23835
23913
|
const existingThreads = await threadManager.listThreads(projectId);
|
|
23836
|
-
const sanitizedNewName =
|
|
23837
|
-
const existingSanitized = existingThreads.map((t) =>
|
|
23914
|
+
const sanitizedNewName = gitManager2.sanitizeBranchName(title);
|
|
23915
|
+
const existingSanitized = existingThreads.map((t) => gitManager2.sanitizeBranchName(t.title));
|
|
23838
23916
|
if (existingSanitized.includes(sanitizedNewName)) {
|
|
23839
23917
|
let fallbackTitle = generateRandomThreadName();
|
|
23840
|
-
while (existingSanitized.includes(
|
|
23918
|
+
while (existingSanitized.includes(gitManager2.sanitizeBranchName(fallbackTitle))) {
|
|
23841
23919
|
fallbackTitle = generateRandomThreadName();
|
|
23842
23920
|
}
|
|
23843
23921
|
return streamAsyncGenerator(c, threadManager.createThread(projectId, fallbackTitle));
|
|
@@ -24441,9 +24519,11 @@ async function handleGetThreadMessages(c, threadManager, conversationManager) {
|
|
|
24441
24519
|
if (!thread) {
|
|
24442
24520
|
return errorResponse(c, ErrorCodes.THREAD_NOT_FOUND, `Thread not found: ${threadId}`, 404);
|
|
24443
24521
|
}
|
|
24444
|
-
const
|
|
24522
|
+
const requestedConversationId = c.req.query("conversationId");
|
|
24523
|
+
const targetConversationId = typeof requestedConversationId === "string" && requestedConversationId.length > 0 ? requestedConversationId : thread.currentConversationId;
|
|
24524
|
+
const history = targetConversationId ? await conversationManager.getConversationHistoryByConversationId(
|
|
24445
24525
|
threadId,
|
|
24446
|
-
|
|
24526
|
+
targetConversationId
|
|
24447
24527
|
) : await conversationManager.getConversationHistory(threadId);
|
|
24448
24528
|
if (!history || history.messages.length === 0) {
|
|
24449
24529
|
return c.json([]);
|
|
@@ -25568,17 +25648,22 @@ init_utils();
|
|
|
25568
25648
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
25569
25649
|
var ScriptProcessManager = class {
|
|
25570
25650
|
processes = /* @__PURE__ */ new Map();
|
|
25651
|
+
threadIds = /* @__PURE__ */ new Map();
|
|
25571
25652
|
/**
|
|
25572
25653
|
* Run a script and stream its output
|
|
25573
25654
|
* @param key - Unique key for this script (e.g. "projectId:scriptName")
|
|
25574
25655
|
* @param command - The shell command to run
|
|
25575
25656
|
* @param cwd - Working directory for the command
|
|
25657
|
+
* @param threadId - Optional thread ID for dev server URL caching
|
|
25576
25658
|
* @yields Output chunks from stdout/stderr
|
|
25577
25659
|
*/
|
|
25578
|
-
async *runScript(key, command, cwd) {
|
|
25660
|
+
async *runScript(key, command, cwd, threadId) {
|
|
25579
25661
|
if (this.processes.has(key)) {
|
|
25580
25662
|
this.stopScript(key);
|
|
25581
25663
|
}
|
|
25664
|
+
if (threadId) {
|
|
25665
|
+
this.threadIds.set(key, threadId);
|
|
25666
|
+
}
|
|
25582
25667
|
const { shell, args: shellArgs } = getShellConfig();
|
|
25583
25668
|
const child = spawnProcess(shell, [...shellArgs, command], {
|
|
25584
25669
|
cwd,
|
|
@@ -25594,16 +25679,39 @@ var ScriptProcessManager = class {
|
|
|
25594
25679
|
const decoder = new TextDecoder();
|
|
25595
25680
|
const outputBuffer = [];
|
|
25596
25681
|
let isDone = false;
|
|
25682
|
+
let urlDetected = false;
|
|
25683
|
+
let urlBuffer = "";
|
|
25684
|
+
function appendOutput(text, isError) {
|
|
25685
|
+
urlBuffer += text;
|
|
25686
|
+
if (!urlDetected) {
|
|
25687
|
+
const detectedUrl = detectDevServerUrl(urlBuffer);
|
|
25688
|
+
if (detectedUrl) {
|
|
25689
|
+
urlDetected = true;
|
|
25690
|
+
if (threadId) {
|
|
25691
|
+
devServerCache.setUrl(threadId, detectedUrl);
|
|
25692
|
+
}
|
|
25693
|
+
outputBuffer.push({ type: "url", url: detectedUrl });
|
|
25694
|
+
}
|
|
25695
|
+
}
|
|
25696
|
+
if (isError) {
|
|
25697
|
+
outputBuffer.push({ type: "error", message: text });
|
|
25698
|
+
} else {
|
|
25699
|
+
outputBuffer.push(text);
|
|
25700
|
+
}
|
|
25701
|
+
}
|
|
25597
25702
|
child.stdout?.on("data", (data) => {
|
|
25598
|
-
|
|
25703
|
+
appendOutput(decoder.decode(data), false);
|
|
25599
25704
|
});
|
|
25600
25705
|
child.stderr?.on("data", (data) => {
|
|
25601
|
-
|
|
25706
|
+
appendOutput(decoder.decode(data), true);
|
|
25602
25707
|
});
|
|
25603
25708
|
child.on("close", (code) => {
|
|
25604
25709
|
if (code !== 0 && code !== null) {
|
|
25605
25710
|
outputBuffer.push({ type: "error", message: `Process exited with code ${code}` });
|
|
25606
25711
|
}
|
|
25712
|
+
if (threadId && urlDetected) {
|
|
25713
|
+
devServerCache.clearUrl(threadId);
|
|
25714
|
+
}
|
|
25607
25715
|
isDone = true;
|
|
25608
25716
|
});
|
|
25609
25717
|
child.on("error", (err) => {
|
|
@@ -25620,6 +25728,7 @@ var ScriptProcessManager = class {
|
|
|
25620
25728
|
}
|
|
25621
25729
|
} finally {
|
|
25622
25730
|
this.processes.delete(key);
|
|
25731
|
+
this.threadIds.delete(key);
|
|
25623
25732
|
}
|
|
25624
25733
|
}
|
|
25625
25734
|
/**
|
|
@@ -25630,8 +25739,13 @@ var ScriptProcessManager = class {
|
|
|
25630
25739
|
stopScript(key) {
|
|
25631
25740
|
const entry = this.processes.get(key);
|
|
25632
25741
|
if (!entry) return false;
|
|
25742
|
+
const threadId = this.threadIds.get(key);
|
|
25633
25743
|
killProcessTree2(entry.pid, entry.process);
|
|
25634
25744
|
this.processes.delete(key);
|
|
25745
|
+
this.threadIds.delete(key);
|
|
25746
|
+
if (threadId) {
|
|
25747
|
+
devServerCache.clearUrl(threadId);
|
|
25748
|
+
}
|
|
25635
25749
|
return true;
|
|
25636
25750
|
}
|
|
25637
25751
|
/**
|
|
@@ -25706,7 +25820,10 @@ async function handleRunProjectScript(c, threadManager) {
|
|
|
25706
25820
|
return errorResponse(c, ErrorCodes.THREAD_NOT_FOUND, `Thread not found: ${threadId}`, 404);
|
|
25707
25821
|
}
|
|
25708
25822
|
const key = `${thread.projectId}:${scriptName}`;
|
|
25709
|
-
return streamAsyncGenerator(
|
|
25823
|
+
return streamAsyncGenerator(
|
|
25824
|
+
c,
|
|
25825
|
+
scriptProcessManager.runScript(key, command, thread.path, threadId)
|
|
25826
|
+
);
|
|
25710
25827
|
} catch (error) {
|
|
25711
25828
|
return errorResponse(
|
|
25712
25829
|
c,
|
|
@@ -25748,10 +25865,10 @@ async function handleStopProjectScript(c, threadManager) {
|
|
|
25748
25865
|
}
|
|
25749
25866
|
|
|
25750
25867
|
// src/features/threads/threads.routes.ts
|
|
25751
|
-
function createThreadRoutes(threadManager,
|
|
25868
|
+
function createThreadRoutes(threadManager, gitManager2, conversationManager) {
|
|
25752
25869
|
const router = new Hono12();
|
|
25753
25870
|
router.post("/", async (c) => {
|
|
25754
|
-
return handleCreateThread(c, threadManager,
|
|
25871
|
+
return handleCreateThread(c, threadManager, gitManager2);
|
|
25755
25872
|
});
|
|
25756
25873
|
router.get("/", async (c) => {
|
|
25757
25874
|
const { getDatabase: getDatabase2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
@@ -26476,9 +26593,63 @@ async function gitGenerateCommitMessageHandler(c, metadataManager) {
|
|
|
26476
26593
|
}
|
|
26477
26594
|
|
|
26478
26595
|
// src/features/git/git-commit.route.ts
|
|
26596
|
+
var gitManager = new GitManagerImpl();
|
|
26597
|
+
async function getUniqueBranchName(baseBranchName, gitRoot, existingBranchNames) {
|
|
26598
|
+
async function isBranchNameTaken(branchName) {
|
|
26599
|
+
if (existingBranchNames.has(branchName)) {
|
|
26600
|
+
return true;
|
|
26601
|
+
}
|
|
26602
|
+
return checkBranchExists(gitRoot, branchName);
|
|
26603
|
+
}
|
|
26604
|
+
if (!await isBranchNameTaken(baseBranchName)) {
|
|
26605
|
+
return baseBranchName;
|
|
26606
|
+
}
|
|
26607
|
+
let counter = 2;
|
|
26608
|
+
while (await isBranchNameTaken(`${baseBranchName}-${counter}`)) {
|
|
26609
|
+
counter++;
|
|
26610
|
+
}
|
|
26611
|
+
return `${baseBranchName}-${counter}`;
|
|
26612
|
+
}
|
|
26613
|
+
async function maybeRenameInitialTarskBranch(gitRoot, threadId, commitMessage, metadataManager) {
|
|
26614
|
+
const [commitCountBeforeCommit, currentBranch, threads] = await Promise.all([
|
|
26615
|
+
getCommitCount(gitRoot),
|
|
26616
|
+
getCurrentBranch(gitRoot),
|
|
26617
|
+
metadataManager.loadThreads()
|
|
26618
|
+
]);
|
|
26619
|
+
if (commitCountBeforeCommit !== 0) {
|
|
26620
|
+
return;
|
|
26621
|
+
}
|
|
26622
|
+
const thread = threads.find((candidate) => candidate.id === threadId);
|
|
26623
|
+
if (!thread) {
|
|
26624
|
+
return;
|
|
26625
|
+
}
|
|
26626
|
+
if (currentBranch !== thread.currentBranch) {
|
|
26627
|
+
return;
|
|
26628
|
+
}
|
|
26629
|
+
const expectedTarskBranchName = gitManager.sanitizeBranchName(thread.title);
|
|
26630
|
+
if (currentBranch !== expectedTarskBranchName) {
|
|
26631
|
+
return;
|
|
26632
|
+
}
|
|
26633
|
+
const requestedBranchName = gitManager.sanitizeBranchName(commitMessage);
|
|
26634
|
+
if (!requestedBranchName || requestedBranchName === currentBranch) {
|
|
26635
|
+
return;
|
|
26636
|
+
}
|
|
26637
|
+
const existingBranchNames = new Set(threads.map((candidate) => candidate.currentBranch));
|
|
26638
|
+
existingBranchNames.delete(currentBranch);
|
|
26639
|
+
const newBranchName = await getUniqueBranchName(
|
|
26640
|
+
requestedBranchName,
|
|
26641
|
+
gitRoot,
|
|
26642
|
+
existingBranchNames
|
|
26643
|
+
);
|
|
26644
|
+
await renameCurrentBranch(gitRoot, newBranchName);
|
|
26645
|
+
await metadataManager.updateThreadFields(threadId, { currentBranch: newBranchName });
|
|
26646
|
+
}
|
|
26479
26647
|
async function gitCommitHandler(c, metadataManager) {
|
|
26480
26648
|
try {
|
|
26481
26649
|
const threadId = c.req.param("threadId");
|
|
26650
|
+
if (!threadId) {
|
|
26651
|
+
return c.json({ error: "Thread ID is required" }, 400);
|
|
26652
|
+
}
|
|
26482
26653
|
const body = await c.req.json();
|
|
26483
26654
|
const { message } = body;
|
|
26484
26655
|
if (!message) {
|
|
@@ -26500,6 +26671,7 @@ async function gitCommitHandler(c, metadataManager) {
|
|
|
26500
26671
|
return c.json({ error: `Path is not a git repository: ${absolutePath}` }, 400);
|
|
26501
26672
|
}
|
|
26502
26673
|
await stageAllChanges(gitRoot);
|
|
26674
|
+
await maybeRenameInitialTarskBranch(gitRoot, threadId, message, metadataManager);
|
|
26503
26675
|
await commitChanges(gitRoot, message);
|
|
26504
26676
|
return c.json({ success: true });
|
|
26505
26677
|
} catch (error) {
|
|
@@ -26803,6 +26975,9 @@ async function gitLogHandler(c, metadataManager) {
|
|
|
26803
26975
|
}
|
|
26804
26976
|
|
|
26805
26977
|
// src/features/git/git-create-pr.route.ts
|
|
26978
|
+
function normalizeThreadTitle(title) {
|
|
26979
|
+
return (title ?? "").trim().replace(/\s+/g, " ");
|
|
26980
|
+
}
|
|
26806
26981
|
async function gitCreatePrHandler(c, metadataManager) {
|
|
26807
26982
|
try {
|
|
26808
26983
|
const threadId = c.req.param("threadId");
|
|
@@ -26812,6 +26987,9 @@ async function gitCreatePrHandler(c, metadataManager) {
|
|
|
26812
26987
|
console.log(`[git-create-pr] PR title: "${title}"`);
|
|
26813
26988
|
console.log(`[git-create-pr] PR description length: ${description?.length ?? 0} chars`);
|
|
26814
26989
|
const thread = await metadataManager.loadThreads().then((threads) => threads.find((t) => t.id === threadId));
|
|
26990
|
+
if (!threadId) {
|
|
26991
|
+
return c.json({ error: "Thread ID is required" }, 400);
|
|
26992
|
+
}
|
|
26815
26993
|
if (!thread) {
|
|
26816
26994
|
console.log(`[git-create-pr] Thread not found: ${threadId}`);
|
|
26817
26995
|
return c.json({ error: "Thread not found" }, 404);
|
|
@@ -26834,10 +27012,17 @@ async function gitCreatePrHandler(c, metadataManager) {
|
|
|
26834
27012
|
}
|
|
26835
27013
|
const currentBranch = await getCurrentBranch(gitRoot);
|
|
26836
27014
|
console.log(`[git-create-pr] Current branch: ${currentBranch}`);
|
|
27015
|
+
const prTitle = title ?? currentBranch;
|
|
26837
27016
|
console.log(`[git-create-pr] Creating PR with GitHub CLI...`);
|
|
26838
|
-
const prUrl = await createPullRequest(gitRoot,
|
|
27017
|
+
const prUrl = await createPullRequest(gitRoot, prTitle, description ?? "");
|
|
26839
27018
|
console.log(`[git-create-pr] \u2713 PR created successfully: ${prUrl}`);
|
|
26840
|
-
|
|
27019
|
+
const normalizedPrTitle = normalizeThreadTitle(prTitle);
|
|
27020
|
+
if (normalizedPrTitle !== thread.title) {
|
|
27021
|
+
const threadUpdates = { title: normalizedPrTitle };
|
|
27022
|
+
await metadataManager.updateThreadFields(threadId, threadUpdates);
|
|
27023
|
+
console.log(`[git-create-pr] \u2713 Updated thread title to PR title: ${normalizedPrTitle}`);
|
|
27024
|
+
}
|
|
27025
|
+
return c.json({ success: true, prUrl, title: normalizedPrTitle });
|
|
26841
27026
|
} catch (error) {
|
|
26842
27027
|
const message = error instanceof Error ? error.message : "Failed to create PR";
|
|
26843
27028
|
console.log(`[git-create-pr] \u2717 PR creation failed: ${message}`);
|
|
@@ -27163,7 +27348,7 @@ function sanitizeBranchName(name) {
|
|
|
27163
27348
|
}
|
|
27164
27349
|
return name.trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-zA-Z0-9\-_/.]/g, "").replace(/^[/.]+|[/.]+$/g, "").replace(/-+/g, "-") || "branch";
|
|
27165
27350
|
}
|
|
27166
|
-
function
|
|
27351
|
+
function checkBranchExists2(gitRoot, branchName) {
|
|
27167
27352
|
return new Promise((resolve8) => {
|
|
27168
27353
|
const proc = spawnProcess(
|
|
27169
27354
|
"git",
|
|
@@ -27227,12 +27412,12 @@ async function gitCreateRepoHandler(c, metadataManager) {
|
|
|
27227
27412
|
}
|
|
27228
27413
|
const repoUrl = await createGitHubRepo(gitRoot, repoName, description, isPrivate);
|
|
27229
27414
|
let branchName = sanitizeBranchName(generateRandomThreadName());
|
|
27230
|
-
let branchExists = await
|
|
27415
|
+
let branchExists = await checkBranchExists2(gitRoot, branchName);
|
|
27231
27416
|
let counter = 2;
|
|
27232
27417
|
const baseBranchName = branchName;
|
|
27233
27418
|
while (branchExists) {
|
|
27234
27419
|
branchName = `${baseBranchName}-${counter}`;
|
|
27235
|
-
branchExists = await
|
|
27420
|
+
branchExists = await checkBranchExists2(gitRoot, branchName);
|
|
27236
27421
|
counter++;
|
|
27237
27422
|
}
|
|
27238
27423
|
await createAndCheckoutBranch(gitRoot, branchName);
|
|
@@ -27285,7 +27470,7 @@ function sanitizeBranchName2(name) {
|
|
|
27285
27470
|
}
|
|
27286
27471
|
return name.trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-zA-Z0-9\-_/.]/g, "").replace(/^[/.]+|[/.]+$/g, "").replace(/-+/g, "-") || "branch";
|
|
27287
27472
|
}
|
|
27288
|
-
function
|
|
27473
|
+
function checkBranchExists3(gitRoot, branchName) {
|
|
27289
27474
|
return new Promise((resolve8) => {
|
|
27290
27475
|
const proc = spawnProcess(
|
|
27291
27476
|
"git",
|
|
@@ -27348,7 +27533,7 @@ async function gitCreateBranchHandler(c, metadataManager) {
|
|
|
27348
27533
|
if (!branchName) {
|
|
27349
27534
|
return c.json({ error: "Invalid branch name" }, 400);
|
|
27350
27535
|
}
|
|
27351
|
-
const branchExists = await
|
|
27536
|
+
const branchExists = await checkBranchExists3(gitRoot, branchName);
|
|
27352
27537
|
if (body.branchName) {
|
|
27353
27538
|
if (branchExists) {
|
|
27354
27539
|
return c.json({ error: `Branch "${branchName}" already exists` }, 409);
|
|
@@ -27359,7 +27544,7 @@ async function gitCreateBranchHandler(c, metadataManager) {
|
|
|
27359
27544
|
let exists = branchExists;
|
|
27360
27545
|
while (exists) {
|
|
27361
27546
|
branchName = `${baseBranchName}-${counter}`;
|
|
27362
|
-
exists = await
|
|
27547
|
+
exists = await checkBranchExists3(gitRoot, branchName);
|
|
27363
27548
|
counter++;
|
|
27364
27549
|
}
|
|
27365
27550
|
}
|
|
@@ -27974,51 +28159,12 @@ async function gitCheckpointRestoreHandler(c, metadataManager) {
|
|
|
27974
28159
|
}
|
|
27975
28160
|
|
|
27976
28161
|
// src/features/git/git-rename-branch.route.ts
|
|
27977
|
-
init_utils();
|
|
27978
28162
|
function sanitizeBranchName3(name) {
|
|
27979
28163
|
if (!name || typeof name !== "string") {
|
|
27980
28164
|
return "";
|
|
27981
28165
|
}
|
|
27982
28166
|
return name.trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-zA-Z0-9\-_/.]/g, "").replace(/^[/.]+|[/.]+$/g, "").replace(/-+/g, "-") || "";
|
|
27983
28167
|
}
|
|
27984
|
-
function checkBranchExists3(gitRoot, branchName) {
|
|
27985
|
-
return new Promise((resolve8) => {
|
|
27986
|
-
const proc = spawnProcess(
|
|
27987
|
-
"git",
|
|
27988
|
-
["show-ref", "--verify", "--quiet", `refs/heads/${branchName}`],
|
|
27989
|
-
{
|
|
27990
|
-
cwd: gitRoot
|
|
27991
|
-
}
|
|
27992
|
-
);
|
|
27993
|
-
proc.on("close", (code) => {
|
|
27994
|
-
resolve8(code === 0);
|
|
27995
|
-
});
|
|
27996
|
-
proc.on("error", () => {
|
|
27997
|
-
resolve8(false);
|
|
27998
|
-
});
|
|
27999
|
-
});
|
|
28000
|
-
}
|
|
28001
|
-
function renameBranch(gitRoot, newBranchName) {
|
|
28002
|
-
return new Promise((resolve8, reject) => {
|
|
28003
|
-
const proc = spawnProcess("git", ["branch", "-m", newBranchName], {
|
|
28004
|
-
cwd: gitRoot
|
|
28005
|
-
});
|
|
28006
|
-
let err = "";
|
|
28007
|
-
if (proc.stderr) {
|
|
28008
|
-
proc.stderr.on("data", (d) => {
|
|
28009
|
-
err += d.toString();
|
|
28010
|
-
});
|
|
28011
|
-
}
|
|
28012
|
-
proc.on("close", (code) => {
|
|
28013
|
-
if (code === 0) {
|
|
28014
|
-
resolve8();
|
|
28015
|
-
} else {
|
|
28016
|
-
reject(new Error(err || `Failed to rename branch to "${newBranchName}"`));
|
|
28017
|
-
}
|
|
28018
|
-
});
|
|
28019
|
-
proc.on("error", reject);
|
|
28020
|
-
});
|
|
28021
|
-
}
|
|
28022
28168
|
async function gitRenameBranchHandler(c, metadataManager) {
|
|
28023
28169
|
try {
|
|
28024
28170
|
const threadId = c.req.param("threadId");
|
|
@@ -28046,11 +28192,11 @@ async function gitRenameBranchHandler(c, metadataManager) {
|
|
|
28046
28192
|
} catch {
|
|
28047
28193
|
return c.json({ error: `Path is not a git repository: ${absolutePath}` }, 400);
|
|
28048
28194
|
}
|
|
28049
|
-
const branchExists = await
|
|
28195
|
+
const branchExists = await checkBranchExists(gitRoot, newBranchName);
|
|
28050
28196
|
if (branchExists) {
|
|
28051
28197
|
return c.json({ error: `Branch "${newBranchName}" already exists` }, 409);
|
|
28052
28198
|
}
|
|
28053
|
-
await
|
|
28199
|
+
await renameCurrentBranch(gitRoot, newBranchName);
|
|
28054
28200
|
const threads = await metadataManager.loadThreads();
|
|
28055
28201
|
const threadIndex = threads.findIndex((t) => t.id === threadId);
|
|
28056
28202
|
if (threadIndex !== -1) {
|
|
@@ -29431,23 +29577,12 @@ function createBrowserRoutes() {
|
|
|
29431
29577
|
|
|
29432
29578
|
// src/features/voice-model/voice-model.routes.ts
|
|
29433
29579
|
import { Hono as Hono24 } from "hono";
|
|
29434
|
-
var
|
|
29435
|
-
default: "https://install.tarsk.io/voice-models/ggml-tiny.en.bin",
|
|
29436
|
-
tiny: "https://install.tarsk.io/voice-models/ggml-tiny.en-q5_1.bin"
|
|
29437
|
-
};
|
|
29438
|
-
function getVoiceModelUrl(model) {
|
|
29439
|
-
if (model === "tiny") {
|
|
29440
|
-
return VOICE_MODEL_URLS.tiny;
|
|
29441
|
-
}
|
|
29442
|
-
return VOICE_MODEL_URLS.default;
|
|
29443
|
-
}
|
|
29580
|
+
var VOICE_MODEL_URL = "https://install.tarsk.io/voice-models/vosk-model-small-en-us-0.15.tar.gz";
|
|
29444
29581
|
function createVoiceModelRoutes() {
|
|
29445
29582
|
const router = new Hono24();
|
|
29446
29583
|
router.get("/download", async (c) => {
|
|
29447
|
-
const selectedModel = c.req.query("model");
|
|
29448
|
-
const modelUrl = getVoiceModelUrl(selectedModel);
|
|
29449
29584
|
try {
|
|
29450
|
-
const response = await fetch(
|
|
29585
|
+
const response = await fetch(VOICE_MODEL_URL);
|
|
29451
29586
|
if (!response.ok) {
|
|
29452
29587
|
return errorResponse(
|
|
29453
29588
|
c,
|
|
@@ -29458,8 +29593,7 @@ function createVoiceModelRoutes() {
|
|
|
29458
29593
|
}
|
|
29459
29594
|
const contentLength = response.headers.get("content-length");
|
|
29460
29595
|
const headers = {
|
|
29461
|
-
"Content-Type": "application/
|
|
29462
|
-
"X-Tarsk-Voice-Model": selectedModel === "tiny" ? "tiny" : "default"
|
|
29596
|
+
"Content-Type": "application/gzip"
|
|
29463
29597
|
};
|
|
29464
29598
|
if (contentLength) {
|
|
29465
29599
|
headers["Content-Length"] = contentLength;
|
|
@@ -29675,7 +29809,7 @@ async function startTarskServer(options) {
|
|
|
29675
29809
|
}
|
|
29676
29810
|
async function startTarskServerInternal(options) {
|
|
29677
29811
|
const { isDebug: isDebug2, publicDir: publicDirOverride } = options;
|
|
29678
|
-
const
|
|
29812
|
+
const initialPort = isDebug2 ? 462 : process.env.PORT ? parseInt(process.env.PORT) : 641;
|
|
29679
29813
|
const app = new Hono28();
|
|
29680
29814
|
app.use("/*", cors());
|
|
29681
29815
|
app.use("/*", async (c, next) => {
|
|
@@ -29687,7 +29821,9 @@ async function startTarskServerInternal(options) {
|
|
|
29687
29821
|
if (c.req.path.startsWith("/api/")) {
|
|
29688
29822
|
const method = c.req.method;
|
|
29689
29823
|
const reqPath = c.req.path;
|
|
29690
|
-
const
|
|
29824
|
+
const hostHeader = c.req.header("host") ?? `localhost:${initialPort}`;
|
|
29825
|
+
const requestUrl = new URL(c.req.url);
|
|
29826
|
+
const fullUrl = `${requestUrl.protocol}//${hostHeader}${reqPath}`;
|
|
29691
29827
|
const isThreadMessages = reqPath.startsWith("/api/threads/") && reqPath.endsWith("/messages");
|
|
29692
29828
|
if (!fullUrl.includes("processing") && !reqPath.startsWith("/api/logs") && !isThreadMessages) {
|
|
29693
29829
|
console.log(`${method} ${fullUrl}`);
|
|
@@ -29697,17 +29833,17 @@ async function startTarskServerInternal(options) {
|
|
|
29697
29833
|
});
|
|
29698
29834
|
const dataDir = getDataDir();
|
|
29699
29835
|
const metadataManager = new MetadataManager(dataDir);
|
|
29700
|
-
const
|
|
29836
|
+
const gitManager2 = new GitManagerImpl();
|
|
29701
29837
|
const processingStateManager = new ProcessingStateManagerImpl();
|
|
29702
29838
|
const projectManager = new ProjectManagerImpl(
|
|
29703
29839
|
dataDir,
|
|
29704
29840
|
metadataManager,
|
|
29705
|
-
|
|
29841
|
+
gitManager2,
|
|
29706
29842
|
processingStateManager
|
|
29707
29843
|
);
|
|
29708
29844
|
const threadManager = new ThreadManagerImpl(
|
|
29709
29845
|
metadataManager,
|
|
29710
|
-
|
|
29846
|
+
gitManager2,
|
|
29711
29847
|
processingStateManager,
|
|
29712
29848
|
dataDir
|
|
29713
29849
|
);
|
|
@@ -29720,7 +29856,8 @@ async function startTarskServerInternal(options) {
|
|
|
29720
29856
|
return c.json({
|
|
29721
29857
|
status: "ok",
|
|
29722
29858
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29723
|
-
service: "project-threads-manager-cli"
|
|
29859
|
+
service: "project-threads-manager-cli",
|
|
29860
|
+
isDevMode: port !== initialPort
|
|
29724
29861
|
});
|
|
29725
29862
|
});
|
|
29726
29863
|
app.get("/api/programs", (c) => {
|
|
@@ -29736,7 +29873,7 @@ async function startTarskServerInternal(options) {
|
|
|
29736
29873
|
app.route("/api/projects", createProjectRoutes(projectManager, threadManager));
|
|
29737
29874
|
app.route("/api/projects", createRunRoutes(projectManager));
|
|
29738
29875
|
app.route("/api/projects", createProjectTodosRoutes(metadataManager));
|
|
29739
|
-
app.route("/api/threads", createThreadRoutes(threadManager,
|
|
29876
|
+
app.route("/api/threads", createThreadRoutes(threadManager, gitManager2, conversationManager));
|
|
29740
29877
|
app.route("/api/threads", createUserTaskRoutes());
|
|
29741
29878
|
app.route(
|
|
29742
29879
|
"/api/chat",
|
|
@@ -29786,16 +29923,37 @@ async function startTarskServerInternal(options) {
|
|
|
29786
29923
|
`No static frontend assets found. Expected one of: ${prodPublicDir}, ${devCopiedPublicDir}, ${appDistDir}. Build the app first with \`cd ../app && bun run build\`.`
|
|
29787
29924
|
);
|
|
29788
29925
|
}
|
|
29926
|
+
function isStaticAssetPath(requestPath) {
|
|
29927
|
+
if (requestPath.startsWith("/assets/")) {
|
|
29928
|
+
return true;
|
|
29929
|
+
}
|
|
29930
|
+
const lastSegment = requestPath.split("/").pop() ?? "";
|
|
29931
|
+
return lastSegment.includes(".") && !lastSegment.endsWith(".html");
|
|
29932
|
+
}
|
|
29933
|
+
function setNoCacheIndexHeaders(c) {
|
|
29934
|
+
c.header("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
29935
|
+
}
|
|
29789
29936
|
app.use("/*", async (c, next) => {
|
|
29790
29937
|
if (c.req.path.startsWith("/api/")) {
|
|
29791
29938
|
return next();
|
|
29792
29939
|
}
|
|
29793
|
-
return serveStatic({
|
|
29940
|
+
return serveStatic({
|
|
29941
|
+
root: resolvedPublicDir,
|
|
29942
|
+
onFound: (_path, context) => {
|
|
29943
|
+
if (context.req.path === "/" || context.req.path === "/index.html") {
|
|
29944
|
+
setNoCacheIndexHeaders(context);
|
|
29945
|
+
}
|
|
29946
|
+
}
|
|
29947
|
+
})(c, next);
|
|
29794
29948
|
});
|
|
29795
29949
|
app.get("*", async (c, next) => {
|
|
29796
29950
|
if (c.req.path.startsWith("/api/")) {
|
|
29797
29951
|
return next();
|
|
29798
29952
|
}
|
|
29953
|
+
if (isStaticAssetPath(c.req.path)) {
|
|
29954
|
+
return next();
|
|
29955
|
+
}
|
|
29956
|
+
setNoCacheIndexHeaders(c);
|
|
29799
29957
|
return serveStatic({
|
|
29800
29958
|
path: path5.join(resolvedPublicDir, "index.html")
|
|
29801
29959
|
})(c, next);
|
|
@@ -29812,16 +29970,22 @@ async function startTarskServerInternal(options) {
|
|
|
29812
29970
|
});
|
|
29813
29971
|
const serverBindMode = readServerBindMode();
|
|
29814
29972
|
const hostname2 = getServerBindHostname(serverBindMode);
|
|
29815
|
-
const
|
|
29816
|
-
const bound = await listenForTarskServer({
|
|
29973
|
+
const port = await listenForTarskServer({
|
|
29817
29974
|
fetch: app.fetch,
|
|
29818
29975
|
hostname: hostname2,
|
|
29819
|
-
|
|
29976
|
+
onPortConflict: (candidatePort) => {
|
|
29977
|
+
process.stdout.write(
|
|
29978
|
+
`Port ${candidatePort} is already in use, trying ${candidatePort + 1}.
|
|
29979
|
+
`
|
|
29980
|
+
);
|
|
29981
|
+
},
|
|
29982
|
+
onListening: (listeningPort) => {
|
|
29983
|
+
const url = `http://localhost:${listeningPort}`;
|
|
29820
29984
|
process.stdout.write(`Tarsk started on ${url}
|
|
29821
29985
|
`);
|
|
29822
29986
|
if (serverBindMode === "network") {
|
|
29823
29987
|
for (const address of getLocalNetworkAddresses()) {
|
|
29824
|
-
process.stdout.write(` Network: http://${address}:${
|
|
29988
|
+
process.stdout.write(` Network: http://${address}:${listeningPort}
|
|
29825
29989
|
`);
|
|
29826
29990
|
}
|
|
29827
29991
|
}
|
|
@@ -29830,38 +29994,48 @@ async function startTarskServerInternal(options) {
|
|
|
29830
29994
|
});
|
|
29831
29995
|
}
|
|
29832
29996
|
},
|
|
29833
|
-
port
|
|
29997
|
+
port: initialPort
|
|
29834
29998
|
});
|
|
29835
|
-
|
|
29836
|
-
|
|
29837
|
-
|
|
29838
|
-
|
|
29999
|
+
return {
|
|
30000
|
+
url: `http://localhost:${port}`,
|
|
30001
|
+
port,
|
|
30002
|
+
bound: true,
|
|
30003
|
+
isDevMode: port !== initialPort
|
|
30004
|
+
};
|
|
29839
30005
|
}
|
|
29840
30006
|
async function listenForTarskServer(options) {
|
|
29841
|
-
|
|
29842
|
-
|
|
29843
|
-
|
|
29844
|
-
|
|
29845
|
-
|
|
29846
|
-
|
|
29847
|
-
|
|
29848
|
-
|
|
29849
|
-
|
|
29850
|
-
|
|
30007
|
+
let port = options.port;
|
|
30008
|
+
while (true) {
|
|
30009
|
+
const server = createAdaptorServer({
|
|
30010
|
+
fetch: options.fetch,
|
|
30011
|
+
hostname: options.hostname,
|
|
30012
|
+
port
|
|
30013
|
+
});
|
|
30014
|
+
const result = await new Promise((resolve8, reject) => {
|
|
30015
|
+
server.once("error", (error) => {
|
|
30016
|
+
if (error.code === "EADDRINUSE") {
|
|
30017
|
+
resolve8("in-use");
|
|
30018
|
+
return;
|
|
30019
|
+
}
|
|
30020
|
+
startPromise = null;
|
|
30021
|
+
reject(error);
|
|
30022
|
+
});
|
|
30023
|
+
function onListening() {
|
|
30024
|
+
resolve8("listening");
|
|
30025
|
+
}
|
|
30026
|
+
if (options.hostname) {
|
|
30027
|
+
server.listen(port, options.hostname, onListening);
|
|
30028
|
+
} else {
|
|
30029
|
+
server.listen(port, onListening);
|
|
29851
30030
|
}
|
|
29852
|
-
startPromise = null;
|
|
29853
|
-
reject(error);
|
|
29854
30031
|
});
|
|
29855
|
-
|
|
29856
|
-
options.onListening();
|
|
29857
|
-
|
|
29858
|
-
}
|
|
29859
|
-
if (options.hostname) {
|
|
29860
|
-
server.listen(options.port, options.hostname, onListening);
|
|
29861
|
-
} else {
|
|
29862
|
-
server.listen(options.port, onListening);
|
|
30032
|
+
if (result === "listening") {
|
|
30033
|
+
options.onListening(port);
|
|
30034
|
+
return port;
|
|
29863
30035
|
}
|
|
29864
|
-
|
|
30036
|
+
options.onPortConflict(port);
|
|
30037
|
+
port += 1;
|
|
30038
|
+
}
|
|
29865
30039
|
}
|
|
29866
30040
|
|
|
29867
30041
|
// src/index.ts
|