orbit-code-ai 0.1.39 → 0.1.41

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 (3) hide show
  1. package/README.md +32 -0
  2. package/dist/cli.mjs +478 -108
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -107,6 +107,38 @@ Built-in reference docs loaded into every session:
107
107
 
108
108
  ---
109
109
 
110
+ ## LLD → APIC artifacts
111
+
112
+ Turn a middleware **Low-Level Design** (`.docx`) into deployable artifacts. `/lld` reads the Word
113
+ document (paragraphs **and** tables), extracts the API spec against the house template, shows you an
114
+ extraction summary to confirm, then generates any combination of:
115
+
116
+ ```
117
+ /lld "C:\path\to\LLD_MyApi.docx" [contract] [api] [diagram] # or: both | all (default: all)
118
+ ```
119
+
120
+ - **contract** → a contract-only OpenAPI (rich request/response/error schemas) via `/api-contract`
121
+ - **api** → the APIC gateway definition (`x-ibm-configuration` assembly) via `/apic-api`
122
+ — supports a `backend` pattern (APIC wraps a raw backend in the ESB envelope) and a `wrapper`
123
+ pattern (a thin proxy over an existing ACE/webMethods service that already returns the envelope)
124
+ - **diagram** → the **Integration Service Flow** as a `.drawio` file (BIDAYA activity-diagram house
125
+ style) via `/drawio`
126
+
127
+ The diagram is drawn deterministically from a small flow model, and branches reflect the LLD:
128
+
129
+ - a **token** branch (access-token call cached until the JWT `exp`) appears only when auth is
130
+ token-based — omitted for no-auth / static-key services;
131
+ - a **cache** branch appears only when the MW caches the response — omitted when the LLD says
132
+ "Cache: Not applicable";
133
+ - the **success/error** decision uses the LLD's actual success rule (e.g. `HTTP 200`, or a body
134
+ status code like `eigerResultCode = 200`), feeding green (success) / red (error) mapping boxes.
135
+
136
+ Output opens directly in [diagrams.net](https://app.diagrams.net) with the house style: green
137
+ swimlanes, blue action parallelograms, pink decision diamonds, green/red mapping boxes, a yellow
138
+ START ellipse and a red-ringed final node.
139
+
140
+ ---
141
+
110
142
  ## Agent Routing
111
143
 
112
144
  Route different agent tasks to different models. Define each model's connection in `agentModels`, then map agents (or `default`) to those names in `agentRouting`. Every name used in `agentRouting` must exist in `agentModels`:
package/dist/cli.mjs CHANGED
@@ -57129,15 +57129,19 @@ function getOpus46CostTier(fastMode) {
57129
57129
  function tokensToUSDCost(modelCosts, usage) {
57130
57130
  return usage.input_tokens / 1e6 * modelCosts.inputTokens + usage.output_tokens / 1e6 * modelCosts.outputTokens + (usage.cache_read_input_tokens ?? 0) / 1e6 * modelCosts.promptCacheReadTokens + (usage.cache_creation_input_tokens ?? 0) / 1e6 * modelCosts.promptCacheWriteTokens + (usage.server_tool_use?.web_search_requests ?? 0) * modelCosts.webSearchRequests;
57131
57131
  }
57132
+ function geminiVersionAtLeast(model, min) {
57133
+ const match = model.toLowerCase().match(/gemini-(\d+\.\d+)/);
57134
+ return match ? Number.parseFloat(match[1]) >= min : false;
57135
+ }
57132
57136
  function getModelCosts(model, usage) {
57133
57137
  const shortName = getCanonicalName(model);
57134
57138
  if (model.toLowerCase().startsWith("gemini")) {
57135
57139
  const lower = model.toLowerCase();
57136
57140
  if (lower.includes("flash-lite") || lower.includes("3.1") && lower.includes("flash")) {
57137
- return COST_GEMINI_31_FLASH_LITE;
57141
+ return lower.includes("lite") && geminiVersionAtLeast(lower, 3.5) ? COST_GEMINI_35_FLASH_LITE : COST_GEMINI_31_FLASH_LITE;
57138
57142
  }
57139
- if (lower.includes("3.5") && lower.includes("flash")) {
57140
- return COST_GEMINI_35_FLASH;
57143
+ if (lower.includes("flash")) {
57144
+ return geminiVersionAtLeast(lower, 3.6) ? COST_GEMINI_36_FLASH : COST_GEMINI_35_FLASH;
57141
57145
  }
57142
57146
  if (lower.includes("pro")) {
57143
57147
  const promptTokens = usage.input_tokens + (usage.cache_read_input_tokens ?? 0) + (usage.cache_creation_input_tokens ?? 0);
@@ -57177,7 +57181,7 @@ function formatPrice(price) {
57177
57181
  function formatModelPricing(costs) {
57178
57182
  return `${formatPrice(costs.inputTokens)}/${formatPrice(costs.outputTokens)} per Mtok`;
57179
57183
  }
57180
- var COST_TIER_3_15, COST_TIER_15_75, COST_TIER_5_25, COST_TIER_30_150, COST_GEMINI_31_PRO, COST_GEMINI_31_PRO_HIGH, COST_GEMINI_31_FLASH_LITE, COST_GEMINI_35_FLASH, COST_HAIKU_35, COST_HAIKU_45, DEFAULT_UNKNOWN_MODEL_COST, MODEL_COSTS;
57184
+ var COST_TIER_3_15, COST_TIER_15_75, COST_TIER_5_25, COST_TIER_30_150, COST_GEMINI_31_PRO, COST_GEMINI_31_PRO_HIGH, COST_GEMINI_31_FLASH_LITE, COST_GEMINI_35_FLASH, COST_GEMINI_36_FLASH, COST_GEMINI_35_FLASH_LITE, COST_HAIKU_35, COST_HAIKU_45, DEFAULT_UNKNOWN_MODEL_COST, MODEL_COSTS;
57181
57185
  var init_modelCost = __esm(() => {
57182
57186
  init_state();
57183
57187
  init_fastMode();
@@ -57239,6 +57243,20 @@ var init_modelCost = __esm(() => {
57239
57243
  promptCacheReadTokens: 0.375,
57240
57244
  webSearchRequests: 0.01
57241
57245
  };
57246
+ COST_GEMINI_36_FLASH = {
57247
+ inputTokens: 1.5,
57248
+ outputTokens: 7.5,
57249
+ promptCacheWriteTokens: 0,
57250
+ promptCacheReadTokens: 0.15,
57251
+ webSearchRequests: 0.01
57252
+ };
57253
+ COST_GEMINI_35_FLASH_LITE = {
57254
+ inputTokens: 0.3,
57255
+ outputTokens: 2.5,
57256
+ promptCacheWriteTokens: 0,
57257
+ promptCacheReadTokens: 0.03,
57258
+ webSearchRequests: 0.01
57259
+ };
57242
57260
  COST_HAIKU_35 = {
57243
57261
  inputTokens: 0.8,
57244
57262
  outputTokens: 4,
@@ -57421,7 +57439,7 @@ function getSmallFastModel() {
57421
57439
  if (process.env.ANTHROPIC_SMALL_FAST_MODEL)
57422
57440
  return process.env.ANTHROPIC_SMALL_FAST_MODEL;
57423
57441
  if (getAPIProvider() === "gemini") {
57424
- return process.env.GEMINI_FAST_MODEL || "gemini-3.1-flash-lite";
57442
+ return process.env.GEMINI_FAST_MODEL || "gemini-3.5-flash-lite";
57425
57443
  }
57426
57444
  if (getAPIProvider() === "openai") {
57427
57445
  return process.env.OPENAI_MODEL || "gpt-4o-mini";
@@ -57485,7 +57503,7 @@ function getDefaultSonnetModel() {
57485
57503
  return process.env.ANTHROPIC_DEFAULT_SONNET_MODEL;
57486
57504
  }
57487
57505
  if (getAPIProvider() === "gemini") {
57488
- return process.env.GEMINI_FLASH_MODEL || "gemini-3.5-flash";
57506
+ return process.env.GEMINI_FLASH_MODEL || "gemini-3.6-flash";
57489
57507
  }
57490
57508
  if (getAPIProvider() === "openai") {
57491
57509
  return process.env.OPENAI_MODEL || "gpt-4o";
@@ -57515,7 +57533,7 @@ function getDefaultHaikuModel() {
57515
57533
  return process.env.OPENAI_MODEL || "github:copilot";
57516
57534
  }
57517
57535
  if (getAPIProvider() === "gemini") {
57518
- return process.env.GEMINI_FAST_MODEL || "gemini-3.1-flash-lite";
57536
+ return process.env.GEMINI_FAST_MODEL || "gemini-3.5-flash-lite";
57519
57537
  }
57520
57538
  return getModelStrings2().haiku45;
57521
57539
  }
@@ -57535,7 +57553,7 @@ function getDefaultMainLoopModelSetting() {
57535
57553
  return settings.model || process.env.OPENAI_MODEL || "github:copilot";
57536
57554
  }
57537
57555
  if (getAPIProvider() === "gemini") {
57538
- return process.env.GEMINI_MODEL || process.env.GEMINI_FAST_MODEL || "gemini-3.1-flash-lite";
57556
+ return process.env.GEMINI_MODEL || process.env.GEMINI_FAST_MODEL || "gemini-3.5-flash-lite";
57539
57557
  }
57540
57558
  if (getAPIProvider() === "openai") {
57541
57559
  return process.env.OPENAI_MODEL || "gpt-4o";
@@ -57686,6 +57704,10 @@ function getPublicModelDisplayName(model) {
57686
57704
  "claude-sonnet-4.5": "Orbit Sonnet 4.5",
57687
57705
  "claude-haiku-4.5": "Orbit Haiku 4.5",
57688
57706
  "gemini-3.1-pro-preview": "Gemini 3.1 Pro Preview",
57707
+ "gemini-3.6-flash": "Gemini 3.6 Flash",
57708
+ "gemini-3.5-flash-lite": "Gemini 3.5 Flash-Lite",
57709
+ "gemini-3.5-flash": "Gemini 3.5 Flash",
57710
+ "gemini-3.1-flash-lite": "Gemini 3.1 Flash-Lite",
57689
57711
  "gemini-3-flash-preview": "Gemini 3 Flash",
57690
57712
  "gemini-2.5-pro": "Gemini 2.5 Pro",
57691
57713
  "grok-code-fast-1": "Grok Code Fast 1"
@@ -57961,6 +57983,8 @@ var init_openaiContextWindows = __esm(() => {
57961
57983
  "google/gemini-2.0-flash": 1048576,
57962
57984
  "google/gemini-2.5-pro": 1048576,
57963
57985
  "gemini-3.1-pro-preview": 1048576,
57986
+ "gemini-3.6-flash": 1048576,
57987
+ "gemini-3.5-flash-lite": 1048576,
57964
57988
  "gemini-3.5-flash": 1048576,
57965
57989
  "gemini-3.1-flash-lite": 1048576,
57966
57990
  "gemini-2.0-flash": 1048576,
@@ -58011,6 +58035,8 @@ var init_openaiContextWindows = __esm(() => {
58011
58035
  "google/gemini-2.0-flash": 8192,
58012
58036
  "google/gemini-2.5-pro": 65536,
58013
58037
  "gemini-3.1-pro-preview": 65536,
58038
+ "gemini-3.6-flash": 65536,
58039
+ "gemini-3.5-flash-lite": 65536,
58014
58040
  "gemini-3.5-flash": 65536,
58015
58041
  "gemini-3.1-flash-lite": 65536,
58016
58042
  "gemini-2.0-flash": 8192,
@@ -83792,7 +83818,7 @@ async function printStartupScreen() {
83792
83818
  const sLen = ` ● ${sL} Ready — type /help to begin`.length;
83793
83819
  out.push(boxRow(sRow, W2, sLen));
83794
83820
  out.push(`${rgb(...BORDER)}╚${"═".repeat(W2 - 2)}╝${RESET}`);
83795
- out.push(` ${DIM}${rgb(...DIMCOL)}orbit-code ${RESET}${rgb(...ACCENT)}v${"0.1.39"}${RESET}`);
83821
+ out.push(` ${DIM}${rgb(...DIMCOL)}orbit-code ${RESET}${rgb(...ACCENT)}v${"0.1.41"}${RESET}`);
83796
83822
  out.push("");
83797
83823
  process.stdout.write(out.join(`
83798
83824
  `) + `
@@ -186106,8 +186132,23 @@ var init_toolArgumentNormalization = __esm(() => {
186106
186132
  // src/services/api/openaiShim.ts
186107
186133
  var exports_openaiShim = {};
186108
186134
  __export(exports_openaiShim, {
186135
+ geminiOmitsSamplingParams: () => geminiOmitsSamplingParams,
186109
186136
  createOpenAIShimClient: () => createOpenAIShimClient
186110
186137
  });
186138
+ function geminiOmitsSamplingParams(model) {
186139
+ const m = model.toLowerCase();
186140
+ if (!m.startsWith("gemini"))
186141
+ return false;
186142
+ const match = m.match(/gemini-(\d+\.\d+)/);
186143
+ if (!match)
186144
+ return false;
186145
+ const version2 = Number.parseFloat(match[1]);
186146
+ if (m.includes("flash-lite"))
186147
+ return version2 >= 3.5;
186148
+ if (m.includes("flash"))
186149
+ return version2 >= 3.6;
186150
+ return false;
186151
+ }
186111
186152
  function isGithubModelsMode() {
186112
186153
  return isEnvTruthy(process.env.ORBIT_CODE_USE_GITHUB);
186113
186154
  }
@@ -186793,10 +186834,12 @@ class OpenAIShimMessages {
186793
186834
  body.max_tokens = body.max_completion_tokens;
186794
186835
  delete body.max_completion_tokens;
186795
186836
  }
186796
- if (params.temperature !== undefined)
186797
- body.temperature = params.temperature;
186798
- if (params.top_p !== undefined)
186799
- body.top_p = params.top_p;
186837
+ if (!geminiOmitsSamplingParams(request.resolvedModel)) {
186838
+ if (params.temperature !== undefined)
186839
+ body.temperature = params.temperature;
186840
+ if (params.top_p !== undefined)
186841
+ body.top_p = params.top_p;
186842
+ }
186800
186843
  if (params.tools && params.tools.length > 0) {
186801
186844
  const converted = convertTools(params.tools);
186802
186845
  if (converted.length > 0) {
@@ -319931,16 +319974,16 @@ function getGeminiModelOptions() {
319931
319974
  descriptionForModel: "Gemini 3.1 Pro - most capable, for complex generative work"
319932
319975
  },
319933
319976
  {
319934
- value: "gemini-3.5-flash",
319935
- label: "Gemini 3.5 Flash",
319936
- description: "Gemini 3.5 Flash · Balanced for everyday tasks",
319937
- descriptionForModel: "Gemini 3.5 Flash - balanced, for everyday tasks"
319977
+ value: "gemini-3.6-flash",
319978
+ label: "Gemini 3.6 Flash",
319979
+ description: "Gemini 3.6 Flash · Balanced for everyday tasks",
319980
+ descriptionForModel: "Gemini 3.6 Flash - balanced, for everyday tasks"
319938
319981
  },
319939
319982
  {
319940
- value: "gemini-3.1-flash-lite",
319941
- label: "Gemini 3.1 Flash-Lite",
319942
- description: "Gemini 3.1 Flash-Lite · Fastest & lowest cost (default)",
319943
- descriptionForModel: "Gemini 3.1 Flash-Lite - fastest and cheapest, for reading/planning"
319983
+ value: "gemini-3.5-flash-lite",
319984
+ label: "Gemini 3.5 Flash-Lite",
319985
+ description: "Gemini 3.5 Flash-Lite · Fastest & lowest cost (default)",
319986
+ descriptionForModel: "Gemini 3.5 Flash-Lite - fastest and cheapest, for reading/planning"
319944
319987
  }
319945
319988
  ];
319946
319989
  }
@@ -334299,7 +334342,7 @@ function getAnthropicEnvMetadata() {
334299
334342
  function getBuildAgeMinutes() {
334300
334343
  if (false)
334301
334344
  ;
334302
- const buildTime = new Date("2026-07-16T10:32:35.333Z").getTime();
334345
+ const buildTime = new Date("2026-07-23T10:01:27.244Z").getTime();
334303
334346
  if (isNaN(buildTime))
334304
334347
  return;
334305
334348
  return Math.floor((Date.now() - buildTime) / 60000);
@@ -358716,7 +358759,7 @@ function buildPrimarySection() {
358716
358759
  }, undefined, false, undefined, this);
358717
358760
  return [{
358718
358761
  label: "Version",
358719
- value: "0.1.39"
358762
+ value: "0.1.41"
358720
358763
  }, {
358721
358764
  label: "Session name",
358722
358765
  value: nameValue
@@ -471025,7 +471068,7 @@ function WelcomeV2() {
471025
471068
  dimColor: true,
471026
471069
  children: [
471027
471070
  "v",
471028
- "0.1.39",
471071
+ "0.1.41",
471029
471072
  " "
471030
471073
  ]
471031
471074
  }, undefined, true, undefined, this)
@@ -471225,7 +471268,7 @@ function WelcomeV2() {
471225
471268
  dimColor: true,
471226
471269
  children: [
471227
471270
  "v",
471228
- "0.1.39",
471271
+ "0.1.41",
471229
471272
  " "
471230
471273
  ]
471231
471274
  }, undefined, true, undefined, this)
@@ -471451,7 +471494,7 @@ function AppleTerminalWelcomeV2(t0) {
471451
471494
  dimColor: true,
471452
471495
  children: [
471453
471496
  "v",
471454
- "0.1.39",
471497
+ "0.1.41",
471455
471498
  " "
471456
471499
  ]
471457
471500
  }, undefined, true, undefined, this);
@@ -471705,7 +471748,7 @@ function AppleTerminalWelcomeV2(t0) {
471705
471748
  dimColor: true,
471706
471749
  children: [
471707
471750
  "v",
471708
- "0.1.39",
471751
+ "0.1.41",
471709
471752
  " "
471710
471753
  ]
471711
471754
  }, undefined, true, undefined, this);
@@ -475730,6 +475773,250 @@ var init_aceSkills = __esm(() => {
475730
475773
  init_bundledSkills();
475731
475774
  });
475732
475775
 
475776
+ // src/utils/drawio/drawioFlow.ts
475777
+ function escapeXml2(s) {
475778
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
475779
+ }
475780
+ function labelValue(label) {
475781
+ return label.split(/\r?\n/).map(escapeXml2).join("&lt;br&gt;");
475782
+ }
475783
+ function laneHeight(name) {
475784
+ const n2 = name.toUpperCase();
475785
+ if (n2 === "CONSUMER")
475786
+ return 320;
475787
+ if (n2 === "MW" || n2 === "MIDDLEWARE")
475788
+ return 860;
475789
+ return 320;
475790
+ }
475791
+ function validateModel2(model) {
475792
+ if (!model.lanes?.length)
475793
+ throw new Error("FlowModel needs at least one lane.");
475794
+ if (!model.nodes?.length)
475795
+ throw new Error("FlowModel needs at least one node.");
475796
+ const laneSet = new Set(model.lanes);
475797
+ const ids = new Set;
475798
+ for (const n2 of model.nodes) {
475799
+ if (ids.has(n2.id))
475800
+ throw new Error(`Duplicate node id: ${n2.id}`);
475801
+ ids.add(n2.id);
475802
+ if (!laneSet.has(n2.lane))
475803
+ throw new Error(`Node "${n2.id}" is in unknown lane "${n2.lane}".`);
475804
+ }
475805
+ for (const e2 of model.edges ?? []) {
475806
+ if (!ids.has(e2.source))
475807
+ throw new Error(`Edge source "${e2.source}" is not a known node id.`);
475808
+ if (!ids.has(e2.target))
475809
+ throw new Error(`Edge target "${e2.target}" is not a known node id.`);
475810
+ }
475811
+ }
475812
+ function layout(model) {
475813
+ const laneBands = [];
475814
+ let y2 = 0;
475815
+ for (const name of model.lanes) {
475816
+ const h2 = laneHeight(name);
475817
+ laneBands.push({ name, y: y2, h: h2 });
475818
+ y2 += h2;
475819
+ }
475820
+ const pageH = y2;
475821
+ const bandOf = (lane) => laneBands.find((b) => b.name === lane);
475822
+ const rects = new Map;
475823
+ for (const band of laneBands) {
475824
+ const laneNodes = model.nodes.filter((n2) => n2.lane === band.name);
475825
+ const isMW = band.name.toUpperCase() === "MW" || band.name.toUpperCase() === "MIDDLEWARE";
475826
+ if (isMW) {
475827
+ let cy = band.y + 40;
475828
+ for (let i3 = 0;i3 < laneNodes.length; i3++) {
475829
+ const n2 = laneNodes[i3];
475830
+ const s = SIZE[n2.kind];
475831
+ const next = laneNodes[i3 + 1];
475832
+ if (n2.kind === "success" && next && next.kind === "error") {
475833
+ rects.set(n2.id, { x: NODE_X0, y: cy, w: s.w, h: s.h });
475834
+ const s2 = SIZE[next.kind];
475835
+ rects.set(next.id, { x: NODE_X0 + s.w + 90, y: cy, w: s2.w, h: s2.h });
475836
+ i3++;
475837
+ cy += Math.max(s.h, s2.h) + 55;
475838
+ } else {
475839
+ rects.set(n2.id, { x: NODE_X0, y: cy, w: s.w, h: s.h });
475840
+ cy += s.h + 55;
475841
+ }
475842
+ }
475843
+ } else {
475844
+ let cx = NODE_X0;
475845
+ const midY = band.y + band.h / 2;
475846
+ for (const n2 of laneNodes) {
475847
+ const s = SIZE[n2.kind];
475848
+ rects.set(n2.id, { x: cx, y: Math.round(midY - s.h / 2), w: s.w, h: s.h });
475849
+ cx += s.w + 70;
475850
+ }
475851
+ }
475852
+ }
475853
+ return { laneBands, rects, pageH };
475854
+ }
475855
+ function anchors(a2, b) {
475856
+ const ac = { x: a2.x + a2.w / 2, y: a2.y + a2.h / 2 };
475857
+ const bc = { x: b.x + b.w / 2, y: b.y + b.h / 2 };
475858
+ const dx = bc.x - ac.x;
475859
+ const dy = bc.y - ac.y;
475860
+ let ex, ey, nx, ny;
475861
+ if (Math.abs(dy) >= Math.abs(dx)) {
475862
+ if (dy >= 0) {
475863
+ ex = 0.5;
475864
+ ey = 1;
475865
+ nx = 0.5;
475866
+ ny = 0;
475867
+ } else {
475868
+ ex = 0.5;
475869
+ ey = 0;
475870
+ nx = 0.5;
475871
+ ny = 1;
475872
+ }
475873
+ } else if (dx >= 0) {
475874
+ ex = 1;
475875
+ ey = 0.5;
475876
+ nx = 0;
475877
+ ny = 0.5;
475878
+ } else {
475879
+ ex = 0;
475880
+ ey = 0.5;
475881
+ nx = 1;
475882
+ ny = 0.5;
475883
+ }
475884
+ return `exitX=${ex};exitY=${ey};exitDx=0;exitDy=0;entryX=${nx};entryY=${ny};entryDx=0;entryDy=0;`;
475885
+ }
475886
+ function generateDrawioFlow(model) {
475887
+ validateModel2(model);
475888
+ const { laneBands, rects, pageH } = layout(model);
475889
+ const cells = ['<mxCell id="0"/>', '<mxCell id="1" parent="0"/>'];
475890
+ laneBands.forEach((b, i3) => {
475891
+ cells.push(`<mxCell id="lane${i3}" value="${escapeXml2(b.name)}" style="${LANE_STYLE}" vertex="1" parent="1">` + `<mxGeometry x="0" y="${b.y}" width="${PAGE_W}" height="${b.h}" as="geometry"/></mxCell>`);
475892
+ });
475893
+ for (const n2 of model.nodes) {
475894
+ const r = rects.get(n2.id);
475895
+ const value = n2.kind === "end" ? "" : labelValue(n2.label);
475896
+ cells.push(`<mxCell id="${escapeXml2(n2.id)}" value="${value}" style="${STYLE[n2.kind]}" vertex="1" parent="1">` + `<mxGeometry x="${r.x}" y="${r.y}" width="${r.w}" height="${r.h}" as="geometry"/></mxCell>`);
475897
+ }
475898
+ model.edges?.forEach((e2, i3) => {
475899
+ const sr = rects.get(e2.source);
475900
+ const tr = rects.get(e2.target);
475901
+ const style = EDGE_STYLE + anchors(sr, tr);
475902
+ cells.push(`<mxCell id="e${i3}" value="${e2.label ? labelValue(e2.label) : ""}" style="${style}" edge="1" parent="1" source="${escapeXml2(e2.source)}" target="${escapeXml2(e2.target)}">` + `<mxGeometry relative="1" as="geometry"/></mxCell>`);
475903
+ });
475904
+ const name = escapeXml2(`${model.apiName} Integration Flow`);
475905
+ return `<mxfile host="app.diagrams.net" version="24.0.0">` + `<diagram name="${name}" id="flow">` + `<mxGraphModel dx="1200" dy="1500" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="${PAGE_W}" pageHeight="${pageH}" math="0" shadow="0">` + `<root>${cells.join("")}</root>` + `</mxGraphModel></diagram></mxfile>`;
475906
+ }
475907
+ var LANE_STYLE = "swimlane;html=1;horizontal=0;startSize=32;fillColor=#3FA34D;swimlaneFillColor=#FFFFFF;strokeColor=#000000;fontColor=#FFFFFF;fontStyle=1;fontSize=13;verticalAlign=middle;", STYLE, EDGE_STYLE = "edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=classic;strokeColor=#000000;fontColor=#000000;fontStyle=1;fontSize=11;", PAGE_W = 1090, LANE_TITLE = 32, NODE_X0, SIZE;
475908
+ var init_drawioFlow = __esm(() => {
475909
+ STYLE = {
475910
+ action: "shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fillColor=#7EA6E0;strokeColor=#3B5A9A;fontColor=#000000;fontStyle=1;",
475911
+ success: "shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fillColor=#8FCB5E;strokeColor=#5E8A34;fontColor=#000000;fontStyle=1;",
475912
+ error: "shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fillColor=#FF2020;strokeColor=#B20000;fontColor=#FFFFFF;fontStyle=1;",
475913
+ decision: "rhombus;whiteSpace=wrap;html=1;fillColor=#F8CECC;strokeColor=#D48A8A;fontColor=#000000;fontStyle=1;",
475914
+ start: "ellipse;whiteSpace=wrap;html=1;fillColor=#FFF176;strokeColor=#B8A400;fontColor=#000000;fontStyle=1;",
475915
+ end: "ellipse;shape=endState;fillColor=#000000;strokeColor=#FF0000;strokeWidth=2;"
475916
+ };
475917
+ NODE_X0 = LANE_TITLE + 40;
475918
+ SIZE = {
475919
+ start: { w: 90, h: 50 },
475920
+ end: { w: 30, h: 30 },
475921
+ action: { w: 190, h: 60 },
475922
+ success: { w: 200, h: 64 },
475923
+ error: { w: 200, h: 64 },
475924
+ decision: { w: 180, h: 90 }
475925
+ };
475926
+ });
475927
+
475928
+ // src/skills/bundled/drawio.ts
475929
+ import { writeFileSync as writeFileSync5 } from "fs";
475930
+ import { join as join127 } from "path";
475931
+ function textBlock(text) {
475932
+ return [{ type: "text", text }];
475933
+ }
475934
+ function sanitizeStem(s) {
475935
+ return s.trim().replace(/\.docx$/i, "").replace(/[^A-Za-z0-9._-]+/g, "_").replace(/^_+|_+$/g, "") || "API";
475936
+ }
475937
+ function handle(args) {
475938
+ const trimmed = args.trim();
475939
+ if (!trimmed || trimmed.toLowerCase() === "help")
475940
+ return HELP;
475941
+ let model;
475942
+ try {
475943
+ model = JSON.parse(trimmed);
475944
+ } catch (e2) {
475945
+ return `/drawio expects a single JSON FlowModel argument, but JSON.parse failed: ${e2.message}
475946
+
475947
+ ${HELP}`;
475948
+ }
475949
+ let xml;
475950
+ try {
475951
+ xml = generateDrawioFlow(model);
475952
+ } catch (e2) {
475953
+ return `The flow model is invalid: ${e2.message}
475954
+
475955
+ Fix the model (check node ids, lanes, and edge endpoints) and call /drawio again.`;
475956
+ }
475957
+ const stem = sanitizeStem(model.fileStem || model.apiName || "API");
475958
+ const filename = `${stem}_Integration_Flow.drawio`;
475959
+ try {
475960
+ writeFileSync5(join127(process.cwd(), filename), xml, "utf8");
475961
+ } catch (e2) {
475962
+ return `Generated valid diagram XML but could not write ${filename}: ${e2.message}.
475963
+ Save this content manually as ${filename}:
475964
+
475965
+ ${xml}`;
475966
+ }
475967
+ return `✓ Integration-flow diagram written → ${filename}
475968
+
475969
+ lanes: ${model.lanes.join(" / ")}
475970
+ nodes: ${model.nodes.length} edges: ${model.edges?.length ?? 0}
475971
+
475972
+ Opens in diagrams.net (app.diagrams.net). Tell the user the file was created at ${filename} and summarize the flow branches it drew (token/cache/success-error) based on the model.`;
475973
+ }
475974
+ function registerDrawioSkill() {
475975
+ registerBundledSkill({
475976
+ name: "drawio",
475977
+ description: "Render an integration-flow semantic model (JSON: lanes/nodes/edges) into a .drawio activity diagram in the BIDAYA house style, written next to the other artifacts. Deterministic layout + XML; used by /lld to emit the Integration Service Flow diagram.",
475978
+ whenToUse: "After extracting an integration-flow semantic model from an LLD (usually via /lld ... diagram), to write the .drawio diagram file. Pass the JSON FlowModel as the argument.",
475979
+ argumentHint: "<json flow model>",
475980
+ userInvocable: true,
475981
+ allowedTools: [],
475982
+ async getPromptForCommand(args) {
475983
+ try {
475984
+ return textBlock(handle(args));
475985
+ } catch (e2) {
475986
+ return textBlock(`/drawio error: ${e2.message}`);
475987
+ }
475988
+ }
475989
+ });
475990
+ }
475991
+ var HELP = `# /drawio — render an integration-flow semantic model to a .drawio diagram
475992
+
475993
+ Usage:
475994
+ /drawio <json flow model>
475995
+
475996
+ The argument is a JSON FlowModel:
475997
+ {
475998
+ "apiName": "Commodity API",
475999
+ "fileStem": "LLD_CommodityAPI", // optional; output = <fileStem>_Integration_Flow.drawio
476000
+ "lanes": ["CONSUMER", "MW", "Eiger"], // top→bottom; MW gets the tallest lane
476001
+ "nodes": [
476002
+ { "id": "start", "kind": "start", "lane": "CONSUMER", "label": "START" },
476003
+ { "id": "send", "kind": "action", "lane": "CONSUMER", "label": "send request to MW" },
476004
+ { "id": "dec", "kind": "decision","lane": "MW", "label": "Valid access token?" },
476005
+ { "id": "ok", "kind": "success", "lane": "MW", "label": "Map success..." },
476006
+ { "id": "err", "kind": "error", "lane": "MW", "label": "Map error..." },
476007
+ { "id": "end", "kind": "end", "lane": "CONSUMER", "label": "" }
476008
+ ],
476009
+ "edges": [ { "source": "start", "target": "send", "label": "" } ]
476010
+ }
476011
+
476012
+ kind ∈ start | action | decision | success | error | end. This skill lays out the nodes and writes
476013
+ the .drawio file in the BIDAYA house style (green lanes, blue parallelograms, pink diamonds,
476014
+ green/red mapping boxes, START ellipse, red-ringed final node).`;
476015
+ var init_drawio = __esm(() => {
476016
+ init_bundledSkills();
476017
+ init_drawioFlow();
476018
+ });
476019
+
475733
476020
  // src/utils/docx.ts
475734
476021
  import { readFileSync as readFileSync10 } from "fs";
475735
476022
  function escapeReg(s) {
@@ -475900,7 +476187,7 @@ async function extractDocxText(filePath, maxChars = 60000) {
475900
476187
  var init_docx = () => {};
475901
476188
 
475902
476189
  // src/skills/bundled/lld.ts
475903
- function textBlock(text) {
476190
+ function textBlock2(text) {
475904
476191
  return [{ type: "text", text }];
475905
476192
  }
475906
476193
  function parseArgs(args) {
@@ -475920,22 +476207,90 @@ function parseArgs(args) {
475920
476207
  rest = trimmed;
475921
476208
  }
475922
476209
  }
475923
- const t = rest.match(/\b(contract|api|both)\b/i)?.[1]?.toLowerCase();
475924
- const target = t === "contract" || t === "api" ? t : "both";
475925
- return { path: path20.replace(/[.,;]$/, ""), target };
476210
+ const kw = rest.toLowerCase();
476211
+ const c6 = /\bcontract\b/.test(kw);
476212
+ const a2 = /\bapi\b/.test(kw);
476213
+ const d = /\b(diagram|drawio|flow)\b/.test(kw);
476214
+ const both = /\bboth\b/.test(kw);
476215
+ const all4 = /\ball\b/.test(kw);
476216
+ const want = all4 || !c6 && !a2 && !d && !both ? { contract: true, api: true, diagram: true } : { contract: c6 || both, api: a2 || both, diagram: d };
476217
+ return { path: path20.replace(/[.,;]$/, ""), want };
475926
476218
  }
475927
- function buildPrompt(path20, content, target) {
475928
- const gen = target === "contract" ? "the CONTRACT only (invoke /api-contract)" : target === "api" ? "the GATEWAY API only (invoke /apic-api)" : "BOTH the contract (/api-contract) and the gateway API (/apic-api)";
475929
- return `You are turning an LLD (Low-Level Design) Word document into APIC artifacts. The full LLD text
475930
- below was extracted from ${path20} (paragraphs as text, tables as markdown). Requested output: ${gen}.
475931
-
475932
- ════════════════════ EXTRACTED LLD ════════════════════
475933
- ${content}
475934
- ════════════════════ END LLD ════════════════════
475935
-
475936
- Do this, in order:
475937
-
475938
- 1. EXTRACT the API spec from the LLD above, using this house-template map (sections/tables → fields):
476219
+ function buildPrompt(path20, content, want) {
476220
+ const parts = [];
476221
+ if (want.contract)
476222
+ parts.push("the CONTRACT (invoke /api-contract)");
476223
+ if (want.api)
476224
+ parts.push("the GATEWAY API (invoke /apic-api)");
476225
+ if (want.diagram)
476226
+ parts.push("the INTEGRATION-FLOW DIAGRAM (build a flow model, then invoke /drawio)");
476227
+ const gen = parts.join(", ");
476228
+ const diagramSection = want.diagram ? `
476229
+
476230
+ ── INTEGRATION-FLOW DIAGRAM ──
476231
+ Also produce the "Integration Service Flow" diagram (the LLD's Figure 1) as a .drawio file. Build a
476232
+ SEMANTIC flow model from the SAME extracted LLD, then invoke the /drawio skill with it as JSON —
476233
+ /drawio does the layout + XML + file write; you only supply the model.
476234
+
476235
+ Model shape (pass as one JSON object to /drawio):
476236
+ { "apiName": "...", "fileStem": "<the LLD file name, no extension>",
476237
+ "lanes": ["CONSUMER", "MW", "<Provider>"], // top→bottom; MW is the middle/tallest lane
476238
+ "nodes": [ { "id","kind","lane","label" } ], // kind ∈ start|action|decision|success|error|end
476239
+ "edges": [ { "source","target","label" } ] }
476240
+
476241
+ Build the flow with these rules — include a branch ONLY when the LLD supports it:
476242
+ CONSUMER lane: start "START" → action "send request to MW"; action "Receive MW response" → end node.
476243
+ MW lane:
476244
+ - If the MW caches the RESPONSE (LLD says so; if it says "Cache: Not applicable", OMIT this):
476245
+ decision "Check cache (payload in last N min)?" → True path returns a green success
476246
+ "get response from cache and return to consumer" → Receive MW response; False path continues.
476247
+ - If auth is TOKEN-BASED (the MW calls an access-token/login op and caches the JWT until exp):
476248
+ decision "Valid access token in cache? (exp not passed)" → True → action "send request to
476249
+ <Provider> (<operation>)"; False → (Provider lane) action "invoke <Provider> Access Token
476250
+ service (get JWT, cache until exp)" → back to "send request to <Provider>".
476251
+ If NO auth / static keys: OMIT the token decision and the Access Token node entirely.
476252
+ - action "send request to <Provider>" → (Provider lane) action "invoke <Provider> <operation>".
476253
+ - provider returns → action "MW will receive BE Response".
476254
+ - decision "Check body status (<the LLD's actual success rule, e.g. eigerResultCode = 200>)?":
476255
+ success edge → green success "Map the success response and send to consumer" → Receive MW response
476256
+ error edge → red error "Map the error response and send to consumer" → Receive MW response
476257
+ <Provider> lane: holds "invoke ... Access Token service" (only if token-based) and
476258
+ "invoke ... <operation>"; the operation's "2xx"/"non-2xx" (or Success/Failure) edges return to
476259
+ "MW will receive BE Response".
476260
+
476261
+ ONE diagram per LLD representing the common MW pattern. If operations diverge (e.g. one cached, one
476262
+ not), pick the richest common flow and label the operation box "<op1> | <op2>". Use success/error
476263
+ mapping boxes for the mapping steps. Every edge's source/target must be a node id you defined.
476264
+ ` : "";
476265
+ const onlyDiagram = want.diagram && !want.contract && !want.api;
476266
+ const asks = [];
476267
+ if (want.contract || want.api)
476268
+ asks.push("OpenAPI version — 2.0 or 3.0");
476269
+ if (want.contract)
476270
+ asks.push("inbound consumer auth scheme (basic / apikey / oauth2)", "API host (e.g. api.example.com)");
476271
+ if (want.api)
476272
+ asks.push("integration pattern — wrapper (thin proxy over an ACE/webMethods service) vs backend (APIC calls the raw backend)", "JWT validation on/off (and the crypto object name if on)", "the backend target-url variable / endpoint");
476273
+ const asksBlock = asks.length ? `Then ask the user ONLY for these unguessables (they are needed for the requested output):
476274
+ - ${asks.join(`
476275
+ - `)}
476276
+ NEVER fabricate hosts, crypto objects, scopes, or business fields — ask, or use clearly-marked
476277
+ CHANGEME placeholders and list them.` : `Do NOT ask for any unguessables. A diagram-only request is fully derived from the LLD (the
476278
+ operations, provider, whether auth is token-based, cache behaviour, and the success rule are all in
476279
+ the document). Do NOT ask about OpenAPI version, host, auth scheme, JWT, crypto, or backend URLs —
476280
+ none of those are needed to draw the flow.`;
476281
+ const notRequested = [];
476282
+ if (!want.contract)
476283
+ notRequested.push("/api-contract");
476284
+ if (!want.api)
476285
+ notRequested.push("/apic-api");
476286
+ if (!want.diagram)
476287
+ notRequested.push("/drawio");
476288
+ const scopeLine = `Produce ONLY: ${gen}.` + (notRequested.length ? ` Do NOT invoke ${notRequested.join(" or ")}, and do NOT ask for details only those skills need.` : "");
476289
+ const extractStep = onlyDiagram ? `1. EXTRACT only the FLOW-relevant facts from the LLD (you do NOT need the request/response field
476290
+ models for a diagram): the operation(s) (name, verb, gateway endpoint); the provider(s); whether the
476291
+ MW obtains and CACHES an access token (→ token-based auth) or uses static/no auth; whether the MW
476292
+ caches the RESPONSE (or says "Cache: Not applicable"); and the success rule (e.g. HTTP 200, or a body
476293
+ status code like eigerResultCode = 200).` : `1. EXTRACT the API spec from the LLD above, using this house-template map (sections/tables → fields):
475939
476294
  - Introduction (Purpose / Scope) → API title + description.
475940
476295
  - "Integration flow (<op>)" → its "API Gateway endpoint" and "Method" → the operation path + verb.
475941
476296
  - "<op> Request" table → request model. Columns are typically Field | Type | Occurrence | Length |
@@ -475947,30 +476302,42 @@ Do this, in order:
475947
476302
  - "Annex / Provider" (endpoints, auth) → the backend/provider endpoint(s) and their auth.
475948
476303
  - Integration pattern: if the middleware is an existing ACE/webMethods service that already returns
475949
476304
  the response envelope, it is a **wrapper**; if APIC calls a raw backend and must build the
475950
- envelope, it is **backend**. State which and why.
476305
+ envelope, it is **backend**. State which and why.`;
476306
+ const genBullets = [];
476307
+ if (want.contract)
476308
+ genBullets.push(` - Contract → invoke /api-contract with the API name, host, security, and the full request/response/error models.`);
476309
+ if (want.api)
476310
+ genBullets.push(` - Gateway API → invoke /apic-api per operation with the verb, basePath, explicit path, --pattern, backend target-url, and flags.`);
476311
+ if (want.diagram)
476312
+ genBullets.push(` - Integration-flow diagram → build the JSON flow model per the DIAGRAM rules above and invoke /drawio. Report the .drawio file it wrote.`);
476313
+ return `You are turning an LLD (Low-Level Design) Word document into APIC artifacts. The full LLD text
476314
+ below was extracted from ${path20} (paragraphs as text, tables as markdown).
476315
+
476316
+ **SCOPE: ${scopeLine}**${diagramSection}
476317
+
476318
+ ════════════════════ EXTRACTED LLD ════════════════════
476319
+ ${content}
476320
+ ════════════════════ END LLD ════════════════════
476321
+
476322
+ Do this, in order:
476323
+
476324
+ ${extractStep}
475951
476325
 
475952
- 2. ECHO a concise EXTRACTION SUMMARY to the user FIRST (do NOT generate yet): API name, pattern,
475953
- each operation (verb + path), request/response field lists, error codes, backend endpoint, and the
475954
- fields you could NOT determine. Then ask for the unguessables only: OpenAPI 2.0 vs 3.0; inbound
475955
- consumer auth (basic/apikey/oauth2); host; and (for /apic-api) JWT on/off + crypto object and the
475956
- backend target-url variable. NEVER fabricate hosts, crypto objects, scopes, or business fields — ask
475957
- or use clearly-marked CHANGEME placeholders and list them.
476326
+ 2. ECHO a concise EXTRACTION SUMMARY to the user FIRST (do NOT generate yet), covering only what the
476327
+ requested output needs. ${asksBlock}
475958
476328
 
475959
476329
  3. After the user confirms/corrects, GENERATE ${gen}:
475960
- - Contract → invoke the /api-contract skill, passing the API name, host, security, and the full
475961
- request/response/error models you extracted.
475962
- - Gateway API → invoke the /apic-api skill, passing the operation (name, verb, basePath, explicit
475963
- path), the chosen --pattern (wrapper vs backend), the backend target-url, and the flags. One
475964
- /apic-api call per operation.
476330
+ ${genBullets.join(`
476331
+ `)}
475965
476332
  Reuse the values from the extraction summary verbatim — do not re-derive or drop fields.
475966
476333
 
475967
476334
  Ground everything in the extracted LLD above; if the LLD does not state something, say so rather than
475968
476335
  inventing it.`;
475969
476336
  }
475970
- async function handle(args) {
475971
- const { path: path20, target } = parseArgs(args);
476337
+ async function handle2(args) {
476338
+ const { path: path20, want } = parseArgs(args);
475972
476339
  if (!path20)
475973
- return HELP;
476340
+ return HELP2;
475974
476341
  let content;
475975
476342
  try {
475976
476343
  content = await extractDocxText(path20);
@@ -475983,33 +476350,34 @@ Give the full path to a .docx file, e.g.
475983
476350
  if (!content.trim()) {
475984
476351
  return `The LLD at "${path20}" extracted no text (it may be image-only or empty). I can't generate from it — confirm the file, or paste the request/response models directly.`;
475985
476352
  }
475986
- return buildPrompt(path20, content, target);
476353
+ return buildPrompt(path20, content, want);
475987
476354
  }
475988
476355
  function registerLldSkill() {
475989
476356
  registerBundledSkill({
475990
476357
  name: "lld",
475991
476358
  description: "Read an LLD (.docx) Word document — paragraphs and tables — extract the API spec against the house template, confirm it, then generate the contract-only OpenAPI (/api-contract) and/or the APIC gateway API (/apic-api) from it.",
475992
476359
  whenToUse: "When the user points at an LLD .docx and wants the APIC contract and/or gateway API generated from it (LLD → YAML).",
475993
- argumentHint: '"<path-to-LLD.docx>" [contract|api|both]',
476360
+ argumentHint: '"<path-to-LLD.docx>" [contract|api|diagram|both|all]',
475994
476361
  userInvocable: true,
475995
476362
  allowedTools: ["Read", "Glob", "Grep"],
475996
476363
  async getPromptForCommand(args) {
475997
476364
  try {
475998
- return textBlock(await handle(args));
476365
+ return textBlock2(await handle2(args));
475999
476366
  } catch (e2) {
476000
- return textBlock(`/lld error: ${e2.message}`);
476367
+ return textBlock2(`/lld error: ${e2.message}`);
476001
476368
  }
476002
476369
  }
476003
476370
  });
476004
476371
  }
476005
- var HELP = `# /lld — read an LLD (.docx) and generate the APIC contract and/or gateway API
476372
+ var HELP2 = `# /lld — read an LLD (.docx) and generate APIC contract / gateway API / flow diagram
476006
476373
 
476007
476374
  Usage:
476008
- /lld "<path-to-LLD.docx>" [contract|api|both]
476375
+ /lld "<path-to-LLD.docx>" [contract] [api] [diagram] | both | all
476009
476376
 
476010
- - contract → generate the contract-only OpenAPI via /api-contract
476011
- - api → generate the gateway implementation via /apic-api
476012
- - both generate both (default)
476377
+ - contract → contract-only OpenAPI via /api-contract
476378
+ - api → gateway implementation via /apic-api
476379
+ - diagram the Integration Service Flow .drawio via /drawio
476380
+ - both → contract + api ; all (or no keyword) → contract + api + diagram
476013
476381
 
476014
476382
  Reads the Word LLD (paragraphs + tables), extracts the API spec against the house template,
476015
476383
  shows you an extraction summary to confirm, then hands off to the generator skill(s).`;
@@ -510649,7 +511017,7 @@ ${declareVars || " -- (no parameters)"}${resultHandling}`;
510649
511017
  }
510650
511018
 
510651
511019
  // src/skills/bundled/sql.ts
510652
- function textBlock2(text) {
511020
+ function textBlock3(text) {
510653
511021
  return [{ type: "text", text }];
510654
511022
  }
510655
511023
  function parseConnectArgs(args) {
@@ -510888,22 +511256,22 @@ Do this, in order:
510888
511256
 
510889
511257
  Data-handling notice (state once): these are REAL values from the connected database and may include personal/production data. Return them as-is; never fabricate. If a SELECT returns no rows, say so plainly — for a happy case it means no qualifying data exists; do not invent a row. If the app calls no stored procedures at all, build the input body from the XSD types alone and clearly mark those values as synthetic (no DB row backs them).`;
510890
511258
  }
510891
- async function handle2(args) {
511259
+ async function handle3(args) {
510892
511260
  const trimmed = args.trim();
510893
511261
  if (!trimmed)
510894
- return HELP2;
511262
+ return HELP3;
510895
511263
  const firstTok = trimmed.split(/\s+/)[0].toLowerCase();
510896
511264
  const restStr = trimmed.slice(trimmed.split(/\s+/)[0].length).trim();
510897
511265
  switch (firstTok) {
510898
511266
  case "help":
510899
- return HELP2;
511267
+ return HELP3;
510900
511268
  case "connect": {
510901
511269
  const parsed = parseConnectArgs(restStr);
510902
511270
  const missing = ["server", "database", "user", "password"].filter((k) => !parsed[k]);
510903
511271
  if (missing.length > 0)
510904
511272
  return `Missing required field(s): ${missing.join(", ")}.
510905
511273
 
510906
- ${HELP2}`;
511274
+ ${HELP3}`;
510907
511275
  const conn2 = parsed;
510908
511276
  const saved = saveSqlConnection(conn2);
510909
511277
  let testMsg;
@@ -511031,14 +511399,14 @@ function registerSqlSkill() {
511031
511399
  allowedTools: ["Read", "Glob", "Grep"],
511032
511400
  async getPromptForCommand(args) {
511033
511401
  try {
511034
- return textBlock2(await handle2(args));
511402
+ return textBlock3(await handle3(args));
511035
511403
  } catch (e2) {
511036
- return textBlock2(`/sql error: ${e2.message}`);
511404
+ return textBlock3(`/sql error: ${e2.message}`);
511037
511405
  }
511038
511406
  }
511039
511407
  });
511040
511408
  }
511041
- var HELP2, GROUND = `
511409
+ var HELP3, GROUND = `
511042
511410
 
511043
511411
  IMPORTANT: The metadata above is the ONLY database information you have — you cannot query the DB yourself. State only what appears above; never invent, guess, or "fill in" parameters, columns, types, or procedures. If something is not shown, say it is not shown.`, STOPWORDS;
511044
511412
  var init_sql = __esm(() => {
@@ -511046,7 +511414,7 @@ var init_sql = __esm(() => {
511046
511414
  init_connectionStore();
511047
511415
  init_mssqlClient();
511048
511416
  init_spMetadata();
511049
- HELP2 = `# /sql — SQL Server helper (native connection)
511417
+ HELP3 = `# /sql — SQL Server helper (native connection)
511050
511418
 
511051
511419
  Subcommands (also understands plain English, e.g. "/sql details of the SP Get_UserInformation"):
511052
511420
  - \`/sql connect server=HOST database=DB user=USER password=PASS [port=1433] [encrypt=false]\` — save the connection once (OS secure vault; password never written to disk in plaintext).
@@ -511610,6 +511978,7 @@ function initBundledSkills() {
511610
511978
  registerAceSkills();
511611
511979
  registerSqlSkill();
511612
511980
  registerLldSkill();
511981
+ registerDrawioSkill();
511613
511982
  registerUpdateConfigSkill();
511614
511983
  if (false) {}
511615
511984
  if (false) {}
@@ -511624,6 +511993,7 @@ function initBundledSkills() {
511624
511993
  var init_bundled = __esm(() => {
511625
511994
  init_setup2();
511626
511995
  init_aceSkills();
511996
+ init_drawio();
511627
511997
  init_lld();
511628
511998
  init_orbitInChrome();
511629
511999
  init_sql();
@@ -512518,9 +512888,9 @@ var init_doctor3 = __esm(() => {
512518
512888
 
512519
512889
  // src/utils/releaseNotes.ts
512520
512890
  import { mkdir as mkdir36, readFile as readFile40, writeFile as writeFile37 } from "fs/promises";
512521
- import { dirname as dirname56, join as join127 } from "path";
512891
+ import { dirname as dirname56, join as join128 } from "path";
512522
512892
  function getChangelogCachePath() {
512523
- return join127(getOrbitConfigHomeDir(), "cache", "changelog.md");
512893
+ return join128(getOrbitConfigHomeDir(), "cache", "changelog.md");
512524
512894
  }
512525
512895
  async function migrateChangelogFromConfig() {
512526
512896
  const config3 = getGlobalConfig();
@@ -512659,12 +513029,12 @@ var init_releaseNotes = __esm(() => {
512659
513029
  });
512660
513030
 
512661
513031
  // src/utils/errorLogSink.ts
512662
- import { dirname as dirname57, join as join128 } from "path";
513032
+ import { dirname as dirname57, join as join129 } from "path";
512663
513033
  function getErrorsPath() {
512664
- return join128(CACHE_PATHS.errors(), DATE + ".jsonl");
513034
+ return join129(CACHE_PATHS.errors(), DATE + ".jsonl");
512665
513035
  }
512666
513036
  function getMCPLogsPath(serverName) {
512667
- return join128(CACHE_PATHS.mcpLogs(serverName), DATE + ".jsonl");
513037
+ return join129(CACHE_PATHS.mcpLogs(serverName), DATE + ".jsonl");
512668
513038
  }
512669
513039
  function createJsonlWriter(options2) {
512670
513040
  const writer = createBufferedWriter(options2);
@@ -513004,7 +513374,7 @@ var init_sessionMemory = __esm(() => {
513004
513374
  // src/utils/iTermBackup.ts
513005
513375
  import { copyFile as copyFile10, stat as stat41 } from "fs/promises";
513006
513376
  import { homedir as homedir37 } from "os";
513007
- import { join as join129 } from "path";
513377
+ import { join as join130 } from "path";
513008
513378
  function markITerm2SetupComplete() {
513009
513379
  saveGlobalConfig((current) => ({
513010
513380
  ...current,
@@ -513019,7 +513389,7 @@ function getIterm2RecoveryInfo() {
513019
513389
  };
513020
513390
  }
513021
513391
  function getITerm2PlistPath() {
513022
- return join129(homedir37(), "Library", "Preferences", "com.googlecode.iterm2.plist");
513392
+ return join130(homedir37(), "Library", "Preferences", "com.googlecode.iterm2.plist");
513023
513393
  }
513024
513394
  async function checkAndRestoreITerm2Backup() {
513025
513395
  const { inProgress, backupPath } = getIterm2RecoveryInfo();
@@ -513850,14 +514220,14 @@ __export(exports_orbitDesktop, {
513850
514220
  });
513851
514221
  import { readdir as readdir27, readFile as readFile41, stat as stat42 } from "fs/promises";
513852
514222
  import { homedir as homedir38 } from "os";
513853
- import { join as join130 } from "path";
514223
+ import { join as join131 } from "path";
513854
514224
  async function getOrbitDesktopConfigPath() {
513855
514225
  const platform6 = getPlatform();
513856
514226
  if (!SUPPORTED_PLATFORMS.includes(platform6)) {
513857
514227
  throw new Error(`Unsupported platform: ${platform6} - Orbit Desktop integration only works on macOS and WSL.`);
513858
514228
  }
513859
514229
  if (platform6 === "macos") {
513860
- return join130(homedir38(), "Library", "Application Support", "Orbit", "orbit_desktop_config.json");
514230
+ return join131(homedir38(), "Library", "Application Support", "Orbit", "orbit_desktop_config.json");
513861
514231
  }
513862
514232
  const windowsHome = process.env.USERPROFILE ? process.env.USERPROFILE.replace(/\\/g, "/") : null;
513863
514233
  if (windowsHome) {
@@ -513876,7 +514246,7 @@ async function getOrbitDesktopConfigPath() {
513876
514246
  if (user.name === "Public" || user.name === "Default" || user.name === "Default User" || user.name === "All Users") {
513877
514247
  continue;
513878
514248
  }
513879
- const potentialConfigPath = join130(usersDir, user.name, "AppData", "Roaming", "Orbit", "orbit_desktop_config.json");
514249
+ const potentialConfigPath = join131(usersDir, user.name, "AppData", "Roaming", "Orbit", "orbit_desktop_config.json");
513880
514250
  try {
513881
514251
  await stat42(potentialConfigPath);
513882
514252
  return potentialConfigPath;
@@ -517991,7 +518361,7 @@ var init_bridgeConfig = __esm(() => {
517991
518361
  // src/bridge/inboundAttachments.ts
517992
518362
  import { randomUUID as randomUUID47 } from "crypto";
517993
518363
  import { mkdir as mkdir37, writeFile as writeFile39 } from "fs/promises";
517994
- import { basename as basename52, join as join131 } from "path";
518364
+ import { basename as basename52, join as join132 } from "path";
517995
518365
  function debug(msg) {
517996
518366
  logForDebugging2(`[bridge:inbound-attach] ${msg}`);
517997
518367
  }
@@ -518007,7 +518377,7 @@ function sanitizeFileName(name) {
518007
518377
  return base2 || "attachment";
518008
518378
  }
518009
518379
  function uploadsDir() {
518010
- return join131(getOrbitConfigHomeDir(), "uploads", getSessionId());
518380
+ return join132(getOrbitConfigHomeDir(), "uploads", getSessionId());
518011
518381
  }
518012
518382
  async function resolveOne(att) {
518013
518383
  const token = getBridgeAccessToken();
@@ -518036,7 +518406,7 @@ async function resolveOne(att) {
518036
518406
  const safeName = sanitizeFileName(att.file_name);
518037
518407
  const prefix = (att.file_uuid.slice(0, 8) || randomUUID47().slice(0, 8)).replace(/[^a-zA-Z0-9_-]/g, "_");
518038
518408
  const dir = uploadsDir();
518039
- const outPath = join131(dir, `${prefix}-${safeName}`);
518409
+ const outPath = join132(dir, `${prefix}-${safeName}`);
518040
518410
  try {
518041
518411
  await mkdir37(dir, { recursive: true });
518042
518412
  await writeFile39(outPath, data);
@@ -518136,7 +518506,7 @@ var init_sessionUrl = __esm(() => {
518136
518506
 
518137
518507
  // src/utils/plugins/zipCacheAdapters.ts
518138
518508
  import { readFile as readFile42 } from "fs/promises";
518139
- import { join as join132 } from "path";
518509
+ import { join as join133 } from "path";
518140
518510
  async function readZipCacheKnownMarketplaces() {
518141
518511
  try {
518142
518512
  const content = await readFile42(getZipCacheKnownMarketplacesPath(), "utf-8");
@@ -518161,13 +518531,13 @@ async function saveMarketplaceJsonToZipCache(marketplaceName, installLocation) {
518161
518531
  const content = await readMarketplaceJsonContent(installLocation);
518162
518532
  if (content !== null) {
518163
518533
  const relPath = getMarketplaceJsonRelativePath(marketplaceName);
518164
- await atomicWriteToZipCache(join132(zipCachePath, relPath), content);
518534
+ await atomicWriteToZipCache(join133(zipCachePath, relPath), content);
518165
518535
  }
518166
518536
  }
518167
518537
  async function readMarketplaceJsonContent(dir) {
518168
518538
  const candidates = [
518169
- join132(dir, ".orbit-plugin", "marketplace.json"),
518170
- join132(dir, "marketplace.json"),
518539
+ join133(dir, ".orbit-plugin", "marketplace.json"),
518540
+ join133(dir, "marketplace.json"),
518171
518541
  dir
518172
518542
  ];
518173
518543
  for (const candidate of candidates) {
@@ -519211,9 +519581,9 @@ __export(exports_bridgePointer, {
519211
519581
  BRIDGE_POINTER_TTL_MS: () => BRIDGE_POINTER_TTL_MS
519212
519582
  });
519213
519583
  import { mkdir as mkdir38, readFile as readFile43, stat as stat44, unlink as unlink23, writeFile as writeFile40 } from "fs/promises";
519214
- import { dirname as dirname58, join as join133 } from "path";
519584
+ import { dirname as dirname58, join as join134 } from "path";
519215
519585
  function getBridgePointerPath(dir) {
519216
- return join133(getProjectsDir(), sanitizePath2(dir), "bridge-pointer.json");
519586
+ return join134(getProjectsDir(), sanitizePath2(dir), "bridge-pointer.json");
519217
519587
  }
519218
519588
  async function writeBridgePointer(dir, pointer) {
519219
519589
  const path20 = getBridgePointerPath(dir);
@@ -523082,7 +523452,7 @@ ${m.text}
523082
523452
  let bridgeFailureDetail;
523083
523453
  try {
523084
523454
  const { initReplBridge: initReplBridge2 } = await Promise.resolve().then(() => (init_initReplBridge(), exports_initReplBridge));
523085
- const handle3 = await initReplBridge2({
523455
+ const handle4 = await initReplBridge2({
523086
523456
  onInboundMessage(msg) {
523087
523457
  const fields = extractInboundMessageFields(msg);
523088
523458
  if (!fields)
@@ -523135,21 +523505,21 @@ ${m.text}
523135
523505
  },
523136
523506
  initialMessages: mutableMessages.length > 0 ? mutableMessages : undefined
523137
523507
  });
523138
- if (!handle3) {
523508
+ if (!handle4) {
523139
523509
  sendControlResponseError(message, bridgeFailureDetail ?? "Remote Control initialization failed");
523140
523510
  } else {
523141
- bridgeHandle = handle3;
523511
+ bridgeHandle = handle4;
523142
523512
  bridgeLastForwardedIndex = mutableMessages.length;
523143
523513
  structuredIO.setOnControlRequestSent((request) => {
523144
- handle3.sendControlRequest(request);
523514
+ handle4.sendControlRequest(request);
523145
523515
  });
523146
523516
  structuredIO.setOnControlRequestResolved((requestId) => {
523147
- handle3.sendControlCancelRequest(requestId);
523517
+ handle4.sendControlCancelRequest(requestId);
523148
523518
  });
523149
523519
  sendControlResponseSuccess(message, {
523150
- session_url: getRemoteSessionUrl(handle3.bridgeSessionId, handle3.sessionIngressUrl),
523151
- connect_url: buildBridgeConnectUrl(handle3.environmentId, handle3.sessionIngressUrl),
523152
- environment_id: handle3.environmentId
523520
+ session_url: getRemoteSessionUrl(handle4.bridgeSessionId, handle4.sessionIngressUrl),
523521
+ connect_url: buildBridgeConnectUrl(handle4.environmentId, handle4.sessionIngressUrl),
523522
+ environment_id: handle4.environmentId
523153
523523
  });
523154
523524
  }
523155
523525
  } catch (err2) {
@@ -524855,12 +525225,12 @@ __export(exports_install, {
524855
525225
  getInstallationPath: () => getInstallationPath2
524856
525226
  });
524857
525227
  import { homedir as homedir39 } from "node:os";
524858
- import { join as join134 } from "node:path";
525228
+ import { join as join135 } from "node:path";
524859
525229
  function getInstallationPath2() {
524860
525230
  const isWindows2 = env2.platform === "win32";
524861
525231
  const homeDir = homedir39();
524862
525232
  if (isWindows2) {
524863
- const windowsPath = join134(homeDir, ".local", "bin", "orbitcode.exe");
525233
+ const windowsPath = join135(homeDir, ".local", "bin", "orbitcode.exe");
524864
525234
  return windowsPath.replace(/\//g, "\\");
524865
525235
  }
524866
525236
  return "~/.local/bin/orbitcode";
@@ -527714,7 +528084,7 @@ Usage: orbit --remote "your task description"`, () => gracefulShutdown(1));
527714
528084
  pendingHookMessages
527715
528085
  }, renderAndRun);
527716
528086
  }
527717
- }).version("0.1.39 (Orbit AI)", "-v, --version", "Output the version number");
528087
+ }).version("0.1.41 (Orbit AI)", "-v, --version", "Output the version number");
527718
528088
  program2.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
527719
528089
  program2.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
527720
528090
  if (canUserConfigureAdvisor()) {
@@ -528236,7 +528606,7 @@ if (false) {}
528236
528606
  async function main2() {
528237
528607
  const args = process.argv.slice(2);
528238
528608
  if (args.length === 1 && (args[0] === "--version" || args[0] === "-v" || args[0] === "-V")) {
528239
- console.log(`${"0.1.39"} (Orbit AI)`);
528609
+ console.log(`${"0.1.41"} (Orbit AI)`);
528240
528610
  return;
528241
528611
  }
528242
528612
  if (args.includes("--provider")) {
@@ -528344,4 +528714,4 @@ async function main2() {
528344
528714
  }
528345
528715
  main2();
528346
528716
 
528347
- //# debugId=3DB19D92C131358564756E2164756E21
528717
+ //# debugId=03E546CCD84EB70B64756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orbit-code-ai",
3
- "version": "0.1.39",
3
+ "version": "0.1.41",
4
4
  "description": "Orbit AI – Your AI-powered IBM ACE coding companion",
5
5
  "type": "module",
6
6
  "author": "moenawaf",