create-windy 0.8.1 → 0.8.3

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 (95) hide show
  1. package/dist/cli.js +52 -34
  2. package/package.json +1 -1
  3. package/template/.windy-template.json +2 -2
  4. package/template/apps/agent-server/src/southwind_agent_server/attempt_context.py +9 -1
  5. package/template/apps/agent-server/src/southwind_agent_server/openai_provider.py +5 -2
  6. package/template/apps/agent-server/src/southwind_agent_server/provider_output_guidance.py +34 -0
  7. package/template/apps/agent-server/src/southwind_agent_server/structured_logging.py +16 -5
  8. package/template/apps/agent-server/tests/test_structured_logging.py +37 -0
  9. package/template/apps/agent-server/tests/test_tool_structured_output.py +347 -0
  10. package/template/apps/server/src/agent/admin-catalog-bootstrap.ts +25 -0
  11. package/template/apps/server/src/agent/agent-session-bootstrap.ts +7 -8
  12. package/template/apps/server/src/agent/agent-session-facade.ts +12 -0
  13. package/template/apps/server/src/agent/agent-session-validation.ts +43 -0
  14. package/template/apps/server/src/agent/operation-catalog.test.ts +202 -0
  15. package/template/apps/server/src/agent/operation-catalog.ts +135 -0
  16. package/template/apps/server/src/agent/run-browser-visibility.test.ts +59 -0
  17. package/template/apps/server/src/agent/run-browser-visibility.ts +11 -0
  18. package/template/apps/server/src/agent/run-operation-policy.ts +1 -0
  19. package/template/apps/server/src/agent/run-route-response.ts +35 -0
  20. package/template/apps/server/src/agent/run-routes.ts +46 -43
  21. package/template/apps/server/src/agent/runtime-bootstrap.ts +21 -20
  22. package/template/apps/server/src/agent/runtime-disabled-composition.ts +28 -0
  23. package/template/apps/server/src/agent/session-projection-facade.ts +8 -9
  24. package/template/apps/server/src/agent/session-projection-governance.ts +10 -0
  25. package/template/apps/server/src/agent/session-projection-view.ts +19 -16
  26. package/template/apps/server/src/agent/session-recording-reader.contract.test.ts +131 -0
  27. package/template/apps/server/src/agent/session-recording-reader.ts +62 -0
  28. package/template/apps/server/src/agent/tool-catalog-audit.ts +22 -0
  29. package/template/apps/server/src/agent/tool-catalog-availability.ts +21 -0
  30. package/template/apps/server/src/agent/tool-catalog-routes.test.ts +103 -0
  31. package/template/apps/server/src/agent/tool-catalog-routes.ts +62 -0
  32. package/template/apps/server/src/agent/tool-catalog.test.ts +122 -0
  33. package/template/apps/server/src/agent/tool-catalog.ts +44 -0
  34. package/template/apps/server/src/agent/tool-registry.ts +45 -14
  35. package/template/apps/server/src/agent/workbench-bootstrap.ts +39 -0
  36. package/template/apps/server/src/agent/workbench-event-projection.ts +115 -0
  37. package/template/apps/server/src/agent/workbench-facade.contract.test.ts +189 -0
  38. package/template/apps/server/src/agent/workbench-facade.ts +339 -0
  39. package/template/apps/server/src/agent/workbench-recording.contract.test.ts +328 -0
  40. package/template/apps/server/src/agent/workbench-routes.ts +97 -0
  41. package/template/apps/server/src/agent/workbench-run-integration.test.ts +231 -0
  42. package/template/apps/server/src/agent/workbench-run-reader.ts +187 -0
  43. package/template/apps/server/src/agent/workbench-safe-result.ts +61 -0
  44. package/template/apps/server/src/agent/workbench-sse.ts +50 -0
  45. package/template/apps/server/src/agent-workflow/query-service.ts +36 -0
  46. package/template/apps/server/src/agent-workflow/recording-projection.contract.test.ts +196 -0
  47. package/template/apps/server/src/agent-workflow/recording-projection.ts +86 -0
  48. package/template/apps/web/src/pages/system/AgentDebugPage.vue +14 -0
  49. package/template/apps/web/src/pages/system/AgentSessionPage.vue +29 -8
  50. package/template/apps/web/src/pages/system/AgentToolsPage.vue +76 -0
  51. package/template/apps/web/src/pages/system/components/agent-workbench/AgentWorkbench.vue +236 -0
  52. package/template/apps/web/src/pages/system/components/agent-workbench/DraftLeaveDialog.vue +34 -0
  53. package/template/apps/web/src/pages/system/components/agent-workbench/ReplayEventDetail.vue +175 -0
  54. package/template/apps/web/src/pages/system/components/agent-workbench/SessionReplayTimeline.vue +142 -0
  55. package/template/apps/web/src/pages/system/components/agent-workbench/SessionReplayTimeline.webtest.ts +242 -0
  56. package/template/apps/web/src/pages/system/components/agent-workbench/TestRunComposer.vue +97 -0
  57. package/template/apps/web/src/pages/system/components/agent-workbench/ToolCatalogPanel.vue +100 -0
  58. package/template/apps/web/src/pages/system/components/agent-workbench/ToolCatalogPanel.webtest.ts +55 -0
  59. package/template/apps/web/src/pages/system/components/agent-workbench/ToolRuleDetail.vue +81 -0
  60. package/template/apps/web/src/pages/system/components/agent-workbench/WorkbenchSessionList.vue +57 -0
  61. package/template/apps/web/src/pages/system/components/agent-workbench/catalog-presenter.ts +20 -0
  62. package/template/apps/web/src/pages/system/components/agent-workbench/replay-presenter.ts +94 -0
  63. package/template/apps/web/src/pages/system/composables/useAgentWorkbench.ts +298 -0
  64. package/template/apps/web/src/pages/system/composables/useAgentWorkbench.webtest.ts +164 -0
  65. package/template/apps/web/src/pages/system/composables/useSessionReplay.ts +48 -0
  66. package/template/apps/web/src/router/index.ts +4 -0
  67. package/template/apps/web/src/router/platform-admin-route-bindings.ts +4 -0
  68. package/template/apps/web/src/services/agent-admin-api.ts +155 -0
  69. package/template/apps/web/src/services/agent-admin-api.webtest.ts +120 -0
  70. package/template/apps/web/src/services/agent-workbench-event.ts +60 -0
  71. package/template/docs/architecture/agent-harness.md +4 -0
  72. package/template/docs/architecture/log-governance-implementation.md +20 -3
  73. package/template/docs/architecture/log-governance-plan.md +2 -2
  74. package/template/docs/platform/agent-runtime.md +18 -0
  75. package/template/packages/modules/src/ai-operation-composition.ts +9 -0
  76. package/template/packages/modules/src/ai-operation-visibility.test.ts +33 -0
  77. package/template/packages/modules/src/manifest.ts +2 -0
  78. package/template/packages/modules/src/system-admin-routes.ts +16 -0
  79. package/template/packages/modules/src/system-admin-ui-catalog.ts +7 -1
  80. package/template/packages/modules/src/system-agent-admin-bindings.ts +42 -0
  81. package/template/packages/modules/src/system-agent-admin-menus.ts +26 -0
  82. package/template/packages/modules/src/system-agent-admin-registration.test.ts +52 -0
  83. package/template/packages/modules/src/system-agent-audit-actions.ts +5 -0
  84. package/template/packages/modules/src/system-ai-api-bindings.ts +2 -0
  85. package/template/packages/modules/src/system-audit-actions.ts +25 -0
  86. package/template/packages/modules/src/system-features.ts +19 -0
  87. package/template/packages/modules/src/system-module-catalog.ts +14 -12
  88. package/template/packages/modules/src/system-module-ownership.ts +12 -0
  89. package/template/packages/modules/src/system-modules.ts +2 -0
  90. package/template/packages/modules/src/system-permissions.ts +5 -0
  91. package/template/packages/server-sdk/index.ts +2 -0
  92. package/template/packages/server-sdk/src/agent-session-provider.ts +19 -0
  93. package/template/packages/shared/index.ts +2 -0
  94. package/template/packages/shared/src/agent-admin-catalog.ts +73 -0
  95. package/template/packages/shared/src/agent-workbench.ts +100 -0
package/dist/cli.js CHANGED
@@ -33,7 +33,7 @@ var __toESM = (mod, isNodeMode, target) => {
33
33
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
34
34
  var __require = import.meta.require;
35
35
 
36
- // ../../node_modules/cli-width/index.js
36
+ // ../../node_modules/.bun/cli-width@4.1.0/node_modules/cli-width/index.js
37
37
  var require_cli_width = __commonJS((exports, module2) => {
38
38
  module2.exports = cliWidth;
39
39
  function normalizeOpts(options) {
@@ -73,7 +73,7 @@ var require_cli_width = __commonJS((exports, module2) => {
73
73
  }
74
74
  });
75
75
 
76
- // ../../node_modules/mute-stream/lib/index.js
76
+ // ../../node_modules/.bun/mute-stream@3.0.0/node_modules/mute-stream/lib/index.js
77
77
  var require_lib = __commonJS((exports, module2) => {
78
78
  var Stream = __require("stream");
79
79
 
@@ -325,6 +325,15 @@ var agentOptionalModule = {
325
325
  "apps/server/src/module-host/tool-handlers.test.ts",
326
326
  "apps/server/src/module-host/module-secret-tool-boundary.test.ts",
327
327
  "apps/web/src/pages/system/AiRuntimePage.vue",
328
+ "apps/web/src/pages/system/AgentToolsPage.vue",
329
+ "apps/web/src/pages/system/AgentDebugPage.vue",
330
+ "apps/web/src/pages/system/components/agent-workbench",
331
+ "apps/web/src/pages/system/composables/useAgentWorkbench.ts",
332
+ "apps/web/src/pages/system/composables/useAgentWorkbench.webtest.ts",
333
+ "apps/web/src/pages/system/composables/useSessionReplay.ts",
334
+ "apps/web/src/services/agent-admin-api.ts",
335
+ "apps/web/src/services/agent-admin-api.webtest.ts",
336
+ "apps/web/src/services/agent-workbench-event.ts",
328
337
  "apps/web/src/pages/system/AgentSessionPage.vue",
329
338
  "apps/web/src/pages/system/AgentSessionPage.webtest.ts",
330
339
  "apps/web/src/pages/system/AgentWorkflowPage.vue",
@@ -344,6 +353,9 @@ var agentOptionalModule = {
344
353
  "apps/web/src/services/ai-runtime-api.ts",
345
354
  "apps/web/src/services/ai-runtime-api.webtest.ts",
346
355
  "scripts/provision-speech-readiness.ts",
356
+ "packages/modules/src/system-agent-admin-registration.test.ts",
357
+ "packages/modules/src/system-agent-admin-menus.ts",
358
+ "packages/modules/src/system-agent-admin-bindings.ts",
347
359
  "packages/modules/src/system-agent-audit-actions.ts",
348
360
  "packages/modules/src/system-agent-tools.ts",
349
361
  "packages/modules/src/system-agent-supervisor.ts",
@@ -359,6 +371,8 @@ var agentOptionalModule = {
359
371
  "packages/server-sdk/src/workflow-input-materialization-handler.ts",
360
372
  "packages/database/src/agent-runtime-schema.test.ts",
361
373
  "packages/database/src/ai-output-artifacts.test.ts",
374
+ "packages/shared/src/agent-admin-catalog.ts",
375
+ "packages/shared/src/agent-workbench.ts",
362
376
  "packages/shared/src/agent-workflow-definition.ts",
363
377
  "packages/shared/src/agent-workflow-delegation.ts",
364
378
  "packages/shared/src/agent-workflow-evaluation.ts",
@@ -371,6 +385,8 @@ var agentOptionalModule = {
371
385
  ],
372
386
  documentation: [
373
387
  "docs/adr/0003-agent-session-event-source.md",
388
+ "docs/architecture/agent-admin-workbench-plan.md",
389
+ "docs/architecture/agent-admin-workbench-implementation.md",
374
390
  "docs/architecture/agent-harness.md",
375
391
  "docs/architecture/agent-runtime-compatibility.md",
376
392
  "docs/architecture/agent-workflow.md",
@@ -4677,7 +4693,7 @@ function isMissing6(error) {
4677
4693
  import { createInterface as createInterface2 } from "readline/promises";
4678
4694
  import { stdin, stdout } from "process";
4679
4695
 
4680
- // ../../node_modules/@inquirer/core/dist/lib/key.js
4696
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/key.js
4681
4697
  var keybindings = ["emacs", "vim"];
4682
4698
  var keybindingLookup = new Set(keybindings);
4683
4699
  function isKeybinding(value) {
@@ -4694,7 +4710,7 @@ var isDownKey = (key, keybindings2 = []) => key.name === "down" || keybindings2.
4694
4710
  var isSpaceKey = (key) => key.name === "space";
4695
4711
  var isNumberKey = (key) => "1234567890".includes(key.name);
4696
4712
  var isEnterKey = (key) => key.name === "enter" || key.name === "return";
4697
- // ../../node_modules/@inquirer/core/dist/lib/errors.js
4713
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/errors.js
4698
4714
  class AbortPromptError extends Error {
4699
4715
  name = "AbortPromptError";
4700
4716
  message = "Prompt was aborted";
@@ -4720,10 +4736,10 @@ class HookError extends Error {
4720
4736
  class ValidationError extends Error {
4721
4737
  name = "ValidationError";
4722
4738
  }
4723
- // ../../node_modules/@inquirer/core/dist/lib/use-state.js
4739
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-state.js
4724
4740
  import { AsyncResource as AsyncResource2 } from "async_hooks";
4725
4741
 
4726
- // ../../node_modules/@inquirer/core/dist/lib/hook-engine.js
4742
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/hook-engine.js
4727
4743
  import { AsyncLocalStorage, AsyncResource } from "async_hooks";
4728
4744
  var hookStorage = new AsyncLocalStorage;
4729
4745
  function createStore(rl) {
@@ -4828,7 +4844,7 @@ var effectScheduler = {
4828
4844
  }
4829
4845
  };
4830
4846
 
4831
- // ../../node_modules/@inquirer/core/dist/lib/use-state.js
4847
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-state.js
4832
4848
  function isFactory(value) {
4833
4849
  return typeof value === "function";
4834
4850
  }
@@ -4849,7 +4865,7 @@ function useState(defaultValue) {
4849
4865
  });
4850
4866
  }
4851
4867
 
4852
- // ../../node_modules/@inquirer/core/dist/lib/use-effect.js
4868
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-effect.js
4853
4869
  function useEffect(cb, depArray) {
4854
4870
  withPointer((pointer) => {
4855
4871
  const oldDeps = pointer.get();
@@ -4861,10 +4877,10 @@ function useEffect(cb, depArray) {
4861
4877
  });
4862
4878
  }
4863
4879
 
4864
- // ../../node_modules/@inquirer/core/dist/lib/theme.js
4880
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/theme.js
4865
4881
  import { styleText } from "util";
4866
4882
 
4867
- // ../../node_modules/@inquirer/figures/dist/index.js
4883
+ // ../../node_modules/.bun/@inquirer+figures@2.0.7/node_modules/@inquirer/figures/dist/index.js
4868
4884
  import process2 from "process";
4869
4885
  function isUnicodeSupported() {
4870
4886
  if (!process2.platform.startsWith("win")) {
@@ -5153,7 +5169,7 @@ var figures = shouldUseMain ? mainSymbols : fallbackSymbols;
5153
5169
  var dist_default = figures;
5154
5170
  var replacements = Object.entries(specialMainSymbols);
5155
5171
 
5156
- // ../../node_modules/@inquirer/core/dist/lib/theme.js
5172
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/theme.js
5157
5173
  var defaultTheme = {
5158
5174
  prefix: {
5159
5175
  idle: styleText("blue", "?"),
@@ -5181,7 +5197,7 @@ function getDefaultTheme() {
5181
5197
  };
5182
5198
  }
5183
5199
 
5184
- // ../../node_modules/@inquirer/core/dist/lib/make-theme.js
5200
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/make-theme.js
5185
5201
  function isPlainObject(value) {
5186
5202
  if (typeof value !== "object" || value === null)
5187
5203
  return false;
@@ -5209,7 +5225,7 @@ function makeTheme(...themes) {
5209
5225
  return deepMerge(...themesToMerge);
5210
5226
  }
5211
5227
 
5212
- // ../../node_modules/@inquirer/core/dist/lib/use-prefix.js
5228
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-prefix.js
5213
5229
  function usePrefix({ status = "idle", theme }) {
5214
5230
  const [showLoader, setShowLoader] = useState(false);
5215
5231
  const [tick, setTick] = useState(0);
@@ -5239,7 +5255,7 @@ function usePrefix({ status = "idle", theme }) {
5239
5255
  const iconName = status === "loading" ? "idle" : status;
5240
5256
  return typeof prefix === "string" ? prefix : prefix[iconName] ?? prefix["idle"];
5241
5257
  }
5242
- // ../../node_modules/@inquirer/core/dist/lib/use-memo.js
5258
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-memo.js
5243
5259
  function useMemo(fn, dependencies) {
5244
5260
  return withPointer((pointer) => {
5245
5261
  const prev = pointer.get();
@@ -5251,12 +5267,12 @@ function useMemo(fn, dependencies) {
5251
5267
  return prev.value;
5252
5268
  });
5253
5269
  }
5254
- // ../../node_modules/@inquirer/core/dist/lib/use-ref.js
5270
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-ref.js
5255
5271
  function useRef(val) {
5256
5272
  return useState({ current: val })[0];
5257
5273
  }
5258
5274
 
5259
- // ../../node_modules/@inquirer/core/dist/lib/use-keypress.js
5275
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/use-keypress.js
5260
5276
  function useKeypress(userHandler) {
5261
5277
  const signal = useRef(userHandler);
5262
5278
  signal.current = userHandler;
@@ -5274,10 +5290,10 @@ function useKeypress(userHandler) {
5274
5290
  };
5275
5291
  }, []);
5276
5292
  }
5277
- // ../../node_modules/@inquirer/core/dist/lib/utils.js
5293
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/utils.js
5278
5294
  var import_cli_width = __toESM(require_cli_width(), 1);
5279
5295
 
5280
- // ../../node_modules/fast-string-truncated-width/dist/utils.js
5296
+ // ../../node_modules/.bun/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
5281
5297
  var getCodePointsLength = (() => {
5282
5298
  const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
5283
5299
  return (input) => {
@@ -5296,7 +5312,7 @@ var isWideNotCJKTNotEmoji = (x) => {
5296
5312
  return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
5297
5313
  };
5298
5314
 
5299
- // ../../node_modules/fast-string-truncated-width/dist/index.js
5315
+ // ../../node_modules/.bun/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
5300
5316
  var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
5301
5317
  var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
5302
5318
  var CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
@@ -5395,7 +5411,7 @@ var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {})
5395
5411
  };
5396
5412
  var dist_default2 = getStringTruncatedWidth;
5397
5413
 
5398
- // ../../node_modules/fast-string-width/dist/index.js
5414
+ // ../../node_modules/.bun/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
5399
5415
  var NO_TRUNCATION2 = {
5400
5416
  limit: Infinity,
5401
5417
  ellipsis: "",
@@ -5406,7 +5422,7 @@ var fastStringWidth = (input, options = {}) => {
5406
5422
  };
5407
5423
  var dist_default3 = fastStringWidth;
5408
5424
 
5409
- // ../../node_modules/fast-wrap-ansi/lib/main.js
5425
+ // ../../node_modules/.bun/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
5410
5426
  var ESC = "\x1B";
5411
5427
  var CSI = "\x9B";
5412
5428
  var END_CODE = 39;
@@ -5618,7 +5634,7 @@ function wrapAnsi(string, columns, options) {
5618
5634
  `);
5619
5635
  }
5620
5636
 
5621
- // ../../node_modules/@inquirer/core/dist/lib/utils.js
5637
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/utils.js
5622
5638
  function breakLines(content, width) {
5623
5639
  return content.split(`
5624
5640
  `).flatMap((line) => wrapAnsi(line, width, { trim: false, wordWrap: false }).split(`
@@ -5629,7 +5645,7 @@ function readlineWidth() {
5629
5645
  return import_cli_width.default({ defaultWidth: 80, output: readline().output });
5630
5646
  }
5631
5647
 
5632
- // ../../node_modules/@inquirer/core/dist/lib/pagination/use-pagination.js
5648
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/pagination/use-pagination.js
5633
5649
  function usePointerPosition({ active, renderedItems, pageSize, loop }) {
5634
5650
  const state = useRef({
5635
5651
  lastPointer: active,
@@ -5695,12 +5711,12 @@ function usePagination({ items, active, renderItem, pageSize, loop = true }) {
5695
5711
  return pageBuffer.filter((line) => typeof line === "string").join(`
5696
5712
  `);
5697
5713
  }
5698
- // ../../node_modules/@inquirer/core/dist/lib/create-prompt.js
5714
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/create-prompt.js
5699
5715
  var import_mute_stream = __toESM(require_lib(), 1);
5700
5716
  import * as readline2 from "readline";
5701
5717
  import { AsyncResource as AsyncResource3 } from "async_hooks";
5702
5718
 
5703
- // ../../node_modules/signal-exit/dist/mjs/signals.js
5719
+ // ../../node_modules/.bun/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/signals.js
5704
5720
  var signals = [];
5705
5721
  signals.push("SIGHUP", "SIGINT", "SIGTERM");
5706
5722
  if (process.platform !== "win32") {
@@ -5710,7 +5726,7 @@ if (process.platform === "linux") {
5710
5726
  signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT");
5711
5727
  }
5712
5728
 
5713
- // ../../node_modules/signal-exit/dist/mjs/index.js
5729
+ // ../../node_modules/.bun/signal-exit@4.1.0/node_modules/signal-exit/dist/mjs/index.js
5714
5730
  var processOk = (process3) => !!process3 && typeof process3 === "object" && typeof process3.removeListener === "function" && typeof process3.emit === "function" && typeof process3.reallyExit === "function" && typeof process3.listeners === "function" && typeof process3.kill === "function" && typeof process3.pid === "number" && typeof process3.on === "function";
5715
5731
  var kExitEmitter = Symbol.for("signal-exit emitter");
5716
5732
  var global = globalThis;
@@ -5908,10 +5924,10 @@ var {
5908
5924
  unload
5909
5925
  } = signalExitWrap(processOk(process3) ? new SignalExit(process3) : new SignalExitFallback);
5910
5926
 
5911
- // ../../node_modules/@inquirer/core/dist/lib/screen-manager.js
5927
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/screen-manager.js
5912
5928
  import { stripVTControlCharacters } from "util";
5913
5929
 
5914
- // ../../node_modules/@inquirer/ansi/dist/index.js
5930
+ // ../../node_modules/.bun/@inquirer+ansi@2.0.7/node_modules/@inquirer/ansi/dist/index.js
5915
5931
  var ESC2 = "\x1B[";
5916
5932
  var cursorLeft = ESC2 + "G";
5917
5933
  var cursorHide = ESC2 + "?25l";
@@ -5927,7 +5943,7 @@ var cursorTo = (x, y) => {
5927
5943
  var eraseLine = ESC2 + "2K";
5928
5944
  var eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : "";
5929
5945
 
5930
- // ../../node_modules/@inquirer/core/dist/lib/screen-manager.js
5946
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/screen-manager.js
5931
5947
  var height = (content) => content.split(`
5932
5948
  `).length;
5933
5949
  var lastLine = (content) => content.split(`
@@ -5993,7 +6009,7 @@ class ScreenManager {
5993
6009
  }
5994
6010
  }
5995
6011
 
5996
- // ../../node_modules/@inquirer/core/dist/lib/promise-polyfill.js
6012
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/promise-polyfill.js
5997
6013
  class PromisePolyfill extends Promise {
5998
6014
  static withResolver() {
5999
6015
  let resolve6;
@@ -6006,7 +6022,7 @@ class PromisePolyfill extends Promise {
6006
6022
  }
6007
6023
  }
6008
6024
 
6009
- // ../../node_modules/@inquirer/core/dist/lib/create-prompt.js
6025
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/create-prompt.js
6010
6026
  import path from "path";
6011
6027
  var nativeSetImmediate = globalThis.setImmediate;
6012
6028
  function getCallSites() {
@@ -6117,7 +6133,7 @@ function createPrompt(view) {
6117
6133
  };
6118
6134
  return prompt;
6119
6135
  }
6120
- // ../../node_modules/@inquirer/core/dist/lib/Separator.js
6136
+ // ../../node_modules/.bun/@inquirer+core@11.2.1+7cb241fc07b679d9/node_modules/@inquirer/core/dist/lib/Separator.js
6121
6137
  import { styleText as styleText2 } from "util";
6122
6138
  class Separator {
6123
6139
  separator = styleText2("dim", Array.from({ length: 15 }).join(dist_default.line));
@@ -6131,7 +6147,7 @@ class Separator {
6131
6147
  return Boolean(choice && typeof choice === "object" && "type" in choice && choice.type === "separator");
6132
6148
  }
6133
6149
  }
6134
- // ../../node_modules/@inquirer/checkbox/dist/index.js
6150
+ // ../../node_modules/.bun/@inquirer+checkbox@5.2.1+7cb241fc07b679d9/node_modules/@inquirer/checkbox/dist/index.js
6135
6151
  import { styleText as styleText3 } from "util";
6136
6152
  var checkboxTheme = {
6137
6153
  icon: {
@@ -8529,7 +8545,9 @@ var recipes = [
8529
8545
  from: "0.7.0",
8530
8546
  to: "0.8.0"
8531
8547
  },
8532
- { id: "starter-0.8.0-to-0.8.1", from: "0.8.0", to: "0.8.1" }
8548
+ { id: "starter-0.8.0-to-0.8.1", from: "0.8.0", to: "0.8.1" },
8549
+ { id: "starter-0.8.1-to-0.8.2", from: "0.8.1", to: "0.8.2" },
8550
+ { id: "starter-0.8.2-to-0.8.3", from: "0.8.2", to: "0.8.3" }
8533
8551
  ];
8534
8552
  function resolveRecipeChain(sourceVersion, targetVersion) {
8535
8553
  if (compareVersions2(sourceVersion, minimumSupportedUpdateVersion) < 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-windy",
3
- "version": "0.8.1",
3
+ "version": "0.8.3",
4
4
  "description": "创建单组织、单租户、私有部署优先的 Windy 企业 Dashboard Starter",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "templateCommit": "066d8018c0ec0c82fbf01d26013b3b303aaa9c22",
4
- "generatorVersion": "0.8.1",
3
+ "templateCommit": "c701e845048c839516533e164cb550e3348eb89c",
4
+ "generatorVersion": "0.8.3",
5
5
  "modules": [
6
6
  {
7
7
  "name": "system",
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from dataclasses import dataclass
3
+ from dataclasses import dataclass, replace
4
4
 
5
5
  from .attempt_context_projection import (
6
6
  AttemptContextPreparation,
@@ -15,6 +15,7 @@ from .contracts import JsonValue, LongSessionContext
15
15
  from .engine import EngineRunRequest, PreparedArtifact
16
16
  from .openai_provider import OpenAiCompatibleProvider
17
17
  from .provider_governance import GovernedAttempt, ProviderRequestGovernance
18
+ from .provider_output_guidance import tool_output_messages
18
19
 
19
20
 
20
21
  @dataclass(frozen=True)
@@ -64,6 +65,13 @@ async def govern_provider_attempt(
64
65
  )
65
66
  ),
66
67
  )
68
+ if governed.tools:
69
+ governed = replace(
70
+ governed,
71
+ messages=tool_output_messages(
72
+ governed.messages, governed.output_schema
73
+ ),
74
+ )
67
75
  provider_request = provider.request_body(
68
76
  governed.messages,
69
77
  governed.tools,
@@ -14,6 +14,7 @@ from .config import (
14
14
  from .contracts import AgentErrorCode, JsonValue, RuntimeToolDefinition
15
15
  from .engine import SafeEngineError
16
16
  from .multimodal import response_format
17
+ from .provider_output_guidance import tool_output_messages
17
18
  from .report_types import UsageFacts
18
19
  from .vision_probe import probe_vision
19
20
 
@@ -97,6 +98,9 @@ class OpenAiCompatibleProvider:
97
98
  output_schema: dict[str, JsonValue] | None = None,
98
99
  max_output_tokens: int | None = None,
99
100
  ) -> bytes:
101
+ structured = response_format(output_schema_key, output_schema)
102
+ if tools:
103
+ messages = tool_output_messages(messages, output_schema)
100
104
  payload: dict[str, JsonValue] = {
101
105
  "model": self.config.model,
102
106
  "messages": cast(JsonValue, messages),
@@ -105,8 +109,7 @@ class OpenAiCompatibleProvider:
105
109
  }
106
110
  if tools:
107
111
  payload["tools"] = [tool_schema(tool) for tool in tools]
108
- structured = response_format(output_schema_key, output_schema)
109
- if structured is not None:
112
+ if structured is not None and not tools:
110
113
  payload["response_format"] = structured
111
114
  if max_output_tokens is not None:
112
115
  payload["max_tokens"] = max_output_tokens
@@ -0,0 +1,34 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+
5
+ from .contracts import JsonValue
6
+ from .engine import SafeEngineError
7
+
8
+
9
+ def tool_output_messages(
10
+ messages: list[dict[str, JsonValue]],
11
+ output_schema: dict[str, JsonValue] | None,
12
+ ) -> list[dict[str, JsonValue]]:
13
+ """Merge already-governed schema guidance without moving Context source ordinals."""
14
+ if output_schema is None:
15
+ return messages
16
+ if not messages or messages[0].get("role") != "system":
17
+ raise SafeEngineError(
18
+ "INVALID_INPUT", "工具结构化输出缺少系统指令", retryable=False
19
+ )
20
+ instructions = messages[0].get("content")
21
+ if not isinstance(instructions, str):
22
+ raise SafeEngineError(
23
+ "INVALID_INPUT", "工具结构化输出指令无效", retryable=False
24
+ )
25
+ guidance = (
26
+ "\n\n需要工具时,只通过 API 的 function calling 调用已提供的工具,"
27
+ "不要在正文中模拟工具调用。工具处理完成后的最终回复必须是符合以下 "
28
+ "JSON Schema 的单个 JSON 值,不含 Markdown 围栏或额外说明;"
29
+ "工具调用阶段不受最终 JSON 格式限制。\n"
30
+ + json.dumps(output_schema, ensure_ascii=False, separators=(",", ":"))
31
+ )
32
+ if instructions.endswith(guidance):
33
+ return messages
34
+ return [{**messages[0], "content": instructions + guidance}, *messages[1:]]
@@ -124,11 +124,22 @@ class AgentStructuredLogHandler(logging.Handler):
124
124
 
125
125
 
126
126
  def configure_agent_logging() -> None:
127
- """Attach once to package loggers; keep Uvicorn's own access logs separate."""
127
+ """Use one package sink without closing handlers shared with Uvicorn."""
128
128
  logger = logging.getLogger("southwind_agent_server")
129
- if not any(
130
- isinstance(handler, AgentStructuredLogHandler) for handler in logger.handlers
131
- ):
132
- logger.addHandler(AgentStructuredLogHandler())
129
+ structured = next(
130
+ (
131
+ handler
132
+ for handler in logger.handlers
133
+ if isinstance(handler, AgentStructuredLogHandler)
134
+ ),
135
+ None,
136
+ )
137
+ if structured is None:
138
+ structured = AgentStructuredLogHandler()
139
+ for handler in logger.handlers[:]:
140
+ if handler is not structured:
141
+ logger.removeHandler(handler)
142
+ if structured not in logger.handlers:
143
+ logger.addHandler(structured)
133
144
  logger.setLevel(logging.INFO)
134
145
  logger.propagate = False
@@ -4,6 +4,8 @@ import logging
4
4
  from importlib import import_module
5
5
  from typing import TextIO, cast
6
6
 
7
+ import pytest
8
+
7
9
  from southwind_agent_server.structured_logging import (
8
10
  MAX_LOG_BYTES,
9
11
  AgentStructuredLogHandler,
@@ -103,3 +105,38 @@ def test_stdout_failure_does_not_interrupt_runtime() -> None:
103
105
  }
104
106
  )
105
107
  handler.emit(record)
108
+
109
+
110
+ def test_bootstrap_removes_borrowed_sink_without_closing_uvicorn(
111
+ monkeypatch: pytest.MonkeyPatch,
112
+ ) -> None:
113
+ stream = io.StringIO()
114
+ legacy_stream = io.StringIO()
115
+ legacy = logging.StreamHandler(legacy_stream)
116
+ structured = AgentStructuredLogHandler(stream)
117
+ logger = logging.getLogger("southwind_agent_server")
118
+ uvicorn = logging.getLogger("uvicorn")
119
+ monkeypatch.setattr(logger, "handlers", [legacy, structured])
120
+ monkeypatch.setattr(logger, "level", logging.INFO)
121
+ monkeypatch.setattr(logger, "propagate", False)
122
+ monkeypatch.setattr(uvicorn, "handlers", [legacy])
123
+ monkeypatch.setattr(uvicorn, "level", logging.INFO)
124
+ monkeypatch.setattr(uvicorn, "propagate", False)
125
+ closed: list[bool] = []
126
+ monkeypatch.setattr(legacy, "close", lambda: closed.append(True))
127
+
128
+ configure_agent_logging()
129
+ configure_agent_logging()
130
+ assert logger.handlers == [structured]
131
+ assert uvicorn.handlers == [legacy]
132
+ assert not closed
133
+ try:
134
+ raise ValueError("secret-exception")
135
+ except ValueError:
136
+ logger.exception("Agent Run 恢复轮询失败,将继续重试")
137
+ assert len(stream.getvalue().splitlines()) == 1
138
+ assert json.loads(stream.getvalue())["errorCode"] == "AGENT_RUN_RECOVERY_FAILED"
139
+ assert legacy_stream.getvalue() == ""
140
+ assert "secret-exception" not in stream.getvalue()
141
+ uvicorn.warning("independent-server-warning")
142
+ assert "independent-server-warning" in legacy_stream.getvalue()