@gobing-ai/knowledge-kit 0.0.21 → 0.0.22

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 (59) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/dist/index.js +161 -142
  3. package/package.json +1 -1
  4. package/plugins/generations/content-gen/dist/index.js +20 -3
  5. package/plugins/generations/core-facts-gen/dist/index.js +20 -3
  6. package/plugins/generations/daily-article-gen/dist/index.js +20 -3
  7. package/plugins/generations/dailynews-gen/dist/index.js +20 -3
  8. package/plugins/generations/episode-plan-gen/dist/index.js +20 -3
  9. package/plugins/generations/image-gen/dist/index.js +147 -69
  10. package/plugins/generations/image-gen/src/presets.ts +2 -2
  11. package/plugins/generations/image-gen/src/providers/agnes.ts +6 -2
  12. package/plugins/generations/image-gen/src/providers/azure.ts +6 -2
  13. package/plugins/generations/image-gen/src/providers/dashscope.ts +10 -3
  14. package/plugins/generations/image-gen/src/providers/google.ts +70 -29
  15. package/plugins/generations/image-gen/src/providers/huggingface.ts +3 -0
  16. package/plugins/generations/image-gen/src/providers/jimeng.ts +9 -2
  17. package/plugins/generations/image-gen/src/providers/minimax.ts +10 -2
  18. package/plugins/generations/image-gen/src/providers/openai.ts +9 -3
  19. package/plugins/generations/image-gen/src/providers/openrouter.ts +16 -4
  20. package/plugins/generations/image-gen/src/providers/replicate.ts +13 -3
  21. package/plugins/generations/image-gen/src/providers/seedream.ts +4 -1
  22. package/plugins/generations/image-gen/src/providers/timeouts.ts +14 -0
  23. package/plugins/generations/image-gen/src/providers/types.ts +10 -0
  24. package/plugins/generations/image-gen/src/providers/zai.ts +4 -1
  25. package/plugins/generations/news-report-gen/dist/index.js +20 -3
  26. package/plugins/generations/voice-gen/dist/index.js +36 -10
  27. package/plugins/generations/voice-gen/src/voicebox-client.ts +18 -4
  28. package/plugins/generations/voice-gen/src/voicebox-server.ts +2 -1
  29. package/plugins/ingestions/aihot-ingest/dist/index.js +25 -5
  30. package/plugins/ingestions/aihot-ingest/src/client.ts +5 -0
  31. package/plugins/ingestions/horizon-ingest/dist/index.js +20 -3
  32. package/plugins/ingestions/last30days-ingest/dist/index.js +20 -3
  33. package/plugins/ingestions/web-search/dist/index.js +22 -3
  34. package/plugins/ingestions/web-search/src/index.ts +4 -0
  35. package/plugins/kk/plugin.json +1 -1
  36. package/plugins/kk/scripts/kk-workflow-stages.ts +35 -7
  37. package/plugins/kk/scripts/render-md.ts +7 -1
  38. package/plugins/publishings/emdash-pub/dist/index.js +76 -19
  39. package/plugins/publishings/emdash-pub/src/index.ts +4 -0
  40. package/plugins/publishings/infoq-pub/dist/index.js +74 -21
  41. package/plugins/publishings/juejin-pub/dist/index.js +74 -21
  42. package/plugins/publishings/medium-pub/dist/index.js +77 -19
  43. package/plugins/publishings/medium-pub/src/index.ts +5 -0
  44. package/plugins/publishings/podcast-pub/dist/index.js +130 -34
  45. package/plugins/publishings/podcast-pub/src/index.ts +20 -5
  46. package/plugins/publishings/podcast-pub/src/map.ts +11 -0
  47. package/plugins/publishings/podcast-pub/src/show-notes.ts +66 -13
  48. package/plugins/publishings/qiita-pub/dist/index.js +75 -18
  49. package/plugins/publishings/qiita-pub/src/index.ts +4 -0
  50. package/plugins/publishings/substack-pub/dist/index.js +74 -21
  51. package/plugins/publishings/surfdash-pub/dist/index.js +99 -62
  52. package/plugins/publishings/surfdash-pub/src/index.ts +60 -19
  53. package/plugins/publishings/wechatmp-pub/dist/index.js +79 -22
  54. package/plugins/publishings/wechatmp-pub/src/index.ts +12 -3
  55. package/plugins/publishings/x-pub/dist/index.js +56 -37
  56. package/plugins/publishings/x-pub/src/index.ts +4 -0
  57. package/plugins/publishings/xhs-pub/dist/index.js +74 -21
  58. package/plugins/publishings/zenn-pub/dist/index.js +103 -25
  59. package/plugins/publishings/zenn-pub/src/index.ts +43 -9
@@ -21781,6 +21781,22 @@ var ResultSchema = exports_external.object({
21781
21781
  error: exports_external.string().optional(),
21782
21782
  metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
21783
21783
  });
21784
+ var TargetOutcomeSchema = exports_external.object({
21785
+ target: exports_external.string(),
21786
+ ok: exports_external.boolean(),
21787
+ status: exports_external.enum(["published", "failed", "skipped"]),
21788
+ url: exports_external.string().optional(),
21789
+ id: exports_external.string().optional(),
21790
+ error: exports_external.string().optional(),
21791
+ durationMs: exports_external.number().optional(),
21792
+ metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
21793
+ });
21794
+ var AggregateResultSchema = exports_external.object({
21795
+ ok: exports_external.boolean(),
21796
+ summary: exports_external.object({ total: exports_external.number(), succeeded: exports_external.number(), failed: exports_external.number(), skipped: exports_external.number() }),
21797
+ targets: exports_external.array(TargetOutcomeSchema),
21798
+ metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
21799
+ });
21784
21800
  var DocListSchema = exports_external.array(DocSchema);
21785
21801
  var omniVoiceGenContentSchema = ContentSchema.extend({
21786
21802
  format: exports_external.literal("audio"),
@@ -21809,14 +21825,15 @@ var PluginKindSchema = exports_external.enum(PLUGIN_KINDS);
21809
21825
  // ../../packages/kk-core/src/manifest.ts
21810
21826
  init_zod();
21811
21827
  var OperationIOSchema = exports_external.enum(["doc-list", "markdown"]);
21812
- var PluginManifestSchema = exports_external.object({
21828
+ var PluginOperationSchema = exports_external.object({ input: OperationIOSchema, output: OperationIOSchema });
21829
+ var PluginManifestSchema = exports_external.looseObject({
21813
21830
  name: exports_external.string().min(1),
21814
21831
  kind: PluginKindSchema,
21815
21832
  entry: exports_external.string().min(1),
21816
21833
  version: exports_external.string().optional(),
21817
21834
  description: exports_external.string().optional(),
21818
- operations: exports_external.record(exports_external.string(), exports_external.object({ input: OperationIOSchema, output: OperationIOSchema })).optional()
21819
- }).passthrough();
21835
+ operations: exports_external.record(exports_external.string(), PluginOperationSchema).optional()
21836
+ });
21820
21837
  // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.39/node_modules/@gobing-ai/ts-runtime/dist/index.js
21821
21838
  init_file_system_node();
21822
21839
  init_config();
@@ -21842,44 +21859,83 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
21842
21859
  // ../../packages/kk-core/src/render-md.ts
21843
21860
  if (false) {}
21844
21861
  // ../../packages/publish-harness/src/index.ts
21845
- class FakeFileCliTransport {
21846
- kind = "file-cli";
21847
- callLogs;
21862
+ class FakeTransportCore {
21863
+ callLogs = [];
21848
21864
  nextResult;
21849
- constructor() {
21850
- this.callLogs = [];
21851
- }
21852
21865
  setNextResult(result) {
21853
21866
  this.nextResult = result;
21854
21867
  }
21855
- async publish(payload) {
21868
+ async publish(payload, defaultResult) {
21856
21869
  this.callLogs.push({
21857
21870
  timestamp: new Date().toISOString(),
21858
21871
  payload
21859
21872
  });
21860
- if (this.nextResult) {
21861
- return this.nextResult;
21862
- }
21863
- return {
21873
+ return this.nextResult ?? defaultResult;
21874
+ }
21875
+ getCallLogs() {
21876
+ return this.callLogs;
21877
+ }
21878
+ reset() {
21879
+ this.callLogs = [];
21880
+ this.nextResult = undefined;
21881
+ }
21882
+ }
21883
+
21884
+ class FakeFileCliTransport {
21885
+ kind = "file-cli";
21886
+ core = new FakeTransportCore;
21887
+ setNextResult(result) {
21888
+ this.core.setNextResult(result);
21889
+ }
21890
+ async publish(payload) {
21891
+ return this.core.publish(payload, {
21864
21892
  ok: true,
21865
21893
  target: "fake-file-cli",
21866
21894
  url: "https://example.com/published-post",
21867
21895
  id: "fake-id-123",
21868
21896
  message: "Published offline via FakeFileCliTransport"
21869
- };
21897
+ });
21870
21898
  }
21871
21899
  getCallLogs() {
21872
- return this.callLogs;
21900
+ return this.core.getCallLogs();
21873
21901
  }
21874
21902
  reset() {
21875
- this.callLogs = [];
21876
- this.nextResult = undefined;
21903
+ this.core.reset();
21904
+ }
21905
+ }
21906
+
21907
+ class FakeBrowserTransport {
21908
+ kind = "browser";
21909
+ driver;
21910
+ core = new FakeTransportCore;
21911
+ constructor(driver = "agent") {
21912
+ this.driver = driver;
21913
+ }
21914
+ setNextResult(result) {
21915
+ this.core.setNextResult(result);
21916
+ }
21917
+ async publish(payload) {
21918
+ return this.core.publish(payload, {
21919
+ ok: true,
21920
+ target: "fake-browser",
21921
+ url: "https://example.com/browser-draft",
21922
+ id: "fake-browser-id-123",
21923
+ message: "Published offline via FakeBrowserTransport",
21924
+ metadata: { driver: this.driver }
21925
+ });
21926
+ }
21927
+ getCallLogs() {
21928
+ return this.core.getCallLogs();
21929
+ }
21930
+ reset() {
21931
+ this.core.reset();
21877
21932
  }
21878
21933
  }
21879
21934
 
21880
21935
  // ../../plugins/publishings/wechatmp-pub/src/index.ts
21881
21936
  var TARGET = "wechatmp";
21882
21937
  var TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
21938
+ var REQUEST_TIMEOUT_MS = 120000;
21883
21939
  var DRAFT_ADD_URL = "https://api.weixin.qq.com/cgi-bin/draft/add";
21884
21940
  var APP_ID_ENV = "WECHAT_APP_ID";
21885
21941
  var APP_SECRET_ENV = "WECHAT_APP_SECRET";
@@ -21887,7 +21943,7 @@ function fail(error51) {
21887
21943
  return ResultSchema.parse({ ok: false, target: TARGET, error: error51 });
21888
21944
  }
21889
21945
  function escapeHtml(text) {
21890
- return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
21946
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
21891
21947
  }
21892
21948
  function markdownToWechatHtml(markdown) {
21893
21949
  const lines = markdown.replace(/\r\n/g, `
@@ -21903,7 +21959,7 @@ function markdownToWechatHtml(markdown) {
21903
21959
  listType = null;
21904
21960
  }
21905
21961
  };
21906
- const inline = (text) => escapeHtml(text).replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>").replace(/\*([^*]+)\*/g, "<em>$1</em>").replace(/`([^`]+)`/g, "<code>$1</code>").replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
21962
+ const inline = (text) => escapeHtml(text).replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>").replace(/\*([^*]+)\*/g, "<em>$1</em>").replace(/`([^`]+)`/g, "<code>$1</code>").replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m, text2, href) => /^https?:\/\//i.test(href) ? `<a href="${href}">${text2}</a>` : text2);
21907
21963
  for (const line of lines) {
21908
21964
  if (line.startsWith("```")) {
21909
21965
  if (inCode) {
@@ -22027,7 +22083,7 @@ class WechatDraftApiTransport {
22027
22083
  }
22028
22084
  try {
22029
22085
  const tokenUrl = `${TOKEN_URL}?grant_type=client_credential&appid=${encodeURIComponent(appId ?? "")}&secret=${encodeURIComponent(appSecret ?? "")}`;
22030
- const tokenResponse = await fetch(tokenUrl);
22086
+ const tokenResponse = await fetch(tokenUrl, { signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS) });
22031
22087
  const tokenJson = await tokenResponse.json();
22032
22088
  if (typeof tokenJson.access_token !== "string") {
22033
22089
  return fail(`WeChat token request failed: ${typeof tokenJson.errmsg === "string" ? tokenJson.errmsg : "missing access_token"}`);
@@ -22035,7 +22091,8 @@ class WechatDraftApiTransport {
22035
22091
  const draftResponse = await fetch(`${DRAFT_ADD_URL}?access_token=${encodeURIComponent(tokenJson.access_token)}`, {
22036
22092
  method: "POST",
22037
22093
  headers: { "Content-Type": "application/json" },
22038
- body: JSON.stringify(articles)
22094
+ body: JSON.stringify(articles),
22095
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
22039
22096
  });
22040
22097
  const draftJson = await draftResponse.json();
22041
22098
  if (typeof draftJson.media_id !== "string") {
@@ -7,6 +7,9 @@ import { echoError } from '@gobing-ai/ts-utils';
7
7
 
8
8
  const TARGET = 'wechatmp';
9
9
  const TOKEN_URL = 'https://api.weixin.qq.com/cgi-bin/token';
10
+
11
+ /** Per-request timeout (ms) for WeChat HTTP calls — Bun's `fetch` has no default deadline (R5). */
12
+ const REQUEST_TIMEOUT_MS = 120_000;
10
13
  const DRAFT_ADD_URL = 'https://api.weixin.qq.com/cgi-bin/draft/add';
11
14
  const APP_ID_ENV = 'WECHAT_APP_ID';
12
15
  const APP_SECRET_ENV = 'WECHAT_APP_SECRET';
@@ -32,7 +35,7 @@ function fail(error: string): Result {
32
35
  }
33
36
 
34
37
  function escapeHtml(text: string): string {
35
- return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
38
+ return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
36
39
  }
37
40
 
38
41
  /**
@@ -58,7 +61,12 @@ export function markdownToWechatHtml(markdown: string): string {
58
61
  .replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
59
62
  .replace(/\*([^*]+)\*/g, '<em>$1</em>')
60
63
  .replace(/`([^`]+)`/g, '<code>$1</code>')
61
- .replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
64
+ // `href` is already HTML-escaped (inline() escapes before replacing), so a `"` can no
65
+ // longer close the attribute. The scheme allowlist is still required: escaping does not
66
+ // neutralise `javascript:`. Non-http(s) links degrade to their label text.
67
+ .replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m, text: string, href: string) =>
68
+ /^https?:\/\//i.test(href) ? `<a href="${href}">${text}</a>` : text,
69
+ );
62
70
 
63
71
  for (const line of lines) {
64
72
  if (line.startsWith('```')) {
@@ -197,7 +205,7 @@ export class WechatDraftApiTransport implements PublishTransport {
197
205
 
198
206
  try {
199
207
  const tokenUrl = `${TOKEN_URL}?grant_type=client_credential&appid=${encodeURIComponent(appId ?? '')}&secret=${encodeURIComponent(appSecret ?? '')}`;
200
- const tokenResponse = await fetch(tokenUrl);
208
+ const tokenResponse = await fetch(tokenUrl, { signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS) });
201
209
  const tokenJson = (await tokenResponse.json()) as {
202
210
  access_token?: unknown;
203
211
  errmsg?: unknown;
@@ -214,6 +222,7 @@ export class WechatDraftApiTransport implements PublishTransport {
214
222
  method: 'POST',
215
223
  headers: { 'Content-Type': 'application/json' },
216
224
  body: JSON.stringify(articles),
225
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
217
226
  },
218
227
  );
219
228
  const draftJson = (await draftResponse.json()) as {
@@ -21782,6 +21782,22 @@ var ResultSchema = exports_external.object({
21782
21782
  error: exports_external.string().optional(),
21783
21783
  metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
21784
21784
  });
21785
+ var TargetOutcomeSchema = exports_external.object({
21786
+ target: exports_external.string(),
21787
+ ok: exports_external.boolean(),
21788
+ status: exports_external.enum(["published", "failed", "skipped"]),
21789
+ url: exports_external.string().optional(),
21790
+ id: exports_external.string().optional(),
21791
+ error: exports_external.string().optional(),
21792
+ durationMs: exports_external.number().optional(),
21793
+ metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
21794
+ });
21795
+ var AggregateResultSchema = exports_external.object({
21796
+ ok: exports_external.boolean(),
21797
+ summary: exports_external.object({ total: exports_external.number(), succeeded: exports_external.number(), failed: exports_external.number(), skipped: exports_external.number() }),
21798
+ targets: exports_external.array(TargetOutcomeSchema),
21799
+ metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
21800
+ });
21785
21801
  var DocListSchema = exports_external.array(DocSchema);
21786
21802
  var omniVoiceGenContentSchema = ContentSchema.extend({
21787
21803
  format: exports_external.literal("audio"),
@@ -21810,14 +21826,15 @@ var PluginKindSchema = exports_external.enum(PLUGIN_KINDS);
21810
21826
  // ../../packages/kk-core/src/manifest.ts
21811
21827
  init_zod();
21812
21828
  var OperationIOSchema = exports_external.enum(["doc-list", "markdown"]);
21813
- var PluginManifestSchema = exports_external.object({
21829
+ var PluginOperationSchema = exports_external.object({ input: OperationIOSchema, output: OperationIOSchema });
21830
+ var PluginManifestSchema = exports_external.looseObject({
21814
21831
  name: exports_external.string().min(1),
21815
21832
  kind: PluginKindSchema,
21816
21833
  entry: exports_external.string().min(1),
21817
21834
  version: exports_external.string().optional(),
21818
21835
  description: exports_external.string().optional(),
21819
- operations: exports_external.record(exports_external.string(), exports_external.object({ input: OperationIOSchema, output: OperationIOSchema })).optional()
21820
- }).passthrough();
21836
+ operations: exports_external.record(exports_external.string(), PluginOperationSchema).optional()
21837
+ });
21821
21838
  // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.39/node_modules/@gobing-ai/ts-runtime/dist/index.js
21822
21839
  init_file_system_node();
21823
21840
  init_config();
@@ -21844,78 +21861,78 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
21844
21861
  if (false) {}
21845
21862
  // ../../packages/publish-harness/src/index.ts
21846
21863
  import { homedir } from "os";
21847
- import { join } from "path";
21864
+ import { join, resolve } from "path";
21848
21865
 
21849
- class FakeFileCliTransport {
21850
- kind = "file-cli";
21851
- callLogs;
21866
+ class FakeTransportCore {
21867
+ callLogs = [];
21852
21868
  nextResult;
21853
- constructor() {
21854
- this.callLogs = [];
21855
- }
21856
21869
  setNextResult(result) {
21857
21870
  this.nextResult = result;
21858
21871
  }
21859
- async publish(payload) {
21872
+ async publish(payload, defaultResult) {
21860
21873
  this.callLogs.push({
21861
21874
  timestamp: new Date().toISOString(),
21862
21875
  payload
21863
21876
  });
21864
- if (this.nextResult) {
21865
- return this.nextResult;
21866
- }
21867
- return {
21877
+ return this.nextResult ?? defaultResult;
21878
+ }
21879
+ getCallLogs() {
21880
+ return this.callLogs;
21881
+ }
21882
+ reset() {
21883
+ this.callLogs = [];
21884
+ this.nextResult = undefined;
21885
+ }
21886
+ }
21887
+
21888
+ class FakeFileCliTransport {
21889
+ kind = "file-cli";
21890
+ core = new FakeTransportCore;
21891
+ setNextResult(result) {
21892
+ this.core.setNextResult(result);
21893
+ }
21894
+ async publish(payload) {
21895
+ return this.core.publish(payload, {
21868
21896
  ok: true,
21869
21897
  target: "fake-file-cli",
21870
21898
  url: "https://example.com/published-post",
21871
21899
  id: "fake-id-123",
21872
21900
  message: "Published offline via FakeFileCliTransport"
21873
- };
21901
+ });
21874
21902
  }
21875
21903
  getCallLogs() {
21876
- return this.callLogs;
21904
+ return this.core.getCallLogs();
21877
21905
  }
21878
21906
  reset() {
21879
- this.callLogs = [];
21880
- this.nextResult = undefined;
21907
+ this.core.reset();
21881
21908
  }
21882
21909
  }
21883
21910
 
21884
21911
  class FakeBrowserTransport {
21885
21912
  kind = "browser";
21886
21913
  driver;
21887
- callLogs;
21888
- nextResult;
21914
+ core = new FakeTransportCore;
21889
21915
  constructor(driver = "agent") {
21890
21916
  this.driver = driver;
21891
- this.callLogs = [];
21892
21917
  }
21893
21918
  setNextResult(result) {
21894
- this.nextResult = result;
21919
+ this.core.setNextResult(result);
21895
21920
  }
21896
21921
  async publish(payload) {
21897
- this.callLogs.push({
21898
- timestamp: new Date().toISOString(),
21899
- payload
21900
- });
21901
- if (this.nextResult) {
21902
- return this.nextResult;
21903
- }
21904
- return {
21922
+ return this.core.publish(payload, {
21905
21923
  ok: true,
21906
21924
  target: "fake-browser",
21907
21925
  url: "https://example.com/browser-draft",
21908
21926
  id: "fake-browser-id-123",
21909
21927
  message: "Published offline via FakeBrowserTransport",
21910
21928
  metadata: { driver: this.driver }
21911
- };
21929
+ });
21912
21930
  }
21913
21931
  getCallLogs() {
21914
- return this.callLogs;
21932
+ return this.core.getCallLogs();
21915
21933
  }
21916
21934
  reset() {
21917
- this.callLogs = [];
21918
- this.nextResult = undefined;
21935
+ this.core.reset();
21919
21936
  }
21920
21937
  }
21921
21938
  function resolveBrowserProfileDir(channel, override) {
@@ -21924,12 +21941,13 @@ function resolveBrowserProfileDir(channel, override) {
21924
21941
  if (trimmed.startsWith("~/")) {
21925
21942
  return join(homedir(), trimmed.slice(2));
21926
21943
  }
21927
- return trimmed;
21944
+ return resolve(trimmed);
21928
21945
  }
21929
21946
  return join(homedir(), ".config", "kk", "browser-profiles", channel);
21930
21947
  }
21931
21948
 
21932
21949
  // ../../plugins/publishings/x-pub/src/index.ts
21950
+ var REQUEST_TIMEOUT_MS = 120000;
21933
21951
  var TARGET = "x";
21934
21952
  var TWEETS_URL = "https://api.twitter.com/2/tweets";
21935
21953
  var TOKEN_ENVS = ["X_API_KEY", "X_API_SECRET", "X_ACCESS_TOKEN", "X_ACCESS_TOKEN_SECRET"];
@@ -21991,7 +22009,8 @@ class XPostApiTransport {
21991
22009
  Authorization: authorization,
21992
22010
  "Content-Type": "application/json"
21993
22011
  },
21994
- body: JSON.stringify({ text: text.slice(0, 280) })
22012
+ body: JSON.stringify({ text: text.slice(0, 280) }),
22013
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
21995
22014
  });
21996
22015
  if (!response.ok) {
21997
22016
  const errorText = (await response.text()).slice(0, 1000);
@@ -13,6 +13,9 @@ import {
13
13
  import { createNodeFileSystem } from '@gobing-ai/ts-runtime';
14
14
  import { echoError } from '@gobing-ai/ts-utils';
15
15
 
16
+ /** Per-request timeout (ms) for the X API call — Bun's `fetch` has no default deadline (R5). */
17
+ const REQUEST_TIMEOUT_MS = 120_000;
18
+
16
19
  const TARGET = 'x';
17
20
  const TWEETS_URL = 'https://api.twitter.com/2/tweets';
18
21
  const TOKEN_ENVS = ['X_API_KEY', 'X_API_SECRET', 'X_ACCESS_TOKEN', 'X_ACCESS_TOKEN_SECRET'] as const;
@@ -98,6 +101,7 @@ export class XPostApiTransport implements PublishTransport {
98
101
  'Content-Type': 'application/json',
99
102
  },
100
103
  body: JSON.stringify({ text: text.slice(0, 280) }),
104
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
101
105
  });
102
106
  if (!response.ok) {
103
107
  const errorText = (await response.text()).slice(0, 1000);
@@ -21781,6 +21781,22 @@ var ResultSchema = exports_external.object({
21781
21781
  error: exports_external.string().optional(),
21782
21782
  metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
21783
21783
  });
21784
+ var TargetOutcomeSchema = exports_external.object({
21785
+ target: exports_external.string(),
21786
+ ok: exports_external.boolean(),
21787
+ status: exports_external.enum(["published", "failed", "skipped"]),
21788
+ url: exports_external.string().optional(),
21789
+ id: exports_external.string().optional(),
21790
+ error: exports_external.string().optional(),
21791
+ durationMs: exports_external.number().optional(),
21792
+ metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
21793
+ });
21794
+ var AggregateResultSchema = exports_external.object({
21795
+ ok: exports_external.boolean(),
21796
+ summary: exports_external.object({ total: exports_external.number(), succeeded: exports_external.number(), failed: exports_external.number(), skipped: exports_external.number() }),
21797
+ targets: exports_external.array(TargetOutcomeSchema),
21798
+ metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
21799
+ });
21784
21800
  var DocListSchema = exports_external.array(DocSchema);
21785
21801
  var omniVoiceGenContentSchema = ContentSchema.extend({
21786
21802
  format: exports_external.literal("audio"),
@@ -21809,14 +21825,15 @@ var PluginKindSchema = exports_external.enum(PLUGIN_KINDS);
21809
21825
  // ../../packages/kk-core/src/manifest.ts
21810
21826
  init_zod();
21811
21827
  var OperationIOSchema = exports_external.enum(["doc-list", "markdown"]);
21812
- var PluginManifestSchema = exports_external.object({
21828
+ var PluginOperationSchema = exports_external.object({ input: OperationIOSchema, output: OperationIOSchema });
21829
+ var PluginManifestSchema = exports_external.looseObject({
21813
21830
  name: exports_external.string().min(1),
21814
21831
  kind: PluginKindSchema,
21815
21832
  entry: exports_external.string().min(1),
21816
21833
  version: exports_external.string().optional(),
21817
21834
  description: exports_external.string().optional(),
21818
- operations: exports_external.record(exports_external.string(), exports_external.object({ input: OperationIOSchema, output: OperationIOSchema })).optional()
21819
- }).passthrough();
21835
+ operations: exports_external.record(exports_external.string(), PluginOperationSchema).optional()
21836
+ });
21820
21837
  // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.39/node_modules/@gobing-ai/ts-runtime/dist/index.js
21821
21838
  init_file_system_node();
21822
21839
  init_config();
@@ -21843,42 +21860,78 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
21843
21860
  if (false) {}
21844
21861
  // ../../packages/publish-harness/src/index.ts
21845
21862
  import { homedir } from "os";
21846
- import { join } from "path";
21863
+ import { join, resolve } from "path";
21864
+
21865
+ class FakeTransportCore {
21866
+ callLogs = [];
21867
+ nextResult;
21868
+ setNextResult(result) {
21869
+ this.nextResult = result;
21870
+ }
21871
+ async publish(payload, defaultResult) {
21872
+ this.callLogs.push({
21873
+ timestamp: new Date().toISOString(),
21874
+ payload
21875
+ });
21876
+ return this.nextResult ?? defaultResult;
21877
+ }
21878
+ getCallLogs() {
21879
+ return this.callLogs;
21880
+ }
21881
+ reset() {
21882
+ this.callLogs = [];
21883
+ this.nextResult = undefined;
21884
+ }
21885
+ }
21886
+
21887
+ class FakeFileCliTransport {
21888
+ kind = "file-cli";
21889
+ core = new FakeTransportCore;
21890
+ setNextResult(result) {
21891
+ this.core.setNextResult(result);
21892
+ }
21893
+ async publish(payload) {
21894
+ return this.core.publish(payload, {
21895
+ ok: true,
21896
+ target: "fake-file-cli",
21897
+ url: "https://example.com/published-post",
21898
+ id: "fake-id-123",
21899
+ message: "Published offline via FakeFileCliTransport"
21900
+ });
21901
+ }
21902
+ getCallLogs() {
21903
+ return this.core.getCallLogs();
21904
+ }
21905
+ reset() {
21906
+ this.core.reset();
21907
+ }
21908
+ }
21909
+
21847
21910
  class FakeBrowserTransport {
21848
21911
  kind = "browser";
21849
21912
  driver;
21850
- callLogs;
21851
- nextResult;
21913
+ core = new FakeTransportCore;
21852
21914
  constructor(driver = "agent") {
21853
21915
  this.driver = driver;
21854
- this.callLogs = [];
21855
21916
  }
21856
21917
  setNextResult(result) {
21857
- this.nextResult = result;
21918
+ this.core.setNextResult(result);
21858
21919
  }
21859
21920
  async publish(payload) {
21860
- this.callLogs.push({
21861
- timestamp: new Date().toISOString(),
21862
- payload
21863
- });
21864
- if (this.nextResult) {
21865
- return this.nextResult;
21866
- }
21867
- return {
21921
+ return this.core.publish(payload, {
21868
21922
  ok: true,
21869
21923
  target: "fake-browser",
21870
21924
  url: "https://example.com/browser-draft",
21871
21925
  id: "fake-browser-id-123",
21872
21926
  message: "Published offline via FakeBrowserTransport",
21873
21927
  metadata: { driver: this.driver }
21874
- };
21928
+ });
21875
21929
  }
21876
21930
  getCallLogs() {
21877
- return this.callLogs;
21931
+ return this.core.getCallLogs();
21878
21932
  }
21879
21933
  reset() {
21880
- this.callLogs = [];
21881
- this.nextResult = undefined;
21934
+ this.core.reset();
21882
21935
  }
21883
21936
  }
21884
21937
  function resolveBrowserProfileDir(channel, override) {
@@ -21887,7 +21940,7 @@ function resolveBrowserProfileDir(channel, override) {
21887
21940
  if (trimmed.startsWith("~/")) {
21888
21941
  return join(homedir(), trimmed.slice(2));
21889
21942
  }
21890
- return trimmed;
21943
+ return resolve(trimmed);
21891
21944
  }
21892
21945
  return join(homedir(), ".config", "kk", "browser-profiles", channel);
21893
21946
  }