@docyrus/docyrus 0.0.41 → 0.0.43

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 (36) hide show
  1. package/README.md +2 -0
  2. package/agent-loader.js +11 -2
  3. package/agent-loader.js.map +2 -2
  4. package/main.js +1823 -697
  5. package/main.js.map +4 -4
  6. package/package.json +8 -7
  7. package/resources/pi-agent/extensions/architect.ts +2 -2
  8. package/resources/pi-agent/extensions/control.ts +0 -8
  9. package/resources/pi-agent/extensions/knowledge.ts +0 -7
  10. package/resources/pi-agent/extensions/loop.ts +1 -5
  11. package/resources/pi-agent/extensions/pi-bash-live-view/package.json +1 -1
  12. package/resources/pi-agent/extensions/pi-custom-compaction/events/register-events.ts +0 -10
  13. package/resources/pi-agent/extensions/pi-custom-compaction/package.json +4 -4
  14. package/resources/pi-agent/extensions/pi-mcp-adapter/package.json +22 -22
  15. package/resources/pi-agent/extensions/plan.ts +183 -45
  16. package/resources/pi-agent/extensions/prompt-editor.ts +0 -18
  17. package/resources/pi-agent/extensions/prompt-url-widget.ts +0 -4
  18. package/resources/pi-agent/extensions/review.ts +0 -4
  19. package/resources/pi-agent/prompts/agent-system.md +12 -0
  20. package/resources/pi-agent/prompts/coder-system.md +18 -0
  21. package/resources/pi-agent/skills/agent-browser/SKILL.md +779 -0
  22. package/resources/pi-agent/skills/agent-browser/references/authentication.md +303 -0
  23. package/resources/pi-agent/skills/agent-browser/references/commands.md +295 -0
  24. package/resources/pi-agent/skills/agent-browser/references/profiling.md +120 -0
  25. package/resources/pi-agent/skills/agent-browser/references/proxy-support.md +194 -0
  26. package/resources/pi-agent/skills/agent-browser/references/session-management.md +193 -0
  27. package/resources/pi-agent/skills/agent-browser/references/snapshot-refs.md +219 -0
  28. package/resources/pi-agent/skills/agent-browser/references/video-recording.md +173 -0
  29. package/resources/pi-agent/skills/agent-browser/templates/authenticated-session.sh +105 -0
  30. package/resources/pi-agent/skills/agent-browser/templates/capture-workflow.sh +69 -0
  31. package/resources/pi-agent/skills/agent-browser/templates/form-automation.sh +62 -0
  32. package/resources/pi-agent/skills/docyrus-app-dev-react/SKILL.md +17 -13
  33. package/resources/pi-agent/skills/docyrus-platform/references/docyrus-cli-usage.md +73 -0
  34. package/resources/pi-agent/skills/grill-me/SKILL.md +109 -0
  35. package/server-loader.js +124 -33
  36. package/server-loader.js.map +4 -4
@@ -24,7 +24,7 @@ Use this skill when you are:
24
24
  - Setting up authentication with `@docyrus/signin`
25
25
  - Bootstrapping tenant-aware runtime utilities with `@docyrus/app-utils`
26
26
  - Fetching or mutating data with generated collections or `@docyrus/api-client`
27
- - Persisting app-level config or saved grid views with `AppConfig` and `DataViews`
27
+ - Persisting app-level config or user-level config or saved grid views with `AppConfig`, `UserAppConfig`, and `DataViews`
28
28
  - Building record sharing, role management, or ACL-driven UI flows
29
29
  - Designing feature UIs such as dashboards, forms, tables, layouts, dialogs, analytics, or detail pages
30
30
  - Selecting between shadcn, diceui, animate-ui, docyrus-ui, and reui components
@@ -36,7 +36,7 @@ Use this skill when you are:
36
36
  2. Bootstrap `TenantPreferences`, date/number utilities, and shared app runtime helpers from `@docyrus/app-utils`.
37
37
  3. Use generated Docyrus collection hooks or the REST client for data access.
38
38
  4. Define `columns`, filters, formulas, child queries, and mutations correctly.
39
- 5. Use `AppConfig` for per-app persisted settings and `DataViews` for saved grid views.
39
+ 5. Use `AppConfig` for per-app persisted settings, `UserAppConfig` for per-user per-app settings, and `DataViews` for saved grid views.
40
40
  6. Check preferred UI components before building anything custom.
41
41
  7. Use Docyrus form and detail patterns for create, edit, item detail, and editable grid flows.
42
42
  8. Connect UI actions to TanStack Query mutations and invalidate relevant queries.
@@ -81,6 +81,7 @@ Use `@docyrus/app-utils` as the default runtime layer for tenant-level formattin
81
81
  ```tsx
82
82
  import {
83
83
  createAppConfigClient,
84
+ createUserAppConfigClient,
84
85
  createDataViewClient,
85
86
  createDateUtils,
86
87
  createNumberUtils,
@@ -109,6 +110,7 @@ function useAppRuntime(appId: string) {
109
110
  }),
110
111
  numberUtils: createNumberUtils({ preferences }),
111
112
  appConfig: createAppConfigClient(client!, appId),
113
+ userConfig: createUserAppConfigClient(client!, appId),
112
114
  dataViews: createDataViewClient(client!, appId),
113
115
  }
114
116
  },
@@ -121,6 +123,7 @@ Use this runtime to:
121
123
  - Format dates and datetimes with tenant format strings and the user's timezone.
122
124
  - Format numbers, currency-like values, and decimals using tenant separators and precision.
123
125
  - Read and upsert the app's single persisted `AppConfig` document.
126
+ - Read and upsert the current user's `UserAppConfig` document (per-user per-app settings).
124
127
  - Read and persist saved grid views through `DataViews`.
125
128
 
126
129
  ### Data fetching with generated collections
@@ -187,17 +190,18 @@ Use `DataGridViewSelect` as the default saved-view UI for Docyrus grids, and per
187
190
  8. **Initialize `TenantPreferences` once per app runtime** and create shared `dateUtils` / `numberUtils` instances from `@docyrus/app-utils`.
188
191
  9. **Formatting functions from `@docyrus/app-utils` are regionalized** — do not hardcode locale, date format, decimal separator, thousand separator, or decimal precision when tenant preferences should drive them.
189
192
  10. **Use `createAppConfigClient(client, appId)`** for the app's single persisted config document; `upsert` is the default write path.
190
- 11. **Use `createDataViewClient(client, appId)`** for saved grid-view CRUD.
191
- 12. **Use `DataViews` with `DataGridViewSelect`** to show, create, edit, reorder, hide, unhide, soft-delete, and hard-delete saved data grid views.
192
- 13. **`DataGridViewSelect` needs a TanStack table instance** and should receive `fields` when you want the built-in filter builder/editor experience.
193
- 14. **Data view creation requires `name` and `tenant_data_source_id`**.
194
- 15. **Use `dataViews.update(viewId, { archived: true })` for soft-delete** and `dataViews.remove(viewId)` only for irreversible hard-delete.
195
- 16. **Regenerate collections after schema changes** by rebuilding the tenant OpenAPI spec, downloading the latest `openapi.json`, and re-running the collection generator.
196
- 17. **ACL endpoints are usually raw-client integrations** use `useDocyrusClient()` or `RestApiClient` for roles, user-role assignments, role queries, record sharing, and ownership transfer.
197
- 18. **Prefer role `uid` values** for ACL role writes, user-role `roleIds`, and role-query `roleIds`.
198
- 19. **Treat `PUT /v1/users/acl/users/:userId/roles` as full replacement** and `POST /v1/users/acl/users/:userId/roles` as additive.
199
- 20. **Send role-query `query` as raw JSON** and omit `tenantAppId` when `dataSourceId` is present; backend derives it.
200
- 21. **After deleting a role, invalidate dependent app queries** for role lists, user-role lists, role-query lists, and any UI that renders primary-role labels.
193
+ 11. **Use `createUserAppConfigClient(client, appId)`** for the current user's persisted config document scoped to an app (e.g. theme, layout preferences, sidebar state); `upsert` is the default write path.
194
+ 12. **Use `createDataViewClient(client, appId)`** for saved grid-view CRUD.
195
+ 13. **Use `DataViews` with `DataGridViewSelect`** to show, create, edit, reorder, hide, unhide, soft-delete, and hard-delete saved data grid views.
196
+ 14. **`DataGridViewSelect` needs a TanStack table instance** and should receive `fields` when you want the built-in filter builder/editor experience.
197
+ 15. **Data view creation requires `name` and `tenant_data_source_id`**.
198
+ 16. **Use `dataViews.update(viewId, { archived: true })` for soft-delete** and `dataViews.remove(viewId)` only for irreversible hard-delete.
199
+ 17. **Regenerate collections after schema changes** by rebuilding the tenant OpenAPI spec, downloading the latest `openapi.json`, and re-running the collection generator.
200
+ 18. **ACL endpoints are usually raw-client integrations** — use `useDocyrusClient()` or `RestApiClient` for roles, user-role assignments, role queries, record sharing, and ownership transfer.
201
+ 19. **Prefer role `uid` values** for ACL role writes, user-role `roleIds`, and role-query `roleIds`.
202
+ 20. **Treat `PUT /v1/users/acl/users/:userId/roles` as full replacement** and `POST /v1/users/acl/users/:userId/roles` as additive.
203
+ 21. **Send role-query `query` as raw JSON** and omit `tenantAppId` when `dataSourceId` is present; backend derives it.
204
+ 22. **After deleting a role, invalidate dependent app queries** for role lists, user-role lists, role-query lists, and any UI that renders primary-role labels.
201
205
 
202
206
  ## Critical UI/UX Rules
203
207
 
@@ -349,6 +349,79 @@ Search endpoint paths and entity names.
349
349
 
350
350
  ---
351
351
 
352
+ ## connect — Connector & Action Commands
353
+
354
+ ### `docyrus connect list-connectors`
355
+
356
+ List available integration connectors.
357
+
358
+ | Option | Type | Default | Description |
359
+ |---|---|---|---|
360
+ | `--q` | string | — | Keyword search on name, slug, or description |
361
+ | `--limit` | number | 100 | Max results |
362
+ | `--offset` | number | 0 | Result offset |
363
+
364
+ ### `docyrus connect get-connector <slug>`
365
+
366
+ Get connector details with data sources and actions.
367
+
368
+ | Argument | Type | Required | Description |
369
+ |---|---|---|---|
370
+ | `slug` | string | yes | Data provider slug (e.g., `msgraph`) |
371
+
372
+ ### `docyrus connect get-action <slug> <actionKey>`
373
+
374
+ Get connector action details including input/output schemas.
375
+
376
+ | Argument | Type | Required | Description |
377
+ |---|---|---|---|
378
+ | `slug` | string | yes | Data provider slug (e.g., `msgraph`) |
379
+ | `actionKey` | string | yes | Action key (e.g., `sendEmailWithOutlook`) |
380
+
381
+ ### `docyrus connect list-connections <slug>`
382
+
383
+ Get tenant and user connections for a connector.
384
+
385
+ | Argument | Type | Required | Description |
386
+ |---|---|---|---|
387
+ | `slug` | string | yes | Data provider slug (e.g., `msgraph`) |
388
+
389
+ ### `docyrus connect curl <slug> <endpoint>`
390
+
391
+ Send an HTTP request through a connector's provider auth.
392
+
393
+ | Argument | Type | Required | Description |
394
+ |---|---|---|---|
395
+ | `slug` | string | yes | Data provider slug (e.g., `msgraph`, `meta`) |
396
+ | `endpoint` | string | yes | Relative endpoint path or absolute URL |
397
+
398
+ | Option | Alias | Type | Default | Description |
399
+ |---|---|---|---|---|
400
+ | `--method` | `-X` | string | GET | HTTP method |
401
+ | `--data` | `-d` | string | — | JSON request payload |
402
+ | `--contentType` | | string | application/json | Content-Type header |
403
+ | `--headers` | | string | — | JSON object of additional headers |
404
+ | `--connectionId` | `-c` | string | — | Tenant connection ID override |
405
+ | `--connectionAccountId` | | string | — | Connection account ID |
406
+
407
+ ### `docyrus connect run-action <appSlug> <actionKey>`
408
+
409
+ Run a connector or app action via `POST /v1/apps/:appSlug/actions/:actionKey/run`.
410
+
411
+ | Argument | Type | Required | Description |
412
+ |---|---|---|---|
413
+ | `appSlug` | string | yes | App slug (e.g., `base`) |
414
+ | `actionKey` | string | yes | Action key (e.g., `sendEmailWithOutlook`) |
415
+
416
+ | Option | Alias | Type | Default | Description |
417
+ |---|---|---|---|---|
418
+ | `--params` | `-p` | string | — | JSON object with action input parameters |
419
+ | `--connectionId` | `-c` | string | — | Tenant connection ID override |
420
+ | `--connectionAccountId` | | string | — | Tenant connection account ID |
421
+ | `--dryRun` | `-n` | boolean | false | Preview request without executing |
422
+
423
+ ---
424
+
352
425
  ## apps — App Management
353
426
 
354
427
  ### `docyrus apps list`
@@ -0,0 +1,109 @@
1
+ ---
2
+ name: grill-me
3
+ description: >
4
+ Interview the user relentlessly about a plan, architecture, or data model design until reaching shared understanding, resolving each branch of the decision tree. Use when the user wants to stress-test a plan, get grilled on their design, or mentions "grill me".
5
+
6
+ **Triggers — use this skill when:**
7
+ - User says "grill me", "stress test this", "challenge my design"
8
+ - User asks to "poke holes", "find gaps", "review my thinking"
9
+ - User wants to validate a plan before implementing
10
+ - User says "interview me about this", "question my decisions"
11
+ - Used after `/architect` or `/plan` when the user wants to pressure-test the output
12
+ ---
13
+
14
+ # Grill Me
15
+
16
+ Interview the user relentlessly about every aspect of their plan until reaching a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one by one.
17
+
18
+ ## How It Works
19
+
20
+ Ask questions **one at a time**. For each question, provide your recommended answer based on what you know about the codebase and the Docyrus platform.
21
+
22
+ If a question can be answered by exploring the codebase or the discovery snapshot, explore it yourself instead of asking.
23
+
24
+ ## Question Domains
25
+
26
+ Work through these domains systematically, but adapt the order based on what matters most for the specific plan:
27
+
28
+ ### Data Model
29
+
30
+ - Why this data source and not an extension of an existing one?
31
+ - What is the expected record volume? Does the schema hold up at 10x scale?
32
+ - Are there fields that should be computed (formulas) instead of stored?
33
+ - Could any proposed data source be replaced by a custom query instead?
34
+ - Are slug and naming choices consistent with existing tenant conventions?
35
+
36
+ ### Field Design
37
+
38
+ - Is this the right field type? (e.g., `field-select` vs `field-radioGroup`, `field-text` vs `field-richText`)
39
+ - Should this field be required, optional, or have a default value?
40
+ - Are validation rules sufficient? Too strict? Missing edge cases?
41
+ - For relation fields: is the cardinality correct? Should it be bidirectional?
42
+ - Are there fields that will rarely be used and could be deferred?
43
+
44
+ ### Enumerations
45
+
46
+ - Are enum options exhaustive? What happens when a new option is needed later?
47
+ - Should this be an enum or a separate data source with its own lifecycle?
48
+ - Are enum values and labels clear and consistent?
49
+ - Is the ordering intentional?
50
+
51
+ ### Relations and Dependencies
52
+
53
+ - What is the dependency graph between data sources? Are there cycles?
54
+ - What happens when a related record is deleted?
55
+ - Are there implicit relations that should be explicit?
56
+ - Does the creation order in the apply plan respect all dependencies?
57
+
58
+ ### Access Control and Security
59
+
60
+ - Who should be able to read/write/delete these records?
61
+ - Are there tenant-level vs app-level permission considerations?
62
+ - Should any fields be hidden or read-only for certain roles?
63
+
64
+ ### Edge Cases and Failure Modes
65
+
66
+ - What happens with empty states? First record ever created?
67
+ - What if the user enters unexpected data?
68
+ - Are there race conditions in concurrent record creation?
69
+ - What if a bulk import has partial failures?
70
+
71
+ ### Implementation Feasibility
72
+
73
+ - Can this be built with existing Docyrus field types, or does it require platform changes?
74
+ - Are there known limitations in the current API that affect this design?
75
+ - Is the proposed migration path realistic?
76
+
77
+ ## Interview Protocol
78
+
79
+ 1. Start by reading the plan or architecture artifacts (PLAN.md, DATA_SOURCES.md, discovery snapshot, or whatever is available).
80
+ 2. Identify the most critical or uncertain decision in the plan.
81
+ 3. Ask one focused question about it, with your recommended answer.
82
+ 4. Based on the user's response, either drill deeper into that branch or move to the next decision.
83
+ 5. Track resolved decisions and open questions as you go.
84
+ 6. When all major branches are resolved, summarize the final shared understanding.
85
+
86
+ ## Output on Completion
87
+
88
+ When the interview is complete, produce a summary:
89
+
90
+ ```markdown
91
+ ## Resolved Decisions
92
+
93
+ - [Decision 1]: [Resolution]
94
+ - [Decision 2]: [Resolution]
95
+ ...
96
+
97
+ ## Changes to the Plan
98
+
99
+ - [Change 1]
100
+ - [Change 2]
101
+ ...
102
+
103
+ ## Remaining Open Questions
104
+
105
+ - [Question 1]
106
+ ...
107
+ ```
108
+
109
+ If the plan artifacts exist on disk (PLAN.md, data-sources.plan.json), offer to update them with the resolved decisions.
package/server-loader.js CHANGED
@@ -13288,7 +13288,7 @@ var require_promise = __commonJS({
13288
13288
  }
13289
13289
  });
13290
13290
 
13291
- // ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
13291
+ // ../../node_modules/.pnpm/@hono+node-server@1.19.13_hono@4.12.12/node_modules/@hono/node-server/dist/index.mjs
13292
13292
  var dist_exports = {};
13293
13293
  __export(dist_exports, {
13294
13294
  RequestError: () => RequestError,
@@ -13341,9 +13341,9 @@ function writeFromReadableStream(stream, writable) {
13341
13341
  }
13342
13342
  return writeFromReadableStreamDefaultReader(stream.getReader(), writable);
13343
13343
  }
13344
- var import_http, import_http2, import_http22, import_stream, import_crypto, RequestError, toRequestError, GlobalRequest, Request2, newHeadersFromIncoming, wrapBodyStream, newRequestFromIncoming, getRequestCache, requestCache, incomingKey, urlKey, headersKey, abortControllerKey, getAbortController, requestPrototype, newRequest, responseCache, getResponseCache, cacheKey, GlobalResponse, Response2, buildOutgoingHttpHeaders, X_ALREADY_SENT, outgoingEnded, handleRequestError, handleFetchError, handleResponseError, flushHeaders, responseViaCache, isPromise, responseViaResponseObject, getRequestListener, createAdaptorServer, serve;
13344
+ var import_http, import_http2, import_http22, import_stream, import_crypto, RequestError, toRequestError, GlobalRequest, Request2, newHeadersFromIncoming, wrapBodyStream, newRequestFromIncoming, getRequestCache, requestCache, incomingKey, urlKey, headersKey, abortControllerKey, getAbortController, requestPrototype, newRequest, responseCache, getResponseCache, cacheKey, GlobalResponse, Response2, buildOutgoingHttpHeaders, X_ALREADY_SENT, outgoingEnded, incomingDraining, DRAIN_TIMEOUT_MS, MAX_DRAIN_BYTES, drainIncoming, handleRequestError, handleFetchError, handleResponseError, flushHeaders, responseViaCache, isPromise, responseViaResponseObject, getRequestListener, createAdaptorServer, serve;
13345
13345
  var init_dist = __esm({
13346
- "../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs"() {
13346
+ "../../node_modules/.pnpm/@hono+node-server@1.19.13_hono@4.12.12/node_modules/@hono/node-server/dist/index.mjs"() {
13347
13347
  "use strict";
13348
13348
  import_http = require("http");
13349
13349
  import_http2 = require("http2");
@@ -13624,6 +13624,50 @@ var init_dist = __esm({
13624
13624
  global.crypto = import_crypto.default;
13625
13625
  }
13626
13626
  outgoingEnded = /* @__PURE__ */ Symbol("outgoingEnded");
13627
+ incomingDraining = /* @__PURE__ */ Symbol("incomingDraining");
13628
+ DRAIN_TIMEOUT_MS = 500;
13629
+ MAX_DRAIN_BYTES = 64 * 1024 * 1024;
13630
+ drainIncoming = (incoming) => {
13631
+ const incomingWithDrainState = incoming;
13632
+ if (incoming.destroyed || incomingWithDrainState[incomingDraining]) {
13633
+ return;
13634
+ }
13635
+ incomingWithDrainState[incomingDraining] = true;
13636
+ if (incoming instanceof import_http2.Http2ServerRequest) {
13637
+ try {
13638
+ ;
13639
+ incoming.stream?.close?.(import_http2.constants.NGHTTP2_NO_ERROR);
13640
+ } catch {
13641
+ }
13642
+ return;
13643
+ }
13644
+ let bytesRead = 0;
13645
+ const cleanup = () => {
13646
+ clearTimeout(timer);
13647
+ incoming.off("data", onData);
13648
+ incoming.off("end", cleanup);
13649
+ incoming.off("error", cleanup);
13650
+ };
13651
+ const forceClose = () => {
13652
+ cleanup();
13653
+ const socket = incoming.socket;
13654
+ if (socket && !socket.destroyed) {
13655
+ socket.destroySoon();
13656
+ }
13657
+ };
13658
+ const timer = setTimeout(forceClose, DRAIN_TIMEOUT_MS);
13659
+ timer.unref?.();
13660
+ const onData = (chunk) => {
13661
+ bytesRead += chunk.length;
13662
+ if (bytesRead > MAX_DRAIN_BYTES) {
13663
+ forceClose();
13664
+ }
13665
+ };
13666
+ incoming.on("data", onData);
13667
+ incoming.on("end", cleanup);
13668
+ incoming.on("error", cleanup);
13669
+ incoming.resume();
13670
+ };
13627
13671
  handleRequestError = () => new Response(null, {
13628
13672
  status: 400
13629
13673
  });
@@ -13795,14 +13839,18 @@ var init_dist = __esm({
13795
13839
  setTimeout(() => {
13796
13840
  if (!incomingEnded) {
13797
13841
  setTimeout(() => {
13798
- incoming.destroy();
13799
- outgoing.destroy();
13842
+ drainIncoming(incoming);
13800
13843
  });
13801
13844
  }
13802
13845
  });
13803
13846
  }
13804
13847
  };
13805
13848
  }
13849
+ outgoing.on("finish", () => {
13850
+ if (!incomingEnded) {
13851
+ drainIncoming(incoming);
13852
+ }
13853
+ });
13806
13854
  }
13807
13855
  outgoing.on("close", () => {
13808
13856
  const abortController = req[abortControllerKey];
@@ -13817,7 +13865,7 @@ var init_dist = __esm({
13817
13865
  setTimeout(() => {
13818
13866
  if (!incomingEnded) {
13819
13867
  setTimeout(() => {
13820
- incoming.destroy();
13868
+ drainIncoming(incoming);
13821
13869
  });
13822
13870
  }
13823
13871
  });
@@ -14003,7 +14051,7 @@ var import_node_crypto6 = require("node:crypto");
14003
14051
  var import_promises14 = require("node:fs/promises");
14004
14052
  var import_node_path18 = require("node:path");
14005
14053
 
14006
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/compose.js
14054
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/compose.js
14007
14055
  var compose = (middleware, onError, onNotFound) => {
14008
14056
  return (context, next) => {
14009
14057
  let index2 = -1;
@@ -14047,10 +14095,10 @@ var compose = (middleware, onError, onNotFound) => {
14047
14095
  };
14048
14096
  };
14049
14097
 
14050
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/request/constants.js
14098
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/request/constants.js
14051
14099
  var GET_MATCH_RESULT = /* @__PURE__ */ Symbol();
14052
14100
 
14053
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/utils/body.js
14101
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/utils/body.js
14054
14102
  var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
14055
14103
  const { all: all2 = false, dot = false } = options;
14056
14104
  const headers = request instanceof HonoRequest ? request.raw.headers : request.headers;
@@ -14122,7 +14170,7 @@ var handleParsingNestedValues = (form, key, value2) => {
14122
14170
  });
14123
14171
  };
14124
14172
 
14125
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/utils/url.js
14173
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/utils/url.js
14126
14174
  var splitPath = (path3) => {
14127
14175
  const paths = path3.split("/");
14128
14176
  if (paths[0] === "") {
@@ -14326,7 +14374,7 @@ var getQueryParams = (url, key) => {
14326
14374
  };
14327
14375
  var decodeURIComponent_ = decodeURIComponent;
14328
14376
 
14329
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/request.js
14377
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/request.js
14330
14378
  var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_);
14331
14379
  var HonoRequest = class {
14332
14380
  /**
@@ -14407,7 +14455,7 @@ var HonoRequest = class {
14407
14455
  return headerData;
14408
14456
  }
14409
14457
  async parseBody(options) {
14410
- return this.bodyCache.parsedBody ??= await parseBody(this, options);
14458
+ return parseBody(this, options);
14411
14459
  }
14412
14460
  #cachedBody = (key) => {
14413
14461
  const { bodyCache, raw: raw2 } = this;
@@ -14594,7 +14642,7 @@ var HonoRequest = class {
14594
14642
  }
14595
14643
  };
14596
14644
 
14597
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/utils/html.js
14645
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/utils/html.js
14598
14646
  var HtmlEscapedCallbackPhase = {
14599
14647
  Stringify: 1,
14600
14648
  BeforeStream: 2,
@@ -14636,7 +14684,7 @@ var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) =>
14636
14684
  }
14637
14685
  };
14638
14686
 
14639
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/context.js
14687
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/context.js
14640
14688
  var TEXT_PLAIN = "text/plain; charset=UTF-8";
14641
14689
  var setDefaultContentType = (contentType, headers) => {
14642
14690
  return {
@@ -15043,7 +15091,7 @@ var Context = class {
15043
15091
  };
15044
15092
  };
15045
15093
 
15046
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router.js
15094
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router.js
15047
15095
  var METHOD_NAME_ALL = "ALL";
15048
15096
  var METHOD_NAME_ALL_LOWERCASE = "all";
15049
15097
  var METHODS = ["get", "post", "put", "delete", "options", "patch"];
@@ -15051,10 +15099,10 @@ var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is
15051
15099
  var UnsupportedPathError = class extends Error {
15052
15100
  };
15053
15101
 
15054
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/utils/constants.js
15102
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/utils/constants.js
15055
15103
  var COMPOSED_HANDLER = "__COMPOSED_HANDLER";
15056
15104
 
15057
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/hono-base.js
15105
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/hono-base.js
15058
15106
  var notFoundHandler = (c) => {
15059
15107
  return c.text("404 Not Found", 404);
15060
15108
  };
@@ -15425,7 +15473,7 @@ var Hono = class _Hono {
15425
15473
  };
15426
15474
  };
15427
15475
 
15428
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router/reg-exp-router/matcher.js
15476
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router/reg-exp-router/matcher.js
15429
15477
  var emptyParam = [];
15430
15478
  function match(method, path3) {
15431
15479
  const matchers = this.buildAllMatchers();
@@ -15446,7 +15494,7 @@ function match(method, path3) {
15446
15494
  return match2(method, path3);
15447
15495
  }
15448
15496
 
15449
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router/reg-exp-router/node.js
15497
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router/reg-exp-router/node.js
15450
15498
  var LABEL_REG_EXP_STR = "[^/]+";
15451
15499
  var ONLY_WILDCARD_REG_EXP_STR = ".*";
15452
15500
  var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
@@ -15554,7 +15602,7 @@ var Node = class _Node {
15554
15602
  }
15555
15603
  };
15556
15604
 
15557
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router/reg-exp-router/trie.js
15605
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router/reg-exp-router/trie.js
15558
15606
  var Trie = class {
15559
15607
  #context = { varIndex: 0 };
15560
15608
  #root = new Node();
@@ -15610,7 +15658,7 @@ var Trie = class {
15610
15658
  }
15611
15659
  };
15612
15660
 
15613
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router/reg-exp-router/router.js
15661
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router/reg-exp-router/router.js
15614
15662
  var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
15615
15663
  var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
15616
15664
  function buildWildcardRegExp(path3) {
@@ -15789,7 +15837,7 @@ var RegExpRouter = class {
15789
15837
  }
15790
15838
  };
15791
15839
 
15792
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router/smart-router/router.js
15840
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router/smart-router/router.js
15793
15841
  var SmartRouter = class {
15794
15842
  name = "SmartRouter";
15795
15843
  #routers = [];
@@ -15844,7 +15892,7 @@ var SmartRouter = class {
15844
15892
  }
15845
15893
  };
15846
15894
 
15847
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router/trie-router/node.js
15895
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router/trie-router/node.js
15848
15896
  var emptyParams = /* @__PURE__ */ Object.create(null);
15849
15897
  var hasChildren = (children) => {
15850
15898
  for (const _ in children) {
@@ -16019,7 +16067,7 @@ var Node2 = class _Node2 {
16019
16067
  }
16020
16068
  };
16021
16069
 
16022
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router/trie-router/router.js
16070
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router/trie-router/router.js
16023
16071
  var TrieRouter = class {
16024
16072
  name = "TrieRouter";
16025
16073
  #node;
@@ -16041,7 +16089,7 @@ var TrieRouter = class {
16041
16089
  }
16042
16090
  };
16043
16091
 
16044
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/hono.js
16092
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/hono.js
16045
16093
  var Hono2 = class extends Hono {
16046
16094
  /**
16047
16095
  * Creates an instance of the Hono class.
@@ -16056,7 +16104,7 @@ var Hono2 = class extends Hono {
16056
16104
  }
16057
16105
  };
16058
16106
 
16059
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/middleware/cors/index.js
16107
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/middleware/cors/index.js
16060
16108
  var cors = (options) => {
16061
16109
  const defaults = {
16062
16110
  origin: "*",
@@ -16071,6 +16119,9 @@ var cors = (options) => {
16071
16119
  const findAllowOrigin = ((optsOrigin) => {
16072
16120
  if (typeof optsOrigin === "string") {
16073
16121
  if (optsOrigin === "*") {
16122
+ if (opts.credentials) {
16123
+ return (origin) => origin || null;
16124
+ }
16074
16125
  return () => optsOrigin;
16075
16126
  } else {
16076
16127
  return (origin) => optsOrigin === origin ? origin : null;
@@ -16105,7 +16156,7 @@ var cors = (options) => {
16105
16156
  set("Access-Control-Expose-Headers", opts.exposeHeaders.join(","));
16106
16157
  }
16107
16158
  if (c.req.method === "OPTIONS") {
16108
- if (opts.origin !== "*") {
16159
+ if (opts.origin !== "*" || opts.credentials) {
16109
16160
  set("Vary", "Origin");
16110
16161
  }
16111
16162
  if (opts.maxAge != null) {
@@ -16135,7 +16186,7 @@ var cors = (options) => {
16135
16186
  });
16136
16187
  }
16137
16188
  await next();
16138
- if (opts.origin !== "*") {
16189
+ if (opts.origin !== "*" || opts.credentials) {
16139
16190
  c.header("Vary", "Origin", { append: true });
16140
16191
  }
16141
16192
  };
@@ -25655,7 +25706,7 @@ async function createAgentServer(params) {
25655
25706
  app.post("/api/chat", async (c) => {
25656
25707
  const body2 = await c.req.json();
25657
25708
  const messages = body2.messages ?? [];
25658
- if (body2.sessionId) {
25709
+ if (body2.sessionId && body2.sessionId.trim() !== activeSession.id?.trim()) {
25659
25710
  try {
25660
25711
  activeSession = await onResumeSession(body2.sessionId);
25661
25712
  } catch (error) {
@@ -25778,6 +25829,21 @@ async function createAgentServer(params) {
25778
25829
  messageCount: s.messageCount,
25779
25830
  firstMessage: s.firstMessage
25780
25831
  })).sort((a, b) => b.modified.localeCompare(a.modified));
25832
+ const activeId = activeSession.id?.trim();
25833
+ if (activeId && !mapped.some((s) => s.id === activeId)) {
25834
+ const now = (/* @__PURE__ */ new Date()).toISOString();
25835
+ mapped.unshift({
25836
+ id: activeId,
25837
+ path: "",
25838
+ cwd: context.cwd,
25839
+ name: null,
25840
+ parentSessionPath: null,
25841
+ created: now,
25842
+ modified: now,
25843
+ messageCount: 0,
25844
+ firstMessage: null
25845
+ });
25846
+ }
25781
25847
  return c.json({ sessions: mapped });
25782
25848
  } catch (error) {
25783
25849
  const message = error instanceof Error ? error.message : String(error);
@@ -26383,11 +26449,13 @@ async function createAgentServer(params) {
26383
26449
  app.post("/api/sessions/:sessionId/resume", async (c) => {
26384
26450
  const sessionId = c.req.param("sessionId");
26385
26451
  try {
26386
- if (activeSession.isStreaming) {
26387
- await activeSession.abort();
26388
- await waitForIdle(activeSession);
26452
+ if (sessionId.trim() !== activeSession.id?.trim()) {
26453
+ if (activeSession.isStreaming) {
26454
+ await activeSession.abort();
26455
+ await waitForIdle(activeSession);
26456
+ }
26457
+ activeSession = await onResumeSession(sessionId);
26389
26458
  }
26390
- activeSession = await onResumeSession(sessionId);
26391
26459
  return c.json({
26392
26460
  ok: true,
26393
26461
  sessionId,
@@ -26902,6 +26970,29 @@ async function createAgentServer(params) {
26902
26970
  return c.json({ error: message }, 500);
26903
26971
  }
26904
26972
  });
26973
+ app.get("/api/git/commits", async (c) => {
26974
+ const cwd = context.cwd;
26975
+ const limit = Math.min(Math.max(Number(c.req.query("limit")) || 50, 1), 500);
26976
+ try {
26977
+ let raw2 = "";
26978
+ try {
26979
+ raw2 = await gitExec(
26980
+ ["log", `--max-count=${limit}`, "--format=%H%x00%an%x00%ae%x00%aI%x00%s"],
26981
+ cwd
26982
+ );
26983
+ } catch {
26984
+ return c.json({ commits: [] });
26985
+ }
26986
+ const commits = raw2.trim().split("\n").filter(Boolean).map((line) => {
26987
+ const [hash, authorName, authorEmail, date, message] = line.split("\0");
26988
+ return { hash, authorName, authorEmail, date, message };
26989
+ });
26990
+ return c.json({ commits });
26991
+ } catch (error) {
26992
+ const message = error instanceof Error ? error.message : String(error);
26993
+ return c.json({ error: message }, 500);
26994
+ }
26995
+ });
26905
26996
  app.get("/api/mcp/servers", async (c) => {
26906
26997
  try {
26907
26998
  const [config, cache, provenance] = await Promise.all([