@jixo/cli 0.26.0 → 4.0.0

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/bundle/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { $ZodAny, $ZodArray, $ZodBoolean, $ZodCustom, $ZodLiteral, $ZodNumber, $ZodObject, $ZodOptional, $ZodString, $ZodType, $ZodUnion, $ZodUnknown, $constructor, __commonJS as __commonJS$1, __export as __export$2, __require as __require$1, __toESM as __toESM$1, _any, _boolean, _custom, _enum, _number, _string, _unknown, array as array$2, assetsResolver, assignProp, boolean as boolean$1, clone as clone$2, createAcontext, createResolver, defineLazy, delay, extend as extend$1, func_catch, func_remember, globFilesWithParams, globbySync, isDynamicPattern, iter_map_not_null, literal as literal$2, map_get_or_put, map_get_or_put_async, normalizeFilePath, normalizeParams, number as number$1, obj_assign_props, obj_props, object as object$1, parse as parse$5, parseAsync, partial as partial$1, reactiveFs, readJson, require_src as require_src$1, safeParse, safeParseAsync, string as string$1, timmers, toJSONSchema, toPath, traversePathUp, union as union$1, z, zod_default } from "./file-replacer-CZhq6MJJ.js";
3
- import { _gen_content, blue, bold, cyan, doGenPrompts, gray, green, italic as italic$1, magenta, red, simpleGit, underline as underline$1, yellow } from "./gen-prompt-3bZp8K__.js";
2
+ import { $ZodAny, $ZodArray, $ZodBoolean, $ZodCustom, $ZodDiscriminatedUnion, $ZodLiteral, $ZodNumber, $ZodObject, $ZodOptional, $ZodString, $ZodType, $ZodUnion, $ZodUnknown, $constructor, __commonJS as __commonJS$1, __export as __export$2, __require as __require$1, __toESM as __toESM$1, _any, _boolean, _custom, _enum, _number, _string, _unknown, array as array$2, assignProp, boolean as boolean$1, clone as clone$2, createAcontext, createResolver, defineLazy, delay, extend as extend$1, func_catch, func_remember, globFilesWithParams, globbySync, isDynamicPattern, iter_map_not_null, literal as literal$2, map_get_or_put, map_get_or_put_async, normalizeFilePath, normalizeParams, number as number$1, obj_assign_props, object as object$1, parse as parse$5, parseAsync, partial as partial$1, reactiveFs, require_src as require_src$1, safeParse, safeParseAsync, string as string$1, timmers, toJSONSchema, toPath, traversePathUp, union as union$1, z, zod_default } from "./file-replacer-C3H2FqOL.js";
3
+ import { _gen_content, blue, bold, cyan, doGenPrompts, gray, green, italic as italic$1, magenta, red, simpleGit, underline as underline$1, yellow as yellow$1 } from "./gen-prompt-DxNgl5Cp.js";
4
4
  import { createRequire } from "node:module";
5
5
  import { URL as URL$1, fileURLToPath, pathToFileURL } from "node:url";
6
6
  import path, { dirname } from "node:path";
7
- import fs, { appendFileSync, createReadStream, createWriteStream, existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "node:fs";
7
+ import fs, { appendFileSync, createReadStream, createWriteStream, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "node:fs";
8
8
  import assert3, { notStrictEqual, strictEqual } from "node:assert";
9
9
  import * as path$6 from "node:path";
10
10
  import path10, { basename, dirname as dirname$1, extname, join as join$1, normalize, relative, resolve } from "node:path";
@@ -1733,7 +1733,7 @@ var import_get_caller_file = /* @__PURE__ */ __toESM$1(require_get_caller_file()
1733
1733
  const __dirname$1 = fileURLToPath$1(import.meta.url);
1734
1734
  const mainFilename = __dirname$1.substring(0, __dirname$1.lastIndexOf("node_modules"));
1735
1735
  const require$2 = createRequire(import.meta.url);
1736
- var esm_default$4 = {
1736
+ var esm_default$2 = {
1737
1737
  assert: {
1738
1738
  notStrictEqual,
1739
1739
  strictEqual
@@ -4630,13 +4630,13 @@ function isYargsInstance(y) {
4630
4630
 
4631
4631
  //#endregion
4632
4632
  //#region ../../node_modules/.pnpm/yargs@18.0.0/node_modules/yargs/index.mjs
4633
- const Yargs = YargsFactory(esm_default$4);
4633
+ const Yargs = YargsFactory(esm_default$2);
4634
4634
  var yargs_default = Yargs;
4635
4635
 
4636
4636
  //#endregion
4637
4637
  //#region package.json
4638
4638
  var name$11 = "@jixo/cli";
4639
- var version = "0.26.0";
4639
+ var version = "0.1.0";
4640
4640
  var type = "module";
4641
4641
  var bin = { "jixo": "./bundle/index.js" };
4642
4642
  var files = [
@@ -4758,7 +4758,6 @@ const func_throttle = (fn, wait = 0, options = {}) => {
4758
4758
  const isUpKey = (key$1) => key$1.name === "up" || key$1.name === "k" || key$1.ctrl && key$1.name === "p";
4759
4759
  const isDownKey = (key$1) => key$1.name === "down" || key$1.name === "j" || key$1.ctrl && key$1.name === "n";
4760
4760
  const isSpaceKey = (key$1) => key$1.name === "space";
4761
- const isBackspaceKey = (key$1) => key$1.name === "backspace";
4762
4761
  const isNumberKey = (key$1) => "1234567890".includes(key$1.name);
4763
4762
  const isEnterKey = (key$1) => key$1.name === "enter" || key$1.name === "return";
4764
4763
 
@@ -5263,7 +5262,7 @@ const fallbackSymbols$1 = {
5263
5262
  };
5264
5263
  const shouldUseMain$1 = isUnicodeSupported$1();
5265
5264
  const figures$1 = shouldUseMain$1 ? mainSymbols$1 : fallbackSymbols$1;
5266
- var esm_default$2 = figures$1;
5265
+ var esm_default = figures$1;
5267
5266
  const replacements$1 = Object.entries(specialMainSymbols$1);
5268
5267
 
5269
5268
  //#endregion
@@ -5272,7 +5271,7 @@ var import_yoctocolors_cjs$2 = /* @__PURE__ */ __toESM$1(require_yoctocolors_cjs
5272
5271
  const defaultTheme = {
5273
5272
  prefix: {
5274
5273
  idle: import_yoctocolors_cjs$2.default.blue("?"),
5275
- done: import_yoctocolors_cjs$2.default.green(esm_default$2.tick)
5274
+ done: import_yoctocolors_cjs$2.default.green(esm_default.tick)
5276
5275
  },
5277
5276
  spinner: {
5278
5277
  interval: 80,
@@ -8061,7 +8060,7 @@ var import_yoctocolors_cjs$1 = /* @__PURE__ */ __toESM$1(require_yoctocolors_cjs
8061
8060
  * Used to space/separate choices group
8062
8061
  */
8063
8062
  var Separator = class {
8064
- separator = import_yoctocolors_cjs$1.default.dim(Array.from({ length: 15 }).join(esm_default$2.line));
8063
+ separator = import_yoctocolors_cjs$1.default.dim(Array.from({ length: 15 }).join(esm_default.line));
8065
8064
  type = "separator";
8066
8065
  constructor(separator) {
8067
8066
  if (separator) this.separator = separator;
@@ -8077,9 +8076,9 @@ var import_yoctocolors_cjs = /* @__PURE__ */ __toESM$1(require_yoctocolors_cjs()
8077
8076
  var import_ansi_escapes = /* @__PURE__ */ __toESM$1(require_ansi_escapes(), 1);
8078
8077
  const checkboxTheme = {
8079
8078
  icon: {
8080
- checked: import_yoctocolors_cjs.default.green(esm_default$2.circleFilled),
8081
- unchecked: esm_default$2.circle,
8082
- cursor: esm_default$2.pointer
8079
+ checked: import_yoctocolors_cjs.default.green(esm_default.circleFilled),
8080
+ unchecked: esm_default.circle,
8081
+ cursor: esm_default.pointer
8083
8082
  },
8084
8083
  style: {
8085
8084
  disabledChoice: (text) => import_yoctocolors_cjs.default.dim(`- ${text}`),
@@ -8130,7 +8129,7 @@ function normalizeChoices(choices) {
8130
8129
  return normalizedChoice;
8131
8130
  });
8132
8131
  }
8133
- var esm_default$3 = createPrompt((config, done) => {
8132
+ var esm_default$1 = createPrompt((config, done) => {
8134
8133
  const { instructions, pageSize = 7, loop = true, required, validate: validate$1 = () => true } = config;
8135
8134
  const shortcuts = {
8136
8135
  all: "a",
@@ -8244,110 +8243,6 @@ var esm_default$3 = createPrompt((config, done) => {
8244
8243
  return `${prefix} ${message}${helpTipTop}\n${page}${helpTipBottom}${choiceDescription}${error}${import_ansi_escapes.default.cursorHide}`;
8245
8244
  });
8246
8245
 
8247
- //#endregion
8248
- //#region ../../node_modules/.pnpm/@inquirer+confirm@5.1.14_@types+node@24.1.0/node_modules/@inquirer/confirm/dist/esm/index.js
8249
- function getBooleanValue(value, defaultValue) {
8250
- let answer = defaultValue !== false;
8251
- if (/^(y|yes)/i.test(value)) answer = true;
8252
- else if (/^(n|no)/i.test(value)) answer = false;
8253
- return answer;
8254
- }
8255
- function boolToString(value) {
8256
- return value ? "Yes" : "No";
8257
- }
8258
- var esm_default$1 = createPrompt((config, done) => {
8259
- const { transformer = boolToString } = config;
8260
- const [status, setStatus] = useState("idle");
8261
- const [value, setValue] = useState("");
8262
- const theme = makeTheme(config.theme);
8263
- const prefix = usePrefix({
8264
- status,
8265
- theme
8266
- });
8267
- useKeypress((key$1, rl) => {
8268
- if (isEnterKey(key$1)) {
8269
- const answer = getBooleanValue(value, config.default);
8270
- setValue(transformer(answer));
8271
- setStatus("done");
8272
- done(answer);
8273
- } else if (key$1.name === "tab") {
8274
- const answer = boolToString(!getBooleanValue(value, config.default));
8275
- rl.clearLine(0);
8276
- rl.write(answer);
8277
- setValue(answer);
8278
- } else setValue(rl.line);
8279
- });
8280
- let formattedValue = value;
8281
- let defaultValue = "";
8282
- if (status === "done") formattedValue = theme.style.answer(value);
8283
- else defaultValue = ` ${theme.style.defaultAnswer(config.default === false ? "y/N" : "Y/n")}`;
8284
- const message = theme.style.message(config.message, status);
8285
- return `${prefix} ${message}${defaultValue} ${formattedValue}`;
8286
- });
8287
-
8288
- //#endregion
8289
- //#region ../../node_modules/.pnpm/@inquirer+input@4.2.1_@types+node@24.1.0/node_modules/@inquirer/input/dist/esm/index.js
8290
- const inputTheme = { validationFailureMode: "keep" };
8291
- var esm_default = createPrompt((config, done) => {
8292
- const { required, validate: validate$1 = () => true, prefill = "tab" } = config;
8293
- const theme = makeTheme(inputTheme, config.theme);
8294
- const [status, setStatus] = useState("idle");
8295
- const [defaultValue = "", setDefaultValue] = useState(config.default);
8296
- const [errorMsg, setError] = useState();
8297
- const [value, setValue] = useState("");
8298
- const prefix = usePrefix({
8299
- status,
8300
- theme
8301
- });
8302
- useKeypress(async (key$1, rl) => {
8303
- if (status !== "idle") return;
8304
- if (isEnterKey(key$1)) {
8305
- const answer = value || defaultValue;
8306
- setStatus("loading");
8307
- const isValid = required && !answer ? "You must provide a value" : await validate$1(answer);
8308
- if (isValid === true) {
8309
- setValue(answer);
8310
- setStatus("done");
8311
- done(answer);
8312
- } else {
8313
- if (theme.validationFailureMode === "clear") setValue("");
8314
- else rl.write(value);
8315
- setError(isValid || "You must provide a valid value");
8316
- setStatus("idle");
8317
- }
8318
- } else if (isBackspaceKey(key$1) && !value) setDefaultValue(void 0);
8319
- else if (key$1.name === "tab" && !value) {
8320
- setDefaultValue(void 0);
8321
- rl.clearLine(0);
8322
- rl.write(defaultValue);
8323
- setValue(defaultValue);
8324
- } else {
8325
- setValue(rl.line);
8326
- setError(void 0);
8327
- }
8328
- });
8329
- useEffect((rl) => {
8330
- if (prefill === "editable" && defaultValue) {
8331
- rl.write(defaultValue);
8332
- setValue(defaultValue);
8333
- }
8334
- }, []);
8335
- const message = theme.style.message(config.message, status);
8336
- let formattedValue = value;
8337
- if (typeof config.transformer === "function") formattedValue = config.transformer(value, { isFinal: status === "done" });
8338
- else if (status === "done") formattedValue = theme.style.answer(value);
8339
- let defaultStr;
8340
- if (defaultValue && status !== "done" && !value) defaultStr = theme.style.defaultAnswer(defaultValue);
8341
- let error = "";
8342
- if (errorMsg) error = theme.style.error(errorMsg);
8343
- return [[
8344
- prefix,
8345
- message,
8346
- defaultStr,
8347
- formattedValue
8348
- ].filter((v) => v !== void 0).join(" "), error];
8349
- });
8350
-
8351
8246
  //#endregion
8352
8247
  //#region ../../node_modules/.pnpm/is-unicode-supported@2.1.0/node_modules/is-unicode-supported/index.js
8353
8248
  function isUnicodeSupported() {
@@ -20217,7 +20112,7 @@ async function readFile(file) {
20217
20112
  }
20218
20113
  }
20219
20114
  var read_file_default = readFile;
20220
- async function readJson$1(file) {
20115
+ async function readJson(file) {
20221
20116
  const content = await read_file_default(file);
20222
20117
  try {
20223
20118
  return parseJson(content);
@@ -20232,7 +20127,7 @@ async function importModuleDefault(file) {
20232
20127
  }
20233
20128
  async function readBunPackageJson(file) {
20234
20129
  try {
20235
- return await readJson$1(file);
20130
+ return await readJson(file);
20236
20131
  } catch (error) {
20237
20132
  try {
20238
20133
  return await importModuleDefault(file);
@@ -20244,7 +20139,7 @@ var loadConfigFromPackageJson = process.versions.bun ? async function loadConfig
20244
20139
  const { prettier } = await readBunPackageJson(file);
20245
20140
  return prettier;
20246
20141
  } : async function loadConfigFromPackageJson2(file) {
20247
- const { prettier } = await readJson$1(file);
20142
+ const { prettier } = await readJson(file);
20248
20143
  return prettier;
20249
20144
  };
20250
20145
  async function loadConfigFromPackageYaml(file) {
@@ -20286,7 +20181,7 @@ ${error.message}`;
20286
20181
  var loaders_default = {
20287
20182
  ".toml": loadToml,
20288
20183
  ".json5": loadJson5,
20289
- ".json": readJson$1,
20184
+ ".json": readJson,
20290
20185
  ".js": importModuleDefault,
20291
20186
  ".mjs": importModuleDefault,
20292
20187
  ".cjs": importModuleDefault,
@@ -25146,15 +25041,15 @@ var src_default = index_exports;
25146
25041
  const logger = {
25147
25042
  info: (message) => console.log(cyan("[INFO]"), message),
25148
25043
  success: (message) => console.log(green("[SUCCESS]"), message),
25149
- warn: (message) => console.log(yellow("[WARN]"), message),
25044
+ warn: (message) => console.log(yellow$1("[WARN]"), message),
25150
25045
  error: (message) => console.error(red("[ERROR]"), message),
25151
25046
  file: (filePath) => magenta(filePath),
25152
- mode: (mode) => z(mode).with("add", () => green("❇️")).with("modify", () => yellow("✏️")).with("delete", () => red("❌")).with("rename", () => red("🔄")).with("rename+modify", () => red("🔀")).exhaustive(),
25047
+ mode: (mode) => z(mode).with("add", () => green("❇️")).with("modify", () => yellow$1("✏️")).with("delete", () => red("❌")).with("rename", () => red("🔄")).with("rename+modify", () => red("🔀")).exhaustive(),
25153
25048
  commitMessage: (title, detail) => {
25154
25049
  return [
25155
25050
  underline$1(bold(title)),
25156
25051
  "",
25157
- detail.replace(/\*\*(.+?)\*\*/g, (_, v) => bold(v)).replace(/__(.+?)__/g, (_, v) => italic$1(v)).replace(/`(.+?)`/g, (_, v) => yellow(v)),
25052
+ detail.replace(/\*\*(.+?)\*\*/g, (_, v) => bold(v)).replace(/__(.+?)__/g, (_, v) => italic$1(v)).replace(/`(.+?)`/g, (_, v) => yellow$1(v)),
25158
25053
  blue("_".repeat(process.stdout.columns || 40)),
25159
25054
  ""
25160
25055
  ].join("\n");
@@ -25244,7 +25139,7 @@ async function confirmAction(filesToUpdate, options) {
25244
25139
  checked: file.safe || !!options.allowUnsafe
25245
25140
  });
25246
25141
  }
25247
- const selectedFiles = await esm_default$3({
25142
+ const selectedFiles = await esm_default$1({
25248
25143
  message: [options.topMessage, "The following files will be overwritten:\n"].filter(Boolean).join("\n"),
25249
25144
  choices,
25250
25145
  pageSize: process.stdout.rows > 0 ? process.stdout.rows - 4 : filesToUpdate.length
@@ -25604,6 +25499,18 @@ function union(options, params) {
25604
25499
  ...normalizeParams(params)
25605
25500
  });
25606
25501
  }
25502
+ const ZodMiniDiscriminatedUnion = /* @__PURE__ */ $constructor("ZodMiniDiscriminatedUnion", (inst, def) => {
25503
+ $ZodDiscriminatedUnion.init(inst, def);
25504
+ ZodMiniType.init(inst, def);
25505
+ });
25506
+ function discriminatedUnion(discriminator, options, params) {
25507
+ return new ZodMiniDiscriminatedUnion({
25508
+ type: "union",
25509
+ options,
25510
+ discriminator,
25511
+ ...normalizeParams(params)
25512
+ });
25513
+ }
25607
25514
  const ZodMiniLiteral = /* @__PURE__ */ $constructor("ZodMiniLiteral", (inst, def) => {
25608
25515
  $ZodLiteral.init(inst, def);
25609
25516
  ZodMiniType.init(inst, def);
@@ -25640,7 +25547,11 @@ function _instanceof(cls, params = { error: `Input not instance of ${cls.name}`
25640
25547
 
25641
25548
  //#endregion
25642
25549
  //#region ../dev/dist/google-aistudio/browser/config/types.js
25643
- const zBaseAgentMetadata = object({ workDir: string() });
25550
+ const zBaseAgentMetadata = object({
25551
+ workDir: string(),
25552
+ tools: optional(object({ exclude: optional(array(string())) }))
25553
+ });
25554
+ const zCommonAgentMetadata = extend(zBaseAgentMetadata, { agent: literal("common") });
25644
25555
  const zCoderAgentMetadata = extend(zBaseAgentMetadata, {
25645
25556
  agent: literal("coder"),
25646
25557
  codeName: string(),
@@ -25649,10 +25560,9 @@ const zCoderAgentMetadata = extend(zBaseAgentMetadata, {
25649
25560
  mcp: array(object({
25650
25561
  command: string(),
25651
25562
  prefix: optional(string())
25652
- })),
25653
- tools: optional(object({ exclude: optional(array(string())) }))
25563
+ }))
25654
25564
  });
25655
- const zAgentMetadata = union([zCoderAgentMetadata]);
25565
+ const zAgentMetadata = discriminatedUnion("agent", [zCommonAgentMetadata, zCoderAgentMetadata]);
25656
25566
  const zPageToolConfig = object({
25657
25567
  name: string(),
25658
25568
  description: string(),
@@ -25661,7 +25571,7 @@ const zPageToolConfig = object({
25661
25571
  disabled: optional(boolean())
25662
25572
  });
25663
25573
  const zPageConfig = object({
25664
- metadata: optional(zAgentMetadata),
25574
+ metadata: zAgentMetadata,
25665
25575
  model: string(),
25666
25576
  systemPrompt: string(),
25667
25577
  tools: array(zPageToolConfig),
@@ -29043,7 +28953,7 @@ const strikethrough = format$3(9, 29);
29043
28953
  const black = format$3(30, 39);
29044
28954
  const red$1 = format$3(31, 39);
29045
28955
  const green$1 = format$3(32, 39);
29046
- const yellow$1 = format$3(33, 39);
28956
+ const yellow = format$3(33, 39);
29047
28957
  const blue$1 = format$3(34, 39);
29048
28958
  const magenta$1 = format$3(35, 39);
29049
28959
  const cyan$1 = format$3(36, 39);
@@ -35180,9 +35090,14 @@ async function loadAgentTools({ agent, workDir, tools }) {
35180
35090
  * @returns A promise that resolves to the generated PageConfig object.
35181
35091
  */
35182
35092
  const genPageConfig = async (metadata) => {
35183
- const systemPromptTemplate = ["[JIXO:CODER2](@INJECT)"];
35093
+ let genContentCodeName = "";
35094
+ let agentModel = "";
35095
+ const systemPromptTemplate = [];
35184
35096
  const { toolDeclarations } = await loadAgentTools(metadata);
35185
- if (metadata) {
35097
+ if (metadata.agent === "coder") {
35098
+ genContentCodeName = (metadata.codeName || metadata.workDir.split(/[\/\\]+/).findLast((v) => !v.startsWith("."))) ?? "NoNameJob";
35099
+ agentModel = "gemini-2.5-pro";
35100
+ systemPromptTemplate.push("[JIXO:CODER2](@INJECT)");
35186
35101
  if (metadata.dirs?.length) {
35187
35102
  systemPromptTemplate.push("\n# Relevant Directories:\n");
35188
35103
  metadata.dirs.forEach((dir) => systemPromptTemplate.push(`[${dir}](@FILE_TREE)`));
@@ -35193,9 +35108,10 @@ const genPageConfig = async (metadata) => {
35193
35108
  }
35194
35109
  }
35195
35110
  const workDirResolver = createResolver(metadata.workDir);
35111
+ const finalSystemPrompt = systemPromptTemplate.length > 0 ? await _gen_content(genContentCodeName, systemPromptTemplate.join("\n"), workDirResolver) : "";
35196
35112
  const finalConfig = {
35197
- model: "gemini-1.5-pro",
35198
- systemPrompt: await _gen_content((metadata.codeName || metadata.workDir.split(/[\/\\]+/).findLast((v) => !v.startsWith("."))) ?? "NoNameJob", systemPromptTemplate.join("\n"), workDirResolver),
35113
+ model: agentModel,
35114
+ systemPrompt: finalSystemPrompt,
35199
35115
  tools: toolDeclarations,
35200
35116
  metadata
35201
35117
  };
@@ -35373,53 +35289,79 @@ function createFunctionCallContext(sessionId) {
35373
35289
 
35374
35290
  //#endregion
35375
35291
  //#region ../dev/dist/tools/tasks.js
35376
- const parseContent = async (fcs, dir, sessionId, contentFilepath, filenames) => {
35292
+ const parseContent = async (fcs, dir, sessionId, contentFilepath) => {
35377
35293
  console.log(magenta("开始处理文件"), path.relative(process.cwd(), contentFilepath));
35378
35294
  const contents = await zContentsSchema.parse(JSON.parse(reactiveFs.readFile(contentFilepath)));
35379
- const latestUserContent = contents.findLast((c$2) => {
35380
- return c$2.role === "user" && c$2.parts.some((p) => "functionResponse" in p);
35381
- });
35382
- if (!latestUserContent) return;
35383
- const functionResponsePart = latestUserContent.parts.find((p) => "functionResponse" in p);
35384
- if (!functionResponsePart || functionResponsePart.functionResponse.response !== "") return;
35385
- const modelContent = contents.slice(0, contents.lastIndexOf(latestUserContent)).findLast((content) => {
35386
- return content.role === "model" && content.parts.some((p) => "functionCall" in p);
35387
- });
35388
- if (!modelContent) return;
35389
- const functionCallPart = modelContent.parts.find((p) => "functionCall" in p)?.["functionCall"];
35390
- if (!functionCallPart) return;
35391
- const modelIndex = contents.indexOf(modelContent);
35392
- const hash = createHash("sha256").update(`INDEX:${modelIndex}`).update(JSON.stringify(modelContent)).digest("hex").slice(0, 8);
35393
- const taskFilename = `${sessionId}.${functionCallPart.name}.${modelIndex}-${hash}.function_call.json`;
35394
- if (filenames.includes(taskFilename)) return;
35395
- console.log(blue("收到 functionCallPart 任务请求"), functionCallPart);
35396
- const fc = fcs.get(functionCallPart.name);
35397
- if (!fc) {
35398
- console.warn("找不到任务处理工具");
35399
- return false;
35400
- } else {
35401
- const { functionCall: functionCall$11 } = fc.module;
35402
- const input = JSON.parse(functionCallPart.parameters);
35403
- try {
35404
- console.log(cyan("开始执行任务"));
35405
- const context = createFunctionCallContext(sessionId);
35406
- const output = await functionCall$11(input, context);
35407
- console.log(green("生成任务结果:"), taskFilename);
35408
- fs.writeFileSync(path.join(dir, taskFilename), JSON.stringify({
35409
- ...functionCallPart,
35410
- input,
35411
- output
35412
- }, null, 2));
35413
- return true;
35414
- } catch (e) {
35415
- console.log(red("任务执行失败:"), e);
35416
- fs.writeFileSync(path.join(dir, taskFilename), JSON.stringify({
35417
- ...functionCallPart,
35418
- input,
35419
- output: { error: e instanceof Error ? e.message : String(e) }
35420
- }, null, 2));
35295
+ const taskFilenames = reactiveFs.readDirByGlob(dir, "*.function_call.json").filter((fn) => fn.startsWith(`${sessionId}.`));
35296
+ const rmFiles = /* @__PURE__ */ new Map();
35297
+ const rmFile = (filename) => {
35298
+ map_get_or_put_async(rmFiles, filename, (filename$1) => {
35299
+ return fs.promises.rm(path.join(dir, filename$1)).then(() => true, () => false);
35300
+ });
35301
+ };
35302
+ try {
35303
+ for (const existTaskFilename of taskFilenames) {
35304
+ const [_sessionId, _toolName, modelIndex$1, contentHash] = existTaskFilename.split(".");
35305
+ const modelContent$1 = contents[+modelIndex$1];
35306
+ const isMatch = () => {
35307
+ if (modelContent$1.role !== "model") return false;
35308
+ if (createHash("sha256").update(`INDEX:${modelIndex$1}`).update(JSON.stringify(modelContent$1)).digest("hex").slice(0, 8) !== contentHash) return false;
35309
+ return true;
35310
+ };
35311
+ if (!isMatch()) rmFile(existTaskFilename);
35312
+ }
35313
+ const latestUserContent = contents.findLast((c$2) => {
35314
+ return c$2.role === "user" && c$2.parts.some((p) => "functionResponse" in p);
35315
+ });
35316
+ if (!latestUserContent) return;
35317
+ const modelContent = contents.slice(0, contents.lastIndexOf(latestUserContent)).findLast((content) => {
35318
+ return content.role === "model" && content.parts.some((p) => "functionCall" in p);
35319
+ });
35320
+ if (!modelContent) return;
35321
+ const functionCallPart = modelContent.parts.find((p) => "functionCall" in p)?.["functionCall"];
35322
+ if (!functionCallPart) return;
35323
+ const modelIndex = contents.indexOf(modelContent);
35324
+ if (modelIndex === -1) return;
35325
+ for (const existTaskFilename of taskFilenames) {
35326
+ const [_sessionId, _toolName, existModelIndex] = existTaskFilename.split(".");
35327
+ if (+existModelIndex < modelIndex) rmFile(existTaskFilename);
35328
+ }
35329
+ const functionResponsePart = latestUserContent.parts.find((p) => "functionResponse" in p);
35330
+ if (!functionResponsePart || functionResponsePart.functionResponse.response !== "") return;
35331
+ const hash = createHash("sha256").update(`INDEX:${modelIndex}`).update(JSON.stringify(modelContent)).digest("hex").slice(0, 8);
35332
+ const taskFilename = `${sessionId}.${functionCallPart.name}.${modelIndex}.${hash}.function_call.json`;
35333
+ if (taskFilenames.includes(taskFilename)) return;
35334
+ console.log(blue("收到 functionCallPart 任务请求"), functionCallPart);
35335
+ const fc = fcs.get(functionCallPart.name);
35336
+ if (!fc) {
35337
+ console.warn("找不到任务处理工具");
35421
35338
  return false;
35339
+ } else {
35340
+ const { functionCall: functionCall$11 } = fc.module;
35341
+ const input = JSON.parse(functionCallPart.parameters);
35342
+ try {
35343
+ console.log(cyan("开始执行任务"));
35344
+ const context = createFunctionCallContext(sessionId);
35345
+ const output = await functionCall$11(input, context);
35346
+ console.log(green("生成任务结果:"), taskFilename);
35347
+ fs.writeFileSync(path.join(dir, taskFilename), JSON.stringify({
35348
+ ...functionCallPart,
35349
+ input,
35350
+ output
35351
+ }, null, 2));
35352
+ return true;
35353
+ } catch (e) {
35354
+ console.log(red("任务执行失败:"), e);
35355
+ fs.writeFileSync(path.join(dir, taskFilename), JSON.stringify({
35356
+ ...functionCallPart,
35357
+ input,
35358
+ output: { error: e instanceof Error ? e.message : String(e) }
35359
+ }, null, 2));
35360
+ return false;
35361
+ }
35422
35362
  }
35363
+ } finally {
35364
+ await Promise.all([...rmFiles.values()]);
35423
35365
  }
35424
35366
  };
35425
35367
  const _cache = /* @__PURE__ */ new Map();
@@ -35449,7 +35391,7 @@ const googleAiStudioAutomation = async ({ dir = process.cwd() }) => {
35449
35391
  const { tools: tools$1 } = await loadAgentTools(metadata);
35450
35392
  return tools$1;
35451
35393
  });
35452
- await parseContent(tools, dir, basename$1, contentFilepath, contentNames).catch(console.error);
35394
+ await parseContent(tools, dir, basename$1, contentFilepath).catch(console.error);
35453
35395
  } catch (e) {
35454
35396
  console.error(red(e instanceof Error ? e.stack ?? e.message : String(e)));
35455
35397
  }
@@ -35473,34 +35415,6 @@ const doGoogleAiStudioAutomation = async ({ watch,...opts }) => {
35473
35415
  });
35474
35416
  };
35475
35417
 
35476
- //#endregion
35477
- //#region ../dev/dist/google-aistudio/jixo/init.js
35478
- const GET_JIXO_TOOLS = func_remember(() => readJson(assetsResolver("tools.json")));
35479
- const copyAssets = async (targetDir, options) => {
35480
- const tools = await GET_JIXO_TOOLS();
35481
- await mkdir(targetDir, { recursive: true });
35482
- for (const filename of obj_props(tools)) {
35483
- const destPath = path.join(targetDir, filename);
35484
- if (existsSync(destPath)) {
35485
- if (options.force === false) {
35486
- console.warn(yellow(`File already exists, skipping: ${filename}`));
35487
- continue;
35488
- }
35489
- if (options.force == null) {
35490
- if (!await esm_default$1({
35491
- message: `File '${blue(filename)}' already exists. Overwrite?`,
35492
- default: false
35493
- })) continue;
35494
- }
35495
- }
35496
- await writeFile$1(destPath, tools[filename]);
35497
- }
35498
- };
35499
- const doInit = (opts) => {
35500
- assetsResolver("bundle", "google-aistudio.browser.js");
35501
- return copyAssets(opts.dir, { force: opts.force });
35502
- };
35503
-
35504
35418
  //#endregion
35505
35419
  //#region ../../node_modules/.pnpm/ws@8.18.3_bufferutil@4.0.9/node_modules/ws/lib/constants.js
35506
35420
  var require_constants = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/ws@8.18.3_bufferutil@4.0.9/node_modules/ws/lib/constants.js": ((exports, module) => {
@@ -39406,7 +39320,7 @@ function startWsServer(port = 8765) {
39406
39320
  }
39407
39321
  });
39408
39322
  server.on("request", (req, res) => {
39409
- if (req.url?.startsWith("/init-session")) return initSession(req, res);
39323
+ if (req.url?.startsWith("/init-session")) return initSessionByHttp(req, res);
39410
39324
  });
39411
39325
  server.on("upgrade", (request, socket, head) => {
39412
39326
  wss.handleUpgrade(request, socket, head, (ws) => {
@@ -39421,7 +39335,7 @@ function startWsServer(port = 8765) {
39421
39335
  else console.error("HTTP Server error:", err);
39422
39336
  });
39423
39337
  }
39424
- const initSession = (req, res) => {
39338
+ const initSessionByHttp = (req, res) => {
39425
39339
  const url$1 = new URL$1(`http://${process.env.HOST ?? "localhost"}${req.url}`);
39426
39340
  const workDir = url$1.searchParams.get("workDir");
39427
39341
  if (!workDir) return res.writeHead(400).end("workDir is required");
@@ -39433,6 +39347,10 @@ const initSession = (req, res) => {
39433
39347
  session.api.setWorkDir(workDir);
39434
39348
  return res.writeHead(200).end();
39435
39349
  };
39350
+ const initSession = async (nid, workDir) => {
39351
+ const res = await fetch(`http://localhost:8765/init-session?nid=${nid}&workDir=${encodeURIComponent(workDir)}`);
39352
+ if (!res.ok) throw new Error(await res.text());
39353
+ };
39436
39354
  const getSessionByNid = (nid) => {
39437
39355
  if (nid == null) return;
39438
39356
  if (typeof nid === "string") nid = parseInt(nid);
@@ -39575,27 +39493,23 @@ const browserCommand = {
39575
39493
  }
39576
39494
  };
39577
39495
  const initCommand = {
39578
- command: "init [dir]",
39496
+ command: "init <nid>",
39579
39497
  aliases: ["i", "I"],
39580
- describe: "init an browser-kit directory for aistudio.google.com",
39581
- builder: (yargs) => yargs.positional("dir", {
39582
- describe: "Directory for aistudio input/output contents",
39583
- type: "string"
39584
- }).option("force", {
39585
- alias: "F",
39586
- type: "boolean",
39587
- describe: "override exits files"
39498
+ describe: "init an chrome ext workspace aistudio.google.com",
39499
+ builder: (yargs) => yargs.positional("nid", {
39500
+ type: "number",
39501
+ demandOption: true
39502
+ }).option("dir", {
39503
+ alias: ["D", "d"],
39504
+ type: "string",
39505
+ describe: "Specify the workspace directory for chrome-ext"
39588
39506
  }),
39589
39507
  handler: async (argv) => {
39590
- let { dir } = argv;
39591
- if (dir == null) dir = await esm_default({
39592
- message: "No directory specified. Do you want to use the default '.ai' directory?",
39593
- default: ".ai"
39594
- });
39595
- doInit({
39596
- ...argv,
39597
- dir
39598
- });
39508
+ try {
39509
+ initSession(argv.nid, argv.dir ? path.resolve(process.cwd(), argv.dir) : process.cwd());
39510
+ } catch (e) {
39511
+ console.error(red(e instanceof Error ? e.message : String(e)));
39512
+ }
39599
39513
  }
39600
39514
  };
39601
39515
  /**