@cortask/core 0.2.10 → 0.2.13

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.d.ts CHANGED
@@ -1033,7 +1033,7 @@ declare function getEligibleSkills(skills: SkillEntry[]): SkillEntry[];
1033
1033
  interface SkillToolRegistry {
1034
1034
  toolDefs: ToolDefinition[];
1035
1035
  toolNames: Set<string>;
1036
- handlers: Map<string, (args: Record<string, unknown>) => Promise<ToolResult>>;
1036
+ handlers: Map<string, (args: Record<string, unknown>, workspacePath: string) => Promise<ToolResult>>;
1037
1037
  }
1038
1038
  /**
1039
1039
  * Build tool definitions and handlers from eligible skills.
package/dist/index.js CHANGED
@@ -3048,9 +3048,9 @@ async function ensureBrowser() {
3048
3048
  async screenshot() {
3049
3049
  const tmpPath = `${process.env.TEMP || "/tmp"}/ab-screenshot-${Date.now()}.png`;
3050
3050
  await exec2(["screenshot", tmpPath]);
3051
- const fs17 = await import("fs/promises");
3052
- const buf = await fs17.readFile(tmpPath);
3053
- await fs17.unlink(tmpPath).catch(() => {
3051
+ const fs18 = await import("fs/promises");
3052
+ const buf = await fs18.readFile(tmpPath);
3053
+ await fs18.unlink(tmpPath).catch(() => {
3054
3054
  });
3055
3055
  return buf;
3056
3056
  },
@@ -4525,7 +4525,8 @@ async function isBinaryAvailable(name) {
4525
4525
  }
4526
4526
 
4527
4527
  // src/skills/tools.ts
4528
- var MAX_RESPONSE_LENGTH = 5e4;
4528
+ import fs16 from "fs/promises";
4529
+ import path15 from "path";
4529
4530
  async function buildSkillTools(skills, credentialStore) {
4530
4531
  const toolDefs = [];
4531
4532
  const toolNames = /* @__PURE__ */ new Set();
@@ -4536,12 +4537,13 @@ async function buildSkillTools(skills, credentialStore) {
4536
4537
  const def = buildHttpToolDefinition(template);
4537
4538
  toolDefs.push(def);
4538
4539
  toolNames.add(def.name);
4539
- handlers.set(def.name, async (args) => {
4540
+ handlers.set(def.name, async (args, workspacePath) => {
4540
4541
  return executeHttpTool(
4541
4542
  template,
4542
4543
  args,
4543
4544
  skill,
4544
- credentialStore
4545
+ credentialStore,
4546
+ workspacePath
4545
4547
  );
4546
4548
  });
4547
4549
  }
@@ -4558,7 +4560,7 @@ async function buildSkillTools(skills, credentialStore) {
4558
4560
  inputSchema: ct.inputSchema
4559
4561
  });
4560
4562
  toolNames.add(ct.name);
4561
- handlers.set(ct.name, async (args) => {
4563
+ handlers.set(ct.name, async (args, _workspacePath) => {
4562
4564
  try {
4563
4565
  const result = await ct.execute(args, {
4564
4566
  credentialStore,
@@ -4613,10 +4615,10 @@ function buildHttpToolDefinition(template) {
4613
4615
  }
4614
4616
  };
4615
4617
  }
4616
- async function executeHttpTool(template, args, skill, credentialStore) {
4618
+ async function executeHttpTool(template, args, skill, credentialStore, workspacePath) {
4617
4619
  try {
4618
4620
  const credValues = await resolveCredentials(skill, credentialStore);
4619
- let url = resolvePlaceholders(
4621
+ const url = resolvePlaceholders(
4620
4622
  template.request.url,
4621
4623
  args,
4622
4624
  credValues
@@ -4645,7 +4647,7 @@ async function executeHttpTool(template, args, skill, credentialStore) {
4645
4647
  body: method !== "GET" ? body : void 0,
4646
4648
  signal: AbortSignal.timeout(6e4)
4647
4649
  });
4648
- let content = await response.text();
4650
+ const content = await response.text();
4649
4651
  if (!response.ok) {
4650
4652
  return {
4651
4653
  toolCallId: "",
@@ -4653,10 +4655,24 @@ async function executeHttpTool(template, args, skill, credentialStore) {
4653
4655
  isError: true
4654
4656
  };
4655
4657
  }
4656
- if (content.length > MAX_RESPONSE_LENGTH) {
4657
- content = content.slice(0, MAX_RESPONSE_LENGTH) + "\n...(truncated)";
4658
- }
4659
- return { toolCallId: "", content };
4658
+ const tempDir = path15.join(workspacePath, "_temp");
4659
+ await fs16.mkdir(tempDir, { recursive: true });
4660
+ const isJson = looksLikeJson(content);
4661
+ const ext = isJson ? "json" : "txt";
4662
+ const filename = `${template.name}_${Date.now()}.${ext}`;
4663
+ const filePath = path15.join(tempDir, filename);
4664
+ await fs16.writeFile(filePath, content, "utf-8");
4665
+ const summary = buildResponseSummary(content, isJson);
4666
+ return {
4667
+ toolCallId: "",
4668
+ content: [
4669
+ `Data saved to: _temp/${filename}`,
4670
+ `Size: ${formatBytes(content.length)}`,
4671
+ summary,
4672
+ "",
4673
+ "Use data_file to inspect or query this data, or artifact to display it."
4674
+ ].join("\n")
4675
+ };
4660
4676
  } catch (err) {
4661
4677
  return {
4662
4678
  toolCallId: "",
@@ -4665,6 +4681,55 @@ async function executeHttpTool(template, args, skill, credentialStore) {
4665
4681
  };
4666
4682
  }
4667
4683
  }
4684
+ function looksLikeJson(content) {
4685
+ const trimmed = content.trimStart();
4686
+ return trimmed.startsWith("{") || trimmed.startsWith("[");
4687
+ }
4688
+ function formatBytes(bytes) {
4689
+ if (bytes < 1024) return `${bytes} B`;
4690
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
4691
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
4692
+ }
4693
+ function buildResponseSummary(content, isJson) {
4694
+ if (!isJson) {
4695
+ const lines = content.split("\n");
4696
+ return `Lines: ${lines.length}
4697
+ Preview:
4698
+ ${lines.slice(0, 5).join("\n")}`;
4699
+ }
4700
+ try {
4701
+ const parsed = JSON.parse(content);
4702
+ if (Array.isArray(parsed)) {
4703
+ const count = parsed.length;
4704
+ const sample = parsed[0];
4705
+ const columns = sample && typeof sample === "object" ? Object.keys(sample) : [];
4706
+ return [
4707
+ `Format: JSON array (${count} items)`,
4708
+ columns.length > 0 ? `Columns: ${columns.join(", ")}` : "",
4709
+ count > 0 ? `Sample: ${JSON.stringify(parsed[0]).slice(0, 300)}` : ""
4710
+ ].filter(Boolean).join("\n");
4711
+ }
4712
+ if (typeof parsed === "object" && parsed !== null) {
4713
+ const keys = Object.keys(parsed);
4714
+ const arrayKey = keys.find((k) => Array.isArray(parsed[k]));
4715
+ if (arrayKey) {
4716
+ const arr = parsed[arrayKey];
4717
+ const sample = arr[0];
4718
+ const columns = sample && typeof sample === "object" && sample !== null ? Object.keys(sample) : [];
4719
+ return [
4720
+ `Format: JSON object with ${keys.length} keys: ${keys.join(", ")}`,
4721
+ `Data in "${arrayKey}": ${arr.length} items`,
4722
+ columns.length > 0 ? `Columns: ${columns.join(", ")}` : "",
4723
+ arr.length > 0 ? `Sample: ${JSON.stringify(arr[0]).slice(0, 300)}` : ""
4724
+ ].filter(Boolean).join("\n");
4725
+ }
4726
+ return `Format: JSON object with ${keys.length} keys: ${keys.join(", ")}`;
4727
+ }
4728
+ return `Format: JSON (${typeof parsed})`;
4729
+ } catch {
4730
+ return "Format: text (invalid JSON)";
4731
+ }
4732
+ }
4668
4733
  async function resolveCredentials(skill, credentialStore) {
4669
4734
  const values = /* @__PURE__ */ new Map();
4670
4735
  if (!skill.credentialSchema || !credentialStore) return values;
@@ -4732,37 +4797,37 @@ function resolvePlaceholders(template, args, credValues) {
4732
4797
 
4733
4798
  // src/skills/installer.ts
4734
4799
  import { exec as exec3 } from "child_process";
4735
- import fs16 from "fs/promises";
4736
- import path15 from "path";
4800
+ import fs17 from "fs/promises";
4801
+ import path16 from "path";
4737
4802
  async function installSkillFromGit(gitUrl, skillsDir) {
4738
- await fs16.mkdir(skillsDir, { recursive: true });
4803
+ await fs17.mkdir(skillsDir, { recursive: true });
4739
4804
  const repoName = gitUrl.split("/").pop()?.replace(/\.git$/, "");
4740
4805
  if (!repoName) {
4741
4806
  throw new Error(`Invalid git URL: ${gitUrl}`);
4742
4807
  }
4743
- const targetDir = path15.join(skillsDir, repoName);
4808
+ const targetDir = path16.join(skillsDir, repoName);
4744
4809
  try {
4745
- await fs16.access(targetDir);
4810
+ await fs17.access(targetDir);
4746
4811
  throw new Error(`Skill "${repoName}" is already installed`);
4747
4812
  } catch (err) {
4748
4813
  if (err.message.includes("already installed")) throw err;
4749
4814
  }
4750
4815
  await execAsync(`git clone --depth 1 "${gitUrl}" "${targetDir}"`);
4751
4816
  try {
4752
- await fs16.access(path15.join(targetDir, "SKILL.md"));
4817
+ await fs17.access(path16.join(targetDir, "SKILL.md"));
4753
4818
  } catch {
4754
- await fs16.rm(targetDir, { recursive: true, force: true });
4819
+ await fs17.rm(targetDir, { recursive: true, force: true });
4755
4820
  throw new Error(
4756
4821
  `Invalid skill: no SKILL.md found in ${repoName}`
4757
4822
  );
4758
4823
  }
4759
- await fs16.writeFile(
4760
- path15.join(targetDir, ".origin"),
4824
+ await fs17.writeFile(
4825
+ path16.join(targetDir, ".origin"),
4761
4826
  gitUrl,
4762
4827
  "utf-8"
4763
4828
  );
4764
4829
  try {
4765
- await fs16.rm(path15.join(targetDir, ".git"), {
4830
+ await fs17.rm(path16.join(targetDir, ".git"), {
4766
4831
  recursive: true,
4767
4832
  force: true
4768
4833
  });
@@ -4773,13 +4838,13 @@ async function installSkillFromGit(gitUrl, skillsDir) {
4773
4838
  return { name: repoName, path: targetDir };
4774
4839
  }
4775
4840
  async function removeSkill(skillName, skillsDir) {
4776
- const targetDir = path15.join(skillsDir, skillName);
4841
+ const targetDir = path16.join(skillsDir, skillName);
4777
4842
  try {
4778
- await fs16.access(targetDir);
4843
+ await fs17.access(targetDir);
4779
4844
  } catch {
4780
4845
  throw new Error(`Skill "${skillName}" not found`);
4781
4846
  }
4782
- await fs16.rm(targetDir, { recursive: true, force: true });
4847
+ await fs17.rm(targetDir, { recursive: true, force: true });
4783
4848
  clearSkillCache();
4784
4849
  logger.info(`Removed skill "${skillName}"`, "skills");
4785
4850
  }