@kienmatu/inkos-studio 0.1.3 → 1.0.1

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.
Files changed (65) hide show
  1. package/dist/api/server.d.ts.map +1 -1
  2. package/dist/api/server.js +91 -9
  3. package/dist/api/server.js.map +1 -1
  4. package/dist/assets/{FilmWizard-BAeDX_rI.js → FilmWizard-CxoOJ7MQ.js} +1 -1
  5. package/dist/assets/{FlowView-C6n6r8pJ.js → FlowView-Bt0EtmEr.js} +1 -1
  6. package/dist/assets/{_baseUniq-CHNUfn5h.js → _baseUniq-ZL9pmMqM.js} +1 -1
  7. package/dist/assets/{arc-CdPV8k-0.js → arc-B8qI0bEW.js} +1 -1
  8. package/dist/assets/{architectureDiagram-Q4EWVU46-oodkcVSQ.js → architectureDiagram-Q4EWVU46-BMqx63uW.js} +1 -1
  9. package/dist/assets/{blockDiagram-DXYQGD6D-CIbxhPHs.js → blockDiagram-DXYQGD6D-CpTeW9T5.js} +1 -1
  10. package/dist/assets/{c4Diagram-AHTNJAMY-CxIpgCiP.js → c4Diagram-AHTNJAMY-DEMZhRny.js} +1 -1
  11. package/dist/assets/channel-DxRmlnS_.js +1 -0
  12. package/dist/assets/{chunk-4BX2VUAB-Cf70tfVa.js → chunk-4BX2VUAB-CATTVIYo.js} +1 -1
  13. package/dist/assets/{chunk-4TB4RGXK-uFQAF256.js → chunk-4TB4RGXK-BVSOdPwi.js} +1 -1
  14. package/dist/assets/{chunk-55IACEB6-4u7WcTds.js → chunk-55IACEB6-roBKSgqh.js} +1 -1
  15. package/dist/assets/{chunk-EDXVE4YY-DKvxdCCA.js → chunk-EDXVE4YY-DcL-JJvQ.js} +1 -1
  16. package/dist/assets/{chunk-FMBD7UC4-DA6v8xvJ.js → chunk-FMBD7UC4-CTt3nqty.js} +1 -1
  17. package/dist/assets/{chunk-OYMX7WX6-DwLlaWl9.js → chunk-OYMX7WX6-BKloZua_.js} +1 -1
  18. package/dist/assets/{chunk-QZHKN3VN-CFgB8UWK.js → chunk-QZHKN3VN-CksGJW6L.js} +1 -1
  19. package/dist/assets/{chunk-YZCP3GAM-JgBXvZgf.js → chunk-YZCP3GAM-DFUs85Mo.js} +1 -1
  20. package/dist/assets/classDiagram-6PBFFD2Q-Bkac267_.js +1 -0
  21. package/dist/assets/classDiagram-v2-HSJHXN6E-Bkac267_.js +1 -0
  22. package/dist/assets/clone-CmiP6enp.js +1 -0
  23. package/dist/assets/{cose-bilkent-S5V4N54A-DKMKqdAL.js → cose-bilkent-S5V4N54A-BhjR9QKW.js} +1 -1
  24. package/dist/assets/{dagre-KV5264BT-DuZ4zm4B.js → dagre-KV5264BT-S0WgqeWF.js} +1 -1
  25. package/dist/assets/{diagram-5BDNPKRD-CoA3HYsp.js → diagram-5BDNPKRD-iziIar_1.js} +1 -1
  26. package/dist/assets/{diagram-G4DWMVQ6-DVnnKNaz.js → diagram-G4DWMVQ6-DGiQ4b3V.js} +1 -1
  27. package/dist/assets/{diagram-MMDJMWI5-iB_Pzv_O.js → diagram-MMDJMWI5-Ctfv9R4Z.js} +1 -1
  28. package/dist/assets/{diagram-TYMM5635-CJ1VtRnc.js → diagram-TYMM5635-DpzPFDFI.js} +1 -1
  29. package/dist/assets/{erDiagram-SMLLAGMA-SWAf-S26.js → erDiagram-SMLLAGMA-e51DloYW.js} +1 -1
  30. package/dist/assets/{flowDiagram-DWJPFMVM-bjSm1F6q.js → flowDiagram-DWJPFMVM-TyuMrie7.js} +1 -1
  31. package/dist/assets/{ganttDiagram-T4ZO3ILL-B3eioyUQ.js → ganttDiagram-T4ZO3ILL-sewHvhyH.js} +1 -1
  32. package/dist/assets/{gitGraphDiagram-UUTBAWPF-DGaIKwEh.js → gitGraphDiagram-UUTBAWPF-DI7YNaAi.js} +1 -1
  33. package/dist/assets/{graph-zC0IkLW4.js → graph-iCANBjLp.js} +1 -1
  34. package/dist/assets/{highlighted-body-OFNGDK62-CkE4PgdB.js → highlighted-body-OFNGDK62-DTkXdU8M.js} +1 -1
  35. package/dist/assets/{index-9mF0_S-1.js → index-3FC9cBAw.js} +268 -263
  36. package/dist/assets/index-8wiyHNEA.css +1 -0
  37. package/dist/assets/{infoDiagram-42DDH7IO-z7BfWhD6.js → infoDiagram-42DDH7IO-KcOGgxDZ.js} +1 -1
  38. package/dist/assets/{ishikawaDiagram-UXIWVN3A-DgkoM8pX.js → ishikawaDiagram-UXIWVN3A-DN46kos1.js} +1 -1
  39. package/dist/assets/{journeyDiagram-VCZTEJTY-7szsjnaK.js → journeyDiagram-VCZTEJTY-CSnW-uiU.js} +1 -1
  40. package/dist/assets/{kanban-definition-6JOO6SKY-CN_iYP62.js → kanban-definition-6JOO6SKY-DgeKhYzm.js} +1 -1
  41. package/dist/assets/{layout-B1_IEbhE.js → layout-C3k8b-wj.js} +1 -1
  42. package/dist/assets/{linear-DgZKeCD_.js → linear-CSj-zsdP.js} +1 -1
  43. package/dist/assets/{min-BGmTIgk7.js → min-BkU8UOgQ.js} +1 -1
  44. package/dist/assets/{mindmap-definition-QFDTVHPH-CaZaCUVQ.js → mindmap-definition-QFDTVHPH-jaWIxQM2.js} +1 -1
  45. package/dist/assets/{pieDiagram-DEJITSTG-Bai_9_pu.js → pieDiagram-DEJITSTG-DSCNVEy0.js} +1 -1
  46. package/dist/assets/{quadrantDiagram-34T5L4WZ-CgKE3-Ag.js → quadrantDiagram-34T5L4WZ-6Aki-Mea.js} +1 -1
  47. package/dist/assets/{requirementDiagram-MS252O5E-CiP3d8R4.js → requirementDiagram-MS252O5E-CIA-stPo.js} +1 -1
  48. package/dist/assets/{sankeyDiagram-XADWPNL6-RIeASvdJ.js → sankeyDiagram-XADWPNL6-Dm92baLv.js} +1 -1
  49. package/dist/assets/{sequenceDiagram-FGHM5R23-Buf7D5PQ.js → sequenceDiagram-FGHM5R23-CijKhpBV.js} +1 -1
  50. package/dist/assets/{stateDiagram-FHFEXIEX-5uYn-_xo.js → stateDiagram-FHFEXIEX-BoRVlJdY.js} +1 -1
  51. package/dist/assets/stateDiagram-v2-QKLJ7IA2-B2UHePPb.js +1 -0
  52. package/dist/assets/{timeline-definition-GMOUNBTQ-fcTegT1X.js → timeline-definition-GMOUNBTQ-Dgq0GzH4.js} +1 -1
  53. package/dist/assets/{value-CCp47p1v.js → value-BU9Hdjc2.js} +1 -1
  54. package/dist/assets/{vennDiagram-DHZGUBPP-BUY_I73j.js → vennDiagram-DHZGUBPP-DrIu0Q4b.js} +1 -1
  55. package/dist/assets/{wardley-RL74JXVD-CfGeUcvr.js → wardley-RL74JXVD-BumycEok.js} +1 -1
  56. package/dist/assets/{wardleyDiagram-NUSXRM2D-0A6kvF9i.js → wardleyDiagram-NUSXRM2D-3fn4THet.js} +1 -1
  57. package/dist/assets/{xychartDiagram-5P7HB3ND-C2L50m3n.js → xychartDiagram-5P7HB3ND-BMcrjrBB.js} +1 -1
  58. package/dist/index.html +2 -2
  59. package/package.json +2 -2
  60. package/dist/assets/channel-BudrdgJ_.js +0 -1
  61. package/dist/assets/classDiagram-6PBFFD2Q-CNYOE6Pk.js +0 -1
  62. package/dist/assets/classDiagram-v2-HSJHXN6E-CNYOE6Pk.js +0 -1
  63. package/dist/assets/clone-CbLIuAlV.js +0 -1
  64. package/dist/assets/index-B9yC-RFq.css +0 -1
  65. package/dist/assets/stateDiagram-v2-QKLJ7IA2-CiNPYrtS.js +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAM5B,OAAO,EAsHL,KAAK,aAAa,EAIlB,KAAK,aAAa,EAMnB,MAAM,sBAAsB,CAAC;AAkB9B,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEhD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAItE;AAGD,wBAAgB,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAGtF;AAu3ED,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE;IAAE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,aAAa,CAAA;CAAO,8EAq/H7I;AAID,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,IAAI,SAAO,EACX,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACxC,OAAO,CAAC,IAAI,CAAC,CA8Cf"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAM5B,OAAO,EAsHL,KAAK,aAAa,EAIlB,KAAK,aAAa,EAMnB,MAAM,sBAAsB,CAAC;AAkB9B,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEhD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAItE;AAGD,wBAAgB,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAGtF;AAk8ED,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE;IAAE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,aAAa,CAAA;CAAO,8EA6gI7I;AAID,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,IAAI,SAAO,EACX,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACxC,OAAO,CAAC,IAAI,CAAC,CA8Cf"}
@@ -879,6 +879,7 @@ function toolResultText(result, lang = "vi") {
879
879
  }
880
880
  async function executeConfirmedProductionAction(args) {
881
881
  const lang = args.language ?? "vi";
882
+ const uiLang = args.uiLanguage ?? lang;
882
883
  const id = args.taskId;
883
884
  const actionPayload = args.actionPayload;
884
885
  const configuredSkills = await loadAvailableAgentSkills({ projectRoot: args.root });
@@ -950,7 +951,7 @@ async function executeConfirmedProductionAction(args) {
950
951
  else if (args.requestedIntent === "generate_cover") {
951
952
  const payload = actionPayload?.generateCover;
952
953
  const title = requirePayloadText(payload?.title, pick(lang, "确认生成封面缺少标题,请重新生成确认卡。", "The cover generation confirmation is missing a title. Regenerate the confirmation card.", "Xác nhận tạo bìa sách thiếu tiêu đề. Vui lòng tạo lại thẻ xác nhận."));
953
- tool = createGenerateCoverTool(args.root, { actionPayload });
954
+ tool = createGenerateCoverTool(args.root, { actionPayload, language: toWritingLanguage(lang) });
954
955
  params = {
955
956
  title,
956
957
  ...(payload?.intro ? { intro: payload.intro } : {}),
@@ -1204,10 +1205,10 @@ async function executeConfirmedProductionAction(args) {
1204
1205
  id,
1205
1206
  tool: tool.name,
1206
1207
  agent,
1207
- label: resolveToolLabel(tool.name, agent, lang),
1208
+ label: resolveToolLabel(tool.name, agent, uiLang),
1208
1209
  status: "running",
1209
1210
  args: params,
1210
- stages: agent ? pipelineStages(agent, lang)?.map(label => ({ label, status: "pending" })) : undefined,
1211
+ stages: agent ? pipelineStages(agent, uiLang)?.map(label => ({ label, status: "pending" })) : undefined,
1211
1212
  startedAt: Date.now(),
1212
1213
  };
1213
1214
  await args.onTaskChange(exec);
@@ -1266,6 +1267,62 @@ async function executeConfirmedProductionAction(args) {
1266
1267
  throw new ConfirmedActionExecutionError(message, exec, error);
1267
1268
  }
1268
1269
  }
1270
+ function parseCompleteShortRunIndex(value, expectedStoryId) {
1271
+ if (!value || typeof value !== "object" || Array.isArray(value))
1272
+ return null;
1273
+ const record = value;
1274
+ if (record.version !== 1
1275
+ || record.kind !== "short-fiction"
1276
+ || record.id !== expectedStoryId
1277
+ || record.status !== "complete"
1278
+ || typeof record.updatedAt !== "string") {
1279
+ return null;
1280
+ }
1281
+ return { storyId: expectedStoryId, updatedAt: record.updatedAt };
1282
+ }
1283
+ function parseShortStoryTitle(value) {
1284
+ if (!value || typeof value !== "object" || Array.isArray(value))
1285
+ return null;
1286
+ const storyTitle = value.storyTitle;
1287
+ return typeof storyTitle === "string" && storyTitle.trim() ? storyTitle.trim() : null;
1288
+ }
1289
+ async function loadStudioShortList(root) {
1290
+ const shortsDir = join(root, "shorts");
1291
+ let storyIds = [];
1292
+ try {
1293
+ const entries = await readdir(shortsDir, { withFileTypes: true });
1294
+ storyIds = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
1295
+ }
1296
+ catch (error) {
1297
+ if (error.code !== "ENOENT")
1298
+ throw error;
1299
+ }
1300
+ const shorts = [];
1301
+ for (const storyId of storyIds) {
1302
+ if (!isSafeBookId(storyId))
1303
+ continue;
1304
+ const shortDir = join(shortsDir, storyId);
1305
+ try {
1306
+ const status = JSON.parse(await readFile(join(shortDir, "status.json"), "utf-8"));
1307
+ const run = parseCompleteShortRunIndex(status, storyId);
1308
+ if (!run)
1309
+ continue;
1310
+ const story = JSON.parse(await readFile(join(shortDir, "final", "short-story.json"), "utf-8"));
1311
+ const title = parseShortStoryTitle(story) ?? storyId;
1312
+ await access(join(shortDir, "final", "full.md"));
1313
+ shorts.push({
1314
+ storyId,
1315
+ title,
1316
+ finalMarkdownPath: toPosixPath(join("shorts", storyId, "final", "full.md")),
1317
+ updatedAt: run.updatedAt,
1318
+ });
1319
+ }
1320
+ catch {
1321
+ // A malformed or incomplete directory is not a completed short work.
1322
+ }
1323
+ }
1324
+ return shorts;
1325
+ }
1269
1326
  const subscribers = new Set();
1270
1327
  const bookCreateStatus = new Map();
1271
1328
  // 内存缓存:service -> 模型列表 + 更新时间戳;避免每次 sidebar 挂载时都打真实 LLM /models
@@ -2174,6 +2231,9 @@ export function createStudioServer(initialConfig, root, overrides = {}) {
2174
2231
  }
2175
2232
  : sseSink;
2176
2233
  const logger = createLogger({ tag: "studio", sinks: [scopedSseSink, consoleSink] });
2234
+ // Progress lines are read by the person watching Studio, so they follow the
2235
+ // UI language rather than the book's writing language.
2236
+ const logLanguage = await currentProjectLanguage();
2177
2237
  return {
2178
2238
  client: overrides?.client ?? createLLMClient(currentConfig.llm),
2179
2239
  model: overrides?.model ?? currentConfig.llm.model,
@@ -2186,6 +2246,7 @@ export function createStudioServer(initialConfig, root, overrides = {}) {
2186
2246
  modelOverrides: currentConfig.modelOverrides,
2187
2247
  notifyChannels: currentConfig.notify,
2188
2248
  logger,
2249
+ logLanguage,
2189
2250
  onContextCompression: (event) => {
2190
2251
  broadcast("context:compression", {
2191
2252
  ...(overrides?.sessionIdForSSE ? { sessionId: overrides.sessionIdForSSE } : {}),
@@ -3189,13 +3250,29 @@ export function createStudioServer(initialConfig, root, overrides = {}) {
3189
3250
  id: `custom:${s.name ?? "Custom"}`,
3190
3251
  baseUrl: s.baseUrl ?? "",
3191
3252
  label: s.name ?? "Custom",
3253
+ configuredModels: s.models ?? [],
3192
3254
  }))
3193
- .filter((s) => s.baseUrl && Boolean(secrets.services[s.id]?.apiKey));
3194
- const groups = await Promise.all(customs.map(async (s) => ({
3195
- service: s.id,
3196
- label: s.label,
3197
- models: filterTextChatModels(await probeModelsFromUpstream(s.baseUrl, secrets.services[s.id].apiKey, 10_000)),
3198
- })));
3255
+ .filter((s) => {
3256
+ if (!s.baseUrl)
3257
+ return false;
3258
+ if (secrets.services[s.id]?.apiKey)
3259
+ return true;
3260
+ // Local/self-hosted endpoints are usable without a key.
3261
+ return isApiKeyOptionalForEndpoint({
3262
+ provider: resolveServiceProviderFamily("custom") ?? "openai",
3263
+ baseUrl: s.baseUrl,
3264
+ });
3265
+ });
3266
+ const groups = await Promise.all(customs.map(async (s) => {
3267
+ const probed = filterTextChatModels(await probeModelsFromUpstream(s.baseUrl, secrets.services[s.id]?.apiKey ?? "", 10_000));
3268
+ // The probe swallows every failure (timeout, offline upstream, bad
3269
+ // gateway) and returns []. Without the configured ids as a fallback a
3270
+ // single slow reload empties the model picker, so the UI drops back to
3271
+ // "set up models" even though the service is configured.
3272
+ const models = mergeServiceModelIds(probed.map((model) => model.id), s.configuredModels)
3273
+ .map((id) => probed.find((model) => model.id.toLowerCase() === id.toLowerCase()) ?? { id, name: id });
3274
+ return { service: s.id, label: s.label, models };
3275
+ }));
3199
3276
  return c.json({ groups });
3200
3277
  });
3201
3278
  app.get("/api/v1/services/:service/models", async (c) => {
@@ -4025,6 +4102,7 @@ export function createStudioServer(initialConfig, root, overrides = {}) {
4025
4102
  requestedSkills,
4026
4103
  disabledSkills,
4027
4104
  language: surfaceLanguage,
4105
+ uiLanguage: language,
4028
4106
  taskId,
4029
4107
  sourceRequestId,
4030
4108
  signal: taskController.signal,
@@ -5313,6 +5391,10 @@ export function createStudioServer(initialConfig, root, overrides = {}) {
5313
5391
  films.sort((a, b) => a.title.localeCompare(b.title, "zh"));
5314
5392
  return c.json({ films });
5315
5393
  });
5394
+ app.get("/api/v1/shorts", async (c) => {
5395
+ const shorts = await loadStudioShortList(root);
5396
+ return c.json({ shorts });
5397
+ });
5316
5398
  app.get("/api/v1/translations", async (c) => {
5317
5399
  const translationsDir = join(root, "translations");
5318
5400
  let entries = [];