tarsk 0.4.8 → 0.4.10
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 +272 -164
- package/dist/public/assets/account-view-D1x7ZeLs.js +1 -0
- package/dist/public/assets/add-agent-view-Ctbm0EgW.js +1 -0
- package/dist/public/assets/add-rule-view-xKAYGOl5.js +7 -0
- package/dist/public/assets/add-skill-view-D63xCrVn.js +1 -0
- package/dist/public/assets/add-slash-command-view-paJjkCml.js +1 -0
- package/dist/public/assets/browser-tab-CWkk3b20.js +1 -0
- package/dist/public/assets/conversation-history-view-BdJJ-7zE.js +1 -0
- package/dist/public/assets/{dialogs-config-DiFQjCeA.js → dialogs-config-CB7G-sX6.js} +13 -13
- package/dist/public/assets/diff-view-kPjfhf7_.js +3 -0
- package/dist/public/assets/file-tree-sidebar-D58ROyfi.js +1 -0
- package/dist/public/assets/files-tab-view-DhnLTfaB.js +2 -0
- package/dist/public/assets/files-view-C1vg37wD.js +1 -0
- package/dist/public/assets/history-view-D-hEB6Qt.js +1 -0
- package/dist/public/assets/index-D7yQjYyf.js +16 -0
- package/dist/public/assets/index-DVHw8RF4.css +1 -0
- package/dist/public/assets/mcp-manager-J9VCn8-1.js +1 -0
- package/dist/public/assets/{mcp-server-edit-view-BAwMNOAH.js → mcp-server-edit-view-yd_q5UVd.js} +3 -3
- package/dist/public/assets/mcp-servers-sidebar-Bwg40dY8.js +1 -0
- package/dist/public/assets/mcp-view-BYzQiRVC.js +1 -0
- package/dist/public/assets/onboarding-CxK4aR2J.js +1 -0
- package/dist/public/assets/onboarding-dialog-DX7DCkK0.js +1 -0
- package/dist/public/assets/project-settings-view-CkAqtfjP.js +1 -0
- package/dist/public/assets/provider-details-view-CzsPzv6h.js +1 -0
- package/dist/public/assets/{providers-sidebar-C4MF6i9d.js → providers-sidebar-BokZx2tk.js} +1 -1
- package/dist/public/assets/radio-group-BpmnaKJk.js +1 -0
- package/dist/public/assets/react-vendor-CR4cAsbx.js +17 -0
- package/dist/public/assets/settings-view-CoL0k8nt.js +2 -0
- package/dist/public/assets/side-panel-resizer-CVC2NC75.js +1 -0
- package/dist/public/assets/store-CxlaVYZ6.js +2 -0
- package/dist/public/assets/terminal-panel-Bv2hLEfW.js +2 -0
- package/dist/public/assets/todos-view-FJ5GkG21.js +1 -0
- package/dist/public/assets/{utils-DY_quHB8.js → utils-DVGxCyLB.js} +1 -1
- package/dist/public/index.html +9 -10
- package/package.json +1 -1
- package/dist/public/assets/add-agent-view-B9IQjAwU.js +0 -1
- package/dist/public/assets/add-rule-view-BdZHurB3.js +0 -7
- package/dist/public/assets/add-skill-view-Cuu6Z0fr.js +0 -1
- package/dist/public/assets/add-slash-command-view-uW75Jvbh.js +0 -1
- package/dist/public/assets/conversation-history-view-D0OBxJMC.js +0 -1
- package/dist/public/assets/diff-view-B5XBM5UZ.js +0 -3
- package/dist/public/assets/file-tree-sidebar-DMX7fHi7.js +0 -1
- package/dist/public/assets/files-view-CUZn7G0o.js +0 -1
- package/dist/public/assets/history-view-B8HM78Wa.js +0 -1
- package/dist/public/assets/index-C-p81QYw.js +0 -17
- package/dist/public/assets/index-DhVMb7D6.css +0 -1
- package/dist/public/assets/mcp-manager-CEm1L3dn.js +0 -1
- package/dist/public/assets/mcp-servers-sidebar-Ncxq9Oj5.js +0 -1
- package/dist/public/assets/mcp-view-Cz7nelGQ.js +0 -1
- package/dist/public/assets/onboarding-CvpvkF3X.js +0 -1
- package/dist/public/assets/onboarding-dialog-CKJw0ULj.js +0 -1
- package/dist/public/assets/project-settings-view-DJ1uvrTL.js +0 -1
- package/dist/public/assets/provider-details-view-CkS6WbnK.js +0 -1
- package/dist/public/assets/radio-group-BItFbSTw.js +0 -1
- package/dist/public/assets/react-vendor-DkKo9QGO.js +0 -17
- package/dist/public/assets/settings-view-C45kmAGH.js +0 -2
- package/dist/public/assets/store-BVVGurzl.js +0 -2
- package/dist/public/assets/use-toast-DEJkXPN4.js +0 -1
- /package/dist/public/assets/{monaco-DvsnxTfD.js → monaco-Cp3BWanQ.js} +0 -0
package/dist/index.js
CHANGED
|
@@ -642,7 +642,7 @@ function isValidPackageManager(value) {
|
|
|
642
642
|
|
|
643
643
|
// src/server.ts
|
|
644
644
|
import fs3 from "fs";
|
|
645
|
-
import { Hono as
|
|
645
|
+
import { Hono as Hono16 } from "hono";
|
|
646
646
|
import { cors } from "hono/cors";
|
|
647
647
|
import open3 from "open";
|
|
648
648
|
import path5 from "path";
|
|
@@ -3425,6 +3425,10 @@ async function resolveProviderKeyName(providerName) {
|
|
|
3425
3425
|
|
|
3426
3426
|
// src/agent/agent.model-resolver.ts
|
|
3427
3427
|
import { getModel } from "@mariozechner/pi-ai";
|
|
3428
|
+
var DEFAULT_HEADERS = {
|
|
3429
|
+
"HTTP-Referer": "https://tarsk.io",
|
|
3430
|
+
"X-Title": "Tarsk.io"
|
|
3431
|
+
};
|
|
3428
3432
|
var PROVIDER_NAME_TO_PI = {
|
|
3429
3433
|
anthropic: "anthropic",
|
|
3430
3434
|
openai: "openai",
|
|
@@ -3449,7 +3453,8 @@ function resolveModel(providerName, modelId, providerConfig) {
|
|
|
3449
3453
|
const piProvider = PROVIDER_NAME_TO_PI[providerName.toLowerCase()];
|
|
3450
3454
|
if (piProvider) {
|
|
3451
3455
|
try {
|
|
3452
|
-
|
|
3456
|
+
const model = getModel(piProvider, modelId);
|
|
3457
|
+
return { ...model, headers: { ...model.headers, ...DEFAULT_HEADERS } };
|
|
3453
3458
|
} catch {
|
|
3454
3459
|
}
|
|
3455
3460
|
}
|
|
@@ -3464,11 +3469,12 @@ function resolveModel(providerName, modelId, providerConfig) {
|
|
|
3464
3469
|
api: apiType,
|
|
3465
3470
|
provider: providerName.toLowerCase(),
|
|
3466
3471
|
baseUrl,
|
|
3467
|
-
reasoning:
|
|
3472
|
+
reasoning: true,
|
|
3468
3473
|
input: ["text"],
|
|
3469
3474
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
3470
3475
|
contextWindow: 128e3,
|
|
3471
|
-
maxTokens: 16384
|
|
3476
|
+
maxTokens: 16384,
|
|
3477
|
+
headers: DEFAULT_HEADERS
|
|
3472
3478
|
};
|
|
3473
3479
|
}
|
|
3474
3480
|
|
|
@@ -5003,7 +5009,7 @@ function createAskUserRoutes() {
|
|
|
5003
5009
|
import { Hono as Hono2 } from "hono";
|
|
5004
5010
|
|
|
5005
5011
|
// src/features/chat/chat-post.route.ts
|
|
5006
|
-
import { randomUUID as
|
|
5012
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
5007
5013
|
|
|
5008
5014
|
// src/features/skills/skills.manager.ts
|
|
5009
5015
|
import { readdir as readdir4, readFile as readFile4 } from "fs/promises";
|
|
@@ -5722,6 +5728,214 @@ async function invalidateGitStatusCache(db, threadId) {
|
|
|
5722
5728
|
await db.execute("DELETE FROM git_status_cache WHERE threadId = ?", [threadId]);
|
|
5723
5729
|
}
|
|
5724
5730
|
|
|
5731
|
+
// src/features/account/account-get-info.route.ts
|
|
5732
|
+
init_database();
|
|
5733
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
5734
|
+
|
|
5735
|
+
// src/core/crypto.ts
|
|
5736
|
+
init_database();
|
|
5737
|
+
import { createCipheriv, createDecipheriv, randomBytes as randomBytes2, createHash } from "crypto";
|
|
5738
|
+
import { networkInterfaces, hostname } from "os";
|
|
5739
|
+
var ALGORITHM = "aes-256-gcm";
|
|
5740
|
+
var IV_LENGTH = 16;
|
|
5741
|
+
function getMachineKey() {
|
|
5742
|
+
try {
|
|
5743
|
+
const interfaces = networkInterfaces();
|
|
5744
|
+
let macAddress = "";
|
|
5745
|
+
for (const name of Object.keys(interfaces)) {
|
|
5746
|
+
const iface = interfaces[name];
|
|
5747
|
+
if (iface) {
|
|
5748
|
+
for (const addr of iface) {
|
|
5749
|
+
if (addr.mac && addr.mac !== "00:00:00:00:00:00" && !addr.internal) {
|
|
5750
|
+
macAddress = addr.mac;
|
|
5751
|
+
break;
|
|
5752
|
+
}
|
|
5753
|
+
}
|
|
5754
|
+
if (macAddress) break;
|
|
5755
|
+
}
|
|
5756
|
+
}
|
|
5757
|
+
const host = hostname();
|
|
5758
|
+
const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
5759
|
+
const machineId = `${macAddress}-${host}-${homeDir}`;
|
|
5760
|
+
return createHash("sha256").update(machineId).digest();
|
|
5761
|
+
} catch {
|
|
5762
|
+
return Buffer.from("Invalid", "utf8");
|
|
5763
|
+
}
|
|
5764
|
+
}
|
|
5765
|
+
async function getEncryptionKey() {
|
|
5766
|
+
try {
|
|
5767
|
+
const db = await getDatabase();
|
|
5768
|
+
const result = await db.execute({
|
|
5769
|
+
sql: "SELECT value FROM state WHERE key = ?",
|
|
5770
|
+
args: ["encryption_key"]
|
|
5771
|
+
});
|
|
5772
|
+
if (result.rows.length > 0 && result.rows[0].value) {
|
|
5773
|
+
const storedValue = result.rows[0].value;
|
|
5774
|
+
try {
|
|
5775
|
+
const parsed = JSON.parse(storedValue);
|
|
5776
|
+
return Buffer.from(parsed, "base64");
|
|
5777
|
+
} catch {
|
|
5778
|
+
return Buffer.from(storedValue, "base64");
|
|
5779
|
+
}
|
|
5780
|
+
}
|
|
5781
|
+
const machineKey = getMachineKey();
|
|
5782
|
+
await db.execute({
|
|
5783
|
+
sql: "INSERT OR REPLACE INTO state (key, value) VALUES (?, ?)",
|
|
5784
|
+
args: ["encryption_key", machineKey.toString("base64")]
|
|
5785
|
+
});
|
|
5786
|
+
return machineKey;
|
|
5787
|
+
} catch {
|
|
5788
|
+
return getMachineKey();
|
|
5789
|
+
}
|
|
5790
|
+
}
|
|
5791
|
+
async function encrypt(plaintext) {
|
|
5792
|
+
if (!plaintext) {
|
|
5793
|
+
return "";
|
|
5794
|
+
}
|
|
5795
|
+
const key = await getEncryptionKey();
|
|
5796
|
+
const iv = randomBytes2(IV_LENGTH);
|
|
5797
|
+
const cipher = createCipheriv(ALGORITHM, key, iv);
|
|
5798
|
+
let encrypted = cipher.update(plaintext, "utf8", "base64");
|
|
5799
|
+
encrypted += cipher.final("base64");
|
|
5800
|
+
const authTag = cipher.getAuthTag();
|
|
5801
|
+
const result = `${iv.toString("base64")}:${authTag.toString("base64")}:${encrypted}`;
|
|
5802
|
+
return result;
|
|
5803
|
+
}
|
|
5804
|
+
async function decrypt(encryptedData) {
|
|
5805
|
+
if (!encryptedData) {
|
|
5806
|
+
return "";
|
|
5807
|
+
}
|
|
5808
|
+
try {
|
|
5809
|
+
const parts = encryptedData.split(":");
|
|
5810
|
+
if (parts.length !== 3) {
|
|
5811
|
+
throw new Error("Invalid encrypted data format");
|
|
5812
|
+
}
|
|
5813
|
+
const [ivBase64, authTagBase64, encrypted] = parts;
|
|
5814
|
+
const key = await getEncryptionKey();
|
|
5815
|
+
const iv = Buffer.from(ivBase64, "base64");
|
|
5816
|
+
const authTag = Buffer.from(authTagBase64, "base64");
|
|
5817
|
+
const decipher = createDecipheriv(ALGORITHM, key, iv);
|
|
5818
|
+
decipher.setAuthTag(authTag);
|
|
5819
|
+
let decrypted = decipher.update(encrypted, "base64", "utf8");
|
|
5820
|
+
decrypted += decipher.final("utf8");
|
|
5821
|
+
return decrypted;
|
|
5822
|
+
} catch (error) {
|
|
5823
|
+
throw new Error(
|
|
5824
|
+
`Decryption failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
5825
|
+
);
|
|
5826
|
+
}
|
|
5827
|
+
}
|
|
5828
|
+
function isEncrypted(value) {
|
|
5829
|
+
if (!value) {
|
|
5830
|
+
return false;
|
|
5831
|
+
}
|
|
5832
|
+
const parts = value.split(":");
|
|
5833
|
+
if (parts.length !== 3) {
|
|
5834
|
+
return false;
|
|
5835
|
+
}
|
|
5836
|
+
const base64Regex = /^[A-Za-z0-9+/]+=*$/;
|
|
5837
|
+
return parts.every((part) => base64Regex.test(part));
|
|
5838
|
+
}
|
|
5839
|
+
|
|
5840
|
+
// src/features/account/account-get-info.route.ts
|
|
5841
|
+
var KEY_BALANCE = "PromptBalance";
|
|
5842
|
+
var KEY_VERIFICATION = "PromptBalanceVerification";
|
|
5843
|
+
var KEY_PLAN = "Plan";
|
|
5844
|
+
var KEY_CLIENT_REFERENCE_ID = "clientReferenceId";
|
|
5845
|
+
var DEFAULT_BALANCE = 1e3;
|
|
5846
|
+
async function writeBalance(balance) {
|
|
5847
|
+
const db = await getDatabase();
|
|
5848
|
+
const verification = await encrypt(String(balance));
|
|
5849
|
+
await db.batch([
|
|
5850
|
+
{
|
|
5851
|
+
sql: "INSERT OR REPLACE INTO state (key, value) VALUES (?, ?)",
|
|
5852
|
+
args: [KEY_BALANCE, JSON.stringify(balance)]
|
|
5853
|
+
},
|
|
5854
|
+
{
|
|
5855
|
+
sql: "INSERT OR REPLACE INTO state (key, value) VALUES (?, ?)",
|
|
5856
|
+
args: [KEY_VERIFICATION, JSON.stringify(verification)]
|
|
5857
|
+
}
|
|
5858
|
+
]);
|
|
5859
|
+
}
|
|
5860
|
+
async function readVerifiedBalance() {
|
|
5861
|
+
const db = await getDatabase();
|
|
5862
|
+
const rawBalance = await getState(db, KEY_BALANCE);
|
|
5863
|
+
if (rawBalance === null || rawBalance === void 0) {
|
|
5864
|
+
await writeBalance(DEFAULT_BALANCE);
|
|
5865
|
+
return DEFAULT_BALANCE;
|
|
5866
|
+
}
|
|
5867
|
+
const balance = rawBalance;
|
|
5868
|
+
const rawVerification = await getState(db, KEY_VERIFICATION);
|
|
5869
|
+
if (rawVerification === null || rawVerification === void 0) {
|
|
5870
|
+
throw new Error("PromptBalanceVerification is missing \u2014 balance integrity cannot be confirmed");
|
|
5871
|
+
}
|
|
5872
|
+
const decrypted = await decrypt(rawVerification);
|
|
5873
|
+
if (decrypted !== String(balance)) {
|
|
5874
|
+
throw new Error(
|
|
5875
|
+
"PromptBalance integrity check failed: verification does not match stored balance"
|
|
5876
|
+
);
|
|
5877
|
+
}
|
|
5878
|
+
return balance;
|
|
5879
|
+
}
|
|
5880
|
+
async function getOrCreateClientReferenceId() {
|
|
5881
|
+
const db = await getDatabase();
|
|
5882
|
+
const existing = await getState(db, KEY_CLIENT_REFERENCE_ID);
|
|
5883
|
+
if (existing !== null && existing !== void 0) {
|
|
5884
|
+
return existing;
|
|
5885
|
+
}
|
|
5886
|
+
const id = randomUUID3();
|
|
5887
|
+
await setState(db, KEY_CLIENT_REFERENCE_ID, id);
|
|
5888
|
+
return id;
|
|
5889
|
+
}
|
|
5890
|
+
async function decrementBalance() {
|
|
5891
|
+
const current = await readVerifiedBalance();
|
|
5892
|
+
if (current <= 0) return;
|
|
5893
|
+
await writeBalance(current - 1);
|
|
5894
|
+
}
|
|
5895
|
+
async function processPayments(clientReferenceId) {
|
|
5896
|
+
const controller = new AbortController();
|
|
5897
|
+
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
5898
|
+
try {
|
|
5899
|
+
const res = await fetch(`https://payments.webnative.dev/account/${clientReferenceId}`, {
|
|
5900
|
+
method: "POST",
|
|
5901
|
+
signal: controller.signal
|
|
5902
|
+
});
|
|
5903
|
+
if (!res.ok) return;
|
|
5904
|
+
const data = await res.json();
|
|
5905
|
+
if (!data.success || !data.lineItems?.length) return;
|
|
5906
|
+
const db = await getDatabase();
|
|
5907
|
+
for (const item of data.lineItems) {
|
|
5908
|
+
if (item === "top-up-1000") {
|
|
5909
|
+
const current = await readVerifiedBalance();
|
|
5910
|
+
await writeBalance(current + 1e3);
|
|
5911
|
+
} else if (item === "pro-plan") {
|
|
5912
|
+
await setState(db, KEY_PLAN, "unlimited-pro");
|
|
5913
|
+
}
|
|
5914
|
+
}
|
|
5915
|
+
} catch {
|
|
5916
|
+
return;
|
|
5917
|
+
} finally {
|
|
5918
|
+
clearTimeout(timeoutId);
|
|
5919
|
+
}
|
|
5920
|
+
}
|
|
5921
|
+
async function getAccountInfo(c) {
|
|
5922
|
+
try {
|
|
5923
|
+
const db = await getDatabase();
|
|
5924
|
+
const clientReferenceId = await getOrCreateClientReferenceId();
|
|
5925
|
+
await processPayments(clientReferenceId);
|
|
5926
|
+
const promptsRemaining = await readVerifiedBalance();
|
|
5927
|
+
const rawPlan = await getState(db, KEY_PLAN);
|
|
5928
|
+
const plan = rawPlan === "unlimited-pro" ? "unlimited-pro" : "pay-as-you-go";
|
|
5929
|
+
return c.json({ promptsRemaining, plan, clientReferenceId });
|
|
5930
|
+
} catch (error) {
|
|
5931
|
+
console.error("Failed to get account info:", error);
|
|
5932
|
+
return c.json(
|
|
5933
|
+
{ error: error instanceof Error ? error.message : "Failed to get account info" },
|
|
5934
|
+
500
|
|
5935
|
+
);
|
|
5936
|
+
}
|
|
5937
|
+
}
|
|
5938
|
+
|
|
5725
5939
|
// src/features/chat/chat-post.route.ts
|
|
5726
5940
|
async function postChatMessage(c, threadManager, agentExecutor, conversationManager, processingStateManager) {
|
|
5727
5941
|
try {
|
|
@@ -5824,7 +6038,7 @@ async function postChatMessage(c, threadManager, agentExecutor, conversationMana
|
|
|
5824
6038
|
}
|
|
5825
6039
|
let conversationId = thread.currentConversationId;
|
|
5826
6040
|
if (!conversationId) {
|
|
5827
|
-
conversationId =
|
|
6041
|
+
conversationId = randomUUID4();
|
|
5828
6042
|
const db = await getDatabase();
|
|
5829
6043
|
await db.execute({
|
|
5830
6044
|
sql: "DELETE FROM todos WHERE threadId = ?",
|
|
@@ -5954,6 +6168,14 @@ User: ${content}` : content;
|
|
|
5954
6168
|
}
|
|
5955
6169
|
} finally {
|
|
5956
6170
|
processingStateManager.clearProcessing(threadId);
|
|
6171
|
+
const noResponse = capturedEvents.some(
|
|
6172
|
+
(e) => e.type === "error" && e.error?.code === "NO_CONTENT_NO_TOOLS"
|
|
6173
|
+
);
|
|
6174
|
+
if (!noResponse) {
|
|
6175
|
+
decrementBalance().catch((err) => {
|
|
6176
|
+
console.error("[ChatRoute] Failed to decrement balance:", err);
|
|
6177
|
+
});
|
|
6178
|
+
}
|
|
5957
6179
|
try {
|
|
5958
6180
|
const db = await getDatabase();
|
|
5959
6181
|
await invalidateGitStatusCache(db, threadId);
|
|
@@ -5994,7 +6216,7 @@ User: ${content}` : content;
|
|
|
5994
6216
|
}
|
|
5995
6217
|
|
|
5996
6218
|
// src/features/chat/chat-delete.route.ts
|
|
5997
|
-
import { randomUUID as
|
|
6219
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
5998
6220
|
init_database();
|
|
5999
6221
|
async function deleteChat(c, threadManager) {
|
|
6000
6222
|
try {
|
|
@@ -6016,7 +6238,7 @@ async function deleteChat(c, threadManager) {
|
|
|
6016
6238
|
sql: "DELETE FROM todos WHERE threadId = ?",
|
|
6017
6239
|
args: [threadId]
|
|
6018
6240
|
});
|
|
6019
|
-
const newConversationId =
|
|
6241
|
+
const newConversationId = randomUUID5();
|
|
6020
6242
|
await threadManager.updateThread(threadId, { currentConversationId: newConversationId });
|
|
6021
6243
|
return successResponse(
|
|
6022
6244
|
c,
|
|
@@ -6128,10 +6350,10 @@ function createChatRoutes(threadManager, agentExecutor, conversationManager, pro
|
|
|
6128
6350
|
init_database();
|
|
6129
6351
|
|
|
6130
6352
|
// src/features/conversations/conversations.database.ts
|
|
6131
|
-
import { randomUUID as
|
|
6353
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
6132
6354
|
async function insertMessage(db, threadId, conversationId, message, model, attachments, planMode) {
|
|
6133
6355
|
try {
|
|
6134
|
-
const messageId =
|
|
6356
|
+
const messageId = randomUUID6();
|
|
6135
6357
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
6136
6358
|
await db.execute(
|
|
6137
6359
|
`
|
|
@@ -7476,111 +7698,6 @@ function deserializeThread(row) {
|
|
|
7476
7698
|
};
|
|
7477
7699
|
}
|
|
7478
7700
|
|
|
7479
|
-
// src/core/crypto.ts
|
|
7480
|
-
init_database();
|
|
7481
|
-
import { createCipheriv, createDecipheriv, randomBytes as randomBytes2, createHash } from "crypto";
|
|
7482
|
-
import { networkInterfaces, hostname } from "os";
|
|
7483
|
-
var ALGORITHM = "aes-256-gcm";
|
|
7484
|
-
var IV_LENGTH = 16;
|
|
7485
|
-
function getMachineKey() {
|
|
7486
|
-
try {
|
|
7487
|
-
const interfaces = networkInterfaces();
|
|
7488
|
-
let macAddress = "";
|
|
7489
|
-
for (const name of Object.keys(interfaces)) {
|
|
7490
|
-
const iface = interfaces[name];
|
|
7491
|
-
if (iface) {
|
|
7492
|
-
for (const addr of iface) {
|
|
7493
|
-
if (addr.mac && addr.mac !== "00:00:00:00:00:00" && !addr.internal) {
|
|
7494
|
-
macAddress = addr.mac;
|
|
7495
|
-
break;
|
|
7496
|
-
}
|
|
7497
|
-
}
|
|
7498
|
-
if (macAddress) break;
|
|
7499
|
-
}
|
|
7500
|
-
}
|
|
7501
|
-
const host = hostname();
|
|
7502
|
-
const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
7503
|
-
const machineId = `${macAddress}-${host}-${homeDir}`;
|
|
7504
|
-
return createHash("sha256").update(machineId).digest();
|
|
7505
|
-
} catch {
|
|
7506
|
-
return Buffer.from("Invalid", "utf8");
|
|
7507
|
-
}
|
|
7508
|
-
}
|
|
7509
|
-
async function getEncryptionKey() {
|
|
7510
|
-
try {
|
|
7511
|
-
const db = await getDatabase();
|
|
7512
|
-
const result = await db.execute({
|
|
7513
|
-
sql: "SELECT value FROM state WHERE key = ?",
|
|
7514
|
-
args: ["encryption_key"]
|
|
7515
|
-
});
|
|
7516
|
-
if (result.rows.length > 0 && result.rows[0].value) {
|
|
7517
|
-
const storedValue = result.rows[0].value;
|
|
7518
|
-
try {
|
|
7519
|
-
const parsed = JSON.parse(storedValue);
|
|
7520
|
-
return Buffer.from(parsed, "base64");
|
|
7521
|
-
} catch {
|
|
7522
|
-
return Buffer.from(storedValue, "base64");
|
|
7523
|
-
}
|
|
7524
|
-
}
|
|
7525
|
-
const machineKey = getMachineKey();
|
|
7526
|
-
await db.execute({
|
|
7527
|
-
sql: "INSERT OR REPLACE INTO state (key, value) VALUES (?, ?)",
|
|
7528
|
-
args: ["encryption_key", machineKey.toString("base64")]
|
|
7529
|
-
});
|
|
7530
|
-
return machineKey;
|
|
7531
|
-
} catch {
|
|
7532
|
-
return getMachineKey();
|
|
7533
|
-
}
|
|
7534
|
-
}
|
|
7535
|
-
async function encrypt(plaintext) {
|
|
7536
|
-
if (!plaintext) {
|
|
7537
|
-
return "";
|
|
7538
|
-
}
|
|
7539
|
-
const key = await getEncryptionKey();
|
|
7540
|
-
const iv = randomBytes2(IV_LENGTH);
|
|
7541
|
-
const cipher = createCipheriv(ALGORITHM, key, iv);
|
|
7542
|
-
let encrypted = cipher.update(plaintext, "utf8", "base64");
|
|
7543
|
-
encrypted += cipher.final("base64");
|
|
7544
|
-
const authTag = cipher.getAuthTag();
|
|
7545
|
-
const result = `${iv.toString("base64")}:${authTag.toString("base64")}:${encrypted}`;
|
|
7546
|
-
return result;
|
|
7547
|
-
}
|
|
7548
|
-
async function decrypt(encryptedData) {
|
|
7549
|
-
if (!encryptedData) {
|
|
7550
|
-
return "";
|
|
7551
|
-
}
|
|
7552
|
-
try {
|
|
7553
|
-
const parts = encryptedData.split(":");
|
|
7554
|
-
if (parts.length !== 3) {
|
|
7555
|
-
throw new Error("Invalid encrypted data format");
|
|
7556
|
-
}
|
|
7557
|
-
const [ivBase64, authTagBase64, encrypted] = parts;
|
|
7558
|
-
const key = await getEncryptionKey();
|
|
7559
|
-
const iv = Buffer.from(ivBase64, "base64");
|
|
7560
|
-
const authTag = Buffer.from(authTagBase64, "base64");
|
|
7561
|
-
const decipher = createDecipheriv(ALGORITHM, key, iv);
|
|
7562
|
-
decipher.setAuthTag(authTag);
|
|
7563
|
-
let decrypted = decipher.update(encrypted, "base64", "utf8");
|
|
7564
|
-
decrypted += decipher.final("utf8");
|
|
7565
|
-
return decrypted;
|
|
7566
|
-
} catch (error) {
|
|
7567
|
-
throw new Error(
|
|
7568
|
-
`Decryption failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
7569
|
-
);
|
|
7570
|
-
}
|
|
7571
|
-
}
|
|
7572
|
-
function isEncrypted(value) {
|
|
7573
|
-
if (!value) {
|
|
7574
|
-
return false;
|
|
7575
|
-
}
|
|
7576
|
-
const parts = value.split(":");
|
|
7577
|
-
if (parts.length !== 3) {
|
|
7578
|
-
return false;
|
|
7579
|
-
}
|
|
7580
|
-
const base64Regex = /^[A-Za-z0-9+/]+=*$/;
|
|
7581
|
-
return parts.every((part) => base64Regex.test(part));
|
|
7582
|
-
}
|
|
7583
|
-
|
|
7584
7701
|
// src/database/database.encryption.ts
|
|
7585
7702
|
async function encryptProviderKey(key) {
|
|
7586
7703
|
if (!key) {
|
|
@@ -9528,17 +9645,6 @@ import { rm as rm3 } from "fs/promises";
|
|
|
9528
9645
|
// src/agent/agent.process-manager.ts
|
|
9529
9646
|
init_utils();
|
|
9530
9647
|
import { EventEmitter } from "events";
|
|
9531
|
-
var Utils = null;
|
|
9532
|
-
var utilsLoaded = false;
|
|
9533
|
-
async function loadUtils() {
|
|
9534
|
-
if (utilsLoaded) return;
|
|
9535
|
-
utilsLoaded = true;
|
|
9536
|
-
try {
|
|
9537
|
-
const electrobun = await import("electrobun/bun");
|
|
9538
|
-
Utils = electrobun.Utils;
|
|
9539
|
-
} catch {
|
|
9540
|
-
}
|
|
9541
|
-
}
|
|
9542
9648
|
var URL_PATTERNS = [
|
|
9543
9649
|
// http(s)://localhost:PORT
|
|
9544
9650
|
/https?:\/\/localhost[:/](\d+)/i,
|
|
@@ -9575,7 +9681,6 @@ var ProcessManager = class extends EventEmitter {
|
|
|
9575
9681
|
"cwd:",
|
|
9576
9682
|
cwd
|
|
9577
9683
|
);
|
|
9578
|
-
await loadUtils();
|
|
9579
9684
|
if (this.processes.has(projectId)) {
|
|
9580
9685
|
console.log("CLI ProcessManager: Process already running for project:", projectId);
|
|
9581
9686
|
yield {
|
|
@@ -9630,9 +9735,6 @@ var ProcessManager = class extends EventEmitter {
|
|
|
9630
9735
|
urlDetected = true;
|
|
9631
9736
|
this.detectedUrls.set(projectId, detectedUrl);
|
|
9632
9737
|
devServerCache.setUrl(threadId, detectedUrl);
|
|
9633
|
-
if (Utils) {
|
|
9634
|
-
Utils.openExternal(detectedUrl);
|
|
9635
|
-
}
|
|
9636
9738
|
addToQueue({ type: "url", url: detectedUrl });
|
|
9637
9739
|
}
|
|
9638
9740
|
}
|
|
@@ -9647,9 +9749,6 @@ var ProcessManager = class extends EventEmitter {
|
|
|
9647
9749
|
urlDetected = true;
|
|
9648
9750
|
this.detectedUrls.set(projectId, detectedUrl);
|
|
9649
9751
|
devServerCache.setUrl(threadId, detectedUrl);
|
|
9650
|
-
if (Utils) {
|
|
9651
|
-
Utils.openExternal(detectedUrl);
|
|
9652
|
-
}
|
|
9653
9752
|
addToQueue({ type: "url", url: detectedUrl });
|
|
9654
9753
|
}
|
|
9655
9754
|
}
|
|
@@ -9757,7 +9856,7 @@ var ProcessManager = class extends EventEmitter {
|
|
|
9757
9856
|
|
|
9758
9857
|
// src/features/projects/projects.creator.ts
|
|
9759
9858
|
init_utils();
|
|
9760
|
-
import { randomUUID as
|
|
9859
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
9761
9860
|
import { basename as basename2, join as join16, relative as relative4 } from "path";
|
|
9762
9861
|
import { access as access3, stat as stat3, readdir as readdir8 } from "fs/promises";
|
|
9763
9862
|
|
|
@@ -10737,14 +10836,14 @@ function generateRandomThreadName() {
|
|
|
10737
10836
|
}
|
|
10738
10837
|
|
|
10739
10838
|
// src/features/projects/projects.creator.ts
|
|
10740
|
-
var
|
|
10741
|
-
var
|
|
10742
|
-
async function
|
|
10743
|
-
if (
|
|
10744
|
-
|
|
10839
|
+
var Utils = null;
|
|
10840
|
+
var utilsLoaded = false;
|
|
10841
|
+
async function loadUtils() {
|
|
10842
|
+
if (utilsLoaded) return;
|
|
10843
|
+
utilsLoaded = true;
|
|
10745
10844
|
try {
|
|
10746
10845
|
const electrobun = await import("electrobun/bun");
|
|
10747
|
-
|
|
10846
|
+
Utils = electrobun.Utils;
|
|
10748
10847
|
} catch {
|
|
10749
10848
|
}
|
|
10750
10849
|
}
|
|
@@ -10766,14 +10865,14 @@ var ProjectCreator = class {
|
|
|
10766
10865
|
}
|
|
10767
10866
|
let initialThreadId;
|
|
10768
10867
|
try {
|
|
10769
|
-
const projectId =
|
|
10868
|
+
const projectId = randomUUID7();
|
|
10770
10869
|
const existingProjects = await this.metadataManager.loadProjects();
|
|
10771
10870
|
const existingNames = existingProjects.map((p) => p.name);
|
|
10772
10871
|
const projectName = this.ensureUniqueProjectName(
|
|
10773
10872
|
this.deriveProjectName(gitUrl),
|
|
10774
10873
|
existingNames
|
|
10775
10874
|
);
|
|
10776
|
-
initialThreadId =
|
|
10875
|
+
initialThreadId = randomUUID7();
|
|
10777
10876
|
const initialThreadTitle = generateRandomThreadName();
|
|
10778
10877
|
const firstThreadPath = this.generateThreadPath(projectId, initialThreadId);
|
|
10779
10878
|
this.processingStateManager?.setProcessing(initialThreadId);
|
|
@@ -10913,8 +11012,8 @@ var ProjectCreator = class {
|
|
|
10913
11012
|
};
|
|
10914
11013
|
return;
|
|
10915
11014
|
}
|
|
10916
|
-
const projectId =
|
|
10917
|
-
const initialThreadId =
|
|
11015
|
+
const projectId = randomUUID7();
|
|
11016
|
+
const initialThreadId = randomUUID7();
|
|
10918
11017
|
const initialThreadTitle = generateRandomThreadName();
|
|
10919
11018
|
this.processingStateManager?.setProcessing(initialThreadId);
|
|
10920
11019
|
try {
|
|
@@ -11039,12 +11138,12 @@ var ProjectCreator = class {
|
|
|
11039
11138
|
return join16(this.rootFolder, threadId);
|
|
11040
11139
|
}
|
|
11041
11140
|
async *createProjectFromFolder() {
|
|
11042
|
-
await
|
|
11043
|
-
if (!
|
|
11141
|
+
await loadUtils();
|
|
11142
|
+
if (!Utils) {
|
|
11044
11143
|
yield { type: "error", message: "File dialog not available in server mode" };
|
|
11045
11144
|
return;
|
|
11046
11145
|
}
|
|
11047
|
-
const chosenPaths = await
|
|
11146
|
+
const chosenPaths = await Utils.openFileDialog({
|
|
11048
11147
|
canChooseFiles: false,
|
|
11049
11148
|
canChooseDirectory: true,
|
|
11050
11149
|
allowsMultipleSelection: false
|
|
@@ -11064,8 +11163,8 @@ var ProjectCreator = class {
|
|
|
11064
11163
|
yield { type: "error", message: `Cannot access folder: ${folderPath}` };
|
|
11065
11164
|
return;
|
|
11066
11165
|
}
|
|
11067
|
-
const projectId =
|
|
11068
|
-
const initialThreadId =
|
|
11166
|
+
const projectId = randomUUID7();
|
|
11167
|
+
const initialThreadId = randomUUID7();
|
|
11069
11168
|
const initialThreadTitle = generateRandomThreadName();
|
|
11070
11169
|
this.processingStateManager?.setProcessing(initialThreadId);
|
|
11071
11170
|
try {
|
|
@@ -11927,20 +12026,20 @@ async function getProviderCredits(c, metadataManager) {
|
|
|
11927
12026
|
}
|
|
11928
12027
|
|
|
11929
12028
|
// src/features/providers/providers-open-external.route.ts
|
|
11930
|
-
var
|
|
11931
|
-
var
|
|
11932
|
-
async function
|
|
11933
|
-
if (
|
|
11934
|
-
|
|
12029
|
+
var Utils2 = null;
|
|
12030
|
+
var utilsLoaded2 = false;
|
|
12031
|
+
async function loadUtils2() {
|
|
12032
|
+
if (utilsLoaded2) return;
|
|
12033
|
+
utilsLoaded2 = true;
|
|
11935
12034
|
try {
|
|
11936
12035
|
const electrobun = await import("electrobun/bun");
|
|
11937
|
-
|
|
12036
|
+
Utils2 = electrobun.Utils;
|
|
11938
12037
|
} catch {
|
|
11939
12038
|
}
|
|
11940
12039
|
}
|
|
11941
12040
|
async function openExternalUrl(c) {
|
|
11942
12041
|
try {
|
|
11943
|
-
await
|
|
12042
|
+
await loadUtils2();
|
|
11944
12043
|
const { url } = await c.req.json();
|
|
11945
12044
|
if (!url || typeof url !== "string") {
|
|
11946
12045
|
return c.json({ error: "URL is required and must be a string" }, 400);
|
|
@@ -11950,8 +12049,8 @@ async function openExternalUrl(c) {
|
|
|
11950
12049
|
} catch {
|
|
11951
12050
|
return c.json({ error: "Invalid URL format" }, 400);
|
|
11952
12051
|
}
|
|
11953
|
-
if (
|
|
11954
|
-
await
|
|
12052
|
+
if (Utils2) {
|
|
12053
|
+
await Utils2.openExternal(url);
|
|
11955
12054
|
return c.json({ success: true });
|
|
11956
12055
|
} else {
|
|
11957
12056
|
console.error(`External URL opening not available in server mode: ${url}`);
|
|
@@ -12696,7 +12795,7 @@ function createRuleRoutes(router, projectManager) {
|
|
|
12696
12795
|
|
|
12697
12796
|
// src/features/threads/threads.manager.ts
|
|
12698
12797
|
init_utils();
|
|
12699
|
-
import { randomUUID as
|
|
12798
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
12700
12799
|
import { join as join20 } from "path";
|
|
12701
12800
|
import { execSync as execSync3 } from "child_process";
|
|
12702
12801
|
import { rm as rm4, stat as stat4, mkdir as mkdir4 } from "fs/promises";
|
|
@@ -12763,7 +12862,7 @@ var ThreadManagerImpl = class {
|
|
|
12763
12862
|
} catch {
|
|
12764
12863
|
await mkdir4(project.path, { recursive: true });
|
|
12765
12864
|
}
|
|
12766
|
-
threadId =
|
|
12865
|
+
threadId = randomUUID8();
|
|
12767
12866
|
const threadPath = this.generateThreadPath(projectId, threadId);
|
|
12768
12867
|
const existingThreads = await this.metadataManager.loadThreads();
|
|
12769
12868
|
const existingTitles = new Set(
|
|
@@ -14444,7 +14543,7 @@ DESCRIPTION: <description here>`;
|
|
|
14444
14543
|
try {
|
|
14445
14544
|
const providerKeys = await metadataManager.getProviderKeys();
|
|
14446
14545
|
const resolved = await resolveProviderAndKey(providerKeys, provider);
|
|
14447
|
-
if (!resolved
|
|
14546
|
+
if (!resolved) {
|
|
14448
14547
|
const errorMsg = provider ? `AI provider "${provider}" is specified but no API key is configured. Please add the API key in settings.` : `No AI provider configured. Please configure a provider in settings.`;
|
|
14449
14548
|
console.log(`[pr-generation] ${errorMsg}`);
|
|
14450
14549
|
return { title: "Update", description: "" };
|
|
@@ -14499,7 +14598,7 @@ Generate only the commit message, nothing else:`;
|
|
|
14499
14598
|
try {
|
|
14500
14599
|
const providerKeys = await metadataManager.getProviderKeys();
|
|
14501
14600
|
const resolved = await resolveProviderAndKey(providerKeys, provider);
|
|
14502
|
-
if (!resolved
|
|
14601
|
+
if (!resolved) {
|
|
14503
14602
|
const errorMsg = provider ? `AI provider "${provider}" is specified but no API key is configured. Please add the API key in settings.` : `No AI provider configured. Please configure a provider in settings.`;
|
|
14504
14603
|
process.stdout.write(`[generate-commit-message] ${errorMsg}
|
|
14505
14604
|
`);
|
|
@@ -16899,7 +16998,7 @@ Todo description: ${description}`;
|
|
|
16899
16998
|
try {
|
|
16900
16999
|
const providerKeys = await metadataManager.getProviderKeys();
|
|
16901
17000
|
const resolved = await resolveProviderAndKey(providerKeys);
|
|
16902
|
-
if (!resolved
|
|
17001
|
+
if (!resolved) return description.slice(0, 60);
|
|
16903
17002
|
const selectedModel = DEFAULT_MODEL_MAP[resolved.provider.name] || "default";
|
|
16904
17003
|
const resolvedModel = resolveModelForGit(
|
|
16905
17004
|
resolved.provider.name,
|
|
@@ -16973,13 +17072,21 @@ function createProjectTodosRoutes(metadataManager) {
|
|
|
16973
17072
|
return router;
|
|
16974
17073
|
}
|
|
16975
17074
|
|
|
17075
|
+
// src/features/account/account.routes.ts
|
|
17076
|
+
import { Hono as Hono15 } from "hono";
|
|
17077
|
+
function createAccountRoutes() {
|
|
17078
|
+
const router = new Hono15();
|
|
17079
|
+
router.get("/info", (c) => getAccountInfo(c));
|
|
17080
|
+
return router;
|
|
17081
|
+
}
|
|
17082
|
+
|
|
16976
17083
|
// src/server.ts
|
|
16977
17084
|
var __filename = fileURLToPath2(import.meta.url);
|
|
16978
17085
|
var __dirname = path5.dirname(__filename);
|
|
16979
17086
|
async function startTarskServer(options) {
|
|
16980
17087
|
const { isDebug: isDebug2, publicDir: publicDirOverride } = options;
|
|
16981
17088
|
const port = isDebug2 ? 462 : process.env.PORT ? parseInt(process.env.PORT) : 641;
|
|
16982
|
-
const app = new
|
|
17089
|
+
const app = new Hono16();
|
|
16983
17090
|
app.use("/*", cors());
|
|
16984
17091
|
app.use("/*", async (c, next) => {
|
|
16985
17092
|
if (c.req.path.startsWith("/api/")) {
|
|
@@ -17043,6 +17150,7 @@ async function startTarskServer(options) {
|
|
|
17043
17150
|
app.route("/api/mcp", createMCPRoutes());
|
|
17044
17151
|
app.route("/api/git", createGitRoutes(metadataManager));
|
|
17045
17152
|
app.route("/api/onboarding", createOnboardingRoutes(metadataManager));
|
|
17153
|
+
app.route("/api/account", createAccountRoutes());
|
|
17046
17154
|
app.route("/api/scaffold", createScaffoldRoutes(projectManager));
|
|
17047
17155
|
app.route("/api/ask-user", createAskUserRoutes());
|
|
17048
17156
|
app.route("/api/update", createUpdateRoutes(options.updater));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-Dw2cE7zH.js";import{Nt as t,Pi as n,Rr as r,Vr as i,X as a,dn as o,er as s,li as c,wi as l}from"./dialogs-config-CB7G-sX6.js";import{a as u}from"./index-D7yQjYyf.js";var d=e(n(),1),f=s();function p(){let[e,n]=(0,d.useState)(null),[s,p]=(0,d.useState)(!0);(0,d.useEffect)(()=>{m();let e=()=>{document.visibilityState===`visible`&&m()};return document.addEventListener(`visibilitychange`,e),()=>document.removeEventListener(`visibilitychange`,e)},[]);async function m(){p(!0);try{n(await a())}catch(e){u({title:`Error`,description:e instanceof Error?e.message:`Failed to load account info`,variant:`destructive`})}finally{p(!1)}}function h(){t(`https://buy.stripe.com/14AcN6feK0Jjbheb2H3Nm03?client_reference_id=${e?.clientReferenceId??``}`)}function g(){t(`https://buy.stripe.com/9B67sMd6CgIh70Y0o33Nm04?client_reference_id=${e?.clientReferenceId??``}`)}if(s)return(0,f.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,f.jsx)(i,{className:`h-5 w-5 animate-spin text-muted-foreground`})});let _=e?.plan===`unlimited-pro`;return(0,f.jsxs)(`div`,{className:`max-w-2xl mx-auto p-6`,children:[(0,f.jsxs)(`div`,{className:`mb-6`,children:[(0,f.jsx)(`h1`,{className:`text-2xl font-bold`,children:`Account`}),(0,f.jsx)(`p`,{className:`text-muted-foreground`,children:`Manage your Tarsk plan and prompt balance.`})]}),(0,f.jsxs)(`div`,{className:`space-y-6`,children:[(0,f.jsxs)(`div`,{className:`flex gap-4`,children:[(0,f.jsxs)(`div`,{className:`flex-1 rounded-xl border bg-card p-5 space-y-2`,children:[(0,f.jsxs)(`div`,{className:`flex items-center gap-2 text-sm font-medium text-muted-foreground`,children:[(0,f.jsx)(r,{className:`h-4 w-4`}),`Balance`]}),(0,f.jsx)(`div`,{className:`flex items-end gap-2`,children:_?(0,f.jsx)(`span`,{className:`text-3xl font-bold`,children:`Unlimited`}):(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(`span`,{className:`text-3xl font-bold`,children:e?.promptsRemaining.toLocaleString()??0}),(0,f.jsx)(`span`,{className:`text-muted-foreground mb-1 text-sm`,children:`prompts remaining`})]})})]}),(0,f.jsxs)(`div`,{className:`flex-1 rounded-xl border bg-card p-5 space-y-3`,children:[(0,f.jsxs)(`div`,{className:`flex items-center gap-2 text-sm font-medium text-muted-foreground`,children:[(0,f.jsx)(c,{className:`h-4 w-4`}),`Current Plan`]}),(0,f.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,f.jsx)(`span`,{className:`text-lg font-semibold`,children:_?`Unlimited Pro`:`Pay as you go`}),_&&(0,f.jsx)(`span`,{className:`rounded-full bg-primary/10 px-2 py-0.5 text-xs font-medium text-primary`,children:`Active`})]}),(0,f.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:_?`You have unlimited prompts with no restrictions.`:`Purchase prompts as needed. Upgrade to Pro for unlimited access.`})]})]}),!_&&(0,f.jsxs)(`div`,{className:`space-y-3`,children:[(0,f.jsx)(`h2`,{className:`text-sm font-semibold text-muted-foreground uppercase tracking-wide`,children:`Add Prompts`}),(0,f.jsxs)(`div`,{className:`rounded-xl border bg-card p-5 flex items-center justify-between gap-4`,children:[(0,f.jsxs)(`div`,{className:`space-y-1`,children:[(0,f.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,f.jsx)(`span`,{className:`font-semibold`,children:`1,000 Prompts`})}),(0,f.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Top up your balance with 1,000 additional prompts for $5.`})]}),(0,f.jsx)(o,{onClick:h,className:`shrink-0`,children:`Top Up Balance`})]}),(0,f.jsxs)(`div`,{className:`rounded-xl border bg-card p-5 flex items-center justify-between gap-4`,children:[(0,f.jsxs)(`div`,{className:`space-y-1`,children:[(0,f.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,f.jsx)(c,{className:`h-4 w-4 text-primary`}),(0,f.jsx)(`span`,{className:`font-semibold`,children:`Unlimited Pro Plan`})]}),(0,f.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Unlimited prompts for $100 and lifetime access to Tarsk.`}),(0,f.jsxs)(`ul`,{className:`text-sm text-muted-foreground space-y-0.5`,children:[(0,f.jsxs)(`li`,{className:`flex items-center gap-1.5`,children:[(0,f.jsx)(l,{className:`h-3 w-3 text-primary`}),`Unlimited prompts`]}),(0,f.jsxs)(`li`,{className:`flex items-center gap-1.5`,children:[(0,f.jsx)(l,{className:`h-3 w-3 text-primary`}),`Priority access`]})]})]}),(0,f.jsx)(o,{onClick:g,className:`shrink-0`,children:`Purchase`})]})]})]})]})}export{p as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-Dw2cE7zH.js";import{I as t,Pi as n,Vr as r,c as i,dn as a,er as o,l as s,xi as c}from"./dialogs-config-CB7G-sX6.js";import"./react-vendor-CR4cAsbx.js";import"./history-view-D-hEB6Qt.js";import{a as l,c as u}from"./index-D7yQjYyf.js";import{n as d,t as f}from"./radio-group-BpmnaKJk.js";var p=e(n(),1),m=o();function h({threadId:e,onAgentCreated:n}){let[o,h]=(0,p.useState)(``),[g,_]=(0,p.useState)(``),[v,y]=(0,p.useState)(``),[b,x]=(0,p.useState)(`local`),[S,C]=(0,p.useState)(!1),w=o.toLowerCase().replace(/\s+/g,`-`).replace(/[^a-z0-9-]/g,``).replace(/-+/g,`-`).replace(/^-|-$/g,``),T=w.length>0&&w.length<=64;return e?(0,m.jsxs)(`div`,{className:`max-w-2xl mx-auto p-6`,children:[(0,m.jsxs)(`div`,{className:`mb-6`,children:[(0,m.jsx)(`h1`,{className:`text-2xl font-bold`,children:`Add Agent`}),(0,m.jsx)(`p`,{className:`text-muted-foreground`,children:`Create a new subagent. The agent will be saved as an AGENT.md file in the .agents/agents folder.`})]}),(0,m.jsxs)(`div`,{className:`space-y-6`,children:[(0,m.jsxs)(`div`,{className:`space-y-2`,children:[(0,m.jsx)(s,{htmlFor:`agentName`,children:`Agent Name`}),(0,m.jsx)(i,{id:`agentName`,value:o,onChange:e=>h(e.target.value),placeholder:`e.g. Security Reviewer`,disabled:S}),o&&(0,m.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Folder name: `,(0,m.jsx)(`span`,{className:`font-mono`,children:w||`...`})]})]}),(0,m.jsxs)(`div`,{className:`space-y-2`,children:[(0,m.jsx)(s,{htmlFor:`agentDescription`,children:`Description`}),(0,m.jsx)(u,{id:`agentDescription`,value:g,onChange:e=>_(e.target.value),placeholder:`Describe what this agent does and when it should be invoked`,className:`resize-none min-h-[120px]`,disabled:S})]}),(0,m.jsxs)(`div`,{className:`space-y-2`,children:[(0,m.jsx)(s,{htmlFor:`agentTools`,children:`Allowed Tools (optional)`}),(0,m.jsx)(i,{id:`agentTools`,value:v,onChange:e=>y(e.target.value),placeholder:`e.g. read grep glob`,disabled:S}),(0,m.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Space-separated list of tools this agent can use. Leave empty to allow all coding tools.`})]}),(0,m.jsxs)(`div`,{className:`space-y-2`,children:[(0,m.jsx)(s,{children:`Scope`}),(0,m.jsxs)(f,{value:b,onValueChange:e=>x(e),className:`flex gap-4`,disabled:S,children:[(0,m.jsxs)(`div`,{className:`flex items-center space-x-2`,children:[(0,m.jsx)(d,{value:`local`,id:`scope-local`}),(0,m.jsx)(s,{htmlFor:`scope-local`,className:`font-normal cursor-pointer`,children:`Local (this project)`})]}),(0,m.jsxs)(`div`,{className:`flex items-center space-x-2`,children:[(0,m.jsx)(d,{value:`global`,id:`scope-global`,disabled:!0}),(0,m.jsx)(s,{htmlFor:`scope-global`,className:`font-normal cursor-pointer text-muted-foreground`,children:`Global (coming soon)`})]})]}),(0,m.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:b===`local`?`This agent will only be available for this project.`:`This agent will be available across all projects (coming soon).`})]}),(0,m.jsx)(`div`,{className:`border-t pt-4 flex justify-end`,children:(0,m.jsx)(a,{onClick:async()=>{if(!(!T||!g.trim()||!e)){C(!0);try{let r=await t(e,w,g.trim(),v.trim()||void 0);l({title:`Agent created`,description:`Agent '${w}' was created successfully.`}),h(``),_(``),y(``),x(`local`),n?.(r.path,`AGENT.md`)}catch(e){l({title:`Error`,description:e instanceof Error?e.message:`Failed to create agent`,variant:`destructive`})}finally{C(!1)}}},disabled:!T||!g.trim()||S,children:S?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)(r,{className:`mr-2 h-4 w-4 animate-spin`}),`Creating...`]}):(0,m.jsxs)(m.Fragment,{children:[`Continue`,(0,m.jsx)(c,{className:`ml-2 h-4 w-4`})]})})})]})]}):(0,m.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,m.jsxs)(`div`,{className:`text-center`,children:[(0,m.jsx)(`h2`,{className:`text-lg font-semibold text-muted-foreground mb-2`,children:`No Thread Selected`}),(0,m.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Please select a thread to add an agent.`})]})})}export{h as default};
|